Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/GitLightweightDecorator.java153
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingView.java13
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewLabelProvider.java59
3 files changed, 180 insertions, 45 deletions
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/GitLightweightDecorator.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/GitLightweightDecorator.java
index 9472e58f59..4d1054fdc7 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/GitLightweightDecorator.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/GitLightweightDecorator.java
@@ -29,6 +29,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
@@ -37,6 +38,7 @@ import org.eclipse.core.runtime.Adapters;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.egit.core.internal.SafeRunnable;
import org.eclipse.egit.core.internal.indexdiff.IndexDiffData;
import org.eclipse.egit.core.internal.util.ExceptionCollector;
import org.eclipse.egit.core.project.GitProjectData;
@@ -108,7 +110,7 @@ public class GitLightweightDecorator extends GitDecorator
UIPreferences.THEME_IgnoredResourceBackgroundColor,
UIPreferences.THEME_IgnoredResourceForegroundColor);
- private final ReloadableColorsAndFonts resources;
+ private final ChangeTrackingColorsAndFonts resources;
private final DecorationHelper helper;
@@ -120,14 +122,12 @@ public class GitLightweightDecorator extends GitDecorator
public GitLightweightDecorator() {
// This is an optimization to ensure that while decorating our fonts and
// colors are pre-created and decoration can occur without having to syncExec.
- resources = new ReloadableColorsAndFonts();
- resources.reload();
+ resources = new ChangeTrackingColorsAndFonts();
helper = new DecorationHelper(
Activator.getDefault().getPreferenceStore(), resources);
+ resources.addListener(this::postLabelEvent);
TeamUI.addPropertyChangeListener(this);
Activator.addPropertyChangeListener(this);
- PlatformUI.getWorkbench().getThemeManager().getCurrentTheme()
- .addPropertyChangeListener(this);
GitProjectData.addRepositoryChangeListener(mappingChangeListener);
}
@@ -135,8 +135,7 @@ public class GitLightweightDecorator extends GitDecorator
@Override
public void dispose() {
super.dispose();
- PlatformUI.getWorkbench().getThemeManager().getCurrentTheme()
- .removePropertyChangeListener(this);
+ resources.dispose();
TeamUI.removePropertyChangeListener(this);
Activator.removePropertyChangeListener(this);
GitProjectData.removeRepositoryChangeListener(mappingChangeListener);
@@ -245,36 +244,95 @@ public class GitLightweightDecorator extends GitDecorator
helper.decorate(decoration, decoRes);
}
- private static interface ColorsAndFonts {
+ /**
+ * A repository of colors and fonts.
+ */
+ public static interface ColorsAndFonts {
+ /**
+ * Retrieves the {@link Color} identified by {@code id}.
+ *
+ * @param id
+ * of the color to get
+ * @return the color, or {@code null} if none
+ */
Color getColor(String id);
+ /**
+ * Retrieves the {@link Font} identified by {@code id}.
+ *
+ * @param id
+ * of the font to get
+ * @return the font, or {@code null} if none
+ */
Font getFont(String id);
+ /**
+ * Retrieves the default font.
+ *
+ * @return the font
+ */
Font getDefaultFont();
+ /**
+ * Retrieves the default background color.
+ *
+ * @return the {@link RGB} of the color
+ */
RGB getDefaultBackground();
}
/**
- * Our own private cache of current colors and fonts. Do not rely on the
- * platform's current theme caching them: when a theme switch occurs, the
- * decorator running asynchronously in the background may get not only wrong
- * but even disposed values, and somehow it never really worked for the
- * default font. The main idea behind caching colors and fonts is to do load
- * them on the UI thread once, and then access them from the decorators
- * background thread. Otherwise the decorator would need to syncExec(),
- * which kind of obviates running in the background.
+ * A font and color cache that tracks changes to the fonts and colors used
+ * by Git decoration and that fires a notification when they have changed.
+ * <p>
+ * The main idea behind caching colors and fonts is to do load them on the
+ * UI thread once, and then access them from the decorators background
+ * thread. Otherwise the decorator would need to syncExec(), which kind of
+ * obviates running in the background.
+ * </p>
*/
- private static class ReloadableColorsAndFonts implements ColorsAndFonts {
+ public static class ChangeTrackingColorsAndFonts implements ColorsAndFonts {
+
+ private final CopyOnWriteArrayList<Runnable> listeners = new CopyOnWriteArrayList<>();
+
+ private final IPropertyChangeListener themeListener = event -> {
+ final String prop = event.getProperty();
+ if (prop == null) {
+ return;
+ }
+ switch (prop) {
+ case IThemeManager.CHANGE_CURRENT_THEME:
+ case TREE_TABLE_FONT:
+ case UIPreferences.THEME_UncommittedChangeBackgroundColor:
+ case UIPreferences.THEME_UncommittedChangeFont:
+ case UIPreferences.THEME_UncommittedChangeForegroundColor:
+ case UIPreferences.THEME_IgnoredResourceFont:
+ case UIPreferences.THEME_IgnoredResourceBackgroundColor:
+ case UIPreferences.THEME_IgnoredResourceForegroundColor:
+ reload();
+ break;
+ default:
+ break;
+ }
+ };
private volatile Map<String, Object> colorsOrFonts = new HashMap<>();
private volatile RGB defaultBackground;
- public void reload() {
- final Display display = PlatformUI.getWorkbench().getDisplay();
+ /**
+ * Creates a new {@link ChangeTrackingColorsAndFonts} object.
+ */
+ public ChangeTrackingColorsAndFonts() {
+ PlatformUI.getWorkbench().getThemeManager().getCurrentTheme()
+ .addPropertyChangeListener(themeListener);
+ reload();
+ }
+
+ private void reload() {
+ Display display = PlatformUI.getWorkbench().getDisplay();
display.syncExec(() -> {
Map<String, Object> newResources = new HashMap<>();
ITheme theme = PlatformUI.getWorkbench().getThemeManager()
@@ -293,6 +351,45 @@ public class GitLightweightDecorator extends GitDecorator
defaultBackground = display
.getSystemColor(SWT.COLOR_LIST_BACKGROUND).getRGB();
});
+ notifyListeners();
+ }
+
+ private void notifyListeners() {
+ for (Runnable listener : listeners) {
+ SafeRunnable.run(listener::run);
+ }
+ }
+
+ /**
+ * Register a listener to be called when the colors or fonts have
+ * changed. A no-op if the listener is already registered.
+ *
+ * @param runnable
+ * to invoke
+ */
+ public void addListener(Runnable runnable) {
+ listeners.addIfAbsent(runnable);
+ }
+
+ /**
+ * Unregister a previously registered listener. A no-op if the listener
+ * is not currently registered.
+ *
+ * @param runnable
+ * to unregister
+ */
+ public void removeListener(Runnable runnable) {
+ listeners.remove(runnable);
+ }
+
+ /**
+ * Disposes internal resources, removes all listeners, and stops
+ * reacting on color or font changes.
+ */
+ public void dispose() {
+ listeners.clear();
+ PlatformUI.getWorkbench().getThemeManager().getCurrentTheme()
+ .removePropertyChangeListener(themeListener);
}
@Override
@@ -482,16 +579,15 @@ public class GitLightweightDecorator extends GitDecorator
}
/**
- * Internal constructor; also used by the
- * {@link GitLightweightDecorator} to provide a {@link ColorsAndFonts}
- * registry that reacts to color, font, or theme changes.
+ * Creates a new {@link DecorationHelper} based on the given
+ * {@link IPreferenceStore} using the given {@link ColorsAndFonts}.
*
* @param preferencesStore
* to get decoration settings from
* @param resources
* to get colors and fonts from
*/
- private DecorationHelper(IPreferenceStore preferencesStore,
+ public DecorationHelper(IPreferenceStore preferencesStore,
ColorsAndFonts resources) {
store = preferencesStore;
this.resources = resources;
@@ -796,17 +892,6 @@ public class GitLightweightDecorator extends GitDecorator
case Activator.DECORATORS_CHANGED:
postLabelEvent();
break;
- case IThemeManager.CHANGE_CURRENT_THEME:
- case TREE_TABLE_FONT:
- case UIPreferences.THEME_UncommittedChangeBackgroundColor:
- case UIPreferences.THEME_UncommittedChangeFont:
- case UIPreferences.THEME_UncommittedChangeForegroundColor:
- case UIPreferences.THEME_IgnoredResourceFont:
- case UIPreferences.THEME_IgnoredResourceBackgroundColor:
- case UIPreferences.THEME_IgnoredResourceForegroundColor:
- resources.reload();
- postLabelEvent();
- break;
default:
break;
}
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 10a459ed6f..0ae2107150 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
@@ -584,10 +584,7 @@ public class StagingView extends ViewPart
public TreeDecoratingLabelProvider(StagingViewLabelProvider base,
ILabelDecorator decorator) {
this.base = base;
- this.provider = new DecoratingLabelProvider(
- new DecoratingLabelProvider(base, decorator),
- PlatformUI.getWorkbench().getDecoratorManager()
- .getLabelDecorator());
+ this.provider = new DecoratingLabelProvider(base, decorator);
}
public StagingViewLabelProvider getBaseLabelProvider() {
@@ -1203,8 +1200,12 @@ public class StagingView extends ViewPart
stagedViewer = createViewer(stagedComposite, false,
selection -> stage(selection.toList()), unstageAction);
stagedViewer.getLabelProvider().addListener(event -> {
- updateMessage();
- updateCommitButtons();
+ if (event.getSource() instanceof ProblemLabelDecorator
+ && !isDisposed()) {
+ // Update UI when problem markers on staged items change
+ updateMessage();
+ updateCommitButtons();
+ }
});
stagedViewer.addSelectionChangedListener(event -> {
boolean hasSelection = !event.getSelection().isEmpty();
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 276e8170e2..4d82722334 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
@@ -14,17 +14,24 @@ package org.eclipse.egit.ui.internal.staging;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
+import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.UIUtils;
import org.eclipse.egit.ui.internal.UIIcons;
+import org.eclipse.egit.ui.internal.decorators.DecorationResult;
+import org.eclipse.egit.ui.internal.decorators.GitLightweightDecorator.ChangeTrackingColorsAndFonts;
+import org.eclipse.egit.ui.internal.decorators.GitLightweightDecorator.DecorationHelper;
import org.eclipse.egit.ui.internal.staging.StagingView.Presentation;
+import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.resource.ResourceManager;
import org.eclipse.jface.viewers.DecorationOverlayIcon;
import org.eclipse.jface.viewers.IDecoration;
import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.LabelProviderChangedEvent;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
@@ -45,6 +52,10 @@ public class StagingViewLabelProvider extends LabelProvider {
private ResourceManager resourceManager = new LocalResourceManager(
JFaceResources.getResources());
+ private final DecorationHelper decorationHelper;
+
+ private final ChangeTrackingColorsAndFonts colorsAndFonts;
+
private boolean fileNameMode = false;
/**
@@ -52,6 +63,10 @@ public class StagingViewLabelProvider extends LabelProvider {
*/
public StagingViewLabelProvider(StagingView stagingView) {
super();
+ colorsAndFonts = new ChangeTrackingColorsAndFonts();
+ decorationHelper = new DecorationHelper(
+ Activator.getDefault().getPreferenceStore(), colorsAndFonts);
+ colorsAndFonts.addListener(this::postLabelEvent);
this.stagingView = stagingView;
}
@@ -70,10 +85,18 @@ public class StagingViewLabelProvider extends LabelProvider {
@Override
public void dispose() {
+ this.colorsAndFonts.dispose();
this.resourceManager.dispose();
super.dispose();
}
+ private void postLabelEvent() {
+ Display display = PlatformUI.getWorkbench().getDisplay();
+ display.asyncExec(() -> {
+ fireLabelProviderChanged(new LabelProviderChangedEvent(this));
+ });
+ }
+
private Image getEditorImage(StagingEntry diff) {
if (diff.isSubmodule()) {
return (Image) resourceManager.get(UIIcons.REPOSITORY);
@@ -95,6 +118,12 @@ public class StagingViewLabelProvider extends LabelProvider {
return image;
}
+ private Image getDecoratedImage(Image base, ImageDescriptor decorator) {
+ DecorationOverlayIcon decorated = new DecorationOverlayIcon(base,
+ decorator, IDecoration.BOTTOM_RIGHT);
+ return (Image) this.resourceManager.get(decorated);
+ }
+
private Image addSymlinkDecorationToImage(Image base) {
DecorationOverlayIcon decorated = new DecorationOverlayIcon(base,
UIIcons.OVR_SYMLINK, IDecoration.TOP_RIGHT);
@@ -114,7 +143,9 @@ public class StagingViewLabelProvider extends LabelProvider {
}
StagingEntry c = (StagingEntry) element;
- return getEditorImage(c);
+ DecorationResult decoration = new DecorationResult();
+ decorationHelper.decorate(decoration, c);
+ return getDecoratedImage(getEditorImage(c), decoration.getOverlay());
}
@Override
@@ -131,17 +162,35 @@ public class StagingViewLabelProvider extends LabelProvider {
return ""; //$NON-NLS-1$
}
+ DecorationResult decoration = new DecorationResult();
+ decorationHelper.decorate(decoration, stagingEntry);
+ String prefix = decoration.getPrefix();
+ String suffix = decoration.getSuffix();
+ StringBuilder label = new StringBuilder();
+ if (prefix != null) {
+ label.append(prefix);
+ }
if (stagingView.getPresentation() == Presentation.LIST) {
if (fileNameMode) {
IPath parsed = Path.fromOSString(stagingEntry.getPath());
if (parsed.segmentCount() > 1) {
- return parsed.lastSegment() + " - " //$NON-NLS-1$
- + parsed.removeLastSegments(1).toString();
+ label.append(parsed.lastSegment());
+ if (suffix != null) {
+ label.append(suffix);
+ }
+ label.append(" - ") //$NON-NLS-1$
+ .append(parsed.removeLastSegments(1).toString());
+ return label.toString();
}
}
- return stagingEntry.getPath();
+ label.append(stagingEntry.getPath());
+ } else {
+ label.append(stagingEntry.getName());
+ }
+ if (suffix != null) {
+ label.append(suffix);
}
- return stagingEntry.getName();
+ return label.toString();
}
@Nullable

Back to the top