From 8d29c7136535524e387091a7387a33a243062f2b Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 24 Apr 2019 15:59:55 +0200 Subject: ui: introduce system icon loading This looks clearly worse in basically all ways and should be reverted. --- ui/systemimageprovider.go | 78 +++++++++++++++++++++++++++++++++++++++++++++++ ui/tunnelspage.go | 13 +++++--- ui/ui.go | 5 +++ 3 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 ui/systemimageprovider.go diff --git a/ui/systemimageprovider.go b/ui/systemimageprovider.go new file mode 100644 index 00000000..26764ccc --- /dev/null +++ b/ui/systemimageprovider.go @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019 WireGuard LLC. All Rights Reserved. + */ + +package ui + +import ( + "fmt" + "path" + + "github.com/lxn/walk" + "github.com/lxn/win" + "golang.org/x/sys/windows" +) + +var ( + systemIconAddTunnel, + systemIconAddTunnelFromScratch, + systemIconAddTunnelFromFile, + systemIconDeleteTunnel, + systemIconExportTunnels, + systemIconSaveTunnelsToZip, + _ *walk.Icon +) + +func loadSystemIcon(dll string, index uint) (*walk.Icon, error) { + system32, err := windows.GetSystemDirectory() + if err != nil { + return nil, err + } + hicon := win.ExtractIcon(win.GetModuleHandle(nil), windows.StringToUTF16Ptr(path.Join(system32, dll+".dll")), int32(index)) + if hicon <= 1 { + return nil, fmt.Errorf("Unable to find icon %d of %s", index, dll) + } + return walk.NewIconFromHICON(hicon) +} + +func setIconOnAction(wb *walk.WindowBase, action *walk.Action, icon *walk.Icon) error { + //TODO: this is an unholy hack. Fix walk! + bitmap, err := walk.NewBitmapFromIcon(icon, walk.Size{32, 32}) + if err != nil { + return err + } + wb.AddDisposable(bitmap) + return action.SetImage(bitmap) +} + +func loadSystemIcons() (err error) { + //TODO: this should probably be in an object that is disposable instead of using globals like this + + systemIconAddTunnel, err = loadSystemIcon("shell32", 149) + if err != nil { + return + } + systemIconAddTunnelFromScratch, err = loadSystemIcon("imageres", 2) + if err != nil { + return + } + systemIconAddTunnelFromFile, err = loadSystemIcon("imageres", 3) + if err != nil { + return + } + systemIconDeleteTunnel, err = loadSystemIcon("shell32", 131) + if err != nil { + return + } + systemIconExportTunnels, err = loadSystemIcon("shell32", 45) + if err != nil { + return + } + systemIconSaveTunnelsToZip, err = loadSystemIcon("imageres", 165) + if err != nil { + return + } + + return +} diff --git a/ui/tunnelspage.go b/ui/tunnelspage.go index ac778b3a..48a25425 100644 --- a/ui/tunnelspage.go +++ b/ui/tunnelspage.go @@ -58,18 +58,23 @@ func NewTunnelsPage() (*TunnelsPage, error) { toolBarContainer, _ := walk.NewComposite(tunnelsContainer) toolBarContainer.SetLayout(walk.NewHBoxLayout()) - tunnelsToolBar, _ := walk.NewToolBarWithOrientationAndButtonStyle(toolBarContainer, walk.Horizontal, walk.ToolBarButtonTextOnly) + tunnelsToolBar, _ := walk.NewToolBarWithOrientationAndButtonStyle(toolBarContainer, walk.Horizontal, walk.ToolBarButtonImageOnly) + imageList, _ := walk.NewImageList(walk.Size{32, 32}, 0) + tunnelsToolBar.SetImageList(imageList) importAction := walk.NewAction() importAction.SetText("Import tunnels from file...") + setIconOnAction(tp.AsWindowBase(), importAction, systemIconAddTunnelFromFile) importAction.Triggered().Attach(tp.onImport) addAction := walk.NewAction() addAction.SetText("Add empty tunnel") + setIconOnAction(tp.AsWindowBase(), addAction, systemIconAddTunnelFromScratch) addAction.Triggered().Attach(tp.onAddTunnel) exportTunnelsAction := walk.NewAction() exportTunnelsAction.SetText("Export tunnels to zip...") + setIconOnAction(tp.AsWindowBase(), exportTunnelsAction, systemIconSaveTunnelsToZip) exportTunnelsAction.Triggered().Attach(tp.onExportTunnels) addMenu, _ := walk.NewMenu() @@ -77,18 +82,18 @@ func NewTunnelsPage() (*TunnelsPage, error) { addMenu.Actions().Add(addAction) addMenu.Actions().Add(importAction) addMenuAction, _ := tunnelsToolBar.Actions().AddMenu(addMenu) - addMenuAction.SetText("➕") + setIconOnAction(tp.AsWindowBase(), addMenuAction, systemIconAddTunnel) deleteAction := walk.NewAction() tunnelsToolBar.Actions().Add(deleteAction) - deleteAction.SetText("➖") + setIconOnAction(tp.AsWindowBase(), deleteAction, systemIconDeleteTunnel) deleteAction.Triggered().Attach(tp.onDelete) settingsMenu, _ := walk.NewMenu() tp.AddDisposable(settingsMenu) settingsMenu.Actions().Add(exportTunnelsAction) settingsMenuAction, _ := tunnelsToolBar.Actions().AddMenu(settingsMenu) - settingsMenuAction.SetText("⚙") + setIconOnAction(tp.AsWindowBase(), settingsMenuAction, systemIconExportTunnels) } currentTunnelContainer, _ := walk.NewComposite(tp) diff --git a/ui/ui.go b/ui/ui.go index 58b52e46..9e0b01cc 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -36,6 +36,11 @@ func RunUI() { } defer icon.Dispose() + err = loadSystemIcons() //TODO: Load these the proper way and make dispose and be more like tunnelstatusimageprovider. + if err != nil { + panic(err) + } + mtw, err := NewManageTunnelsWindow(icon, logger) if err != nil { panic(err) -- cgit v1.2.3-59-g8ed1b