Merge change 3848 into donut
* changes: SDK Updater: Revamp ITaskMonitor to be able to create sub monitors.
This commit is contained in:
@@ -21,6 +21,8 @@ import com.android.prefs.AndroidLocation.AndroidLocationException;
|
||||
import com.android.sdkuilib.internal.repository.ISettingsPage;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Button;
|
||||
@@ -28,16 +30,11 @@ import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Group;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
@@ -45,18 +45,27 @@ public interface ITaskMonitor {
|
||||
/**
|
||||
* Sets the max value of the progress bar.
|
||||
* This method can be invoked from a non-UI thread.
|
||||
*
|
||||
* This method MUST be invoked once before using {@link #incProgress(int)} or
|
||||
* {@link #getProgress()} or {@link #createSubMonitor(int)}. Callers are
|
||||
* discouraged from using more than once -- implementations can either discard
|
||||
* the next calls or behave incoherently.
|
||||
*/
|
||||
public void setProgressMax(int max);
|
||||
|
||||
/**
|
||||
* Increments the current value of the progress bar.
|
||||
* This method can be invoked from a non-UI thread.
|
||||
*
|
||||
* Callers MUST use setProgressMax before using this method.
|
||||
*/
|
||||
public void incProgress(int delta);
|
||||
|
||||
/**
|
||||
* Returns the current value of the progress bar,
|
||||
* between 0 and up to {@link #setProgressMax(int)} - 1.
|
||||
*
|
||||
* Callers MUST use setProgressMax before using this method.
|
||||
*/
|
||||
public int getProgress();
|
||||
|
||||
@@ -66,4 +75,10 @@ public interface ITaskMonitor {
|
||||
* as possible.
|
||||
*/
|
||||
public boolean isCancelRequested();
|
||||
|
||||
/**
|
||||
* Creates a sub-monitor that will use up to tickCount on the progress bar.
|
||||
* tickCount must be 1 or more.
|
||||
*/
|
||||
public ITaskMonitor createSubMonitor(int tickCount);
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public class RepoSource implements IDescription {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of known packages found by the last call to {@link #load(ITaskFactory)}.
|
||||
* Returns the list of known packages found by the last call to {@link #load(ITaskMonitor)}.
|
||||
* This is null when the source hasn't been loaded yet.
|
||||
*/
|
||||
public Package[] getPackages() {
|
||||
@@ -77,7 +77,7 @@ public class RepoSource implements IDescription {
|
||||
|
||||
/**
|
||||
* Clear the internal packages list. After this call, {@link #getPackages()} will return
|
||||
* null till {@link #load(ITaskFactory)} is called.
|
||||
* null till {@link #load(ITaskMonitor)} is called.
|
||||
*/
|
||||
public void clearPackages() {
|
||||
mPackages = null;
|
||||
@@ -94,47 +94,43 @@ public class RepoSource implements IDescription {
|
||||
/**
|
||||
* Tries to fetch the repository index for the given URL.
|
||||
*/
|
||||
public void load(ITaskFactory taskFactory) {
|
||||
public void load(ITaskMonitor monitor) {
|
||||
|
||||
taskFactory.start("Init SDK Updater", new ITask() {
|
||||
public void run(ITaskMonitor monitor) {
|
||||
monitor.setProgressMax(4);
|
||||
monitor.setProgressMax(4);
|
||||
|
||||
setDefaultDescription();
|
||||
setDefaultDescription();
|
||||
|
||||
monitor.setDescription("Fetching %1$s", mUrl);
|
||||
monitor.incProgress(1);
|
||||
monitor.setDescription("Fetching %1$s", mUrl);
|
||||
monitor.incProgress(1);
|
||||
|
||||
String xml = fetchUrl(mUrl, monitor);
|
||||
String xml = fetchUrl(mUrl, monitor);
|
||||
|
||||
if (xml == null) {
|
||||
mDescription += String.format("\nFailed to fetch URL %1$s", mUrl);
|
||||
return;
|
||||
}
|
||||
if (xml == null) {
|
||||
mDescription += String.format("\nFailed to fetch URL %1$s", mUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.setDescription("Validate XML");
|
||||
monitor.incProgress(1);
|
||||
monitor.setDescription("Validate XML");
|
||||
monitor.incProgress(1);
|
||||
|
||||
if (!validateXml(xml, monitor)) {
|
||||
mDescription += String.format("\nFailed to validate XML at %1$s", mUrl);
|
||||
return;
|
||||
}
|
||||
if (!validateXml(xml, monitor)) {
|
||||
mDescription += String.format("\nFailed to validate XML at %1$s", mUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.setDescription("Parse XML");
|
||||
monitor.incProgress(1);
|
||||
parsePackages(xml, monitor);
|
||||
if (mPackages.length == 0) {
|
||||
mDescription += "\nNo packages found.";
|
||||
} else if (mPackages.length == 1) {
|
||||
mDescription += "\nOne package found.";
|
||||
} else {
|
||||
mDescription += String.format("\n%1$d packages found.", mPackages.length);
|
||||
}
|
||||
monitor.setDescription("Parse XML");
|
||||
monitor.incProgress(1);
|
||||
parsePackages(xml, monitor);
|
||||
if (mPackages.length == 0) {
|
||||
mDescription += "\nNo packages found.";
|
||||
} else if (mPackages.length == 1) {
|
||||
mDescription += "\nOne package found.";
|
||||
} else {
|
||||
mDescription += String.format("\n%1$d packages found.", mPackages.length);
|
||||
}
|
||||
|
||||
// done
|
||||
monitor.incProgress(1);
|
||||
}
|
||||
});
|
||||
// done
|
||||
monitor.incProgress(1);
|
||||
}
|
||||
|
||||
private void setDefaultDescription() {
|
||||
|
||||
@@ -320,15 +320,15 @@ final class ProgressDialog extends Dialog {
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the current value of the progress bar.
|
||||
* Sets the current value of the progress bar.
|
||||
* This method can be invoked from a non-UI thread.
|
||||
*/
|
||||
public void incProgress(final int delta) {
|
||||
public void setProgress(final int value) {
|
||||
if (!mDialogShell.isDisposed()) {
|
||||
mDialogShell.getDisplay().syncExec(new Runnable() {
|
||||
public void run() {
|
||||
if (!mProgressBar.isDisposed()) {
|
||||
mProgressBar.setSelection(mProgressBar.getSelection() + delta);
|
||||
mProgressBar.setSelection(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -28,8 +28,12 @@ import org.eclipse.swt.widgets.Shell;
|
||||
*/
|
||||
class ProgressTask implements ITaskMonitor {
|
||||
|
||||
private ProgressDialog mDialog;
|
||||
private static final double MAX_COUNT = 10000.0;
|
||||
|
||||
private final ProgressDialog mDialog;
|
||||
private boolean mAutomaticallyCloseOnTaskCompletion = true;
|
||||
private double mIncCoef = 0;
|
||||
private double mValue = 0;
|
||||
|
||||
|
||||
/**
|
||||
@@ -46,29 +50,39 @@ class ProgressTask implements ITaskMonitor {
|
||||
|
||||
/**
|
||||
* Sets the description in the current task dialog.
|
||||
* This method can be invoke from a non-UI thread.
|
||||
* This method can be invoked from a non-UI thread.
|
||||
*/
|
||||
public void setDescription(final String descriptionFormat, final Object...args) {
|
||||
public void setDescription(String descriptionFormat, Object...args) {
|
||||
mDialog.setDescription(descriptionFormat, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the description in the current task dialog.
|
||||
* This method can be invoke from a non-UI thread.
|
||||
* This method can be invoked from a non-UI thread.
|
||||
*/
|
||||
public void setResult(final String resultFormat, final Object...args) {
|
||||
public void setResult(String resultFormat, Object...args) {
|
||||
mAutomaticallyCloseOnTaskCompletion = false;
|
||||
mDialog.setResult(resultFormat, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the max value of the progress bar.
|
||||
* This method can be invoke from a non-UI thread.
|
||||
* This method can be invoked from a non-UI thread.
|
||||
*
|
||||
* Weird things will happen if setProgressMax is called multiple times
|
||||
* *after* {@link #incProgress(int)}: we don't try to adjust it on the
|
||||
* fly.
|
||||
*
|
||||
* @see ProgressBar#setMaximum(int)
|
||||
*/
|
||||
public void setProgressMax(final int max) {
|
||||
mDialog.setProgressMax(max);
|
||||
public void setProgressMax(int max) {
|
||||
assert max > 0;
|
||||
// Always set the dialog's progress max to 10k since it only handles
|
||||
// integers and we want to have a better inner granularity. Instead
|
||||
// we use the max to compute a coefficient for inc deltas.
|
||||
mDialog.setProgressMax((int) MAX_COUNT);
|
||||
mIncCoef = max > 0 ? MAX_COUNT / max : 0;
|
||||
assert mIncCoef > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,8 +90,15 @@ class ProgressTask implements ITaskMonitor {
|
||||
*
|
||||
* This method can be invoked from a non-UI thread.
|
||||
*/
|
||||
public void incProgress(final int delta) {
|
||||
mDialog.incProgress(delta);
|
||||
public void incProgress(int delta) {
|
||||
assert mIncCoef > 0;
|
||||
assert delta > 0;
|
||||
internalIncProgress(delta * mIncCoef);
|
||||
}
|
||||
|
||||
private void internalIncProgress(double realDelta) {
|
||||
mValue += realDelta;
|
||||
mDialog.setProgress((int)mValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,7 +108,8 @@ class ProgressTask implements ITaskMonitor {
|
||||
* This method can be invoked from a non-UI thread.
|
||||
*/
|
||||
public int getProgress() {
|
||||
return mDialog.getProgress();
|
||||
assert mIncCoef > 0;
|
||||
return mIncCoef > 0 ? (int)(mDialog.getProgress() / mIncCoef) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,4 +141,95 @@ class ProgressTask implements ITaskMonitor {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a sub-monitor that will use up to tickCount on the progress bar.
|
||||
* tickCount must be 1 or more.
|
||||
*/
|
||||
public ITaskMonitor createSubMonitor(int tickCount) {
|
||||
assert mIncCoef > 0;
|
||||
assert tickCount > 0;
|
||||
return new SubTaskMonitor(this, null, mValue, tickCount * mIncCoef);
|
||||
}
|
||||
|
||||
private interface ISubTaskMonitor extends ITaskMonitor {
|
||||
public void subIncProgress(double realDelta);
|
||||
}
|
||||
|
||||
private static class SubTaskMonitor implements ISubTaskMonitor {
|
||||
|
||||
private final ProgressTask mRoot;
|
||||
private final ISubTaskMonitor mParent;
|
||||
private final double mStart;
|
||||
private final double mSpan;
|
||||
private double mSubValue;
|
||||
private double mSubCoef;
|
||||
|
||||
/**
|
||||
* Creates a new sub task monitor which will work for the given range [start, start+span]
|
||||
* in its parent.
|
||||
*
|
||||
* @param root The ProgressTask root
|
||||
* @param parent The immediate parent. Can be the null or another sub task monitor.
|
||||
* @param start The start value in the root's coordinates
|
||||
* @param span The span value in the root's coordinates
|
||||
*/
|
||||
public SubTaskMonitor(ProgressTask root,
|
||||
ISubTaskMonitor parent,
|
||||
double start,
|
||||
double span) {
|
||||
mRoot = root;
|
||||
mParent = parent;
|
||||
mStart = start;
|
||||
mSpan = span;
|
||||
mSubValue = start;
|
||||
}
|
||||
|
||||
public boolean isCancelRequested() {
|
||||
return mRoot.isCancelRequested();
|
||||
}
|
||||
|
||||
public void setDescription(String descriptionFormat, Object... args) {
|
||||
mRoot.setDescription(descriptionFormat, args);
|
||||
}
|
||||
|
||||
public void setResult(String resultFormat, Object... args) {
|
||||
mRoot.setResult(resultFormat, args);
|
||||
}
|
||||
|
||||
public void setProgressMax(int max) {
|
||||
assert max > 0;
|
||||
mSubCoef = max > 0 ? mSpan / max : 0;
|
||||
assert mSubCoef > 0;
|
||||
}
|
||||
|
||||
public int getProgress() {
|
||||
assert mSubCoef > 0;
|
||||
return mSubCoef > 0 ? (int)((mSubValue - mStart) / mSubCoef) : 0;
|
||||
}
|
||||
|
||||
public void incProgress(int delta) {
|
||||
assert mSubCoef > 0;
|
||||
subIncProgress(delta * mSubCoef);
|
||||
}
|
||||
|
||||
public void subIncProgress(double realDelta) {
|
||||
mSubValue += realDelta;
|
||||
if (mParent != null) {
|
||||
mParent.subIncProgress(realDelta);
|
||||
} else {
|
||||
mRoot.internalIncProgress(realDelta);
|
||||
}
|
||||
}
|
||||
|
||||
public ITaskMonitor createSubMonitor(int tickCount) {
|
||||
assert mSubCoef > 0;
|
||||
assert tickCount > 0;
|
||||
return new SubTaskMonitor(mRoot,
|
||||
this,
|
||||
mSubValue,
|
||||
tickCount * mSubCoef);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ package com.android.sdkuilib.internal.repository;
|
||||
|
||||
import com.android.sdklib.internal.repository.Archive;
|
||||
import com.android.sdklib.internal.repository.IDescription;
|
||||
import com.android.sdklib.internal.repository.ITask;
|
||||
import com.android.sdklib.internal.repository.ITaskMonitor;
|
||||
|
||||
import org.eclipse.jface.viewers.CheckStateChangedEvent;
|
||||
import org.eclipse.jface.viewers.CheckboxTreeViewer;
|
||||
@@ -265,7 +267,7 @@ public class RemotePackagesPage extends Composite {
|
||||
|
||||
private void onRefreshSelected() {
|
||||
if (mUpdaterWindow != null) {
|
||||
mUpdaterWindow.refreshSources(false /*forceFetching*/);
|
||||
mUpdaterWindow.refreshSources(false /*forceFetching*/, null /*monitor*/);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ package com.android.sdkuilib.internal.repository;
|
||||
|
||||
import com.android.sdklib.internal.repository.Archive;
|
||||
import com.android.sdklib.internal.repository.IDescription;
|
||||
import com.android.sdklib.internal.repository.ITask;
|
||||
import com.android.sdklib.internal.repository.ITaskMonitor;
|
||||
import com.android.sdklib.internal.repository.Package;
|
||||
import com.android.sdklib.internal.repository.RepoSource;
|
||||
import com.android.sdklib.internal.repository.RepoSources;
|
||||
@@ -110,11 +112,17 @@ class RepoSourcesAdapter {
|
||||
return ((RepoSourcesAdapter) parentElement).mRepoSources.getSources().toArray();
|
||||
|
||||
} else if (parentElement instanceof RepoSource) {
|
||||
RepoSource source = (RepoSource) parentElement;
|
||||
final RepoSource source = (RepoSource) parentElement;
|
||||
Package[] packages = source.getPackages();
|
||||
|
||||
if (packages == null) {
|
||||
source.load(mInput.mRepoSources.getTaskFactory());
|
||||
|
||||
mInput.mRepoSources.getTaskFactory().start("Loading Source", new ITask() {
|
||||
public void run(ITaskMonitor monitor) {
|
||||
source.load(monitor);
|
||||
}
|
||||
});
|
||||
|
||||
packages = source.getPackages();
|
||||
}
|
||||
if (packages != null) {
|
||||
|
||||
@@ -407,17 +407,14 @@ public class UpdaterWindowImpl {
|
||||
}
|
||||
|
||||
public void updateAll() {
|
||||
refreshSources(true);
|
||||
mTaskFactory.start("Update Archives", new ITask() {
|
||||
public void run(ITaskMonitor monitor) {
|
||||
monitor.setProgressMax(3);
|
||||
|
||||
// TODO have refreshSources reuse the current progress task
|
||||
// mTaskFactory.start("Update Archives", new ITask() {
|
||||
// public void run(ITaskMonitor monitor) {
|
||||
// monitor.setProgressMax(3);
|
||||
//
|
||||
// monitor.setDescription("Refresh sources");
|
||||
// refreshSources(true);
|
||||
// }
|
||||
// });
|
||||
monitor.setDescription("Refresh sources");
|
||||
refreshSources(true, monitor.createSubMonitor(1));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -426,32 +423,26 @@ public class UpdaterWindowImpl {
|
||||
* @param forceFetching When true, load sources that haven't been loaded yet. When
|
||||
* false, only refresh sources that have been loaded yet.
|
||||
*/
|
||||
public void refreshSources(final boolean forceFetching) {
|
||||
ArrayList<RepoSource> sources = mUpdaterData.getSources().getSources();
|
||||
for (RepoSource source : sources) {
|
||||
if (forceFetching || source.getPackages() != null) {
|
||||
source.load(mTaskFactory);
|
||||
public void refreshSources(final boolean forceFetching, ITaskMonitor monitor) {
|
||||
ITask task = new ITask() {
|
||||
public void run(ITaskMonitor monitor) {
|
||||
ArrayList<RepoSource> sources = mUpdaterData.getSources().getSources();
|
||||
monitor.setProgressMax(sources.size());
|
||||
for (RepoSource source : sources) {
|
||||
if (forceFetching || source.getPackages() != null) {
|
||||
source.load(monitor.createSubMonitor(1));
|
||||
}
|
||||
monitor.incProgress(1);
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (monitor != null) {
|
||||
task.run(monitor);
|
||||
} else {
|
||||
mTaskFactory.start("Refresh Sources", task);
|
||||
}
|
||||
|
||||
// TODO have source.load reuse the current progress task
|
||||
// mTaskFactory.start("Refresh sources", new ITask() {
|
||||
// public void run(ITaskMonitor monitor) {
|
||||
// ArrayList<RepoSource> sources = mUpdaterData.getSources().getSources();
|
||||
// monitor.setProgressMax(sources.size());
|
||||
//
|
||||
// for (RepoSource source : sources) {
|
||||
// if (forceFetching || source.getPackages() != null) {
|
||||
// monitor.setDescription(String.format("Refresh %1$s",
|
||||
// source.getShortDescription()));
|
||||
// source.load(mTaskFactory);
|
||||
// }
|
||||
// monitor.incProgress(1);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
}
|
||||
|
||||
// End of hiding from SWT Designer
|
||||
|
||||
Reference in New Issue
Block a user