Fixed issues with shake
This commit is contained in:
parent
097411136b
commit
b67eea2b7a
|
@ -45,8 +45,8 @@ internal class AppAccessor : TweenAccessor<AppNotify> {
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAKE -> {
|
SHAKE -> {
|
||||||
returnValues[0] = target.x.toFloat()
|
returnValues[0] = target.shakeX.toFloat()
|
||||||
returnValues[1] = target.y.toFloat()
|
returnValues[1] = target.shakeY.toFloat()
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ internal class AppAccessor : TweenAccessor<AppNotify> {
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAKE -> {
|
SHAKE -> {
|
||||||
target.setLocationInternal(newValues[0].toInt(), newValues[1].toInt())
|
target.setLocationShake(newValues[0].toInt(), newValues[1].toInt())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,10 +72,12 @@ internal class AppNotify(override val notification: Notify): Canvas(), NotifyTyp
|
||||||
|
|
||||||
// for the progress bar. we directly draw this onscreen
|
// for the progress bar. we directly draw this onscreen
|
||||||
// non-volatile because it's always accessed in the active render thread
|
// non-volatile because it's always accessed in the active render thread
|
||||||
|
private var prevProgress = 0
|
||||||
override var progress = 0
|
override var progress = 0
|
||||||
|
set(value) {
|
||||||
@Volatile
|
prevProgress = field
|
||||||
var mouseOver = false
|
field = value
|
||||||
|
}
|
||||||
|
|
||||||
override var shakeTween: Tween<AppNotify>? = null
|
override var shakeTween: Tween<AppNotify>? = null
|
||||||
override var moveTween: Tween<AppNotify>? = null
|
override var moveTween: Tween<AppNotify>? = null
|
||||||
|
@ -88,6 +90,11 @@ internal class AppNotify(override val notification: Notify): Canvas(), NotifyTyp
|
||||||
override var anchorX = 0
|
override var anchorX = 0
|
||||||
override var anchorY = 0
|
override var anchorY = 0
|
||||||
|
|
||||||
|
// the ONLY reason "shake" works, is because we configure the target X/Y location for moving based on where we WANT the popup to go
|
||||||
|
// and completely ignoring its current position
|
||||||
|
var shakeX = 0
|
||||||
|
var shakeY = 0
|
||||||
|
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
var mouseY = 0
|
var mouseY = 0
|
||||||
|
@ -99,6 +106,9 @@ internal class AppNotify(override val notification: Notify): Canvas(), NotifyTyp
|
||||||
|
|
||||||
// this is on the swing EDT
|
// this is on the swing EDT
|
||||||
init {
|
init {
|
||||||
|
addMouseListener(mouseListener)
|
||||||
|
addMouseMotionListener(mouseListener)
|
||||||
|
|
||||||
val actualSize = Dimension(Notify.WIDTH, Notify.HEIGHT)
|
val actualSize = Dimension(Notify.WIDTH, Notify.HEIGHT)
|
||||||
|
|
||||||
preferredSize = actualSize
|
preferredSize = actualSize
|
||||||
|
@ -110,10 +120,6 @@ internal class AppNotify(override val notification: Notify): Canvas(), NotifyTyp
|
||||||
background = notification.theme.panel_BG
|
background = notification.theme.panel_BG
|
||||||
|
|
||||||
|
|
||||||
addMouseListener(mouseListener)
|
|
||||||
addMouseMotionListener(mouseListener)
|
|
||||||
|
|
||||||
|
|
||||||
idAndPosition = parent.name + ":" + notification.position
|
idAndPosition = parent.name + ":" + notification.position
|
||||||
|
|
||||||
anchorX = getAnchorX(notification.position, parent.bounds)
|
anchorX = getAnchorX(notification.position, parent.bounds)
|
||||||
|
@ -152,14 +158,6 @@ internal class AppNotify(override val notification: Notify): Canvas(), NotifyTyp
|
||||||
refresh()
|
refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getX(): Int {
|
|
||||||
return super.getX()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getY(): Int {
|
|
||||||
return super.getY()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun refresh() {
|
override fun refresh() {
|
||||||
cachedImage = renderBackgroundInfo(notification.title, notification.text, notification.theme, notification.image)
|
cachedImage = renderBackgroundInfo(notification.title, notification.text, notification.theme, notification.image)
|
||||||
cachedClose = renderCloseButton(notification.theme, false)
|
cachedClose = renderCloseButton(notification.theme, false)
|
||||||
|
@ -173,16 +171,8 @@ internal class AppNotify(override val notification: Notify): Canvas(), NotifyTyp
|
||||||
|
|
||||||
override fun paint(g: Graphics) {
|
override fun paint(g: Graphics) {
|
||||||
// we cache the text + image (to an image), the two stats of the close "button" and then always render the close + progressbar
|
// we cache the text + image (to an image), the two stats of the close "button" and then always render the close + progressbar
|
||||||
|
|
||||||
// use our cached image, so we don't have to re-render text/background/etc
|
|
||||||
try {
|
try {
|
||||||
g.drawImage(cachedImage, 0, 0, null)
|
draw(g)
|
||||||
|
|
||||||
if (mouseOver && mouseX >= 280 && mouseY <= 20) {
|
|
||||||
g.drawImage(cachedCloseEnabled, 0, 0, null)
|
|
||||||
} else {
|
|
||||||
g.drawImage(cachedClose, 0, 0, null)
|
|
||||||
}
|
|
||||||
} catch (ignored: Exception) {
|
} catch (ignored: Exception) {
|
||||||
// have also seen (happened after screen/PC was "woken up", in Xubuntu 16.04):
|
// have also seen (happened after screen/PC was "woken up", in Xubuntu 16.04):
|
||||||
// java.lang.ClassCastException:sun.awt.image.BufImgSurfaceData cannot be cast to sun.java2d.xr.XRSurfaceData at sun.java2d.xr.XRPMBlitLoops.cacheToTmpSurface(XRPMBlitLoops.java:148)
|
// java.lang.ClassCastException:sun.awt.image.BufImgSurfaceData cannot be cast to sun.java2d.xr.XRSurfaceData at sun.java2d.xr.XRPMBlitLoops.cacheToTmpSurface(XRPMBlitLoops.java:148)
|
||||||
|
@ -203,25 +193,44 @@ internal class AppNotify(override val notification: Notify): Canvas(), NotifyTyp
|
||||||
|
|
||||||
// try to draw again
|
// try to draw again
|
||||||
try {
|
try {
|
||||||
g.drawImage(cachedImage, 0, 0, null)
|
draw(g)
|
||||||
|
|
||||||
if (mouseOver && mouseX >= NotifyType.closeX && mouseY <= 20) {
|
|
||||||
g.drawImage(cachedCloseEnabled, 0, 0, null)
|
|
||||||
} else {
|
|
||||||
g.drawImage(cachedClose, 0, 0, null)
|
|
||||||
}
|
|
||||||
} catch (ignored2: Exception) {
|
} catch (ignored2: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the progress bar can change, so we always draw it every time
|
// the progress bar can change, so we always draw it every time
|
||||||
if (progress > 0) {
|
if (progress > 0 && prevProgress != progress) {
|
||||||
// draw the progress bar along the bottom
|
// draw the progress bar along the bottom
|
||||||
g.color = notification.theme.progress_FG
|
g.color = notification.theme.progress_FG
|
||||||
g.fillRect(0, Notify.HEIGHT - 2, progress, 2)
|
g.fillRect(0, Notify.HEIGHT - 2, progress, 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun draw(g: Graphics) {
|
||||||
|
g.drawImage(cachedImage, 0, 0, null)
|
||||||
|
|
||||||
|
if (!notification.hideCloseButton) {
|
||||||
|
if (mouseX >= 280 && mouseY <= 20) {
|
||||||
|
g.drawImage(cachedCloseEnabled, 0, 0, null)
|
||||||
|
} else {
|
||||||
|
g.drawImage(cachedClose, 0, 0, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onClick(x: Int, y: Int) {
|
||||||
|
// Check - we were over the 'X' (and thus no notify), or was it in the general area?
|
||||||
|
val isClickOnCloseButton = !notification.hideCloseButton && x >= 280 && y <= 20
|
||||||
|
|
||||||
|
if (isClickOnCloseButton) {
|
||||||
|
// we always close the notification popup
|
||||||
|
notification.onClose()
|
||||||
|
} else {
|
||||||
|
// only call the general click handler IF we click in the general area!
|
||||||
|
notification.onClickAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun setupHide() {
|
override fun setupHide() {
|
||||||
if (hideTween == null && notification.hideAfterDurationInMillis > 0) {
|
if (hideTween == null && notification.hideAfterDurationInMillis > 0) {
|
||||||
// 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)
|
||||||
|
@ -262,7 +271,7 @@ internal class AppNotify(override val notification: Notify): Canvas(), NotifyTyp
|
||||||
.repeatAutoReverse(count, 0f)
|
.repeatAutoReverse(count, 0f)
|
||||||
} else {
|
} else {
|
||||||
val tween = tweenEngine
|
val tween = tweenEngine
|
||||||
.to(this, AppAccessor.X_Y_POS, tweenAccessor, 0.05f)
|
.to(this, AppAccessor.SHAKE, tweenAccessor, 0.05f)
|
||||||
.valueRelative(targetX, targetY)
|
.valueRelative(targetX, targetY)
|
||||||
.repeatAutoReverse(count, 0f)
|
.repeatAutoReverse(count, 0f)
|
||||||
.ease(TweenEquations.Linear)
|
.ease(TweenEquations.Linear)
|
||||||
|
@ -272,19 +281,12 @@ internal class AppNotify(override val notification: Notify): Canvas(), NotifyTyp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onClick(x: Int, y: Int) {
|
fun setLocationShake(x: Int, y: Int) {
|
||||||
// Check - we were over the 'X' (and thus no notify), or was it in the general area?
|
val x1 = getX() - shakeX
|
||||||
|
val y1 = getY() - shakeY
|
||||||
val isClickOnCloseButton = !notification.hideCloseButton && x >= 280 && y <= 20
|
shakeX = x
|
||||||
|
shakeY = y
|
||||||
// reasonable position for detecting mouse over
|
setLocationInternal(x1 + x, y1 + y)
|
||||||
if (isClickOnCloseButton) {
|
|
||||||
// we always close the notification popup
|
|
||||||
notification.onClose()
|
|
||||||
} else {
|
|
||||||
// only call the general click handler IF we click in the general area!
|
|
||||||
notification.onClickAction()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setLocationInternal(x: Int, y: Int) {
|
override fun setLocationInternal(x: Int, y: Int) {
|
||||||
|
@ -292,6 +294,7 @@ internal class AppNotify(override val notification: Notify): Canvas(), NotifyTyp
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is called during parent initialization (before we are initialized), so we cannot access objects here properly!
|
// this is called during parent initialization (before we are initialized), so we cannot access objects here properly!
|
||||||
|
// NOTE: This is present here because DesktopNotify requires it (and consistency is important)
|
||||||
// override fun setLocation(x: Int, y: Int) {
|
// override fun setLocation(x: Int, y: Int) {
|
||||||
// super.setLocation(x, y)
|
// super.setLocation(x, y)
|
||||||
// }
|
// }
|
||||||
|
@ -302,7 +305,6 @@ internal class AppNotify(override val notification: Notify): Canvas(), NotifyTyp
|
||||||
updatePositionsPost(this, this, visible)
|
updatePositionsPost(this, this, visible)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// called on the Swing EDT.
|
// called on the Swing EDT.
|
||||||
override fun close() {
|
override fun close() {
|
||||||
cancelMove()
|
cancelMove()
|
||||||
|
|
|
@ -45,8 +45,8 @@ internal class DesktopAccessor : TweenAccessor<DesktopNotify> {
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAKE -> {
|
SHAKE -> {
|
||||||
returnValues[0] = target.x.toFloat()
|
returnValues[0] = target.shakeX.toFloat()
|
||||||
returnValues[1] = target.y.toFloat()
|
returnValues[1] = target.shakeY.toFloat()
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ internal class DesktopAccessor : TweenAccessor<DesktopNotify> {
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAKE -> {
|
SHAKE -> {
|
||||||
target.setLocationInternal(newValues[0].toInt(), newValues[1].toInt())
|
target.setLocationShake(newValues[0].toInt(), newValues[1].toInt())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,14 +71,16 @@ internal class DesktopNotify(override val notification: Notify) : JWindow(), Not
|
||||||
|
|
||||||
// for the progress bar. we directly draw this onscreen
|
// for the progress bar. we directly draw this onscreen
|
||||||
// non-volatile because it's always accessed in the active render thread
|
// non-volatile because it's always accessed in the active render thread
|
||||||
|
private var prevProgress = 0
|
||||||
override var progress = 0
|
override var progress = 0
|
||||||
|
set(value) {
|
||||||
|
prevProgress = field
|
||||||
|
field = value
|
||||||
|
}
|
||||||
|
|
||||||
// The button is "hittable" from the entire corner
|
// The button is "hittable" from the entire corner
|
||||||
private val closeButton: Rectangle
|
private val closeButton: Rectangle
|
||||||
|
|
||||||
@Volatile
|
|
||||||
var mouseOver = false
|
|
||||||
|
|
||||||
override var shakeTween: Tween<DesktopNotify>? = null
|
override var shakeTween: Tween<DesktopNotify>? = null
|
||||||
override var moveTween: Tween<DesktopNotify>? = null
|
override var moveTween: Tween<DesktopNotify>? = null
|
||||||
override var hideTween: Tween<DesktopNotify>? = null
|
override var hideTween: Tween<DesktopNotify>? = null
|
||||||
|
@ -90,6 +92,11 @@ internal class DesktopNotify(override val notification: Notify) : JWindow(), Not
|
||||||
override var anchorX = 0
|
override var anchorX = 0
|
||||||
override var anchorY = 0
|
override var anchorY = 0
|
||||||
|
|
||||||
|
// the ONLY reason "shake" works, is because we configure the target X/Y location for moving based on where we WANT the popup to go
|
||||||
|
// and completely ignoring its current position
|
||||||
|
var shakeX = 0
|
||||||
|
var shakeY = 0
|
||||||
|
|
||||||
|
|
||||||
// this is on the swing EDT
|
// this is on the swing EDT
|
||||||
init {
|
init {
|
||||||
|
@ -115,14 +122,6 @@ internal class DesktopNotify(override val notification: Notify) : JWindow(), Not
|
||||||
refresh()
|
refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getX(): Int {
|
|
||||||
return super.getX()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getY(): Int {
|
|
||||||
return super.getY()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun refresh() {
|
override fun refresh() {
|
||||||
cachedImage = renderBackgroundInfo(notification.title, notification.text, notification.theme, notification.image)
|
cachedImage = renderBackgroundInfo(notification.title, notification.text, notification.theme, notification.image)
|
||||||
cachedClose = renderCloseButton(notification.theme, false)
|
cachedClose = renderCloseButton(notification.theme, false)
|
||||||
|
@ -138,8 +137,92 @@ internal class DesktopNotify(override val notification: Notify) : JWindow(), Not
|
||||||
anchorY = getAnchorY(notification.position, bounds) + calculateOffset(growDown, point)
|
anchorY = getAnchorY(notification.position, bounds) + calculateOffset(growDown, point)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* have to adjust for offsets when the window-manager has a toolbar that consumes space and prevents overlap.
|
||||||
|
*/
|
||||||
|
private fun calculateOffset(showFromTop: Boolean, point: Point): Int {
|
||||||
|
val gc = ScreenUtil.getMonitorAtLocation(point).defaultConfiguration
|
||||||
|
val screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(gc)
|
||||||
|
|
||||||
|
if (showFromTop) {
|
||||||
|
if (screenInsets.top > 0) {
|
||||||
|
return screenInsets.top - Notify.MARGIN
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (screenInsets.bottom > 0) {
|
||||||
|
return screenInsets.bottom + Notify.MARGIN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun paint(g: Graphics) {
|
||||||
|
// we cache the text + image (to an image), the two states of the close "button" and then always render the progressbar
|
||||||
|
try {
|
||||||
|
draw(g)
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
// have also seen (happened after screen/PC was "woken up", in Xubuntu 16.04):
|
||||||
|
// java.lang.ClassCastException:sun.awt.image.BufImgSurfaceData cannot be cast to sun.java2d.xr.XRSurfaceData at sun.java2d.xr.XRPMBlitLoops.cacheToTmpSurface(XRPMBlitLoops.java:148)
|
||||||
|
// at sun.java2d.xr.XrSwToPMBlit.Blit(XRPMBlitLoops.java:356)
|
||||||
|
// at sun.java2d.SurfaceDataProxy.updateSurfaceData(SurfaceDataProxy.java:498)
|
||||||
|
// at sun.java2d.SurfaceDataProxy.replaceData(SurfaceDataProxy.java:455)
|
||||||
|
// at sun.java2d.SurfaceData.getSourceSurfaceData(SurfaceData.java:233)
|
||||||
|
// at sun.java2d.pipe.DrawImage.renderImageCopy(DrawImage.java:566)
|
||||||
|
// at sun.java2d.pipe.DrawImage.copyImage(DrawImage.java:67)
|
||||||
|
// at sun.java2d.pipe.DrawImage.copyImage(DrawImage.java:1014)
|
||||||
|
// at sun.java2d.pipe.ValidatePipe.copyImage(ValidatePipe.java:186)
|
||||||
|
// at sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:3318)
|
||||||
|
// at sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:3296)
|
||||||
|
// at dorkbox.notify.NotifyCanvas.paint(NotifyCanvas.java:92)
|
||||||
|
|
||||||
|
// redo the cache
|
||||||
|
refresh()
|
||||||
|
|
||||||
|
// try to draw again
|
||||||
|
try {
|
||||||
|
draw(g)
|
||||||
|
} catch (ignored2: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the progress bar can change (only getting bigger!), so we always draw it when it grows
|
||||||
|
if (progress > 0 && prevProgress != progress) {
|
||||||
|
// draw the progress bar along the bottom
|
||||||
|
g.color = notification.theme.progress_FG
|
||||||
|
g.fillRect(0, Notify.HEIGHT - 2, progress, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun draw(g: Graphics) {
|
||||||
|
g.drawImage(cachedImage, 0, 0, null)
|
||||||
|
|
||||||
|
if (!notification.hideCloseButton) {
|
||||||
|
if (closeButton.contains(MouseInfo.getPointerInfo().location)) {
|
||||||
|
g.drawImage(cachedCloseEnabled, 0, 0, null)
|
||||||
|
} else {
|
||||||
|
g.drawImage(cachedClose, 0, 0, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onClick() {
|
||||||
|
// Check - we were over the 'X' (and thus no notify), or was it in the general area
|
||||||
|
val isClickOnCloseButton = !notification.hideCloseButton && closeButton.contains(MouseInfo.getPointerInfo().location)
|
||||||
|
|
||||||
|
if (isClickOnCloseButton) {
|
||||||
|
// we always close the notification popup
|
||||||
|
notification.onClose()
|
||||||
|
} else {
|
||||||
|
// only call the general click handler IF we click in the general area!
|
||||||
|
notification.onClickAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun setupHide() {
|
override fun setupHide() {
|
||||||
if (hideTween == null && notification.hideAfterDurationInMillis > 0) {
|
if (hideTween != null) {
|
||||||
|
hideTween!!.value(Notify.WIDTH.toFloat())
|
||||||
|
} else if (notification.hideAfterDurationInMillis > 0) {
|
||||||
// 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)
|
||||||
val tween = tweenEngine
|
val tween = tweenEngine
|
||||||
.to(this, DesktopAccessor.PROGRESS, tweenAccessor, notification.hideAfterDurationInMillis / 1000.0f)
|
.to(this, DesktopAccessor.PROGRESS, tweenAccessor, notification.hideAfterDurationInMillis / 1000.0f)
|
||||||
|
@ -174,12 +257,12 @@ internal class DesktopNotify(override val notification: Notify) : JWindow(), Not
|
||||||
|
|
||||||
override fun doShake(count: Int, targetX: Float, targetY: Float) {
|
override fun doShake(count: Int, targetX: Float, targetY: Float) {
|
||||||
if (shakeTween != null) {
|
if (shakeTween != null) {
|
||||||
shakeTween!!.valueRelative(targetX, targetY)
|
shakeTween!!.value(targetX, targetY)
|
||||||
.repeatAutoReverse(count, 0f)
|
.repeatAutoReverse(count, 0f)
|
||||||
} else {
|
} else {
|
||||||
val tween = tweenEngine
|
val tween = tweenEngine
|
||||||
.to(this, DesktopAccessor.X_Y_POS, tweenAccessor, 0.05f)
|
.to(this, DesktopAccessor.SHAKE, tweenAccessor, 0.05f)
|
||||||
.valueRelative(targetX, targetY)
|
.value(targetX, targetY)
|
||||||
.repeatAutoReverse(count, 0f)
|
.repeatAutoReverse(count, 0f)
|
||||||
.ease(TweenEquations.Linear)
|
.ease(TweenEquations.Linear)
|
||||||
|
|
||||||
|
@ -188,85 +271,12 @@ internal class DesktopNotify(override val notification: Notify) : JWindow(), Not
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun paint(g: Graphics) {
|
fun setLocationShake(x: Int, y: Int) {
|
||||||
// we cache the text + image (to an image), the two stats of the close "button" and then always render the close + progressbar
|
val x1 = getX() - shakeX
|
||||||
|
val y1 = getY() - shakeY
|
||||||
// use our cached image, so we don't have to re-render text/background/etc
|
shakeX = x
|
||||||
try {
|
shakeY = y
|
||||||
g.drawImage(cachedImage, 0, 0, null)
|
setLocationInternal(x1 + x, y1 + y)
|
||||||
|
|
||||||
if (mouseOver && closeButton.contains(MouseInfo.getPointerInfo().location)) {
|
|
||||||
g.drawImage(cachedCloseEnabled, 0, 0, null)
|
|
||||||
} else {
|
|
||||||
g.drawImage(cachedClose, 0, 0, null)
|
|
||||||
}
|
|
||||||
} catch (ignored: Exception) {
|
|
||||||
// have also seen (happened after screen/PC was "woken up", in Xubuntu 16.04):
|
|
||||||
// java.lang.ClassCastException:sun.awt.image.BufImgSurfaceData cannot be cast to sun.java2d.xr.XRSurfaceData at sun.java2d.xr.XRPMBlitLoops.cacheToTmpSurface(XRPMBlitLoops.java:148)
|
|
||||||
// at sun.java2d.xr.XrSwToPMBlit.Blit(XRPMBlitLoops.java:356)
|
|
||||||
// at sun.java2d.SurfaceDataProxy.updateSurfaceData(SurfaceDataProxy.java:498)
|
|
||||||
// at sun.java2d.SurfaceDataProxy.replaceData(SurfaceDataProxy.java:455)
|
|
||||||
// at sun.java2d.SurfaceData.getSourceSurfaceData(SurfaceData.java:233)
|
|
||||||
// at sun.java2d.pipe.DrawImage.renderImageCopy(DrawImage.java:566)
|
|
||||||
// at sun.java2d.pipe.DrawImage.copyImage(DrawImage.java:67)
|
|
||||||
// at sun.java2d.pipe.DrawImage.copyImage(DrawImage.java:1014)
|
|
||||||
// at sun.java2d.pipe.ValidatePipe.copyImage(ValidatePipe.java:186)
|
|
||||||
// at sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:3318)
|
|
||||||
// at sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:3296)
|
|
||||||
// at dorkbox.notify.NotifyCanvas.paint(NotifyCanvas.java:92)
|
|
||||||
|
|
||||||
// redo the cache
|
|
||||||
refresh()
|
|
||||||
|
|
||||||
// try to draw again
|
|
||||||
try {
|
|
||||||
g.drawImage(cachedImage, 0, 0, null)
|
|
||||||
|
|
||||||
if (mouseOver && closeButton.contains(MouseInfo.getPointerInfo().location)) {
|
|
||||||
g.drawImage(cachedCloseEnabled, 0, 0, null)
|
|
||||||
} else {
|
|
||||||
g.drawImage(cachedClose, 0, 0, null)
|
|
||||||
}
|
|
||||||
} catch (ignored2: Exception) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// the progress bar can change, so we always draw it every time
|
|
||||||
if (progress > 0) {
|
|
||||||
// draw the progress bar along the bottom
|
|
||||||
g.color = notification.theme.progress_FG
|
|
||||||
g.fillRect(0, Notify.HEIGHT - 2, progress, 2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fun onClick() {
|
|
||||||
// Check - we were over the 'X', or was it in the general area?
|
|
||||||
if (mouseOver && closeButton.contains(MouseInfo.getPointerInfo().location)) {
|
|
||||||
// we always close the notification popup
|
|
||||||
notification.onClose()
|
|
||||||
} else {
|
|
||||||
// only call the general click handler IF we click in the general area!
|
|
||||||
notification.onClickAction()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* have to adjust for offsets when the window-manager has a toolbar that consumes space and prevents overlap.
|
|
||||||
*/
|
|
||||||
private fun calculateOffset(showFromTop: Boolean, point: Point): Int {
|
|
||||||
val gc = ScreenUtil.getMonitorAtLocation(point).defaultConfiguration
|
|
||||||
val screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(gc)
|
|
||||||
|
|
||||||
if (showFromTop) {
|
|
||||||
if (screenInsets.top > 0) {
|
|
||||||
return screenInsets.top - Notify.MARGIN
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (screenInsets.bottom > 0) {
|
|
||||||
return screenInsets.bottom + Notify.MARGIN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setLocationInternal(x: Int, y: Int) {
|
override fun setLocationInternal(x: Int, y: Int) {
|
||||||
|
@ -301,14 +311,14 @@ internal class DesktopNotify(override val notification: Notify) : JWindow(), Not
|
||||||
cancelHide()
|
cancelHide()
|
||||||
cancelShake()
|
cancelShake()
|
||||||
|
|
||||||
super.setVisible(false)
|
|
||||||
|
|
||||||
removeWindowListener(windowCloseListener)
|
removeWindowListener(windowCloseListener)
|
||||||
removeMouseMotionListener(mouseListener)
|
removeMouseMotionListener(mouseListener)
|
||||||
removeMouseListener(mouseListener)
|
removeMouseListener(mouseListener)
|
||||||
|
|
||||||
updatePositionsPre(component = this, notify = this, visible = false)
|
updatePositionsPre(component = this, notify = this, visible = false)
|
||||||
|
|
||||||
|
super.setVisible(false)
|
||||||
|
|
||||||
removeAll()
|
removeAll()
|
||||||
dispose()
|
dispose()
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,8 +53,6 @@ internal interface NotifyType<T> {
|
||||||
var anchorX: Int
|
var anchorX: Int
|
||||||
var anchorY: Int
|
var anchorY: Int
|
||||||
|
|
||||||
fun getX(): Int
|
|
||||||
fun getY(): Int
|
|
||||||
|
|
||||||
// for the progress bar. we directly draw this onscreen
|
// for the progress bar. we directly draw this onscreen
|
||||||
// non-volatile because it's always accessed in the active render thread
|
// non-volatile because it's always accessed in the active render thread
|
||||||
|
|
Loading…
Reference in New Issue
Block a user