mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
View utils:
Progress bar interface Progress bar base class Progress bar embedded class (extends base)
This commit is contained in:
4
.gitattributes
vendored
4
.gitattributes
vendored
@@ -9797,6 +9797,10 @@ src/main/java/forge/view/swing/Main.java svneol=native#text/plain
|
|||||||
src/main/java/forge/view/swing/OldGuiNewGame.java svneol=native#text/plain
|
src/main/java/forge/view/swing/OldGuiNewGame.java svneol=native#text/plain
|
||||||
src/main/java/forge/view/swing/SplashFrame.java -text
|
src/main/java/forge/view/swing/SplashFrame.java -text
|
||||||
src/main/java/forge/view/swing/package-info.java svneol=native#text/plain
|
src/main/java/forge/view/swing/package-info.java svneol=native#text/plain
|
||||||
|
src/main/java/forge/view/util/ProgressBar_Base.java -text
|
||||||
|
src/main/java/forge/view/util/ProgressBar_Embedded.java -text
|
||||||
|
src/main/java/forge/view/util/ProgressBar_Interface.java -text
|
||||||
|
src/main/java/forge/view/util/package-info.java -text
|
||||||
src/main/java/net/slightlymagic/braids/LICENSE.txt svneol=native#text/plain
|
src/main/java/net/slightlymagic/braids/LICENSE.txt svneol=native#text/plain
|
||||||
src/main/java/net/slightlymagic/braids/util/ClumsyRunnable.java svneol=native#text/plain
|
src/main/java/net/slightlymagic/braids/util/ClumsyRunnable.java svneol=native#text/plain
|
||||||
src/main/java/net/slightlymagic/braids/util/ImmutableIterableFrom.java svneol=native#text/plain
|
src/main/java/net/slightlymagic/braids/util/ImmutableIterableFrom.java svneol=native#text/plain
|
||||||
|
|||||||
575
src/main/java/forge/view/util/ProgressBar_Base.java
Normal file
575
src/main/java/forge/view/util/ProgressBar_Base.java
Normal file
@@ -0,0 +1,575 @@
|
|||||||
|
package forge.view.util;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import javax.swing.JProgressBar;
|
||||||
|
import com.esotericsoftware.minlog.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This base class also acts as a "null" progress monitor; it doesn't display
|
||||||
|
* anything when updated.
|
||||||
|
*
|
||||||
|
* Absolute times are measured in seconds, in congruence with ProgressMonitor.
|
||||||
|
*
|
||||||
|
* @see forge.view.util.ProgressBar_Interface
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class ProgressBar_Base extends JProgressBar implements ProgressBar_Interface {
|
||||||
|
private int numPhases;
|
||||||
|
private int currentPhase;
|
||||||
|
private long totalUnitsThisPhase;
|
||||||
|
private long unitsCompletedSoFarThisPhase;
|
||||||
|
private float minUIUpdateIntervalSec;
|
||||||
|
private long lastUIUpdateTime;
|
||||||
|
private long phaseOneStartTime;
|
||||||
|
private long currentPhaseStartTime;
|
||||||
|
private float currentPhaseExponent;
|
||||||
|
private long[] phaseDurationHistorySecList;
|
||||||
|
private float[] phaseWeights;
|
||||||
|
private Hashtable<Integer,String> phaseNames;
|
||||||
|
|
||||||
|
public final int SECONDS_PER_MINUTE = 60;
|
||||||
|
public final int SECONDS_PER_HOUR = 60 * SECONDS_PER_MINUTE;
|
||||||
|
public final int SECONDS_PER_DAY = 24 * SECONDS_PER_HOUR;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience for
|
||||||
|
* ProgressBar_Base(numPhases, totalUnitsFirstPhase, 2.0f, null).
|
||||||
|
*
|
||||||
|
* @see #ProgressBar_Base(int,long,float,float[])
|
||||||
|
*/
|
||||||
|
public ProgressBar_Base(int numPhases, long totalUnitsFirstPhase) {
|
||||||
|
this(numPhases, totalUnitsFirstPhase, 2.0f, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience for
|
||||||
|
* ProgressBar_Base(numPhases, totalUnitsFirstPhase,
|
||||||
|
* minUIUpdateIntervalSec, null).
|
||||||
|
*
|
||||||
|
* @see #ProgressBar_Base(int,long,float,float[])
|
||||||
|
*/
|
||||||
|
public ProgressBar_Base(int numPhases, long totalUnitsFirstPhase,
|
||||||
|
float minUIUpdateIntervalSec)
|
||||||
|
{
|
||||||
|
this(numPhases, totalUnitsFirstPhase, minUIUpdateIntervalSec, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes fields and starts the timers.
|
||||||
|
*
|
||||||
|
* @param numPhases the total number of phases we will monitor
|
||||||
|
*
|
||||||
|
* @param totalUnitsFirstPhase how many units to expect in phase 1
|
||||||
|
*
|
||||||
|
* @param minUIUpdateIntervalSec the approximate interval at which we
|
||||||
|
* update the user interface, in seconds
|
||||||
|
*
|
||||||
|
* @param phaseWeights may be null; if not null, this indicates the
|
||||||
|
* relative weight of each phase in terms of time to complete all phases.
|
||||||
|
* Index 0 of this array indicates phase 1's weight, index 1 indicates
|
||||||
|
* the weight of phase 2, and so on. If null, all phases are considered to
|
||||||
|
* take an equal amount of time to complete, which is equivalent to setting
|
||||||
|
* all phase weights to 1.0f. For example, if there are two phases, and
|
||||||
|
* the phase weights are set to {2.0f, 1.0f}, then the methods that compute
|
||||||
|
* the final ETA (Estimated Time of Arrival or completion) will assume that
|
||||||
|
* phase 2 takes half as long as phase 1. In other words, the operation
|
||||||
|
* will spend 67% of its time in phase 1, and 33% of its time in phase 2.
|
||||||
|
*/
|
||||||
|
public ProgressBar_Base(int numPhases, long totalUnitsFirstPhase,
|
||||||
|
float minUIUpdateIntervalSec, float[] phaseWeights)
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.numPhases = numPhases;
|
||||||
|
this.currentPhase = 1;
|
||||||
|
this.unitsCompletedSoFarThisPhase = 0L;
|
||||||
|
this.minUIUpdateIntervalSec = minUIUpdateIntervalSec;
|
||||||
|
this.lastUIUpdateTime = 0L;
|
||||||
|
this.phaseOneStartTime = new Date().getTime()/1000;
|
||||||
|
this.currentPhaseStartTime = this.phaseOneStartTime;
|
||||||
|
this.currentPhaseExponent = 1;
|
||||||
|
this.phaseDurationHistorySecList = new long[numPhases];
|
||||||
|
|
||||||
|
if (phaseWeights == null) {
|
||||||
|
this.phaseWeights = new float[numPhases];
|
||||||
|
for (int ix = 0; ix < numPhases; ix++) {
|
||||||
|
this.phaseWeights[ix] = 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.phaseWeights = phaseWeights;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phaseNames == null) {
|
||||||
|
this.phaseNames = new Hashtable<Integer, String>();
|
||||||
|
for(int i=1;i<=numPhases;i++) {
|
||||||
|
this.phaseNames.put(i, "Phase "+i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setTotalUnitsThisPhase(totalUnitsFirstPhase);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does nothing.
|
||||||
|
*/
|
||||||
|
public void dispose() {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#getNumPhases()
|
||||||
|
*/
|
||||||
|
public int getNumPhases() {
|
||||||
|
return this.numPhases;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#getMinUpdateIntervalSec()
|
||||||
|
*/
|
||||||
|
public float getMinUpdateIntervalSec() {
|
||||||
|
return this.minUIUpdateIntervalSec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#getCurrentPhase()
|
||||||
|
*/
|
||||||
|
public int getCurrentPhase() {
|
||||||
|
return this.currentPhase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#getUnitsCompletedSoFarThisPhase()
|
||||||
|
*/
|
||||||
|
public long getUnitsCompletedSoFarThisPhase() {
|
||||||
|
return this.unitsCompletedSoFarThisPhase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#getTotalUnitsThisPhase()
|
||||||
|
*/
|
||||||
|
public long getTotalUnitsThisPhase() {
|
||||||
|
return this.totalUnitsThisPhase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#getLastUIUpdateTime()
|
||||||
|
*/
|
||||||
|
public long getLastUIUpdateTime() {
|
||||||
|
return this.lastUIUpdateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#getPhaseOneStartTime()
|
||||||
|
*/
|
||||||
|
public long getPhaseOneStartTime() {
|
||||||
|
return this.phaseOneStartTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#getCurrentPhaseStartTime()
|
||||||
|
*/
|
||||||
|
public long getCurrentPhaseStartTime() {
|
||||||
|
return this.currentPhaseStartTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#setMinUpdateIntervalSec(float)
|
||||||
|
*/
|
||||||
|
public void setMinUpdateIntervalSec(float value) {
|
||||||
|
this.minUIUpdateIntervalSec = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#setTotalUnitsThisPhase(long)
|
||||||
|
*/
|
||||||
|
public void setTotalUnitsThisPhase(long value) {
|
||||||
|
// DS - why is this called twice?
|
||||||
|
if (value > Integer.MAX_VALUE) {
|
||||||
|
throw new IllegalArgumentException("numUnits must be <= " + Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.totalUnitsThisPhase = value;
|
||||||
|
|
||||||
|
// (Temporary solution until I know a better way)
|
||||||
|
this.setProgressRange(0,(int)value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>setProgressRange.</p>
|
||||||
|
*
|
||||||
|
* @param min an int.
|
||||||
|
* @param max an int.
|
||||||
|
*/
|
||||||
|
public void setProgressRange(int min, int max) {
|
||||||
|
this.setMinimum(min);
|
||||||
|
this.setMaximum(max);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#getPercentCompleteOfThisPhaseAsString()
|
||||||
|
*/
|
||||||
|
public String getPercentCompleteOfThisPhaseAsString() {
|
||||||
|
|
||||||
|
Float percent = getPercentCompleteOfThisPhaseAsFloat();
|
||||||
|
|
||||||
|
if (percent != null) {
|
||||||
|
return Integer.toString((int) (float) percent);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "??";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#getTotalPercentCompleteAsString()
|
||||||
|
*/
|
||||||
|
public String getTotalPercentCompleteAsString() {
|
||||||
|
Float percent = getTotalPercentCompleteAsFloat();
|
||||||
|
|
||||||
|
if (percent == null) {
|
||||||
|
return "??";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Integer.toString((int) (float) percent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience for getRelativeETAAsString(false), meaning to compute the
|
||||||
|
* value for the end of the last phase.
|
||||||
|
*
|
||||||
|
* @see #getRelativeETAAsString(boolean)
|
||||||
|
*/
|
||||||
|
public String getRelativeETAAsString() {
|
||||||
|
return getRelativeETAAsString(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#getRelativeETAAsString(boolean)
|
||||||
|
*/
|
||||||
|
public String getRelativeETAAsString(boolean thisPhaseOnly) {
|
||||||
|
|
||||||
|
Integer etaSec = getRelativeETASec(thisPhaseOnly);
|
||||||
|
|
||||||
|
if (etaSec == null) {
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
String result = "";
|
||||||
|
if (etaSec > SECONDS_PER_DAY) {
|
||||||
|
result += Integer.toString(etaSec / SECONDS_PER_DAY);
|
||||||
|
result += " da, ";
|
||||||
|
etaSec %= SECONDS_PER_DAY; // Shave off the portion recorded.
|
||||||
|
}
|
||||||
|
if (result.length() > 0 || etaSec > SECONDS_PER_HOUR) {
|
||||||
|
result += Integer.toString(etaSec / SECONDS_PER_HOUR);
|
||||||
|
result += " hr, ";
|
||||||
|
etaSec %= SECONDS_PER_HOUR; // Shave off the portion recorded.
|
||||||
|
}
|
||||||
|
if (result.length() > 0 || etaSec > SECONDS_PER_MINUTE) {
|
||||||
|
result += Integer.toString(etaSec / SECONDS_PER_MINUTE);
|
||||||
|
result += " min, ";
|
||||||
|
etaSec %= SECONDS_PER_MINUTE; // Shave off the portion recorded.
|
||||||
|
}
|
||||||
|
|
||||||
|
result += Integer.toString(etaSec);
|
||||||
|
result += " sec";
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience for getAbsoluteETAAsLocalTimeString(false), meaning to
|
||||||
|
* compute the value for the end of the last phase.
|
||||||
|
*
|
||||||
|
* @see #getAbsoluteETAAsLocalTimeString(boolean)
|
||||||
|
*/
|
||||||
|
public String getAbsoluteETAAsLocalTimeString() {
|
||||||
|
return getAbsoluteETAAsLocalTimeString(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#getAbsoluteETAAsLocalTimeString(boolean)
|
||||||
|
*/
|
||||||
|
public String getAbsoluteETAAsLocalTimeString(boolean thisPhaseOnly) {
|
||||||
|
Long etaTime = getAbsoluteETATime(thisPhaseOnly);
|
||||||
|
|
||||||
|
if (etaTime == null) {
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
return (new Date(etaTime*1000).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#incrementUnitsCompletedThisPhase(long)
|
||||||
|
*/
|
||||||
|
public void incrementUnitsCompletedThisPhase(long numUnits) {
|
||||||
|
this.unitsCompletedSoFarThisPhase += numUnits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void increment() {
|
||||||
|
setValue(getValue() + 1);
|
||||||
|
if (getValue() % 10 == 0) { repaint(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses must call this immediately after updating the UI, to
|
||||||
|
* preserve the integrity of the shouldUpdateUI method.
|
||||||
|
*/
|
||||||
|
protected void justUpdatedUI() {
|
||||||
|
this.lastUIUpdateTime = new Date().getTime()/1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#shouldUpdateUI()
|
||||||
|
*/
|
||||||
|
public boolean shouldUpdateUI() {
|
||||||
|
|
||||||
|
doctorStartTimes();
|
||||||
|
long nowTime = (new Date().getTime()/1000);
|
||||||
|
|
||||||
|
if (nowTime - this.lastUIUpdateTime >= this.minUIUpdateIntervalSec ||
|
||||||
|
(this.getUnitsCompletedSoFarThisPhase() ==
|
||||||
|
this.getTotalUnitsThisPhase()))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#markCurrentPhaseAsComplete(long)
|
||||||
|
*/
|
||||||
|
public void markCurrentPhaseAsComplete(long totalUnitsNextPhase) {
|
||||||
|
|
||||||
|
if ((this.currentPhase > this.numPhases)) {
|
||||||
|
String message = "The phase just completed (";
|
||||||
|
message += this.currentPhase;
|
||||||
|
message += ") is greater than the total number ";
|
||||||
|
message += "of anticipated phases (";
|
||||||
|
message += this.numPhases;
|
||||||
|
message += "); the latter is probably incorrect.";
|
||||||
|
|
||||||
|
Log.warn(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentPhase += 1;
|
||||||
|
this.unitsCompletedSoFarThisPhase = 0;
|
||||||
|
setTotalUnitsThisPhase(totalUnitsNextPhase);
|
||||||
|
this.currentPhaseExponent = 1;
|
||||||
|
|
||||||
|
long nowTime = (new Date().getTime()/1000);
|
||||||
|
long durationOfThisPhaseSec = nowTime - this.currentPhaseStartTime;
|
||||||
|
if (durationOfThisPhaseSec < 0) {
|
||||||
|
durationOfThisPhaseSec = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 <= currentPhase-2 && currentPhase-2 < phaseDurationHistorySecList.length) {
|
||||||
|
this.phaseDurationHistorySecList[currentPhase-2] = durationOfThisPhaseSec;
|
||||||
|
}
|
||||||
|
this.currentPhaseStartTime = nowTime;
|
||||||
|
|
||||||
|
if (this.currentPhase >= this.numPhases) {
|
||||||
|
String message = "Actual individual phase durations: [";
|
||||||
|
for (int ix = 0 ; ix < phaseDurationHistorySecList.length ; ix++) {
|
||||||
|
message += phaseDurationHistorySecList[ix] + ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.info(message + ']');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#sendMessage(java.lang.String)
|
||||||
|
*/
|
||||||
|
public void sendMessage(String message) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#setCurrentPhaseAsExponential(float)
|
||||||
|
*/
|
||||||
|
public void setCurrentPhaseAsExponential(float value) {
|
||||||
|
this.currentPhaseExponent = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Interface#getCurrentPhaseExponent()
|
||||||
|
*/
|
||||||
|
public float getCurrentPhaseExponent() {
|
||||||
|
return this.currentPhaseExponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the name of a phase in the process (e.g. "Phase 1" becomes "Loading XML")
|
||||||
|
*/
|
||||||
|
public void setPhaseName(int i, String name) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPhaseName(int i) {
|
||||||
|
return phaseNames.get(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return number in range [0.0, 100.0] or null.
|
||||||
|
*/
|
||||||
|
protected Float getPercentCompleteOfThisPhaseAsFloat() {
|
||||||
|
if (this.totalUnitsThisPhase < 1 ||
|
||||||
|
this.unitsCompletedSoFarThisPhase > this.totalUnitsThisPhase) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
float ratio = ((float) (this.unitsCompletedSoFarThisPhase)) /
|
||||||
|
((float) this.totalUnitsThisPhase);
|
||||||
|
|
||||||
|
ratio = (float) Math.pow(ratio, this.getCurrentPhaseExponent());
|
||||||
|
|
||||||
|
return (ratio * 100.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns number in range [0.0, 100.0] or null.
|
||||||
|
*/
|
||||||
|
protected Float getTotalPercentCompleteAsFloat() {
|
||||||
|
long totalPoints = 0;
|
||||||
|
for (float weight : this.phaseWeights) {
|
||||||
|
totalPoints += weight * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
Float percentThisPhase = getPercentCompleteOfThisPhaseAsFloat();
|
||||||
|
|
||||||
|
if (percentThisPhase == null) {
|
||||||
|
// If we can't know the percentage for this phase, use a
|
||||||
|
// conservative estimate.
|
||||||
|
percentThisPhase = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
long pointsSoFar = 0;
|
||||||
|
for (int ix = 0; ix < this.currentPhase-1; ix++) {
|
||||||
|
// We get full points for (all the phases completed prior to this one.
|
||||||
|
pointsSoFar += phaseWeights[ix] * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
pointsSoFar += percentThisPhase * this.phaseWeights[this.currentPhase-1];
|
||||||
|
|
||||||
|
if (totalPoints <= 0.0 || pointsSoFar > totalPoints) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (100.0f * pointsSoFar) / totalPoints;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience for getRelativeETASec(false), meaning to compute the value
|
||||||
|
* for the end of the last phase.
|
||||||
|
*
|
||||||
|
* @see #getRelativeETASec(boolean)
|
||||||
|
*/
|
||||||
|
protected Integer getRelativeETASec() {
|
||||||
|
return getRelativeETASec(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return estimated seconds until completion for either thisPhaseOnly
|
||||||
|
* or for the entire operation. May return null if unknown.
|
||||||
|
*/
|
||||||
|
protected Integer getRelativeETASec(boolean thisPhaseOnly) {
|
||||||
|
|
||||||
|
Long absoluteETATime = getAbsoluteETATime(thisPhaseOnly);
|
||||||
|
if (absoluteETATime == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (int) (absoluteETATime - (new Date().getTime()/1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience for getAbsoluteETATime(false), meaning to compute the value
|
||||||
|
* for the end of all phases.
|
||||||
|
*
|
||||||
|
* @see #getAbsoluteETATime(boolean)
|
||||||
|
*/
|
||||||
|
protected Long getAbsoluteETATime() {
|
||||||
|
return getAbsoluteETATime(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the estimated time (in absolute seconds) at which thisPhaseOnly
|
||||||
|
* or the entire operation will be completed. May return null if (unknown.
|
||||||
|
*/
|
||||||
|
protected Long getAbsoluteETATime(boolean thisPhaseOnly) {
|
||||||
|
doctorStartTimes();
|
||||||
|
|
||||||
|
// If we're in the last phase, the overall ETA is the same as the ETA
|
||||||
|
// for (this particular phase.
|
||||||
|
if (this.getCurrentPhase() >= this.getNumPhases()) {
|
||||||
|
thisPhaseOnly = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Float percentDone = null;
|
||||||
|
long startTime = 0L;
|
||||||
|
|
||||||
|
if (thisPhaseOnly) {
|
||||||
|
percentDone = getPercentCompleteOfThisPhaseAsFloat();
|
||||||
|
startTime = this.currentPhaseStartTime;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
percentDone = getTotalPercentCompleteAsFloat();
|
||||||
|
startTime = this.phaseOneStartTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (percentDone == null || percentDone <= 0.001) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Elapsed time is to percent done as total time is to total done =>
|
||||||
|
// elapsed/percentDone == totalTime/100.0 =>
|
||||||
|
long totalTime = (long) (100.0f * ((new Date().getTime()/1000) - startTime) / percentDone);
|
||||||
|
|
||||||
|
return totalTime + startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repair the start times in case the system clock has been moved
|
||||||
|
* backwards.
|
||||||
|
*/
|
||||||
|
protected void doctorStartTimes() {
|
||||||
|
|
||||||
|
long nowTime = (new Date().getTime()/1000);
|
||||||
|
|
||||||
|
if (this.lastUIUpdateTime > nowTime) {
|
||||||
|
this.lastUIUpdateTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.phaseOneStartTime > nowTime) {
|
||||||
|
this.phaseOneStartTime = nowTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.currentPhaseStartTime > nowTime) {
|
||||||
|
this.currentPhaseStartTime = nowTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
97
src/main/java/forge/view/util/ProgressBar_Embedded.java
Normal file
97
src/main/java/forge/view/util/ProgressBar_Embedded.java
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
package forge.view.util;
|
||||||
|
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
|
||||||
|
import forge.view.util.ProgressBar_Base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GUI Progress Monitor that displays the ETA (Estimated Time of Arrival or
|
||||||
|
* completion) on some platforms and supports one or multiple phases of
|
||||||
|
* progress.
|
||||||
|
*
|
||||||
|
* In this implementation, the progress bar must be embedded in a parent component.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class ProgressBar_Embedded extends ProgressBar_Base {
|
||||||
|
|
||||||
|
public ProgressBar_Embedded(int numPhases, long totalUnitsFirstPhase) {
|
||||||
|
super(numPhases, totalUnitsFirstPhase);
|
||||||
|
|
||||||
|
setIndeterminate(false);
|
||||||
|
setString("");
|
||||||
|
setStringPainted(true);
|
||||||
|
setValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public void increment() {
|
||||||
|
// setValue(getValue() + 1);
|
||||||
|
// System.out.println("x");
|
||||||
|
// //if (getValue() % 10 == 0) { repaint(); }
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
/**
|
||||||
|
* @see forge.view.util.ProgressBar_Base#incrementUnitsCompletedThisPhase(long)
|
||||||
|
*/
|
||||||
|
public final void incrementUnitsCompletedThisPhase(final long numUnits) {
|
||||||
|
super.incrementUnitsCompletedThisPhase(numUnits);
|
||||||
|
SwingUtilities.invokeLater(new Runnable() { // NOPMD by Braids on 8/18/11 11:18 PM
|
||||||
|
public void run() {
|
||||||
|
for (int i = 0; i < numUnits; i++) {
|
||||||
|
increment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (shouldUpdateUI()) {
|
||||||
|
|
||||||
|
if ((getNumPhases() > 1)) {
|
||||||
|
displayUpdate(
|
||||||
|
"Phase " + getCurrentPhase() + ". "
|
||||||
|
//+ getUnitsCompletedSoFarThisPhase() + " units processed. "
|
||||||
|
//+ "Overall: " + getTotalPercentCompleteAsString() + "% complete, "
|
||||||
|
+ "Overall ETA in " + getRelativeETAAsString() + "."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
displayUpdate(
|
||||||
|
//"Overall: " +
|
||||||
|
getUnitsCompletedSoFarThisPhase() + " units processed; "
|
||||||
|
//+ "(" + getTotalPercentCompleteAsString() + "%); "
|
||||||
|
+ "ETA in " + getRelativeETAAsString() + "."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getCurrentPhase() == getNumPhases()
|
||||||
|
&& getUnitsCompletedSoFarThisPhase() >= getTotalUnitsThisPhase())
|
||||||
|
{
|
||||||
|
displayUpdate("Done!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the message inside the progress dialog; does not always work on
|
||||||
|
* all platforms.
|
||||||
|
*
|
||||||
|
* @param message the message to display
|
||||||
|
*/
|
||||||
|
public final void displayUpdate(final String message) {
|
||||||
|
|
||||||
|
final Runnable proc = new Runnable() { // NOPMD by Braids on 8/18/11 11:18 PM
|
||||||
|
public void run() {
|
||||||
|
setString(message);
|
||||||
|
justUpdatedUI();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (SwingUtilities.isEventDispatchThread()) {
|
||||||
|
proc.run();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SwingUtilities.invokeLater(proc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
152
src/main/java/forge/view/util/ProgressBar_Interface.java
Normal file
152
src/main/java/forge/view/util/ProgressBar_Interface.java
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
package forge.view.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for a progress monitor that can have multiple phases
|
||||||
|
* and periodically update its UI.
|
||||||
|
*
|
||||||
|
* All times must be in seconds; absolute times are measured in seconds since
|
||||||
|
* 01 Jan 1970 00:00:00 UTC (GMT) a la (new Date().getTime()/1000).
|
||||||
|
*/
|
||||||
|
public interface ProgressBar_Interface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy this progress monitor, making it no longer usable and/or
|
||||||
|
* visible.
|
||||||
|
*/
|
||||||
|
public void dispose();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the total number of phases monitored by this object.
|
||||||
|
*/
|
||||||
|
public abstract int getNumPhases();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the approximate minimum interval in seconds at which the UI
|
||||||
|
* should be updated.
|
||||||
|
*/
|
||||||
|
public abstract float getMinUpdateIntervalSec();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the current phase number; this is never less than 1 (one).
|
||||||
|
*/
|
||||||
|
public abstract int getCurrentPhase();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the number of units (an intentionally vague amount) completed
|
||||||
|
* so far in the current phase.
|
||||||
|
*/
|
||||||
|
public abstract long getUnitsCompletedSoFarThisPhase();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the total units we expect to process in this phase
|
||||||
|
*/
|
||||||
|
public abstract long getTotalUnitsThisPhase();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the time in absolute seconds since the UI was last updated
|
||||||
|
*/
|
||||||
|
public abstract long getLastUIUpdateTime();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the time in absolute seconds at which the first phase started
|
||||||
|
*/
|
||||||
|
public abstract long getPhaseOneStartTime();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the time in absolute seconds at which the current phase started
|
||||||
|
*/
|
||||||
|
public abstract long getCurrentPhaseStartTime();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param value
|
||||||
|
* the approximate time in relative seconds at which the UI
|
||||||
|
* should be updated periodically
|
||||||
|
*/
|
||||||
|
public abstract void setMinUpdateIntervalSec(float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param value the total number of units expected to processed in this
|
||||||
|
* phase
|
||||||
|
*/
|
||||||
|
public abstract void setTotalUnitsThisPhase(long value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resulting string does not contain a percent sign.
|
||||||
|
*
|
||||||
|
* @return the percentage completion of this phase as a String with no
|
||||||
|
* percent sign.
|
||||||
|
*/
|
||||||
|
public abstract String getPercentCompleteOfThisPhaseAsString();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resulting string does not contain a percent sign.
|
||||||
|
*
|
||||||
|
* @return the percentage completion at this point, taking into account all
|
||||||
|
* phases and phase-weights, as a String with no percent sign.
|
||||||
|
*/
|
||||||
|
public abstract String getTotalPercentCompleteAsString();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* May return "unknown"
|
||||||
|
*/
|
||||||
|
public abstract String getRelativeETAAsString(boolean thisPhaseOnly);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* May return "unknown"
|
||||||
|
*/
|
||||||
|
public abstract String getAbsoluteETAAsLocalTimeString(boolean thisPhaseOnly);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note this will NOT advance the phase.
|
||||||
|
* To do that, use markCurrentPhaseAsComplete().
|
||||||
|
*/
|
||||||
|
public abstract void incrementUnitsCompletedThisPhase(long numUnits);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a boolean, whether or not to display the updated information.
|
||||||
|
* This throttles the update so it doesn't refresh so fast that it is
|
||||||
|
* unreadable. Implementers should call this method from their own
|
||||||
|
* incrementUnitsCompletedThisPhase method.
|
||||||
|
*
|
||||||
|
* If we have just reached 100% for (the current phase, we return true,
|
||||||
|
* even if it would otherwise be too soon to update the UI.
|
||||||
|
*/
|
||||||
|
public abstract boolean shouldUpdateUI();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the only way to advance the phase number.
|
||||||
|
* It automatically "starts the clock" for the next phase.
|
||||||
|
*
|
||||||
|
* @param totalUnitsNextPhase if unknown, use zero (0), and be sure to call
|
||||||
|
* setTotalUnitsThisPhase() soon after.
|
||||||
|
*/
|
||||||
|
public abstract void markCurrentPhaseAsComplete(long totalUnitsNextPhase);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to display a message to the user; not all implementations
|
||||||
|
* support this.
|
||||||
|
*
|
||||||
|
* If they do not, they may silently ignore this call.
|
||||||
|
*
|
||||||
|
* @param message the message to display
|
||||||
|
*/
|
||||||
|
public abstract void sendMessage(String message);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the current phase as having an exponential rate; such phases
|
||||||
|
* reach their totalUnits slower and slower as they process more units.
|
||||||
|
*
|
||||||
|
* By default, a phase is considered to be linear, meaning this value is
|
||||||
|
* 1.0f.
|
||||||
|
*
|
||||||
|
* @param value usually less than 1.0f; often determined empirically.
|
||||||
|
*/
|
||||||
|
public abstract void setCurrentPhaseAsExponential(float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the exponent for this phase
|
||||||
|
*/
|
||||||
|
public abstract float getCurrentPhaseExponent();
|
||||||
|
|
||||||
|
}
|
||||||
2
src/main/java/forge/view/util/package-info.java
Normal file
2
src/main/java/forge/view/util/package-info.java
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/** Forge Card Game */
|
||||||
|
package forge.view.util;
|
||||||
Reference in New Issue
Block a user