1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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)
}
|