mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-07 09:38:52 -06:00
Move view tests to common
This commit is contained in:
@@ -22,17 +22,22 @@ package org.isoron.platform.io
|
||||
interface Log {
|
||||
fun info(tag: String, msg: String)
|
||||
fun debug(tag: String, msg: String)
|
||||
fun warn(tag: String, msg: String)
|
||||
}
|
||||
|
||||
/**
|
||||
* A Log that prints to the standard output.
|
||||
*/
|
||||
class StandardLog : Log {
|
||||
override fun warn(tag: String, msg: String) {
|
||||
println(sprintf("W %-20s %s", tag, msg))
|
||||
}
|
||||
|
||||
override fun info(tag: String, msg: String) {
|
||||
println("I/$tag $msg")
|
||||
println(sprintf("I %-20s %s", tag, msg))
|
||||
}
|
||||
|
||||
override fun debug(tag: String, msg: String) {
|
||||
println("D/$tag $msg")
|
||||
println(sprintf("D %-20s %s", tag, msg))
|
||||
}
|
||||
}
|
||||
@@ -19,18 +19,27 @@
|
||||
|
||||
package org.isoron.platform.gui
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import org.w3c.dom.*
|
||||
import kotlin.browser.*
|
||||
import kotlin.js.*
|
||||
import kotlin.math.*
|
||||
|
||||
class HtmlCanvas(val canvas: HTMLCanvasElement) : Canvas {
|
||||
class JsCanvas(val element: HTMLCanvasElement,
|
||||
val pixelScale: Double) : Canvas {
|
||||
|
||||
val ctx = canvas.getContext("2d") as CanvasRenderingContext2D
|
||||
val ctx = element.getContext("2d") as CanvasRenderingContext2D
|
||||
var fontSize = 12.0
|
||||
var fontWeight = ""
|
||||
var fontFamily = "sans-serif"
|
||||
var fontFamily = "NotoRegular"
|
||||
var align = CanvasTextAlign.CENTER
|
||||
|
||||
private fun toPixel(x: Double): Double {
|
||||
return pixelScale * x
|
||||
}
|
||||
|
||||
private fun toDp(x: Int): Double {
|
||||
return x / pixelScale
|
||||
}
|
||||
|
||||
override fun setColor(color: Color) {
|
||||
val c = "rgb(${color.red * 255}, ${color.green * 255}, ${color.blue * 255})"
|
||||
ctx.fillStyle = c;
|
||||
@@ -39,45 +48,54 @@ class HtmlCanvas(val canvas: HTMLCanvasElement) : Canvas {
|
||||
|
||||
override fun drawLine(x1: Double, y1: Double, x2: Double, y2: Double) {
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(x1 + 0.5, y1 + 0.5)
|
||||
ctx.lineTo(x2 + 0.5, y2 + 0.5)
|
||||
ctx.moveTo(toPixel(x1), toPixel(y1))
|
||||
ctx.lineTo(toPixel(x2), toPixel(y2))
|
||||
ctx.stroke()
|
||||
}
|
||||
|
||||
override fun drawText(text: String, x: Double, y: Double) {
|
||||
ctx.font = "${fontWeight} ${fontSize}px ${fontFamily}"
|
||||
ctx.font = "${fontSize}px ${fontFamily}"
|
||||
ctx.textAlign = align
|
||||
ctx.textBaseline = CanvasTextBaseline.MIDDLE
|
||||
ctx.fillText(text, x, y)
|
||||
ctx.fillText(text, toPixel(x), toPixel(y + fontSize * 0.05))
|
||||
}
|
||||
|
||||
override fun fillRect(x: Double, y: Double, width: Double, height: Double) {
|
||||
ctx.fillRect(x - 0.5, y - 0.5, width + 1.0, height + 1.0)
|
||||
ctx.fillRect(toPixel(x),
|
||||
toPixel(y),
|
||||
toPixel(width),
|
||||
toPixel(height))
|
||||
}
|
||||
|
||||
override fun drawRect(x: Double, y: Double, width: Double, height: Double) {
|
||||
ctx.strokeRect(x - 0.5, y - 0.5, width + 1.0, height + 1.0)
|
||||
ctx.strokeRect(toPixel(x),
|
||||
toPixel(y),
|
||||
toPixel(width),
|
||||
toPixel(height))
|
||||
}
|
||||
|
||||
override fun getHeight(): Double {
|
||||
return canvas.height.toDouble()
|
||||
return toDp(element.height)
|
||||
}
|
||||
|
||||
override fun getWidth(): Double {
|
||||
return canvas.width.toDouble()
|
||||
return toDp(element.width)
|
||||
}
|
||||
|
||||
override fun setFont(font: Font) {
|
||||
fontWeight = if (font == Font.BOLD) "bold" else ""
|
||||
fontFamily = if (font == Font.FONT_AWESOME) "FontAwesome" else "sans-serif"
|
||||
fontFamily = when(font) {
|
||||
Font.REGULAR -> "NotoRegular"
|
||||
Font.BOLD -> "NotoBold"
|
||||
Font.FONT_AWESOME -> "FontAwesome"
|
||||
}
|
||||
}
|
||||
|
||||
override fun setFontSize(size: Double) {
|
||||
fontSize = size
|
||||
fontSize = size * pixelScale
|
||||
}
|
||||
|
||||
override fun setStrokeWidth(size: Double) {
|
||||
ctx.lineWidth = size
|
||||
ctx.lineWidth = size * pixelScale
|
||||
}
|
||||
|
||||
override fun fillArc(centerX: Double,
|
||||
@@ -85,18 +103,24 @@ class HtmlCanvas(val canvas: HTMLCanvasElement) : Canvas {
|
||||
radius: Double,
|
||||
startAngle: Double,
|
||||
swipeAngle: Double) {
|
||||
val x = toPixel(centerX)
|
||||
val y = toPixel(centerY)
|
||||
val from = startAngle / 180 * PI
|
||||
val to = (startAngle + swipeAngle) / 180 * PI
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(centerX, centerY)
|
||||
ctx.arc(centerX, centerY, radius, -from, -to, swipeAngle >= 0)
|
||||
ctx.lineTo(centerX, centerY)
|
||||
ctx.moveTo(x, y)
|
||||
ctx.arc(x, y, toPixel(radius), -from, -to, swipeAngle >= 0)
|
||||
ctx.lineTo(x, y)
|
||||
ctx.fill()
|
||||
}
|
||||
|
||||
override fun fillCircle(centerX: Double, centerY: Double, radius: Double) {
|
||||
ctx.beginPath()
|
||||
ctx.arc(centerX, centerY, radius, 0.0, 2 * PI)
|
||||
ctx.arc(toPixel(centerX),
|
||||
toPixel(centerY),
|
||||
toPixel(radius),
|
||||
0.0,
|
||||
2 * PI)
|
||||
ctx.fill()
|
||||
}
|
||||
|
||||
@@ -107,4 +131,15 @@ class HtmlCanvas(val canvas: HTMLCanvasElement) : Canvas {
|
||||
TextAlign.RIGHT -> CanvasTextAlign.RIGHT
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun loadImage(src: String) {
|
||||
Promise<Int> { resolve, reject ->
|
||||
val img = Image()
|
||||
img.onload = {
|
||||
ctx.drawImage(img, 0.0, 0.0)
|
||||
resolve(0)
|
||||
}
|
||||
img.src = src
|
||||
}.await()
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,9 @@ import org.w3c.xhr.*
|
||||
import kotlin.js.*
|
||||
|
||||
class JsFileStorage {
|
||||
private val TAG = "JsFileStorage"
|
||||
private val log = StandardLog()
|
||||
|
||||
private val indexedDB = eval("indexedDB")
|
||||
private var db: dynamic = null
|
||||
|
||||
@@ -31,16 +34,16 @@ class JsFileStorage {
|
||||
private val OS_NAME = "Files"
|
||||
|
||||
suspend fun init() {
|
||||
console.log("Initializing JsFileStorage...")
|
||||
log.info(TAG, "Initializing")
|
||||
Promise<Int> { resolve, reject ->
|
||||
val req = indexedDB.open(DB_NAME, 2)
|
||||
req.onerror = { reject(Exception("could not open IndexedDB")) }
|
||||
req.onupgradeneeded = {
|
||||
console.log("Creating document store for JsFileStorage...")
|
||||
log.info(TAG, "Creating document store")
|
||||
req.result.createObjectStore(OS_NAME)
|
||||
}
|
||||
req.onsuccess = {
|
||||
console.log("JsFileStorage is ready.")
|
||||
log.info(TAG, "Ready")
|
||||
db = req.result
|
||||
resolve(0)
|
||||
}
|
||||
|
||||
@@ -20,5 +20,5 @@
|
||||
package org.isoron.platform.io
|
||||
|
||||
actual fun sprintf(format: String, vararg args: Any?): String {
|
||||
TODO()
|
||||
return js("vsprintf")(format, args)
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
package org.isoron.platform.gui
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import org.isoron.platform.io.*
|
||||
import java.awt.*
|
||||
import java.awt.RenderingHints.*
|
||||
@@ -26,14 +27,6 @@ import java.awt.font.*
|
||||
import java.awt.image.*
|
||||
import kotlin.math.*
|
||||
|
||||
fun createFont(path: String): java.awt.Font {
|
||||
val file = JavaFileOpener().openResourceFile(path) as JavaResourceFile
|
||||
return java.awt.Font.createFont(0, file.stream())
|
||||
}
|
||||
|
||||
private val NOTO_REGULAR_FONT = createFont("fonts/NotoSans-Regular.ttf")
|
||||
private val NOTO_BOLD_FONT = createFont("fonts/NotoSans-Bold.ttf")
|
||||
private val FONT_AWESOME_FONT = createFont("fonts/FontAwesome.ttf")
|
||||
|
||||
class JavaCanvas(val image: BufferedImage,
|
||||
val pixelScale: Double = 2.0) : Canvas {
|
||||
@@ -46,6 +39,10 @@ class JavaCanvas(val image: BufferedImage,
|
||||
val heightPx = image.height
|
||||
val g2d = image.createGraphics()
|
||||
|
||||
private val NOTO_REGULAR_FONT = createFont("fonts/NotoSans-Regular.ttf")
|
||||
private val NOTO_BOLD_FONT = createFont("fonts/NotoSans-Bold.ttf")
|
||||
private val FONT_AWESOME_FONT = createFont("fonts/FontAwesome.ttf")
|
||||
|
||||
init {
|
||||
g2d.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);
|
||||
g2d.setRenderingHint(KEY_TEXT_ANTIALIASING, VALUE_TEXT_ANTIALIAS_ON);
|
||||
@@ -73,6 +70,7 @@ class JavaCanvas(val image: BufferedImage,
|
||||
}
|
||||
|
||||
override fun drawText(text: String, x: Double, y: Double) {
|
||||
updateFont()
|
||||
val bounds = g2d.font.getStringBounds(text, frc)
|
||||
val bWidth = bounds.width.roundToInt()
|
||||
val bHeight = bounds.height.roundToInt()
|
||||
@@ -122,7 +120,7 @@ class JavaCanvas(val image: BufferedImage,
|
||||
}
|
||||
|
||||
override fun setStrokeWidth(size: Double) {
|
||||
g2d.setStroke(BasicStroke(size.toFloat()))
|
||||
g2d.stroke = BasicStroke((size * pixelScale).toFloat())
|
||||
}
|
||||
|
||||
private fun updateFont() {
|
||||
@@ -158,4 +156,10 @@ class JavaCanvas(val image: BufferedImage,
|
||||
override fun setTextAlign(align: TextAlign) {
|
||||
this.textAlign = align
|
||||
}
|
||||
|
||||
private fun createFont(path: String) = runBlocking<java.awt.Font> {
|
||||
val file = JavaFileOpener().openResourceFile(path) as JavaResourceFile
|
||||
if (!file.exists()) throw RuntimeException("File not found: ${file.path}")
|
||||
java.awt.Font.createFont(0, file.stream())
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ package org.isoron.platform.io
|
||||
import java.io.*
|
||||
import java.nio.file.*
|
||||
|
||||
class JavaResourceFile(private val path: String) : ResourceFile {
|
||||
class JavaResourceFile(val path: String) : ResourceFile {
|
||||
private val javaPath: Path
|
||||
get() {
|
||||
val mainPath = Paths.get("assets/main/$path")
|
||||
@@ -41,7 +41,9 @@ class JavaResourceFile(private val path: String) : ResourceFile {
|
||||
|
||||
override suspend fun copyTo(dest: UserFile) {
|
||||
if (dest.exists()) dest.delete()
|
||||
Files.copy(javaPath, (dest as JavaUserFile).path)
|
||||
val destPath = (dest as JavaUserFile).path
|
||||
destPath.toFile().parentFile?.mkdirs()
|
||||
Files.copy(javaPath, destPath)
|
||||
}
|
||||
|
||||
fun stream(): InputStream {
|
||||
|
||||
Reference in New Issue
Block a user