41d0e409746dd4104750af3a927db9776bc49c4e
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / project / wizards / importtrace / ImportTraceWizardScanPage.java
1 /*******************************************************************************
2 * Copyright (c) 2013 Ericsson
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 * Matthew Khouzam - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.linuxtools.tmf.ui.project.wizards.importtrace;
14
15 import java.io.File;
16 import java.util.concurrent.ArrayBlockingQueue;
17 import java.util.concurrent.BlockingQueue;
18
19 import org.eclipse.core.runtime.IProgressMonitor;
20 import org.eclipse.core.runtime.IStatus;
21 import org.eclipse.core.runtime.Status;
22 import org.eclipse.core.runtime.SubMonitor;
23 import org.eclipse.core.runtime.jobs.Job;
24 import org.eclipse.jface.viewers.CellEditor;
25 import org.eclipse.jface.viewers.CheckStateChangedEvent;
26 import org.eclipse.jface.viewers.CheckboxTreeViewer;
27 import org.eclipse.jface.viewers.ColumnLabelProvider;
28 import org.eclipse.jface.viewers.ColumnViewer;
29 import org.eclipse.jface.viewers.ColumnViewerEditor;
30 import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
31 import org.eclipse.jface.viewers.EditingSupport;
32 import org.eclipse.jface.viewers.FocusCellOwnerDrawHighlighter;
33 import org.eclipse.jface.viewers.ICheckStateListener;
34 import org.eclipse.jface.viewers.IStructuredSelection;
35 import org.eclipse.jface.viewers.TextCellEditor;
36 import org.eclipse.jface.viewers.TreeViewerColumn;
37 import org.eclipse.jface.viewers.TreeViewerEditor;
38 import org.eclipse.jface.viewers.TreeViewerFocusCellManager;
39 import org.eclipse.linuxtools.internal.tmf.ui.Activator;
40 import org.eclipse.linuxtools.internal.tmf.ui.ITmfImageConstants;
41 import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceType;
42 import org.eclipse.linuxtools.tmf.ui.project.model.TraceValidationHelper;
43 import org.eclipse.swt.SWT;
44 import org.eclipse.swt.events.SelectionEvent;
45 import org.eclipse.swt.events.SelectionListener;
46 import org.eclipse.swt.graphics.Image;
47 import org.eclipse.swt.layout.GridData;
48 import org.eclipse.swt.layout.GridLayout;
49 import org.eclipse.swt.widgets.Button;
50 import org.eclipse.swt.widgets.Composite;
51 import org.eclipse.swt.widgets.Control;
52 import org.eclipse.ui.IWorkbench;
53
54 /**
55 * <b>Import page that scans files, can be cancelled</b> this page is the third
56 * of three pages shown. This one selects the traces to be imported that are to
57 * be scanned.
58 *
59 * @author Matthew Khouzam
60 * @since 2.0
61 */
62 public class ImportTraceWizardScanPage extends AbstractImportTraceWizardPage {
63
64 private static final int COL_WIDTH = 200;
65 private static final int MAX_TRACES = 65536;
66 private CheckboxTreeViewer traceTypeViewer;
67
68 final ScanRunnable fRunnable = new ScanRunnable("Scan job"); //$NON-NLS-1$
69 final private BlockingQueue<TraceValidationHelper> fTracesToScan = new ArrayBlockingQueue<TraceValidationHelper>(MAX_TRACES);
70 private volatile boolean fCanRun = true;
71
72 // --------------------------------------------------------------------------------
73 // Constructor and destructor
74 // --------------------------------------------------------------------------------
75
76 /**
77 * Import page that scans files, can be cancelled.
78 *
79 * @param name
80 * The name of the page.
81 * @param selection
82 * The current selection
83 */
84 protected ImportTraceWizardScanPage(String name, IStructuredSelection selection) {
85 super(name, selection);
86 }
87
88 /**
89 * Import page that scans files, can be cancelled
90 *
91 * @param workbench
92 * The workbench reference.
93 * @param selection
94 * The current selection
95 */
96 public ImportTraceWizardScanPage(IWorkbench workbench, IStructuredSelection selection) {
97 super(workbench, selection);
98 }
99
100 @Override
101 public void dispose() {
102 fCanRun = false;
103 fRunnable.done(Status.OK_STATUS);
104 super.dispose();
105 }
106
107 /*
108 * Init
109 */
110
111 @Override
112 public void createControl(Composite parent) {
113 super.createControl(parent);
114 final Composite control = (Composite) this.getControl();
115 setTitle(Messages.ImportTraceWizardScanPageTitle);
116 traceTypeViewer = new CheckboxTreeViewer(control, SWT.CHECK);
117 traceTypeViewer.setContentProvider(getBatchWizard().getScannedTraces());
118 traceTypeViewer.getTree().setHeaderVisible(true);
119 traceTypeViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
120 traceTypeViewer.setInput(getBatchWizard().getScannedTraces());
121 traceTypeViewer.addCheckStateListener(new ImportTraceCheckStateListener());
122
123 TreeViewerFocusCellManager focusCellManager = new TreeViewerFocusCellManager(traceTypeViewer, new FocusCellOwnerDrawHighlighter(traceTypeViewer));
124 ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(traceTypeViewer) {
125 };
126 TreeViewerEditor.create(traceTypeViewer, focusCellManager, actSupport, ColumnViewerEditor.TABBING_HORIZONTAL
127 | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR
128 | ColumnViewerEditor.TABBING_VERTICAL | ColumnViewerEditor.KEYBOARD_ACTIVATION);
129
130 final TextCellEditor textCellEditor = new TextCellEditor(traceTypeViewer.getTree());
131 // --------------------
132 // Column 1
133 // --------------------
134 TreeViewerColumn column = new TreeViewerColumn(traceTypeViewer, SWT.NONE);
135 column.getColumn().setWidth(COL_WIDTH);
136 column.getColumn().setText(Messages.ImportTraceWizardTraceDisplayName);
137 column.setLabelProvider(new FirstColumnLabelProvider());
138 column.setEditingSupport(new ColumnEditorSupport(traceTypeViewer, textCellEditor));
139
140 // --------------------
141 // Column 2
142 // --------------------
143
144 column = new TreeViewerColumn(traceTypeViewer, SWT.NONE);
145 column.getColumn().setWidth(COL_WIDTH);
146 column.getColumn().setText(Messages.ImportTraceWizardImportCaption);
147 column.setLabelProvider(new ColumnLabelProvider() {
148 @Override
149 public String getText(Object element) {
150 if (element instanceof FileAndName) {
151 FileAndName elem = (FileAndName) element;
152 return elem.getFile().getPath();
153 }
154 return null;
155 }
156 });
157
158 init();
159 getBatchWizard().setTracesToScan(fTracesToScan);
160 getBatchWizard().setTraceFolder(fTargetFolder);
161
162 fRunnable.schedule();
163 setErrorMessage(Messages.ImportTraceWizardScanPageSelectAtleastOne);
164 }
165
166 private void init() {
167 Composite optionPane = (Composite) this.getControl();
168
169 optionPane.setLayout(new GridLayout());
170 optionPane.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true));
171
172 final Button fLink = new Button(optionPane, SWT.RADIO);
173 fLink.setText(Messages.ImportTraceWizardLinkTraces);
174 fLink.setSelection(true);
175 fLink.setLayoutData(new GridData());
176
177 final Button fCopy = new Button(optionPane, SWT.RADIO);
178 fCopy.setText(Messages.ImportTraceWizardCopyTraces);
179 fCopy.setLayoutData(new GridData());
180
181 final SelectionListener linkedListener = new RadioChooser(fLink);
182
183 fLink.addSelectionListener(linkedListener);
184 fCopy.addSelectionListener(linkedListener);
185
186 Button fOverwrite = new Button(optionPane, SWT.CHECK);
187 fOverwrite.setText(Messages.ImportTraceWizardOverwriteTraces);
188 fOverwrite.setLayoutData(new GridData());
189 fOverwrite.setSelection(true);
190 fOverwrite.addSelectionListener(new SelectionListener() {
191
192 @Override
193 public void widgetSelected(SelectionEvent e) {
194 getBatchWizard().setOverwrite(((Button) e.widget).getSelection());
195 }
196
197 @Override
198 public void widgetDefaultSelected(SelectionEvent e) {
199 }
200 });
201 }
202
203 /*
204 * Helper classes
205 */
206
207 private final class RadioChooser implements SelectionListener {
208 final private Button isLinked;
209
210 public RadioChooser(Button desiredButton) {
211 isLinked = desiredButton;
212 }
213
214 @Override
215 public void widgetSelected(SelectionEvent e) {
216
217 final Button widget = (Button) e.widget;
218 getBatchWizard().setLinked(widget.equals(isLinked));
219 }
220
221 @Override
222 public void widgetDefaultSelected(SelectionEvent e) {
223
224 }
225 }
226
227 private final class ColumnEditorSupport extends EditingSupport {
228 private final TextCellEditor textCellEditor;
229
230 private ColumnEditorSupport(ColumnViewer viewer, TextCellEditor textCellEditor) {
231 super(viewer);
232 this.textCellEditor = textCellEditor;
233 }
234
235 @Override
236 protected boolean canEdit(Object element) {
237 return element instanceof FileAndName;
238 }
239
240 @Override
241 protected CellEditor getCellEditor(Object element) {
242 return textCellEditor;
243 }
244
245 @Override
246 protected Object getValue(Object element) {
247 if (element instanceof FileAndName) {
248 return ((FileAndName) element).getName();
249 }
250 return null;
251 }
252
253 @Override
254 protected void setValue(Object element, Object value) {
255 FileAndName fan = (FileAndName) element;
256 fan.setName((String) value);
257 getBatchWizard().updateConflicts();
258 traceTypeViewer.update(element, null);
259 traceTypeViewer.refresh();
260 }
261 }
262
263 private final class FirstColumnLabelProvider extends ColumnLabelProvider {
264 Image fConflict;
265
266 @Override
267 public Image getImage(Object element) {
268 if (element instanceof FileAndName) {
269 final FileAndName fan = (FileAndName) element;
270 if (fan.isConflictingName()) {
271 if (fConflict == null) {
272 fConflict = Activator.getDefault().getImageFromImageRegistry(ITmfImageConstants.IMG_UI_CONFLICT);
273 }
274 return fConflict;
275 }
276 }
277 return null;
278 }
279
280 @Override
281 public String getText(Object element) {
282 if (element instanceof FileAndName) {
283 FileAndName elem = (FileAndName) element;
284 return elem.getName();
285 }
286 if (element instanceof String) {
287 return (String) element;
288 }
289 return null;
290 }
291 }
292
293 private final class ImportTraceCheckStateListener implements ICheckStateListener {
294 @Override
295 public void checkStateChanged(CheckStateChangedEvent event) {
296 final CheckboxTreeViewer tv = (CheckboxTreeViewer)
297 event.getSource();
298 if (event.getElement() instanceof FileAndName) {
299 final FileAndName element = (FileAndName) event.getElement();
300 if (event.getChecked()) {
301 getBatchWizard().addFileToImport(element);
302 traceTypeViewer.update(element, null);
303 }
304 else {
305 getBatchWizard().removeFileToImport(element);
306 traceTypeViewer.update(element, null);
307 }
308 maintainCheckIntegrity(tv, element);
309 }
310 if (event.getElement() instanceof String) {
311
312 tv.setSubtreeChecked(event.getElement(), event.getChecked());
313 final Object[] children =
314 getBatchWizard().getScannedTraces().getChildren(event.getElement());
315 if (event.getChecked()) {
316 for (int i = 0; i < children.length; i++) {
317 final FileAndName element = (FileAndName) children[i];
318 getBatchWizard().addFileToImport(element);
319 traceTypeViewer.update(children[i], null);
320 }
321 }
322 else {
323 for (int i = 0; i < children.length; i++) {
324 getBatchWizard().removeFileToImport((FileAndName) children[i]);
325
326 }
327 }
328
329 }
330 getBatchWizard().updateConflicts();
331 if (getBatchWizard().hasConflicts()) {
332 setErrorMessage(Messages.ImportTraceWizardScanPageRenameError);
333 } else if (!getBatchWizard().hasTracesToImport()) {
334 setErrorMessage(Messages.ImportTraceWizardScanPageSelectAtleastOne);
335 } else {
336 setErrorMessage(null);
337 }
338 getWizard().getContainer().updateButtons();
339 traceTypeViewer.update(event.getElement(), null);
340 }
341
342 private void maintainCheckIntegrity(final CheckboxTreeViewer viewer, final FileAndName element) {
343 final ImportTraceContentProvider scannedTraces = getBatchWizard().getScannedTraces();
344 String parentElement = (String) scannedTraces.getParent(element);
345 boolean allChecked = true;
346 final FileAndName[] siblings = scannedTraces.getSiblings(element);
347 if (siblings != null) {
348 for (FileAndName child : siblings) {
349 allChecked &= viewer.getChecked(child);
350 }
351 }
352 viewer.setChecked(parentElement, allChecked);
353 }
354 }
355
356 private final class ScanRunnable extends Job {
357
358 // monitor is stored here, starts as the main monitor but becomes a
359 // submonitor
360 private IProgressMonitor fMonitor;
361
362 public ScanRunnable(String name) {
363 super(name);
364 this.setSystem(true);
365 }
366
367 private synchronized IProgressMonitor getMonitor() {
368 return fMonitor;
369 }
370
371 @Override
372 public IStatus run(IProgressMonitor monitor) {
373 /*
374 * Set up phase, it is synchronous
375 */
376 fMonitor = monitor;
377 final Control control = traceTypeViewer.getControl();
378 // please note the sync exec here is to allow us to set
379 control.getDisplay().syncExec(new Runnable() {
380 @Override
381 public void run() {
382 // monitor gets overwritten here so it's necessary to save
383 // it in a field.
384 fMonitor = SubMonitor.convert(getMonitor());
385 getMonitor().setTaskName(Messages.ImportTraceWizardPageScanScanning + ' ');
386 ((SubMonitor) getMonitor()).setWorkRemaining(IProgressMonitor.UNKNOWN);
387 }
388 });
389 /*
390 * At this point we start calling async execs and updating the view.
391 * This is a good candidate to parallelise.
392 */
393 while (fCanRun == true) {
394 boolean updated = false;
395 boolean validCombo;
396 if (fTracesToScan.isEmpty() && !control.isDisposed()) {
397 control.getDisplay().asyncExec(new Runnable() {
398
399 @Override
400 public void run() {
401 if (!control.isDisposed()) {
402 getMonitor().setTaskName(Messages.ImportTraceWizardPageScanScanning + ' ');
403 getMonitor().subTask(Messages.ImportTraceWizardPageScanDone);
404 ImportTraceWizardScanPage.this.setMessage(Messages.ImportTraceWizardPageScanScanning + ' ' + Messages.ImportTraceWizardPageScanDone);
405 }
406 }
407 });
408 }
409 try {
410 final TraceValidationHelper traceToScan = fTracesToScan.take();
411
412 if (!getBatchWizard().hasScanned(traceToScan)) {
413 getBatchWizard().addResult(traceToScan, TmfTraceType.getInstance().validate(traceToScan));
414 }
415
416 /*
417 * The following is to update the UI
418 */
419 validCombo = getBatchWizard().getResult(traceToScan);
420 if (validCombo) {
421 // Synched on it's parent
422
423 getBatchWizard().getScannedTraces().addCandidate(traceToScan.getTraceType(), new File(traceToScan.getTraceToScan()));
424 updated = true;
425 }
426 final int scanned = getBatchWizard().getNumberOfResults();
427 final int total = scanned + fTracesToScan.size();
428 final int prevVal = (int) ((scanned - 1) * 100.0 / total);
429 final int curVal = (int) ((scanned) * 100.0 / total);
430 if (curVal != prevVal) {
431 updated = true;
432 }
433 /*
434 * update the progress
435 */
436 if (updated) {
437 if (!control.isDisposed()) {
438 control.getDisplay().asyncExec(new Runnable() {
439 @Override
440 public void run() {
441 if (!control.isDisposed()) {
442 getMonitor().setTaskName(Messages.ImportTraceWizardPageScanScanning + ' ');
443 getMonitor().subTask(traceToScan.getTraceToScan());
444 getMonitor().worked(1);
445 ImportTraceWizardScanPage.this.setMessage(Messages.ImportTraceWizardPageScanScanning + ' '
446 + Integer.toString(curVal)
447 + '%');
448 }
449 }
450 }
451 );
452 }
453 }
454
455 /*
456 * here we update the table
457 */
458 final boolean editing = traceTypeViewer.isCellEditorActive();
459 if (updated && !editing) {
460 if (!control.isDisposed()) {
461 control.getDisplay().asyncExec(new Runnable() {
462
463 @Override
464 public void run() {
465 if (!control.isDisposed()) {
466 if (!traceTypeViewer.isCellEditorActive()) {
467 traceTypeViewer.refresh();
468 }
469 }
470 }
471 });
472 }
473 }
474 } catch (InterruptedException e) {
475 return new Status(IStatus.CANCEL, Activator.PLUGIN_ID, new String());
476 }
477 }
478 return Status.OK_STATUS;
479 }
480 }
481
482 /**
483 * Refresh the view and the corresponding model.
484 */
485 public void refresh() {
486 final Control control = traceTypeViewer.getControl();
487 if (!control.isDisposed()) {
488 control.getDisplay().asyncExec(new Runnable() {
489 @Override
490 public void run() {
491 if (!control.isDisposed()) {
492 traceTypeViewer.refresh();
493 }
494 }
495 });
496 }
497 }
498 }
This page took 0.049189 seconds and 4 git commands to generate.