From d828a4778443c692ac97a27c4aac6fdaf208f082 Mon Sep 17 00:00:00 2001 From: rnentjes Date: Wed, 10 May 2017 23:02:06 +0200 Subject: [PATCH] Testing resize --- .../inspectionProfiles/profiles_settings.xml | 6 - gradle/wrapper/gradle-wrapper.properties | 2 +- .../kotlin/nl/astraeus/komp/ComponentSize.kt | 122 +++++++++++- .../kotlin/nl/astraeus/komp/HtmlComponent.kt | 2 +- src/main/kotlin/nl/astraeus/komp/Komp.kt | 173 ++++++++++++++---- 5 files changed, 259 insertions(+), 46 deletions(-) delete mode 100644 .idea/inspectionProfiles/profiles_settings.xml 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() + } + } + + +}