diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
deleted file mode 100644
index cb2fdb3..0000000
--- a/.idea/inspectionProfiles/profiles_settings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index eb34d53..5998969 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,4 +1,4 @@
-#Wed May 10 15:59:40 CEST 2017
+#Wed May 10 19:56:18 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
diff --git a/src/main/kotlin/nl/astraeus/komp/ComponentSize.kt b/src/main/kotlin/nl/astraeus/komp/ComponentSize.kt
index 2f103b4..0fef47f 100644
--- a/src/main/kotlin/nl/astraeus/komp/ComponentSize.kt
+++ b/src/main/kotlin/nl/astraeus/komp/ComponentSize.kt
@@ -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
+) {
+ 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)
diff --git a/src/main/kotlin/nl/astraeus/komp/HtmlComponent.kt b/src/main/kotlin/nl/astraeus/komp/HtmlComponent.kt
index 48a4420..10a9311 100644
--- a/src/main/kotlin/nl/astraeus/komp/HtmlComponent.kt
+++ b/src/main/kotlin/nl/astraeus/komp/HtmlComponent.kt
@@ -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
}
diff --git a/src/main/kotlin/nl/astraeus/komp/Komp.kt b/src/main/kotlin/nl/astraeus/komp/Komp.kt
index 494811e..4a4ef8b 100644
--- a/src/main/kotlin/nl/astraeus/komp/Komp.kt
+++ b/src/main/kotlin/nl/astraeus/komp/Komp.kt
@@ -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 = HashMap()
+ private val elementList: MutableList = 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)
+ }
+ }
}
}
-}
\ No newline at end of file
+ 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 {
+ val result: MutableList = 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 {
+ 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()
+ }
+ }
+
+
+}