package org.esa.snap.rcp.util;
import com.bc.ceres.core.Assert;
import com.bc.ceres.core.ProgressMonitor;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory;
import org.openide.util.Cancellable;
/**
* A progress monitor that notifies a {@code ProgressHandle} instance (of the NetBeans Progress API).
* <p>
* Use case 1:
* <pre>
* ProgressHandleMonitor pm = ProgressHandleMonitor.create("Training");
* Runnable operation = () -> {
* pm.beginTask("Classifier training...", 100);
* try {
* session.startTraining(queryPatches, pm);
* } catch (Exception e) {
* SnapApp.getDefault().handleError("Failed to train classifier", e);
* } finally {
* pm.done();
* }
* };
* ProgressUtils.runOffEventThreadWithProgressDialog(operation, "Extracting Features", pm.getProgressHandle(), true, 50, 1000);
* </pre>
*
* <p>
* Use case 2:
* <pre>
* RequestProcessor.getDefault().post(() -> {
* ProgressHandle handle = ProgressHandleFactory.createHandle("Performing time consuming task");
* ProgressMonitor pm = new ProgressHandleMonitor(handle);
* performTimeConsumingTask(pm);
* });
* </pre>
*
* @author Norman Fomferra
* @since SNAP 2
*/
public class ProgressHandleMonitor implements ProgressMonitor, Cancellable {
private static final int F = 100;
private ProgressHandle progressHandle;
private Cancellable cancellable;
private boolean canceled;
private int totalWorkUnits;
private int currentWorkUnits;
private double currentWorkUnitsRational;
public static ProgressHandleMonitor create(String displayName) {
return create(displayName, null);
}
public static ProgressHandleMonitor create(String displayName, Cancellable cancellable) {
ProgressHandleMonitor progressMonitor = new ProgressHandleMonitor(cancellable);
ProgressHandle progressHandle = ProgressHandleFactory.createHandle(displayName, progressMonitor);
progressMonitor.setProgressHandle(progressHandle);
return progressMonitor;
}
public ProgressHandleMonitor(ProgressHandle progressHandle) {
Assert.notNull(progressHandle);
this.progressHandle = progressHandle;
}
private ProgressHandleMonitor(Cancellable cancellable) {
this.cancellable = cancellable;
}
/**
* @return The progress handle.
*/
public ProgressHandle getProgressHandle() {
return progressHandle;
}
/**
* @param progressHandle The progress handle.
*/
public void setProgressHandle(ProgressHandle progressHandle) {
Assert.notNull(progressHandle);
this.progressHandle = progressHandle;
}
@Override
public void beginTask(String taskName, int totalWork) {
if(totalWork < 0) {
this.totalWorkUnits = 0;
}else {
this.totalWorkUnits = F * totalWork;
}
this.currentWorkUnits = 0;
this.currentWorkUnitsRational = 0.0;
if (progressHandle == null) {
progressHandle = ProgressHandleFactory.createHandle(taskName, this);
progressHandle.start(this.totalWorkUnits);
} else {
try {
progressHandle.start(this.totalWorkUnits);
} catch (java.lang.IllegalStateException e) {
// if already started, use fall back
progressHandle.switchToDeterminate(this.totalWorkUnits);
}
progressHandle.setDisplayName(taskName);
}
}
@Override
public void done() {
Assert.notNull(progressHandle);
progressHandle.finish();
}
@Override
public void internalWorked(double work) {
currentWorkUnitsRational += F * work;
int i = (int) currentWorkUnitsRational;
if (i > currentWorkUnits) {
currentWorkUnits = i;
progressHandle.progress(currentWorkUnits);
}
}
@Override
public boolean isCanceled() {
return canceled;
}
@Override
public void setCanceled(boolean canceled) {
this.canceled = canceled;
}
@Override
public void setTaskName(String taskName) {
Assert.notNull(progressHandle);
progressHandle.setDisplayName(taskName);
}
@Override
public void setSubTaskName(String subTaskName) {
Assert.notNull(progressHandle);
progressHandle.progress(subTaskName);
}
@Override
public void worked(int work) {
internalWorked(work);
}
@Override
public boolean cancel() {
if (cancellable != null) {
setCanceled(cancellable.cancel());
} else {
setCanceled(true);
}
return isCanceled();
}
}