org.overture.ide.ui.VdmProblemsLabelDecorator.java Source code

Java tutorial

Introduction

Here is the source code for org.overture.ide.ui.VdmProblemsLabelDecorator.java

Source

/*
 * #%~
 * org.overture.ide.ui
 * %%
 * Copyright (C) 2008 - 2014 Overture
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/gpl-3.0.html>.
 * #~%
 */
package org.overture.ide.ui;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IDecoration;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ILightweightLabelDecorator;
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.overture.ide.core.IVdmElement;
import org.overture.ide.ui.internal.viewsupport.IProblemChangedListener;
import org.overture.ide.ui.internal.viewsupport.ImageDescriptorRegistry;
import org.overture.ide.ui.internal.viewsupport.ImageImageDescriptor;
import org.overture.ide.ui.internal.viewsupport.VdmElementImageDescriptor;

/**
 * LabelDecorator that decorates an element's image with error and warning overlays that represent the
 * severity of markers attached to the element's underlying resource. To see a problem decoration for a
 * marker, the marker needs to be a subtype of <code>IMarker.PROBLEM</code>.
 * <p>
 * <b>Important</b>: Although this decorator implements ILightweightLabelDecorator, do not contribute this
 * class as a decorator to the <code>org.eclipse.ui.decorators</code> extension. Only use this class in your
 * own views and label providers.
 * 
 * @since 2.0
 */
public class VdmProblemsLabelDecorator implements ILabelDecorator, ILightweightLabelDecorator {

    /**
     * This is a special <code>LabelProviderChangedEvent</code> carrying additional information whether the
     * event origins from a maker change.
     * <p>
     * <code>ProblemsLabelChangedEvent</code>s are only generated by <code>
     * ProblemsLabelDecorator</code>s.
     * </p>
     */
    public static class ProblemsLabelChangedEvent extends LabelProviderChangedEvent {

        private static final long serialVersionUID = 1L;

        private boolean fMarkerChange;

        /**
         * @param eventSource
         *            the base label provider
         * @param changedResource
         *            the changed resources
         * @param isMarkerChange
         *            <code>true</code> if the change is a marker change; otherwise <code>false</code>
         */
        public ProblemsLabelChangedEvent(IBaseLabelProvider eventSource, IResource[] changedResource,
                boolean isMarkerChange) {
            super(eventSource, changedResource);
            fMarkerChange = isMarkerChange;
        }

        /**
         * Returns whether this event origins from marker changes. If <code>false</code> an annotation model
         * change is the origin. In this case viewers not displaying working copies can ignore these events.
         * 
         * @return if this event origins from a marker change.
         */
        public boolean isMarkerChange() {
            return fMarkerChange;
        }

    }

    private static final int ERRORTICK_WARNING = VdmElementImageDescriptor.WARNING;
    private static final int ERRORTICK_ERROR = VdmElementImageDescriptor.ERROR;

    private ImageDescriptorRegistry fRegistry;
    private boolean fUseNewRegistry = false;
    private IProblemChangedListener fProblemChangedListener;

    private ListenerList fListeners;

    // private ISourceRange fCachedRange;

    /**
     * Creates a new <code>ProblemsLabelDecorator</code>.
     */
    public VdmProblemsLabelDecorator() {
        this(null);
        fUseNewRegistry = true;
    }

    /**
     * Note: This constructor is for internal use only. Clients should not call this constructor.
     * 
     * @param registry
     *            The registry to use or <code>null</code> to use the Java plugin's image registry
     * @noreference This constructor is not intended to be referenced by clients.
     */
    public VdmProblemsLabelDecorator(ImageDescriptorRegistry registry) {
        fRegistry = registry;
        fProblemChangedListener = null;
    }

    private ImageDescriptorRegistry getRegistry() {
        if (fRegistry == null) {
            fRegistry = fUseNewRegistry ? new ImageDescriptorRegistry() : VdmUIPlugin.getImageDescriptorRegistry();
        }
        return fRegistry;
    }

    /*
     * (non-Javadoc)
     * 
     * @see ILabelDecorator#decorateText(String, Object)
     */
    public String decorateText(String text, Object element) {
        return text;
    }

    /*
     * (non-Javadoc)
     * 
     * @see ILabelDecorator#decorateImage(Image, Object)
     */
    public Image decorateImage(Image image, Object obj) {
        if (image == null)
            return null;

        int adornmentFlags = computeAdornmentFlags(obj);
        if (adornmentFlags != 0) {
            ImageDescriptor baseImage = new ImageImageDescriptor(image);
            Rectangle bounds = image.getBounds();
            return getRegistry()
                    .get(new VdmElementImageDescriptor(baseImage, 0, new Point(bounds.width, bounds.height)));
        }
        return image;
    }

