/******************************************************************************* * Copyright (c) 2000, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package net.sourceforge.phpdt.internal.ui.viewsupport; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Stack; import net.sourceforge.phpdt.core.ICompilationUnit; import net.sourceforge.phpdt.core.IJavaElement; import org.eclipse.core.resources.IResource; import org.eclipse.jface.viewers.ContentViewer; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.IViewerLabelProvider; import org.eclipse.jface.viewers.ViewerLabel; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Item; /** * Helper class for updating error markers and other decorators that work on * resources. Items are mapped to their element's underlying resource. Method * resourceChanged updates all items that are affected from the * changed elements. */ public class ResourceToItemsMapper { private static final int NUMBER_LIST_REUSE = 10; // map from resource to item private HashMap fResourceToItem; private Stack fReuseLists; private ContentViewer fContentViewer; public ResourceToItemsMapper(ContentViewer viewer) { fResourceToItem = new HashMap(); fReuseLists = new Stack(); fContentViewer = viewer; } /** * Must be called from the UI thread. */ public void resourceChanged(IResource changedResource) { Object obj = fResourceToItem.get(changedResource); if (obj == null) { // not mapped } else if (obj instanceof Item) { updateItem((Item) obj); } else { // List of Items List list = (List) obj; for (int k = 0; k < list.size(); k++) { updateItem((Item) list.get(k)); } } } private void updateItem(Item item) { if (!item.isDisposed()) { // defensive code ILabelProvider lprovider = (ILabelProvider) fContentViewer .getLabelProvider(); Object data = item.getData(); // If it is an IItemLabelProvider than short circuit: patch Tod (bug // 55012) if (lprovider instanceof IViewerLabelProvider) { IViewerLabelProvider provider = (IViewerLabelProvider) lprovider; ViewerLabel updateLabel = new ViewerLabel(item.getText(), item .getImage()); provider.updateLabel(updateLabel, data); if (updateLabel.hasNewImage()) { item.setImage(updateLabel.getImage()); } if (updateLabel.hasNewText()) { item.setText(updateLabel.getText()); } } else { Image oldImage = item.getImage(); Image image = lprovider.getImage(data); if (image != null && !image.equals(oldImage)) { item.setImage(image); } String oldText = item.getText(); String text = lprovider.getText(data); if (text != null && !text.equals(oldText)) { item.setText(text); } } } } /** * Adds a new item to the map. * * @param element * Element to map * @param item * The item used for the element */ public void addToMap(Object element, Item item) { IResource resource = getCorrespondingResource(element); if (resource != null) { Object existingMapping = fResourceToItem.get(resource); if (existingMapping == null) { fResourceToItem.put(resource, item); } else if (existingMapping instanceof Item) { if (existingMapping != item) { List list = getNewList(); list.add(existingMapping); list.add(item); fResourceToItem.put(resource, list); } } else { // List List list = (List) existingMapping; if (!list.contains(item)) { list.add(item); } } } } /** * Removes an element from the map. */ public void removeFromMap(Object element, Item item) { IResource resource = getCorrespondingResource(element); if (resource != null) { Object existingMapping = fResourceToItem.get(resource); if (existingMapping == null) { return; } else if (existingMapping instanceof Item) { fResourceToItem.remove(resource); } else { // List List list = (List) existingMapping; list.remove(item); if (list.isEmpty()) { fResourceToItem.remove(list); releaseList(list); } } } } private List getNewList() { if (!fReuseLists.isEmpty()) { return (List) fReuseLists.pop(); } return new ArrayList(2); } private void releaseList(List list) { if (fReuseLists.size() < NUMBER_LIST_REUSE) { fReuseLists.push(list); } } /** * Clears the map. */ public void clearMap() { fResourceToItem.clear(); } /** * Tests if the map is empty */ public boolean isEmpty() { return fResourceToItem.isEmpty(); } /** * Method that decides which elements can have error markers Returns null if * an element can not have error markers. */ private static IResource getCorrespondingResource(Object element) { if (element instanceof IJavaElement) { IJavaElement elem = (IJavaElement) element; if (!elem.isReadOnly()) { // only modifieable elements can get // error ticks IResource res = elem.getResource(); if (res == null) { ICompilationUnit cu = (ICompilationUnit) elem .getAncestor(IJavaElement.COMPILATION_UNIT); if (cu != null) { // elements in compilation units are mapped to the // underlying resource of the original cu res = cu.getResource(); } } return res; } return null; } else if (element instanceof IResource) { return (IResource) element; } return null; } }