blob: 02fd8a82b0fd24399e81061ef721408c15c1d988 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nlpcraft.common.ansi
import java.io.PrintWriter
import org.apache.nlpcraft.common._
import NCAnsi._
import org.apache.nlpcraft.common.ansi.NCAnsiProgressBar._
/**
* Forward-only, bound ANSI-based progress bar.
*
* @param out
* @param totalTicks Number of ticks to complete.
* @param dispSize Visual size of the progress bar.
* @param clearOnComplete
* @param useAnsi
*/
class NCAnsiProgressBar(
out: PrintWriter,
totalTicks: Int,
dispSize: Int,
clearOnComplete: Boolean = true,
useAnsi: Boolean = true) {
require(dispSize <= totalTicks)
@volatile private var tick = 0
private final val mux = new Object()
//noinspection ZeroIndexToHead
private final val PB_LEFT = s"$B${CHAR_SET(0)}$RST"
private final val PB_RIGHT = s"$B${CHAR_SET(3)}$RST"
private final val PB_EMPTY =s"$W${CHAR_SET(2)}$RST"
private final val PB_FULL = s"$R$BO${CHAR_SET(1)}$RST"
/**
*
*/
private def clean(): Unit = {
out.print(ansiCursorLeft * (dispSize + 2))
out.print(ansiClearLineAfter)
out.flush()
}
/**
* Starts progress bar.
*/
def start(): Unit = {
tick = 0
if (useAnsi) mux.synchronized {
// Hide cursor to avoid blinking.
out.print(ansiCursorHide)
out.print(PB_LEFT)
out.print(PB_EMPTY * dispSize)
out.print(PB_RIGHT)
out.flush()
}
}
/**
* Ticks progress bar one tick at a time.
*/
def ticked(): Unit = {
mux.synchronized {
tick += 1
if (useAnsi) {
clean()
val bar = if (tick == 1) 1 else Math.round((tick.toFloat / totalTicks.toFloat) * dispSize)
out.print(PB_LEFT)
for (i ← 0 until dispSize)
out.print(if (i < bar) PB_FULL else PB_EMPTY)
out.print(PB_RIGHT)
out.flush()
}
else if (tick == 1 || tick % (totalTicks / dispSize) == 0) {
out.print(NON_ANSI_CHAR)
out.flush()
}
}
}
/**
* Whether progress is complete.
*
* @return
*/
def completed: Boolean =
tick == totalTicks
/**
* Stops progress bar.
*/
def stop(): Unit = {
if (useAnsi && clearOnComplete) mux.synchronized {
clean()
// Show cursor.
out.print(ansiCursorShow)
out.flush()
}
}
}
/**
*
*/
object NCAnsiProgressBar{
// Active charset to use.
private final val NON_ANSI_CHAR = '='
private val CHAR_SET = Seq('[', '=', '.', ']')
}