1 /*******************************************************************************
 
   2  * Copyright (c) 2000, 2004 IBM Corporation and others.
 
   3  * All rights reserved. This program and the accompanying materials 
 
   4  * are made available under the terms of the Common Public License v1.0
 
   5  * which accompanies this distribution, and is available at
 
   6  * http://www.eclipse.org/legal/cpl-v10.html
 
   9  *     IBM Corporation - initial API and implementation
 
  10  *******************************************************************************/
 
  11 package net.sourceforge.phpdt.internal.ui.viewsupport;
 
  13 import java.util.ArrayList;
 
  14 import java.util.HashMap;
 
  15 import java.util.List;
 
  16 import java.util.Stack;
 
  18 import net.sourceforge.phpdt.core.ICompilationUnit;
 
  19 import net.sourceforge.phpdt.core.IJavaElement;
 
  21 import org.eclipse.core.resources.IResource;
 
  22 import org.eclipse.jface.viewers.ContentViewer;
 
  23 import org.eclipse.jface.viewers.ILabelProvider;
 
  24 import org.eclipse.jface.viewers.IViewerLabelProvider;
 
  25 import org.eclipse.jface.viewers.ViewerLabel;
 
  26 import org.eclipse.swt.graphics.Image;
 
  27 import org.eclipse.swt.widgets.Item;
 
  30  * Helper class for updating error markers and other decorators that work on
 
  31  * resources. Items are mapped to their element's underlying resource. Method
 
  32  * <code>resourceChanged</code> updates all items that are affected from the
 
  35 public class ResourceToItemsMapper {
 
  37         private static final int NUMBER_LIST_REUSE = 10;
 
  39         // map from resource to item
 
  40         private HashMap fResourceToItem;
 
  42         private Stack fReuseLists;
 
  44         private ContentViewer fContentViewer;
 
  46         public ResourceToItemsMapper(ContentViewer viewer) {
 
  47                 fResourceToItem = new HashMap();
 
  48                 fReuseLists = new Stack();
 
  50                 fContentViewer = viewer;
 
  54          * Must be called from the UI thread.
 
  56         public void resourceChanged(IResource changedResource) {
 
  57                 Object obj = fResourceToItem.get(changedResource);
 
  60                 } else if (obj instanceof Item) {
 
  61                         updateItem((Item) obj);
 
  62                 } else { // List of Items
 
  63                         List list = (List) obj;
 
  64                         for (int k = 0; k < list.size(); k++) {
 
  65                                 updateItem((Item) list.get(k));
 
  70         private void updateItem(Item item) {
 
  71                 if (!item.isDisposed()) { // defensive code
 
  72                         ILabelProvider lprovider = (ILabelProvider) fContentViewer
 
  75                         Object data = item.getData();
 
  77                         // If it is an IItemLabelProvider than short circuit: patch Tod (bug
 
  79                         if (lprovider instanceof IViewerLabelProvider) {
 
  80                                 IViewerLabelProvider provider = (IViewerLabelProvider) lprovider;
 
  82                                 ViewerLabel updateLabel = new ViewerLabel(item.getText(), item
 
  84                                 provider.updateLabel(updateLabel, data);
 
  86                                 if (updateLabel.hasNewImage()) {
 
  87                                         item.setImage(updateLabel.getImage());
 
  89                                 if (updateLabel.hasNewText()) {
 
  90                                         item.setText(updateLabel.getText());
 
  93                                 Image oldImage = item.getImage();
 
  94                                 Image image = lprovider.getImage(data);
 
  95                                 if (image != null && !image.equals(oldImage)) {
 
  98                                 String oldText = item.getText();
 
  99                                 String text = lprovider.getText(data);
 
 100                                 if (text != null && !text.equals(oldText)) {
 
 108          * Adds a new item to the map.
 
 113          *            The item used for the element
 
 115         public void addToMap(Object element, Item item) {
 
 116                 IResource resource = getCorrespondingResource(element);
 
 117                 if (resource != null) {
 
 118                         Object existingMapping = fResourceToItem.get(resource);
 
 119                         if (existingMapping == null) {
 
 120                                 fResourceToItem.put(resource, item);
 
 121                         } else if (existingMapping instanceof Item) {
 
 122                                 if (existingMapping != item) {
 
 123                                         List list = getNewList();
 
 124                                         list.add(existingMapping);
 
 126                                         fResourceToItem.put(resource, list);
 
 129                                 List list = (List) existingMapping;
 
 130                                 if (!list.contains(item)) {
 
 138          * Removes an element from the map.
 
 140         public void removeFromMap(Object element, Item item) {
 
 141                 IResource resource = getCorrespondingResource(element);
 
 142                 if (resource != null) {
 
 143                         Object existingMapping = fResourceToItem.get(resource);
 
 144                         if (existingMapping == null) {
 
 146                         } else if (existingMapping instanceof Item) {
 
 147                                 fResourceToItem.remove(resource);
 
 149                                 List list = (List) existingMapping;
 
 151                                 if (list.isEmpty()) {
 
 152                                         fResourceToItem.remove(list);
 
 159         private List getNewList() {
 
 160                 if (!fReuseLists.isEmpty()) {
 
 161                         return (List) fReuseLists.pop();
 
 163                 return new ArrayList(2);
 
 166         private void releaseList(List list) {
 
 167                 if (fReuseLists.size() < NUMBER_LIST_REUSE) {
 
 168                         fReuseLists.push(list);
 
 175         public void clearMap() {
 
 176                 fResourceToItem.clear();
 
 180          * Tests if the map is empty
 
 182         public boolean isEmpty() {
 
 183                 return fResourceToItem.isEmpty();
 
 187          * Method that decides which elements can have error markers Returns null if
 
 188          * an element can not have error markers.
 
 190         private static IResource getCorrespondingResource(Object element) {
 
 191                 if (element instanceof IJavaElement) {
 
 192                         IJavaElement elem = (IJavaElement) element;
 
 193                         if (!elem.isReadOnly()) { // only modifieable elements can get
 
 195                                 IResource res = elem.getResource();
 
 197                                         ICompilationUnit cu = (ICompilationUnit) elem
 
 198                                                         .getAncestor(IJavaElement.COMPILATION_UNIT);
 
 200                                                 // elements in compilation units are mapped to the
 
 201                                                 // underlying resource of the original cu
 
 202                                                 res = cu.getResource();
 
 208                 } else if (element instanceof IResource) {
 
 209                         return (IResource) element;