-def formatTime(t: Int): String =
- if (t < -1) "???"
- else {
- val (s, t1) = (t%60, t/60);
- val (m, h) = (t1%60, t1/60);
- if (h > 0) f"$h%d:$m%02d:$s%02d"
- else f"$m%02d:$s%02d"
- }
-
-private val UDATA = Seq("kB", "MB", "GB", "TB", "PB", "EB");
-def formatBytes(n: Long): String = {
- val (x, u) = ((n.toDouble, "B ") /: UDATA) { (xu, n) => (xu, n) match {
- case ((x, u), name) if x >= 1024.0 => (x/1024.0, name)
- case (xu, _) => xu
- } }
- f"$x%6.1f$u%s"
-}
-
-trait Eyecandy {
- def set(line: String);
- def clear();
- def commit();
- def commit(line: String) { commit(); set(line); commit(); }
- def begin(job: Job);
-}
-
-abstract class Event; // other subclasses can be added!
-abstract class Progress extends Event { def cur: Long; } // it changed
-object Progress {
- def unapply(p: Progress) =
- if (p == null) None
- else Some(p.cur);
-}
-case class Update(override val cur: Long) extends Progress; // progress has been made
-case class Changed(override val cur: Long) extends Progress; // what or max changed
-abstract class Stopped extends Event; // job has stopped
-case object Done extends Stopped; // job completed successfuly
-final case class Failed(why: String) extends Stopped; // job failed
-case object Cancelled extends Stopped; // job was cancelled
-
-trait Job extends Publisher[Event] {
- def what: String; // imperative for what we're doing
- def cur: Long; // current position in work
- def max: Long; // maximum work to do
- def format: String = { // describe progress in useful terms
- val c = cur;
- val m = max;
- if (m >= 0) {
- val fm = m.formatted("%d");
- s"%${fm.length}d/%s".format(c, fm) // ugh!
- } else if (c > 0) s"$c"
- else ""
- }
- def cancel();