Passed
Push — main ( 05b53a...cd1aeb )
by Rafael
01:13
created

ui.*fileDirectoryRowRenderer.Refresh   A

Complexity

Conditions 2

Size

Total Lines 7
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
dl 0
loc 7
rs 10
c 0
b 0
f 0
nop 0
1
package ui
2
3
import (
4
	"image/color"
5
6
	"fyne.io/fyne/v2"
7
	"fyne.io/fyne/v2/canvas"
8
	"fyne.io/fyne/v2/container"
9
	"fyne.io/fyne/v2/data/binding"
10
	"fyne.io/fyne/v2/driver/desktop"
11
	"fyne.io/fyne/v2/layout"
12
	"fyne.io/fyne/v2/theme"
13
	"fyne.io/fyne/v2/widget"
14
	"github.com/rchargel/hdfs-explorer/files"
15
)
16
17
var sizes [7]float32 = [7]float32{}
18
19
var _ fyne.Widget = (*fileDirectoryRow)(nil)
20
var _ fyne.Tappable = (*fileDirectoryRow)(nil)
21
var _ fyne.DoubleTappable = (*fileDirectoryRow)(nil)
22
var _ desktop.Hoverable = (*fileDirectoryRow)(nil)
23
24
type FileDirectoryList struct {
25
	container *fyne.Container
26
}
27
28
func NewFileDirectoryList(data HdfsFileInfoList, openItem func(string)) *FileDirectoryList {
29
	list := &FileDirectoryList{
30
		container: container.New(layout.NewVBoxLayout()),
31
	}
32
	data.AddListener(binding.NewDataListener(func() {
33
		infos, _ := data.Get()
34
		objects := make([]fyne.CanvasObject, len(infos))
35
		for i, info := range infos {
36
			objects[i] = newFileDirectoryRow(info, list.deselectAll, openItem)
37
		}
38
		list.container.Objects = objects
39
		list.container.Refresh()
40
	}))
41
	return list
42
}
43
44
func (f *FileDirectoryList) deselectAll(name string) {
45
	for _, obj := range f.container.Objects {
46
		if obj.(*fileDirectoryRow).info.Name() != name {
47
			obj.(*fileDirectoryRow).selected = false
48
			obj.Refresh()
49
		}
50
	}
51
}
52
53
type fileDirectoryRow struct {
54
	widget.BaseWidget
55
	info  files.HdfsFileInfo
56
	child fyne.CanvasObject
57
58
	mode  *canvas.Text
59
	owner *canvas.Text
60
	group *canvas.Text
61
	size  *canvas.Text
62
	block *canvas.Text
63
	time  *canvas.Text
64
	name  *canvas.Text
65
66
	selected, hovered bool
67
	onTapped          func(name string)
68
	onDoubleTapped    func(name string)
69
}
70
71
type fileDirectoryRowRenderer struct {
72
	objects []fyne.CanvasObject
73
74
	row *fileDirectoryRow
75
}
76
77
func newFileDirectoryRow(info files.HdfsFileInfo, onTapped, onDoubleTapped func(name string)) *fileDirectoryRow {
78
	mode := newText(info.Mode().String(), fyne.TextAlignLeading)
79
	owner := newText(info.Owner(), fyne.TextAlignLeading)
80
	group := newText(info.OwnerGroup(), fyne.TextAlignLeading)
81
	size := newText(files.FormatBytes(uint64(info.Size())), fyne.TextAlignTrailing)
82
	block := newText(files.FormatBytes(info.BlockSize()), fyne.TextAlignTrailing)
83
	time := newText(info.ModTime().Format("Jan 02 15:04"), fyne.TextAlignLeading)
84
	name := newText(info.Name(), fyne.TextAlignLeading)
85
86
	r := &fileDirectoryRow{
87
		BaseWidget:     widget.BaseWidget{},
88
		info:           info,
89
		mode:           mode,
90
		owner:          owner,
91
		group:          group,
92
		size:           size,
93
		block:          block,
94
		time:           time,
95
		name:           name,
96
		onTapped:       onTapped,
97
		onDoubleTapped: onDoubleTapped,
98
		child: container.New(
99
			layout.NewGridLayoutWithColumns(7),
100
			mode, owner, group, size, block, time, name,
101
		),
102
	}
103
	r.ExtendBaseWidget(r)
104
	return r
105
}
106
107
func (r *fileDirectoryRow) setStyle(style fyne.TextStyle) {
108
	objects := r.child.(*fyne.Container).Objects
109
	for _, obj := range objects {
110
		obj.(*canvas.Text).TextStyle = style
111
	}
112
}
113
114
func (r *fileDirectoryRow) setColor(color color.Color) {
115
	objects := r.child.(*fyne.Container).Objects
116
	for _, obj := range objects {
117
		obj.(*canvas.Text).Color = color
118
	}
119
}
120
121
func (r *fileDirectoryRow) MinSize() fyne.Size {
122
	r.ExtendBaseWidget(r)
123
	return r.BaseWidget.MinSize()
124
}
125
126
func (r *fileDirectoryRow) Tapped(*fyne.PointEvent) {
127
	r.selected = !r.selected
128
	r.onTapped(r.info.Name())
129
	r.Refresh()
130
}
131
132
func (r *fileDirectoryRow) DoubleTapped(*fyne.PointEvent) {
133
	r.onDoubleTapped(r.info.Name())
134
}
135
136
func (r *fileDirectoryRow) MouseIn(*desktop.MouseEvent) {
137
	r.hovered = true
138
	r.Refresh()
139
}
140
141
func (r *fileDirectoryRow) MouseOut() {
142
	r.hovered = false
143
	r.Refresh()
144
}
145
146
func (r *fileDirectoryRow) MouseMoved(*desktop.MouseEvent) {}
147
148
func newText(text string, alignment fyne.TextAlign) *canvas.Text {
149
	return &canvas.Text{
150
		Text:      text,
151
		Alignment: alignment,
152
		Color:     theme.ForegroundColor(),
153
		TextStyle: fyne.TextStyle{Monospace: true},
154
		TextSize:  fyne.CurrentApp().Settings().Theme().Size("text") * float32(0.9),
155
	}
156
}
157
158
func (r *fileDirectoryRow) CreateRenderer() fyne.WidgetRenderer {
159
	r.ExtendBaseWidget(r)
160
	objects := []fyne.CanvasObject{r.child}
161
162
	return &fileDirectoryRowRenderer{objects, r}
163
}
164
165
func (r *fileDirectoryRowRenderer) Destroy() {
166
	// nothing done here
167
}
168
169
func (r *fileDirectoryRowRenderer) Objects() []fyne.CanvasObject {
170
	return r.objects
171
}
172
173
func (r *fileDirectoryRowRenderer) SetObjects(objects []fyne.CanvasObject) {
174
	r.objects = objects
175
}
176
177
func (r *fileDirectoryRowRenderer) MinSize() fyne.Size {
178
	objects := r.row.child.(*fyne.Container).Objects
179
	height := r.row.child.MinSize().Height
180
181
	for i, o := range objects {
182
		sizes[i] = max(sizes[i], o.MinSize().Width)
183
	}
184
185
	return fyne.NewSize(minWidth(), height+theme.Padding()*2)
186
}
187
188
func (r *fileDirectoryRowRenderer) Layout(size fyne.Size) {
189
	r.row.child.Move(fyne.NewPos(theme.Padding(), theme.Padding()))
190
	r.row.child.Resize(fyne.NewSize(size.Width+theme.Padding()*2, size.Height+theme.Padding()*2))
191
192
	x := theme.Padding()
193
	for i, obj := range r.row.child.(*fyne.Container).Objects {
194
		width := sizes[i]
195
		obj.Resize(fyne.NewSize(width, obj.MinSize().Height))
196
		obj.Move(fyne.NewPos(x, theme.Padding()))
197
		x += width + theme.Padding()
198
	}
199
}
200
201
func (r *fileDirectoryRowRenderer) Refresh() {
202
	if r.row.hovered {
203
		r.row.setColor(theme.PrimaryColor())
204
	} else {
205
		r.row.setColor(theme.ForegroundColor())
206
	}
207
	canvas.Refresh(r.row)
208
}
209
210
func minWidth() float32 {
211
	width := float32(0)
212
	for _, w := range sizes {
213
		width += w + theme.Padding()*2
214
	}
215
	return width
216
}
217
218
func max(a, b float32) float32 {
219
	if a > b {
220
		return a
221
	}
222
	return b
223
}
224