import io.data2viz.color.*
import io.data2viz.geom.*
import io.data2viz.math.*
import io.data2viz.scale.*
import io.data2viz.viz.*
import io.data2viz.time.*
import io.data2viz.timeFormat.*
fun main() {
val startDates = listOf(Date(), Date(), Date(), Date())
val steps = listOf(timeMillisecond, timeHour, timeDay, timeMonth)
val formats = listOf(
"%L", // milliseconds
"%H:%M:%S",
"%d.%m.%Y",
"%x, %X",
"%-m/%-d/%Y",
"%-I:%M:%S %p",
"%a", // Weekday
"%B", // Month
"%Z" // Month
)
val cellWidth = 140.0
val cellHeight = 50.0
var secondsCounter = 0
// this scale map names of the days (as String) to colors
val scale = ScalesChromatic.Discrete.category10<Date> { domain = startDates }
val startXOffset = cellWidth / 2
val startYOffset = 25.0
val tableRows = formats.size + 1
val tableColumns = startDates.size + 1
val vizWidth = (startDates.size + 1) * cellWidth
val vizHeight = (formats.size + 1) * cellHeight
val viz = viz {
size = size(vizWidth, vizHeight)
text {
x = startXOffset
y = startYOffset
textAlign = textAlign(TextHAlign.MIDDLE, TextVAlign.MIDDLE)
textContent = "Format"
}
for (i in 0..tableRows) {
line {
x1 = 0.0
x2 = vizWidth
y1 = i * cellHeight - 1
y2 = i * cellHeight - 1
}
}
for (i in 0..tableColumns) {
line {
x1 = i * cellWidth - 1
x2 = i * cellWidth - 1
y1 = 0.0
y2 = vizHeight
}
}
line {
x1 = vizWidth - 1
x2 = vizWidth - 1
y1 = 0.0
y2 = vizHeight
}
startDates.forEachIndexed { dateIndex, startDate ->
text {
x = startXOffset + (dateIndex + 1) * cellWidth
y = startYOffset
textColor = scale(startDate)
textAlign = textAlign(TextHAlign.MIDDLE, TextVAlign.MIDDLE)
textContent = "Date"
}
}
val columns =
startDates.mapIndexed { dateIndex, date ->
formats.mapIndexed { formatIndex, formatSpec ->
text {
x = startXOffset
y = startYOffset + (formatIndex + 1) * cellHeight
textAlign = textAlign(TextHAlign.MIDDLE, TextVAlign.MIDDLE)
textContent = "$formatSpec"
}
text {
x = startXOffset + (dateIndex + 1) * cellWidth
y = startYOffset + (formatIndex + 1) * cellHeight
textColor = scale(date)
textAlign = textAlign(TextHAlign.MIDDLE, TextVAlign.MIDDLE)
textContent = format(formatSpec)(date)
}
}
}
animation { timerInMs: Double ->
// update one time per second
if (timerInMs / 1000 > secondsCounter) {
secondsCounter++
startDates.forEachIndexed { index, startDate ->
columns[index].forEachIndexed { rowIndex, text ->
text.textContent = format(formats[rowIndex])(steps[index].offset(startDate, secondsCounter.toLong()))
}
}
}
}
}.bindRendererOnNewCanvas()
}