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 org.eclipse.core.resources.IResource;
20 import org.eclipse.swt.graphics.Image;
21 import org.eclipse.swt.widgets.Item;
23 import org.eclipse.jface.viewers.ContentViewer;
24 import org.eclipse.jface.viewers.ILabelProvider;
25 import org.eclipse.jface.viewers.IViewerLabelProvider;
26 import org.eclipse.jface.viewers.ViewerLabel;
28 import net.sourceforge.phpdt.core.ICompilationUnit;
29 import net.sourceforge.phpdt.core.IJavaElement;
32 * Helper class for updating error markers and other decorators that work on resources.
33 * Items are mapped to their element's underlying resource.
34 * Method <code>resourceChanged</code> updates all items that are affected from the changed
37 public class ResourceToItemsMapper {
39 private static final int NUMBER_LIST_REUSE= 10;
41 // map from resource to item
42 private HashMap fResourceToItem;
43 private Stack fReuseLists;
45 private ContentViewer fContentViewer;
47 public ResourceToItemsMapper(ContentViewer viewer) {
48 fResourceToItem= new HashMap();
49 fReuseLists= new Stack();
51 fContentViewer= viewer;
55 * Must be called from the UI thread.
57 public void resourceChanged(IResource changedResource) {
58 Object obj= fResourceToItem.get(changedResource);
61 } else if (obj instanceof Item) {
62 updateItem((Item) obj);
63 } else { // List of Items
64 List list= (List) obj;
65 for (int k= 0; k < list.size(); k++) {
66 updateItem((Item) list.get(k));
71 private void updateItem(Item item) {
72 if (!item.isDisposed()) { // defensive code
73 ILabelProvider lprovider= (ILabelProvider) fContentViewer.getLabelProvider();
75 Object data= item.getData();
77 // If it is an IItemLabelProvider than short circuit: patch Tod (bug 55012)
78 if (lprovider instanceof IViewerLabelProvider) {
79 IViewerLabelProvider provider= (IViewerLabelProvider) lprovider;
81 ViewerLabel updateLabel= new ViewerLabel(item.getText(), item.getImage());
82 provider.updateLabel(updateLabel, data);
84 if (updateLabel.hasNewImage()) {
85 item.setImage(updateLabel.getImage());
87 if (updateLabel.hasNewText()) {
88 item.setText(updateLabel.getText());
91 Image oldImage= item.getImage();
92 Image image= lprovider.getImage(data);
93 if (image != null && !image.equals(oldImage)) {
96 String oldText= item.getText();
97 String text= lprovider.getText(data);
98 if (text != null && !text.equals(oldText)) {
106 * Adds a new item to the map.
107 * @param element Element to map
108 * @param item The item used for the element
110 public void addToMap(Object element, Item item) {
111 IResource resource= getCorrespondingResource(element);
112 if (resource != null) {
113 Object existingMapping= fResourceToItem.get(resource);
114 if (existingMapping == null) {
115 fResourceToItem.put(resource, item);
116 } else if (existingMapping instanceof Item) {
117 if (existingMapping != item) {
118 List list= getNewList();
119 list.add(existingMapping);
121 fResourceToItem.put(resource, list);
124 List list= (List) existingMapping;
125 if (!list.contains(item)) {
133 * Removes an element from the map.
135 public void removeFromMap(Object element, Item item) {
136 IResource resource= getCorrespondingResource(element);
137 if (resource != null) {
138 Object existingMapping= fResourceToItem.get(resource);
139 if (existingMapping == null) {
141 } else if (existingMapping instanceof Item) {
142 fResourceToItem.remove(resource);
144 List list= (List) existingMapping;
146 if (list.isEmpty()) {
147 fResourceToItem.remove(list);
154 private List getNewList() {
155 if (!fReuseLists.isEmpty()) {
156 return (List) fReuseLists.pop();
158 return new ArrayList(2);
161 private void releaseList(List list) {
162 if (fReuseLists.size() < NUMBER_LIST_REUSE) {
163 fReuseLists.push(list);
170 public void clearMap() {
171 fResourceToItem.clear();
175 * Tests if the map is empty
177 public boolean isEmpty() {
178 return fResourceToItem.isEmpty();
182 * Method that decides which elements can have error markers
183 * Returns null if an element can not have error markers.
185 private static IResource getCorrespondingResource(Object element) {
186 if (element instanceof IJavaElement) {
187 IJavaElement elem= (IJavaElement) element;
188 if (!elem.isReadOnly()) { // only modifieable elements can get error ticks
189 IResource res= elem.getResource();
191 ICompilationUnit cu= (ICompilationUnit) elem.getAncestor(IJavaElement.COMPILATION_UNIT);
193 // elements in compilation units are mapped to the underlying resource of the original cu
194 res= cu.getResource();
200 } else if (element instanceof IResource) {
201 return (IResource) element;