Icon and app name

This commit is contained in:
Rukira 2026-03-04 16:18:25 +00:00
parent 910fbc3497
commit 8a437abb0f
2 changed files with 64 additions and 32 deletions

View file

@ -69,8 +69,16 @@ compose.desktop {
nativeDistributions { nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageName = "com.rukira.wowbackup" packageName = "WoW Backup"
packageVersion = appVersion packageVersion = appVersion
macOS {
bundleID = "com.rukira.wowbackup"
}
windows {
upgradeUuid = "e5a8b2c4-1f3d-4a6e-9b7c-2d8f0e1a3b5c"
}
} }
} }
} }

View file

@ -1,45 +1,69 @@
package com.rukira.wowbackup.ui package com.rukira.wowbackup.ui
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.toComposeImageBitmap
import androidx.compose.ui.graphics.Path import java.awt.BasicStroke
import androidx.compose.ui.geometry.Size import java.awt.Graphics2D
import java.awt.RenderingHints
import java.awt.geom.GeneralPath
import java.awt.image.BufferedImage
/** /**
* A simple shield-shaped tray icon drawn in code. * A simple shield-shaped tray icon with a "W" letter inside.
* Rendered via Java2D BufferedImage for reliable AWT system tray display.
* Works with macOS template images (-Dapple.awt.enableTemplateImages=true) * Works with macOS template images (-Dapple.awt.enableTemplateImages=true)
* which will automatically adapt to dark/light menu bar. * which will automatically adapt to dark/light menu bar.
*/ */
fun trayIconPainter(): Painter = object : Painter() { fun trayIconPainter(): Painter {
override val intrinsicSize = Size(32f, 32f) val size = 128
val img = BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB)
val g: Graphics2D = img.createGraphics()
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY)
override fun DrawScope.onDraw() { val w = size.toFloat()
val w = size.width val h = size.toFloat()
val h = size.height
// Shield shape // Shield shape (filled black)
val shield = Path().apply { val shield = GeneralPath().apply {
moveTo(w * 0.5f, h * 0.05f) moveTo((w * 0.5f).toDouble(), (h * 0.05f).toDouble())
lineTo(w * 0.9f, h * 0.2f) lineTo((w * 0.9f).toDouble(), (h * 0.2f).toDouble())
lineTo(w * 0.9f, h * 0.5f) lineTo((w * 0.9f).toDouble(), (h * 0.5f).toDouble())
cubicTo(w * 0.9f, h * 0.75f, w * 0.5f, h * 0.95f, w * 0.5f, h * 0.95f) curveTo(
cubicTo(w * 0.5f, h * 0.95f, w * 0.1f, h * 0.75f, w * 0.1f, h * 0.5f) (w * 0.9f).toDouble(), (h * 0.75f).toDouble(),
lineTo(w * 0.1f, h * 0.2f) (w * 0.5f).toDouble(), (h * 0.95f).toDouble(),
close() (w * 0.5f).toDouble(), (h * 0.95f).toDouble(),
}
drawPath(shield, Color.Black)
// Checkmark inside the shield
val check = Path().apply {
moveTo(w * 0.25f, h * 0.48f)
lineTo(w * 0.42f, h * 0.65f)
lineTo(w * 0.72f, h * 0.32f)
}
drawPath(
check,
Color.White,
style = androidx.compose.ui.graphics.drawscope.Stroke(width = w * 0.08f),
) )
curveTo(
(w * 0.5f).toDouble(), (h * 0.95f).toDouble(),
(w * 0.1f).toDouble(), (h * 0.75f).toDouble(),
(w * 0.1f).toDouble(), (h * 0.5f).toDouble(),
)
lineTo((w * 0.1f).toDouble(), (h * 0.2f).toDouble())
closePath()
} }
// Create the "W" stroke shape to carve out of the shield
val letterW = GeneralPath().apply {
moveTo((w * 0.22f).toDouble(), (h * 0.30f).toDouble())
lineTo((w * 0.35f).toDouble(), (h * 0.70f).toDouble())
lineTo((w * 0.50f).toDouble(), (h * 0.45f).toDouble())
lineTo((w * 0.65f).toDouble(), (h * 0.70f).toDouble())
lineTo((w * 0.78f).toDouble(), (h * 0.30f).toDouble())
}
val wStroke = BasicStroke(w * 0.06f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)
val wShape = wStroke.createStrokedShape(letterW)
// Subtract the W from the shield using Area
val shieldArea = java.awt.geom.Area(shield)
shieldArea.subtract(java.awt.geom.Area(wShape))
g.color = java.awt.Color.BLACK
g.fill(shieldArea)
g.dispose()
return BitmapPainter(img.toComposeImageBitmap())
} }