chore(gui): add AX usage examples
This commit is contained in:
parent
d3443d4be9
commit
274a81689c
12 changed files with 70 additions and 17 deletions
|
|
@ -4,6 +4,7 @@ package systray
|
|||
import "forge.lthn.ai/core/go/pkg/core"
|
||||
|
||||
// SetMenu sets a dynamic menu on the tray from TrayMenuItem descriptors.
|
||||
// Use: _ = m.SetMenu([]TrayMenuItem{{Label: "Quit", ActionID: "quit"}})
|
||||
func (m *Manager) SetMenu(items []TrayMenuItem) error {
|
||||
if m.tray == nil {
|
||||
return core.E("systray.SetMenu", "tray not initialised", nil)
|
||||
|
|
@ -54,6 +55,7 @@ func (m *Manager) buildMenuInto(menu PlatformMenu, items []TrayMenuItem) {
|
|||
}
|
||||
|
||||
// RegisterCallback registers a callback for a menu action ID.
|
||||
// Use: m.RegisterCallback("quit", func() { _ = app.Quit() })
|
||||
func (m *Manager) RegisterCallback(actionID string, callback func()) {
|
||||
m.mu.Lock()
|
||||
m.callbacks[actionID] = callback
|
||||
|
|
@ -61,6 +63,7 @@ func (m *Manager) RegisterCallback(actionID string, callback func()) {
|
|||
}
|
||||
|
||||
// UnregisterCallback removes a callback.
|
||||
// Use: m.UnregisterCallback("quit")
|
||||
func (m *Manager) UnregisterCallback(actionID string) {
|
||||
m.mu.Lock()
|
||||
delete(m.callbacks, actionID)
|
||||
|
|
@ -68,6 +71,7 @@ func (m *Manager) UnregisterCallback(actionID string) {
|
|||
}
|
||||
|
||||
// GetCallback returns the callback for an action ID.
|
||||
// Use: callback, ok := m.GetCallback("quit")
|
||||
func (m *Manager) GetCallback(actionID string) (func(), bool) {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
|
|
@ -76,6 +80,7 @@ func (m *Manager) GetCallback(actionID string) (func(), bool) {
|
|||
}
|
||||
|
||||
// GetInfo returns tray status information.
|
||||
// Use: info := m.GetInfo()
|
||||
func (m *Manager) GetInfo() map[string]any {
|
||||
return map[string]any{
|
||||
"active": m.IsActive(),
|
||||
|
|
|
|||
|
|
@ -2,41 +2,52 @@ package systray
|
|||
|
||||
// QueryConfig requests this service's config section from the display orchestrator.
|
||||
// Result: map[string]any
|
||||
// Use: result, _, err := c.QUERY(systray.QueryConfig{})
|
||||
type QueryConfig struct{}
|
||||
|
||||
// --- Tasks ---
|
||||
|
||||
// TaskSetTrayIcon sets the tray icon.
|
||||
// Use: _, _, err := c.PERFORM(systray.TaskSetTrayIcon{Data: iconBytes})
|
||||
type TaskSetTrayIcon struct{ Data []byte }
|
||||
|
||||
// TaskSetTooltip updates the tray tooltip text.
|
||||
// Use: _, _, err := c.PERFORM(systray.TaskSetTooltip{Tooltip: "Core is ready"})
|
||||
type TaskSetTooltip struct{ Tooltip string }
|
||||
|
||||
// TaskSetLabel updates the tray label text.
|
||||
// Use: _, _, err := c.PERFORM(systray.TaskSetLabel{Label: "Core"})
|
||||
type TaskSetLabel struct{ Label string }
|
||||
|
||||
// TaskSetTrayMenu sets the tray menu items.
|
||||
// Use: _, _, err := c.PERFORM(systray.TaskSetTrayMenu{Items: items})
|
||||
type TaskSetTrayMenu struct{ Items []TrayMenuItem }
|
||||
|
||||
// TaskShowPanel shows the tray panel window.
|
||||
// Use: _, _, err := c.PERFORM(systray.TaskShowPanel{})
|
||||
type TaskShowPanel struct{}
|
||||
|
||||
// TaskHidePanel hides the tray panel window.
|
||||
// Use: _, _, err := c.PERFORM(systray.TaskHidePanel{})
|
||||
type TaskHidePanel struct{}
|
||||
|
||||
// TaskShowMessage shows a tray message or notification.
|
||||
// Use: _, _, err := c.PERFORM(systray.TaskShowMessage{Title: "Core", Message: "Sync complete"})
|
||||
type TaskShowMessage struct {
|
||||
Title string `json:"title"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// TaskSaveConfig persists this service's config section via the display orchestrator.
|
||||
// Use: _, _, err := c.PERFORM(systray.TaskSaveConfig{Value: map[string]any{"tooltip": "Core"}})
|
||||
type TaskSaveConfig struct{ Value map[string]any }
|
||||
|
||||
// --- Actions ---
|
||||
|
||||
// ActionTrayClicked is broadcast when the tray icon is clicked.
|
||||
// Use: _ = c.ACTION(systray.ActionTrayClicked{})
|
||||
type ActionTrayClicked struct{}
|
||||
|
||||
// ActionTrayMenuItemClicked is broadcast when a tray menu item is clicked.
|
||||
// Use: _ = c.ACTION(systray.ActionTrayMenuItemClicked{ActionID: "quit"})
|
||||
type ActionTrayMenuItemClicked struct{ ActionID string }
|
||||
|
|
|
|||
|
|
@ -1,11 +1,19 @@
|
|||
package systray
|
||||
|
||||
// MockPlatform is an exported mock for cross-package integration tests.
|
||||
// Use: platform := systray.NewMockPlatform()
|
||||
type MockPlatform struct{}
|
||||
|
||||
// NewMockPlatform creates a tray platform mock.
|
||||
// Use: platform := systray.NewMockPlatform()
|
||||
func NewMockPlatform() *MockPlatform { return &MockPlatform{} }
|
||||
|
||||
// NewTray creates a mock tray handle for tests.
|
||||
// Use: tray := platform.NewTray()
|
||||
func (m *MockPlatform) NewTray() PlatformTray { return &exportedMockTray{} }
|
||||
|
||||
// NewMenu creates a mock tray menu for tests.
|
||||
// Use: menu := platform.NewMenu()
|
||||
func (m *MockPlatform) NewMenu() PlatformMenu { return &exportedMockMenu{} }
|
||||
|
||||
type exportedMockTray struct {
|
||||
|
|
|
|||
|
|
@ -2,12 +2,14 @@
|
|||
package systray
|
||||
|
||||
// Platform abstracts the system tray backend.
|
||||
// Use: var p systray.Platform
|
||||
type Platform interface {
|
||||
NewTray() PlatformTray
|
||||
NewMenu() PlatformMenu // Menu factory for building tray menus
|
||||
}
|
||||
|
||||
// PlatformTray is a live tray handle from the backend.
|
||||
// Use: var tray systray.PlatformTray
|
||||
type PlatformTray interface {
|
||||
SetIcon(data []byte)
|
||||
SetTemplateIcon(data []byte)
|
||||
|
|
@ -18,6 +20,7 @@ type PlatformTray interface {
|
|||
}
|
||||
|
||||
// PlatformMenu is a tray menu built by the backend.
|
||||
// Use: var menu systray.PlatformMenu
|
||||
type PlatformMenu interface {
|
||||
Add(label string) PlatformMenuItem
|
||||
AddSeparator()
|
||||
|
|
@ -25,6 +28,7 @@ type PlatformMenu interface {
|
|||
}
|
||||
|
||||
// PlatformMenuItem is a single item in a tray menu.
|
||||
// Use: var item systray.PlatformMenuItem
|
||||
type PlatformMenuItem interface {
|
||||
SetTooltip(text string)
|
||||
SetChecked(checked bool)
|
||||
|
|
@ -36,6 +40,7 @@ type PlatformMenuItem interface {
|
|||
// WindowHandle is a cross-package interface for window operations.
|
||||
// Defined locally to avoid circular imports (display imports systray).
|
||||
// pkg/window.PlatformWindow satisfies this implicitly.
|
||||
// Use: var w systray.WindowHandle
|
||||
type WindowHandle interface {
|
||||
Name() string
|
||||
Show()
|
||||
|
|
|
|||
|
|
@ -16,10 +16,7 @@ import (
|
|||
type Options struct{}
|
||||
|
||||
// Service manages system tray operations via Core tasks.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// svc := &systray.Service{}
|
||||
// Use: svc := &systray.Service{}
|
||||
type Service struct {
|
||||
*core.ServiceRuntime[Options]
|
||||
manager *Manager
|
||||
|
|
@ -28,10 +25,7 @@ type Service struct {
|
|||
}
|
||||
|
||||
// OnStartup loads tray config and registers task handlers.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// _ = svc.OnStartup(context.Background())
|
||||
// Use: _ = svc.OnStartup(context.Background())
|
||||
func (s *Service) OnStartup(ctx context.Context) error {
|
||||
cfg, handled, _ := s.Core().QUERY(QueryConfig{})
|
||||
if handled {
|
||||
|
|
@ -118,6 +112,7 @@ func (s *Service) showTrayMessage(title, message string) error {
|
|||
}
|
||||
|
||||
// Manager returns the underlying systray Manager.
|
||||
// Use: manager := svc.Manager()
|
||||
func (s *Service) Manager() *Manager {
|
||||
return s.manager
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,10 +12,7 @@ import (
|
|||
var defaultIcon []byte
|
||||
|
||||
// Manager manages the system tray lifecycle.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// manager := systray.NewManager(platform)
|
||||
// Use: manager := systray.NewManager(platform)
|
||||
type Manager struct {
|
||||
platform Platform
|
||||
tray PlatformTray
|
||||
|
|
@ -30,10 +27,7 @@ type Manager struct {
|
|||
}
|
||||
|
||||
// NewManager creates a systray Manager.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// manager := systray.NewManager(platform)
|
||||
// Use: manager := systray.NewManager(platform)
|
||||
func NewManager(platform Platform) *Manager {
|
||||
return &Manager{
|
||||
platform: platform,
|
||||
|
|
@ -42,6 +36,7 @@ func NewManager(platform Platform) *Manager {
|
|||
}
|
||||
|
||||
// Setup creates the system tray with default icon and tooltip.
|
||||
// Use: _ = manager.Setup("Core", "Core")
|
||||
func (m *Manager) Setup(tooltip, label string) error {
|
||||
m.tray = m.platform.NewTray()
|
||||
if m.tray == nil {
|
||||
|
|
@ -57,6 +52,7 @@ func (m *Manager) Setup(tooltip, label string) error {
|
|||
}
|
||||
|
||||
// SetIcon sets the tray icon.
|
||||
// Use: _ = manager.SetIcon(iconBytes)
|
||||
func (m *Manager) SetIcon(data []byte) error {
|
||||
if m.tray == nil {
|
||||
return core.E("systray.SetIcon", "tray not initialised", nil)
|
||||
|
|
@ -67,6 +63,7 @@ func (m *Manager) SetIcon(data []byte) error {
|
|||
}
|
||||
|
||||
// SetTemplateIcon sets the template icon (macOS).
|
||||
// Use: _ = manager.SetTemplateIcon(iconBytes)
|
||||
func (m *Manager) SetTemplateIcon(data []byte) error {
|
||||
if m.tray == nil {
|
||||
return core.E("systray.SetTemplateIcon", "tray not initialised", nil)
|
||||
|
|
@ -77,6 +74,7 @@ func (m *Manager) SetTemplateIcon(data []byte) error {
|
|||
}
|
||||
|
||||
// SetTooltip sets the tray tooltip.
|
||||
// Use: _ = manager.SetTooltip("Core is ready")
|
||||
func (m *Manager) SetTooltip(text string) error {
|
||||
if m.tray == nil {
|
||||
return core.E("systray.SetTooltip", "tray not initialised", nil)
|
||||
|
|
@ -87,6 +85,7 @@ func (m *Manager) SetTooltip(text string) error {
|
|||
}
|
||||
|
||||
// SetLabel sets the tray label.
|
||||
// Use: _ = manager.SetLabel("Core")
|
||||
func (m *Manager) SetLabel(text string) error {
|
||||
if m.tray == nil {
|
||||
return core.E("systray.SetLabel", "tray not initialised", nil)
|
||||
|
|
@ -97,6 +96,7 @@ func (m *Manager) SetLabel(text string) error {
|
|||
}
|
||||
|
||||
// AttachWindow attaches a panel window to the tray.
|
||||
// Use: _ = manager.AttachWindow(windowHandle)
|
||||
func (m *Manager) AttachWindow(w WindowHandle) error {
|
||||
if m.tray == nil {
|
||||
return core.E("systray.AttachWindow", "tray not initialised", nil)
|
||||
|
|
@ -109,6 +109,7 @@ func (m *Manager) AttachWindow(w WindowHandle) error {
|
|||
}
|
||||
|
||||
// ShowPanel shows the attached tray panel window if one is configured.
|
||||
// Use: _ = manager.ShowPanel()
|
||||
func (m *Manager) ShowPanel() error {
|
||||
m.mu.RLock()
|
||||
w := m.panelWindow
|
||||
|
|
@ -121,6 +122,7 @@ func (m *Manager) ShowPanel() error {
|
|||
}
|
||||
|
||||
// HidePanel hides the attached tray panel window if one is configured.
|
||||
// Use: _ = manager.HidePanel()
|
||||
func (m *Manager) HidePanel() error {
|
||||
m.mu.RLock()
|
||||
w := m.panelWindow
|
||||
|
|
@ -133,11 +135,13 @@ func (m *Manager) HidePanel() error {
|
|||
}
|
||||
|
||||
// Tray returns the underlying platform tray for direct access.
|
||||
// Use: tray := manager.Tray()
|
||||
func (m *Manager) Tray() PlatformTray {
|
||||
return m.tray
|
||||
}
|
||||
|
||||
// IsActive returns whether a tray has been created.
|
||||
// Use: active := manager.IsActive()
|
||||
func (m *Manager) IsActive() bool {
|
||||
return m.tray != nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,18 +6,25 @@ import (
|
|||
)
|
||||
|
||||
// WailsPlatform implements Platform using Wails v3.
|
||||
// Use: platform := systray.NewWailsPlatform(app)
|
||||
type WailsPlatform struct {
|
||||
app *application.App
|
||||
}
|
||||
|
||||
// NewWailsPlatform creates a Wails-backed tray platform.
|
||||
// Use: platform := systray.NewWailsPlatform(app)
|
||||
func NewWailsPlatform(app *application.App) *WailsPlatform {
|
||||
return &WailsPlatform{app: app}
|
||||
}
|
||||
|
||||
// NewTray creates a Wails system tray handle.
|
||||
// Use: tray := platform.NewTray()
|
||||
func (wp *WailsPlatform) NewTray() PlatformTray {
|
||||
return &wailsTray{tray: wp.app.SystemTray.New()}
|
||||
}
|
||||
|
||||
// NewMenu creates a Wails tray menu handle.
|
||||
// Use: menu := platform.NewMenu()
|
||||
func (wp *WailsPlatform) NewMenu() PlatformMenu {
|
||||
return &wailsTrayMenu{menu: wp.app.NewMenu()}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ type LayoutInfo struct {
|
|||
}
|
||||
|
||||
// LayoutManager persists named window arrangements to ~/.config/Core/layouts.json.
|
||||
// Use: lm := window.NewLayoutManager()
|
||||
type LayoutManager struct {
|
||||
configDir string
|
||||
layouts map[string]Layout
|
||||
|
|
|
|||
|
|
@ -255,6 +255,8 @@ type ActionWindowFocused struct{ Name string }
|
|||
// Use: _ = c.ACTION(window.ActionWindowBlurred{Name: "editor"})
|
||||
type ActionWindowBlurred struct{ Name string }
|
||||
|
||||
// ActionFilesDropped is broadcast when files are dropped onto a window.
|
||||
// Use: _ = c.ACTION(window.ActionFilesDropped{Name: "editor", Paths: []string{"/tmp/report.pdf"}})
|
||||
type ActionFilesDropped struct {
|
||||
Name string `json:"name"` // window name
|
||||
Paths []string `json:"paths"`
|
||||
|
|
|
|||
|
|
@ -1,15 +1,20 @@
|
|||
package window
|
||||
|
||||
// MockPlatform is an exported mock for cross-package integration tests.
|
||||
// Use: platform := window.NewMockPlatform()
|
||||
// For internal tests, use the unexported mockPlatform in mock_test.go.
|
||||
type MockPlatform struct {
|
||||
Windows []*MockWindow
|
||||
}
|
||||
|
||||
// NewMockPlatform creates a window platform mock.
|
||||
// Use: platform := window.NewMockPlatform()
|
||||
func NewMockPlatform() *MockPlatform {
|
||||
return &MockPlatform{}
|
||||
}
|
||||
|
||||
// CreateWindow creates an in-memory window for tests.
|
||||
// Use: w := platform.CreateWindow(window.PlatformWindowOptions{Name: "editor"})
|
||||
func (m *MockPlatform) CreateWindow(opts PlatformWindowOptions) PlatformWindow {
|
||||
w := &MockWindow{
|
||||
name: opts.Name, title: opts.Title, url: opts.URL,
|
||||
|
|
@ -23,6 +28,8 @@ func (m *MockPlatform) CreateWindow(opts PlatformWindowOptions) PlatformWindow {
|
|||
return w
|
||||
}
|
||||
|
||||
// GetWindows returns all tracked mock windows.
|
||||
// Use: windows := platform.GetWindows()
|
||||
func (m *MockPlatform) GetWindows() []PlatformWindow {
|
||||
out := make([]PlatformWindow, len(m.Windows))
|
||||
for i, w := range m.Windows {
|
||||
|
|
@ -31,6 +38,8 @@ func (m *MockPlatform) GetWindows() []PlatformWindow {
|
|||
return out
|
||||
}
|
||||
|
||||
// MockWindow is an in-memory window handle used by tests.
|
||||
// Use: w := &window.MockWindow{}
|
||||
type MockWindow struct {
|
||||
name, title, url string
|
||||
width, height, x, y int
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ type Platform interface {
|
|||
}
|
||||
|
||||
// PlatformWindowOptions are the backend-specific options passed to CreateWindow.
|
||||
// Use: opts := window.PlatformWindowOptions{Name: "editor"}
|
||||
// Use: opts := window.PlatformWindowOptions{Name: "editor", URL: "/editor"}
|
||||
type PlatformWindowOptions struct {
|
||||
Name string
|
||||
Title string
|
||||
|
|
|
|||
|
|
@ -7,15 +7,19 @@ import (
|
|||
)
|
||||
|
||||
// WailsPlatform implements Platform using Wails v3.
|
||||
// Use: platform := window.NewWailsPlatform(app)
|
||||
type WailsPlatform struct {
|
||||
app *application.App
|
||||
}
|
||||
|
||||
// NewWailsPlatform creates a Wails-backed Platform.
|
||||
// Use: platform := window.NewWailsPlatform(app)
|
||||
func NewWailsPlatform(app *application.App) *WailsPlatform {
|
||||
return &WailsPlatform{app: app}
|
||||
}
|
||||
|
||||
// CreateWindow opens a new Wails window from platform options.
|
||||
// Use: w := wp.CreateWindow(window.PlatformWindowOptions{Name: "editor", URL: "/editor"})
|
||||
func (wp *WailsPlatform) CreateWindow(opts PlatformWindowOptions) PlatformWindow {
|
||||
wOpts := application.WebviewWindowOptions{
|
||||
Name: opts.Name,
|
||||
|
|
@ -40,6 +44,8 @@ func (wp *WailsPlatform) CreateWindow(opts PlatformWindowOptions) PlatformWindow
|
|||
return &wailsWindow{w: w, title: opts.Title}
|
||||
}
|
||||
|
||||
// GetWindows returns the live Wails windows.
|
||||
// Use: windows := wp.GetWindows()
|
||||
func (wp *WailsPlatform) GetWindows() []PlatformWindow {
|
||||
all := wp.app.Window.GetAll()
|
||||
out := make([]PlatformWindow, 0, len(all))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue