/** * 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); } } }