Added
Link Here
|
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2008 Wind River Systems 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 |
* Wind River Systems - initial API and implementation |
10 |
*******************************************************************************/ |
11 |
package org.eclipse.cdt.dsf.debug.ui.viewmodel.breakpoints; |
12 |
|
13 |
import java.util.ArrayList; |
14 |
import java.util.Arrays; |
15 |
import java.util.HashSet; |
16 |
import java.util.LinkedHashSet; |
17 |
import java.util.List; |
18 |
import java.util.Map; |
19 |
import java.util.Set; |
20 |
|
21 |
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; |
22 |
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; |
23 |
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; |
24 |
import org.eclipse.cdt.dsf.concurrent.RequestMonitor; |
25 |
import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; |
26 |
import org.eclipse.cdt.dsf.ui.concurrent.ViewerCountingRequestMonitor; |
27 |
import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; |
28 |
import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMNode; |
29 |
import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta; |
30 |
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider; |
31 |
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; |
32 |
import org.eclipse.cdt.dsf.ui.viewmodel.properties.VMPropertiesUpdate; |
33 |
import org.eclipse.cdt.dsf.ui.viewmodel.update.ICachingVMProvider; |
34 |
import org.eclipse.core.runtime.CoreException; |
35 |
import org.eclipse.core.runtime.IAdaptable; |
36 |
import org.eclipse.core.runtime.IStatus; |
37 |
import org.eclipse.core.runtime.Status; |
38 |
import org.eclipse.debug.core.DebugPlugin; |
39 |
import org.eclipse.debug.core.model.IBreakpoint; |
40 |
import org.eclipse.debug.internal.ui.CompositeDebugImageDescriptor; |
41 |
import org.eclipse.debug.internal.ui.DebugUIPlugin; |
42 |
import org.eclipse.debug.internal.ui.viewers.model.provisional.ICheckUpdate; |
43 |
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate; |
44 |
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; |
45 |
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider; |
46 |
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate; |
47 |
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; |
48 |
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; |
49 |
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; |
50 |
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate; |
51 |
import org.eclipse.debug.internal.ui.views.DebugModelPresentationContext; |
52 |
import org.eclipse.debug.internal.ui.views.breakpoints.IBreakpointOrganizer; |
53 |
import org.eclipse.debug.ui.IDebugModelPresentation; |
54 |
import org.eclipse.jface.resource.ImageDescriptor; |
55 |
import org.eclipse.jface.viewers.TreePath; |
56 |
import org.eclipse.swt.graphics.Image; |
57 |
import org.eclipse.ui.model.IWorkbenchAdapter; |
58 |
|
59 |
/** |
60 |
* |
61 |
* |
62 |
* @since 2.1 |
63 |
*/ |
64 |
public class BreakpointOrganizerVMNode extends AbstractVMNode implements IElementPropertiesProvider, IElementLabelProvider { |
65 |
|
66 |
public static final String PROP_CATEGORY_BREAKPOINTS = "categoryBreakpoints"; //$NON-NLS-1$ |
67 |
|
68 |
public static final Set<String> SET_PROP_CATEGORY_BREAKPOINTS = new HashSet<String>(2); |
69 |
|
70 |
static { |
71 |
SET_PROP_CATEGORY_BREAKPOINTS.add(PROP_CATEGORY_BREAKPOINTS); |
72 |
} |
73 |
|
74 |
private class OtherCategoryLabelProvider implements IElementLabelProvider { |
75 |
public void update(ILabelUpdate[] updates) { |
76 |
for (ILabelUpdate update : updates) { |
77 |
update.setLabel(fOrganizer.getOthersLabel(), 0); |
78 |
//update.setImageDescriptor(DebugPluginImages.getImageDescriptor(IDebugUIConstants.IMG_VIEW_BREAKPOINTS), 0); |
79 |
update.setImageDescriptor(fOrganizer.getImageDescriptor(), 0); |
80 |
} |
81 |
} |
82 |
} |
83 |
|
84 |
private final IBreakpointOrganizer fOrganizer; |
85 |
private final IElementLabelProvider fOtherCategoryLabelProvider = new OtherCategoryLabelProvider(); |
86 |
|
87 |
public BreakpointOrganizerVMNode(ICachingVMProvider provider, IBreakpointOrganizer organizer) { |
88 |
super(provider); |
89 |
fOrganizer = organizer; |
90 |
} |
91 |
|
92 |
public IBreakpointOrganizer getBreakpointOrganizer() { |
93 |
return fOrganizer; |
94 |
} |
95 |
|
96 |
public void update(final IHasChildrenUpdate[] updates) { |
97 |
for (IHasChildrenUpdate update : updates) { |
98 |
if (!checkUpdate(update)) continue; |
99 |
update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented, clients should call to update all children instead.", null)); //$NON-NLS-1$ |
100 |
update.done(); |
101 |
} |
102 |
} |
103 |
|
104 |
public void update(final IChildrenCountUpdate[] updates) { |
105 |
for (IChildrenCountUpdate update : updates) { |
106 |
if (!checkUpdate(update)) continue; |
107 |
update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented, clients should call to update all children instead.", null)); //$NON-NLS-1$ |
108 |
update.done(); |
109 |
} |
110 |
} |
111 |
|
112 |
public void update(IChildrenUpdate[] updates) { |
113 |
for (IChildrenUpdate update : updates) { |
114 |
if (!checkUpdate(update)) continue; |
115 |
doUpdate(update); |
116 |
} |
117 |
} |
118 |
|
119 |
private void doUpdate(final IChildrenUpdate update) { |
120 |
getNestingCategoryBreakpoints( |
121 |
update.getElementPath(), |
122 |
update.getViewerInput(), |
123 |
update.getPresentationContext(), |
124 |
new ViewerDataRequestMonitor<List<IBreakpoint>>(ImmediateExecutor.getInstance(), update) { |
125 |
@Override |
126 |
protected void handleSuccess() { |
127 |
final Set<IAdaptable> categoriesSet = new LinkedHashSet<IAdaptable>(); |
128 |
|
129 |
boolean otherBPs = false; |
130 |
for (IBreakpoint bp : getData()) { |
131 |
final IAdaptable[] bpCategories = fOrganizer.getCategories(bp); |
132 |
if (bpCategories == null || bpCategories.length == 0) { |
133 |
otherBPs = true; |
134 |
} else { |
135 |
for (IAdaptable category : bpCategories) { |
136 |
categoriesSet.add(category); |
137 |
} |
138 |
} |
139 |
} |
140 |
|
141 |
final IAdaptable[] independentCategories = fOrganizer.getCategories(); |
142 |
if (independentCategories != null) { |
143 |
for (IAdaptable category : independentCategories) { |
144 |
categoriesSet.add(category); |
145 |
} |
146 |
} |
147 |
|
148 |
if (otherBPs) { |
149 |
categoriesSet.add(null); |
150 |
} |
151 |
IAdaptable[] categories = categoriesSet.toArray(new IAdaptable[categoriesSet.size()]); |
152 |
|
153 |
int updateIdx = update.getOffset() != -1 ? update.getOffset() : 0; |
154 |
int endIdx = updateIdx + (update.getLength() != -1 ? update.getLength() : (categories.length)); |
155 |
while (updateIdx < endIdx && updateIdx < categoriesSet.size()) { |
156 |
update.setChild( createVMContext(categories[updateIdx]) , updateIdx); |
157 |
updateIdx++; |
158 |
} |
159 |
update.done(); |
160 |
|
161 |
} |
162 |
}); |
163 |
} |
164 |
|
165 |
private void fillUpdateWithBreakpointOrganizerVMContexts(IChildrenUpdate update, BreakpointOrganizerVMContext[] vmcs) { |
166 |
int updateIdx = update.getOffset() != -1 ? update.getOffset() : 0; |
167 |
int endIdx = updateIdx + (update.getLength() != -1 ? update.getLength() : vmcs.length); |
168 |
while (updateIdx < endIdx && updateIdx < vmcs.length) { |
169 |
update.setChild(vmcs[updateIdx], updateIdx); |
170 |
updateIdx++; |
171 |
} |
172 |
update.done(); |
173 |
} |
174 |
|
175 |
public void update(IPropertiesUpdate[] updates) { |
176 |
for (IPropertiesUpdate update : updates) { |
177 |
if (!checkUpdate(update)) continue; |
178 |
doUpdate(update); |
179 |
} |
180 |
} |
181 |
|
182 |
// Dead end |
183 |
// public void update(ILabelUpdate[] updates) { |
184 |
// boolean first = true; |
185 |
// IElementLabelProvider firstProvider = null; |
186 |
// boolean allProvidersSame = true; |
187 |
// for (ILabelUpdate update : updates) { |
188 |
// IAdaptable category = getCategory(update); |
189 |
// IElementLabelProvider provider = null; |
190 |
// if (category != null) { |
191 |
// provider = (IElementLabelProvider)category.getAdapter(IElementLabelProvider.class); |
192 |
// } else { |
193 |
// provider = fOtherCategoryLabelProvider; |
194 |
// } |
195 |
// if (first) { |
196 |
// first = false; |
197 |
// firstProvider = provider; |
198 |
// } else if (!provider.equals(firstProvider)) { |
199 |
// allProvidersSame = false; |
200 |
// break; |
201 |
// } |
202 |
// } |
203 |
// if (allProvidersSame) { |
204 |
// if (firstProvider != null) {// could occur only if updates.length == 0 |
205 |
// firstProvider.update(updates); |
206 |
// } |
207 |
// return; |
208 |
// } |
209 |
// |
210 |
// Map<IElementLabelProvider, List<ILabelUpdate>> updatesMap = new HashMap<IElementLabelProvider, List<ILabelUpdate>>(4); |
211 |
// for (ILabelUpdate update : updates) { |
212 |
// IAdaptable category = getCategory(update); |
213 |
// IElementLabelProvider provider = null; |
214 |
// if (category != null) { |
215 |
// provider = (IElementLabelProvider)category.getAdapter(IElementLabelProvider.class); |
216 |
// } |
217 |
// List<ILabelUpdate> updatesList = updatesMap.get(category); |
218 |
// if (updatesList == null) { |
219 |
// updatesList = new ArrayList<ILabelUpdate>(updates.length < 4 ? updates.length - 1 : 4); |
220 |
// updatesMap.put(provider, updatesList); |
221 |
// } |
222 |
// updatesList.add(update); |
223 |
// } |
224 |
// for (Map.Entry<IElementLabelProvider, List<ILabelUpdate>> entry : updatesMap.entrySet()) { |
225 |
// entry.getKey().update( entry.getValue().toArray(new ILabelUpdate[entry.getValue().size()]) ); |
226 |
// } |
227 |
// } |
228 |
|
229 |
public void update(ILabelUpdate[] updates) { |
230 |
IPropertiesUpdate[] propertiesUpdates = new IPropertiesUpdate[updates.length]; |
231 |
for (int i = 0; i < updates.length; i++) { |
232 |
final ILabelUpdate update = updates[i]; |
233 |
if (!checkUpdate(update)) continue; |
234 |
|
235 |
if ( !(update.getElement() instanceof BreakpointOrganizerVMContext) ) { |
236 |
handleFailedUpdate(update); |
237 |
return; |
238 |
} |
239 |
IAdaptable category = ((BreakpointOrganizerVMContext)update.getElement()).getCategory(); |
240 |
String label = null; |
241 |
ImageDescriptor desc = null; |
242 |
if (category != null) { |
243 |
IWorkbenchAdapter workbenchAdapter = (IWorkbenchAdapter)category.getAdapter(IWorkbenchAdapter.class); |
244 |
if (workbenchAdapter != null) { |
245 |
label = workbenchAdapter.getLabel(category); |
246 |
desc = workbenchAdapter.getImageDescriptor(category); |
247 |
} |
248 |
} else { |
249 |
label = fOrganizer.getOthersLabel(); |
250 |
//update.setImageDescriptor(DebugPluginImages.getImageDescriptor(IDebugUIConstants.IMG_VIEW_BREAKPOINTS), 0); |
251 |
desc = fOrganizer.getImageDescriptor(); |
252 |
} |
253 |
|
254 |
if (!DebugPlugin.getDefault().getBreakpointManager().isEnabled()) { |
255 |
Image image = DebugUIPlugin.getImageDescriptorRegistry().get(desc); |
256 |
desc = new CompositeDebugImageDescriptor(image, CompositeDebugImageDescriptor.SKIP_BREAKPOINT); |
257 |
} |
258 |
|
259 |
if (label != null) { |
260 |
update.setLabel(label, 0); |
261 |
} |
262 |
update.setImageDescriptor(desc, 0); |
263 |
|
264 |
propertiesUpdates[i] = new VMPropertiesUpdate( |
265 |
SET_PROP_CATEGORY_BREAKPOINTS, update, |
266 |
new ViewerDataRequestMonitor<Map<String,Object>>(ImmediateExecutor.getInstance(), update) { |
267 |
@Override |
268 |
protected void handleSuccess() { |
269 |
List<IBreakpoint> bps = (List<IBreakpoint>)getData().get(PROP_CATEGORY_BREAKPOINTS); |
270 |
boolean checked = bps.size() == 0; |
271 |
boolean hasDisabled = false; |
272 |
for (IBreakpoint bp : bps) { |
273 |
try { |
274 |
if (bp.isEnabled()) { |
275 |
checked = true; |
276 |
} else { |
277 |
hasDisabled = true; |
278 |
} |
279 |
} catch (CoreException e) {} |
280 |
} |
281 |
if (update instanceof ICheckUpdate) { |
282 |
((ICheckUpdate) update).setChecked(checked, checked && hasDisabled); |
283 |
} |
284 |
update.done(); |
285 |
} |
286 |
}); |
287 |
} |
288 |
|
289 |
((ICachingVMProvider)getVMProvider()).update(propertiesUpdates); |
290 |
} |
291 |
|
292 |
private IAdaptable getCategory(IViewerUpdate update) { |
293 |
if ( update.getElement() instanceof BreakpointOrganizerVMContext) { |
294 |
return ((BreakpointOrganizerVMContext)update.getElement()).getCategory(); |
295 |
} |
296 |
return null; |
297 |
} |
298 |
|
299 |
private IDebugModelPresentation getDebugModelPresentation() { |
300 |
DebugModelPresentationContext debugContext = |
301 |
(DebugModelPresentationContext) getVMProvider().getPresentationContext(); |
302 |
return debugContext.getModelPresentation(); |
303 |
} |
304 |
|
305 |
private void doUpdate(IPropertiesUpdate update) { |
306 |
ViewerCountingRequestMonitor countingRm = new ViewerCountingRequestMonitor(ImmediateExecutor.getInstance(), update); |
307 |
int count = 0; |
308 |
|
309 |
if (update.getProperties().contains(PROP_CATEGORY_BREAKPOINTS)) { |
310 |
fillCategoryBreakpoints(update, new RequestMonitor(ImmediateExecutor.getInstance(), countingRm)); |
311 |
} |
312 |
countingRm.setDoneCount(count); |
313 |
} |
314 |
|
315 |
private void fillCategoryBreakpoints(final IPropertiesUpdate update, final RequestMonitor rm) { |
316 |
if (!(update.getElement() instanceof BreakpointOrganizerVMContext)) { |
317 |
rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_HANDLE, "Update is not for a breakpoint organizer", null)); //$NON-NLS-1$ |
318 |
rm.done(); |
319 |
return; |
320 |
} |
321 |
|
322 |
getNestingCategoryBreakpoints( |
323 |
update.getElementPath().getParentPath(), |
324 |
update.getViewerInput(), |
325 |
update.getPresentationContext(), |
326 |
new DataRequestMonitor<List<IBreakpoint>>(ImmediateExecutor.getInstance(), rm) { |
327 |
@Override |
328 |
protected void handleSuccess() { |
329 |
BreakpointOrganizerVMContext vmc = (BreakpointOrganizerVMContext)update.getElement(); |
330 |
List<IBreakpoint> parentBreakpoints = getData(); |
331 |
IAdaptable vmcCategory = vmc.getCategory(); |
332 |
List<IBreakpoint> categoryBPs = new ArrayList<IBreakpoint>(1); |
333 |
for (IBreakpoint bp : parentBreakpoints) { |
334 |
IAdaptable[] bpCategories = fOrganizer.getCategories(bp); |
335 |
if (bpCategories == null || bpCategories.length == 0) { |
336 |
// BP is in the "Other" category. Add it if the category |
337 |
// from the update is null. |
338 |
if (vmcCategory == null) { |
339 |
categoryBPs.add(bp); |
340 |
} |
341 |
} else { |
342 |
// Check if any of the BP categories match the update category. |
343 |
for (IAdaptable bpCategory : bpCategories) { |
344 |
if (bpCategory.equals(vmcCategory)) { |
345 |
categoryBPs.add(bp); |
346 |
break; |
347 |
} |
348 |
} |
349 |
} |
350 |
} |
351 |
update.setProperty(PROP_CATEGORY_BREAKPOINTS, categoryBPs); |
352 |
rm.done(); |
353 |
} |
354 |
}); |
355 |
} |
356 |
|
357 |
static void getNestingCategoryBreakpoints(TreePath path, Object viewerInput, IPresentationContext presentationContext, final DataRequestMonitor<List<IBreakpoint>> rm) { |
358 |
BreakpointOrganizerVMContext nestingOrganizerVmc = null; |
359 |
while (path.getSegmentCount() > 0) { |
360 |
if (path.getLastSegment() instanceof BreakpointOrganizerVMContext) { |
361 |
nestingOrganizerVmc = (BreakpointOrganizerVMContext)path.getLastSegment(); |
362 |
break; |
363 |
} |
364 |
path = path.getParentPath(); |
365 |
} |
366 |
if (nestingOrganizerVmc == null) { |
367 |
rm.setData(Arrays.asList(DebugPlugin.getDefault().getBreakpointManager().getBreakpoints())); |
368 |
rm.done(); |
369 |
return; |
370 |
} else { |
371 |
IElementPropertiesProvider propertiesProvider = (IElementPropertiesProvider) |
372 |
nestingOrganizerVmc.getAdapter(IElementPropertiesProvider.class); |
373 |
propertiesProvider.update(new IPropertiesUpdate[] { |
374 |
new VMPropertiesUpdate( |
375 |
SET_PROP_CATEGORY_BREAKPOINTS, path, viewerInput, presentationContext, |
376 |
new DataRequestMonitor<Map<String,Object>>(ImmediateExecutor.getInstance(), rm) { |
377 |
@Override |
378 |
protected void handleSuccess() { |
379 |
assert getData().get(PROP_CATEGORY_BREAKPOINTS) != null; |
380 |
rm.setData((List<IBreakpoint>)getData().get(PROP_CATEGORY_BREAKPOINTS)); |
381 |
rm.done(); |
382 |
} |
383 |
}) |
384 |
}); |
385 |
} |
386 |
} |
387 |
|
388 |
private BreakpointOrganizerVMContext createVMContext(IAdaptable category) { |
389 |
return new BreakpointOrganizerVMContext(this, category); |
390 |
} |
391 |
|
392 |
public void buildDelta(Object event, VMDelta parent, int nodeOffset, RequestMonitor requestMonitor) { |
393 |
if (event instanceof BreakpointsChangedEvent) { |
394 |
parent.setFlags(parent.getFlags() | IModelDelta.CONTENT); |
395 |
} |
396 |
requestMonitor.done(); |
397 |
} |
398 |
|
399 |
public int getDeltaFlags(Object event) { |
400 |
if (event instanceof BreakpointsChangedEvent) { |
401 |
return IModelDelta.CONTENT; |
402 |
} |
403 |
return 0; |
404 |
} |
405 |
|
406 |
|
407 |
} |