mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-04 01:31:54 +08:00
add set custom badge and update docs/examples/readmes
This commit is contained in:
parent
51c0d1dcdc
commit
900da01ad7
@ -74,6 +74,30 @@ badgeService.SetBadge("3")
|
|||||||
badgeService.SetBadge("New")
|
badgeService.SetBadge("New")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Setting a Custom Badge
|
||||||
|
|
||||||
|
Set a badge on the application tile/dock icon with one-off options applied:
|
||||||
|
|
||||||
|
#### Go
|
||||||
|
```go
|
||||||
|
options := badge.Options{
|
||||||
|
BackgroundColour: color.RGBA{0, 255, 255, 255},
|
||||||
|
FontName: "arialb.ttf", // System font
|
||||||
|
FontSize: 16,
|
||||||
|
SmallFontSize: 10,
|
||||||
|
TextColour: color.RGBA{0, 0, 0, 255},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a default badge
|
||||||
|
badgeService.SetCustomBadge("", options)
|
||||||
|
|
||||||
|
// Set a numeric badge
|
||||||
|
badgeService.SetCustomBadge("3", options)
|
||||||
|
|
||||||
|
// Set a text badge
|
||||||
|
badgeService.SetCustomBadge("New", options)
|
||||||
|
```
|
||||||
|
|
||||||
### Removing a Badge
|
### Removing a Badge
|
||||||
|
|
||||||
Remove the badge from the application icon:
|
Remove the badge from the application icon:
|
||||||
|
@ -35,7 +35,7 @@ app := application.New(application.Options{
|
|||||||
|
|
||||||
### Setting a Badge
|
### Setting a Badge
|
||||||
|
|
||||||
Set a badge on the application tile/dock icon:
|
Set a badge on the application tile/dock icon with the global options applied:
|
||||||
|
|
||||||
#### Go
|
#### Go
|
||||||
```go
|
```go
|
||||||
@ -63,6 +63,54 @@ SetBadge("3")
|
|||||||
SetBadge("New")
|
SetBadge("New")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Setting a Custom Badge
|
||||||
|
|
||||||
|
Set a badge on the application tile/dock icon with one-off options applied:
|
||||||
|
|
||||||
|
#### Go
|
||||||
|
```go
|
||||||
|
// Set a default badge
|
||||||
|
badgeService.SetCustomBadge("")
|
||||||
|
|
||||||
|
// Set a numeric badge
|
||||||
|
badgeService.SetCustomBadge("3")
|
||||||
|
|
||||||
|
// Set a text badge
|
||||||
|
badgeService.SetCustomBadge("New")
|
||||||
|
```
|
||||||
|
|
||||||
|
#### JS
|
||||||
|
```js
|
||||||
|
import {SetCustomBadge} from "../bindings/github.com/wailsapp/wails/v3/pkg/services/badge/service";
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
BackgroundColour: RGBA.createFrom({
|
||||||
|
R: 0,
|
||||||
|
G: 255,
|
||||||
|
B: 255,
|
||||||
|
A: 255,
|
||||||
|
}),
|
||||||
|
FontName: "arialb.ttf", // System font
|
||||||
|
FontSize: 16,
|
||||||
|
SmallFontSize: 10,
|
||||||
|
TextColour: RGBA.createFrom({
|
||||||
|
R: 0,
|
||||||
|
G: 0,
|
||||||
|
B: 0,
|
||||||
|
A: 255,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a default badge
|
||||||
|
SetCustomBadge("", options)
|
||||||
|
|
||||||
|
// Set a numeric badge
|
||||||
|
SetCustomBadge("3", options)
|
||||||
|
|
||||||
|
// Set a text badge
|
||||||
|
SetCustomBadge("New", options)
|
||||||
|
```
|
||||||
|
|
||||||
### Removing a Badge
|
### Removing a Badge
|
||||||
|
|
||||||
Remove the badge from the application icon:
|
Remove the badge from the application icon:
|
||||||
|
@ -5,3 +5,7 @@ import * as Service from "./service.js";
|
|||||||
export {
|
export {
|
||||||
Service
|
Service
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
Options
|
||||||
|
} from "./models.js";
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore: Unused imports
|
||||||
|
import { Create as $Create } from "@wailsio/runtime";
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore: Unused imports
|
||||||
|
import * as color$0 from "../../../../../../../image/color/models.js";
|
||||||
|
|
||||||
|
export class Options {
|
||||||
|
"TextColour": color$0.RGBA;
|
||||||
|
"BackgroundColour": color$0.RGBA;
|
||||||
|
"FontName": string;
|
||||||
|
"FontSize": number;
|
||||||
|
"SmallFontSize": number;
|
||||||
|
|
||||||
|
/** Creates a new Options instance. */
|
||||||
|
constructor($$source: Partial<Options> = {}) {
|
||||||
|
if (!("TextColour" in $$source)) {
|
||||||
|
this["TextColour"] = (new color$0.RGBA());
|
||||||
|
}
|
||||||
|
if (!("BackgroundColour" in $$source)) {
|
||||||
|
this["BackgroundColour"] = (new color$0.RGBA());
|
||||||
|
}
|
||||||
|
if (!("FontName" in $$source)) {
|
||||||
|
this["FontName"] = "";
|
||||||
|
}
|
||||||
|
if (!("FontSize" in $$source)) {
|
||||||
|
this["FontSize"] = 0;
|
||||||
|
}
|
||||||
|
if (!("SmallFontSize" in $$source)) {
|
||||||
|
this["SmallFontSize"] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign(this, $$source);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Options instance from a string or object.
|
||||||
|
*/
|
||||||
|
static createFrom($$source: any = {}): Options {
|
||||||
|
const $$createField0_0 = $$createType0;
|
||||||
|
const $$createField1_0 = $$createType0;
|
||||||
|
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||||
|
if ("TextColour" in $$parsedSource) {
|
||||||
|
$$parsedSource["TextColour"] = $$createField0_0($$parsedSource["TextColour"]);
|
||||||
|
}
|
||||||
|
if ("BackgroundColour" in $$parsedSource) {
|
||||||
|
$$parsedSource["BackgroundColour"] = $$createField1_0($$parsedSource["BackgroundColour"]);
|
||||||
|
}
|
||||||
|
return new Options($$parsedSource as Partial<Options>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private type creation functions
|
||||||
|
const $$createType0 = color$0.RGBA.createFrom;
|
@ -10,6 +10,10 @@
|
|||||||
// @ts-ignore: Unused imports
|
// @ts-ignore: Unused imports
|
||||||
import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "@wailsio/runtime";
|
import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "@wailsio/runtime";
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore: Unused imports
|
||||||
|
import * as $models from "./models.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RemoveBadge removes the badge label from the application icon.
|
* RemoveBadge removes the badge label from the application icon.
|
||||||
*/
|
*/
|
||||||
@ -23,3 +27,7 @@ export function RemoveBadge(): $CancellablePromise<void> {
|
|||||||
export function SetBadge(label: string): $CancellablePromise<void> {
|
export function SetBadge(label: string): $CancellablePromise<void> {
|
||||||
return $Call.ByID(3052354152, label);
|
return $Call.ByID(3052354152, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function SetCustomBadge(label: string, options: $models.Options): $CancellablePromise<void> {
|
||||||
|
return $Call.ByID(921166821, label, options);
|
||||||
|
}
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
export {
|
||||||
|
RGBA
|
||||||
|
} from "./models.js";
|
@ -0,0 +1,46 @@
|
|||||||
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore: Unused imports
|
||||||
|
import { Create as $Create } from "@wailsio/runtime";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RGBA represents a traditional 32-bit alpha-premultiplied color, having 8
|
||||||
|
* bits for each of red, green, blue and alpha.
|
||||||
|
*
|
||||||
|
* An alpha-premultiplied color component C has been scaled by alpha (A), so
|
||||||
|
* has valid values 0 <= C <= A.
|
||||||
|
*/
|
||||||
|
export class RGBA {
|
||||||
|
"R": number;
|
||||||
|
"G": number;
|
||||||
|
"B": number;
|
||||||
|
"A": number;
|
||||||
|
|
||||||
|
/** Creates a new RGBA instance. */
|
||||||
|
constructor($$source: Partial<RGBA> = {}) {
|
||||||
|
if (!("R" in $$source)) {
|
||||||
|
this["R"] = 0;
|
||||||
|
}
|
||||||
|
if (!("G" in $$source)) {
|
||||||
|
this["G"] = 0;
|
||||||
|
}
|
||||||
|
if (!("B" in $$source)) {
|
||||||
|
this["B"] = 0;
|
||||||
|
}
|
||||||
|
if (!("A" in $$source)) {
|
||||||
|
this["A"] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign(this, $$source);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new RGBA instance from a string or object.
|
||||||
|
*/
|
||||||
|
static createFrom($$source: any = {}): RGBA {
|
||||||
|
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||||
|
return new RGBA($$parsedSource as Partial<RGBA>);
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,6 @@
|
|||||||
|
var __defProp = Object.defineProperty;
|
||||||
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
||||||
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
||||||
(function polyfill() {
|
(function polyfill() {
|
||||||
const relList = document.createElement("link").relList;
|
const relList = document.createElement("link").relList;
|
||||||
if (relList && relList.supports && relList.supports("modulepreload")) {
|
if (relList && relList.supports && relList.supports("modulepreload")) {
|
||||||
@ -1329,12 +1332,67 @@ function RemoveBadge() {
|
|||||||
function SetBadge(label) {
|
function SetBadge(label) {
|
||||||
return ByID(3052354152, label);
|
return ByID(3052354152, label);
|
||||||
}
|
}
|
||||||
|
function SetCustomBadge(label, options) {
|
||||||
|
return ByID(921166821, label, options);
|
||||||
|
}
|
||||||
|
class RGBA {
|
||||||
|
/** Creates a new RGBA instance. */
|
||||||
|
constructor($$source = {}) {
|
||||||
|
__publicField(this, "R");
|
||||||
|
__publicField(this, "G");
|
||||||
|
__publicField(this, "B");
|
||||||
|
__publicField(this, "A");
|
||||||
|
if (!("R" in $$source)) {
|
||||||
|
this["R"] = 0;
|
||||||
|
}
|
||||||
|
if (!("G" in $$source)) {
|
||||||
|
this["G"] = 0;
|
||||||
|
}
|
||||||
|
if (!("B" in $$source)) {
|
||||||
|
this["B"] = 0;
|
||||||
|
}
|
||||||
|
if (!("A" in $$source)) {
|
||||||
|
this["A"] = 0;
|
||||||
|
}
|
||||||
|
Object.assign(this, $$source);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Creates a new RGBA instance from a string or object.
|
||||||
|
*/
|
||||||
|
static createFrom($$source = {}) {
|
||||||
|
let $$parsedSource = typeof $$source === "string" ? JSON.parse($$source) : $$source;
|
||||||
|
return new RGBA($$parsedSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const setCustomButton = document.getElementById("set-custom");
|
||||||
const setButton = document.getElementById("set");
|
const setButton = document.getElementById("set");
|
||||||
const removeButton = document.getElementById("remove");
|
const removeButton = document.getElementById("remove");
|
||||||
const setButtonUsingGo = document.getElementById("set-go");
|
const setButtonUsingGo = document.getElementById("set-go");
|
||||||
const removeButtonUsingGo = document.getElementById("remove-go");
|
const removeButtonUsingGo = document.getElementById("remove-go");
|
||||||
const labelElement = document.getElementById("label");
|
const labelElement = document.getElementById("label");
|
||||||
const timeElement = document.getElementById("time");
|
const timeElement = document.getElementById("time");
|
||||||
|
setCustomButton.addEventListener("click", () => {
|
||||||
|
console.log("click!");
|
||||||
|
let label = labelElement.value;
|
||||||
|
SetCustomBadge(label, {
|
||||||
|
BackgroundColour: RGBA.createFrom({
|
||||||
|
R: 0,
|
||||||
|
G: 255,
|
||||||
|
B: 255,
|
||||||
|
A: 255
|
||||||
|
}),
|
||||||
|
FontName: "arialb.ttf",
|
||||||
|
// System font
|
||||||
|
FontSize: 16,
|
||||||
|
SmallFontSize: 10,
|
||||||
|
TextColour: RGBA.createFrom({
|
||||||
|
R: 0,
|
||||||
|
G: 0,
|
||||||
|
B: 0,
|
||||||
|
A: 255
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
setButton.addEventListener("click", () => {
|
setButton.addEventListener("click", () => {
|
||||||
let label = labelElement.value;
|
let label = labelElement.value;
|
||||||
SetBadge(label);
|
SetBadge(label);
|
@ -6,7 +6,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
<link rel="stylesheet" href="/style.css"/>
|
<link rel="stylesheet" href="/style.css"/>
|
||||||
<title>Wails App</title>
|
<title>Wails App</title>
|
||||||
<script type="module" crossorigin src="/assets/index-edhLCYCH.js"></script>
|
<script type="module" crossorigin src="/assets/index-DHsC0KxN.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@ -23,6 +23,7 @@
|
|||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="input-box" id="input">
|
<div class="input-box" id="input">
|
||||||
<input class="input" id="label" type="text" autocomplete="off"/>
|
<input class="input" id="label" type="text" autocomplete="off"/>
|
||||||
|
<button class="btn" id="set-custom">Set Custom</button>
|
||||||
<button class="btn" id="set">Set</button>
|
<button class="btn" id="set">Set</button>
|
||||||
<button class="btn" id="remove">Remove</button>
|
<button class="btn" id="remove">Remove</button>
|
||||||
<button class="btn" id="set-go">Set using Go</button>
|
<button class="btn" id="set-go">Set using Go</button>
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="input-box" id="input">
|
<div class="input-box" id="input">
|
||||||
<input class="input" id="label" type="text" autocomplete="off"/>
|
<input class="input" id="label" type="text" autocomplete="off"/>
|
||||||
|
<button class="btn" id="set-custom">Set Custom</button>
|
||||||
<button class="btn" id="set">Set</button>
|
<button class="btn" id="set">Set</button>
|
||||||
<button class="btn" id="remove">Remove</button>
|
<button class="btn" id="remove">Remove</button>
|
||||||
<button class="btn" id="set-go">Set using Go</button>
|
<button class="btn" id="set-go">Set using Go</button>
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import {Events} from "@wailsio/runtime";
|
import {Events} from "@wailsio/runtime";
|
||||||
import {SetBadge, RemoveBadge} from "../bindings/github.com/wailsapp/wails/v3/pkg/services/badge/service";
|
import {SetBadge, RemoveBadge, SetCustomBadge} from "../bindings/github.com/wailsapp/wails/v3/pkg/services/badge/service";
|
||||||
|
import { RGBA } from "../bindings/image/color/models";
|
||||||
|
|
||||||
|
const setCustomButton = document.getElementById('set-custom')! as HTMLButtonElement;
|
||||||
const setButton = document.getElementById('set')! as HTMLButtonElement;
|
const setButton = document.getElementById('set')! as HTMLButtonElement;
|
||||||
const removeButton = document.getElementById('remove')! as HTMLButtonElement;
|
const removeButton = document.getElementById('remove')! as HTMLButtonElement;
|
||||||
const setButtonUsingGo = document.getElementById('set-go')! as HTMLButtonElement;
|
const setButtonUsingGo = document.getElementById('set-go')! as HTMLButtonElement;
|
||||||
@ -8,6 +10,28 @@ const removeButtonUsingGo = document.getElementById('remove-go')! as HTMLButtonE
|
|||||||
const labelElement : HTMLInputElement = document.getElementById('label')! as HTMLInputElement;
|
const labelElement : HTMLInputElement = document.getElementById('label')! as HTMLInputElement;
|
||||||
const timeElement = document.getElementById('time')! as HTMLDivElement;
|
const timeElement = document.getElementById('time')! as HTMLDivElement;
|
||||||
|
|
||||||
|
setCustomButton.addEventListener('click', () => {
|
||||||
|
console.log("click!")
|
||||||
|
let label = (labelElement as HTMLInputElement).value
|
||||||
|
SetCustomBadge(label, {
|
||||||
|
BackgroundColour: RGBA.createFrom({
|
||||||
|
R: 0,
|
||||||
|
G: 255,
|
||||||
|
B: 255,
|
||||||
|
A: 255,
|
||||||
|
}),
|
||||||
|
FontName: "arialb.ttf", // System font
|
||||||
|
FontSize: 16,
|
||||||
|
SmallFontSize: 10,
|
||||||
|
TextColour: RGBA.createFrom({
|
||||||
|
R: 0,
|
||||||
|
G: 0,
|
||||||
|
B: 0,
|
||||||
|
A: 255,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
setButton.addEventListener('click', () => {
|
setButton.addEventListener('click', () => {
|
||||||
let label = (labelElement as HTMLInputElement).value
|
let label = (labelElement as HTMLInputElement).value
|
||||||
SetBadge(label);
|
SetBadge(label);
|
||||||
|
@ -13,6 +13,7 @@ type platformBadge interface {
|
|||||||
Shutdown() error
|
Shutdown() error
|
||||||
|
|
||||||
SetBadge(label string) error
|
SetBadge(label string) error
|
||||||
|
SetCustomBadge(label string, options Options) error
|
||||||
RemoveBadge() error
|
RemoveBadge() error
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +50,10 @@ func (b *Service) SetBadge(label string) error {
|
|||||||
return b.impl.SetBadge(label)
|
return b.impl.SetBadge(label)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Service) SetCustomBadge(label string, options Options) error {
|
||||||
|
return b.impl.SetCustomBadge(label, options)
|
||||||
|
}
|
||||||
|
|
||||||
// RemoveBadge removes the badge label from the application icon.
|
// RemoveBadge removes the badge label from the application icon.
|
||||||
func (b *Service) RemoveBadge() error {
|
func (b *Service) RemoveBadge() error {
|
||||||
return b.impl.RemoveBadge()
|
return b.impl.RemoveBadge()
|
||||||
|
@ -61,6 +61,12 @@ func (d *darwinBadge) SetBadge(label string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetCustomBadge is not supported on macOS, SetBadge is called instead.
|
||||||
|
// (Windows-specific)
|
||||||
|
func (d *darwinBadge) SetCustomBadge(label string, options Options) error {
|
||||||
|
return d.SetBadge(label)
|
||||||
|
}
|
||||||
|
|
||||||
// RemoveBadge removes the badge label from the application icon.
|
// RemoveBadge removes the badge label from the application icon.
|
||||||
func (d *darwinBadge) RemoveBadge() error {
|
func (d *darwinBadge) RemoveBadge() error {
|
||||||
C.setBadge(nil)
|
C.setBadge(nil)
|
||||||
|
@ -110,6 +110,63 @@ func (w *windowsBadge) SetBadge(label string) error {
|
|||||||
return w.taskbar.SetOverlayIcon(hwnd, hicon, nil)
|
return w.taskbar.SetOverlayIcon(hwnd, hicon, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetCustomBadge sets the badge label on the application icon with one-off options.
|
||||||
|
func (w *windowsBadge) SetCustomBadge(label string, options Options) error {
|
||||||
|
if w.taskbar == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
app := application.Get()
|
||||||
|
if app == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
window := app.CurrentWindow()
|
||||||
|
if window == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
hwnd, err := window.NativeWindowHandle()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const badgeSize = 32
|
||||||
|
|
||||||
|
img := image.NewRGBA(image.Rect(0, 0, badgeSize, badgeSize))
|
||||||
|
|
||||||
|
backgroundColour := options.BackgroundColour
|
||||||
|
radius := badgeSize / 2
|
||||||
|
centerX, centerY := radius, radius
|
||||||
|
|
||||||
|
for y := 0; y < badgeSize; y++ {
|
||||||
|
for x := 0; x < badgeSize; x++ {
|
||||||
|
dx := float64(x - centerX)
|
||||||
|
dy := float64(y - centerY)
|
||||||
|
|
||||||
|
if dx*dx+dy*dy < float64(radius*radius) {
|
||||||
|
img.Set(x, y, backgroundColour)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var hicon w32.HICON
|
||||||
|
if label == "" {
|
||||||
|
hicon, err = createBadgeIcon(badgeSize, img, options)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hicon, err = createBadgeIconWithText(w, label, badgeSize, img, options)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer w32.DestroyIcon(hicon)
|
||||||
|
|
||||||
|
return w.taskbar.SetOverlayIcon(hwnd, hicon, nil)
|
||||||
|
}
|
||||||
|
|
||||||
// RemoveBadge removes the badge label from the application icon.
|
// RemoveBadge removes the badge label from the application icon.
|
||||||
func (w *windowsBadge) RemoveBadge() error {
|
func (w *windowsBadge) RemoveBadge() error {
|
||||||
if w.taskbar == nil {
|
if w.taskbar == nil {
|
||||||
@ -160,9 +217,33 @@ func (w *windowsBadge) createBadgeIcon() (w32.HICON, error) {
|
|||||||
return hicon, err
|
return hicon, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createBadgeIcon(badgeSize int, img *image.RGBA, options Options) (w32.HICON, error) {
|
||||||
|
radius := badgeSize / 2
|
||||||
|
centerX, centerY := radius, radius
|
||||||
|
innerRadius := badgeSize / 5
|
||||||
|
|
||||||
|
for y := 0; y < badgeSize; y++ {
|
||||||
|
for x := 0; x < badgeSize; x++ {
|
||||||
|
dx := float64(x - centerX)
|
||||||
|
dy := float64(y - centerY)
|
||||||
|
|
||||||
|
if dx*dx+dy*dy < float64(innerRadius*innerRadius) {
|
||||||
|
img.Set(x, y, options.TextColour)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err := png.Encode(&buf, img); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
hicon, err := w32.CreateSmallHIconFromImage(buf.Bytes())
|
||||||
|
return hicon, err
|
||||||
|
}
|
||||||
|
|
||||||
// createBadgeIconWithText creates a badge icon with the specified text.
|
// createBadgeIconWithText creates a badge icon with the specified text.
|
||||||
func (w *windowsBadge) createBadgeIconWithText(label string) (w32.HICON, error) {
|
func (w *windowsBadge) createBadgeIconWithText(label string) (w32.HICON, error) {
|
||||||
|
|
||||||
fontPath := w.fontManager.FindFontOrDefault(w.options.FontName)
|
fontPath := w.fontManager.FindFontOrDefault(w.options.FontName)
|
||||||
if fontPath == "" {
|
if fontPath == "" {
|
||||||
return w.createBadgeIcon()
|
return w.createBadgeIcon()
|
||||||
@ -215,6 +296,59 @@ func (w *windowsBadge) createBadgeIconWithText(label string) (w32.HICON, error)
|
|||||||
return w32.CreateSmallHIconFromImage(buf.Bytes())
|
return w32.CreateSmallHIconFromImage(buf.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createBadgeIconWithText(w *windowsBadge, label string, badgeSize int, img *image.RGBA, options Options) (w32.HICON, error) {
|
||||||
|
fontPath := w.fontManager.FindFontOrDefault(options.FontName)
|
||||||
|
if fontPath == "" {
|
||||||
|
return createBadgeIcon(badgeSize, img, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
fontBytes, err := os.ReadFile(fontPath)
|
||||||
|
if err != nil {
|
||||||
|
return createBadgeIcon(badgeSize, img, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
ttf, err := opentype.Parse(fontBytes)
|
||||||
|
if err != nil {
|
||||||
|
return createBadgeIcon(badgeSize, img, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
fontSize := float64(options.FontSize)
|
||||||
|
if len(label) > 1 {
|
||||||
|
fontSize = float64(options.SmallFontSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get DPI of the current screen
|
||||||
|
screen := w32.GetDesktopWindow()
|
||||||
|
dpi := w32.GetDpiForWindow(screen)
|
||||||
|
|
||||||
|
face, err := opentype.NewFace(ttf, &opentype.FaceOptions{
|
||||||
|
Size: fontSize,
|
||||||
|
DPI: float64(dpi),
|
||||||
|
Hinting: font.HintingFull,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return createBadgeIcon(badgeSize, img, options)
|
||||||
|
}
|
||||||
|
defer face.Close()
|
||||||
|
|
||||||
|
d := &font.Drawer{
|
||||||
|
Dst: img,
|
||||||
|
Src: image.NewUniform(options.TextColour),
|
||||||
|
Face: face,
|
||||||
|
}
|
||||||
|
|
||||||
|
textWidth := d.MeasureString(label).Ceil()
|
||||||
|
d.Dot = fixed.P((badgeSize-textWidth)/2, int(float64(badgeSize)/2+fontSize/2))
|
||||||
|
d.DrawString(label)
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err := png.Encode(&buf, img); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return w32.CreateSmallHIconFromImage(buf.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
// createBadge creates a circular badge with the specified background color.
|
// createBadge creates a circular badge with the specified background color.
|
||||||
func (w *windowsBadge) createBadge() {
|
func (w *windowsBadge) createBadge() {
|
||||||
w.badgeSize = 32
|
w.badgeSize = 32
|
||||||
|
Loading…
Reference in New Issue
Block a user