5
0
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:
Lea Anthony 2020-12-22 18:08:38 +11:00
parent e414eda151
commit 16b872352d
No known key found for this signature in database
GPG Key ID: 33DAF7BB90A58405
18 changed files with 135 additions and 49 deletions

View File

@ -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)

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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),

View File

@ -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)
}

View File

@ -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")

View File

@ -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)

View 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
}

View File

@ -9,6 +9,6 @@ type Options struct {
WebviewIsTransparent bool
WindowBackgroundIsTranslucent bool
Menu *menu.Menu
Tray *menu.Menu
Tray *menu.TrayOptions
ContextMenus *menu.ContextMenus
}

View File

@ -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 {

View File

@ -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>

View File

@ -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,
})

View File

@ -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
}