]>
Commit | Line | Data |
---|---|---|
1b2798f6 EK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2000, 2011 IBM Corporation and others. | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * IBM Corporation - initial API and implementation | |
10 | *******************************************************************************/ | |
11 | package org.eclipse.jdt.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 org.eclipse.swt.widgets.Item; | |
19 | import org.eclipse.swt.widgets.Widget; | |
20 | ||
21 | import org.eclipse.core.resources.IResource; | |
22 | ||
23 | import org.eclipse.jdt.core.ICompilationUnit; | |
24 | import org.eclipse.jdt.core.IJavaElement; | |
25 | ||
26 | /** | |
27 | * Helper class for updating error markers and other decorators that work on resources. | |
28 | * Items are mapped to their element's underlying resource. | |
29 | * Method <code>resourceChanged</code> updates all items that are affected from the changed | |
30 | * elements. | |
31 | */ | |
32 | public class ResourceToItemsMapper { | |
33 | ||
34 | public static interface IContentViewerAccessor { | |
35 | public void doUpdateItem(Widget item); | |
36 | } | |
37 | ||
38 | ||
39 | private static final int NUMBER_LIST_REUSE= 10; | |
40 | ||
41 | // map from IResource to Item or List<Item> | |
42 | private HashMap<IResource, Object> fResourceToItem; | |
43 | private Stack<List<Item>> fReuseLists; | |
44 | ||
45 | private IContentViewerAccessor fContentViewerAccess; | |
46 | ||
47 | public ResourceToItemsMapper(IContentViewerAccessor viewer) { | |
48 | fResourceToItem= new HashMap<IResource, Object>(); | |
49 | fReuseLists= new Stack<List<Item>>(); | |
50 | ||
51 | fContentViewerAccess= viewer; | |
52 | } | |
53 | ||
54 | /** | |
55 | * Must be called from the UI thread. | |
56 | * @param changedResource Changed resource | |
57 | */ | |
58 | public void resourceChanged(IResource changedResource) { | |
59 | Object obj= fResourceToItem.get(changedResource); | |
60 | if (obj == null) { | |
61 | // not mapped | |
62 | } else if (obj instanceof Item) { | |
63 | updateItem((Item) obj); | |
64 | } else { // List of Items | |
65 | @SuppressWarnings("unchecked") | |
66 | List<Item> list= (List<Item>) obj; | |
67 | for (int k= 0; k < list.size(); k++) { | |
68 | updateItem(list.get(k)); | |
69 | } | |
70 | } | |
71 | } | |
72 | ||
73 | private void updateItem(Item item) { | |
74 | if (!item.isDisposed()) { | |
75 | fContentViewerAccess.doUpdateItem(item); | |
76 | } | |
77 | } | |
78 | ||
79 | /** | |
80 | * Adds a new item to the map. | |
81 | * @param element Element to map | |
82 | * @param item The item used for the element | |
83 | */ | |
84 | public void addToMap(Object element, Item item) { | |
85 | IResource resource= getCorrespondingResource(element); | |
86 | if (resource != null) { | |
87 | Object existingMapping= fResourceToItem.get(resource); | |
88 | if (existingMapping == null) { | |
89 | fResourceToItem.put(resource, item); | |
90 | } else if (existingMapping instanceof Item) { | |
91 | if (existingMapping != item) { | |
92 | List<Item> list= getNewList(); | |
93 | list.add((Item) existingMapping); | |
94 | list.add(item); | |
95 | fResourceToItem.put(resource, list); | |
96 | } | |
97 | } else { // List | |
98 | @SuppressWarnings("unchecked") | |
99 | List<Item> list= (List<Item>) existingMapping; | |
100 | if (!list.contains(item)) { | |
101 | list.add(item); | |
102 | } | |
103 | } | |
104 | } | |
105 | } | |
106 | ||
107 | /** | |
108 | * Removes an element from the map. | |
109 | * @param element The data element | |
110 | * @param item The table or tree item | |
111 | */ | |
112 | public void removeFromMap(Object element, Item item) { | |
113 | IResource resource= getCorrespondingResource(element); | |
114 | if (resource != null) { | |
115 | Object existingMapping= fResourceToItem.get(resource); | |
116 | if (existingMapping == null) { | |
117 | return; | |
118 | } else if (existingMapping instanceof Item) { | |
119 | fResourceToItem.remove(resource); | |
120 | } else { // List | |
121 | @SuppressWarnings("unchecked") | |
122 | List<Item> list= (List<Item>) existingMapping; | |
123 | list.remove(item); | |
124 | if (list.isEmpty()) { | |
125 | fResourceToItem.remove(list); | |
126 | releaseList(list); | |
127 | } | |
128 | } | |
129 | } | |
130 | } | |
131 | ||
132 | private List<Item> getNewList() { | |
133 | if (!fReuseLists.isEmpty()) { | |
134 | return fReuseLists.pop(); | |
135 | } | |
136 | return new ArrayList<Item>(2); | |
137 | } | |
138 | ||
139 | private void releaseList(List<Item> list) { | |
140 | if (fReuseLists.size() < NUMBER_LIST_REUSE) { | |
141 | fReuseLists.push(list); | |
142 | } | |
143 | } | |
144 | ||
145 | /** | |
146 | * Clears the map. | |
147 | */ | |
148 | public void clearMap() { | |
149 | fResourceToItem.clear(); | |
150 | } | |
151 | ||
152 | /** | |
153 | * Tests if the map is empty | |
154 | * @return Returns if there are mappings | |
155 | */ | |
156 | public boolean isEmpty() { | |
157 | return fResourceToItem.isEmpty(); | |
158 | } | |
159 | ||
160 | /** | |
161 | * Method that decides which elements can have error markers | |
162 | * Returns null if an element can not have error markers. | |
163 | * @param element The input element | |
164 | * @return Returns the corresponding resource or null | |
165 | */ | |
166 | private static IResource getCorrespondingResource(Object element) { | |
167 | if (element instanceof IJavaElement) { | |
168 | IJavaElement elem= (IJavaElement) element; | |
169 | IResource res= elem.getResource(); | |
170 | if (res == null) { | |
171 | ICompilationUnit cu= (ICompilationUnit) elem.getAncestor(IJavaElement.COMPILATION_UNIT); | |
172 | if (cu != null) { | |
173 | // elements in compilation units are mapped to the underlying resource of the original cu | |
174 | res= cu.getResource(); | |
175 | } | |
176 | } | |
177 | return res; | |
178 | } else if (element instanceof IResource) { | |
179 | return (IResource) element; | |
180 | } | |
181 | return null; | |
182 | } | |
183 | ||
184 | } |