-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlist.sh
More file actions
240 lines (215 loc) · 7.27 KB
/
list.sh
File metadata and controls
240 lines (215 loc) · 7.27 KB
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
declare -A _list_obj
# $1 - variable name
function list.new() {
_list_obj["$1"]=list
_list_obj["$1:selected"]=0
register_object $1 list
_list_obj["$1:style"]=1
_list_obj["$1:size"]=0
_list_obj["$1:fixed_size"]=-1
_list_obj["$1:prev_sx"]=0
_list_obj["$1:prev_sy"]=0
_list_obj["$1:prev_ex"]=0
_list_obj["$1:prev_ey"]=0
_list_obj["$1:fixed_layouts_size"]=0
style.new $1
style.new "$1.selected"
}
# $1 - list
# $2...$etc - items
# Set items to render inside of this list
# Resets selected item to 0
function list.set_items() {
local i z=0
while [ -n "${_list_obj["$1:items:$z"]}" ]; do
unset _list_obj["$1:items:$z"]
z=$((z+1))
done
z=0
for i in "${@:2}"; do
_list_obj["$1:items:$z"]="${@:$((z+2)):1}"
((z+=1))
done
_list_obj["$1:selected"]=0
_list_obj["$1:size"]=$z
}
# $1 - list
# $2 - item
# Adds item to end of list
function list.insert_item() {
local i=${_list_obj["$1:size"]}
_list_obj["$1:items:$i"]="$2"
_list_obj["$1:size"]=$((i + 1))
}
# $1 - list
# $2 - positive, non zero, size in pixels to enable or disable (-1)
# Sets fixed size of layout for all components, resulting faster computation
function list.set_fixed_size() {
_list_obj["$1:fixed_size"]=$2
}
# $1 - list
# $2 - selected position
# Guarantees that selecected component at given position gonna be visible
# If position greater than items size, it will set position to last item in list
function list.set_selected() {
_list_obj["$1:selected"]=$2
}
# $1 - list
# $2, $3, ... - names of properties to enable, see style.set_style for more
function list.set_style() {
style.set_style "$@"
}
# $1 - list
# $2, $3, ... - names of properties to enable, see style.set_style for more
# Style for selected item
function list.set_selected_style() {
style.set_style "$1.selected" "${@:2}"
}
# $1 - list
# $2 - start x of layout
# $3 - start y of layout
# $4 - end x of layout
# $5 - end y of layout
function list._create_fixed_layouts() {
if ! [ "${_list_obj["$1:prev_sx"]}" -eq "$2" ] || ! [ "${_list_obj["$1:prev_ex"]}" -eq "$4" ] || ! [ "${_list_obj["$1:prev_sy"]}" -eq "$3" ] || ! [ "${_list_obj["$1:prev_ey"]}" -eq "$5" ]; then
list._delete_fixed_layouts $1
local fixed_size=${_list_obj["$1:fixed_size"]}
local free_space=$(( $5 - $3 + 1 ))
local length=$((free_space / fixed_size ))
local i=0
local current_y=$3
while [ "$current_y" -le "$5" ]; do
layout.create_from_size ".$1.nested-$i" $2 $current_y $4 $((current_y + fixed_size - 1))
((i+=1))
current_y=$((current_y + fixed_size))
done
_list_obj["$1:prev_sx"]=$2
_list_obj["$1:prev_sy"]=$3
_list_obj["$1:prev_ex"]=$4
_list_obj["$1:prev_ey"]=$5
_list_obj["$1:fixed_layouts_size"]=$i
fi
}
# $1 - list
function list._delete_fixed_layouts() {
local i=$((${_list_obj["$1:fixed_layouts_size"]} - 1))
for ((i; i>=0; i--)) {
layout.delete ".$1.nested-$i"
}
}
# $1 - list
# $2 - layout
function list.draw() {
local i=0
local start_x start_y end_x end_y
layout.get_rect $2 start_x start_y end_x end_y
local current_y=$start_y
style.apply_rect $1 $start_x $start_y $end_x $end_y
if [ "${_list_obj["$1:size"]}" -ge 1 ]; then
local break=0
local selected=${_list_obj["$1:selected"]}
if [ $selected -gt $((${_list_obj["$1:size"]} - 1)) ]; then
selected=$((${_list_obj["$1:size"]} - 1))
fi
if [ ${_list_obj["$1:size"]} -eq 0 ]; then
selected=-1
fi
local free_space=$((end_y - start_y + 1))
local fixed_size=${_list_obj["$1:fixed_size"]}
local starting_pos=0
if [ "$fixed_size" -gt 0 ]; then
list._create_fixed_layouts $1 $start_x $start_y $end_x $end_y
starting_pos=$((selected + 1 - (free_space / fixed_size) ))
if [ "$starting_pos" -lt 0 ]; then
starting_pos=0
fi
local i=0
while [ $starting_pos -le $((${_list_obj["$1:size"]} - 1)) ]; do
local item=${_list_obj["$1:items:$starting_pos"]}
local item_key=".$1.nested-$i"
((i+=1))
if [ $starting_pos -eq $selected ]; then
style.apply_rect "$1.selected" $start_x $current_y $end_x $((current_y + fixed_size - 1))
fi
object.draw $item $item_key
current_y=$((current_y + fixed_size))
if [ $current_y -ge $((end_y + 1)) ]; then
break
fi
((starting_pos += 1))
done
else
# Before selected
for ((i=selected; i>=0; i-- )); do
local ox oy;
object.get_minimal_size ${_list_obj["$1:items:$i"]} $2 ox oy
free_space=$((free_space - oy))
if [ $free_space -lt 0 ]; then
starting_pos=$((i+1))
break
fi
done
while [ $starting_pos -le $((${_list_obj["$1:size"]} - 1)) ]; do
local item=${_list_obj["$1:items:$starting_pos"]}
local item_key=".$1.nested-$item"
local ox oy;
if [ "$fixed_size" -gt 0 ]; then
oy=$fixed_size
ox=$fixed_size
else
object.get_minimal_size $item $2 ox oy
fi
local max_y=$((current_y + oy - 1))
if [ $max_y -ge $end_y ]; then
max_y=$end_y
break=1
fi
if [ $starting_pos -eq $selected ]; then
style.apply_rect "$1.selected" $start_x $current_y $end_x $max_y
fi
layout.create_from_size $item_key $start_x $current_y $end_x $max_y
object.draw $item $item_key
layout.delete $item_key
current_y=$((max_y + 1))
if [ $break -eq 1 ]; then
break
fi
((starting_pos += 1))
done
fi
fi
}
# $1 - label
# $2 - layout within label will calculate its size
# $3 - variable name for x size
# $4 - variable name for y size
# Returns 0 0. You shoudn't rely on list implementation and instead define needed size in your components by yourself
function list.get_minimal_size() {
export "$3=0"
export "$4=0"
}
# $1 - variable name
# Deletes object
# After deletion of object its usage leads to undifined behaviour
# This list doesn't delete its items
function list.delete() {
unset _list_obj["$1"]
unset _list_obj["$1:selected"]
unset _list_obj["$1:items"]
unset _list_obj["$1:style"]
unset _list_obj["$1:size"]
unset _list_obj["$1:fixed_size"]
list._delete_fixed_layouts $1
unset _list_obj["$1:prev_sx"]
unset _list_obj["$1:prev_sy"]
unset _list_obj["$1:prev_ex"]
unset _list_obj["$1:prev_ey"]
local i=0
while [ -n "${_list_obj["$1:items:$i"]}" ]; do
unset ${_list_obj["$1:items:$i"]}
((i+=1))
done
style.delete $1
style.delete "$1.selected"
unregister_object $1
}