diff options
Diffstat (limited to 'src/main/kotlin')
4 files changed, 206 insertions, 6 deletions
diff --git a/src/main/kotlin/pl/treksoft/kvision/utils/Snabbdom.kt b/src/main/kotlin/pl/treksoft/kvision/utils/Snabbdom.kt index cb48cfd1..db40c072 100644 --- a/src/main/kotlin/pl/treksoft/kvision/utils/Snabbdom.kt +++ b/src/main/kotlin/pl/treksoft/kvision/utils/Snabbdom.kt @@ -53,7 +53,7 @@ inline fun obj(init: dynamic.() -> Unit): dynamic { @Suppress("UNUSED_VARIABLE") inline fun <reified T> Any?.createInstance(vararg args: dynamic): T { val jsClass = this - val argsArray = (listOf(null) + args).toTypedArray() + val argsArray = (listOf<dynamic>() + args).toTypedArray() return js("new (Function.prototype.bind.apply(jsClass, argsArray))").unsafeCast<T>() } @@ -117,6 +117,9 @@ interface BtOn : On { var fileBrowseUpload: ((KvEvent) -> Unit)? var filePreUpload: ((KvEvent) -> Unit)? var resizeWindow: ((KvEvent) -> Unit)? + var closeWindow: ((KvEvent) -> Unit)? + var maximizeWindow: ((KvEvent) -> Unit)? + var minimizeWindow: ((KvEvent) -> Unit)? var tabulatorRowClick: ((KvEvent) -> Unit)? var tabulatorRowDblClick: ((KvEvent) -> Unit)? var tabulatorRowSelectionChanged: ((KvEvent) -> Unit)? diff --git a/src/main/kotlin/pl/treksoft/kvision/window/MaximizeIcon.kt b/src/main/kotlin/pl/treksoft/kvision/window/MaximizeIcon.kt new file mode 100644 index 00000000..a3ceaf61 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/window/MaximizeIcon.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017-present Robert Jaros + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package pl.treksoft.kvision.window + +import com.github.snabbdom.VNode +import pl.treksoft.kvision.KVManager +import pl.treksoft.kvision.core.StringBoolPair +import pl.treksoft.kvision.core.StringPair +import pl.treksoft.kvision.core.Widget + +/** + * Helper class for maximize icon component. + */ +open class MaximizeIcon : Widget(setOf()) { + + override fun render(): VNode { + return render("button", arrayOf(KVManager.virtualize("<span aria-hidden='true'>🗖</span>"))) + } + + override fun getSnClass(): List<StringBoolPair> { + val cl = super.getSnClass().toMutableList() + cl.add("close" to true) + return cl + } + + override fun getSnAttrs(): List<StringPair> { + return super.getSnAttrs() + listOf("type" to "button", "aria-label" to "Maximize") + } +} diff --git a/src/main/kotlin/pl/treksoft/kvision/window/MinimizeIcon.kt b/src/main/kotlin/pl/treksoft/kvision/window/MinimizeIcon.kt new file mode 100644 index 00000000..c8034d09 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/window/MinimizeIcon.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017-present Robert Jaros + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package pl.treksoft.kvision.window + +import com.github.snabbdom.VNode +import pl.treksoft.kvision.KVManager +import pl.treksoft.kvision.core.StringBoolPair +import pl.treksoft.kvision.core.StringPair +import pl.treksoft.kvision.core.Widget + +/** + * Helper class for minimize icon component. + */ +open class MinimizeIcon : Widget(setOf()) { + + override fun render(): VNode { + return render("button", arrayOf(KVManager.virtualize("<span aria-hidden='true'>🗕</span>"))) + } + + override fun getSnClass(): List<StringBoolPair> { + val cl = super.getSnClass().toMutableList() + cl.add("close" to true) + return cl + } + + override fun getSnAttrs(): List<StringPair> { + return super.getSnAttrs() + listOf("type" to "button", "aria-label" to "Minimize") + } +} diff --git a/src/main/kotlin/pl/treksoft/kvision/window/Window.kt b/src/main/kotlin/pl/treksoft/kvision/window/Window.kt index 0898440f..b0a3cb7d 100644 --- a/src/main/kotlin/pl/treksoft/kvision/window/Window.kt +++ b/src/main/kotlin/pl/treksoft/kvision/window/Window.kt @@ -32,6 +32,7 @@ import pl.treksoft.kvision.core.Overflow import pl.treksoft.kvision.core.Position import pl.treksoft.kvision.core.Resize import pl.treksoft.kvision.core.UNIT +import pl.treksoft.kvision.html.Icon import pl.treksoft.kvision.html.TAG import pl.treksoft.kvision.html.Tag import pl.treksoft.kvision.modal.CloseIcon @@ -53,6 +54,8 @@ internal const val WINDOW_CONTENT_MARGIN_BOTTOM = 11 * @param isResizable determines if the window is resizable * @param isDraggable determines if the window is draggable * @param closeButton determines if Close button is visible + * @param maximizeButton determines if Maximize button is visible + * @param minimizeButton determines if Minimize button is visible * @param classes a set of CSS class names * @param init an initializer extension function */ @@ -64,6 +67,9 @@ open class Window( isResizable: Boolean = true, isDraggable: Boolean = true, closeButton: Boolean = false, + maximizeButton: Boolean = false, + minimizeButton: Boolean = false, + icon: String? = null, classes: Set<String> = setOf(), init: (Window.() -> Unit)? = null ) : @@ -119,6 +125,33 @@ open class Window( closeIcon.visible = value checkHeaderVisibility() } + /** + * Determines if Maximize button is visible. + */ + var maximizeButton + get() = maximizeIcon.visible + set(value) { + maximizeIcon.visible = value + checkHeaderVisibility() + } + /** + * Determines if Maximize button is visible. + */ + var minimizeButton + get() = minimizeIcon.visible + set(value) { + minimizeIcon.visible = value + checkHeaderVisibility() + } + /** + * Window icon. + */ + var icon + get() = if (windowIcon.icon == "") null else windowIcon.icon + set(value) { + windowIcon.icon = value ?: "" + windowIcon.visible = (value != null && value != "") + } private val header = SimplePanel(setOf("modal-header")) @@ -131,7 +164,10 @@ open class Window( this.overflow = Overflow.AUTO } private val closeIcon = CloseIcon() + private val maximizeIcon = MaximizeIcon() + private val minimizeIcon = MinimizeIcon() private val captionTag = Tag(TAG.H4, caption, classes = setOf("modal-title")) + private val windowIcon = Icon(icon ?: "").apply { addCssClass("window-icon") } private var isResizeEvent = false @@ -147,12 +183,42 @@ open class Window( zIndex = ++zIndexCounter closeIcon.visible = closeButton closeIcon.setEventListener { - click = { - hide() + click = { e -> + if (this@Window.dispatchEvent("closeWindow", obj {}) != false) { + close() + } + } + mousedown = { e -> + e.stopPropagation() } } header.add(closeIcon) + maximizeIcon.visible = maximizeButton + maximizeIcon.setEventListener { + click = { e -> + if (this@Window.dispatchEvent("maximizeWindow", obj {}) != false) { + toggleMaximize() + } + } + mousedown = { e -> + e.stopPropagation() + } + } + header.add(maximizeIcon) + minimizeIcon.visible = minimizeButton + minimizeIcon.setEventListener { + click = { e -> + if (this@Window.dispatchEvent("minimizeWindow", obj {}) != false) { + toggleMinimize() + } + } + mousedown = { e -> + e.stopPropagation() + } + } + header.add(minimizeIcon) header.add(captionTag) + captionTag.add(windowIcon) checkHeaderVisibility() addInternal(header) addInternal(content) @@ -175,7 +241,7 @@ open class Window( } private fun checkHeaderVisibility() { - if (!closeButton && caption == null && !isDraggable) { + if (!closeButton && !maximizeButton && !minimizeButton && caption == null && !isDraggable) { header.hide() } else { header.show() @@ -238,7 +304,7 @@ open class Window( isResizeEvent = true KVManager.setResizeEvent(this) { val eid = getElementJQuery()?.attr("id") - if (eid == id) { + if (isResizable && eid == id) { val outerWidth = (getElementJQuery()?.outerWidth()?.toInt() ?: 0) val outerHeight = (getElementJQuery()?.outerHeight()?.toInt() ?: 0) val intWidth = (getElementJQuery()?.width()?.toInt() ?: 0) @@ -293,6 +359,7 @@ open class Window( override fun afterDestroy() { if (isResizeEvent) { KVManager.clearResizeEvent(this) + isResizeEvent = false } } @@ -310,6 +377,25 @@ open class Window( getElementJQuery()?.focus() } + /** + * Close the window. + */ + open fun close() { + hide() + } + + /** + * Maximize or restore the window size. + */ + open fun toggleMaximize() { + } + + /** + * Minimize or restore the window size. + */ + open fun toggleMinimize() { + } + companion object { internal var counter = 0 internal var zIndexCounter = DEFAULT_Z_INDEX @@ -326,11 +412,26 @@ open class Window( isResizable: Boolean = true, isDraggable: Boolean = true, closeButton: Boolean = false, + maximizeButton: Boolean = false, + minimizeButton: Boolean = false, + icon: String? = null, classes: Set<String> = setOf(), init: (Window.() -> Unit)? = null ): Window { val window = - Window(caption, contentWidth, contentHeight, isResizable, isDraggable, closeButton, classes, init) + Window( + caption, + contentWidth, + contentHeight, + isResizable, + isDraggable, + closeButton, + maximizeButton, + minimizeButton, + icon, + classes, + init + ) this.add(window) return window } |