Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add icon decoration for tracked and untracked resources

Can be enabled/disabled in the preferences

Signed-off-by: Tor Arne Vestbø <torarnv@gmail.com>
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
  • Loading branch information...
commit 3c0fab8043a6d5f8c1a5efe13f3d02c48b1eae06 1 parent 58a6ba8
@torarnv torarnv authored robinrosenberg committed
View
BIN  org.spearce.egit.ui/icons/ovr/shared.gif
Deleted file not rendered
View
BIN  org.spearce.egit.ui/icons/ovr/untracked.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
4 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,
View
6 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");
View
4 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.
View
6 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);
View
162 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
View
15 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();
}
View
89 ...arce.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) {
+ preview.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 {
View
2  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
Please sign in to comment.
Something went wrong with that request. Please try again.