From 4f4d77c007248efa4881734e59e5439d273d8322 Mon Sep 17 00:00:00 2001 From: Anthony Dong Date: Mon, 25 Mar 2019 18:00:19 +0100 Subject: ui: add tunnels tableview Signed-off-by: Anthony Dong --- ui/tunnelsview.go | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 ui/tunnelsview.go diff --git a/ui/tunnelsview.go b/ui/tunnelsview.go new file mode 100644 index 00000000..c1bba252 --- /dev/null +++ b/ui/tunnelsview.go @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019 WireGuard LLC. All Rights Reserved. + */ + +package ui + +import ( + "sort" + + "github.com/lxn/walk" + "golang.zx2c4.com/wireguard/windows/service" +) + +// TunnelModel is a struct to store the currently known tunnels to the GUI, suitable as a model for a walk.TableView. +type TunnelModel struct { + walk.TableModelBase + walk.SorterBase + + // TODO: also store the state to display a small icon as the first column + tunnels []service.Tunnel +} + +func (t *TunnelModel) RowCount() int { + return len(t.tunnels) +} + +func (t *TunnelModel) Value(row, col int) interface{} { + tunnel := t.tunnels[row] + + switch col { + case 0: + return tunnel.Name + + default: + panic("unreachable col") + } +} + +func (t *TunnelModel) Sort(col int, order walk.SortOrder) error { + sort.SliceStable(t.tunnels, func(i, j int) bool { + a, b := t.tunnels[i], t.tunnels[j] + + c := func(res bool) bool { + if order == walk.SortAscending { + return res + } + return !res + } + + // don't match col, always sort by name + return c(a.Name < b.Name) + }) + + return t.SorterBase.Sort(col, order) +} + +type TunnelsView struct { + *walk.TableView + + model *TunnelModel +} + +func NewTunnelsView(parent walk.Container) (*TunnelsView, error) { + tv, err := walk.NewTableView(parent) + if err != nil { + return nil, err + } + + model := &TunnelModel{} + + tv.SetModel(model) + tv.SetAlternatingRowBGColor(walk.RGB(239, 239, 239)) + tv.SetLastColumnStretched(true) + tv.SetHeaderHidden(true) + tv.Columns().Add(walk.NewTableViewColumn()) + + return &TunnelsView{ + TableView: tv, + model: model, + }, nil +} + +func (tv *TunnelsView) CurrentTunnel() *service.Tunnel { + idx := tv.CurrentIndex() + if idx == -1 { + return nil + } + + return &tv.model.tunnels[idx] +} + +func (tv *TunnelsView) SetTunnelState(tunnel *service.Tunnel, state service.TunnelState) { + idx := -1 + for i, _ := range tv.model.tunnels { + if tv.model.tunnels[i].Name == tunnel.Name { + idx = i + break + } + } + + if idx != -1 { + // we don't do anything with the state right now + return + } + + // New tunnel, add it + tv.model.tunnels = append(tv.model.tunnels, *tunnel) + tv.model.Sort(0, walk.SortAscending) + for i, _ := range tv.model.tunnels { + if tv.model.tunnels[i].Name == tunnel.Name { + idx = i + } + } + + tv.model.PublishRowsInserted(idx, idx) +} -- cgit v1.2.3-59-g8ed1b