/**
* Copyright (c) 2013 committers of YAKINDU and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
* Contributors:
* committers of YAKINDU - initial API and implementation
*
*/
package org.yakindu.base.gmf.runtime.decorators;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.emf.workspace.util.WorkspaceSynchronizer;
import org.eclipse.gef.EditDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.editparts.AbstractConnectionEditPart;
import org.eclipse.gmf.runtime.common.ui.resources.FileChangeManager;
import org.eclipse.gmf.runtime.common.ui.resources.IFileObserver;
import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditDomain;
import org.eclipse.gmf.runtime.diagram.ui.services.decorator.AbstractDecorator;
import org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecorator;
import org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecoratorProvider;
import org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecoratorTarget;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PlatformUI;
/**
* Abstract base class for all GMF {@link IDecoratorProvider} that provide
* decoration based on {@link IMarker}s. Code initially copied form GMF tooling
* generated validation provider.
*
* @author andreas muelder - Initial contribution and API
*
*/
public abstract class AbstractMarkerBasedDecorationProvider extends AbstractDecoratorProvider
implements IDecoratorProvider {
private static MarkerObserver fileObserver;
protected static Map<String, List<IDecorator>> allDecorators = new HashMap<String, List<IDecorator>>();
protected abstract boolean shouldInstall(IEditorPart part);
protected abstract String getDecoratorKey();
protected abstract IDecorator createStatusDecorator(IDecoratorTarget decoratorTarget);
public void createDecorators(IDecoratorTarget decoratorTarget) {
EditPart editPart = (EditPart) decoratorTarget.getAdapter(EditPart.class);
if (editPart instanceof GraphicalEditPart || editPart instanceof AbstractConnectionEditPart) {
EditDomain ed = editPart.getViewer().getEditDomain();
if (!(ed instanceof DiagramEditDomain)) {
return;
}
if (shouldInstall(((DiagramEditDomain) ed).getEditorPart())) {
decoratorTarget.installDecorator(getDecoratorKey(), createStatusDecorator(decoratorTarget));
}
}
}
protected static void refreshDecorators(String viewId, Diagram diagram) {
final List<IDecorator> decorators = viewId != null ? (List<IDecorator>) allDecorators.get(viewId) : null;
if (decorators == null || decorators.isEmpty() || diagram == null) {
return;
}
PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
public void run() {
for (Iterator<IDecorator> it = decorators.iterator(); it.hasNext();) {
IDecorator decorator = it.next();
decorator.refresh();
}
}
});
}
public abstract static class StatusDecorator extends AbstractDecorator {
private String viewId;
protected abstract String getMarkerType();
protected abstract void createDecorators(View view, List<IMarker> markers);
public StatusDecorator(IDecoratorTarget decoratorTarget) {
super(decoratorTarget);
try {
final View view = (View) getDecoratorTarget().getAdapter(View.class);
TransactionUtil.getEditingDomain(view).runExclusive(new Runnable() {
public void run() {
StatusDecorator.this.viewId = view != null ? ViewUtil.getIdStr(view) : null;
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
public void refresh() {
removeDecoration();
View view = (View) getDecoratorTarget().getAdapter(View.class);
if (view == null || view.eResource() == null) {
return;
}
EditPart editPart = (EditPart) getDecoratorTarget().getAdapter(EditPart.class);
if (editPart == null || editPart.getViewer() == null) {
return;
}
IResource resource = WorkspaceSynchronizer.getFile(view.eResource());
if (resource == null || !resource.exists()) {
return;
}
List<IMarker> markers = new ArrayList<IMarker>();
try {
markers.addAll(Arrays.asList(resource.findMarkers(getMarkerType(), true, IResource.DEPTH_INFINITE)));
} catch (CoreException e) {
e.printStackTrace();
}
if (markers == null || markers.size() == 0) {
return;
}
createDecorators(view, markers);
}
public void activate() {
if (viewId == null) {
return;
}
// add self to global decorators registry
List<IDecorator> list = allDecorators.get(viewId);
if (list == null) {
list = new ArrayList<IDecorator>(2);
list.add(this);
allDecorators.put(viewId, list);
} else if (!list.contains(this)) {
list.add(this);
}
// start listening to changes in resources
View view = (View) getDecoratorTarget().getAdapter(View.class);
if (view == null) {
return;
}
Diagram diagramView = view.getDiagram();
if (diagramView == null) {
return;
}
if (fileObserver == null) {
FileChangeManager.getInstance().addFileObserver(fileObserver = new MarkerObserver(diagramView));
}
}
public void deactivate() {
if (viewId == null) {
return;
}
// remove self from global decorators registry
List<IDecorator> list = allDecorators.get(viewId);
if (list != null) {
list.remove(this);
if (list.isEmpty()) {
allDecorators.remove(viewId);
}
}
// stop listening to changes in resources if there are no more
// decorators
if (fileObserver != null && allDecorators.isEmpty()) {
FileChangeManager.getInstance().removeFileObserver(fileObserver);
fileObserver = null;
}
super.deactivate();
}
}
protected static class MarkerObserver implements IFileObserver {
private final Diagram diagram;
private MarkerObserver(Diagram diagram) {
this.diagram = diagram;
}
public void handleFileRenamed(IFile oldFile, IFile file) {
}
public void handleFileMoved(IFile oldFile, IFile file) {
}
public void handleFileDeleted(IFile file) {
}
public void handleFileChanged(IFile file) {
}
public void handleMarkerAdded(IMarker marker) {
if (marker.getAttribute(org.eclipse.gmf.runtime.common.ui.resources.IMarker.ELEMENT_ID, null) != null) {
handleMarkerChanged(marker);
}
}
public void handleMarkerDeleted(IMarker marker, @SuppressWarnings("rawtypes") Map attributes) {
if (attributes == null)
return;
String viewId = (String) attributes.get(org.eclipse.gmf.runtime.common.ui.resources.IMarker.ELEMENT_ID);
if (viewId == null)
return;
refreshDecorators(viewId, diagram);
}
public void handleMarkerChanged(IMarker marker) {
String viewId = marker.getAttribute(org.eclipse.gmf.runtime.common.ui.resources.IMarker.ELEMENT_ID, "");
refreshDecorators(viewId, diagram);
}
}
}