    /**
     * Computes the adornment flags for the given element.
     * 
     * @param obj
     *            the element to compute the flags for
     * 
     * @return the adornment flags
     */
    protected int computeAdornmentFlags(Object obj) {
        //      try
        //      {
        if (obj instanceof IVdmElement) {
            IVdmElement element = (IVdmElement) obj;
            int type = element.getElementType();
            switch (type) {
            case IVdmElement.VDM_MODEL:
            case IVdmElement.VDM_PROJECT:
                // case IVdmElement.PACKAGE_FRAGMENT_ROOT:
                // return getErrorTicksFromMarkers(element.getResource(), IResource.DEPTH_INFINITE, null);
                // case IVdmElement.PACKAGE_FRAGMENT:
            case IVdmElement.COMPILATION_UNIT:
                // case IVdmElement.CLASS_FILE:
                // return getErrorTicksFromMarkers(element.getResource(), IResource.DEPTH_ONE, null);
                // case IVdmElement.PACKAGE_DECLARATION:
                // case IVdmElement.IMPORT_DECLARATION:
                // case IVdmElement.IMPORT_CONTAINER:
            case IVdmElement.TYPE:
            case IVdmElement.INITIALIZER:
            case IVdmElement.METHOD:
            case IVdmElement.FIELD:
                // case IVdmElement.LOCAL_VARIABLE:
                // ICompilationUnit cu= (ICompilationUnit)
                // element.getAncestor(IVdmElement.COMPILATION_UNIT);
                // if (cu != null) {
                // ISourceReference ref= (type == IVdmElement.COMPILATION_UNIT) ? null :
                // (ISourceReference) element;
                // // The assumption is that only source elements in compilation unit can have markers
                // IAnnotationModel model= isInJavaAnnotationModel(cu);
                // int result= 0;
                // if (model != null) {
                // // open in Java editor: look at annotation model
                // result= getErrorTicksFromAnnotationModel(model, ref);
                // } else {
                // result= getErrorTicksFromMarkers(cu.getResource(), IResource.DEPTH_ONE, ref);
                // }
                // fCachedRange= null;
                // return result;
                // }
                break;
            default:
            }
        }
        //         else if (obj instanceof IResource)
        //         {
        //            return getErrorTicksFromMarkers((IResource) obj,
        //                  IResource.DEPTH_INFINITE,
        //                  null);
        //         }
        //      } catch (CoreException e)
        //      {
        //         if (e instanceof VdmModelException)
        //         {
        //            if (((VdmModelException) e).isDoesNotExist())
        //            {
        //               return 0;
        //            }
        //         }
        //         if (e.getStatus().getCode() == IResourceStatus.MARKER_NOT_FOUND)
        //         {
        //            return 0;
        //         }
        //
        //         VdmUIPlugin.log(e);
        //      }
        return 0;
    }

    //   private int getErrorTicksFromMarkers(IResource res, int depth,
    //         ISourceReference sourceElement) throws CoreException
    //   {
    //      if (res == null || !res.isAccessible())
    //      {
    //         return 0;
    //      }
    //      int severity = 0;
    //      if (sourceElement == null)
    //      {
    //         severity = res.findMaxProblemSeverity(IMarker.PROBLEM, true, depth);
    //      } else
    //      {
    //         IMarker[] markers = res.findMarkers(IMarker.PROBLEM, true, depth);
    //         if (markers != null && markers.length > 0)
    //         {
    //            for (int i = 0; i < markers.length
    //                  && (severity != IMarker.SEVERITY_ERROR); i++)
    //            {
    //               IMarker curr = markers[i];
    //               if (isMarkerInRange(curr, sourceElement))
    //               {
    //                  int val = curr.getAttribute(IMarker.SEVERITY, -1);
    //                  if (val == IMarker.SEVERITY_WARNING
    //                        || val == IMarker.SEVERITY_ERROR)
    //                  {
    //                     severity = val;
    //                  }
    //               }
    //            }
    //         }
    //      }
    //      if (severity == IMarker.SEVERITY_ERROR)
    //      {
    //         return ERRORTICK_ERROR;
    //      } else if (severity == IMarker.SEVERITY_WARNING)
    //      {
    //         return ERRORTICK_WARNING;
    //      }
    //      return 0;
    //   }
    //
    //   private boolean isMarkerInRange(IMarker marker,
    //         ISourceReference sourceElement) throws CoreException
    //   {
    //      if (marker.isSubtypeOf(IMarker.TEXT))
    //      {
    //         int pos = marker.getAttribute(IMarker.CHAR_START, -1);
    //         return isInside(pos, sourceElement);
    //      }
    //      return false;
    //   }

    // private IAnnotationModel isInJavaAnnotationModel(ICompilationUnit original) {
    // if (original.isWorkingCopy()) {
    // FileEditorInput editorInput= new FileEditorInput((IFile) original.getResource());
    // //return JavaPlugin.getDefault().getCompilationUnitDocumentProvider().getAnnotationModel(editorInput);
    // }
    // return null;
    // }

