aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ui/tunnelstatusimageprovider.go
diff options
context:
space:
mode:
authorAlexander Neumann <alexander.neumann@picos-software.com>2019-04-04 10:14:28 +0200
committerAlexander Neumann <alexander.neumann@picos-software.com>2019-04-23 11:04:59 +0200
commit6694a5d6d6597f48a2724f922958675200e306bb (patch)
treee6c9f6d66a342a8f59d4b3e61f774688e9fd17a7 /ui/tunnelstatusimageprovider.go
parentui: add initial support for [de]activating tunnels (diff)
downloadwireguard-windows-6694a5d6d6597f48a2724f922958675200e306bb.tar.xz
wireguard-windows-6694a5d6d6597f48a2724f922958675200e306bb.zip
ui: implement a reusable helper for status image painting
Signed-off-by: Alexander Neumann <alexander.neumann@picos-software.com> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to '')
-rw-r--r--ui/tunnelstatusimageprovider.go161
1 files changed, 161 insertions, 0 deletions
diff --git a/ui/tunnelstatusimageprovider.go b/ui/tunnelstatusimageprovider.go
new file mode 100644
index 00000000..4ee8dafa
--- /dev/null
+++ b/ui/tunnelstatusimageprovider.go
@@ -0,0 +1,161 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package ui
+
+import (
+ "github.com/lxn/walk"
+ "golang.zx2c4.com/wireguard/windows/service"
+)
+
+type sizeAndState struct {
+ size walk.Size
+ state service.TunnelState
+}
+
+type TunnelStatusImageProvider struct {
+ imagesBySizeAndState map[sizeAndState]*walk.Bitmap
+ stoppedBrush *walk.SolidColorBrush
+ startingBrush *walk.SolidColorBrush
+ startedBrush *walk.SolidColorBrush
+ statusPen *walk.CosmeticPen
+}
+
+func NewTunnelStatusImageProvider() (*TunnelStatusImageProvider, error) {
+ tsip := &TunnelStatusImageProvider{imagesBySizeAndState: make(map[sizeAndState]*walk.Bitmap)}
+ var err error
+
+ var disposables walk.Disposables
+ defer disposables.Treat()
+
+ if tsip.stoppedBrush, err = walk.NewSolidColorBrush(walk.RGB(239, 239, 239)); err != nil {
+ return nil, err
+ }
+ disposables.Add(tsip.stoppedBrush)
+
+ if tsip.startingBrush, err = walk.NewSolidColorBrush(walk.RGB(255, 211, 31)); err != nil {
+ return nil, err
+ }
+ disposables.Add(tsip.startingBrush)
+
+ if tsip.startedBrush, err = walk.NewSolidColorBrush(walk.RGB(0, 255, 0)); err != nil {
+ return nil, err
+ }
+ disposables.Add(tsip.startedBrush)
+
+ if tsip.statusPen, err = walk.NewCosmeticPen(walk.PenSolid, walk.RGB(191, 191, 191)); err != nil {
+ return nil, err
+ }
+ disposables.Add(tsip.statusPen)
+
+ disposables.Spare()
+
+ return tsip, nil
+}
+
+func (tsip *TunnelStatusImageProvider) Dispose() {
+ if tsip.imagesBySizeAndState != nil {
+ for _, img := range tsip.imagesBySizeAndState {
+ img.Dispose()
+ }
+ tsip.imagesBySizeAndState = nil
+ }
+ if tsip.stoppedBrush != nil {
+ tsip.stoppedBrush.Dispose()
+ tsip.stoppedBrush = nil
+ }
+ if tsip.startingBrush != nil {
+ tsip.startingBrush.Dispose()
+ tsip.startingBrush = nil
+ }
+ if tsip.startedBrush != nil {
+ tsip.startedBrush.Dispose()
+ tsip.startedBrush = nil
+ }
+ if tsip.statusPen != nil {
+ tsip.statusPen.Dispose()
+ tsip.statusPen = nil
+ }
+}
+
+func (tsip *TunnelStatusImageProvider) ImageForTunnel(tunnel *service.Tunnel, size walk.Size) (*walk.Bitmap, error) {
+ state, err := tunnel.State()
+ if err != nil {
+ return nil, err
+ }
+
+ return tsip.ImageForState(state, size)
+}
+
+func (tsip *TunnelStatusImageProvider) ImageForState(state service.TunnelState, size walk.Size) (*walk.Bitmap, error) {
+ key := sizeAndState{size, state}
+
+ if img, ok := tsip.imagesBySizeAndState[key]; ok {
+ return img, nil
+ }
+
+ var disposables walk.Disposables
+ defer disposables.Treat()
+
+ img, err := walk.NewBitmapWithTransparentPixels(size)
+ if err != nil {
+ return nil, err
+ }
+
+ canvas, err := walk.NewCanvasFromImage(img)
+ if err != nil {
+ return nil, err
+ }
+ defer canvas.Dispose()
+
+ if err := tsip.PaintForState(state, canvas, walk.Rectangle{0, 0, size.Width, size.Height}); err != nil {
+ return nil, err
+ }
+
+ tsip.imagesBySizeAndState[key] = img
+
+ disposables.Spare()
+
+ return img, nil
+}
+
+func (tsip *TunnelStatusImageProvider) PaintForTunnel(tunnel *service.Tunnel, canvas *walk.Canvas, bounds walk.Rectangle) error {
+ state, err := tunnel.State()
+ if err != nil {
+ return err
+ }
+
+ return tsip.PaintForState(state, canvas, bounds)
+}
+
+func (tsip *TunnelStatusImageProvider) PaintForState(state service.TunnelState, canvas *walk.Canvas, bounds walk.Rectangle) error {
+ var brush *walk.SolidColorBrush
+ switch state {
+ case service.TunnelStarted:
+ brush = tsip.startedBrush
+
+ case service.TunnelStarting:
+ brush = tsip.startingBrush
+
+ default:
+ brush = tsip.stoppedBrush
+ }
+
+ b := bounds
+
+ b.X = 4
+ b.Y += 4
+ b.Height -= 8
+ b.Width = b.Height
+
+ if err := canvas.FillEllipse(brush, b); err != nil {
+ return err
+ }
+ if err := canvas.DrawEllipse(tsip.statusPen, b); err != nil {
+ return err
+ }
+
+ return nil
+}