From cfea8aa03dd0f397febd0eafe154ed6e5a30ed22 Mon Sep 17 00:00:00 2001 From: Stephen Elsemore Date: Fri, 10 May 2013 13:53:18 -0700 Subject: Add file filtering to the Staging View toolbar Bug: 407776 Change-Id: I6c31047587b53ae84efe64492206d74cac3893e4 Signed-off-by: Stephen Elsemore Signed-off-by: Matthias Sohn --- .../src/org/eclipse/egit/ui/internal/UIText.java | 3 + .../egit/ui/internal/staging/StagingView.java | 133 +++++++++++++++++++-- .../staging/StagingViewContentProvider.java | 4 + .../org/eclipse/egit/ui/internal/uitext.properties | 1 + 4 files changed, 134 insertions(+), 7 deletions(-) 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 593dad4524..d472c4d8a0 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 @@ -4653,6 +4653,9 @@ public class UIText extends NLS { /** */ public static String StagingView_DeleteItemMenuLabel; + /** */ + public static String StagingView_Find; + /** */ public static String StagingViewContentProvider_SubmoduleError; 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 5d588d8b1c..cc6740d04b 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 @@ -67,6 +67,7 @@ import org.eclipse.egit.ui.internal.operations.DeletePathsOperationUI; import org.eclipse.egit.ui.internal.operations.IgnoreOperationUI; import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNode; import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.ControlContribution; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.IMenuListener; @@ -93,6 +94,8 @@ import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.OpenEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jgit.api.AddCommand; import org.eclipse.jgit.api.CheckoutCommand; import org.eclipse.jgit.api.Git; @@ -133,9 +136,12 @@ import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.VerifyEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IActionBars; @@ -176,6 +182,8 @@ public class StagingView extends ViewPart implements IShowInSource { private static final String EMPTY_STRING = ""; //$NON-NLS-1$ + private FormToolkit toolkit; + private Form form; private Section stagedSection; @@ -190,6 +198,8 @@ public class StagingView extends ViewPart implements IShowInSource { private ToggleableWarningLabel warningLabel; + private Text filterText; + private SpellcheckableMessageArea commitMessageText; private Text committerText; @@ -266,6 +276,31 @@ public class StagingView extends ViewPart implements IShowInSource { } } + static class StagingViewSearchThread extends Thread { + private StagingView stagingView; + + private static final Object lock = new Object(); + + private volatile static int globalThreadIndex = 0; + + private int currentThreadIx; + + public StagingViewSearchThread(StagingView stagingView) { + super("staging_view_filter_thread" + ++globalThreadIndex); //$NON-NLS-1$ + this.stagingView = stagingView; + currentThreadIx = globalThreadIndex; + } + + public void run() { + synchronized (lock) { + if (currentThreadIx < globalThreadIndex) + return; + stagingView.refreshViewers(); + } + } + + } + private final IPreferenceChangeListener prefListener = new IPreferenceChangeListener() { public void preferenceChange(PreferenceChangeEvent event) { @@ -319,7 +354,7 @@ public class StagingView extends ViewPart implements IShowInSource { public void createPartControl(Composite parent) { GridLayoutFactory.fillDefaults().applyTo(parent); - final FormToolkit toolkit = new FormToolkit(parent.getDisplay()); + toolkit = new FormToolkit(parent.getDisplay()); parent.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { @@ -701,6 +736,27 @@ public class StagingView extends ViewPart implements IShowInSource { } site.setSelectionProvider(unstagedTableViewer); + + ViewerFilter filter = new ViewerFilter() { + @Override + public boolean select(Viewer viewer, Object parentElement, + Object element) { + if (element instanceof StagingEntry) { + if (filterText != null && filterText.getText() != null + && filterText.getText().trim().length() > 0) { + return ((StagingEntry) element) + .getPath() + .toUpperCase() + .contains( + filterText.getText().trim() + .toUpperCase()); + } + } + return true; + } + }; + unstagedTableViewer.addFilter(filter); + stagedTableViewer.addFilter(filter); } public ShowInContext getShowInContext() { @@ -756,9 +812,51 @@ public class StagingView extends ViewPart implements IShowInSource { } private void updateToolbar() { + + ControlContribution controlContribution = new ControlContribution( + "StagingView.searchText") { //$NON-NLS-1$ + @Override + protected Control createControl(Composite parent) { + Composite toolbarComposite = toolkit.createComposite(parent, + SWT.NONE); + toolbarComposite.setBackground(null); + GridLayout headLayout = new GridLayout(); + headLayout.numColumns = 2; + headLayout.marginHeight = 0; + headLayout.marginWidth = 0; + headLayout.marginTop = 0; + headLayout.marginBottom = 0; + headLayout.marginLeft = 0; + headLayout.marginRight = 0; + toolbarComposite.setLayout(headLayout); + + filterText = new Text(toolbarComposite, SWT.SEARCH + | SWT.ICON_CANCEL | SWT.ICON_SEARCH); + filterText.setMessage(UIText.StagingView_Find); + GridData data = new GridData(GridData.FILL_HORIZONTAL); + data.widthHint = 150; + filterText.setLayoutData(data); + final Display display = Display.getCurrent(); + filterText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + final StagingViewSearchThread searchThread = new StagingViewSearchThread( + StagingView.this); + display.timerExec(200, new Runnable() { + public void run() { + searchThread.start(); + } + }); + } + }); + return toolbarComposite; + } + }; + IActionBars actionBars = getViewSite().getActionBars(); IToolBarManager toolbar = actionBars.getToolBarManager(); + toolbar.add(controlContribution); + refreshAction = new Action(UIText.StagingView_Refresh, IAction.AS_PUSH_BUTTON) { public void run() { if(cacheEntry != null) @@ -864,14 +962,22 @@ public class StagingView extends ViewPart implements IShowInSource { } private void updateSectionText() { - Integer stagedCount = Integer.valueOf(stagedTableViewer.getTable() - .getItemCount()); stagedSection.setText(MessageFormat.format( - UIText.StagingView_StagedChanges, stagedCount)); - Integer unstagedCount = Integer.valueOf(unstagedTableViewer.getTable() - .getItemCount()); + UIText.StagingView_StagedChanges, + getSectionCount(stagedTableViewer))); unstagedSection.setText(MessageFormat.format( - UIText.StagingView_UnstagedChanges, unstagedCount)); + UIText.StagingView_UnstagedChanges, + getSectionCount(unstagedTableViewer))); + } + + private String getSectionCount(TableViewer viewer) { + int stagingEntryCount = ((StagingViewContentProvider) viewer + .getContentProvider()).getStagingEntryCount(); + int itemCount = viewer.getTable().getItemCount(); + if (itemCount == stagingEntryCount) + return Integer.toString(itemCount); + else + return itemCount + "/" + stagingEntryCount; //$NON-NLS-1$ } private void updateMessage() { @@ -996,6 +1102,19 @@ public class StagingView extends ViewPart implements IShowInSource { } + /** + * Refresh the unstaged and staged viewers + */ + public void refreshViewers() { + Display.getDefault().asyncExec(new Runnable() { + public void run() { + unstagedTableViewer.refresh(); + stagedTableViewer.refresh(); + updateSectionText(); + } + }); + } + private IContributionItem createShowInMenu() { IWorkbenchWindow workbenchWindow = getSite().getWorkbenchWindow(); return UIUtils.createShowInMenu(workbenchWindow); diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewContentProvider.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewContentProvider.java index 47d953e840..25c62b269b 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewContentProvider.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewContentProvider.java @@ -53,6 +53,10 @@ public class StagingViewContentProvider implements return content; } + int getStagingEntryCount() { + return content.length; + } + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { if (!(newInput instanceof StagingViewUpdate)) 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 6b0aeb2c56..ff1fb94a43 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 @@ -1625,6 +1625,7 @@ StagingView_UnstageItemMenuLabel=Remove from Git Index StagingView_StageItemMenuLabel=Add to Git Index StagingView_IgnoreItemMenuLabel=Ignore StagingView_DeleteItemMenuLabel=Delete +StagingView_Find=Filter files StagingViewContentProvider_SubmoduleError=Unhandled exception while analyzing submodules StashApplyCommand_applyFailed=Applying stashed commit ''{0}'' failed due to ''{1}'' StashApplyCommand_jobTitle=Apply changes from stashed commit ''{0}'' -- cgit v1.2.3