1 /*******************************************************************************
2 * Copyright (c) 2013 Ericsson
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
10 * Matthew Khouzam - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.tmf
.ui
.project
.wizards
.importtrace
;
16 import java
.util
.concurrent
.ArrayBlockingQueue
;
17 import java
.util
.concurrent
.BlockingQueue
;
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
;
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
59 * @author Matthew Khouzam
62 public class ImportTraceWizardScanPage
extends AbstractImportTraceWizardPage
{
64 private static final int COL_WIDTH
= 200;
65 private static final int MAX_TRACES
= 65536;
66 private CheckboxTreeViewer traceTypeViewer
;
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;
72 // --------------------------------------------------------------------------------
73 // Constructor and destructor
74 // --------------------------------------------------------------------------------
77 * Import page that scans files, can be cancelled.
80 * The name of the page.
82 * The current selection
84 protected ImportTraceWizardScanPage(String name
, IStructuredSelection selection
) {
85 super(name
, selection
);
89 * Import page that scans files, can be cancelled
92 * The workbench reference.
94 * The current selection
96 public ImportTraceWizardScanPage(IWorkbench workbench
, IStructuredSelection selection
) {
97 super(workbench
, selection
);
101 public void dispose() {
103 fRunnable
.done(Status
.OK_STATUS
);
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());
123 TreeViewerFocusCellManager focusCellManager
= new TreeViewerFocusCellManager(traceTypeViewer
, new FocusCellOwnerDrawHighlighter(traceTypeViewer
));
124 ColumnViewerEditorActivationStrategy actSupport
= new ColumnViewerEditorActivationStrategy(traceTypeViewer
) {
126 TreeViewerEditor
.create(traceTypeViewer
, focusCellManager
, actSupport
, ColumnViewerEditor
.TABBING_HORIZONTAL
127 | ColumnViewerEditor
.TABBING_MOVE_TO_ROW_NEIGHBOR
128 | ColumnViewerEditor
.TABBING_VERTICAL
| ColumnViewerEditor
.KEYBOARD_ACTIVATION
);
130 final TextCellEditor textCellEditor
= new TextCellEditor(traceTypeViewer
.getTree());
131 // --------------------
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
));
140 // --------------------
142 // --------------------
144 column
= new TreeViewerColumn(traceTypeViewer
, SWT
.NONE
);
145 column
.getColumn().setWidth(COL_WIDTH
);
146 column
.getColumn().setText(Messages
.ImportTraceWizardImportCaption
);
147 column
.setLabelProvider(new ColumnLabelProvider() {
149 public String
getText(Object element
) {
150 if (element
instanceof FileAndName
) {
151 FileAndName elem
= (FileAndName
) element
;
152 return elem
.getFile().getPath();
159 getBatchWizard().setTracesToScan(fTracesToScan
);
160 getBatchWizard().setTraceFolder(fTargetFolder
);
162 fRunnable
.schedule();
163 setErrorMessage(Messages
.ImportTraceWizardScanPageSelectAtleastOne
);
166 private void init() {
167 Composite optionPane
= (Composite
) this.getControl();
169 optionPane
.setLayout(new GridLayout());
170 optionPane
.setLayoutData(new GridData(SWT
.LEFT
, SWT
.TOP
, true, true));
172 final Button fLink
= new Button(optionPane
, SWT
.RADIO
);
173 fLink
.setText(Messages
.ImportTraceWizardLinkTraces
);
174 fLink
.setSelection(true);
175 fLink
.setLayoutData(new GridData());
177 final Button fCopy
= new Button(optionPane
, SWT
.RADIO
);
178 fCopy
.setText(Messages
.ImportTraceWizardCopyTraces
);
179 fCopy
.setLayoutData(new GridData());
181 final SelectionListener linkedListener
= new RadioChooser(fLink
);
183 fLink
.addSelectionListener(linkedListener
);
184 fCopy
.addSelectionListener(linkedListener
);
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() {
193 public void widgetSelected(SelectionEvent e
) {
194 getBatchWizard().setOverwrite(((Button
) e
.widget
).getSelection());
198 public void widgetDefaultSelected(SelectionEvent e
) {
207 private final class RadioChooser
implements SelectionListener
{
208 final private Button isLinked
;
210 public RadioChooser(Button desiredButton
) {
211 isLinked
= desiredButton
;
215 public void widgetSelected(SelectionEvent e
) {
217 final Button widget
= (Button
) e
.widget
;
218 getBatchWizard().setLinked(widget
.equals(isLinked
));
222 public void widgetDefaultSelected(SelectionEvent e
) {
227 private final class ColumnEditorSupport
extends EditingSupport
{
228 private final TextCellEditor textCellEditor
;
230 private ColumnEditorSupport(ColumnViewer viewer
, TextCellEditor textCellEditor
) {
232 this.textCellEditor
= textCellEditor
;
236 protected boolean canEdit(Object element
) {
237 return element
instanceof FileAndName
;
241 protected CellEditor
getCellEditor(Object element
) {
242 return textCellEditor
;
246 protected Object
getValue(Object element
) {
247 if (element
instanceof FileAndName
) {
248 return ((FileAndName
) element
).getName();
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();
263 private final class FirstColumnLabelProvider
extends ColumnLabelProvider
{
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
);
281 public String
getText(Object element
) {
282 if (element
instanceof FileAndName
) {
283 FileAndName elem
= (FileAndName
) element
;
284 return elem
.getName();
286 if (element
instanceof String
) {
287 return (String
) element
;
293 private final class ImportTraceCheckStateListener
implements ICheckStateListener
{
295 public void checkStateChanged(CheckStateChangedEvent event
) {
296 final CheckboxTreeViewer tv
= (CheckboxTreeViewer
)
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);
305 getBatchWizard().removeFileToImport(element
);
306 traceTypeViewer
.update(element
, null);
308 maintainCheckIntegrity(tv
, element
);
310 if (event
.getElement() instanceof String
) {
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);
323 for (int i
= 0; i
< children
.length
; i
++) {
324 getBatchWizard().removeFileToImport((FileAndName
) children
[i
]);
330 getBatchWizard().updateConflicts();
331 if (getBatchWizard().hasConflicts()) {
332 setErrorMessage(Messages
.ImportTraceWizardScanPageRenameError
);
333 } else if (!getBatchWizard().hasTracesToImport()) {
334 setErrorMessage(Messages
.ImportTraceWizardScanPageSelectAtleastOne
);
336 setErrorMessage(null);
338 getWizard().getContainer().updateButtons();
339 traceTypeViewer
.update(event
.getElement(), null);
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
);
352 viewer
.setChecked(parentElement
, allChecked
);
356 private final class ScanRunnable
extends Job
{
358 // monitor is stored here, starts as the main monitor but becomes a
360 private IProgressMonitor fMonitor
;
362 public ScanRunnable(String name
) {
364 this.setSystem(true);
367 private synchronized IProgressMonitor
getMonitor() {
372 public IStatus
run(IProgressMonitor monitor
) {
374 * Set up phase, it is synchronous
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() {
382 // monitor gets overwritten here so it's necessary to save
384 fMonitor
= SubMonitor
.convert(getMonitor());
385 getMonitor().setTaskName(Messages
.ImportTraceWizardPageScanScanning
+ ' ');
386 ((SubMonitor
) getMonitor()).setWorkRemaining(IProgressMonitor
.UNKNOWN
);
390 * At this point we start calling async execs and updating the view.
391 * This is a good candidate to parallelise.
393 while (fCanRun
== true) {
394 boolean updated
= false;
396 if (fTracesToScan
.isEmpty() && !control
.isDisposed()) {
397 control
.getDisplay().asyncExec(new Runnable() {
401 if (!control
.isDisposed()) {
402 getMonitor().setTaskName(Messages
.ImportTraceWizardPageScanScanning
+ ' ');
403 getMonitor().subTask(Messages
.ImportTraceWizardPageScanDone
);
404 ImportTraceWizardScanPage
.this.setMessage(Messages
.ImportTraceWizardPageScanScanning
+ ' ' + Messages
.ImportTraceWizardPageScanDone
);
410 final TraceValidationHelper traceToScan
= fTracesToScan
.take();
412 if (!getBatchWizard().hasScanned(traceToScan
)) {
413 getBatchWizard().addResult(traceToScan
, TmfTraceType
.getInstance().validate(traceToScan
));
417 * The following is to update the UI
419 validCombo
= getBatchWizard().getResult(traceToScan
);
421 // Synched on it's parent
423 getBatchWizard().getScannedTraces().addCandidate(traceToScan
.getTraceType(), new File(traceToScan
.getTraceToScan()));
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
) {
434 * update the progress
437 if (!control
.isDisposed()) {
438 control
.getDisplay().asyncExec(new Runnable() {
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
)
456 * here we update the table
458 final boolean editing
= traceTypeViewer
.isCellEditorActive();
459 if (updated
&& !editing
) {
460 if (!control
.isDisposed()) {
461 control
.getDisplay().asyncExec(new Runnable() {
465 if (!control
.isDisposed()) {
466 if (!traceTypeViewer
.isCellEditorActive()) {
467 traceTypeViewer
.refresh();
474 } catch (InterruptedException e
) {
475 return new Status(IStatus
.CANCEL
, Activator
.PLUGIN_ID
, new String());
478 return Status
.OK_STATUS
;
483 * Refresh the view and the corresponding model.
485 public void refresh() {
486 final Control control
= traceTypeViewer
.getControl();
487 if (!control
.isDisposed()) {
488 control
.getDisplay().asyncExec(new Runnable() {
491 if (!control
.isDisposed()) {
492 traceTypeViewer
.refresh();