1
/*******************************************************************************
2
* Copyright (c) 2006, 2009 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
9
* Wind River Systems - initial API and implementation
10
*******************************************************************************/
11
package org.eclipse.cdt.examples.dsf.filebrowser;
14
import java.util.Arrays;
15
import java.util.HashMap;
16
import java.util.LinkedList;
17
import java.util.List;
20
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
21
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
22
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
23
import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
24
import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext;
25
import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
26
import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider;
27
import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta;
28
import org.eclipse.core.runtime.IProgressMonitor;
29
import org.eclipse.core.runtime.IStatus;
30
import org.eclipse.core.runtime.Status;
31
import org.eclipse.core.runtime.jobs.Job;
32
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
33
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
34
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
35
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
36
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
37
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
38
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
39
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
43
* File view model node which returns file elements that are found in the directory
44
* specified by the parent element. The child nodes of this node are fixed to
45
* reference this element, and therefore this node will recursively populate
46
* the contents of the tree reflecting the underlying filesystem directories.
48
* Note: this node does NOT sub-class the {@link org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMNode}
50
@SuppressWarnings("restriction")
52
implements IElementLabelProvider, IVMNode
55
* Reference to the viewer model provider. It's mainly used to access the
56
* viewer model adapter and its executor.
58
private final FileBrowserVMProvider fProvider;
60
public FileVMNode(FileBrowserVMProvider provider) {
65
public String toString() {
70
public void dispose() {
71
// All resources garbage collected.
74
public void setChildNodes(IVMNode[] childNodes) {
75
throw new UnsupportedOperationException("This node does not support children."); //$NON-NLS-1$
79
* List of child nodes containing only a reference to this.
81
private final IVMNode[] fChildNodes = { this };
83
public IVMNode[] getChildNodes() {
87
public void update(final IHasChildrenUpdate[] updates) {
88
new Job("") { //$NON-NLS-1$
91
setPriority(INTERACTIVE);
95
protected IStatus run(IProgressMonitor monitor) {
96
for (IHasChildrenUpdate update : updates) {
98
* Do not retrieve directory contents just to mark the plus
99
* sign in the tree. If it's a directory, just assume that
102
FileVMContext vmc = (FileVMContext)update.getElement();
103
update.setHasChilren(vmc.getFile().isDirectory());
107
return Status.OK_STATUS;
112
public void update(final IChildrenCountUpdate[] updates) {
113
new Job("") { //$NON-NLS-1$
116
setPriority(INTERACTIVE);
120
protected IStatus run(IProgressMonitor monitor) {
121
for (IChildrenCountUpdate update : updates) {
122
update.setChildCount(getFiles(update).length);
125
return Status.OK_STATUS;
130
public void update(final IChildrenUpdate[] updates) {
131
new Job("") { //$NON-NLS-1$
134
setPriority(INTERACTIVE);
138
protected IStatus run(IProgressMonitor monitor) {
139
for (IChildrenUpdate update : updates) {
140
File[] files = getFiles(update);
141
int offset = update.getOffset() != -1 ? update.getOffset() : 0;
142
int length = update.getLength() != -1 ? update.getLength() : files.length;
143
for (int i = offset; (i < files.length) && (i < (offset + length)); i++) {
144
update.setChild(new FileVMContext(FileVMNode.this, files[i]), i);
148
return Status.OK_STATUS;
153
public void update(final ILabelUpdate[] updates) {
154
new Job("") { //$NON-NLS-1$
157
setPriority(INTERACTIVE);
161
protected IStatus run(IProgressMonitor monitor) {
162
for (ILabelUpdate update : updates) {
163
update.setLabel(getLabel((FileVMContext)update.getElement()), 0);
167
return Status.OK_STATUS;
172
private static final File[] EMPTY_FILE_LIST = new File[0];
175
* Retrieves the list of files for this node. The list of files is based
176
* on the parent element in the tree, which must be of type FileVMC.
178
* @param update Update object containing the path (and the parent element)
179
* in the tree viewer.
180
* @return List of files contained in the directory specified in the
181
* update object. An empty list if the parent element is not a directory.
182
* @throws ClassCastException If the parent element contained in the update
183
* is NOT of type FileVMC.
185
private File[] getFiles(IViewerUpdate update) {
186
FileVMContext vmc = (FileVMContext)update.getElement();
187
File[] files = vmc.getFile().listFiles();
188
return files != null ? files : EMPTY_FILE_LIST;
192
* Returs the text label to show in the tree for given element.
194
private String getLabel(FileVMContext vmc) {
195
return vmc.getFile().getName();
198
public void getContextsForEvent(VMDelta parentDelta, Object event, DataRequestMonitor<IVMContext[]> rm) {
199
rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "", null)); //$NON-NLS-1$
203
public int getDeltaFlags(Object e) {
207
int retVal = IModelDelta.NO_CHANGE;
208
if (e instanceof String) {
209
retVal |= IModelDelta.SELECT | IModelDelta.EXPAND;
215
public void buildDelta(final Object event, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor requestMonitor) {
217
* The FileLayoutNode is recursive, with itself as the only child. In this
218
* method the delta is calculated for a full path VMContext elements, and the
219
* implementation of this method is not recursive.
221
if (event instanceof String) {
222
new Job("") { //$NON-NLS-1$
225
setPriority(INTERACTIVE);
229
protected IStatus run(IProgressMonitor monitor) {
231
* Requirements for a selection event to be issued is that the file exist, and
232
* that the parentDelta contain a FileVMC of a parent directory as its element.
234
* The test for first the former requirement could be performed inside getDeltaFlags()
235
* but getDeltaFlags() is synchronous, so it is better to perform this test here using
236
* a background thread (job).
238
* The latter is requirement is needed because this node does not have the algorithm
239
* calculate the complete list of root nodes. That algorithm is implemented inside the
240
* {@link FileSystemRootsLayoutNode#updateElements} method.
243
final File eventFile = new File((String)event);
244
File parentFile = null;
245
if (parentDelta.getElement() instanceof FileVMContext) {
246
parentFile = ((FileVMContext)parentDelta.getElement()).getFile();
249
// The file has to exist in order for us to be able to select
251
if (eventFile.exists() && parentFile != null) {
252
// Create a list containing all files in path
253
List<File> filePath = new LinkedList<File>();
254
for (File file = eventFile; file != null && !file.equals(parentFile); file = file.getParentFile()) {
255
filePath.add(0, file);
258
if (filePath.size() != 0) {
259
// Build the delta for all files in path.
260
ModelDelta delta = parentDelta;
261
File[] allFilesInDirectory = parentFile.listFiles();
262
for (File pathSegment : filePath) {
263
// All files in path should be directories, and should therefore
264
// have a valid list of elements.
265
assert allFilesInDirectory != null;
267
File[] pathSegmentDirectoryFiles = pathSegment.listFiles();
268
delta = delta.addNode(
269
new FileVMContext(FileVMNode.this, pathSegment),
270
nodeOffset + Arrays.asList(allFilesInDirectory).indexOf(pathSegment),
271
IModelDelta.NO_CHANGE,
272
pathSegmentDirectoryFiles != null ? pathSegmentDirectoryFiles.length : 0);
273
allFilesInDirectory = pathSegmentDirectoryFiles;
276
// The last file in path gets the EXPAND | SELECT flags.
277
delta.setFlags(delta.getFlags() | IModelDelta.SELECT | IModelDelta.EXPAND);
281
// Invoke the request monitor.
283
requestMonitor.done();
285
return Status.OK_STATUS;
289
requestMonitor.done();
294
* Override the behavior which checks for delta flags of all the child nodes,
295
* because we would get stuck in a recursive loop. Instead call only the child
296
* nodes which are not us.
298
protected Map<IVMNode, Integer> getChildNodesWithDeltas(Object e) {
299
Map<IVMNode, Integer> nodes = new HashMap<IVMNode, Integer>();
300
for (final IVMNode childNode : getChildNodes()) {
301
int delta = childNode.getDeltaFlags(e);
302
if (delta != IModelDelta.NO_CHANGE) {
303
nodes.put(childNode, delta);
309
public IVMProvider getVMProvider() {