Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Wolf2019-07-16 11:44:20 -0400
committerThomas Wolf2019-07-16 14:36:26 -0400
commita6320bfc2193461e479a14e73fe062d60d36fad4 (patch)
tree0d1ab029ec4441268bc1ed56306a9dc06948d078 /org.eclipse.egit.ui
parent16ce6278de965eae48a8a529000fe9fd019000b6 (diff)
downloadegit-a6320bfc2193461e479a14e73fe062d60d36fad4.tar.gz
egit-a6320bfc2193461e479a14e73fe062d60d36fad4.tar.xz
egit-a6320bfc2193461e479a14e73fe062d60d36fad4.zip
Put a "presentation" button in the unstaged viewer's toolbar
Adds a button to switch the file presentation in both the unstaged and staged viewers between list mode, tree mode, and compact tree mode to the toolbar of the unstaged viewer, where we already have the button to switch the sort order that also affects both viewers. Re-uses the actions defined for the view menu. The button changes its icon depending on the mode chosen. A first implementation made selecting the button cycle through the presentations, but that introduced a usability problem: when clicked and the presentation switched to list mode, the two buttons for "expand all" and "collapse all" would be hidden. The mouse would then suddenly be over the "stage selected files" button. A user who'd mistakenly click twice might inadvertently stage things he hadn't wanted to stage. Thus this implementation now simple shows the drop-down menu also when the button is selected, not only when the arrow is selected. When the user selects an entry from the drop-down menu and the toolbar changes, the mouse won't be over any of the buttons. Note that the staging view reacts only upon the next refresh or repository switch on changes of the "Maximum number of lines" preference that governs the automatic switching to tree mode. Thus when this preference is changed to a higher value and the view currently is in that forced tree mode, the "list" menu item may remain disabled until the next refresh. That issue is unrelated to this change, though. (But it is made more visible.) Bug: 549269 Change-Id: I347941440ec411eaa21b4e014ebc44893e6c28ce Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
Diffstat (limited to 'org.eclipse.egit.ui')
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/RepositoryMenuUtil.java82
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/ToolbarMenuAction.java122
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingView.java232
3 files changed, 296 insertions, 140 deletions
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/RepositoryMenuUtil.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/RepositoryMenuUtil.java
index 3c04ffa22..01ec794a2 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/RepositoryMenuUtil.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/RepositoryMenuUtil.java
@@ -32,22 +32,12 @@ import org.eclipse.egit.ui.internal.CommonUtils;
import org.eclipse.egit.ui.internal.UIIcons;
import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.jface.action.Action;
-import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.action.IMenuCreator;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Menu;
-import org.eclipse.swt.widgets.ToolItem;
-import org.eclipse.swt.widgets.Widget;
-import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
/**
* Provides a way to populate a menu with a list of repositories.
@@ -100,6 +90,7 @@ public final class RepositoryMenuUtil {
* to perform on the chosen repository
* @return the (possibly empty) list of actions
*/
+ @NonNull
public static Collection<IAction> getRepositoryActions(boolean includeBare,
@Nullable File currentRepoDir,
@NonNull Consumer<Repository> action) {
@@ -165,8 +156,7 @@ public final class RepositoryMenuUtil {
* menu of all registered repositories, performing a given action on a
* selected repository.
*/
- public static class RepositoryToolbarAction extends Action
- implements IWorkbenchAction, IMenuCreator {
+ public static class RepositoryToolbarAction extends ToolbarMenuAction {
private final RepositoryUtil util = org.eclipse.egit.core.Activator
.getDefault().getRepositoryUtil();
@@ -181,10 +171,6 @@ public final class RepositoryMenuUtil {
private final boolean includeBare;
- private Menu menu;
-
- private boolean showMenu;
-
/**
* Creates a new {@link RepositoryToolbarAction} with the given
* {@code action} and default text, image, and tooltip.
@@ -231,7 +217,7 @@ public final class RepositoryMenuUtil {
@Nullable ImageDescriptor image, @Nullable String tooltip,
boolean includeBare, @NonNull Supplier<Repository> currentRepo,
@NonNull Consumer<Repository> action) {
- super(text, IAction.AS_DROP_DOWN_MENU);
+ super(text);
setImageDescriptor(image);
setToolTipText(tooltip == null ? text : tooltip);
this.includeBare = includeBare;
@@ -247,69 +233,19 @@ public final class RepositoryMenuUtil {
preferences.addPreferenceChangeListener(listener);
}
- @Override
- public void run() {
- showMenu = true;
- }
-
- @Override
- public void runWithEvent(Event event) {
- if (!isEnabled()) {
- return;
- }
- // Show the menu also when the button is clicked, unless run() is
- // overridden (and not called via super).
- showMenu = false;
- run();
- Widget widget = event.widget;
- if (showMenu && (widget instanceof ToolItem)) {
- ToolItem item = (ToolItem) widget;
- Rectangle bounds = item.getBounds();
- event.detail = SWT.ARROW;
- event.x = bounds.x;
- event.y = bounds.y + bounds.height;
- item.notifyListeners(SWT.Selection, event);
- }
- }
@Override
- public IMenuCreator getMenuCreator() {
- return this;
- }
-
- @Override
- public Menu getMenu(Control parent) {
- if (menu != null) {
- menu.dispose();
- menu = null;
- }
- if (isEnabled()) {
- Repository current = currentRepo.get();
- File gitDir = current == null ? null : current.getDirectory();
- Collection<IAction> actions = RepositoryMenuUtil
- .getRepositoryActions(includeBare, gitDir, action);
- menu = new Menu(parent);
- for (IAction a : actions) {
- ActionContributionItem item = new ActionContributionItem(a);
- item.fill(menu, -1);
- }
- }
- return menu;
- }
-
- @Override
- public Menu getMenu(Menu parent) {
- // Not used
- return null;
+ public Collection<IAction> getActions() {
+ Repository current = currentRepo.get();
+ File gitDir = current == null ? null : current.getDirectory();
+ return RepositoryMenuUtil.getRepositoryActions(includeBare, gitDir,
+ action);
}
@Override
public void dispose() {
- if (menu != null) {
- menu.dispose();
- menu = null;
- }
preferences.removePreferenceChangeListener(listener);
+ super.dispose();
}
}
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/ToolbarMenuAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/ToolbarMenuAction.java
new file mode 100644
index 000000000..799913e8e
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/ToolbarMenuAction.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (C) 2019 Thomas Wolf <thomas.wolf@paranor.ch>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.components;
+
+import java.util.Collection;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuCreator;
+import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
+
+/**
+ * Specialized {@link Action} intended to be used in a
+ * {@link org.eclipse.jface.action.ToolBarManager ToolBarManager} for buttons
+ * with a drop-down menu. By default selecting the button itself will also show
+ * the menu; if that is not desired, override {@link #runWithEvent(Event)} or
+ * {@link #run()}.
+ */
+public abstract class ToolbarMenuAction extends Action
+ implements IWorkbenchAction, IMenuCreator {
+
+ private Menu menu;
+
+ private boolean showMenu;
+
+ /**
+ * Creates a new {@link ToolbarMenuAction}.
+ *
+ * @param title
+ * for the action
+ */
+ public ToolbarMenuAction(String title) {
+ super(title, IAction.AS_DROP_DOWN_MENU);
+ }
+
+ @Override
+ public void run() {
+ showMenu = true;
+ }
+
+ @Override
+ public void runWithEvent(Event event) {
+ if (!isEnabled()) {
+ return;
+ }
+ // Show the menu also when the button is clicked, unless run() is
+ // overridden (and not called via super).
+ showMenu = false;
+ run();
+ Widget widget = event.widget;
+ if (showMenu && (widget instanceof ToolItem)) {
+ ToolItem item = (ToolItem) widget;
+ Rectangle bounds = item.getBounds();
+ event.detail = SWT.ARROW;
+ event.x = bounds.x;
+ event.y = bounds.y + bounds.height;
+ item.notifyListeners(SWT.Selection, event);
+ }
+ }
+
+ @Override
+ public IMenuCreator getMenuCreator() {
+ return this;
+ }
+
+ @Override
+ public Menu getMenu(Menu parent) {
+ // Not used
+ return null;
+ }
+
+ @Override
+ public Menu getMenu(Control parent) {
+ if (menu != null) {
+ menu.dispose();
+ menu = null;
+ }
+ if (isEnabled()) {
+ menu = new Menu(parent);
+ for (IAction action : getActions()) {
+ ActionContributionItem item = new ActionContributionItem(
+ action);
+ item.fill(menu, -1);
+ }
+ }
+ return menu;
+ }
+
+ /**
+ * Obtains the actions to display in the drop-down menu.
+ *
+ * @return the actions
+ */
+ @NonNull
+ protected abstract Collection<IAction> getActions();
+
+ @Override
+ public void dispose() {
+ if (menu != null) {
+ menu.dispose();
+ menu = null;
+ }
+ }
+
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingView.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingView.java
index 68de0f9a6..2645c32de 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingView.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingView.java
@@ -25,7 +25,9 @@ import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashSet;
@@ -92,6 +94,7 @@ import org.eclipse.egit.ui.internal.commit.CommitProposalProcessor;
import org.eclipse.egit.ui.internal.commit.DiffViewer;
import org.eclipse.egit.ui.internal.components.PartVisibilityListener;
import org.eclipse.egit.ui.internal.components.RepositoryMenuUtil.RepositoryToolbarAction;
+import org.eclipse.egit.ui.internal.components.ToolbarMenuAction;
import org.eclipse.egit.ui.internal.decorators.ProblemLabelDecorator;
import org.eclipse.egit.ui.internal.dialogs.CommandConfirmation;
import org.eclipse.egit.ui.internal.dialogs.CommitMessageArea;
@@ -341,6 +344,8 @@ public class StagingView extends ViewPart
private Presentation presentation = Presentation.LIST;
+ private PresentationAction presentationAction;
+
private Set<IPath> pathsToExpandInStaged = new HashSet<>();
private Set<IPath> pathsToExpandInUnstaged = new HashSet<>();
@@ -839,6 +844,8 @@ public class StagingView extends ViewPart
unstageAllAction.setEnabled(false);
stageAllAction.setEnabled(false);
+ createPresentationActions();
+
unstagedSection = toolkit.createSection(stagingSashForm,
ExpandableComposite.SHORT_TITLE_BAR);
unstagedSection.clientVerticalSpacing = 0;
@@ -1172,6 +1179,7 @@ public class StagingView extends ViewPart
}
};
+ initPresentation();
partListener = new PartListener();
IPreferenceStore preferenceStore = getPreferenceStore();
@@ -1545,6 +1553,8 @@ public class StagingView extends ViewPart
unstagedToolBarManager.add(stageAction);
unstagedToolBarManager.add(stageAllAction);
+ unstagedToolBarManager.add(presentationAction);
+ presentationAction.setToolbar(unstagedToolBarManager);
unstagedToolBarManager.add(sortAction);
unstagedToolBarManager.add(unstagedExpandAllAction);
unstagedToolBarManager.add(unstagedCollapseAllAction);
@@ -1730,6 +1740,84 @@ public class StagingView extends ViewPart
}
}
+ private void createPresentationActions() {
+ listPresentationAction = new Action(UIText.StagingView_List,
+ IAction.AS_RADIO_BUTTON) {
+ @Override
+ public void run() {
+ if (!isChecked()) {
+ return;
+ }
+ switchToListMode();
+ refreshViewers();
+ }
+ };
+ listPresentationAction.setImageDescriptor(UIIcons.FLAT);
+
+ treePresentationAction = new Action(UIText.StagingView_Tree,
+ IAction.AS_RADIO_BUTTON) {
+ @Override
+ public void run() {
+ if (!isChecked()) {
+ return;
+ }
+ presentation = Presentation.TREE;
+ setPresentation(presentation, false);
+ listPresentationAction.setChecked(false);
+ compactTreePresentationAction.setChecked(false);
+ setExpandCollapseActionsVisible(false, isExpandAllowed(false),
+ true);
+ setExpandCollapseActionsVisible(true, isExpandAllowed(true),
+ true);
+ refreshViewers();
+ }
+ };
+ treePresentationAction.setImageDescriptor(UIIcons.HIERARCHY);
+
+ compactTreePresentationAction = new Action(
+ UIText.StagingView_CompactTree, IAction.AS_RADIO_BUTTON) {
+ @Override
+ public void run() {
+ if (!isChecked()) {
+ return;
+ }
+ switchToCompactModeInternal(false);
+ refreshViewers();
+ }
+
+ };
+ compactTreePresentationAction.setImageDescriptor(UIIcons.COMPACT);
+
+ presentationAction = new PresentationAction(getPreferenceStore(),
+ listPresentationAction, treePresentationAction,
+ compactTreePresentationAction);
+ presentationAction.setImageDescriptor(UIIcons.FLAT);
+ }
+
+ private void initPresentation() {
+ presentation = readPresentation(UIPreferences.STAGING_VIEW_PRESENTATION,
+ Presentation.LIST);
+ switch (presentation) {
+ case LIST:
+ presentationAction.setImageDescriptor(UIIcons.FLAT);
+ listPresentationAction.setChecked(true);
+ setExpandCollapseActionsVisible(false, false, false);
+ setExpandCollapseActionsVisible(true, false, false);
+ break;
+ case TREE:
+ presentationAction.setImageDescriptor(UIIcons.HIERARCHY);
+ treePresentationAction.setChecked(true);
+ break;
+ case COMPACT_TREE:
+ presentationAction.setImageDescriptor(UIIcons.COMPACT);
+ compactTreePresentationAction.setChecked(true);
+ break;
+ default:
+ break;
+ }
+ presentationAction.update();
+ }
+
private void updateToolbar() {
ControlContribution controlContribution = new ControlContribution(
@@ -1883,73 +1971,9 @@ public class StagingView extends ViewPart
IMenuManager dropdownMenu = actionBars.getMenuManager();
MenuManager presentationMenu = new MenuManager(
UIText.StagingView_Presentation);
- listPresentationAction = new Action(UIText.StagingView_List,
- IAction.AS_RADIO_BUTTON) {
- @Override
- public void run() {
- if (!isChecked()) {
- return;
- }
- switchToListMode();
- refreshViewers();
- }
- };
- listPresentationAction.setImageDescriptor(UIIcons.FLAT);
presentationMenu.add(listPresentationAction);
-
- treePresentationAction = new Action(UIText.StagingView_Tree,
- IAction.AS_RADIO_BUTTON) {
- @Override
- public void run() {
- if (!isChecked()) {
- return;
- }
- presentation = Presentation.TREE;
- setPresentation(presentation, false);
- listPresentationAction.setChecked(false);
- compactTreePresentationAction.setChecked(false);
- setExpandCollapseActionsVisible(false, isExpandAllowed(false),
- true);
- setExpandCollapseActionsVisible(true, isExpandAllowed(true),
- true);
- refreshViewers();
- }
- };
- treePresentationAction.setImageDescriptor(UIIcons.HIERARCHY);
presentationMenu.add(treePresentationAction);
-
- compactTreePresentationAction = new Action(UIText.StagingView_CompactTree,
- IAction.AS_RADIO_BUTTON) {
- @Override
- public void run() {
- if (!isChecked()) {
- return;
- }
- switchToCompactModeInternal(false);
- refreshViewers();
- }
-
- };
- compactTreePresentationAction.setImageDescriptor(UIIcons.COMPACT);
presentationMenu.add(compactTreePresentationAction);
-
- presentation = readPresentation(UIPreferences.STAGING_VIEW_PRESENTATION,
- Presentation.LIST);
- switch (presentation) {
- case LIST:
- listPresentationAction.setChecked(true);
- setExpandCollapseActionsVisible(false, false, false);
- setExpandCollapseActionsVisible(true, false, false);
- break;
- case TREE:
- treePresentationAction.setChecked(true);
- break;
- case COMPACT_TREE:
- compactTreePresentationAction.setChecked(true);
- break;
- default:
- break;
- }
dropdownMenu.add(presentationMenu);
dropdownMenu.add(new Separator());
dropdownMenu.add(openNewCommitsAction);
@@ -1970,10 +1994,14 @@ public class StagingView extends ViewPart
}
private Presentation readPresentation(String key, Presentation def) {
- String presentationString = getPreferenceStore().getString(key);
- if (presentationString.length() > 0) {
+ return getPresentation(getPreferenceStore().getString(key), def);
+ }
+
+ private static Presentation getPresentation(String value,
+ Presentation def) {
+ if (!value.isEmpty()) {
try {
- return Presentation.valueOf(presentationString);
+ return Presentation.valueOf(value);
} catch (IllegalArgumentException e) {
// Use given default
}
@@ -4312,6 +4340,10 @@ public class StagingView extends ViewPart
switchRepositoriesAction.dispose();
switchRepositoriesAction = null;
}
+ if (presentationAction != null) {
+ presentationAction.dispose();
+ presentationAction = null;
+ }
getPreferenceStore().removePropertyChangeListener(uiPrefsListener);
@@ -4510,4 +4542,70 @@ public class StagingView extends ViewPart
}
}
+
+ private static class PresentationAction extends ToolbarMenuAction
+ implements IPropertyChangeListener {
+
+ private ToolBarManager toolbar;
+
+ private final IPreferenceStore store;
+
+ private final @NonNull List<IAction> actions;
+
+ public PresentationAction(IPreferenceStore store, IAction... actions) {
+ super(UIText.StagingView_Presentation);
+ @SuppressWarnings("null")
+ @NonNull
+ List<IAction> a = actions != null ? Arrays.asList(actions)
+ : Collections.emptyList();
+ this.actions = a;
+ this.store = store;
+ store.addPropertyChangeListener(this);
+ }
+
+ @Override
+ protected Collection<IAction> getActions() {
+ return actions;
+ }
+
+ public void setToolbar(ToolBarManager toolbar) {
+ this.toolbar = toolbar;
+ }
+
+ @Override
+ public void dispose() {
+ store.removePropertyChangeListener(this);
+ super.dispose();
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent event) {
+ if (UIPreferences.STAGING_VIEW_PRESENTATION
+ .equals(event.getProperty())) {
+ Presentation current = getPresentation(
+ event.getNewValue().toString(), Presentation.LIST);
+ switch (current) {
+ case LIST:
+ setImageDescriptor(UIIcons.FLAT);
+ break;
+ case TREE:
+ setImageDescriptor(UIIcons.HIERARCHY);
+ break;
+ case COMPACT_TREE:
+ setImageDescriptor(UIIcons.COMPACT);
+ break;
+ default:
+ return;
+ }
+ update();
+ }
+ }
+
+ public void update() {
+ if (toolbar != null) {
+ toolbar.update(true);
+ }
+ }
+
+ }
}

Back to the top