From a134bb93fa3b30e23ee7af818304156be3f7a2a4 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Mon, 4 Feb 2019 18:58:19 +0300 Subject: [PATCH 1/6] simplify creation of switcher --- .../platform-impl/src/com/intellij/ide/actions/Switcher.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 5f2b49eb252e..ed44f32c11bb 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -146,7 +146,8 @@ public class Switcher extends AnAction implements DumbAware { } if (SWITCHER == null) { isNewSwitcher = true; - SWITCHER = createAndShowSwitcher(e, SWITCHER_TITLE, false, null); + // Assigns SWITCHER field + createAndShowSwitcher(project, SWITCHER_TITLE, false, null); FeatureUsageTracker.getInstance().triggerFeatureUsed(SWITCHER_FEATURE_ID); } } @@ -169,7 +170,7 @@ public class Switcher extends AnAction implements DumbAware { @Nullable public static SwitcherPanel createAndShowSwitcher(@NotNull AnActionEvent e, @NotNull String title, boolean pinned, @Nullable final VirtualFile[] vFiles) { - Project project = getEventProject(e); + Project project = e.getProject(); if (SWITCHER != null && Comparing.equal(SWITCHER.myTitle, title)) { SWITCHER.goForward(); return null; From 5bcc3e6ebe5a35a860433a68b352d31ba2f72571 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Mon, 4 Feb 2019 20:19:16 +0300 Subject: [PATCH 2/6] streamline files definition/collection in switcher --- .../com/intellij/ide/actions/Switcher.java | 140 +++++++++--------- 1 file changed, 73 insertions(+), 67 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index ed44f32c11bb..47480b680794 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -187,13 +187,7 @@ public class Switcher extends AnAction implements DumbAware { if (SWITCHER != null) { SWITCHER.cancel(); } - SWITCHER = new SwitcherPanel(project, title, pinned) { - @NotNull - @Override - protected List getFiles(@NotNull Project project) { - return vFiles != null ? vFiles : super.getFiles(project); - } - }; + SWITCHER = new SwitcherPanel(project, title, vFiles != null ? vFiles : EditorHistoryManager.getInstance(project).getFileList(), pinned); return SWITCHER; } } @@ -302,7 +296,7 @@ public class Switcher extends AnAction implements DumbAware { }; @SuppressWarnings({"ConstantConditions"}) - SwitcherPanel(@NotNull final Project project, @NotNull String title, boolean pinned) { + SwitcherPanel(@NotNull final Project project, @NotNull String title, @NotNull List filesToShow, boolean pinned) { setLayout(new SwitcherLayouter()); this.project = project; myTitle = title; @@ -391,65 +385,11 @@ public class Switcher extends AnAction implements DumbAware { separator.setPreferredSize(JBUI.size(9, 10)); separator.setBackground(toolWindows.getBackground()); - int selectionIndex = -1; - final FileEditorManagerImpl editorManager = (FileEditorManagerImpl)FileEditorManager.getInstance(project); - final ArrayList filesData = new ArrayList<>(); - final ArrayList editors = new ArrayList<>(); - if (!pinned) { - if (UISettings.getInstance().getEditorTabPlacement() != UISettings.TABS_NONE) { - for (Pair pair : editorManager.getSelectionHistory()) { - editors.add(new FileInfo(pair.first, pair.second, project)); - } - } - } - if (editors.size() < 2 || isPinnedMode()) { - if (isPinnedMode() && editors.size() > 1) { - filesData.addAll(editors); - } - final List recentFiles = getFiles(project); - final int maxFiles = Math.max(editors.size(), recentFiles.size()); - final int minIndex = isPinnedMode() ? 0 : (recentFiles.size() - Math.min(toolWindows.getModel().getSize(), maxFiles)); - boolean firstRecentMarked = false; - final List selectedFiles = Arrays.asList(editorManager.getSelectedFiles()); - for (int i = recentFiles.size() - 1; i >= minIndex; i--) { - if (isPinnedMode() - && selectedFiles.contains(recentFiles.get(i)) - && UISettings.getInstance().getEditorTabPlacement() != UISettings.TABS_NONE) { - continue; - } - - final FileInfo info = new FileInfo(recentFiles.get(i), null, project); - boolean add = true; - if (isPinnedMode()) { - for (FileInfo fileInfo : filesData) { - if (fileInfo.first.equals(info.first)) { - add = false; - break; - } - } - } - if (add) { - filesData.add(info); - if (!firstRecentMarked) { - selectionIndex = filesData.size() - 1; - if (selectionIndex != 0 || UISettings.getInstance().getEditorTabPlacement() != UISettings.TABS_NONE || !isPinnedMode() || selectedFiles.isEmpty()) { - firstRecentMarked = true; - } - } - } - } - //if (editors.size() == 1) selectionIndex++; - if (editors.size() == 1 && (filesData.isEmpty() || !editors.get(0).getFirst().equals(filesData.get(0).getFirst()))) { - filesData.add(0, editors.get(0)); - } - } else { - for (int i = 0; i < Math.min(30, editors.size()); i++) { - filesData.add(editors.get(i)); - } - } - + final Pair, Integer> filesAndSelection = getFilesToShowAndSelectionIndex(project, filesToShow, + toolWindows.getModel().getSize(), pinned); + final int selectionIndex = filesAndSelection.getSecond(); final DefaultListModel filesModel = new DefaultListModel(); - for (FileInfo editor : filesData) { + for (FileInfo editor : filesAndSelection.getFirst()) { filesModel.addElement(editor); } @@ -646,6 +586,71 @@ public class Switcher extends AnAction implements DumbAware { return content == null ? null : content.getFocusCycleRootAncestor(); } + @NotNull + private static Pair, Integer> getFilesToShowAndSelectionIndex(@NotNull Project project, + @NotNull List filesForInit, + int toolWindowsCount, + boolean pinned) { + int selectionIndex = -1; + final FileEditorManagerImpl editorManager = (FileEditorManagerImpl)FileEditorManager.getInstance(project); + final ArrayList filesData = new ArrayList<>(); + final ArrayList editors = new ArrayList<>(); + if (!pinned) { + if (UISettings.getInstance().getEditorTabPlacement() != UISettings.TABS_NONE) { + for (Pair pair : editorManager.getSelectionHistory()) { + editors.add(new FileInfo(pair.first, pair.second, project)); + } + } + } + if (editors.size() < 2 || pinned) { + if (pinned && editors.size() > 1) { + filesData.addAll(editors); + } + final List recentFiles = filesForInit; + final int maxFiles = Math.max(editors.size(), recentFiles.size()); + final int minIndex = pinned ? 0 : (recentFiles.size() - Math.min(toolWindowsCount, maxFiles)); + boolean firstRecentMarked = false; + final List selectedFiles = Arrays.asList(editorManager.getSelectedFiles()); + for (int i = recentFiles.size() - 1; i >= minIndex; i--) { + if (pinned + && selectedFiles.contains(recentFiles.get(i)) + && UISettings.getInstance().getEditorTabPlacement() != UISettings.TABS_NONE) { + continue; + } + + final FileInfo info = new FileInfo(recentFiles.get(i), null, project); + boolean add = true; + if (pinned) { + for (FileInfo fileInfo : filesData) { + if (fileInfo.first.equals(info.first)) { + add = false; + break; + } + } + } + if (add) { + filesData.add(info); + if (!firstRecentMarked) { + selectionIndex = filesData.size() - 1; + if (selectionIndex != 0 || UISettings.getInstance().getEditorTabPlacement() != UISettings.TABS_NONE || !pinned || selectedFiles.isEmpty()) { + firstRecentMarked = true; + } + } + } + } + //if (editors.size() == 1) selectionIndex++; + if (editors.size() == 1 && (filesData.isEmpty() || !editors.get(0).getFirst().equals(filesData.get(0).getFirst()))) { + filesData.add(0, editors.get(0)); + } + } else { + for (int i = 0; i < Math.min(30, editors.size()); i++) { + filesData.add(editors.get(i)); + } + } + + return Pair.create(filesData, selectionIndex); + } + private static void addFocusTraversalKeys (Container focusCycleRoot, int focusTraversalType, String keyStroke) { Set focusTraversalKeySet = focusCycleRoot.getFocusTraversalKeys(focusTraversalType); @@ -654,9 +659,10 @@ public class Switcher extends AnAction implements DumbAware { focusCycleRoot.setFocusTraversalKeys(focusTraversalType, set); } + @Deprecated @NotNull protected List getFiles(@NotNull Project project) { - return EditorHistoryManager.getInstance(project).getFileList(); + throw new UnsupportedOperationException("deprecated"); } @NotNull From 54324821a43b68558982f25aeca8c58cd9aea652 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Mon, 4 Feb 2019 20:50:08 +0300 Subject: [PATCH 3/6] streamline specifying whether switcher should show recent files or recently edited files --- .../ide/actions/ShowRecentFilesAction.java | 2 +- .../ShowRecentlyEditedFilesAction.java | 3 +- .../com/intellij/ide/actions/Switcher.java | 29 ++++++++++++++----- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java index 003581b0c8e9..35f1e23ff236 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java @@ -32,7 +32,7 @@ public class ShowRecentFilesAction extends DumbAwareAction { @Override public void actionPerformed(@NotNull AnActionEvent e) { FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.recent.files"); - Switcher.createAndShowSwitcher(e, IdeBundle.message("title.popup.recent.files"), true, null); + Switcher.createAndShowSwitcher(e, IdeBundle.message("title.popup.recent.files"), false, true); } @Override diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentlyEditedFilesAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentlyEditedFilesAction.java index 76fce0205c1c..d84fcda3573a 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentlyEditedFilesAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentlyEditedFilesAction.java @@ -20,7 +20,6 @@ package com.intellij.ide.actions; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; @@ -30,7 +29,7 @@ public class ShowRecentlyEditedFilesAction extends DumbAwareAction { public void actionPerformed(@NotNull AnActionEvent e) { final Project project = e.getProject(); if (project != null) { - Switcher.createAndShowSwitcher(e, "Recently Edited Files", true, IdeDocumentHistory.getInstance(project).getChangedFiles()); + Switcher.createAndShowSwitcher(e, "Recently Edited Files", true, true); } } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 47480b680794..142a92b54da5 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -15,6 +15,7 @@ import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; +import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory; import com.intellij.openapi.fileEditor.impl.EditorHistoryManager; import com.intellij.openapi.fileEditor.impl.EditorTabPresentationUtil; import com.intellij.openapi.fileEditor.impl.EditorWindow; @@ -147,7 +148,7 @@ public class Switcher extends AnAction implements DumbAware { if (SWITCHER == null) { isNewSwitcher = true; // Assigns SWITCHER field - createAndShowSwitcher(project, SWITCHER_TITLE, false, null); + createAndShowSwitcher(project, SWITCHER_TITLE, false, false); FeatureUsageTracker.getInstance().triggerFeatureUsed(SWITCHER_FEATURE_ID); } } @@ -168,26 +169,34 @@ public class Switcher extends AnAction implements DumbAware { } } + /** + * @deprecated Please use {@link Switcher#createAndShowSwitcher(AnActionEvent, String, boolean, boolean)} + */ + @Deprecated @Nullable public static SwitcherPanel createAndShowSwitcher(@NotNull AnActionEvent e, @NotNull String title, boolean pinned, @Nullable final VirtualFile[] vFiles) { + return createAndShowSwitcher(e, title, pinned, vFiles != null); + } + + public static SwitcherPanel createAndShowSwitcher(@NotNull AnActionEvent e, @NotNull String title, boolean onlyEdited, boolean pinned) { Project project = e.getProject(); if (SWITCHER != null && Comparing.equal(SWITCHER.myTitle, title)) { SWITCHER.goForward(); return null; } - return project == null ? null : createAndShowSwitcher(project, title, pinned, vFiles == null ? null : Arrays.asList(vFiles)); + return project == null ? null : createAndShowSwitcher(project, title, onlyEdited, pinned); } @Nullable private static SwitcherPanel createAndShowSwitcher(@NotNull Project project, @NotNull String title, - boolean pinned, - @Nullable final List vFiles) { + boolean onlyEdited, + boolean pinned) { synchronized (Switcher.class) { if (SWITCHER != null) { SWITCHER.cancel(); } - SWITCHER = new SwitcherPanel(project, title, vFiles != null ? vFiles : EditorHistoryManager.getInstance(project).getFileList(), pinned); + SWITCHER = new SwitcherPanel(project, title, onlyEdited, pinned); return SWITCHER; } } @@ -296,7 +305,7 @@ public class Switcher extends AnAction implements DumbAware { }; @SuppressWarnings({"ConstantConditions"}) - SwitcherPanel(@NotNull final Project project, @NotNull String title, @NotNull List filesToShow, boolean pinned) { + SwitcherPanel(@NotNull final Project project, @NotNull String title, boolean onlyEdited, boolean pinned) { setLayout(new SwitcherLayouter()); this.project = project; myTitle = title; @@ -385,7 +394,7 @@ public class Switcher extends AnAction implements DumbAware { separator.setPreferredSize(JBUI.size(9, 10)); separator.setBackground(toolWindows.getBackground()); - final Pair, Integer> filesAndSelection = getFilesToShowAndSelectionIndex(project, filesToShow, + final Pair, Integer> filesAndSelection = getFilesToShowAndSelectionIndex(project, collectFiles(project, onlyEdited), toolWindows.getModel().getSize(), pinned); final int selectionIndex = filesAndSelection.getSecond(); final DefaultListModel filesModel = new DefaultListModel(); @@ -586,6 +595,12 @@ public class Switcher extends AnAction implements DumbAware { return content == null ? null : content.getFocusCycleRootAncestor(); } + @NotNull + private static List collectFiles(@NotNull Project project, boolean onlyEdited) { + return onlyEdited ? Arrays.asList(IdeDocumentHistory.getInstance(project).getChangedFiles()) + : EditorHistoryManager.getInstance(project).getFileList(); + } + @NotNull private static Pair, Integer> getFilesToShowAndSelectionIndex(@NotNull Project project, @NotNull List filesForInit, From c4f22c84e2ac1feb78b540db0eaa168f590ff568 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Mon, 4 Feb 2019 21:37:21 +0300 Subject: [PATCH 4/6] use CollectionListModel instead of DefaultListModel because the latter does not play well with NameFilteringListModel --- .../src/com/intellij/ide/actions/Switcher.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 142a92b54da5..915f8a203ccd 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -331,7 +331,7 @@ public class Switcher extends AnAction implements DumbAware { descriptions.setBorder(new CustomLineBorder(JBUI.CurrentTheme.Advertiser.borderColor(), JBUI.insetsTop(1))); descriptions.add(pathLabel, BorderLayout.CENTER); twManager = ToolWindowManager.getInstance(project); - DefaultListModel twModel = new DefaultListModel(); + CollectionListModel twModel = new CollectionListModel(); List actions = ToolWindowsGroup.getToolWindowActions(project, true); List windows = ContainerUtil.newArrayList(); for (ActivateToolWindowAction action : actions) { @@ -344,7 +344,7 @@ public class Switcher extends AnAction implements DumbAware { final Map map = ContainerUtil.reverseMap(twShortcuts); Collections.sort(windows, (o1, o2) -> StringUtil.compare(map.get(o1), map.get(o2), false)); for (ToolWindow window : windows) { - twModel.addElement(window); + twModel.add(window); } toolWindows = new JBList(twModel); @@ -397,9 +397,9 @@ public class Switcher extends AnAction implements DumbAware { final Pair, Integer> filesAndSelection = getFilesToShowAndSelectionIndex(project, collectFiles(project, onlyEdited), toolWindows.getModel().getSize(), pinned); final int selectionIndex = filesAndSelection.getSecond(); - final DefaultListModel filesModel = new DefaultListModel(); + final CollectionListModel filesModel = new CollectionListModel(); for (FileInfo editor : filesAndSelection.getFirst()) { - filesModel.addElement(editor); + filesModel.add(editor); } final VirtualFilesRenderer filesRenderer = new VirtualFilesRenderer(this) { @@ -507,7 +507,7 @@ public class Switcher extends AnAction implements DumbAware { ScrollingUtil.ensureSelectionExists(files); this.add(toolWindows, BorderLayout.WEST); - if (filesModel.size() > 0) { + if (filesModel.getSize() > 0) { files.setAlignmentY(1f); final JScrollPane pane = ScrollPaneFactory.createScrollPane(files, true); pane.setPreferredSize(new Dimension(files.getPreferredSize().width, 20 * 20)); @@ -839,8 +839,8 @@ public class Switcher extends AnAction implements DumbAware { private static void removeElementAt(@NotNull JList jList, int index) { final ListModel model = jList.getModel(); - if (model instanceof DefaultListModel) { - ((DefaultListModel)model).removeElementAt(index); + if (model instanceof CollectionListModel) { + ((CollectionListModel)model).remove(index); } else if (model instanceof NameFilteringListModel) { ((NameFilteringListModel)model).remove(index); From b5abb6650ff9bc7548aa468764e2a22168c6d1e4 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Mon, 4 Feb 2019 22:11:51 +0300 Subject: [PATCH 5/6] merge "recent files" and "recently edited files" to reuse the same popup and switch into each other via check box This feature is closed under "experimental" toggle --- .../com/intellij/ide/actions/Switcher.java | 84 +++++++++++++++++-- .../src/META-INF/PlatformExtensions.xml | 4 + 2 files changed, 83 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 915f8a203ccd..432358aa8853 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -3,12 +3,14 @@ package com.intellij.ide.actions; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.ide.DataManager; +import com.intellij.ide.IdeBundle; import com.intellij.ide.IdeEventQueue; import com.intellij.ide.ui.UISettings; import com.intellij.ide.ui.UISettingsState; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.impl.PresentationFactory; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.Experiments; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.markup.EffectType; @@ -44,6 +46,7 @@ import com.intellij.openapi.wm.impl.ToolWindowManagerImpl; import com.intellij.problems.WolfTheProblemSolver; import com.intellij.ui.*; import com.intellij.ui.border.CustomLineBorder; +import com.intellij.ui.components.JBCheckBox; import com.intellij.ui.components.JBList; import com.intellij.ui.speedSearch.NameFilteringListModel; import com.intellij.ui.speedSearch.SpeedSearchUtil; @@ -180,9 +183,21 @@ public class Switcher extends AnAction implements DumbAware { public static SwitcherPanel createAndShowSwitcher(@NotNull AnActionEvent e, @NotNull String title, boolean onlyEdited, boolean pinned) { Project project = e.getProject(); - if (SWITCHER != null && Comparing.equal(SWITCHER.myTitle, title)) { - SWITCHER.goForward(); - return null; + if (SWITCHER != null) { + final boolean sameShortcut = Comparing.equal(SWITCHER.myTitle, title); + if (SWITCHER.isCheckboxMode()) { + if (sameShortcut) { + SWITCHER.toggleShowEditedFiles(); + } + else { + SWITCHER.setShowOnlyEditedFiles(onlyEdited); + } + return null; + } + else if (sameShortcut) { + SWITCHER.goForward(); + return null; + } } return project == null ? null : createAndShowSwitcher(project, title, onlyEdited, pinned); } @@ -207,6 +222,7 @@ public class Switcher extends AnAction implements DumbAware { final JBList files; final JPanel separator; final ToolWindowManager twManager; + final JBCheckBox myShowOnlyEditedFilesCheckBox; final JLabel pathLabel = new JLabel(" "); final JPanel descriptions; final Project project; @@ -530,13 +546,37 @@ public class Switcher extends AnAction implements DumbAware { KeymapUtil.reassignAction(files, getKeyStroke(VK_UP, 0), getKeyStroke(VK_UP, CTRL_DOWN_MASK), WHEN_FOCUSED, false); KeymapUtil.reassignAction(files, getKeyStroke(VK_DOWN, 0), getKeyStroke(VK_DOWN, CTRL_DOWN_MASK), WHEN_FOCUSED, false); - + myShowOnlyEditedFilesCheckBox = new JBCheckBox("Show Only Edited Files", onlyEdited); + myShowOnlyEditedFilesCheckBox.setOpaque(false); + myShowOnlyEditedFilesCheckBox.setFocusable(false); + UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, myShowOnlyEditedFilesCheckBox); + if (isCheckboxMode()) { + myShowOnlyEditedFilesCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + setShowOnlyEditedFiles(myShowOnlyEditedFilesCheckBox.isSelected()); + } + }); + } + else { + myShowOnlyEditedFilesCheckBox.setEnabled(false); + myShowOnlyEditedFilesCheckBox.setVisible(false); + } + + + myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(this, filesModel.getSize() > 0 ? files : toolWindows) .setResizable(pinned) .setModalContext(false) .setFocusable(true) .setRequestFocus(true) - .setTitle(title) + .setTitle(isCheckboxMode() ? IdeBundle.message("title.popup.recent.files") : title) + .setCommandButton(new ActiveComponent.Adapter() { + @Override + public JComponent getComponent() { + return myShowOnlyEditedFilesCheckBox; + } + }) .setCancelOnWindowDeactivation(true) .setCancelOnOtherWindowOpen(true) .setMovable(pinned) @@ -913,6 +953,40 @@ public class Switcher extends AnAction implements DumbAware { return files.hasFocus() ? files : toolWindows.hasFocus() ? toolWindows : preferable; } + boolean isCheckboxMode() { + return isPinnedMode() && Experiments.isFeatureEnabled("recent.and.edited.files.together"); + } + + void toggleShowEditedFiles() { + myShowOnlyEditedFilesCheckBox.doClick(); + } + + void setShowOnlyEditedFiles(boolean onlyEdited) { + if (myShowOnlyEditedFilesCheckBox.isSelected() != onlyEdited) { + myShowOnlyEditedFilesCheckBox.setSelected(onlyEdited); + } + + final boolean listWasSelected = files.getSelectedIndex() != -1; + + final Pair, Integer> filesAndSelection = getFilesToShowAndSelectionIndex( + project, collectFiles(project, onlyEdited), toolWindows.getModel().getSize(), isPinnedMode()); + final int selectionIndex = filesAndSelection.getSecond(); + + final ListModel model = files.getModel(); + if (model instanceof CollectionListModel) { + ((CollectionListModel)model).replaceAll(filesAndSelection.getFirst()); + } + else if (model instanceof NameFilteringListModel) { + ((NameFilteringListModel)model).replaceAll(filesAndSelection.getFirst()); + } + + if (selectionIndex > -1 && listWasSelected) { + files.setSelectedIndex(selectionIndex); + } + files.revalidate(); + files.repaint(); + } + void navigate(final InputEvent e) { final boolean openInNewWindow = e != null && e.isShiftDown() && e instanceof KeyEvent && ((KeyEvent)e).getKeyCode() == VK_ENTER; final Object[] values = getSelectedList().getSelectedValues(); diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index cbc7ba45f2e9..c59b42193131 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -594,6 +594,10 @@ Intergation with global menu in Linux + + Second Cmd/Ctrl+E switches to Recently Edited Files + + From 724f6a65a03c6d2102d663866306d812b57626f7 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 5 Feb 2019 20:58:24 +0300 Subject: [PATCH 6/6] Make switcher header look alike recent locations header --- .../ide/actions/RecentLocationsAction.java | 2 +- .../ide/actions/ShowRecentFilesAction.java | 3 +- .../ShowRecentlyEditedFilesAction.java | 2 +- .../com/intellij/ide/actions/Switcher.java | 68 +++++++++++++------ .../src/messages/IdeBundle.properties | 1 + 5 files changed, 54 insertions(+), 22 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/RecentLocationsAction.java b/platform/platform-impl/src/com/intellij/ide/actions/RecentLocationsAction.java index cf07ac1f46b8..6832c1a79ce6 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/RecentLocationsAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/RecentLocationsAction.java @@ -81,7 +81,7 @@ public class RecentLocationsAction extends AnAction { private static final int MINIMUM_WIDTH = JBUI.scale(200); private static final int MINIMUM_HEIGHT = JBUI.scale(100); private static final Color SHORTCUT_FOREGROUND_COLOR = UIUtil.getContextHelpForeground(); - private static final String SHORTCUT_HEX_COLOR = String.format("#%02x%02x%02x", + public static final String SHORTCUT_HEX_COLOR = String.format("#%02x%02x%02x", SHORTCUT_FOREGROUND_COLOR.getRed(), SHORTCUT_FOREGROUND_COLOR.getGreen(), SHORTCUT_FOREGROUND_COLOR.getBlue()); diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java index 35f1e23ff236..91180e3532a6 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java @@ -22,6 +22,7 @@ package com.intellij.ide.actions; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.ide.IdeBundle; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.project.DumbAwareAction; import org.jetbrains.annotations.NotNull; @@ -32,7 +33,7 @@ public class ShowRecentFilesAction extends DumbAwareAction { @Override public void actionPerformed(@NotNull AnActionEvent e) { FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.recent.files"); - Switcher.createAndShowSwitcher(e, IdeBundle.message("title.popup.recent.files"), false, true); + Switcher.createAndShowSwitcher(e, IdeBundle.message("title.popup.recent.files"), IdeActions.ACTION_RECENT_FILES,false, true); } @Override diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentlyEditedFilesAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentlyEditedFilesAction.java index d84fcda3573a..b5afc71a4216 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentlyEditedFilesAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentlyEditedFilesAction.java @@ -29,7 +29,7 @@ public class ShowRecentlyEditedFilesAction extends DumbAwareAction { public void actionPerformed(@NotNull AnActionEvent e) { final Project project = e.getProject(); if (project != null) { - Switcher.createAndShowSwitcher(e, "Recently Edited Files", true, true); + Switcher.createAndShowSwitcher(e, "Recently Edited Files", "RecentChangedFiles", true, true); } } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 432358aa8853..5166a0ef2e14 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -47,6 +47,7 @@ import com.intellij.problems.WolfTheProblemSolver; import com.intellij.ui.*; import com.intellij.ui.border.CustomLineBorder; import com.intellij.ui.components.JBCheckBox; +import com.intellij.ui.components.JBLabel; import com.intellij.ui.components.JBList; import com.intellij.ui.speedSearch.NameFilteringListModel; import com.intellij.ui.speedSearch.SpeedSearchUtil; @@ -70,6 +71,7 @@ import java.io.File; import java.util.List; import java.util.*; +import static com.intellij.ide.actions.RecentLocationsAction.SHORTCUT_HEX_COLOR; import static com.intellij.openapi.keymap.KeymapUtil.getActiveKeymapShortcuts; import static java.awt.event.InputEvent.CTRL_DOWN_MASK; import static java.awt.event.KeyEvent.*; @@ -151,7 +153,7 @@ public class Switcher extends AnAction implements DumbAware { if (SWITCHER == null) { isNewSwitcher = true; // Assigns SWITCHER field - createAndShowSwitcher(project, SWITCHER_TITLE, false, false); + createAndShowSwitcher(project, SWITCHER_TITLE, IdeActions.ACTION_SWITCHER, false, false); FeatureUsageTracker.getInstance().triggerFeatureUsed(SWITCHER_FEATURE_ID); } } @@ -178,10 +180,10 @@ public class Switcher extends AnAction implements DumbAware { @Deprecated @Nullable public static SwitcherPanel createAndShowSwitcher(@NotNull AnActionEvent e, @NotNull String title, boolean pinned, @Nullable final VirtualFile[] vFiles) { - return createAndShowSwitcher(e, title, pinned, vFiles != null); + return createAndShowSwitcher(e, title, "RecentFiles", pinned, vFiles != null); } - public static SwitcherPanel createAndShowSwitcher(@NotNull AnActionEvent e, @NotNull String title, boolean onlyEdited, boolean pinned) { + public static SwitcherPanel createAndShowSwitcher(@NotNull AnActionEvent e, @NotNull String title, @NotNull String actionId, boolean onlyEdited, boolean pinned) { Project project = e.getProject(); if (SWITCHER != null) { final boolean sameShortcut = Comparing.equal(SWITCHER.myTitle, title); @@ -199,19 +201,20 @@ public class Switcher extends AnAction implements DumbAware { return null; } } - return project == null ? null : createAndShowSwitcher(project, title, onlyEdited, pinned); + return project == null ? null : createAndShowSwitcher(project, title, actionId, onlyEdited, pinned); } @Nullable private static SwitcherPanel createAndShowSwitcher(@NotNull Project project, @NotNull String title, + @NotNull String actionId, boolean onlyEdited, boolean pinned) { synchronized (Switcher.class) { if (SWITCHER != null) { SWITCHER.cancel(); } - SWITCHER = new SwitcherPanel(project, title, onlyEdited, pinned); + SWITCHER = new SwitcherPanel(project, title, actionId, onlyEdited, pinned); return SWITCHER; } } @@ -231,6 +234,7 @@ public class Switcher extends AnAction implements DumbAware { final Alarm myAlarm; final SwitcherSpeedSearch mySpeedSearch; final String myTitle; + final String myActionId; @Nullable @Override @@ -321,10 +325,11 @@ public class Switcher extends AnAction implements DumbAware { }; @SuppressWarnings({"ConstantConditions"}) - SwitcherPanel(@NotNull final Project project, @NotNull String title, boolean onlyEdited, boolean pinned) { + SwitcherPanel(@NotNull final Project project, @NotNull String title, @NotNull String actionId, boolean onlyEdited, boolean pinned) { setLayout(new SwitcherLayouter()); this.project = project; myTitle = title; + myActionId = actionId; myPinned = pinned; mySpeedSearch = pinned ? new SwitcherSpeedSearch() : null; @@ -546,10 +551,11 @@ public class Switcher extends AnAction implements DumbAware { KeymapUtil.reassignAction(files, getKeyStroke(VK_UP, 0), getKeyStroke(VK_UP, CTRL_DOWN_MASK), WHEN_FOCUSED, false); KeymapUtil.reassignAction(files, getKeyStroke(VK_DOWN, 0), getKeyStroke(VK_DOWN, CTRL_DOWN_MASK), WHEN_FOCUSED, false); - myShowOnlyEditedFilesCheckBox = new JBCheckBox("Show Only Edited Files", onlyEdited); - myShowOnlyEditedFilesCheckBox.setOpaque(false); - myShowOnlyEditedFilesCheckBox.setFocusable(false); - UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, myShowOnlyEditedFilesCheckBox); + myShowOnlyEditedFilesCheckBox = new MyCheckBox(actionId, onlyEdited); + + JPanel topPanel = createTopPanel(myShowOnlyEditedFilesCheckBox, isCheckboxMode() ? IdeBundle.message("title.popup.recent.files") : title); + this.add(topPanel, BorderLayout.NORTH); + if (isCheckboxMode()) { myShowOnlyEditedFilesCheckBox.addActionListener(new ActionListener() { @Override @@ -570,13 +576,6 @@ public class Switcher extends AnAction implements DumbAware { .setModalContext(false) .setFocusable(true) .setRequestFocus(true) - .setTitle(isCheckboxMode() ? IdeBundle.message("title.popup.recent.files") : title) - .setCommandButton(new ActiveComponent.Adapter() { - @Override - public JComponent getComponent() { - return myShowOnlyEditedFilesCheckBox; - } - }) .setCancelOnWindowDeactivation(true) .setCancelOnOtherWindowOpen(true) .setMovable(pinned) @@ -627,7 +626,6 @@ public class Switcher extends AnAction implements DumbAware { addFocusTraversalKeys(popupFocusAncestor, KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, "LEFT"); addFocusTraversalKeys(popupFocusAncestor, KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, "control RIGHT"); addFocusTraversalKeys(popupFocusAncestor, KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, "control LEFT"); - } private Container getPopupFocusAncestor() { @@ -640,7 +638,7 @@ public class Switcher extends AnAction implements DumbAware { return onlyEdited ? Arrays.asList(IdeDocumentHistory.getInstance(project).getChangedFiles()) : EditorHistoryManager.getInstance(project).getFileList(); } - + @NotNull private static Pair, Integer> getFilesToShowAndSelectionIndex(@NotNull Project project, @NotNull List filesForInit, @@ -706,6 +704,21 @@ public class Switcher extends AnAction implements DumbAware { return Pair.create(filesData, selectionIndex); } + @NotNull + private static JPanel createTopPanel(JBCheckBox showOnlyEditedFilesCheckBox, @NotNull String title) { + JPanel topPanel = new CaptionPanel(); + JBLabel titleLabel = new JBLabel(title); + titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD)); + topPanel.add(titleLabel, BorderLayout.WEST); + topPanel.add(showOnlyEditedFilesCheckBox, BorderLayout.EAST); + + Dimension size = topPanel.getPreferredSize(); + size.height = JBUI.scale(29); + topPanel.setPreferredSize(size); + topPanel.setBorder(JBUI.Borders.empty(5, 8)); + return topPanel; + } + private static void addFocusTraversalKeys (Container focusCycleRoot, int focusTraversalType, String keyStroke) { Set focusTraversalKeySet = focusCycleRoot.getFocusTraversalKeys(focusTraversalType); @@ -1274,6 +1287,23 @@ public class Switcher extends AnAction implements DumbAware { } } + private static class MyCheckBox extends JBCheckBox { + private MyCheckBox(@NotNull String actionId, boolean selected) { + super(layoutText(actionId), selected); + setOpaque(false); + setFocusable(false); + } + + private static String layoutText(@NotNull String actionId) { + ShortcutSet shortcuts = KeymapUtil.getActiveKeymapShortcuts(actionId); + return "" + + IdeBundle.message("recent.files.checkbox.label") + + " " + + KeymapUtil.getShortcutsText(shortcuts.getShortcuts()) + "" + + ""; + } + } + private static class VirtualFilesRenderer extends ColoredListCellRenderer { private final SwitcherPanel mySwitcherPanel; boolean open; diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index b552ad5193f3..339b3f66547e 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -473,6 +473,7 @@ command.select.all=Select All message.no.targets.available=No targets available in this context title.popup.select.target=Select In title.popup.recent.files=Recent Files +recent.files.checkbox.label=Show changed only recent.locations.popup.title=Recent Locations recent.locations.changed.locations=Recent Changed Locations recent.locations.popup.empty.text=No recent locations found