Testing resize

This commit is contained in:
2017-05-10 23:02:06 +02:00
parent 78ce8858d5
commit d828a47784
5 changed files with 259 additions and 46 deletions

View File

@@ -1,6 +0,0 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="PROJECT_PROFILE" />
<version value="1.0" />
</settings>
</component>

View File

@@ -1,4 +1,4 @@
#Wed May 10 15:59:40 CEST 2017 #Wed May 10 19:56:18 CEST 2017
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

View File

@@ -1,11 +1,19 @@
package nl.astraeus.komp package nl.astraeus.komp
import org.w3c.dom.HTMLElement
/** /**
* User: rnentjes * User: rnentjes
* Date: 10-5-17 * Date: 10-5-17
* Time: 16:48 * Time: 16:48
*/ */
enum class LayoutType {
NONE,
HORIZONTAL,
VERTICAL
}
enum class SizeType { enum class SizeType {
NONE, NONE,
ABSOLUTE, ABSOLUTE,
@@ -15,10 +23,112 @@ enum class SizeType {
} }
open class ComponentSize( open class ComponentSize(
val xType: SizeType, val element: HTMLElement,
val yType: SizeType, val layout: LayoutType,
val xValue: Float, val type: SizeType,
val yValue: Float 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)

View File

@@ -15,6 +15,7 @@ fun DIV.include(component: HtmlComponent) {
abstract class HtmlComponent { abstract class HtmlComponent {
var element: HTMLElement? = null var element: HTMLElement? = null
var size: ComponentSize? = null
fun create(): HTMLElement { fun create(): HTMLElement {
var elem =element var elem =element
@@ -37,5 +38,4 @@ abstract class HtmlComponent {
Komp.refresh(element) Komp.refresh(element)
} }
open fun getSize(): ComponentSize? = null
} }

View File

@@ -1,6 +1,9 @@
package nl.astraeus.komp package nl.astraeus.komp
import org.w3c.dom.Element
import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLElement
import org.w3c.dom.get
import kotlin.browser.document
import kotlin.browser.window import kotlin.browser.window
/** /**
@@ -12,9 +15,18 @@ import kotlin.browser.window
object Komp { object Komp {
private val elements: MutableMap<HTMLElement, HtmlComponent> = HashMap() 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) { fun define(element: HTMLElement, component: HtmlComponent) {
elements[element] = component elements[element] = component
elementList.add(component)
} }
fun create(parent: HTMLElement, component: HtmlComponent, insertAsFirst: Boolean = false) { fun create(parent: HTMLElement, component: HtmlComponent, insertAsFirst: Boolean = false) {
@@ -27,10 +39,16 @@ object Komp {
} }
elements[element] = component elements[element] = component
elementList.add(component)
resize()
} }
fun remove(element: HTMLElement) { fun remove(element: HTMLElement) {
val component = elements[element]
elements.remove(element) elements.remove(element)
elementList.remove(component)
} }
@JsName("remove") @JsName("remove")
@@ -40,6 +58,7 @@ object Komp {
elements.remove(key) elements.remove(key)
} }
} }
elementList.remove(component)
} }
fun refresh(component: HtmlComponent) { fun refresh(component: HtmlComponent) {
@@ -55,45 +74,135 @@ object Komp {
val newElement = comp.create() val newElement = comp.create()
parent?.replaceChild(newElement, element) parent?.replaceChild(newElement, element)
}
}
resize()
}
private fun resize() {
if (!resizing) {
resizing = true
window.setTimeout({ window.setTimeout({
resize(comp) resizing = false
resizeComponents()
}) })
} }
}
private fun resizeComponents() {
for (component in elementList) {
component.element?.setAttribute("data-resized", "false")
}
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(component: HtmlComponent) { private fun resize(comp: HtmlComponent) {
println("Resize $component") val parent = comp.element?.parentElement
}
fun sizeElement(element: HTMLElement, size: ComponentSize) { if (parent != null) {
var width = "" val sizes = getSiblingSizes(parent)
var height = "" val parentSize = elements[parent]?.size
val parent = element.parentElement as HTMLElement val container: SizeContainer
when(size.xType) { if (parentSize != null) {
SizeType.ABSOLUTE -> { container = SizeContainer(
width = "${size.xValue.toInt()}px" parentSize.calculatedSize,
} sizes
SizeType.PERCENTAGE -> { )
width = "${(parent.clientWidth * size.xValue / 100f).toInt()}px" } else {
} val leftString = (parent as HTMLElement).style.left
SizeType.FILL -> { val topString = parent.style.top
val widthString = parent.style.width
} val heightString = parent.style.height
SizeType.FLEX -> {
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
)
} }
} }
if (width.isNotBlank()) { container.calculate()
element.style.width = width
}
if (height.isNotBlank()) {
element.style.height = height
} }
} }
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()
}
}
} }