From 039ed922905bb27e496282b931cdd7b5e90b2e57 Mon Sep 17 00:00:00 2001 From: Denis Zygann Date: Thu, 30 Jul 2015 23:21:58 +0200 Subject: Add a sort order to the unstaged changes Add a button to sort the unstaged changes in alphabetically order or in a grouping order(sort order: Untracked, Missing, Modified), which is also alphabetically sorted. Bug: 473919 Change-Id: Ic59dd8f8d5f621dacfd06063d11a954d311a3e95 Signed-off-by: Denis Zygann Signed-off-by: Matthias Sohn --- org.eclipse.egit.ui/icons/obj16/alphab_sort_co.gif | Bin 0 -> 157 bytes .../src/org/eclipse/egit/ui/internal/UIIcons.java | 5 + .../src/org/eclipse/egit/ui/internal/UIText.java | 4 + .../egit/ui/internal/staging/StagingView.java | 148 ++++++++++++++++++++- .../internal/staging/StagingViewLabelProvider.java | 30 ++++- .../org/eclipse/egit/ui/internal/uitext.properties | 2 + 6 files changed, 180 insertions(+), 9 deletions(-) create mode 100644 org.eclipse.egit.ui/icons/obj16/alphab_sort_co.gif diff --git a/org.eclipse.egit.ui/icons/obj16/alphab_sort_co.gif b/org.eclipse.egit.ui/icons/obj16/alphab_sort_co.gif new file mode 100644 index 0000000000..907d34fc8d Binary files /dev/null and b/org.eclipse.egit.ui/icons/obj16/alphab_sort_co.gif differ diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIIcons.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIIcons.java index c7e0bd6866..1509ef7efd 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIIcons.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIIcons.java @@ -6,6 +6,7 @@ * Copyright (C) 2013, Daniel Megert * Copyright (C) 2013, Robin Stocker * Copyright (C) 2014, Axel Richard + * Copyright (C) 2015, Denis Zygann * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -304,6 +305,9 @@ public class UIIcons { /** Reword for current rebase step */ public final static ImageDescriptor CURRENT_STEP; + /** Sort alphabetically icon */ + public final static ImageDescriptor ALPHABETICALLY_SORT; + /** base URL */ public final static URL base; @@ -406,6 +410,7 @@ public class UIIcons { REWORD = map("obj16/reword.gif"); //$NON-NLS-1$ DONE_STEP = map("obj16/done_step.gif"); //$NON-NLS-1$ CURRENT_STEP = map("obj16/current_step.gif"); //$NON-NLS-1$ + ALPHABETICALLY_SORT = map("obj16/alphab_sort_co.gif"); //$NON-NLS-1$ } private static ImageDescriptor map(final String icon) { diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java index 3297a29523..6bb064f094 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java @@ -15,6 +15,7 @@ * Copyright (C) 2015, SAP SE (Christian Georgi ) * Copyright (C) 2015, Jan-Ove Weichel * Copyright (C) 2015, Laurent Delaigue + * Copyright (C) 2015, Denis Zygann * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -5138,6 +5139,9 @@ public class UIText extends NLS { /** */ public static String StagingView_UnstageItemMenuLabel; + /** */ + public static String StagingView_UnstagedSort; + /** */ public static String StagingView_StageItemMenuLabel; 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 19b33f3811..cebd3a3a53 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 @@ -1,6 +1,7 @@ /******************************************************************************* * Copyright (C) 2011, 2015 Bernard Leach and others. * Copyright (C) 2015 SAP SE (Christian Georgi ) + * Copyright (C) 2015 Denis Zygann * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -18,6 +19,7 @@ import java.io.File; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; +import java.util.Comparator; import java.util.EnumSet; import java.util.HashSet; import java.util.Iterator; @@ -126,6 +128,7 @@ import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeExpansionEvent; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jgit.api.AddCommand; import org.eclipse.jgit.api.CheckoutCommand; @@ -174,6 +177,7 @@ import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; @@ -216,6 +220,11 @@ public class StagingView extends ViewPart implements IShowInSource { private static final String EMPTY_STRING = ""; //$NON-NLS-1$ + private static final String SORT_ITEM_TOOLBAR_ID = "sortItem"; //$NON-NLS-1$ + + private static final String STORE_SORT_STATE = SORT_ITEM_TOOLBAR_ID + + "State"; //$NON-NLS-1$ + private static final String HORIZONTAL_SASH_FORM_WEIGHT = "HORIZONTAL_SASH_FORM_WEIGHT"; //$NON-NLS-1$ private static final String STAGING_SASH_FORM_WEIGHT = "STAGING_SASH_FORM_WEIGHT"; //$NON-NLS-1$ @@ -548,6 +557,8 @@ public class StagingView extends ViewPart implements IShowInSource { private Action refreshAction; + private Action sortAction; + private SashForm stagingSashForm; private IndexDiffChangedListener myIndexDiffListener = new IndexDiffChangedListener() { @@ -640,10 +651,12 @@ public class StagingView extends ViewPart implements IShowInSource { unstagedSection = toolkit.createSection(stagingSashForm, ExpandableComposite.TITLE_BAR); + unstagedSection.setLayoutData( + GridDataFactory.fillDefaults().grab(true, true).create()); + createUnstagedToolBarComposite(); - Composite unstagedComposite = toolkit - .createComposite(unstagedSection); + Composite unstagedComposite = toolkit.createComposite(unstagedSection); toolkit.paintBordersFor(unstagedComposite); unstagedSection.setClient(unstagedComposite); GridLayoutFactory.fillDefaults().extendedMargins(2, 2, 2, 2) @@ -688,6 +701,8 @@ public class StagingView extends ViewPart implements IShowInSource { compareWith(event); } }); + unstagedViewer + .setComparator(new UnstagedComparator(getSortCheckState())); enableAutoExpand(unstagedViewer); addListenerToDisableAutoExpandOnCollapse(unstagedViewer); @@ -1275,6 +1290,10 @@ public class StagingView extends ViewPart implements IShowInSource { } } + private boolean getSortCheckState() { + return getDialogSettings().getBoolean(STORE_SORT_STATE); + } + private void executeRebaseOperation(AbstractRebaseCommandHandler command) { try { command.execute(currentRepository); @@ -1333,8 +1352,25 @@ public class StagingView extends ViewPart implements IShowInSource { }; unstagedCollapseAllAction.setImageDescriptor(UIIcons.COLLAPSEALL); + sortAction = new Action(UIText.StagingView_UnstagedSort, + IAction.AS_CHECK_BOX) { + + @Override + public void run() { + UnstagedComparator comparator = (UnstagedComparator) unstagedViewer + .getComparator(); + comparator.setAlphabeticSort(isChecked()); + unstagedViewer.refresh(); + } + }; + + sortAction.setImageDescriptor(UIIcons.ALPHABETICALLY_SORT); + sortAction.setId(SORT_ITEM_TOOLBAR_ID); + sortAction.setChecked(getSortCheckState()); + unstagedToolBarManager = new ToolBarManager(SWT.FLAT | SWT.HORIZONTAL); + unstagedToolBarManager.add(sortAction); unstagedToolBarManager.add(unstagedExpandAllAction); unstagedToolBarManager.add(unstagedCollapseAllAction); @@ -1748,14 +1784,21 @@ public class StagingView extends ViewPart implements IShowInSource { } private void setExpandCollapseActionsVisible(boolean visible) { - for (IContributionItem item : unstagedToolBarManager.getItems()) - item.setVisible(visible); - for (IContributionItem item : stagedToolBarManager.getItems()) - item.setVisible(visible); + for (IContributionItem item : unstagedToolBarManager.getItems()) { + if (!SORT_ITEM_TOOLBAR_ID.equals(item.getId())) { + item.setVisible(visible); + } + } + for (IContributionItem item : stagedToolBarManager.getItems()) { + if (!SORT_ITEM_TOOLBAR_ID.equals(item.getId())) { + item.setVisible(visible); + } + } unstagedExpandAllAction.setEnabled(visible); unstagedCollapseAllAction.setEnabled(visible); stagedExpandAllAction.setEnabled(visible); stagedCollapseAllAction.setEnabled(visible); + sortAction.setEnabled(true); unstagedToolBarManager.update(true); stagedToolBarManager.update(true); } @@ -1948,10 +1991,11 @@ public class StagingView extends ViewPart implements IShowInSource { Action openCompareWithIndex = new Action( UIText.StagingView_CompareWithIndexMenuLabel) { + @Override public void run() { runCommand(ActionCommands.COMPARE_WITH_INDEX_ACTION, fileSelection); - }; + } }; menuMgr.add(openCompareWithIndex); } @@ -3192,6 +3236,9 @@ public class StagingView extends ViewPart implements IShowInSource { getPreferenceStore().removePropertyChangeListener(uiPrefsListener); + + getDialogSettings().put(STORE_SORT_STATE, sortAction.isChecked()); + disposed = true; } @@ -3207,4 +3254,91 @@ public class StagingView extends ViewPart implements IShowInSource { PlatformUI.getWorkbench().getDisplay().asyncExec(runnable); } + /** + * This comparator sorts the {@link StagingEntry}s in a grouped or in a + * alphabetically order. The grouped order is also in a alphabetically order + * sorted. + */ + private static class UnstagedComparator extends ViewerComparator { + + private boolean alphabeticSort; + + private Comparator comparator; + + private UnstagedComparator(boolean alphabeticSort) { + this.alphabeticSort = alphabeticSort; + comparator = CommonUtils.STRING_ASCENDING_COMPARATOR; + } + + private void setAlphabeticSort(boolean sort) { + this.alphabeticSort = sort; + } + + private boolean isAlphabeticSort() { + return alphabeticSort; + } + + @Override + public int category(Object element) { + if (!isAlphabeticSort()) { + StagingEntry stagingEntry = getStagingEntry(element); + if (stagingEntry != null) { + return getState(stagingEntry); + } + } + return super.category(element); + } + + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + int cat1 = category(e1); + int cat2 = category(e2); + + if (cat1 != cat2) { + return cat1 - cat2; + } + + String name1 = getStagingEntryName(e1); + String name2 = getStagingEntryName(e2); + + return comparator.compare(name1, name2); + } + + private String getStagingEntryName(Object element) { + String name = ""; //$NON-NLS-1$ + StagingEntry stagingEntry = getStagingEntry(element); + if (stagingEntry != null) { + name = stagingEntry.getName(); + } + return name; + } + + @Nullable + private StagingEntry getStagingEntry(Object element) { + StagingEntry entry = null; + if (element instanceof StagingEntry) { + entry = (StagingEntry) element; + } + if (element instanceof TreeItem) { + TreeItem item = (TreeItem) element; + if (item.getData() instanceof StagingEntry) { + entry = (StagingEntry) item.getData(); + } + } + return entry; + } + + private int getState(StagingEntry entry) { + switch (entry.getState()) { + case UNTRACKED: + return 1; + case MISSING: + return 2; + case MODIFIED: + return 3; + default: + return super.category(entry); + } + } + } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewLabelProvider.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewLabelProvider.java index adc7887e43..e57962249b 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewLabelProvider.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewLabelProvider.java @@ -1,10 +1,12 @@ /******************************************************************************* - * Copyright (C) 2011, 2014 Bernard Leach and others. + * Copyright (C) 2011, 2015 Bernard Leach and others. + * Copyright (C) 2015 Denis Zygann * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html + * *******************************************************************************/ package org.eclipse.egit.ui.internal.staging; @@ -18,6 +20,7 @@ import org.eclipse.egit.ui.internal.UIIcons; import org.eclipse.egit.ui.internal.decorators.DecorationResult; import org.eclipse.egit.ui.internal.decorators.GitLightweightDecorator.DecorationHelper; import org.eclipse.egit.ui.internal.staging.StagingView.Presentation; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.resource.LocalResourceManager; @@ -27,6 +30,7 @@ import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.StyledString; import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.model.WorkbenchLabelProvider; @@ -145,7 +149,12 @@ public class StagingViewLabelProvider extends LabelProvider { return stagingFolderEntry.getNodePath().toString(); } - StagingEntry stagingEntry = (StagingEntry) element; + StagingEntry stagingEntry = getStagingEntry(element); + + if (stagingEntry == null) { + return ""; //$NON-NLS-1$ + } + final DecorationResult decoration = new DecorationResult(); decorationHelper.decorate(decoration, stagingEntry); final StyledString styled = new StyledString(); @@ -181,4 +190,21 @@ public class StagingViewLabelProvider extends LabelProvider { return styled.toString(); } + @Nullable + private StagingEntry getStagingEntry(Object element) { + StagingEntry entry = null; + + if (element instanceof StagingEntry) { + entry = (StagingEntry) element; + } + + if (element instanceof TreeItem) { + TreeItem item = (TreeItem) element; + if (item.getData() instanceof StagingEntry) { + entry = (StagingEntry) item.getData(); + } + } + return entry; + } + } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties index 3f9f3c45f5..837ca558cf 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties @@ -18,6 +18,7 @@ # Mickael Istria (Red Hat Inc.) - 463339 Simple push wizard improvements # Axel Richard - handle symlink decorator in staging view # Christian Georgi - Check for empty second line is configurable +# Denis Zygann - 473919 Add tooltip text for sorting files action ############################################################################### AbortRebaseCommand_CancelDialogMessage=The abort operation was canceled AbortRebaseCommand_JobName=Aborting Rebase @@ -1789,6 +1790,7 @@ StagingView_LinkSelection=Link with Editor and Selection StagingView_replaceWithFileInGitIndex=Replace with &Index StagingView_replaceWithHeadRevision=Replace with &HEAD Revision StagingView_UnstageItemMenuLabel=&Remove from Index +StagingView_UnstagedSort=Sort alphabetically StagingView_StageItemMenuLabel=&Add to Index StagingView_IgnoreItemMenuLabel=&Ignore StagingView_DeleteItemMenuLabel=&Delete -- cgit v1.2.3