1 /*******************************************************************************
2 * Copyright (C) 2012, Robin Stocker <robin@nibor.org>
3 * Copyright (C) 2016, Thomas Wolf <thomas.wolf@paranor.ch>
5 * All rights reserved. This program and the accompanying materials
6 * are made available under the terms of the Eclipse Public License 2.0
7 * which accompanies this distribution, and is available at
8 * https://www.eclipse.org/legal/epl-2.0/
10 * SPDX-License-Identifier: EPL-2.0
11 *******************************************************************************/
12 package org
.eclipse
.egit
.ui
.internal
.decorators
;
15 import java
.util
.ArrayList
;
16 import java
.util
.HashSet
;
17 import java
.util
.List
;
20 import org
.eclipse
.core
.resources
.IMarker
;
21 import org
.eclipse
.core
.resources
.IMarkerDelta
;
22 import org
.eclipse
.core
.resources
.IResource
;
23 import org
.eclipse
.core
.resources
.IResourceChangeEvent
;
24 import org
.eclipse
.core
.resources
.IResourceChangeListener
;
25 import org
.eclipse
.core
.resources
.ResourcesPlugin
;
26 import org
.eclipse
.core
.runtime
.IPath
;
27 import org
.eclipse
.core
.runtime
.Path
;
28 import org
.eclipse
.egit
.core
.AdapterUtils
;
29 import org
.eclipse
.egit
.core
.project
.RepositoryMapping
;
30 import org
.eclipse
.jface
.resource
.ImageDescriptor
;
31 import org
.eclipse
.jface
.resource
.JFaceResources
;
32 import org
.eclipse
.jface
.resource
.LocalResourceManager
;
33 import org
.eclipse
.jface
.resource
.ResourceManager
;
34 import org
.eclipse
.jface
.viewers
.BaseLabelProvider
;
35 import org
.eclipse
.jface
.viewers
.DecorationOverlayIcon
;
36 import org
.eclipse
.jface
.viewers
.IDecoration
;
37 import org
.eclipse
.jface
.viewers
.ILabelDecorator
;
38 import org
.eclipse
.jface
.viewers
.IStructuredContentProvider
;
39 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
40 import org
.eclipse
.jface
.viewers
.LabelProviderChangedEvent
;
41 import org
.eclipse
.jface
.viewers
.StructuredViewer
;
42 import org
.eclipse
.swt
.graphics
.Image
;
43 import org
.eclipse
.swt
.widgets
.Display
;
44 import org
.eclipse
.team
.ui
.ISharedImages
;
45 import org
.eclipse
.team
.ui
.TeamImages
;
48 * Label decorator for warning/error problem markers (used in Staging View and
51 * Users must make the decoratable element implement {@link IProblemDecoratable}.
53 public class ProblemLabelDecorator
extends BaseLabelProvider
implements
54 ILabelDecorator
, IResourceChangeListener
{
56 private final StructuredViewer viewer
;
58 private final ResourceManager resourceManager
= new LocalResourceManager(
59 JFaceResources
.getResources());
63 * the viewer to use for label updates because of changed
64 * resources, or null for none
66 public ProblemLabelDecorator(StructuredViewer viewer
) {
68 if (this.viewer
!= null)
69 ResourcesPlugin
.getWorkspace().addResourceChangeListener(this);
73 public void dispose() {
75 resourceManager
.dispose();
76 if (this.viewer
!= null)
77 ResourcesPlugin
.getWorkspace().removeResourceChangeListener(this);
81 public Image
decorateImage(Image image
, Object element
) {
82 IProblemDecoratable decoratable
= getProblemDecoratable(element
);
83 if (decoratable
!= null) {
84 int problemSeverity
= decoratable
.getProblemSeverity();
85 if (problemSeverity
== IMarker
.SEVERITY_ERROR
)
86 return getDecoratedImage(image
, ISharedImages
.IMG_ERROR_OVR
);
87 else if (problemSeverity
== IMarker
.SEVERITY_WARNING
)
88 return getDecoratedImage(image
, ISharedImages
.IMG_WARNING_OVR
);
94 public String
decorateText(String text
, Object element
) {
99 private IProblemDecoratable
getProblemDecoratable(Object element
) {
100 if (element
instanceof IProblemDecoratable
)
101 return (IProblemDecoratable
) element
;
106 private Image
getDecoratedImage(Image base
, String teamImageId
) {
107 ImageDescriptor overlay
= TeamImages
.getImageDescriptor(teamImageId
);
108 DecorationOverlayIcon decorated
= new DecorationOverlayIcon(base
,
109 overlay
, IDecoration
.BOTTOM_LEFT
);
110 return (Image
) this.resourceManager
.get(decorated
);
114 public void resourceChanged(IResourceChangeEvent event
) {
115 Set
<IPath
> paths
= new HashSet
<>();
117 IMarkerDelta
[] markerDeltas
= event
.findMarkerDeltas(IMarker
.PROBLEM
,
119 for (IMarkerDelta delta
: markerDeltas
) {
120 IResource resource
= delta
.getResource();
121 if (resource
== null) {
124 RepositoryMapping mapping
= RepositoryMapping
.getMapping(resource
);
125 if (mapping
== null || mapping
.getRepository().isBare()) {
128 IPath path
= resource
.getLocation();
133 File workTree
= mapping
.getWorkTree();
134 if (workTree
== null) {
137 int n
= new Path(workTree
.getAbsolutePath()).segmentCount();
138 for (int i
= path
.segmentCount(); i
> n
; i
--) {
140 path
= path
.removeLastSegments(1);
144 if (!paths
.isEmpty()) {
149 private void updateLabels(Set
<IPath
> changedPaths
) {
150 List
<Object
> elements
= getAffectedElements(changedPaths
);
151 if (!elements
.isEmpty()) {
152 final Object
[] updateElements
= elements
.toArray(new Object
[elements
.size()]);
153 Display display
= viewer
.getControl().getDisplay();
154 display
.asyncExec(new Runnable() {
157 fireLabelProviderChanged(new LabelProviderChangedEvent(
158 ProblemLabelDecorator
.this, updateElements
));
164 private List
<Object
> getAffectedElements(Set
<IPath
> paths
) {
165 List
<Object
> result
= new ArrayList
<>();
166 if (viewer
.getContentProvider() instanceof IStructuredContentProvider
) {
167 IStructuredContentProvider contentProvider
= (IStructuredContentProvider
) viewer
.getContentProvider();
168 getAffectedElements(paths
, contentProvider
.getElements(null),
169 contentProvider
, result
);
174 private void getAffectedElements(Set
<IPath
> paths
, Object
[] elements
,
175 IStructuredContentProvider contentProvider
, List
<Object
> result
) {
176 for (Object element
: elements
) {
177 IPath path
= AdapterUtils
.adapt(element
, IPath
.class);
179 IResource resource
= AdapterUtils
.adapt(element
,
181 if (resource
!= null) {
182 path
= resource
.getLocation();
185 if (path
!= null && paths
.contains(path
)) {
187 if (contentProvider
instanceof ITreeContentProvider
) {
188 getAffectedElements(paths
,
189 ((ITreeContentProvider
) contentProvider
)
190 .getChildren(element
),
191 contentProvider
, result
);