-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathImageDrawable.kt
98 lines (81 loc) · 3.6 KB
/
ImageDrawable.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package gg.essential.elementa.markdown.drawables
import gg.essential.elementa.UIComponent
import gg.essential.elementa.components.UIImage
import gg.essential.elementa.constraints.ConstraintType
import gg.essential.elementa.constraints.XConstraint
import gg.essential.elementa.constraints.YConstraint
import gg.essential.elementa.constraints.resolution.ConstraintVisitor
import gg.essential.elementa.dsl.childOf
import gg.essential.elementa.dsl.pixels
import gg.essential.elementa.dsl.toConstraint
import gg.essential.elementa.markdown.DrawState
import gg.essential.elementa.markdown.MarkdownComponent
import gg.essential.elementa.markdown.selection.ImageCursor
import gg.essential.universal.UMatrixStack
import java.awt.Color
import java.net.URL
class ImageDrawable(md: MarkdownComponent, val url: URL, private val fallback: Drawable) : Drawable(md) {
var selected = false
set(value) {
field = value
if (value) {
image.setColor(Color(200, 200, 255, 255).toConstraint())
} else {
image.setColor(Color.WHITE.toConstraint())
}
}
private lateinit var imageX: ShiftableMDPixelConstraint
private lateinit var imageY: ShiftableMDPixelConstraint
private val image = UIImage.ofURL(url) childOf md
private var hasLoaded = false
override fun layoutImpl(x: Float, y: Float, width: Float): Layout {
return if (image.isLoaded) {
imageX = ShiftableMDPixelConstraint(x, 0f)
imageY = ShiftableMDPixelConstraint(y, 0f)
image.setX(imageX)
image.setY(imageY)
val aspectRatio = image.imageWidth / image.imageHeight
val imageWidth = image.imageWidth.coerceAtMost(width)
val imageHeight = imageWidth / aspectRatio
image.setWidth(imageWidth.pixels())
image.setHeight(imageHeight.pixels())
Layout(x, y, imageWidth, imageHeight)
} else fallback.layout(x, y, width)
}
override fun draw(matrixStack: UMatrixStack, state: DrawState) {
if (!image.isLoaded) {
fallback.drawCompat(matrixStack, state)
} else {
if (!hasLoaded) {
hasLoaded = true
md.layout()
}
imageX.shift = state.xShift
imageY.shift = state.yShift
image.drawCompat(matrixStack)
}
}
// ImageDrawable mouse selection is managed by ParagraphDrawable#select
override fun cursorAt(mouseX: Float, mouseY: Float, dragged: Boolean, mouseButton: Int) = throw IllegalStateException("never called")
override fun cursorAtStart() = ImageCursor(this)
override fun cursorAtEnd() = ImageCursor(this)
override fun selectedText(asMarkdown: Boolean): String {
if (asMarkdown) {
// TODO: `fallback.selectedText(true)` will be empty since the children aren't
// marked as selected
return "  "
}
return " $url "
}
// TODO: Rename this function?
override fun hasSelectedText() = selected
fun getImageWidth(): Float = image.imageWidth
private inner class ShiftableMDPixelConstraint(val base: Float, var shift: Float) : XConstraint, YConstraint {
override var cachedValue = 0f
override var recalculate = true
override var constrainTo: UIComponent? = null
override fun getXPositionImpl(component: UIComponent) = base + shift
override fun getYPositionImpl(component: UIComponent) = base + shift
override fun visitImpl(visitor: ConstraintVisitor, type: ConstraintType) { }
}
}