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.text.DecimalFormat;
17
import java.util.concurrent.ArrayBlockingQueue;
18
import java.util.concurrent.BlockingQueue;
20
import org.eclipse.core.runtime.IProgressMonitor;
21
import org.eclipse.core.runtime.IStatus;
22
import org.eclipse.core.runtime.Status;
23
import org.eclipse.core.runtime.SubMonitor;
24
import org.eclipse.core.runtime.jobs.Job;
25
import org.eclipse.jface.viewers.CellEditor;
26
import org.eclipse.jface.viewers.CheckStateChangedEvent;
27
import org.eclipse.jface.viewers.CheckboxTreeViewer;
28
import org.eclipse.jface.viewers.ColumnLabelProvider;
29
import org.eclipse.jface.viewers.ColumnViewer;
30
import org.eclipse.jface.viewers.ColumnViewerEditor;
31
import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
32
import org.eclipse.jface.viewers.EditingSupport;
33
import org.eclipse.jface.viewers.FocusCellOwnerDrawHighlighter;
34
import org.eclipse.jface.viewers.ICheckStateListener;
35
import org.eclipse.jface.viewers.IStructuredSelection;
36
import org.eclipse.jface.viewers.TextCellEditor;
37
import org.eclipse.jface.viewers.TreeViewerColumn;
38
import org.eclipse.jface.viewers.TreeViewerEditor;
39
import org.eclipse.jface.viewers.TreeViewerFocusCellManager;
40
import org.eclipse.linuxtools.internal.tmf.ui.Activator;
41
import org.eclipse.linuxtools.internal.tmf.ui.ITmfImageConstants;
42
import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceType;
43
import org.eclipse.linuxtools.tmf.ui.project.model.TraceValidationHelper;
44
import org.eclipse.swt.SWT;
45
import org.eclipse.swt.events.SelectionEvent;
46
import org.eclipse.swt.events.SelectionListener;
47
import org.eclipse.swt.graphics.Image;
48
import org.eclipse.swt.layout.GridData;
49
import org.eclipse.swt.layout.GridLayout;
50
import org.eclipse.swt.widgets.Button;
51
import org.eclipse.swt.widgets.Composite;
52
import org.eclipse.swt.widgets.Control;
53
import org.eclipse.ui.IWorkbench;
56
* <b>Import page that scans files, can be cancelled</b> this page is the third
57
* of three pages shown. This one selects the traces to be imported that are to
60
* @author Matthew Khouzam
63
public class ImportTraceWizardScanPage extends AbstractImportTraceWizardPage {
65
private static final int COL_WIDTH = 200;
66
private static final int MAX_TRACES = 65536;
67
private CheckboxTreeViewer traceTypeViewer;
69
final ScanRunnable fRunnable = new ScanRunnable("Scan job"); //$NON-NLS-1$
70
final private BlockingQueue<TraceValidationHelper> fTracesToScan = new ArrayBlockingQueue<TraceValidationHelper>(MAX_TRACES);
71
private volatile boolean fCanRun = true;
73
// --------------------------------------------------------------------------------
74
// Constructor and destructor
75
// --------------------------------------------------------------------------------
78
* Import page that scans files, can be cancelled.
81
* The name of the page.
83
* The current selection
85
protected ImportTraceWizardScanPage(String name, IStructuredSelection selection) {
86
super(name, selection);
90
* Import page that scans files, can be cancelled
93
* The workbench reference.
95
* The current selection
97
public ImportTraceWizardScanPage(IWorkbench workbench, IStructuredSelection selection) {
98
super(workbench, selection);
102
public void dispose() {
104
fRunnable.done(Status.OK_STATUS);
113
public void createControl(Composite parent) {
114
super.createControl(parent);
115
final Composite control = (Composite) this.getControl();
116
setTitle(Messages.ImportTraceWizardScanPageTitle);
117
traceTypeViewer = new CheckboxTreeViewer(control, SWT.CHECK);
118
traceTypeViewer.setContentProvider(getBatchWizard().getScannedTraces());
119
traceTypeViewer.getTree().setHeaderVisible(true);
120
traceTypeViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
121
traceTypeViewer.setInput(getBatchWizard().getScannedTraces());
122
traceTypeViewer.addCheckStateListener(new ImportTraceCheckStateListener());
124
TreeViewerFocusCellManager focusCellManager = new TreeViewerFocusCellManager(traceTypeViewer, new FocusCellOwnerDrawHighlighter(traceTypeViewer));
125
ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(traceTypeViewer) {
127
TreeViewerEditor.create(traceTypeViewer, focusCellManager, actSupport, ColumnViewerEditor.TABBING_HORIZONTAL
128
| ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR
129
| ColumnViewerEditor.TABBING_VERTICAL | ColumnViewerEditor.KEYBOARD_ACTIVATION);
131
final TextCellEditor textCellEditor = new TextCellEditor(traceTypeViewer.getTree());
132
// --------------------
134
// --------------------
135
TreeViewerColumn column = new TreeViewerColumn(traceTypeViewer, SWT.NONE);
136
column.getColumn().setWidth(COL_WIDTH);
137
column.getColumn().setText(Messages.ImportTraceWizardTraceDisplayName);
138
column.setLabelProvider(new FirstColumnLabelProvider());
139
column.setEditingSupport(new ColumnEditorSupport(traceTypeViewer, textCellEditor));
141
// --------------------
143
// --------------------
145
column = new TreeViewerColumn(traceTypeViewer, SWT.NONE);
146
column.getColumn().setWidth(500);
147
column.getColumn().setText(Messages.ImportTraceWizardImportCaption);
148
column.setLabelProvider(new ColumnLabelProvider() {
150
public String getText(Object element) {
151
if (element instanceof FileAndName) {
152
FileAndName elem = (FileAndName) element;
153
return elem.getFile().getPath();
158
// --------------------
160
// --------------------
162
column = new TreeViewerColumn(traceTypeViewer, SWT.NONE);
164
column.getColumn().setWidth(80);
165
column.getColumn().setText(Messages.ImportTraceWizardScanPageSize);
166
column.getColumn().setAlignment(SWT.RIGHT);
167
column.setLabelProvider(new ColumnLabelProvider() {
170
public String getText(Object element) {
171
if (element instanceof FileAndName) {
173
FileAndName elem = (FileAndName) element;
174
long len = recurseSize(elem.getFile());
176
double sizeb10 = Math.log10(len);
177
DecimalFormat df = new DecimalFormat();
178
df.setMaximumFractionDigits(2);
179
df.setMinimumFractionDigits(0);
181
final double tbSize = len / 1024.0 / 1024 / 1024 / 1024;
182
return df.format(tbSize) + Messages.ImportTraceWizardScanPageTerabyte;
185
final double gbSize = len / 1024.0 / 1024 / 1024;
186
return df.format(gbSize) + Messages.ImportTraceWizardScanPageGigabyte;
189
final double mbSize = len / 1024.0 / 1024;
190
return df.format(mbSize) + Messages.ImportTraceWizardScanPageMegabyte;
193
final double kbSize = len / 1024.0;
194
return df.format(kbSize) + Messages.ImportTraceWizardScanPageKilobyte;
197
return Long.toString(len) + Messages.ImportTraceWizardScanPagebyte;
203
private long recurseSize(File file) {
204
if (file.isFile() && file.canRead()) {
205
return file.length();
208
if (file.exists() && file.isDirectory() && file.canRead()) {
209
final File[] listFiles = file.listFiles();
210
if (listFiles != null) {
211
for (File child : listFiles) {
212
if (child.isFile() && child.canRead()) {
213
size += child.length();
214
} else if (child.isDirectory()) {
215
size += recurseSize(child);
217
Activator.getDefault().logError("Unknown \"file\" type for " + child + ' ' + child.toString()); //$NON-NLS-1$
227
getBatchWizard().setTracesToScan(fTracesToScan);
228
getBatchWizard().setTraceFolder(fTargetFolder);
230
fRunnable.schedule();
231
setErrorMessage(Messages.ImportTraceWizardScanPageSelectAtleastOne);
234
private void init() {
235
Composite optionPane = (Composite) this.getControl();
237
optionPane.setLayout(new GridLayout());
238
optionPane.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true));
240
final Button fLink = new Button(optionPane, SWT.RADIO);
241
fLink.setText(Messages.ImportTraceWizardLinkTraces);
242
fLink.setSelection(true);
243
fLink.setLayoutData(new GridData());
245
final Button fCopy = new Button(optionPane, SWT.RADIO);
246
fCopy.setText(Messages.ImportTraceWizardCopyTraces);
247
fCopy.setLayoutData(new GridData());
249
final SelectionListener linkedListener = new RadioChooser(fLink);
251
fLink.addSelectionListener(linkedListener);
252
fCopy.addSelectionListener(linkedListener);
254
Button fOverwrite = new Button(optionPane, SWT.CHECK);
255
fOverwrite.setText(Messages.ImportTraceWizardOverwriteTraces);
256
fOverwrite.setLayoutData(new GridData());
257
fOverwrite.setSelection(true);
258
fOverwrite.addSelectionListener(new SelectionListener() {
261
public void widgetSelected(SelectionEvent e) {
262
getBatchWizard().setOverwrite(((Button) e.widget).getSelection());
266
public void widgetDefaultSelected(SelectionEvent e) {
275
private final class RadioChooser implements SelectionListener {
276
final private Button isLinked;
278
public RadioChooser(Button desiredButton) {
279
isLinked = desiredButton;
283
public void widgetSelected(SelectionEvent e) {
285
final Button widget = (Button) e.widget;
286
getBatchWizard().setLinked(widget.equals(isLinked));
290
public void widgetDefaultSelected(SelectionEvent e) {
295
private final class ColumnEditorSupport extends EditingSupport {
296
private final TextCellEditor textCellEditor;
298
private ColumnEditorSupport(ColumnViewer viewer, TextCellEditor textCellEditor) {
300
this.textCellEditor = textCellEditor;
304
protected boolean canEdit(Object element) {
305
return element instanceof FileAndName;
309
protected CellEditor getCellEditor(Object element) {
310
return textCellEditor;
314
protected Object getValue(Object element) {
315
if (element instanceof FileAndName) {
316
return ((FileAndName) element).getName();
322
protected void setValue(Object element, Object value) {
323
FileAndName fan = (FileAndName) element;
324
fan.setName((String) value);
325
getBatchWizard().updateConflicts();
326
traceTypeViewer.update(element, null);
327
traceTypeViewer.refresh();
331
private final class FirstColumnLabelProvider extends ColumnLabelProvider {
335
public Image getImage(Object element) {
336
if (element instanceof FileAndName) {
337
final FileAndName fan = (FileAndName) element;
338
if (fan.isConflictingName()) {
339
if (fConflict == null) {
340
fConflict = Activator.getDefault().getImageFromImageRegistry(ITmfImageConstants.IMG_UI_CONFLICT);
349
public String getText(Object element) {
350
if (element instanceof FileAndName) {
351
FileAndName elem = (FileAndName) element;
352
return elem.getName();
354
if (element instanceof String) {
355
return (String) element;
361
private final class ImportTraceCheckStateListener implements ICheckStateListener {
363
public void checkStateChanged(CheckStateChangedEvent event) {
364
final CheckboxTreeViewer tv = (CheckboxTreeViewer)
366
if (event.getElement() instanceof FileAndName) {
367
final FileAndName element = (FileAndName) event.getElement();
368
if (event.getChecked()) {
369
getBatchWizard().addFileToImport(element);
370
traceTypeViewer.update(element, null);
373
getBatchWizard().removeFileToImport(element);
374
traceTypeViewer.update(element, null);
376
maintainCheckIntegrity(tv, element);
378
if (event.getElement() instanceof String) {
380
tv.setSubtreeChecked(event.getElement(), event.getChecked());
381
final Object[] children =
382
getBatchWizard().getScannedTraces().getChildren(event.getElement());
383
if (event.getChecked()) {
384
for (int i = 0; i < children.length; i++) {
385
final FileAndName element = (FileAndName) children[i];
386
getBatchWizard().addFileToImport(element);
387
traceTypeViewer.update(children[i], null);
391
for (int i = 0; i < children.length; i++) {
392
getBatchWizard().removeFileToImport((FileAndName) children[i]);
398
getBatchWizard().updateConflicts();
399
if (getBatchWizard().hasConflicts()) {
400
setErrorMessage(Messages.ImportTraceWizardScanPageRenameError);
401
} else if (!getBatchWizard().hasTracesToImport()) {
402
setErrorMessage(Messages.ImportTraceWizardScanPageSelectAtleastOne);
404
setErrorMessage(null);
406
getWizard().getContainer().updateButtons();
407
traceTypeViewer.update(event.getElement(), null);
410
private void maintainCheckIntegrity(final CheckboxTreeViewer viewer, final FileAndName element) {
411
final ImportTraceContentProvider scannedTraces = getBatchWizard().getScannedTraces();
412
String parentElement = (String) scannedTraces.getParent(element);
413
boolean allChecked = true;
414
final FileAndName[] siblings = scannedTraces.getSiblings(element);
415
if (siblings != null) {
416
for (FileAndName child : siblings) {
417
allChecked &= viewer.getChecked(child);
420
viewer.setChecked(parentElement, allChecked);
424
private final class ScanRunnable extends Job {
426
// monitor is stored here, starts as the main monitor but becomes a
428
private IProgressMonitor fMonitor;
430
public ScanRunnable(String name) {
432
this.setSystem(true);
435
private synchronized IProgressMonitor getMonitor() {
440
public IStatus run(IProgressMonitor monitor) {
442
* Set up phase, it is synchronous
445
final Control control = traceTypeViewer.getControl();
446
// please note the sync exec here is to allow us to set
447
control.getDisplay().syncExec(new Runnable() {
450
// monitor gets overwritten here so it's necessary to save
452
fMonitor = SubMonitor.convert(getMonitor());
453
getMonitor().setTaskName(Messages.ImportTraceWizardPageScanScanning + ' ');
454
((SubMonitor) getMonitor()).setWorkRemaining(IProgressMonitor.UNKNOWN);
458
* At this point we start calling async execs and updating the view.
459
* This is a good candidate to parallelise.
461
while (fCanRun == true) {
462
boolean updated = false;
464
if (fTracesToScan.isEmpty() && !control.isDisposed()) {
465
control.getDisplay().asyncExec(new Runnable() {
469
if (!control.isDisposed()) {
470
getMonitor().setTaskName(Messages.ImportTraceWizardPageScanScanning + ' ');
471
getMonitor().subTask(Messages.ImportTraceWizardPageScanDone);
472
ImportTraceWizardScanPage.this.setMessage(Messages.ImportTraceWizardPageScanScanning + ' ' + Messages.ImportTraceWizardPageScanDone);
478
final TraceValidationHelper traceToScan = fTracesToScan.take();
480
if (!getBatchWizard().hasScanned(traceToScan)) {
481
getBatchWizard().addResult(traceToScan, TmfTraceType.getInstance().validate(traceToScan));
485
* The following is to update the UI
487
validCombo = getBatchWizard().getResult(traceToScan);
489
// Synched on it's parent
491
getBatchWizard().getScannedTraces().addCandidate(traceToScan.getTraceType(), new File(traceToScan.getTraceToScan()));
494
final int scanned = getBatchWizard().getNumberOfResults();
495
final int total = scanned + fTracesToScan.size();
496
final int prevVal = (int) ((scanned - 1) * 100.0 / total);
497
final int curVal = (int) ((scanned) * 100.0 / total);
498
if (curVal != prevVal) {
502
* update the progress
505
if (!control.isDisposed()) {
506
control.getDisplay().asyncExec(new Runnable() {
509
if (!control.isDisposed()) {
510
getMonitor().setTaskName(Messages.ImportTraceWizardPageScanScanning + ' ');
511
getMonitor().subTask(traceToScan.getTraceToScan());
512
getMonitor().worked(1);
513
ImportTraceWizardScanPage.this.setMessage(Messages.ImportTraceWizardPageScanScanning + ' '
514
+ Integer.toString(curVal)
524
* here we update the table
526
final boolean editing = traceTypeViewer.isCellEditorActive();
527
if (updated && !editing) {
528
if (!control.isDisposed()) {
529
control.getDisplay().asyncExec(new Runnable() {
533
if (!control.isDisposed()) {
534
if (!traceTypeViewer.isCellEditorActive()) {
535
traceTypeViewer.refresh();
542
} catch (InterruptedException e) {
543
return new Status(IStatus.CANCEL, Activator.PLUGIN_ID, new String());
546
return Status.OK_STATUS;
551
* Refresh the view and the corresponding model.
553
public void refresh() {
554
final Control control = traceTypeViewer.getControl();
555
if (!control.isDisposed()) {
556
control.getDisplay().asyncExec(new Runnable() {
559
if (!control.isDisposed()) {
560
traceTypeViewer.refresh();