Can be enabled/disabled in the preferences Signed-off-by: Tor Arne Vestbø <torarnv@xxxxxxxxx> --- org.spearce.egit.ui/icons/ovr/shared.gif | Bin 106 -> 0 bytes org.spearce.egit.ui/icons/ovr/untracked.gif | Bin 0 -> 79 bytes .../egit/ui/PluginPreferenceInitializer.java | 4 +- .../src/org/spearce/egit/ui/UIIcons.java | 6 +- .../src/org/spearce/egit/ui/UIPreferences.java | 4 + .../src/org/spearce/egit/ui/UIText.java | 6 + .../decorators/GitLightweightDecorator.java | 162 ++++++++++++++++++-- .../internal/decorators/IDecoratableResource.java | 15 ++ .../preferences/GitDecoratorPreferencePage.java | 89 +++++++++-- .../src/org/spearce/egit/ui/uitext.properties | 2 + 10 files changed, 259 insertions(+), 29 deletions(-) delete mode 100644 org.spearce.egit.ui/icons/ovr/shared.gif create mode 100644 org.spearce.egit.ui/icons/ovr/untracked.gif diff --git a/org.spearce.egit.ui/icons/ovr/shared.gif b/org.spearce.egit.ui/icons/ovr/shared.gif deleted file mode 100644 index eb71a3c742e133c2ed61c958e237c71e0f7cb6aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106 zcmZ?wbhEHbWM|-D*v!E2|KHF5k5c|0Q~7_){{ITmE8U{M-dx?8EBgQce+Fzo@h1x- p15m3DND^cQ1B<x8$xa82iYrMhmeJo^<v0pdEtw8K%o1d<1^~aoAP)cl diff --git a/org.spearce.egit.ui/icons/ovr/untracked.gif b/org.spearce.egit.ui/icons/ovr/untracked.gif new file mode 100644 index 0000000000000000000000000000000000000000..45ca32060700d71abcb88bbcdb1000d503fe11cf GIT binary patch literal 79 zcmZ?wbhEHbWM|-DSj51<z}U+mGMhnsAy57};pVIV!2l?%_>+Z^fq{)d2gqgssbydm biP#m!(lAAgdxkboj%vJ&f(EaJDuXouU6m8v literal 0 HcmV?d00001 diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/PluginPreferenceInitializer.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/PluginPreferenceInitializer.java index 79c2665..7465444 100644 --- a/org.spearce.egit.ui/src/org/spearce/egit/ui/PluginPreferenceInitializer.java +++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/PluginPreferenceInitializer.java @@ -35,13 +35,15 @@ public void initializeDefaultPreferences() { prefs.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_REV_COMMENT, true); prefs.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_TOOLTIPS, false); + prefs.setDefault(UIPreferences.DECORATOR_CALCULATE_DIRTY, true); prefs.setDefault(UIPreferences.DECORATOR_FILETEXT_DECORATION, UIText.DecoratorPreferencesPage_fileFormatDefault); prefs.setDefault(UIPreferences.DECORATOR_FOLDERTEXT_DECORATION, UIText.DecoratorPreferencesPage_folderFormatDefault); prefs.setDefault(UIPreferences.DECORATOR_PROJECTTEXT_DECORATION, UIText.DecoratorPreferencesPage_projectFormatDefault); - prefs.setDefault(UIPreferences.DECORATOR_CALCULATE_DIRTY, true); + prefs.setDefault(UIPreferences.DECORATOR_SHOW_TRACKED_ICON, true); + prefs.setDefault(UIPreferences.DECORATOR_SHOW_UNTRACKED_ICON, true); w = new int[] { 500, 500 }; UIPreferences.setDefault(prefs, diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/UIIcons.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/UIIcons.java index ced186e..4c0d189 100644 --- a/org.spearce.egit.ui/src/org/spearce/egit/ui/UIIcons.java +++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/UIIcons.java @@ -24,8 +24,8 @@ /** Decoration for resource removed from the index but not commit. */ public static final ImageDescriptor OVR_PENDING_REMOVE; - /** Decoration for resource tracked and committed in git. */ - public static final ImageDescriptor OVR_SHARED; + /** Decoration for resource not being tracked by Git */ + public static final ImageDescriptor OVR_UNTRACKED; /** Decoration for tracked resource with a merge conflict. */ public static final ImageDescriptor OVR_CONFLICT; @@ -86,7 +86,7 @@ base = init(); OVR_PENDING_ADD = map("ovr/pending_add.gif"); OVR_PENDING_REMOVE = map("ovr/pending_remove.gif"); - OVR_SHARED = map("ovr/shared.gif"); + OVR_UNTRACKED = map("ovr/untracked.gif"); OVR_CONFLICT = map("ovr/conflict.gif"); OVR_ASSUMEVALID = map("ovr/assumevalid.gif"); ELCL16_FIND = map("elcl16/find.gif"); diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/UIPreferences.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/UIPreferences.java index a6168a0..7916cea 100644 --- a/org.spearce.egit.ui/src/org/spearce/egit/ui/UIPreferences.java +++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/UIPreferences.java @@ -60,6 +60,10 @@ public final static String DECORATOR_FOLDERTEXT_DECORATION = "decorator_foldertext_decoration"; /** */ public final static String DECORATOR_PROJECTTEXT_DECORATION = "decorator_projecttext_decoration"; + /** */ + public final static String DECORATOR_SHOW_TRACKED_ICON = "decorator_show_tracked_icon"; + /** */ + public final static String DECORATOR_SHOW_UNTRACKED_ICON = "decorator_show_untracked_icon"; /** * Get the preference values associated with a fixed integer array. diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java index 345c66b..60e4eaa 100644 --- a/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java +++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java @@ -988,6 +988,12 @@ /** */ public static String DecoratorPreferencesPage_labelDecorationsLink; + /** */ + public static String DecoratorPreferencesPage_iconsShowTracked; + + /** */ + public static String DecoratorPreferencesPage_iconsShowUntracked; + static { initializeMessages(UIText.class.getPackage().getName() + ".uitext", UIText.class); diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/GitLightweightDecorator.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/GitLightweightDecorator.java index 265d5a3..b20070a 100644 --- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/GitLightweightDecorator.java +++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/GitLightweightDecorator.java @@ -15,6 +15,7 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -34,6 +35,7 @@ import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.IDecoration; @@ -41,7 +43,11 @@ import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.LabelProviderChangedEvent; import org.eclipse.osgi.util.TextProcessor; +import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.widgets.Display; +import org.eclipse.team.core.Team; +import org.eclipse.team.ui.ISharedImages; +import org.eclipse.team.ui.TeamImages; import org.eclipse.team.ui.TeamUI; import org.eclipse.ui.IContributorResourceAdapter; import org.eclipse.ui.PlatformUI; @@ -51,13 +57,22 @@ import org.spearce.egit.core.project.RepositoryChangeListener; import org.spearce.egit.core.project.RepositoryMapping; import org.spearce.egit.ui.Activator; +import org.spearce.egit.ui.UIIcons; import org.spearce.egit.ui.UIPreferences; import org.spearce.egit.ui.UIText; +import org.spearce.jgit.dircache.DirCache; +import org.spearce.jgit.dircache.DirCacheIterator; +import org.spearce.jgit.lib.Constants; import org.spearce.jgit.lib.IndexChangedEvent; +import org.spearce.jgit.lib.ObjectId; import org.spearce.jgit.lib.RefsChangedEvent; import org.spearce.jgit.lib.Repository; import org.spearce.jgit.lib.RepositoryChangedEvent; import org.spearce.jgit.lib.RepositoryListener; +import org.spearce.jgit.revwalk.RevWalk; +import org.spearce.jgit.treewalk.EmptyTreeIterator; +import org.spearce.jgit.treewalk.TreeWalk; +import org.spearce.jgit.treewalk.filter.PathFilterGroup; /** * Supplies annotations for displayed resources @@ -144,7 +159,7 @@ public void decorate(Object element, IDecoration decoration) { if (!resource.exists() && !resource.isPhantom()) return; - // Make sure we're dealing with a Git project + // Make sure we're dealing with a project under Git revision control final RepositoryMapping mapping = RepositoryMapping .getMapping(resource); if (mapping == null) @@ -171,14 +186,80 @@ public void decorate(Object element, IDecoration decoration) { private class DecoratableResourceAdapter implements IDecoratableResource { - private IResource resource; - private String branch; + private final IResource resource; - public DecoratableResourceAdapter(IResource resourceToWrap) throws IOException { + private final RepositoryMapping mapping; + + private final Repository repository; + + private final ObjectId headId; + + private String branch = ""; + + private boolean tracked = false; + + private boolean ignored = false; + + public DecoratableResourceAdapter(IResource resourceToWrap) + throws IOException { resource = resourceToWrap; - RepositoryMapping mapping = RepositoryMapping.getMapping(resource); - Repository repository = mapping.getRepository(); + mapping = RepositoryMapping.getMapping(resource); + repository = mapping.getRepository(); + headId = repository.resolve(Constants.HEAD); + + initializeValues(); + } + + /** + * Initialize the various values that are used for making decoration + * decisions later on. + * + * We might as well pre-load these now, instead of using lazy + * initialization, because they are all read by the decorator when + * building variable bindings and computing the preferred overlay. + * + * @throws IOException + */ + private void initializeValues() throws IOException { + + // Resolve current branch branch = repository.getBranch(); + + // Resolve tracked state + if (getType() == IResource.PROJECT) { + tracked = true; + } else { + final TreeWalk treeWalk = new TreeWalk(repository); + + Set<String> repositoryPaths = Collections.singleton(mapping + .getRepoRelativePath(resource)); + if (!(repositoryPaths.isEmpty() || repositoryPaths.contains(""))) { + treeWalk.setFilter(PathFilterGroup + .createFromStrings(repositoryPaths)); + treeWalk.setRecursive(treeWalk.getFilter() + .shouldBeRecursive()); + treeWalk.reset(); + + if (headId != null) + treeWalk.addTree(new RevWalk(repository) + .parseTree(headId)); + else + treeWalk.addTree(new EmptyTreeIterator()); + + treeWalk.addTree(new DirCacheIterator(DirCache + .read(repository))); + if (treeWalk.next()) { + tracked = true; + } + } + } + + // Resolve ignored state (currently only reads the global Eclipse + // ignores) + // TODO: Also read ignores from .git/info/excludes et al. + if (Team.isIgnoredHint(resource)) { + ignored = true; + } } public String getName() { @@ -192,6 +273,14 @@ public int getType() { public String getBranch() { return branch; } + + public boolean isTracked() { + return tracked; + } + + public boolean isIgnored() { + return ignored; + } } /** @@ -203,13 +292,45 @@ public String getBranch() { */ public static class DecorationHelper { - private IPreferenceStore store; - /** */ public static final String BINDING_RESOURCE_NAME = "name"; //$NON-NLS-1$ + /** */ public static final String BINDING_BRANCH_NAME = "branch"; //$NON-NLS-1$ + private IPreferenceStore store; + + /** + * Define a cached image descriptor which only creates the image data + * once + */ + private static class CachedImageDescriptor extends ImageDescriptor { + ImageDescriptor descriptor; + + ImageData data; + + public CachedImageDescriptor(ImageDescriptor descriptor) { + this.descriptor = descriptor; + } + + public ImageData getImageData() { + if (data == null) { + data = descriptor.getImageData(); + } + return data; + } + } + + private static ImageDescriptor trackedImage; + + private static ImageDescriptor untrackedImage; + + static { + trackedImage = new CachedImageDescriptor(TeamImages + .getImageDescriptor(ISharedImages.IMG_CHECKEDIN_OVR)); + untrackedImage = new CachedImageDescriptor(UIIcons.OVR_UNTRACKED); + } + /** * Constructs a decorator using the rules from the given * <code>preferencesStore</code> @@ -233,6 +354,12 @@ public DecorationHelper(IPreferenceStore preferencesStore) { */ public void decorate(IDecoration decoration, IDecoratableResource resource) { + decorateText(decoration, resource); + decorateIcons(decoration, resource); + } + + private void decorateText(IDecoration decoration, + IDecoratableResource resource) { String format = ""; switch (resource.getType()) { case IResource.FILE: @@ -256,9 +383,24 @@ public void decorate(IDecoration decoration, decorate(decoration, format, bindings); } + private void decorateIcons(IDecoration decoration, + IDecoratableResource resource) { + if (resource.isIgnored()) + return; + + if (resource.isTracked()) { + if (store.getBoolean(UIPreferences.DECORATOR_SHOW_TRACKED_ICON)) + decoration.addOverlay(trackedImage); + } else if (store + .getBoolean(UIPreferences.DECORATOR_SHOW_UNTRACKED_ICON)) { + decoration.addOverlay(untrackedImage); + } + } + /** - * Decorates the given <code>decoration</code>, using the given - * <code>format</code>, and mapped using <code>bindings</code> + * Decorates the given <code>decoration</code>, using the specified text + * <code>format</code>, and mapped using the variable bindings from + * <code>bindings</code> * * @param decoration * the decoration to decorate diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/IDecoratableResource.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/IDecoratableResource.java index 6b36e0e..f144214 100644 --- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/IDecoratableResource.java +++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/IDecoratableResource.java @@ -36,4 +36,19 @@ * applicable */ String getBranch(); + + /** + * Returns whether or not the resource is tracked by Git + * + * @return whether or not the resource is tracked by Git + */ + boolean isTracked(); + + /** + * Returns whether or not the resource is ignored, either by a global team + * ignore in Eclipse, or by .git/info/exclude et al. + * + * @return whether or not the resource is ignored + */ + boolean isIgnored(); } diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/preferences/GitDecoratorPreferencePage.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/preferences/GitDecoratorPreferencePage.java index b7d737c..7b637e3 100644 --- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/preferences/GitDecoratorPreferencePage.java +++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/preferences/GitDecoratorPreferencePage.java @@ -44,6 +44,9 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; @@ -83,7 +86,11 @@ private Text projectTextFormat; - private Button showDirty; + private Button computeDeepDirtyState; + + private Button showTracked; + + private Button showUntracked; private Preview preview; @@ -93,10 +100,16 @@ static { final PreviewResource project = new PreviewResource( - "Project", IResource.PROJECT, "master"); //$NON-NLS-1$1 + "Project", IResource.PROJECT, "master", true, false); //$NON-NLS-1$1 final ArrayList<PreviewResource> children = new ArrayList<PreviewResource>(); - children.add(new PreviewResource("folder", IResource.FOLDER, null)); //$NON-NLS-1$ - children.add(new PreviewResource("file.txt", IResource.FILE, null)); //$NON-NLS-1$ + children.add(new PreviewResource( + "folder", IResource.FOLDER, null, true, false)); //$NON-NLS-1$ + children.add(new PreviewResource( + "file.txt", IResource.FILE, null, true, false)); //$NON-NLS-1$ + children.add(new PreviewResource( + "untracked.txt", IResource.FILE, null, false, false)); //$NON-NLS-1$ + children.add(new PreviewResource( + "ignored.txt", IResource.FILE, null, false, true)); //$NON-NLS-1$ project.children = children; PREVIEW_FILESYSTEM_ROOT = Collections.singleton(project); } @@ -160,7 +173,7 @@ private Control createGeneralDecoratorPage(Composite parent) { Composite composite = SWTUtils.createHVFillComposite(parent, SWTUtils.MARGINS_DEFAULT); - showDirty = SWTUtils.createCheckBox(composite, + computeDeepDirtyState = SWTUtils.createCheckBox(composite, UIText.DecoratorPreferencesPage_computeDeep); return composite; @@ -202,6 +215,11 @@ private Control createIconDecoratorPage(Composite parent) { Composite imageGroup = SWTUtils.createHVFillComposite(parent, SWTUtils.MARGINS_DEFAULT, 2); + showTracked = SWTUtils.createCheckBox(imageGroup, + UIText.DecoratorPreferencesPage_iconsShowTracked); + showUntracked = SWTUtils.createCheckBox(imageGroup, + UIText.DecoratorPreferencesPage_iconsShowUntracked); + return imageGroup; } @@ -241,6 +259,9 @@ public void handleEvent(Event event) { private void initializeValues() { final IPreferenceStore store = getPreferenceStore(); + computeDeepDirtyState.setSelection(store + .getBoolean(UIPreferences.DECORATOR_CALCULATE_DIRTY)); + fileTextFormat.setText(store .getString(UIPreferences.DECORATOR_FILETEXT_DECORATION)); folderTextFormat.setText(store @@ -248,8 +269,20 @@ private void initializeValues() { projectTextFormat.setText(store .getString(UIPreferences.DECORATOR_PROJECTTEXT_DECORATION)); - showDirty.setSelection(store - .getBoolean(UIPreferences.DECORATOR_CALCULATE_DIRTY)); + showTracked.setSelection(store + .getBoolean(UIPreferences.DECORATOR_SHOW_TRACKED_ICON)); + showUntracked.setSelection(store + .getBoolean(UIPreferences.DECORATOR_SHOW_UNTRACKED_ICON)); + + SelectionListener selectionListener = new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + fPreview.refresh(); + } + }; + + computeDeepDirtyState.addSelectionListener(selectionListener); + showTracked.addSelectionListener(selectionListener); + showUntracked.addSelectionListener(selectionListener); setValid(true); } @@ -287,6 +320,9 @@ public boolean performOk() { */ private boolean performOk(IPreferenceStore store) { + store.setValue(UIPreferences.DECORATOR_CALCULATE_DIRTY, + computeDeepDirtyState.getSelection()); + store.setValue(UIPreferences.DECORATOR_FILETEXT_DECORATION, fileTextFormat.getText()); store.setValue(UIPreferences.DECORATOR_FOLDERTEXT_DECORATION, @@ -294,8 +330,10 @@ private boolean performOk(IPreferenceStore store) { store.setValue(UIPreferences.DECORATOR_PROJECTTEXT_DECORATION, projectTextFormat.getText()); - store.setValue(UIPreferences.DECORATOR_CALCULATE_DIRTY, showDirty + store.setValue(UIPreferences.DECORATOR_SHOW_TRACKED_ICON, showTracked .getSelection()); + store.setValue(UIPreferences.DECORATOR_SHOW_UNTRACKED_ICON, + showUntracked.getSelection()); return true; } @@ -308,6 +346,9 @@ protected void performDefaults() { super.performDefaults(); IPreferenceStore store = getPreferenceStore(); + computeDeepDirtyState.setSelection(store + .getDefaultBoolean(UIPreferences.DECORATOR_CALCULATE_DIRTY)); + fileTextFormat.setText(store .getDefaultString(UIPreferences.DECORATOR_FILETEXT_DECORATION)); folderTextFormat @@ -317,8 +358,11 @@ protected void performDefaults() { .setText(store .getDefaultString(UIPreferences.DECORATOR_PROJECTTEXT_DECORATION)); - showDirty.setSelection(store - .getDefaultBoolean(UIPreferences.DECORATOR_CALCULATE_DIRTY)); + showTracked.setSelection(store + .getDefaultBoolean(UIPreferences.DECORATOR_SHOW_TRACKED_ICON)); + showUntracked + .setSelection(store + .getDefaultBoolean(UIPreferences.DECORATOR_SHOW_UNTRACKED_ICON)); } /** @@ -602,19 +646,26 @@ private PreviewDecoration getDecoration(Object element) { } private static class PreviewResource implements IDecoratableResource { - public final String name; + private final String name; + + private final String branch; - public final String branch; + private final int type; - public final int type; + private Collection children; - public Collection children; + private boolean tracked; - public PreviewResource(String name, int type, String branch) { + private boolean ignored; + + public PreviewResource(String name, int type, String branch, + boolean tracked, boolean ignored) { this.name = name; this.branch = branch; this.type = type; this.children = Collections.EMPTY_LIST; + this.tracked = tracked; + this.ignored = ignored; } public String getName() { @@ -628,6 +679,14 @@ public int getType() { public String getBranch() { return branch; } + + public boolean isTracked() { + return tracked; + } + + public boolean isIgnored() { + return ignored; + } } private class PreviewDecoration implements IDecoration { diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/uitext.properties b/org.spearce.egit.ui/src/org/spearce/egit/ui/uitext.properties index d050be9..9940177 100644 --- a/org.spearce.egit.ui/src/org/spearce/egit/ui/uitext.properties +++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/uitext.properties @@ -369,4 +369,6 @@ DecoratorPreferencesPage_selectFormats=Select the format for file, folders, and DecoratorPreferencesPage_selectVariablesToAdd=Select the &variables to add to the decoration format: DecoratorPreferencesPage_textLabel=T&ext Decorations DecoratorPreferencesPage_iconLabel=&Icon Decorations +DecoratorPreferencesPage_iconsShowTracked=Tracked resources +DecoratorPreferencesPage_iconsShowUntracked=Untracked resources -- 1.6.1.2.309.g2ea3 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html