From f9ed9d14b5a5c10c981e77232c066e0e1cda07ca Mon Sep 17 00:00:00 2001 From: Anthony Dong Date: Mon, 25 Mar 2019 18:12:14 +0100 Subject: ui: split tray logic into tray component Signed-off-by: Anthony Dong Signed-off-by: Jason A. Donenfeld --- ui/tray.go | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ui/ui.go | 11 +++++ 2 files changed, 174 insertions(+) create mode 100644 ui/tray.go diff --git a/ui/tray.go b/ui/tray.go new file mode 100644 index 00000000..e1fc65e1 --- /dev/null +++ b/ui/tray.go @@ -0,0 +1,163 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019 WireGuard LLC. All Rights Reserved. + */ + +package ui + +import ( + "fmt" + "sort" + + "github.com/lxn/walk" + "golang.zx2c4.com/wireguard/windows/service" +) + +type Tray struct { + *walk.NotifyIcon + + // The action that displays the current active CIDRs + // May be nil if no tunnels are active currently + activeCIDRs *walk.Action + + // Current known tunnels by name + tunnels map[string]*walk.Action + + parent *ManageTunnelsWindow + icon *walk.Icon +} + +func NewTray(parent *ManageTunnelsWindow, icon *walk.Icon) (*Tray, error) { + var err error + + tray := &Tray{ + parent: parent, + icon: icon, + tunnels: make(map[string]*walk.Action), + } + tray.NotifyIcon, err = walk.NewNotifyIcon(parent.MainWindow) + if err != nil { + return nil, err + } + + return tray, tray.setup() +} + +func (tray *Tray) setup() error { + tray.SetToolTip("WireGuard: Deactivated") + tray.SetVisible(true) + tray.SetIcon(tray.icon) + + tray.MouseDown().Attach(func(x, y int, button walk.MouseButton) { + if button == walk.LeftButton { + tray.parent.Show() + } + }) + + // configure initial menu items + for _, item := range [...]struct { + label string + handler walk.EventHandler + enabled bool + separator bool + }{ + {label: "Status: unknown"}, + {separator: true}, + {separator: true}, + {label: "&Manage tunnels...", handler: tray.parent.Show, enabled: true}, + {label: "&Import tunnel(s) from file...", handler: tray.parent.onImport, enabled: true}, + {separator: true}, + {label: "&About WireGuard", handler: onAbout, enabled: true}, + {label: "&Quit", handler: onQuit, enabled: true}, + } { + var action *walk.Action + if item.separator { + action = walk.NewSeparatorAction() + } else { + action = walk.NewAction() + action.SetText(item.label) + action.SetEnabled(item.enabled) + if item.handler != nil { + action.Triggered().Attach(item.handler) + } + } + + tray.ContextMenu().Actions().Add(action) + } + + return nil +} + +func (tray *Tray) SetTunnelState(tunnel *service.Tunnel, state service.TunnelState) { + tray.SetTunnelStateWithNotification(tunnel, state, true) +} + +func (tray *Tray) SetTunnelStateWithNotification(tunnel *service.Tunnel, state service.TunnelState, showNotifications bool) { + action, ok := tray.tunnels[tunnel.Name] + if !ok { + // First time seeing this tunnel, create a new action + action = walk.NewAction() + action.SetText(tunnel.Name) + action.SetEnabled(true) + action.SetCheckable(true) + // TODO: Wire up the click event + tray.tunnels[tunnel.Name] = action + + // Add the action at the right spot + var names []string + for name, _ := range tray.tunnels { + names = append(names, name) + } + sort.Strings(names) + + var ( + idx int + name string + ) + for idx, name = range names { + if name == tunnel.Name { + break + } + } + + // Status action + separator action + offset := 2 + if tray.activeCIDRs != nil { + offset++ + } + + tray.ContextMenu().Actions().Insert(idx+offset, action) + } + + // TODO: No event for deleting a tunnel? + + //TODO: also set tray icon to reflect state + switch state { + case service.TunnelStarting: + action.SetEnabled(false) + + tray.SetToolTip("WireGuard: Activating...") + case service.TunnelStarted: + // TODO: Set the activeCIDRs + + action.SetEnabled(true) + action.SetChecked(true) + + tray.SetToolTip("WireGuard: Activated") + if showNotifications { + tray.ShowInfo("WireGuard Activated", fmt.Sprintf("The %s tunnel has been activated.", tunnel.Name)) + } + case service.TunnelStopping: + action.SetEnabled(false) + + tray.SetToolTip("WireGuard: Deactivating...") + case service.TunnelStopped: + action.SetEnabled(true) + action.SetChecked(false) + + tray.SetToolTip("WireGuard: Deactivated") + if showNotifications { + tray.ShowInfo("WireGuard Deactivated", fmt.Sprintf("The %s tunnel has been deactivated.", tunnel.Name)) + } + } +} diff --git a/ui/ui.go b/ui/ui.go index 633fc19b..2cd558b7 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -298,3 +298,14 @@ func onQuit() { os.Exit(1) } } + +const aboutText = ` +WireGuard +TODO. + +Copyright (C) 2019 WireGuard LLC. All Rights Reserved. +` + +func onAbout() { + walk.MsgBox(nil, "About WireGuard", aboutText, walk.MsgBoxOK) +} -- cgit v1.2.3-59-g8ed1b