    //   private int getErrorTicksFromAnnotationModel(IAnnotationModel model,
    //         ISourceReference sourceElement) throws CoreException
    //   {
    //      int info = 0;
    //      Iterator iter = model.getAnnotationIterator();
    //      while ((info != ERRORTICK_ERROR) && iter.hasNext())
    //      {
    //         Annotation annot = (Annotation) iter.next();
    //         IMarker marker = isAnnotationInRange(model, annot, sourceElement);
    //         if (marker != null)
    //         {
    //            int priority = marker.getAttribute(IMarker.SEVERITY, -1);
    //            if (priority == IMarker.SEVERITY_WARNING)
    //            {
    //               info = ERRORTICK_WARNING;
    //            } else if (priority == IMarker.SEVERITY_ERROR)
    //            {
    //               info = ERRORTICK_ERROR;
    //            }
    //         }
    //      }
    //      return info;
    //   }
    //
    //   private IMarker isAnnotationInRange(IAnnotationModel model,
    //         Annotation annot, ISourceReference sourceElement)
    //         throws CoreException
    //   {
    //      if (annot instanceof MarkerAnnotation)
    //      {
    //         if (sourceElement == null
    //               || isInside(model.getPosition(annot), sourceElement))
    //         {
    //            IMarker marker = ((MarkerAnnotation) annot).getMarker();
    //            if (marker.exists() && marker.isSubtypeOf(IMarker.PROBLEM))
    //            {
    //               return marker;
    //            }
    //         }
    //      }
    //      return null;
    //   }
    //
    //   private boolean isInside(Position pos, ISourceReference sourceElement)
    //         throws CoreException
    //   {
    //      return pos != null && isInside(pos.getOffset(), sourceElement);
    //   }
    //
    //   /**
    //    * Tests if a position is inside the source range of an element.
    //    * 
    //    * @param pos
    //    *            Position to be tested.
    //    * @param sourceElement
    //    *            Source element (must be a IVdmElement)
    //    * @return boolean Return <code>true</code> if position is located inside the source element.
    //    * @throws CoreException
    //    *             Exception thrown if element range could not be accessed.
    //    * 
    //    * @since 2.1
    //    */
    //   protected boolean isInside(int pos, ISourceReference sourceElement)
    //         throws CoreException
    //   {
    //      if (fCachedRange == null)
    //      {
    //         fCachedRange = sourceElement.getSourceRange();
    //      }
    //      ISourceRange range = fCachedRange;
    //      if (range != null)
    //      {
    //         int rangeOffset = range.getOffset();
    //         return (rangeOffset <= pos && rangeOffset + range.getLength() > pos);
    //      }
    //      return false;
    //   }

    /*
     * (non-Javadoc)
     * 
     * @see IBaseLabelProvider#dispose()
     */
    public void dispose() {
        if (fProblemChangedListener != null) {
            VdmUIPlugin.getDefault().getProblemMarkerManager().removeListener(fProblemChangedListener);
            fProblemChangedListener = null;
        }
        if (fRegistry != null && fUseNewRegistry) {
            fRegistry.dispose();
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see IBaseLabelProvider#isLabelProperty(Object, String)
     */
    public boolean isLabelProperty(Object element, String property) {
        return true;
    }

    /*
     * (non-Javadoc)
     * 
     * @see IBaseLabelProvider#addListener(ILabelProviderListener)
     */
    public void addListener(ILabelProviderListener listener) {
        if (fListeners == null) {
            fListeners = new ListenerList();
        }
        fListeners.add(listener);
        if (fProblemChangedListener == null) {
            fProblemChangedListener = new IProblemChangedListener() {
                public void problemsChanged(IResource[] changedResources, boolean isMarkerChange) {
                    fireProblemsChanged(changedResources, isMarkerChange);
                }
            };
            VdmUIPlugin.getDefault().getProblemMarkerManager().addListener(fProblemChangedListener);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see IBaseLabelProvider#removeListener(ILabelProviderListener)
     */
    public void removeListener(ILabelProviderListener listener) {
        if (fListeners != null) {
            fListeners.remove(listener);
            if (fListeners.isEmpty() && fProblemChangedListener != null) {
                VdmUIPlugin.getDefault().getProblemMarkerManager().removeListener(fProblemChangedListener);
                fProblemChangedListener = null;
            }
        }
    }

    private void fireProblemsChanged(IResource[] changedResources, boolean isMarkerChange) {
        if (fListeners != null && !fListeners.isEmpty()) {
            LabelProviderChangedEvent event = new ProblemsLabelChangedEvent(this, changedResources, isMarkerChange);
            Object[] listeners = fListeners.getListeners();
            for (int i = 0; i < listeners.length; i++) {
                ((ILabelProviderListener) listeners[i]).labelProviderChanged(event);
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.viewers.ILightweightLabelDecorator#decorate(java.lang.Object,
     * org.eclipse.jface.viewers.IDecoration)
     */
    public void decorate(Object element, IDecoration decoration) {
        int adornmentFlags = computeAdornmentFlags(element);
        if (adornmentFlags == ERRORTICK_ERROR) {
            decoration.addOverlay(VdmPluginImages.DESC_OVR_ERROR);
        } else if (adornmentFlags == ERRORTICK_WARNING) {
            decoration.addOverlay(VdmPluginImages.DESC_OVR_WARNING);
        }
    }

}