aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kvision-modules/kvision-bootstrap/src/main/resources/css/style.css9
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/utils/Snabbdom.kt5
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/window/MaximizeIcon.kt48
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/window/MinimizeIcon.kt48
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/window/Window.kt111
5 files changed, 215 insertions, 6 deletions
diff --git a/kvision-modules/kvision-bootstrap/src/main/resources/css/style.css b/kvision-modules/kvision-bootstrap/src/main/resources/css/style.css
index 7633ed6c..475a0b85 100644
--- a/kvision-modules/kvision-bootstrap/src/main/resources/css/style.css
+++ b/kvision-modules/kvision-bootstrap/src/main/resources/css/style.css
@@ -128,10 +128,19 @@ trix-toolbar .trix-button-group {
padding: 10px 15px 5px 15px;
}
+.kv-window .modal-header button.close {
+ width: 21px;
+}
+
.kv-window .modal-header .modal-title {
white-space: nowrap;
}
+.kv-window .modal-header .window-icon {
+ display: inline-block;
+ margin-right: 6px;
+}
+
ul.dropdown-menu li a {
cursor: pointer;
}
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'>&#x1f5d6;</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'>&#x1f5d5;</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
}