Testing resize
This commit is contained in:
@@ -1,11 +1,19 @@
|
||||
package nl.astraeus.komp
|
||||
|
||||
import org.w3c.dom.HTMLElement
|
||||
|
||||
/**
|
||||
* User: rnentjes
|
||||
* Date: 10-5-17
|
||||
* Time: 16:48
|
||||
*/
|
||||
|
||||
enum class LayoutType {
|
||||
NONE,
|
||||
HORIZONTAL,
|
||||
VERTICAL
|
||||
}
|
||||
|
||||
enum class SizeType {
|
||||
NONE,
|
||||
ABSOLUTE,
|
||||
@@ -15,10 +23,112 @@ enum class SizeType {
|
||||
}
|
||||
|
||||
open class ComponentSize(
|
||||
val xType: SizeType,
|
||||
val yType: SizeType,
|
||||
val xValue: Float,
|
||||
val yValue: Float
|
||||
)
|
||||
val element: HTMLElement,
|
||||
val layout: LayoutType,
|
||||
val type: SizeType,
|
||||
val value: Float
|
||||
) {
|
||||
var calculatedSize: Rect = Rect(0,0,0,0)
|
||||
}
|
||||
|
||||
class Rect(
|
||||
val left: Int,
|
||||
val top: Int,
|
||||
val width: Int,
|
||||
val height: Int
|
||||
) {
|
||||
override fun toString(): String {
|
||||
return "Rect(left=$left, top=$top, width=$width, height=$height)"
|
||||
}
|
||||
}
|
||||
|
||||
class SizeContainer(
|
||||
val parentSize: Rect,
|
||||
val componentList: List<ComponentSize>
|
||||
) {
|
||||
var layout: LayoutType? = null
|
||||
var totalSize = 0
|
||||
var totalPixels = 0f
|
||||
var totalPercentage = 0f
|
||||
var totalFlex = 0f
|
||||
var fillCount = 0f
|
||||
|
||||
var afterPixels = 0f
|
||||
var afterPercentage = 0f
|
||||
var calculatedSize = 0
|
||||
var calculatedStart = 0
|
||||
|
||||
fun calculate() {
|
||||
for (size in componentList) {
|
||||
if (layout == null) {
|
||||
layout = size.layout
|
||||
} else if (layout != size.layout) {
|
||||
console.log("hbox/vbox combined:", componentList)
|
||||
throw IllegalStateException("hbox and vbox mixed between siblings!")
|
||||
}
|
||||
|
||||
when(size.type) {
|
||||
SizeType.ABSOLUTE -> {
|
||||
totalPixels += size.value
|
||||
}
|
||||
SizeType.PERCENTAGE -> {
|
||||
totalPercentage += size.value
|
||||
}
|
||||
SizeType.FLEX -> {
|
||||
totalFlex += size.value
|
||||
}
|
||||
SizeType.FILL -> {
|
||||
fillCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (layout == null) {
|
||||
throw IllegalStateException("No hbox or vbox attribute found!?")
|
||||
}
|
||||
|
||||
if (layout == LayoutType.HORIZONTAL) {
|
||||
totalSize = parentSize.width
|
||||
} else {
|
||||
totalSize = parentSize.height
|
||||
}
|
||||
|
||||
afterPixels = totalSize - totalPixels
|
||||
afterPercentage = afterPixels * totalPercentage / 100f
|
||||
|
||||
for (size in componentList) {
|
||||
when(size.type) {
|
||||
SizeType.ABSOLUTE -> {
|
||||
calculatedSize = size.value.toInt()
|
||||
}
|
||||
SizeType.PERCENTAGE -> {
|
||||
calculatedSize = (afterPixels * size.value / 100f).toInt()
|
||||
}
|
||||
SizeType.FLEX -> {
|
||||
calculatedSize = (afterPercentage * size.value / totalFlex).toInt()
|
||||
}
|
||||
SizeType.FILL -> {
|
||||
calculatedSize = (afterPercentage * size.value / fillCount).toInt()
|
||||
}
|
||||
}
|
||||
|
||||
if (layout == LayoutType.HORIZONTAL) {
|
||||
size.calculatedSize = Rect(calculatedStart, parentSize.top, calculatedSize, parentSize.height)
|
||||
} else {
|
||||
size.calculatedSize = Rect(parentSize.left, calculatedStart, parentSize.width, calculatedSize)
|
||||
}
|
||||
|
||||
calculatedStart += calculatedSize
|
||||
console.log("Set component to ${size.calculatedSize}", size.element)
|
||||
|
||||
size.element.style.position = "absolute"
|
||||
size.element.style.left = "${size.calculatedSize.left}px"
|
||||
size.element.style.top = "${size.calculatedSize.top}px"
|
||||
size.element.style.width = "${size.calculatedSize.width}px"
|
||||
size.element.style.height = "${size.calculatedSize.height}px"
|
||||
|
||||
size.element.setAttribute("data-resized", "true")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class NotSized : ComponentSize(SizeType.NONE, SizeType.NONE, 0f, 0f)
|
||||
|
||||
@@ -15,6 +15,7 @@ fun DIV.include(component: HtmlComponent) {
|
||||
|
||||
abstract class HtmlComponent {
|
||||
var element: HTMLElement? = null
|
||||
var size: ComponentSize? = null
|
||||
|
||||
fun create(): HTMLElement {
|
||||
var elem =element
|
||||
@@ -37,5 +38,4 @@ abstract class HtmlComponent {
|
||||
Komp.refresh(element)
|
||||
}
|
||||
|
||||
open fun getSize(): ComponentSize? = null
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package nl.astraeus.komp
|
||||
|
||||
import org.w3c.dom.Element
|
||||
import org.w3c.dom.HTMLElement
|
||||
import org.w3c.dom.get
|
||||
import kotlin.browser.document
|
||||
import kotlin.browser.window
|
||||
|
||||
/**
|
||||
@@ -12,9 +15,18 @@ import kotlin.browser.window
|
||||
object Komp {
|
||||
|
||||
private val elements: MutableMap<HTMLElement, HtmlComponent> = HashMap()
|
||||
private val elementList: MutableList<HtmlComponent> = ArrayList()
|
||||
private var resizing = false
|
||||
|
||||
init {
|
||||
window.onresize = {
|
||||
Komp.resize()
|
||||
}
|
||||
}
|
||||
|
||||
fun define(element: HTMLElement, component: HtmlComponent) {
|
||||
elements[element] = component
|
||||
elementList.add(component)
|
||||
}
|
||||
|
||||
fun create(parent: HTMLElement, component: HtmlComponent, insertAsFirst: Boolean = false) {
|
||||
@@ -27,10 +39,16 @@ object Komp {
|
||||
}
|
||||
|
||||
elements[element] = component
|
||||
elementList.add(component)
|
||||
|
||||
resize()
|
||||
}
|
||||
|
||||
fun remove(element: HTMLElement) {
|
||||
val component = elements[element]
|
||||
|
||||
elements.remove(element)
|
||||
elementList.remove(component)
|
||||
}
|
||||
|
||||
@JsName("remove")
|
||||
@@ -40,6 +58,7 @@ object Komp {
|
||||
elements.remove(key)
|
||||
}
|
||||
}
|
||||
elementList.remove(component)
|
||||
}
|
||||
|
||||
fun refresh(component: HtmlComponent) {
|
||||
@@ -55,45 +74,135 @@ object Komp {
|
||||
val newElement = comp.create()
|
||||
|
||||
parent?.replaceChild(newElement, element)
|
||||
|
||||
window.setTimeout({
|
||||
resize(comp)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
resize()
|
||||
}
|
||||
|
||||
private fun resize() {
|
||||
if (!resizing) {
|
||||
resizing = true
|
||||
|
||||
window.setTimeout({
|
||||
resizing = false
|
||||
|
||||
resizeComponents()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun resize(component: HtmlComponent) {
|
||||
println("Resize $component")
|
||||
}
|
||||
|
||||
fun sizeElement(element: HTMLElement, size: ComponentSize) {
|
||||
var width = ""
|
||||
var height = ""
|
||||
val parent = element.parentElement as HTMLElement
|
||||
|
||||
when(size.xType) {
|
||||
SizeType.ABSOLUTE -> {
|
||||
width = "${size.xValue.toInt()}px"
|
||||
}
|
||||
SizeType.PERCENTAGE -> {
|
||||
width = "${(parent.clientWidth * size.xValue / 100f).toInt()}px"
|
||||
}
|
||||
SizeType.FILL -> {
|
||||
|
||||
}
|
||||
SizeType.FLEX -> {
|
||||
|
||||
}
|
||||
private fun resizeComponents() {
|
||||
for (component in elementList) {
|
||||
component.element?.setAttribute("data-resized", "false")
|
||||
}
|
||||
|
||||
if (width.isNotBlank()) {
|
||||
element.style.width = width
|
||||
}
|
||||
if (height.isNotBlank()) {
|
||||
element.style.height = height
|
||||
for (component in elementList) {
|
||||
if (component.element?.getAttribute("data-resize") != "true") {
|
||||
if (component.element?.attributes?.get("hbox") != null || component.element?.attributes?.get("vbox") != null) {
|
||||
console.log("resize", component)
|
||||
|
||||
resize(component)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private fun resize(comp: HtmlComponent) {
|
||||
val parent = comp.element?.parentElement
|
||||
|
||||
if (parent != null) {
|
||||
val sizes = getSiblingSizes(parent)
|
||||
val parentSize = elements[parent]?.size
|
||||
val container: SizeContainer
|
||||
|
||||
if (parentSize != null) {
|
||||
container = SizeContainer(
|
||||
parentSize.calculatedSize,
|
||||
sizes
|
||||
)
|
||||
} else {
|
||||
val leftString = (parent as HTMLElement).style.left
|
||||
val topString = parent.style.top
|
||||
val widthString = parent.style.width
|
||||
val heightString = parent.style.height
|
||||
|
||||
if (parent == document.body) {
|
||||
container = SizeContainer(
|
||||
Rect(parent.clientLeft, parent.clientTop, parent.clientWidth, parent.clientHeight),
|
||||
sizes
|
||||
)
|
||||
} else if (leftString.endsWith("px") && topString.endsWith("px") && widthString.endsWith("px") && heightString.endsWith("px")) {
|
||||
container = SizeContainer(
|
||||
Rect(
|
||||
leftString.slice(0..leftString.length - 3).toInt(),
|
||||
topString.slice(0..topString.length - 3).toInt(),
|
||||
widthString.slice(0..widthString.length - 3).toInt(),
|
||||
heightString.slice(0..heightString.length - 3).toInt()
|
||||
),
|
||||
sizes
|
||||
)
|
||||
} else {
|
||||
container = SizeContainer(
|
||||
Rect(parent.clientLeft, parent.clientTop, parent.clientWidth, parent.clientHeight),
|
||||
sizes
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
container.calculate()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSiblingSizes(parent: Element): List<ComponentSize> {
|
||||
val result: MutableList<ComponentSize> = ArrayList()
|
||||
|
||||
for (index in 0..parent.children.length-1) {
|
||||
val child = parent.children[index]
|
||||
|
||||
if (child is HTMLElement) {
|
||||
val comp = elements[child]
|
||||
val size = getSize(child)
|
||||
comp?.size = size
|
||||
|
||||
result.add(ComponentSize(child, size.layout, size.type, size.value))
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
fun getSize(element: HTMLElement): ComponentSize {
|
||||
val horText = element.attributes?.get("hbox")?.value
|
||||
val verText = element.attributes?.get("vbox")?.value
|
||||
var result: ComponentSize? = null
|
||||
|
||||
if (horText != null && verText != null) {
|
||||
throw IllegalStateException("Attributes 'hbox' and 'vbox' can not be combined!")
|
||||
} else if (horText != null) {
|
||||
val (type, size) = getSizeFromAttribute(horText)
|
||||
|
||||
result = ComponentSize(element, LayoutType.HORIZONTAL, type, size)
|
||||
} else if (verText != null) {
|
||||
val (type, size) = getSizeFromAttribute(verText)
|
||||
|
||||
result = ComponentSize(element, LayoutType.VERTICAL, type, size)
|
||||
}
|
||||
|
||||
return result ?: throw IllegalStateException("Unable to calculate size for $this")
|
||||
}
|
||||
|
||||
private fun getSizeFromAttribute(sizeString: String): Pair<SizeType, Float> {
|
||||
if (sizeString == "fill") {
|
||||
return SizeType.FILL to 0f
|
||||
} else if (sizeString.endsWith("px")) {
|
||||
return SizeType.ABSOLUTE to sizeString.slice(0..sizeString.length-3).toFloat()
|
||||
} else if (sizeString.endsWith("%")) {
|
||||
return SizeType.PERCENTAGE to sizeString.slice(0..sizeString.length-2).toFloat()
|
||||
} else {
|
||||
return SizeType.FLEX to sizeString.toFloat()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user