Organized imports
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / viewsupport / ResourceToItemsMapper.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.ui.viewsupport;
12
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Stack;
17
18 import net.sourceforge.phpdt.core.ICompilationUnit;
19 import net.sourceforge.phpdt.core.IJavaElement;
20
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;
28
29 /**
30  * Helper class for updating error markers and other decorators that work on resources.
31  * Items are mapped to their element's underlying resource.
32  * Method <code>resourceChanged</code> updates all items that are affected from the changed
33  * elements.
34  */
35 public class ResourceToItemsMapper {
36
37         private static final int NUMBER_LIST_REUSE= 10;
38
39         // map from resource to item
40         private HashMap fResourceToItem;
41         private Stack fReuseLists;
42         
43         private ContentViewer fContentViewer;
44
45         public ResourceToItemsMapper(ContentViewer viewer) {
46                 fResourceToItem= new HashMap();
47                 fReuseLists= new Stack();
48                 
49                 fContentViewer= viewer;
50         }
51
52         /**
53          * Must be called from the UI thread.
54          */
55         public void resourceChanged(IResource changedResource) {
56                 Object obj= fResourceToItem.get(changedResource);
57                 if (obj == null) {
58                         // not mapped
59                 } else if (obj instanceof Item) {
60                         updateItem((Item) obj);
61                 } else { // List of Items
62                         List list= (List) obj;
63                         for (int k= 0; k < list.size(); k++) {
64                                 updateItem((Item) list.get(k));
65                         }
66                 }
67         }
68                 
69         private void updateItem(Item item) {
70                 if (!item.isDisposed()) { // defensive code
71                         ILabelProvider lprovider= (ILabelProvider) fContentViewer.getLabelProvider();
72                         
73                         Object data= item.getData();
74                         
75                         // If it is an IItemLabelProvider than short circuit: patch Tod (bug 55012)
76                         if (lprovider instanceof IViewerLabelProvider) {
77                                 IViewerLabelProvider provider= (IViewerLabelProvider) lprovider;
78                                 
79                                 ViewerLabel updateLabel= new ViewerLabel(item.getText(), item.getImage());
80                                 provider.updateLabel(updateLabel, data);
81                                 
82                                 if (updateLabel.hasNewImage()) {
83                                         item.setImage(updateLabel.getImage());
84                                 }
85                                 if (updateLabel.hasNewText()) {
86                                         item.setText(updateLabel.getText());
87                                 }
88                         } else {
89                                 Image oldImage= item.getImage();
90                                 Image image= lprovider.getImage(data);
91                                 if (image != null && !image.equals(oldImage)) {
92                                         item.setImage(image);
93                                 }
94                                 String oldText= item.getText();
95                                 String text= lprovider.getText(data);
96                                 if (text != null && !text.equals(oldText)) {
97                                         item.setText(text);
98                                 }
99                         }
100                 }
101         }
102
103         /**
104          * Adds a new item to the map.
105          * @param element Element to map
106          * @param item The item used for the element
107          */
108         public void addToMap(Object element, Item item) {
109                 IResource resource= getCorrespondingResource(element);
110                 if (resource != null) {
111                         Object existingMapping= fResourceToItem.get(resource);
112                         if (existingMapping == null) {
113                                 fResourceToItem.put(resource, item);
114                         } else if (existingMapping instanceof Item) {
115                                 if (existingMapping != item) {
116                                         List list= getNewList();
117                                         list.add(existingMapping);
118                                         list.add(item);
119                                         fResourceToItem.put(resource, list);
120                                 }
121                         } else { // List                        
122                                 List list= (List) existingMapping;
123                                 if (!list.contains(item)) {
124                                         list.add(item);
125                                 }
126                         }
127                 }
128         }
129
130         /**
131          * Removes an element from the map.
132          */     
133         public void removeFromMap(Object element, Item item) {
134                 IResource resource= getCorrespondingResource(element);
135                 if (resource != null) {
136                         Object existingMapping= fResourceToItem.get(resource);
137                         if (existingMapping == null) {
138                                 return;
139                         } else if (existingMapping instanceof Item) {
140                                 fResourceToItem.remove(resource);
141                         } else { // List
142                                 List list= (List) existingMapping;
143                                 list.remove(item);
144                                 if (list.isEmpty()) {
145                                         fResourceToItem.remove(list);
146                                         releaseList(list);
147                                 }
148                         }
149                 }
150         }
151         
152         private List getNewList() {
153                 if (!fReuseLists.isEmpty()) {
154                         return (List) fReuseLists.pop();
155                 }
156                 return new ArrayList(2);
157         }
158         
159         private void releaseList(List list) {
160                 if (fReuseLists.size() < NUMBER_LIST_REUSE) {
161                         fReuseLists.push(list);
162                 }
163         }
164         
165         /**
166          * Clears the map.
167          */
168         public void clearMap() {
169                 fResourceToItem.clear();
170         }
171         
172         /**
173          * Tests if the map is empty
174          */
175         public boolean isEmpty() {
176                 return fResourceToItem.isEmpty();
177         }       
178         
179         /**
180          * Method that decides which elements can have error markers
181          * Returns null if an element can not have error markers.
182          */     
183         private static IResource getCorrespondingResource(Object element) {
184                 if (element instanceof IJavaElement) {
185                         IJavaElement elem= (IJavaElement) element;
186                         if (!elem.isReadOnly()) { // only modifieable elements can get error ticks
187                                 IResource res= elem.getResource();
188                                 if (res == null) {
189                                         ICompilationUnit cu= (ICompilationUnit) elem.getAncestor(IJavaElement.COMPILATION_UNIT);
190                                         if (cu != null) {
191                                                 // elements in compilation units are mapped to the underlying resource of the original cu
192                                                 res= cu.getResource();
193                                         }
194                                 }
195                                 return res; 
196                         }
197                         return null;
198                 } else if (element instanceof IResource) {
199                         return (IResource) element;
200                 }
201                 return null;
202         }
203         
204 }