Code polish, finish conversion to kotlin
This commit is contained in:
parent
b286ee9cf1
commit
ac44a42ae5
23
LICENSE
23
LICENSE
|
@ -6,6 +6,14 @@
|
||||||
Linux, MacOS, or Windows (notification/growl/toast/) popups for the desktop for Java 8+
|
Linux, MacOS, or Windows (notification/growl/toast/) popups for the desktop for Java 8+
|
||||||
|
|
||||||
Extra license information
|
Extra license information
|
||||||
|
- Kotlin -
|
||||||
|
[The Apache Software License, Version 2.0]
|
||||||
|
https://github.com/JetBrains/kotlin
|
||||||
|
Copyright 2020
|
||||||
|
JetBrains s.r.o. and Kotlin Programming Language contributors
|
||||||
|
Kotlin Compiler, Test Data+Libraries, and Tools repository contain third-party code, to which different licenses may apply
|
||||||
|
See: https://github.com/JetBrains/kotlin/blob/master/license/README.md
|
||||||
|
|
||||||
- TweenEngine -
|
- TweenEngine -
|
||||||
[The Apache Software License, Version 2.0]
|
[The Apache Software License, Version 2.0]
|
||||||
https://git.dorkbox.com/dorkbox/TweenEngine
|
https://git.dorkbox.com/dorkbox/TweenEngine
|
||||||
|
@ -15,14 +23,8 @@
|
||||||
High performance and lightweight Animation/Tween framework for Java 8+
|
High performance and lightweight Animation/Tween framework for Java 8+
|
||||||
|
|
||||||
Extra license information
|
Extra license information
|
||||||
- Robert Penner's Easing Functions -
|
|
||||||
[BSD 3-Clause License]
|
|
||||||
http://robertpenner.com/easing
|
|
||||||
Copyright 2001
|
|
||||||
Robert Penner
|
|
||||||
|
|
||||||
- Easing Functions -
|
- Easing Functions -
|
||||||
[BSD 3-Clause License]
|
[Public Domain, per Creative Commons CC0]
|
||||||
https://github.com/Michaelangel007/easing/blob/master/js/core/easing.js
|
https://github.com/Michaelangel007/easing/blob/master/js/core/easing.js
|
||||||
Copyright 2017
|
Copyright 2017
|
||||||
Michael Pohoreski
|
Michael Pohoreski
|
||||||
|
@ -665,10 +667,3 @@
|
||||||
https://git.dorkbox.com/dorkbox/PropertyLoader
|
https://git.dorkbox.com/dorkbox/PropertyLoader
|
||||||
Copyright 2023
|
Copyright 2023
|
||||||
Dorkbox LLC
|
Dorkbox LLC
|
||||||
|
|
||||||
|
|
||||||
- Dorkbox TweenEngine -
|
|
||||||
[The Apache Software License, Version 2.0]
|
|
||||||
https://git.dorkbox.com/dorkbox/TweenEngine
|
|
||||||
Copyright 2023
|
|
||||||
Dorkbox LLC
|
|
||||||
|
|
|
@ -30,8 +30,6 @@ internal class AsApplication internal constructor(
|
||||||
private const val glassPanePrefix = "dorkbox.notify"
|
private const val glassPanePrefix = "dorkbox.notify"
|
||||||
}
|
}
|
||||||
|
|
||||||
private val window = notification.attachedFrame!!
|
|
||||||
|
|
||||||
private val parentListener: ComponentListener
|
private val parentListener: ComponentListener
|
||||||
private val windowStateListener: WindowStateListener
|
private val windowStateListener: WindowStateListener
|
||||||
private var glassPane: JPanel
|
private var glassPane: JPanel
|
||||||
|
@ -41,13 +39,13 @@ internal class AsApplication internal constructor(
|
||||||
// this makes sure that our notify canvas stay anchored to the parent window (if it's hidden/shown/moved/etc)
|
// this makes sure that our notify canvas stay anchored to the parent window (if it's hidden/shown/moved/etc)
|
||||||
parentListener = object : ComponentListener {
|
parentListener = object : ComponentListener {
|
||||||
override fun componentShown(e: ComponentEvent) {
|
override fun componentShown(e: ComponentEvent) {
|
||||||
notification.notifyLook?.reLayout(window.bounds)
|
notification.doLayoutForApp()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun componentHidden(e: ComponentEvent) {}
|
override fun componentHidden(e: ComponentEvent) {}
|
||||||
|
|
||||||
override fun componentResized(e: ComponentEvent) {
|
override fun componentResized(e: ComponentEvent) {
|
||||||
notification.notifyLook?.reLayout(window.bounds)
|
notification.doLayoutForApp()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun componentMoved(e: ComponentEvent) {}
|
override fun componentMoved(e: ComponentEvent) {}
|
||||||
|
@ -56,10 +54,12 @@ internal class AsApplication internal constructor(
|
||||||
windowStateListener = WindowStateListener { e ->
|
windowStateListener = WindowStateListener { e ->
|
||||||
val state = e.newState
|
val state = e.newState
|
||||||
if (state and Frame.ICONIFIED == 0) {
|
if (state and Frame.ICONIFIED == 0) {
|
||||||
notification.notifyLook?.reLayout(window.bounds)
|
notification.doLayoutForApp()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val window = notification.attachedFrame!!
|
||||||
window.addWindowStateListener(windowStateListener)
|
window.addWindowStateListener(windowStateListener)
|
||||||
window.addComponentListener(parentListener)
|
window.addComponentListener(parentListener)
|
||||||
|
|
||||||
|
@ -88,14 +88,22 @@ internal class AsApplication internal constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setVisible(visible: Boolean, look: LookAndFeel) {
|
override fun setVisible(visible: Boolean, look: LookAndFeel) {
|
||||||
|
// was it already visible?
|
||||||
|
if (visible == glassPane.isVisible) {
|
||||||
|
// prevent "double setting" visible state
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// this is because the order of operations are different based upon visibility.
|
// this is because the order of operations are different based upon visibility.
|
||||||
look.updatePositionsPre(visible)
|
look.updatePositionsPre(visible)
|
||||||
look.updatePositionsPost(visible)
|
look.updatePositionsPost(visible, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// called on the Swing EDT.
|
// called on the Swing EDT.
|
||||||
override fun close() {
|
override fun close() {
|
||||||
glassPane.remove(notifyCanvas)
|
glassPane.remove(notifyCanvas)
|
||||||
|
|
||||||
|
val window = notification.attachedFrame!!
|
||||||
window.removeWindowStateListener(windowStateListener)
|
window.removeWindowStateListener(windowStateListener)
|
||||||
window.removeComponentListener(parentListener)
|
window.removeComponentListener(parentListener)
|
||||||
|
|
||||||
|
|
108
src/dorkbox/notify/AsApplicationLAF.kt
Executable file
108
src/dorkbox/notify/AsApplicationLAF.kt
Executable file
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2015 dorkbox, llc
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package dorkbox.notify
|
||||||
|
|
||||||
|
import dorkbox.notify.LAFUtil.SPACER
|
||||||
|
import dorkbox.notify.LAFUtil.growDown
|
||||||
|
import dorkbox.notify.LAFUtil.popups
|
||||||
|
import java.awt.Rectangle
|
||||||
|
import java.awt.Window
|
||||||
|
|
||||||
|
internal class AsApplicationLAF(notification: Notify, notifyCanvas: NotifyCanvas, parent: Window, parentBounds: Rectangle):
|
||||||
|
LookAndFeel(parent, notifyCanvas, notification) {
|
||||||
|
|
||||||
|
override val isDesktop = false
|
||||||
|
|
||||||
|
init {
|
||||||
|
idAndPosition = parent.name + ":" + position
|
||||||
|
|
||||||
|
anchorX = getAnchorX(position, parentBounds)
|
||||||
|
anchorY = getAnchorY(position, parentBounds)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getAnchorX(position: Position, bounds: Rectangle): Int {
|
||||||
|
// we use the screen that the mouse is currently on.
|
||||||
|
val startX = 0
|
||||||
|
val screenWidth = bounds.getWidth().toInt()
|
||||||
|
|
||||||
|
return when (position) {
|
||||||
|
Position.TOP_LEFT, Position.BOTTOM_LEFT -> LAFUtil.MARGIN + startX
|
||||||
|
Position.CENTER -> startX + screenWidth / 2 - NotifyCanvas.WIDTH / 2 - LAFUtil.MARGIN / 2
|
||||||
|
Position.TOP_RIGHT, Position.BOTTOM_RIGHT -> startX + screenWidth - NotifyCanvas.WIDTH - LAFUtil.MARGIN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getAnchorY(position: Position, bounds: Rectangle): Int {
|
||||||
|
val startY = 0
|
||||||
|
val screenHeight = bounds.getHeight().toInt()
|
||||||
|
|
||||||
|
return when (position) {
|
||||||
|
Position.TOP_LEFT, Position.TOP_RIGHT -> startY + LAFUtil.MARGIN
|
||||||
|
Position.CENTER -> startY + screenHeight / 2 - NotifyCanvas.HEIGHT / 2 - LAFUtil.MARGIN / 2 - SPACER
|
||||||
|
Position.BOTTOM_LEFT, Position.BOTTOM_RIGHT -> screenHeight - NotifyCanvas.HEIGHT - LAFUtil.MARGIN - SPACER * 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// only called from an application
|
||||||
|
override fun reLayout(bounds: Rectangle) {
|
||||||
|
// when the parent window moves, we stop all animation and snap the popup into place. This simplifies logic greatly
|
||||||
|
anchorX = getAnchorX(position, bounds)
|
||||||
|
anchorY = getAnchorY(position, bounds)
|
||||||
|
|
||||||
|
val growDown = growDown(this)
|
||||||
|
|
||||||
|
if (tween != null) {
|
||||||
|
tween!!.cancel() // cancel does its thing on the next tick of animation cycle
|
||||||
|
tween = null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var changedY: Int
|
||||||
|
if (popupIndex == 0) {
|
||||||
|
changedY = anchorY
|
||||||
|
} else {
|
||||||
|
synchronized(popups) {
|
||||||
|
val id = idAndPosition
|
||||||
|
val looks = popups[id]
|
||||||
|
changedY = if (looks != null) {
|
||||||
|
if (growDown) {
|
||||||
|
anchorY + popupIndex * (NotifyCanvas.HEIGHT + SPACER)
|
||||||
|
} else {
|
||||||
|
anchorY - popupIndex * (NotifyCanvas.HEIGHT + SPACER)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
anchorY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setLocation(anchorX, changedY)
|
||||||
|
}
|
||||||
|
|
||||||
|
override var y: Int
|
||||||
|
get() = notifyCanvas.y
|
||||||
|
set(y) {
|
||||||
|
notifyCanvas.setLocation(notifyCanvas.x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val x: Int
|
||||||
|
get() = notifyCanvas.x
|
||||||
|
|
||||||
|
override fun setLocation(x: Int, y: Int) {
|
||||||
|
notifyCanvas.setLocation(x, y)
|
||||||
|
}
|
||||||
|
}
|
|
@ -51,7 +51,8 @@ internal class AsDesktop internal constructor(val notification: Notify, notifyCa
|
||||||
super.setVisible(visible)
|
super.setVisible(visible)
|
||||||
|
|
||||||
// this is because the order of operations are different based upon visibility.
|
// this is because the order of operations are different based upon visibility.
|
||||||
look.updatePositionsPost(visible)
|
look.updatePositionsPost(visible, true)
|
||||||
|
|
||||||
if (visible) {
|
if (visible) {
|
||||||
toFront()
|
toFront()
|
||||||
}
|
}
|
||||||
|
|
75
src/dorkbox/notify/AsDesktopLAF.kt
Executable file
75
src/dorkbox/notify/AsDesktopLAF.kt
Executable file
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2015 dorkbox, llc
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package dorkbox.notify
|
||||||
|
|
||||||
|
import dorkbox.notify.LAFUtil.SPACER
|
||||||
|
import dorkbox.notify.LAFUtil.windowCloseListener
|
||||||
|
import dorkbox.util.ScreenUtil
|
||||||
|
import java.awt.Point
|
||||||
|
import java.awt.Rectangle
|
||||||
|
import java.awt.Window
|
||||||
|
|
||||||
|
internal class AsDesktopLAF(notification: Notify, notifyCanvas: NotifyCanvas, private val parent: Window, parentBounds: Rectangle)
|
||||||
|
: LookAndFeel(parent, notifyCanvas, notification) {
|
||||||
|
|
||||||
|
override val isDesktop = true
|
||||||
|
|
||||||
|
init {
|
||||||
|
parent.addWindowListener(windowCloseListener)
|
||||||
|
|
||||||
|
val point = Point(parentBounds.getX().toInt(), parentBounds.getY().toInt())
|
||||||
|
idAndPosition = ScreenUtil.getMonitorNumberAtLocation(point).toString() + ":" + position
|
||||||
|
|
||||||
|
anchorX = getAnchorX(position, parentBounds)
|
||||||
|
anchorY = getAnchorY(position, parentBounds)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getAnchorX(position: Position, bounds: Rectangle): Int {
|
||||||
|
// we use the screen that the mouse is currently on.
|
||||||
|
val startX = bounds.getX().toInt()
|
||||||
|
val screenWidth = bounds.getWidth().toInt()
|
||||||
|
|
||||||
|
return when (position) {
|
||||||
|
Position.TOP_LEFT, Position.BOTTOM_LEFT -> LAFUtil.MARGIN + startX
|
||||||
|
Position.CENTER -> startX + screenWidth / 2 - NotifyCanvas.WIDTH / 2 - LAFUtil.MARGIN / 2
|
||||||
|
Position.TOP_RIGHT, Position.BOTTOM_RIGHT -> startX + screenWidth - NotifyCanvas.WIDTH - LAFUtil.MARGIN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getAnchorY(position: Position, bounds: Rectangle): Int {
|
||||||
|
val startY = bounds.getY().toInt()
|
||||||
|
val screenHeight = bounds.getHeight().toInt()
|
||||||
|
|
||||||
|
return when (position) {
|
||||||
|
Position.TOP_LEFT, Position.TOP_RIGHT -> startY + LAFUtil.MARGIN
|
||||||
|
Position.CENTER -> startY + screenHeight / 2 - NotifyCanvas.HEIGHT / 2 - LAFUtil.MARGIN / 2 - SPACER
|
||||||
|
Position.BOTTOM_LEFT, Position.BOTTOM_RIGHT -> startY + screenHeight - NotifyCanvas.HEIGHT - LAFUtil.MARGIN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override var y: Int
|
||||||
|
get() = parent.y
|
||||||
|
set(y) {
|
||||||
|
parent.setLocation(parent.x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val x: Int
|
||||||
|
get() = parent.x
|
||||||
|
|
||||||
|
override fun setLocation(x: Int, y: Int) {
|
||||||
|
parent.setLocation(x, y)
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,9 +16,9 @@
|
||||||
package dorkbox.notify
|
package dorkbox.notify
|
||||||
|
|
||||||
import dorkbox.swingActiveRender.ActionHandlerLong
|
import dorkbox.swingActiveRender.ActionHandlerLong
|
||||||
import dorkbox.tweenEngine.TweenCallback.Events.COMPLETE
|
|
||||||
import dorkbox.tweenEngine.TweenEngine.Companion.create
|
import dorkbox.tweenEngine.TweenEngine.Companion.create
|
||||||
import dorkbox.tweenEngine.TweenEquations
|
import dorkbox.tweenEngine.TweenEquations
|
||||||
|
import dorkbox.tweenEngine.TweenEvents
|
||||||
import dorkbox.util.ScreenUtil
|
import dorkbox.util.ScreenUtil
|
||||||
import java.awt.GraphicsEnvironment
|
import java.awt.GraphicsEnvironment
|
||||||
import java.awt.MouseInfo
|
import java.awt.MouseInfo
|
||||||
|
@ -27,7 +27,7 @@ import java.awt.event.MouseAdapter
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
internal object LAFUtil{
|
internal object LAFUtil{
|
||||||
val popups: MutableMap<String, PopupList> = HashMap()
|
val popups = mutableMapOf<String, PopupList>()
|
||||||
|
|
||||||
// access is only from a single thread ever, so unsafe is preferred.
|
// access is only from a single thread ever, so unsafe is preferred.
|
||||||
val animation = create().unsafe().build()
|
val animation = create().unsafe().build()
|
||||||
|
@ -40,7 +40,7 @@ internal object LAFUtil{
|
||||||
const val SPACER = 10
|
const val SPACER = 10
|
||||||
const val MARGIN = 20
|
const val MARGIN = 20
|
||||||
|
|
||||||
val windowListener: java.awt.event.WindowAdapter = WindowAdapter()
|
val windowCloseListener: java.awt.event.WindowAdapter = WindowCloseAdapter()
|
||||||
val mouseListener: MouseAdapter = ClickAdapter()
|
val mouseListener: MouseAdapter = ClickAdapter()
|
||||||
val RANDOM = Random()
|
val RANDOM = Random()
|
||||||
|
|
||||||
|
@ -69,43 +69,8 @@ internal object LAFUtil{
|
||||||
return device.defaultConfiguration.bounds
|
return device.defaultConfiguration.bounds
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAnchorX(position: Position, bounds: Rectangle, isDesktop: Boolean): Int {
|
|
||||||
// we use the screen that the mouse is currently on.
|
|
||||||
val startX = if (isDesktop) {
|
|
||||||
bounds.getX().toInt()
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
val screenWidth = bounds.getWidth().toInt()
|
|
||||||
return when (position) {
|
|
||||||
Position.TOP_LEFT, Position.BOTTOM_LEFT -> MARGIN + startX
|
|
||||||
Position.CENTER -> startX + screenWidth / 2 - NotifyCanvas.WIDTH / 2 - MARGIN / 2
|
|
||||||
Position.TOP_RIGHT, Position.BOTTOM_RIGHT -> startX + screenWidth - NotifyCanvas.WIDTH - MARGIN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getAnchorY(position: Position, bounds: Rectangle, isDesktop: Boolean): Int {
|
|
||||||
val startY = if (isDesktop) {
|
|
||||||
bounds.getY().toInt()
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
val screenHeight = bounds.getHeight().toInt()
|
|
||||||
return when (position) {
|
|
||||||
Position.TOP_LEFT, Position.TOP_RIGHT -> startY + MARGIN
|
|
||||||
Position.CENTER -> startY + screenHeight / 2 - NotifyCanvas.HEIGHT / 2 - MARGIN / 2 - SPACER
|
|
||||||
Position.BOTTOM_LEFT, Position.BOTTOM_RIGHT -> if (isDesktop) {
|
|
||||||
startY + screenHeight - NotifyCanvas.HEIGHT - MARGIN
|
|
||||||
} else {
|
|
||||||
screenHeight - NotifyCanvas.HEIGHT - MARGIN - SPACER * 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// only called on the swing EDT thread
|
// only called on the swing EDT thread
|
||||||
fun addPopupToMap(sourceLook: LookAndFeel) {
|
fun addPopupToMap(sourceLook: LookAndFeel, isDesktop: Boolean) {
|
||||||
synchronized(popups) {
|
synchronized(popups) {
|
||||||
val id = sourceLook.idAndPosition
|
val id = sourceLook.idAndPosition
|
||||||
var looks = popups[id]
|
var looks = popups[id]
|
||||||
|
@ -126,7 +91,7 @@ internal object LAFUtil{
|
||||||
anchorY
|
anchorY
|
||||||
} else {
|
} else {
|
||||||
val growDown = growDown(sourceLook)
|
val growDown = growDown(sourceLook)
|
||||||
if (sourceLook.isDesktopNotification && index == 1) {
|
if (isDesktop && index == 1) {
|
||||||
// have to adjust for offsets when the window-manager has a toolbar that consumes space and prevents overlap.
|
// have to adjust for offsets when the window-manager has a toolbar that consumes space and prevents overlap.
|
||||||
// this is only done when the 2nd popup is added to the list
|
// this is only done when the 2nd popup is added to the list
|
||||||
looks.calculateOffset(growDown, anchorX, anchorY)
|
looks.calculateOffset(growDown, anchorX, anchorY)
|
||||||
|
@ -141,13 +106,16 @@ internal object LAFUtil{
|
||||||
looks.add(sourceLook)
|
looks.add(sourceLook)
|
||||||
sourceLook.setLocation(anchorX, targetY)
|
sourceLook.setLocation(anchorX, targetY)
|
||||||
|
|
||||||
if (sourceLook.hideAfterDurationInSeconds > 0 && sourceLook.hideTween == null) {
|
if (index == 0 && sourceLook.hideAfterDurationInSeconds > 0 && sourceLook.hideTween == null) {
|
||||||
|
println("start timeline")
|
||||||
// begin a timeline to get rid of the popup (default is 5 seconds)
|
// begin a timeline to get rid of the popup (default is 5 seconds)
|
||||||
animation.to(sourceLook, NotifyAccessor.PROGRESS, accessor, sourceLook.hideAfterDurationInSeconds)
|
val x = animation.to(sourceLook, NotifyAccessor.PROGRESS, accessor, sourceLook.hideAfterDurationInSeconds)
|
||||||
.target(NotifyCanvas.WIDTH.toFloat())
|
.target(NotifyCanvas.WIDTH.toFloat())
|
||||||
.ease(TweenEquations.Linear)
|
.ease(TweenEquations.Linear)
|
||||||
.addCallback(COMPLETE) { sourceLook.notification.onClose() }
|
.addCallback(TweenEvents.COMPLETE) { sourceLook.notification.onClose() }
|
||||||
.start()
|
.start()
|
||||||
|
|
||||||
|
println("started $x")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,6 +126,7 @@ internal object LAFUtil{
|
||||||
var popupsAreEmpty: Boolean
|
var popupsAreEmpty: Boolean
|
||||||
|
|
||||||
synchronized(popups) {
|
synchronized(popups) {
|
||||||
|
println("remove")
|
||||||
popupsAreEmpty = popups.isEmpty()
|
popupsAreEmpty = popups.isEmpty()
|
||||||
val allLooks = popups[sourceLook.idAndPosition]
|
val allLooks = popups[sourceLook.idAndPosition]
|
||||||
|
|
||||||
|
@ -203,7 +172,7 @@ internal object LAFUtil{
|
||||||
.to(look, NotifyAccessor.Y_POS, accessor, MOVE_DURATION)
|
.to(look, NotifyAccessor.Y_POS, accessor, MOVE_DURATION)
|
||||||
.target(changedY.toFloat())
|
.target(changedY.toFloat())
|
||||||
.ease(TweenEquations.Linear)
|
.ease(TweenEquations.Linear)
|
||||||
.addCallback(COMPLETE) {
|
.addCallback(TweenEvents.COMPLETE) {
|
||||||
// make sure to remove the tween once it's done, otherwise .kill can do weird things.
|
// make sure to remove the tween once it's done, otherwise .kill can do weird things.
|
||||||
look.tween = null
|
look.tween = null
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,43 +16,31 @@
|
||||||
package dorkbox.notify
|
package dorkbox.notify
|
||||||
|
|
||||||
import dorkbox.notify.LAFUtil.RANDOM
|
import dorkbox.notify.LAFUtil.RANDOM
|
||||||
import dorkbox.notify.LAFUtil.SPACER
|
|
||||||
import dorkbox.notify.LAFUtil.accessor
|
import dorkbox.notify.LAFUtil.accessor
|
||||||
import dorkbox.notify.LAFUtil.addPopupToMap
|
import dorkbox.notify.LAFUtil.addPopupToMap
|
||||||
import dorkbox.notify.LAFUtil.animation
|
import dorkbox.notify.LAFUtil.animation
|
||||||
import dorkbox.notify.LAFUtil.frameStartHandler
|
import dorkbox.notify.LAFUtil.frameStartHandler
|
||||||
import dorkbox.notify.LAFUtil.getAnchorX
|
|
||||||
import dorkbox.notify.LAFUtil.getAnchorY
|
|
||||||
import dorkbox.notify.LAFUtil.growDown
|
|
||||||
import dorkbox.notify.LAFUtil.mouseListener
|
import dorkbox.notify.LAFUtil.mouseListener
|
||||||
import dorkbox.notify.LAFUtil.popups
|
|
||||||
import dorkbox.notify.LAFUtil.removePopupFromMap
|
import dorkbox.notify.LAFUtil.removePopupFromMap
|
||||||
import dorkbox.notify.LAFUtil.windowListener
|
|
||||||
import dorkbox.swingActiveRender.SwingActiveRender
|
import dorkbox.swingActiveRender.SwingActiveRender
|
||||||
import dorkbox.tweenEngine.Tween
|
import dorkbox.tweenEngine.Tween
|
||||||
import dorkbox.tweenEngine.TweenEquations
|
import dorkbox.tweenEngine.TweenEquations
|
||||||
import dorkbox.util.ScreenUtil
|
|
||||||
import java.awt.Point
|
|
||||||
import java.awt.Rectangle
|
import java.awt.Rectangle
|
||||||
import java.awt.Window
|
import java.awt.Window
|
||||||
|
|
||||||
internal class LookAndFeel(
|
internal abstract class LookAndFeel(private val parent: Window, val notifyCanvas: NotifyCanvas, val notification: Notify) {
|
||||||
private val parent: Window,
|
|
||||||
private val notifyCanvas: NotifyCanvas,
|
|
||||||
val notification: Notify,
|
|
||||||
parentBounds: Rectangle,
|
|
||||||
val isDesktopNotification: Boolean
|
|
||||||
) {
|
|
||||||
@Volatile
|
|
||||||
var anchorX: Int
|
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
var anchorY: Int
|
var anchorX = 0
|
||||||
|
|
||||||
|
@Volatile
|
||||||
|
var anchorY = 0
|
||||||
|
|
||||||
val hideAfterDurationInSeconds: Float
|
val hideAfterDurationInSeconds: Float
|
||||||
val position: Position
|
val position: Position
|
||||||
|
|
||||||
// this is used in combination with position, so that we can track which screen and what position a popup is in
|
// this is used in combination with position, so that we can track which screen and what position a popup is in
|
||||||
var idAndPosition: String
|
var idAndPosition = ""
|
||||||
var popupIndex = 0
|
var popupIndex = 0
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
|
@ -61,64 +49,19 @@ internal class LookAndFeel(
|
||||||
@Volatile
|
@Volatile
|
||||||
var hideTween: Tween<*>? = null
|
var hideTween: Tween<*>? = null
|
||||||
|
|
||||||
|
abstract val isDesktop: Boolean
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (isDesktopNotification) {
|
|
||||||
parent.addWindowListener(windowListener)
|
|
||||||
}
|
|
||||||
|
|
||||||
notifyCanvas.addMouseListener(mouseListener)
|
notifyCanvas.addMouseListener(mouseListener)
|
||||||
hideAfterDurationInSeconds = notification.hideAfterDurationInMillis / 1000.0f
|
hideAfterDurationInSeconds = notification.hideAfterDurationInMillis / 1000.0f
|
||||||
position = notification.position
|
position = notification.position
|
||||||
|
|
||||||
idAndPosition = if (isDesktopNotification) {
|
|
||||||
val point = Point(parentBounds.getX().toInt(), parentBounds.getY().toInt())
|
|
||||||
ScreenUtil.getMonitorNumberAtLocation(point).toString() + ":" + position
|
|
||||||
} else {
|
|
||||||
parent.name + ":" + position
|
|
||||||
}
|
|
||||||
|
|
||||||
anchorX = getAnchorX(position, parentBounds, isDesktopNotification)
|
|
||||||
anchorY = getAnchorY(position, parentBounds, isDesktopNotification)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// only called from an application
|
// only called from an application
|
||||||
fun reLayout(bounds: Rectangle) {
|
open fun reLayout(bounds: Rectangle) {}
|
||||||
// when the parent window moves, we stop all animation and snap the popup into place. This simplifies logic greatly
|
|
||||||
anchorX = getAnchorX(position, bounds, isDesktopNotification)
|
|
||||||
anchorY = getAnchorY(position, bounds, isDesktopNotification)
|
|
||||||
|
|
||||||
val growDown = growDown(this)
|
open fun close() {
|
||||||
|
|
||||||
if (tween != null) {
|
|
||||||
tween!!.cancel() // cancel does its thing on the next tick of animation cycle
|
|
||||||
tween = null
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var changedY: Int
|
|
||||||
if (popupIndex == 0) {
|
|
||||||
changedY = anchorY
|
|
||||||
} else {
|
|
||||||
synchronized(popups) {
|
|
||||||
val id = idAndPosition
|
|
||||||
val looks = popups[id]
|
|
||||||
changedY = if (looks != null) {
|
|
||||||
if (growDown) {
|
|
||||||
anchorY + popupIndex * (NotifyCanvas.HEIGHT + SPACER)
|
|
||||||
} else {
|
|
||||||
anchorY - popupIndex * (NotifyCanvas.HEIGHT + SPACER)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
anchorY
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setLocation(anchorX, changedY)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun close() {
|
|
||||||
if (hideTween != null) {
|
if (hideTween != null) {
|
||||||
hideTween!!.cancel()
|
hideTween!!.cancel()
|
||||||
hideTween = null
|
hideTween = null
|
||||||
|
@ -129,13 +72,9 @@ internal class LookAndFeel(
|
||||||
tween = null
|
tween = null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDesktopNotification) {
|
|
||||||
parent.removeWindowListener(windowListener)
|
|
||||||
}
|
|
||||||
|
|
||||||
parent.removeMouseListener(mouseListener)
|
parent.removeMouseListener(mouseListener)
|
||||||
updatePositionsPre(false)
|
updatePositionsPre(false)
|
||||||
updatePositionsPost(false)
|
updatePositionsPost(false, isDesktop)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun shake(durationInMillis: Int, amplitude: Int) {
|
fun shake(durationInMillis: Int, amplitude: Int) {
|
||||||
|
@ -170,34 +109,12 @@ internal class LookAndFeel(
|
||||||
.start()
|
.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
var y: Int
|
abstract var y: Int
|
||||||
get() = if (isDesktopNotification) {
|
|
||||||
parent.y
|
|
||||||
} else {
|
|
||||||
notifyCanvas.y
|
|
||||||
}
|
|
||||||
set(y) {
|
|
||||||
if (isDesktopNotification) {
|
|
||||||
parent.setLocation(parent.x, y)
|
|
||||||
} else {
|
|
||||||
notifyCanvas.setLocation(notifyCanvas.x, y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val x: Int
|
abstract val x: Int
|
||||||
get() = if (isDesktopNotification) {
|
|
||||||
parent.x
|
abstract fun setLocation(x: Int, y: Int)
|
||||||
} else {
|
|
||||||
notifyCanvas.x
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setLocation(x: Int, y: Int) {
|
|
||||||
if (isDesktopNotification) {
|
|
||||||
parent.setLocation(x, y)
|
|
||||||
} else {
|
|
||||||
notifyCanvas.setLocation(x, y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var progress: Int
|
var progress: Int
|
||||||
get() = notifyCanvas.progress
|
get() = notifyCanvas.progress
|
||||||
|
@ -210,6 +127,7 @@ internal class LookAndFeel(
|
||||||
*/
|
*/
|
||||||
fun updatePositionsPre(visible: Boolean) {
|
fun updatePositionsPre(visible: Boolean) {
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
|
println("remove post")
|
||||||
val popupsAreEmpty = removePopupFromMap(this)
|
val popupsAreEmpty = removePopupFromMap(this)
|
||||||
SwingActiveRender.removeActiveRender(notifyCanvas)
|
SwingActiveRender.removeActiveRender(notifyCanvas)
|
||||||
if (popupsAreEmpty) {
|
if (popupsAreEmpty) {
|
||||||
|
@ -222,8 +140,9 @@ internal class LookAndFeel(
|
||||||
/**
|
/**
|
||||||
* when using active rendering, we have to add it AFTER we have set the visibility status
|
* when using active rendering, we have to add it AFTER we have set the visibility status
|
||||||
*/
|
*/
|
||||||
fun updatePositionsPost(visible: Boolean) {
|
fun updatePositionsPost(visible: Boolean, isDesktop: Boolean) {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
|
println("add post")
|
||||||
SwingActiveRender.addActiveRender(notifyCanvas)
|
SwingActiveRender.addActiveRender(notifyCanvas)
|
||||||
|
|
||||||
// start if we have previously stopped the timer
|
// start if we have previously stopped the timer
|
||||||
|
@ -231,7 +150,8 @@ internal class LookAndFeel(
|
||||||
animation.resetUpdateTime()
|
animation.resetUpdateTime()
|
||||||
SwingActiveRender.addActiveRenderFrameStart(frameStartHandler)
|
SwingActiveRender.addActiveRenderFrameStart(frameStartHandler)
|
||||||
}
|
}
|
||||||
addPopupToMap(this)
|
|
||||||
|
addPopupToMap(this, isDesktop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,6 +151,8 @@ class Notify private constructor() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Volatile
|
||||||
|
private var notifyCanvas: NotifyCanvas? = null
|
||||||
@Volatile
|
@Volatile
|
||||||
internal var notifyPopup: NotifyType? = null
|
internal var notifyPopup: NotifyType? = null
|
||||||
@Volatile
|
@Volatile
|
||||||
|
@ -158,12 +160,24 @@ class Notify private constructor() {
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
var title = "Notification"
|
var title = "Notification"
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
notifyCanvas?.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
var text = "Lorem ipsum"
|
var text = "Lorem ipsum"
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
notifyCanvas?.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
var theme = Theme.defaultLight
|
var theme = Theme.defaultLight
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
notifyCanvas?.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
var position = Position.BOTTOM_RIGHT
|
var position = Position.BOTTOM_RIGHT
|
||||||
|
@ -176,12 +190,20 @@ class Notify private constructor() {
|
||||||
*/
|
*/
|
||||||
@Volatile
|
@Volatile
|
||||||
var hideCloseButton = false
|
var hideCloseButton = false
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
notifyCanvas?.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
var screen = Short.MIN_VALUE.toInt()
|
var screen = Short.MIN_VALUE.toInt()
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
var image: ImageIcon? = null
|
var image: ImageIcon? = null
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
notifyCanvas?.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the notification is closed, either via close button or via close()
|
* Called when the notification is closed, either via close button or via close()
|
||||||
|
@ -195,9 +217,6 @@ class Notify private constructor() {
|
||||||
@Volatile
|
@Volatile
|
||||||
var onClickAction: Notify.()->Unit = {}
|
var onClickAction: Notify.()->Unit = {}
|
||||||
|
|
||||||
@Volatile
|
|
||||||
var name = DIALOG_ERROR
|
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
var shakeDurationInMillis = 0
|
var shakeDurationInMillis = 0
|
||||||
|
|
||||||
|
@ -293,6 +312,7 @@ class Notify private constructor() {
|
||||||
*/
|
*/
|
||||||
fun theme(theme: Theme): Notify {
|
fun theme(theme: Theme): Notify {
|
||||||
this.theme = theme
|
this.theme = theme
|
||||||
|
notifyCanvas?.refresh()
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,6 +321,7 @@ class Notify private constructor() {
|
||||||
*/
|
*/
|
||||||
fun hideCloseButton(): Notify {
|
fun hideCloseButton(): Notify {
|
||||||
hideCloseButton = true
|
hideCloseButton = true
|
||||||
|
notifyCanvas?.refresh()
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,7 +329,7 @@ class Notify private constructor() {
|
||||||
* Shows the notification with the built-in 'warning' image.
|
* Shows the notification with the built-in 'warning' image.
|
||||||
*/
|
*/
|
||||||
fun showWarning() {
|
fun showWarning() {
|
||||||
name = DIALOG_WARNING
|
title = DIALOG_WARNING
|
||||||
image = getImage(DIALOG_WARNING)
|
image = getImage(DIALOG_WARNING)
|
||||||
show()
|
show()
|
||||||
}
|
}
|
||||||
|
@ -317,7 +338,7 @@ class Notify private constructor() {
|
||||||
* Shows the notification with the built-in 'information' image.
|
* Shows the notification with the built-in 'information' image.
|
||||||
*/
|
*/
|
||||||
fun showInformation() {
|
fun showInformation() {
|
||||||
name = DIALOG_INFORMATION
|
title = "Information"
|
||||||
image = getImage(DIALOG_INFORMATION)
|
image = getImage(DIALOG_INFORMATION)
|
||||||
show()
|
show()
|
||||||
}
|
}
|
||||||
|
@ -326,7 +347,7 @@ class Notify private constructor() {
|
||||||
* Shows the notification with the built-in 'error' image.
|
* Shows the notification with the built-in 'error' image.
|
||||||
*/
|
*/
|
||||||
fun showError() {
|
fun showError() {
|
||||||
name = DIALOG_ERROR
|
title = "Error"
|
||||||
image = getImage(DIALOG_ERROR)
|
image = getImage(DIALOG_ERROR)
|
||||||
show()
|
show()
|
||||||
}
|
}
|
||||||
|
@ -335,7 +356,7 @@ class Notify private constructor() {
|
||||||
* Shows the notification with the built-in 'confirm' image.
|
* Shows the notification with the built-in 'confirm' image.
|
||||||
*/
|
*/
|
||||||
fun showConfirm() {
|
fun showConfirm() {
|
||||||
name = DIALOG_CONFIRM
|
title = "Confirm"
|
||||||
image = getImage(DIALOG_CONFIRM)
|
image = getImage(DIALOG_CONFIRM)
|
||||||
show()
|
show()
|
||||||
}
|
}
|
||||||
|
@ -349,6 +370,10 @@ class Notify private constructor() {
|
||||||
|
|
||||||
// must be done in the swing EDT
|
// must be done in the swing EDT
|
||||||
SwingUtil.invokeAndWaitQuietly {
|
SwingUtil.invokeAndWaitQuietly {
|
||||||
|
if (notify.notifyCanvas != null) {
|
||||||
|
return@invokeAndWaitQuietly
|
||||||
|
}
|
||||||
|
|
||||||
val window = notify.attachedFrame
|
val window = notify.attachedFrame
|
||||||
val shakeDuration = notify.shakeDurationInMillis
|
val shakeDuration = notify.shakeDurationInMillis
|
||||||
val shakeAmp = notify.shakeAmplitude
|
val shakeAmp = notify.shakeAmplitude
|
||||||
|
@ -360,10 +385,10 @@ class Notify private constructor() {
|
||||||
|
|
||||||
if (window == null) {
|
if (window == null) {
|
||||||
notifyPopup = AsDesktop(notify, notifyCanvas)
|
notifyPopup = AsDesktop(notify, notifyCanvas)
|
||||||
look = LookAndFeel(notifyPopup, notifyCanvas, notify, LAFUtil.getGraphics(notify.screen), true)
|
look = AsDesktopLAF(notify, notifyCanvas, notifyPopup, LAFUtil.getGraphics(notify.screen))
|
||||||
} else {
|
} else {
|
||||||
notifyPopup = AsApplication(notify, notifyCanvas)
|
notifyPopup = AsApplication(notify, notifyCanvas)
|
||||||
look = LookAndFeel(window, notifyCanvas, notify, window.bounds, false)
|
look = AsApplicationLAF(notify, notifyCanvas, window, window.bounds)
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyPopup.setVisible(true, look)
|
notifyPopup.setVisible(true, look)
|
||||||
|
@ -372,6 +397,7 @@ class Notify private constructor() {
|
||||||
look.shake(shakeDuration, shakeAmp)
|
look.shake(shakeDuration, shakeAmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notify.notifyCanvas = notifyCanvas
|
||||||
notify.notifyPopup = notifyPopup
|
notify.notifyPopup = notifyPopup
|
||||||
notify.notifyLook = look
|
notify.notifyLook = look
|
||||||
}
|
}
|
||||||
|
@ -431,12 +457,20 @@ class Notify private constructor() {
|
||||||
// called when this notification is closed. called in the swing EDT!
|
// called when this notification is closed. called in the swing EDT!
|
||||||
internal fun onClose() {
|
internal fun onClose() {
|
||||||
this.notifyPopup!!.close()
|
this.notifyPopup!!.close()
|
||||||
|
this.notifyLook!!.close()
|
||||||
|
|
||||||
this.onCloseAction.invoke(this)
|
this.onCloseAction.invoke(this)
|
||||||
|
|
||||||
notifyPopup = null
|
notifyPopup = null
|
||||||
notifyLook = null
|
notifyLook = null
|
||||||
|
notifyCanvas = null
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun onClickAction() {
|
internal fun onClickAction() {
|
||||||
this.onClickAction.invoke(this)
|
this.onClickAction.invoke(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun doLayoutForApp() {
|
||||||
|
notifyLook?.reLayout(attachedFrame!!.bounds)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,11 +48,14 @@ internal class NotifyCanvas(
|
||||||
isFocusable = false
|
isFocusable = false
|
||||||
background = theme.panel_BG
|
background = theme.panel_BG
|
||||||
|
|
||||||
|
|
||||||
// now we setup the rendering of the image
|
// now we setup the rendering of the image
|
||||||
cachedImage = renderBackgroundInfo(notification.title, notification.text, theme, imageIcon)
|
cachedImage = renderBackgroundInfo(notification.title, notification.text, theme, imageIcon)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun refresh() {
|
||||||
|
cachedImage = renderBackgroundInfo(notification.title, notification.text, theme, imageIcon)
|
||||||
|
}
|
||||||
|
|
||||||
override fun paint(g: Graphics) {
|
override fun paint(g: Graphics) {
|
||||||
// we cache the text + image (to another image), and then always render the close + progressbar
|
// we cache the text + image (to another image), and then always render the close + progressbar
|
||||||
|
|
||||||
|
@ -111,6 +114,13 @@ internal class NotifyCanvas(
|
||||||
// draw the progress bar along the bottom
|
// draw the progress bar along the bottom
|
||||||
g2.color = theme.progress_FG
|
g2.color = theme.progress_FG
|
||||||
g2.fillRect(0, PROGRESS_HEIGHT, progress, 2)
|
g2.fillRect(0, PROGRESS_HEIGHT, progress, 2)
|
||||||
|
// if (notification.title == "Notify title 0") {
|
||||||
|
// println("asd")
|
||||||
|
// Toolkit.getDefaultToolkit().sync()
|
||||||
|
// }
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
} finally {
|
} finally {
|
||||||
g2.dispose()
|
g2.dispose()
|
||||||
}
|
}
|
||||||
|
@ -148,7 +158,7 @@ internal class NotifyCanvas(
|
||||||
const val WIDTH = 300
|
const val WIDTH = 300
|
||||||
const val HEIGHT = 87
|
const val HEIGHT = 87
|
||||||
private const val PROGRESS_HEIGHT = HEIGHT - 2
|
private const val PROGRESS_HEIGHT = HEIGHT - 2
|
||||||
private fun renderBackgroundInfo(title: String, notificationText: String, theme: Theme, imageIcon: ImageIcon?): BufferedImage {
|
private fun renderBackgroundInfo(title: String, textBody: String, theme: Theme, imageIcon: ImageIcon?): BufferedImage {
|
||||||
|
|
||||||
val image = BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB)
|
val image = BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB)
|
||||||
val g2 = image.createGraphics()
|
val g2 = image.createGraphics()
|
||||||
|
@ -185,17 +195,17 @@ internal class NotifyCanvas(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the main text
|
// Draw the main text
|
||||||
var length = notificationText.length
|
var length = textBody.length
|
||||||
val text = StringBuilder(length)
|
val text = StringBuilder(length)
|
||||||
|
|
||||||
// are we "html" already? just check for the starting tag and strip off END html tag
|
// are we "html" already? just check for the starting tag and strip off END html tag
|
||||||
if (length >= 13 && notificationText.regionMatches(length - 7, "</html>", 0, 7, ignoreCase = true)) {
|
if (length >= 13 && textBody.regionMatches(length - 7, "</html>", 0, 7, ignoreCase = true)) {
|
||||||
text.append(notificationText)
|
text.append(textBody)
|
||||||
text.delete(text.length - 7, text.length)
|
text.delete(text.length - 7, text.length)
|
||||||
length -= 7
|
length -= 7
|
||||||
} else {
|
} else {
|
||||||
text.append("<html>")
|
text.append("<html>")
|
||||||
text.append(notificationText)
|
text.append(textBody)
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure the text is the correct length
|
// make sure the text is the correct length
|
||||||
|
@ -218,6 +228,7 @@ internal class NotifyCanvas(
|
||||||
} finally {
|
} finally {
|
||||||
g2.dispose()
|
g2.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
return image
|
return image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ package dorkbox.notify
|
||||||
import java.awt.event.WindowAdapter
|
import java.awt.event.WindowAdapter
|
||||||
import java.awt.event.WindowEvent
|
import java.awt.event.WindowEvent
|
||||||
|
|
||||||
internal class WindowAdapter : WindowAdapter() {
|
internal class WindowCloseAdapter : WindowAdapter() {
|
||||||
override fun windowClosing(e: WindowEvent) {
|
override fun windowClosing(e: WindowEvent) {
|
||||||
if (e.newState != WindowEvent.WINDOW_CLOSED) {
|
if (e.newState != WindowEvent.WINDOW_CLOSED) {
|
||||||
val source = e.source as AsDesktop
|
val source = e.source as AsDesktop
|
|
@ -51,8 +51,8 @@ object NotifyTest {
|
||||||
// bottomRightInFrame(3, frame)
|
// bottomRightInFrame(3, frame)
|
||||||
// topLeftInFrame(3, frame)
|
// topLeftInFrame(3, frame)
|
||||||
|
|
||||||
react()
|
// react()
|
||||||
// topRightMonitor(3)
|
topRightMonitor(2)
|
||||||
// bottomLeftScaled(3, frame, image)
|
// bottomLeftScaled(3, frame, image)
|
||||||
// bottomLeftStacking(3, frame, image)
|
// bottomLeftStacking(3, frame, image)
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ object NotifyTest {
|
||||||
.shake(4300, 10)
|
.shake(4300, 10)
|
||||||
// .hideCloseButton() // if the hideButton is visible, then it's possible to change things when clicked
|
// .hideCloseButton() // if the hideButton is visible, then it's possible to change things when clicked
|
||||||
.onClickAction {
|
.onClickAction {
|
||||||
notify.text = "HOWDY"
|
text = "HOWDY"
|
||||||
System.err.println("Notification clicked on!")
|
System.err.println("Notification clicked on!")
|
||||||
}
|
}
|
||||||
notify.show()
|
notify.show()
|
||||||
|
@ -81,7 +81,7 @@ object NotifyTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun topRightMonitor(count: Int) {
|
private fun topRightMonitor(count: Int) {
|
||||||
var notify: Notify
|
var notify: Notify
|
||||||
|
|
||||||
for (i in 0 until count) {
|
for (i in 0 until count) {
|
||||||
|
@ -89,17 +89,17 @@ object NotifyTest {
|
||||||
.title("Notify title $i")
|
.title("Notify title $i")
|
||||||
.text("This is a notification " + i + " popup message This is a notification popup message This is a " +
|
.text("This is a notification " + i + " popup message This is a notification popup message This is a " +
|
||||||
"notification popup message")
|
"notification popup message")
|
||||||
.hideAfter(13000)
|
.hideAfter(130000)
|
||||||
.position(Position.TOP_RIGHT)
|
.position(Position.TOP_RIGHT)
|
||||||
// .setScreen(0)
|
// .setScreen(0)
|
||||||
.theme(Theme.defaultDark)
|
.theme(Theme.defaultDark)
|
||||||
// .shake(1300, 4)
|
// .shake(1300, 4)
|
||||||
.shake(4300, 10)
|
// .shake(4300, 10)
|
||||||
.hideCloseButton()
|
// .hideCloseButton()
|
||||||
.onClickAction { System.err.println("Notification $i clicked on!") }
|
.onClickAction { System.err.println("Notification $i clicked on!") }
|
||||||
notify.show()
|
notify.show()
|
||||||
try {
|
try {
|
||||||
Thread.sleep(3000)
|
Thread.sleep(2000)
|
||||||
} catch (e: InterruptedException) {
|
} catch (e: InterruptedException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user