ss: Move plugins to Trace Compass namespace
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / project / wizards / SelectTracesWizardPage.java
1 /*******************************************************************************
2 * Copyright (c) 2009, 2014 Ericsson, École Polytechnique de Montréal
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Francois Chouinard - Initial API and implementation
11 * Geneviève Bastien - Moved the add and remove code to the experiment class
12 * Patrick Tasse - Add support for folder elements
13 * Marc-Andre Laperle - Convert to tree structure and add select/deselect all
14 *******************************************************************************/
15
16 package org.eclipse.linuxtools.tmf.ui.project.wizards;
17
18 import java.lang.reflect.InvocationTargetException;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Set;
24 import java.util.Vector;
25
26 import org.eclipse.core.resources.IFolder;
27 import org.eclipse.core.resources.IWorkspace;
28 import org.eclipse.core.resources.IWorkspaceRunnable;
29 import org.eclipse.core.resources.ResourcesPlugin;
30 import org.eclipse.core.runtime.CoreException;
31 import org.eclipse.core.runtime.IProgressMonitor;
32 import org.eclipse.core.runtime.IStatus;
33 import org.eclipse.core.runtime.Status;
34 import org.eclipse.core.runtime.SubMonitor;
35 import org.eclipse.jface.dialogs.MessageDialog;
36 import org.eclipse.jface.operation.IRunnableWithProgress;
37 import org.eclipse.jface.operation.ModalContext;
38 import org.eclipse.jface.viewers.CheckStateChangedEvent;
39 import org.eclipse.jface.viewers.CheckboxTreeViewer;
40 import org.eclipse.jface.viewers.ColumnLabelProvider;
41 import org.eclipse.jface.viewers.ICheckStateListener;
42 import org.eclipse.jface.viewers.TreeViewer;
43 import org.eclipse.jface.viewers.TreeViewerColumn;
44 import org.eclipse.jface.viewers.ViewerSorter;
45 import org.eclipse.jface.wizard.WizardPage;
46 import org.eclipse.linuxtools.internal.tmf.ui.Activator;
47 import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceType;
48 import org.eclipse.linuxtools.tmf.ui.project.model.ITmfProjectModelElement;
49 import org.eclipse.linuxtools.tmf.ui.project.model.TmfExperimentElement;
50 import org.eclipse.linuxtools.tmf.ui.project.model.TmfNavigatorContentProvider;
51 import org.eclipse.linuxtools.tmf.ui.project.model.TmfNavigatorLabelProvider;
52 import org.eclipse.linuxtools.tmf.ui.project.model.TmfProjectElement;
53 import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceElement;
54 import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceFolder;
55 import org.eclipse.swt.SWT;
56 import org.eclipse.swt.events.SelectionAdapter;
57 import org.eclipse.swt.events.SelectionEvent;
58 import org.eclipse.swt.graphics.Image;
59 import org.eclipse.swt.layout.FillLayout;
60 import org.eclipse.swt.layout.GridData;
61 import org.eclipse.swt.layout.GridLayout;
62 import org.eclipse.swt.widgets.Button;
63 import org.eclipse.swt.widgets.Composite;
64 import org.eclipse.swt.widgets.Tree;
65 import org.eclipse.ui.dialogs.FilteredTree;
66 import org.eclipse.ui.dialogs.PatternFilter;
67
68 /**
69 * Implementation of a wizard page for selecting trace for an experiment.
70 * <p>
71 *
72 * @version 1.0
73 * @author Francois Chouinard
74 */
75 public class SelectTracesWizardPage extends WizardPage {
76
77 // ------------------------------------------------------------------------
78 // Attributes
79 // ------------------------------------------------------------------------
80
81 private final TmfProjectElement fProject;
82 private final TmfExperimentElement fExperiment;
83 private Map<String, TmfTraceElement> fPreviousTraces;
84 private CheckboxTreeViewer fCheckboxTreeViewer;
85 private TmfNavigatorContentProvider fContentProvider;
86 private TmfNavigatorLabelProvider fLabelProvider;
87
88 private static final int COLUMN_WIDTH = 200;
89 private static final int BUTTON_SPACING = 4;
90
91 // ------------------------------------------------------------------------
92 // Constructor
93 // ------------------------------------------------------------------------
94 /**
95 * Constructor
96 *
97 * @param project
98 * The project model element.
99 * @param experiment
100 * The experiment model experiment.
101 */
102 protected SelectTracesWizardPage(TmfProjectElement project, TmfExperimentElement experiment) {
103 super(""); //$NON-NLS-1$
104 setTitle(Messages.SelectTracesWizardPage_WindowTitle);
105 setDescription(Messages.SelectTracesWizardPage_Description);
106 fProject = project;
107 fExperiment = experiment;
108 }
109
110 // ------------------------------------------------------------------------
111 // Dialog
112 // ------------------------------------------------------------------------
113
114 @Override
115 public void createControl(Composite parent) {
116 Composite container = new Composite(parent, SWT.NULL);
117 container.setLayout(new GridLayout(2, false));
118 setControl(container);
119
120 new FilteredTree(container, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER, new PatternFilter(), true) {
121 @Override
122 protected TreeViewer doCreateTreeViewer(Composite aparent, int style) {
123 return SelectTracesWizardPage.this.doCreateTreeViewer(aparent);
124 }
125 };
126
127 Composite buttonComposite = new Composite(container, SWT.NONE);
128 FillLayout layout = new FillLayout(SWT.VERTICAL);
129 layout.spacing = BUTTON_SPACING;
130 buttonComposite.setLayout(layout);
131 GridData gd = new GridData();
132 gd.verticalAlignment = SWT.CENTER;
133 buttonComposite.setLayoutData(gd);
134
135 Button selectAllButton = new Button(buttonComposite, SWT.PUSH);
136 selectAllButton.setText(org.eclipse.linuxtools.internal.tmf.ui.project.dialogs.Messages.Dialog_SelectAll);
137 selectAllButton.addSelectionListener(new SelectionAdapter() {
138 @Override
139 public void widgetSelected(SelectionEvent e) {
140 setAllChecked(true);
141 }
142 });
143
144 Button deselectAllButton = new Button(buttonComposite, SWT.PUSH);
145 deselectAllButton.setText(org.eclipse.linuxtools.internal.tmf.ui.project.dialogs.Messages.Dialog_DeselectAll);
146 deselectAllButton.addSelectionListener(new SelectionAdapter() {
147 @Override
148 public void widgetSelected(SelectionEvent e) {
149 setAllChecked(false);
150 }
151 });
152 }
153
154 private TreeViewer doCreateTreeViewer(Composite parent) {
155 fCheckboxTreeViewer = new CheckboxTreeViewer(parent, SWT.BORDER);
156 fContentProvider = new TmfNavigatorContentProvider() {
157
158 @Override
159 public Object[] getElements(Object inputElement) {
160 return getChildren(inputElement);
161 }
162
163 @Override
164 public synchronized Object[] getChildren(Object parentElement) {
165 // We only care about the content of trace folders
166 if (parentElement instanceof TmfTraceFolder) {
167 Object[] children = super.getChildren(parentElement);
168 List<ITmfProjectModelElement> filteredChildren = new ArrayList<>();
169 for (Object child : children) {
170 if (child instanceof TmfTraceElement) {
171 TmfTraceElement traceElement = (TmfTraceElement) child;
172 String traceType = traceElement.getTraceType();
173 if (traceType != null && TmfTraceType.getTraceType(traceType) != null) {
174 filteredChildren.add(traceElement);
175 }
176 } else if (child instanceof TmfTraceFolder) {
177 filteredChildren.add((TmfTraceFolder) child);
178 }
179 }
180 return filteredChildren.toArray();
181 }
182 return null;
183 }
184
185 @Override
186 public boolean hasChildren(Object element) {
187 Object[] children = getChildren(element);
188 return children != null && children.length > 0;
189 }
190 };
191 fCheckboxTreeViewer.setContentProvider(fContentProvider);
192 fLabelProvider = new TmfNavigatorLabelProvider();
193 fCheckboxTreeViewer.setLabelProvider(fLabelProvider);
194 fCheckboxTreeViewer.setSorter(new ViewerSorter());
195
196 final Tree tree = fCheckboxTreeViewer.getTree();
197 GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
198 tree.setLayoutData(gd);
199 tree.setHeaderVisible(true);
200
201 final TreeViewerColumn column = new TreeViewerColumn(fCheckboxTreeViewer, SWT.NONE);
202 column.getColumn().setWidth(COLUMN_WIDTH);
203 column.getColumn().setText(Messages.SelectTracesWizardPage_TraceColumnHeader);
204 column.setLabelProvider(new ColumnLabelProvider() {
205 @Override
206 public String getText(Object element) {
207 return fLabelProvider.getText(element);
208 }
209
210 @Override
211 public Image getImage(Object element) {
212 return fLabelProvider.getImage(element);
213 }
214 });
215
216 // Get the list of traces already part of the experiment
217 fPreviousTraces = new HashMap<>();
218 for (ITmfProjectModelElement child : fExperiment.getChildren()) {
219 if (child instanceof TmfTraceElement) {
220 TmfTraceElement trace = (TmfTraceElement) child;
221 String name = trace.getElementPath();
222 fPreviousTraces.put(name, trace);
223 }
224 }
225
226 // Populate the list of traces to choose from
227 Set<String> keys = fPreviousTraces.keySet();
228 TmfTraceFolder traceFolder = fProject.getTracesFolder();
229 fCheckboxTreeViewer.setInput(traceFolder);
230
231 // Set the checkbox for the traces already included
232 setCheckedAlreadyIncludedTraces(keys, fContentProvider.getElements(fCheckboxTreeViewer.getInput()));
233
234 fCheckboxTreeViewer.addCheckStateListener(new ICheckStateListener() {
235 @Override
236 public void checkStateChanged(CheckStateChangedEvent event) {
237 Object element = event.getElement();
238 setSubtreeChecked(element, event.getChecked());
239 maintainCheckIntegrity(element);
240 }
241 });
242
243 return fCheckboxTreeViewer;
244 }
245
246 private void maintainCheckIntegrity(final Object element) {
247 Object parentElement = fContentProvider.getParent(element);
248 boolean allChecked = true;
249 boolean oneChecked = false;
250 boolean oneGrayed = false;
251 if (parentElement != null) {
252 if (fContentProvider.getChildren(parentElement) != null) {
253 for (Object child : fContentProvider.getChildren(parentElement)) {
254 boolean checked = fCheckboxTreeViewer.getChecked(child);
255 oneChecked |= checked;
256 allChecked &= checked;
257 oneGrayed |= fCheckboxTreeViewer.getGrayed(child);
258 }
259 }
260 if (oneGrayed || oneChecked && !allChecked) {
261 fCheckboxTreeViewer.setGrayChecked(parentElement, true);
262 } else {
263 fCheckboxTreeViewer.setGrayed(parentElement, false);
264 fCheckboxTreeViewer.setChecked(parentElement, allChecked);
265 }
266 maintainCheckIntegrity(parentElement);
267 }
268 }
269
270 private void setCheckedAlreadyIncludedTraces(Set<String> alreadyIncludedTraces, Object[] elements) {
271 for (Object element : elements) {
272 if (element instanceof TmfTraceElement) {
273 TmfTraceElement trace = (TmfTraceElement) element;
274 String elementPath = trace.getElementPath();
275 if (alreadyIncludedTraces.contains(elementPath)) {
276 fCheckboxTreeViewer.setChecked(element, true);
277 maintainCheckIntegrity(element);
278 }
279 }
280 Object[] children = fContentProvider.getChildren(element);
281 if (children != null) {
282 setCheckedAlreadyIncludedTraces(alreadyIncludedTraces, children);
283 }
284 }
285 }
286
287 /**
288 * Sets all items in the element viewer to be checked or unchecked
289 *
290 * @param checked
291 * whether or not items should be checked
292 */
293 private void setAllChecked(boolean checked) {
294 for (Object element : fContentProvider.getChildren(fCheckboxTreeViewer.getInput())) {
295 setSubtreeChecked(element, checked);
296 }
297 }
298
299 /**
300 * A version of setSubtreeChecked that also handles the grayed state
301 *
302 * @param element
303 * the element
304 * @param checked
305 * true if the item should be checked, and false if it should be
306 * unchecked
307 */
308 private void setSubtreeChecked(Object element, boolean checked) {
309 fCheckboxTreeViewer.setChecked(element, checked);
310 if (checked) {
311 fCheckboxTreeViewer.setGrayed(element, false);
312 }
313 Object[] children = fContentProvider.getChildren(element);
314 if (children != null) {
315 for (Object child : children) {
316 setSubtreeChecked(child, checked);
317 }
318 }
319 }
320
321 /**
322 * Method to finalize the select operation.
323 *
324 * @return <code>true</code> if successful else <code>false</code>
325 */
326 public boolean performFinish() {
327
328 IFolder experiment = fExperiment.getResource();
329
330 final SelectTracesOperation operation = new SelectTracesOperation(experiment, getSelection());
331
332 IStatus status = Status.OK_STATUS;
333 try {
334 getContainer().run(true, true, new IRunnableWithProgress() {
335 @Override
336 public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
337 // Wrapper to have only one resource changed event at the
338 // end of the operation.
339 IWorkspaceRunnable workspaceRunnable = new IWorkspaceRunnable() {
340 @Override
341 public void run(IProgressMonitor pm) throws CoreException {
342 operation.run(pm);
343 }
344 };
345
346 IWorkspace workspace = ResourcesPlugin.getWorkspace();
347 try {
348 workspace.run(workspaceRunnable, workspace.getRoot(), IWorkspace.AVOID_UPDATE, monitor);
349 } catch (CoreException e) {
350 throw new InvocationTargetException(e);
351 } finally {
352 monitor.done();
353 }
354 }
355 });
356
357 status = operation.getStatus();
358 } catch (InvocationTargetException e) {
359 status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.SelectTracesWizardPage_SelectionError, e);
360 } catch (InterruptedException e) {
361 status = Status.CANCEL_STATUS;
362 }
363 if (!status.isOK()) {
364 if (status.getSeverity() == IStatus.CANCEL) {
365 setMessage(Messages.SelectTracesWizardPage_SelectionOperationCancelled);
366 setErrorMessage(null);
367 } else {
368 if (status.getException() != null) {
369 MessageDialog.open(MessageDialog.ERROR, getContainer().getShell(),
370 Messages.SelectTracesWizardPage_InternalErrorTitle, status.getMessage() + ": " + status.getException(), SWT.SHEET); //$NON-NLS-1$
371 }
372 setMessage(null);
373 setErrorMessage(Messages.SelectTracesWizardPage_SelectionError);
374 }
375 return false;
376 }
377 setErrorMessage(null);
378
379 return true;
380 }
381
382 private class SelectTracesOperation {
383
384 IFolder experiment = null;
385 TmfTraceElement[] traces;
386 private IStatus fStatus;
387
388 public SelectTracesOperation(IFolder experiment, TmfTraceElement[] traces) {
389 this.experiment = experiment;
390 this.traces = traces;
391 }
392
393 public void run(IProgressMonitor progressMonitor) {
394
395 // Check if operation was cancelled.
396 boolean changed = false;
397
398 // Add the selected traces to the experiment
399 Set<String> keys = fPreviousTraces.keySet();
400 SubMonitor subMonitor = SubMonitor.convert(progressMonitor, traces.length + keys.size());
401 try {
402 for (TmfTraceElement trace : traces) {
403 ModalContext.checkCanceled(progressMonitor);
404 String name = trace.getElementPath();
405 if (keys.contains(name)) {
406 subMonitor.setTaskName(Messages.SelectTracesWizardPage_TraceRemovalTask + " " + trace.getElementPath()); //$NON-NLS-1$
407 fPreviousTraces.remove(name);
408 } else {
409 subMonitor.setTaskName(Messages.SelectTracesWizardPage_TraceSelectionTask + " " + trace.getElementPath()); //$NON-NLS-1$
410 fExperiment.addTrace(trace, false);
411 changed = true;
412 }
413 subMonitor.worked(1);
414 }
415
416 // Remove traces that were unchecked (thus left in
417 // fPreviousTraces)
418 keys = fPreviousTraces.keySet();
419 for (String key : keys) {
420 ModalContext.checkCanceled(progressMonitor);
421 TmfTraceElement trace = fPreviousTraces.get(key);
422 subMonitor.setTaskName(Messages.SelectTracesWizardPage_TraceRemovalTask + " " + trace.getElementPath()); //$NON-NLS-1$
423
424 try {
425 fExperiment.removeTrace(trace);
426 } catch (CoreException e) {
427 Activator.getDefault().logError(Messages.SelectTracesWizardPage_SelectionError + " " + experiment.getName(), e); //$NON-NLS-1$
428 }
429 changed = true;
430 subMonitor.worked(1);
431 }
432 if (changed) {
433 fExperiment.closeEditors();
434 fExperiment.deleteSupplementaryResources();
435 }
436 setStatus(Status.OK_STATUS);
437 } catch (InterruptedException e) {
438 setStatus(Status.CANCEL_STATUS);
439 } catch (Exception e) {
440 Activator.getDefault().logError(Messages.SelectTracesWizardPage_SelectionError, e);
441 setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.SelectTracesWizardPage_SelectionError, e));
442 }
443 }
444
445 /**
446 * Set the status for this operation
447 *
448 * @param status
449 * the status
450 */
451 protected void setStatus(IStatus status) {
452 fStatus = status;
453 }
454
455 public IStatus getStatus() {
456 return fStatus;
457 }
458
459 }
460
461 /**
462 * Get the list of selected traces
463 */
464 private TmfTraceElement[] getSelection() {
465 Vector<TmfTraceElement> traces = new Vector<>();
466 Object[] selection = fCheckboxTreeViewer.getCheckedElements();
467 for (Object sel : selection) {
468 if (sel instanceof TmfTraceElement) {
469 traces.add((TmfTraceElement) sel);
470 }
471 }
472 TmfTraceElement[] result = new TmfTraceElement[traces.size()];
473 traces.toArray(result);
474 return result;
475 }
476
477 }
This page took 0.072148 seconds and 5 git commands to generate.