mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-02 21:29:09 +08:00
Support Text label tray
This commit is contained in:
parent
e414eda151
commit
16b872352d
@ -94,7 +94,7 @@ func (a *App) Run() error {
|
||||
|
||||
// Start the runtime
|
||||
applicationMenu := options.GetApplicationMenu(a.options)
|
||||
trayMenu := options.GetTrayMenu(a.options)
|
||||
trayMenu := options.GetTray(a.options)
|
||||
contextMenus := options.GetContextMenus(a.options)
|
||||
|
||||
runtimesubsystem, err := subsystem.NewRuntime(a.servicebus, a.logger, applicationMenu, trayMenu, contextMenus)
|
||||
|
@ -35,5 +35,6 @@ extern void DarkModeEnabled(void *appPointer, char *callbackID);
|
||||
extern void UpdateMenu(void *app, char *menuAsJSON);
|
||||
extern void UpdateTray(void *app, char *menuAsJSON);
|
||||
extern void UpdateContextMenus(void *app, char *contextMenusAsJSON);
|
||||
extern void UpdateTrayLabel(void *app, const char *label);
|
||||
|
||||
#endif
|
||||
|
@ -188,6 +188,9 @@ func (c *Client) UpdateTray(menu *menu.Menu) {
|
||||
}
|
||||
C.UpdateTray(c.app.app, c.app.string2CString(string(trayMenuJSON)))
|
||||
}
|
||||
func (c *Client) UpdateTrayLabel(label string) {
|
||||
C.UpdateTrayLabel(c.app.app, c.app.string2CString(label))
|
||||
}
|
||||
|
||||
func (c *Client) UpdateContextMenus(contextMenus *menu.ContextMenus) {
|
||||
|
||||
|
@ -213,6 +213,8 @@ struct Application {
|
||||
|
||||
// Tray
|
||||
const char *trayMenuAsJSON;
|
||||
const char *trayType;
|
||||
const char *trayLabel;
|
||||
JsonNode *processedTrayMenu;
|
||||
id statusItem;
|
||||
|
||||
@ -794,6 +796,8 @@ void* NewApplication(const char *title, int width, int height, int resizable, in
|
||||
|
||||
// Tray
|
||||
result->trayMenuAsJSON = NULL;
|
||||
result->trayType = NULL;
|
||||
result->trayLabel = NULL;
|
||||
result->processedTrayMenu = NULL;
|
||||
result->statusItem = NULL;
|
||||
|
||||
@ -1302,8 +1306,10 @@ void SetMenu(struct Application *app, const char *menuAsJSON) {
|
||||
}
|
||||
|
||||
// SetTray sets the initial tray menu for the application
|
||||
void SetTray(struct Application *app, const char *trayMenuAsJSON) {
|
||||
void SetTray(struct Application *app, const char *trayMenuAsJSON, const char *trayType, const char *trayLabel) {
|
||||
app->trayMenuAsJSON = trayMenuAsJSON;
|
||||
app->trayType = trayType;
|
||||
app->trayLabel = trayLabel;
|
||||
}
|
||||
|
||||
// SetContextMenus sets the context menu map for this application
|
||||
@ -2217,6 +2223,11 @@ void parseContextMenus(struct Application *app) {
|
||||
// dumpContextMenus(app);
|
||||
}
|
||||
|
||||
void UpdateTrayLabel(struct Application *app, const char *label) {
|
||||
id statusBarButton = msg(app->statusItem, s("button"));
|
||||
msg(statusBarButton, s("setTitle:"), str(label));
|
||||
}
|
||||
|
||||
void parseTrayData(struct Application *app) {
|
||||
|
||||
// Allocate the hashmaps we need
|
||||
@ -2235,13 +2246,20 @@ void parseTrayData(struct Application *app) {
|
||||
msg(statusItem, s("retain"));
|
||||
id statusBarButton = msg(statusItem, s("button"));
|
||||
|
||||
// If we have a tray icon
|
||||
if ( trayIconLength > 0 ) {
|
||||
id imageData = msg(c("NSData"), s("dataWithBytes:length:"), trayIcon, trayIconLength);
|
||||
id trayImage = ALLOC("NSImage");
|
||||
msg(trayImage, s("initWithData:"), imageData);
|
||||
msg(statusBarButton, s("setImage:"), trayImage);
|
||||
if( STREQ(app->trayType, "icon") ) {
|
||||
// If we have a tray icon
|
||||
if ( trayIconLength > 0 ) {
|
||||
id imageData = msg(c("NSData"), s("dataWithBytes:length:"), trayIcon, trayIconLength);
|
||||
id trayImage = ALLOC("NSImage");
|
||||
msg(trayImage, s("initWithData:"), imageData);
|
||||
msg(statusBarButton, s("setImage:"), trayImage);
|
||||
}
|
||||
}
|
||||
if( STREQ(app->trayType, "label") ) {
|
||||
// If we have a tray icon
|
||||
msg(statusBarButton, s("setTitle:"), str(app->trayLabel));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Parse the processed menu json
|
||||
|
@ -83,7 +83,7 @@ func (a *Application) processPlatformSettings() error {
|
||||
}
|
||||
|
||||
// Process tray
|
||||
tray := options.GetTrayMenu(a.config)
|
||||
tray := options.GetTray(a.config)
|
||||
if tray != nil {
|
||||
|
||||
/*
|
||||
@ -94,12 +94,12 @@ func (a *Application) processPlatformSettings() error {
|
||||
a list of all members of the group and the number of members
|
||||
in the group (this last one is for optimisation at the C layer).
|
||||
*/
|
||||
processedMenu := NewProcessedMenu(tray)
|
||||
processedMenu := NewProcessedMenu(tray.Menu)
|
||||
trayMenuJSON, err := json.Marshal(processedMenu)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
C.SetTray(a.app, a.string2CString(string(trayMenuJSON)))
|
||||
C.SetTray(a.app, a.string2CString(string(trayMenuJSON)), a.string2CString(string(tray.Type)), a.string2CString(tray.Label))
|
||||
}
|
||||
|
||||
// Process context menus
|
||||
|
@ -13,7 +13,7 @@ extern void SetAppearance(void *, const char *);
|
||||
extern void WebviewIsTransparent(void *);
|
||||
extern void WindowBackgroundIsTranslucent(void *);
|
||||
extern void SetMenu(void *, const char *);
|
||||
extern void SetTray(void *, const char *);
|
||||
extern void SetTray(void *, const char *, const char *, const char *);
|
||||
extern void SetContextMenus(void *, const char *);
|
||||
|
||||
#endif
|
@ -33,6 +33,7 @@ type Client interface {
|
||||
DarkModeEnabled(callbackID string)
|
||||
UpdateMenu(menu *menu.Menu)
|
||||
UpdateTray(menu *menu.Menu)
|
||||
UpdateTrayLabel(label string)
|
||||
UpdateContextMenus(contextMenus *menu.ContextMenus)
|
||||
}
|
||||
|
||||
|
@ -508,6 +508,21 @@ func (d *Dispatcher) processTrayMessage(result *servicebus.Message) {
|
||||
client.frontend.UpdateTray(updatedMenu)
|
||||
}
|
||||
|
||||
case "setlabel":
|
||||
|
||||
updatedLabel, ok := result.Data().(string)
|
||||
if !ok {
|
||||
d.logger.Error("Invalid data for 'trayfrontend:setlabel' : %#v",
|
||||
result.Data())
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Work out what we mean in a multi window environment...
|
||||
// For now we will just pick the first one
|
||||
for _, client := range d.clients {
|
||||
client.frontend.UpdateTrayLabel(updatedLabel)
|
||||
}
|
||||
|
||||
default:
|
||||
d.logger.Error("Unknown menufrontend command: %s", command)
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ type Runtime struct {
|
||||
}
|
||||
|
||||
// New creates a new runtime
|
||||
func New(serviceBus *servicebus.ServiceBus, menu *menu.Menu, trayMenu *menu.Menu, contextMenus *menu.ContextMenus) *Runtime {
|
||||
func New(serviceBus *servicebus.ServiceBus, menu *menu.Menu, trayMenu *menu.TrayOptions, contextMenus *menu.ContextMenus) *Runtime {
|
||||
result := &Runtime{
|
||||
Browser: newBrowser(),
|
||||
Events: newEvents(serviceBus),
|
||||
|
@ -12,15 +12,16 @@ type Tray interface {
|
||||
Update()
|
||||
GetByID(menuID string) *menu.MenuItem
|
||||
RemoveByID(id string) bool
|
||||
SetLabel(label string)
|
||||
}
|
||||
|
||||
type trayRuntime struct {
|
||||
bus *servicebus.ServiceBus
|
||||
trayMenu *menu.Menu
|
||||
trayMenu *menu.TrayOptions
|
||||
}
|
||||
|
||||
// newTray creates a new Menu struct
|
||||
func newTray(bus *servicebus.ServiceBus, menu *menu.Menu) Tray {
|
||||
func newTray(bus *servicebus.ServiceBus, menu *menu.TrayOptions) Tray {
|
||||
return &trayRuntime{
|
||||
bus: bus,
|
||||
trayMenu: menu,
|
||||
@ -39,10 +40,14 @@ func (t *trayRuntime) Update() {
|
||||
t.bus.Publish("tray:update", t.trayMenu)
|
||||
}
|
||||
|
||||
func (t *trayRuntime) SetLabel(label string) {
|
||||
t.bus.Publish("tray:setlabel", label)
|
||||
}
|
||||
|
||||
func (t *trayRuntime) GetByID(menuID string) *menu.MenuItem {
|
||||
return t.trayMenu.GetByID(menuID)
|
||||
return t.trayMenu.Menu.GetByID(menuID)
|
||||
}
|
||||
|
||||
func (t *trayRuntime) RemoveByID(id string) bool {
|
||||
return t.trayMenu.RemoveByID(id)
|
||||
return t.trayMenu.Menu.RemoveByID(id)
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ type Runtime struct {
|
||||
}
|
||||
|
||||
// NewRuntime creates a new runtime subsystem
|
||||
func NewRuntime(bus *servicebus.ServiceBus, logger *logger.Logger, menu *menu.Menu, trayMenu *menu.Menu, contextMenus *menu.ContextMenus) (*Runtime, error) {
|
||||
func NewRuntime(bus *servicebus.ServiceBus, logger *logger.Logger, menu *menu.Menu, trayMenu *menu.TrayOptions, contextMenus *menu.ContextMenus) (*Runtime, error) {
|
||||
|
||||
// Register quit channel
|
||||
quitChannel, err := bus.Subscribe("quit")
|
||||
|
@ -26,14 +26,14 @@ type Tray struct {
|
||||
logger logger.CustomLogger
|
||||
|
||||
// The tray menu
|
||||
trayMenu *menu.Menu
|
||||
trayMenu *menu.TrayOptions
|
||||
|
||||
// Service Bus
|
||||
bus *servicebus.ServiceBus
|
||||
}
|
||||
|
||||
// NewTray creates a new menu subsystem
|
||||
func NewTray(trayMenu *menu.Menu, bus *servicebus.ServiceBus,
|
||||
func NewTray(trayMenu *menu.TrayOptions, bus *servicebus.ServiceBus,
|
||||
logger *logger.Logger) (*Tray, error) {
|
||||
|
||||
// Register quit channel
|
||||
@ -59,7 +59,7 @@ func NewTray(trayMenu *menu.Menu, bus *servicebus.ServiceBus,
|
||||
}
|
||||
|
||||
// Build up list of item/id pairs
|
||||
result.processMenu(trayMenu)
|
||||
result.processMenu(trayMenu.Menu)
|
||||
|
||||
return result, nil
|
||||
}
|
||||
@ -118,6 +118,14 @@ func (t *Tray) Start() error {
|
||||
// Notify frontend of menu change
|
||||
t.bus.Publish("trayfrontend:update", updatedMenu)
|
||||
|
||||
// Make sure we catch any menu updates
|
||||
case "setlabel":
|
||||
updatedLabel := menuMessage.Data().(string)
|
||||
t.trayMenu.Label = updatedLabel
|
||||
|
||||
// Notify frontend of menu change
|
||||
t.bus.Publish("trayfrontend:setlabel", updatedLabel)
|
||||
|
||||
default:
|
||||
t.logger.Error("unknown tray message: %+v", menuMessage)
|
||||
}
|
||||
@ -134,7 +142,7 @@ func (t *Tray) Start() error {
|
||||
func (t *Tray) processMenu(trayMenu *menu.Menu) {
|
||||
// Initialise the variables
|
||||
t.menuItems = make(map[string]*menu.MenuItem)
|
||||
t.trayMenu = trayMenu
|
||||
t.trayMenu.Menu = trayMenu
|
||||
|
||||
for _, item := range trayMenu.Items {
|
||||
t.processMenuItem(item)
|
||||
|
14
v2/pkg/menu/trayoptions.go
Normal file
14
v2/pkg/menu/trayoptions.go
Normal file
@ -0,0 +1,14 @@
|
||||
package menu
|
||||
|
||||
type TrayType string
|
||||
|
||||
const (
|
||||
TrayIcon TrayType = "icon"
|
||||
TrayLabel TrayType = "label"
|
||||
)
|
||||
|
||||
type TrayOptions struct {
|
||||
Type TrayType
|
||||
Label string
|
||||
Menu *Menu
|
||||
}
|
@ -9,6 +9,6 @@ type Options struct {
|
||||
WebviewIsTransparent bool
|
||||
WindowBackgroundIsTranslucent bool
|
||||
Menu *menu.Menu
|
||||
Tray *menu.Menu
|
||||
Tray *menu.TrayOptions
|
||||
ContextMenus *menu.ContextMenus
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ type App struct {
|
||||
DevTools bool
|
||||
RGBA int
|
||||
ContextMenus *menu.ContextMenus
|
||||
Tray *menu.Menu
|
||||
Tray *menu.TrayOptions
|
||||
Menu *menu.Menu
|
||||
Mac *mac.Options
|
||||
Logger logger.Logger `json:"-"`
|
||||
@ -49,8 +49,8 @@ func MergeDefaults(appoptions *App) {
|
||||
|
||||
}
|
||||
|
||||
func GetTrayMenu(appoptions *App) *menu.Menu {
|
||||
var result *menu.Menu
|
||||
func GetTray(appoptions *App) *menu.TrayOptions {
|
||||
var result *menu.TrayOptions
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
if appoptions.Mac != nil {
|
||||
|
@ -35,10 +35,8 @@
|
||||
break;
|
||||
case 'Hide':
|
||||
windowRuntime.Hide();
|
||||
setTimeout( windowRuntime.Show, 3000 );
|
||||
case 'Minimise':
|
||||
windowRuntime.Hide();
|
||||
setTimeout( windowRuntime.Unminimise, 3000 );
|
||||
windowRuntime.Minimise();
|
||||
default:
|
||||
windowRuntime[windowAction]();
|
||||
}
|
||||
@ -92,8 +90,6 @@
|
||||
<div class="custom-radio">
|
||||
<input type="radio" name="window" bind:group="{windowAction}" id="{id}-{option}" value="{option}" disabled={disabledActions.includes(option)}>
|
||||
<label for="{id}-{option}">{option}
|
||||
{#if option == 'Hide' } - Show() will be called after 3 seconds {/if}
|
||||
{#if option == 'Minimise' } - Unminimise() will be called after 3 seconds {/if}
|
||||
{#if option == 'SetTitle' && !setTitleEnabled} - disabled as there is no title displayed {/if}
|
||||
</label>
|
||||
|
||||
|
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/mac"
|
||||
"log"
|
||||
@ -27,7 +28,12 @@ func main() {
|
||||
// Comment out line below to see Window.SetTitle() work
|
||||
TitleBar: mac.TitleBarHiddenInset(),
|
||||
Menu: createApplicationMenu(),
|
||||
Tray: createApplicationTray(),
|
||||
Tray: &menu.TrayOptions{
|
||||
//Type: menu.TrayLabel,
|
||||
Type: menu.TrayIcon,
|
||||
Label: "Hi Go BitBar!",
|
||||
Menu: createApplicationTray(),
|
||||
},
|
||||
},
|
||||
LogLevel: logger.TRACE,
|
||||
})
|
||||
|
@ -1,8 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||
@ -16,6 +19,8 @@ type Tray struct {
|
||||
lock sync.Mutex
|
||||
dynamicMenuItems map[string]*menu.MenuItem
|
||||
anotherDynamicMenuCounter int
|
||||
|
||||
done bool
|
||||
}
|
||||
|
||||
// WailsInit is called at application startup
|
||||
@ -26,25 +31,42 @@ func (t *Tray) WailsInit(runtime *wails.Runtime) error {
|
||||
// Setup Menu Listeners
|
||||
t.runtime.Tray.On("Show Window", func(mi *menu.MenuItem) {
|
||||
t.runtime.Window.Show()
|
||||
showWindow := t.runtime.Tray.GetByID("Show Window")
|
||||
hideWindow := t.runtime.Tray.GetByID("Hide Window")
|
||||
showWindow.Hidden = true
|
||||
hideWindow.Hidden = false
|
||||
t.runtime.Tray.Update()
|
||||
})
|
||||
t.runtime.Tray.On("Hide Window", func(mi *menu.MenuItem) {
|
||||
t.runtime.Window.Hide()
|
||||
showWindow := t.runtime.Tray.GetByID("Show Window")
|
||||
hideWindow := t.runtime.Tray.GetByID("Hide Window")
|
||||
showWindow.Hidden = false
|
||||
hideWindow.Hidden = true
|
||||
t.runtime.Tray.Update()
|
||||
|
||||
})
|
||||
|
||||
t.runtime.Tray.On("Minimise Window", func(mi *menu.MenuItem) {
|
||||
t.runtime.Window.Minimise()
|
||||
})
|
||||
|
||||
t.runtime.Tray.On("Unminimise Window", func(mi *menu.MenuItem) {
|
||||
t.runtime.Window.Unminimise()
|
||||
})
|
||||
|
||||
// Start ticker
|
||||
//go t.startTicker()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Tray) WailsShutdown() {
|
||||
t.done = true
|
||||
}
|
||||
|
||||
func (t *Tray) startTicker() {
|
||||
time.Sleep(1 * time.Second)
|
||||
ticker := time.NewTicker(1 * time.Second)
|
||||
for t.done == false {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
r := rand.Intn(100)
|
||||
t.runtime.Tray.SetLabel(fmt.Sprintf("CPU: %d", r))
|
||||
}
|
||||
}
|
||||
ticker.Stop()
|
||||
}
|
||||
|
||||
func (t *Tray) incrementcounter() int {
|
||||
t.dynamicMenuCounter++
|
||||
return t.dynamicMenuCounter
|
||||
@ -119,12 +141,9 @@ func (t *Tray) removeMenu(_ *menu.MenuItem) {
|
||||
|
||||
func createApplicationTray() *menu.Menu {
|
||||
trayMenu := &menu.Menu{}
|
||||
trayMenu.Append(&menu.MenuItem{
|
||||
ID: "Show Window",
|
||||
Label: "Show Window",
|
||||
Type: menu.TextType,
|
||||
Hidden: true,
|
||||
})
|
||||
trayMenu.Append(menu.Text("Show Window", "Show Window"))
|
||||
trayMenu.Append(menu.Text("Hide Window", "Hide Window"))
|
||||
trayMenu.Append(menu.Text("Minimise Window", "Minimise Window"))
|
||||
trayMenu.Append(menu.Text("Unminimise Window", "Unminimise Window"))
|
||||
return trayMenu
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user