v / examples / viewer
Raw file | 343 loc (321 sloc) | 7.84 KB | Latest commit hash 017ace6ea
1/**********************************************************************
2*
3* File scanner
4*
5* Copyright (c) 2021 Dario Deledda. All rights reserved.
6* Use of this source code is governed by an MIT license
7* that can be found in the LICENSE file.
8*
9* TODO:
10**********************************************************************/
11import os
12
13// STBI supported format
14// STBI_NO_JPEG *
15// STBI_NO_PNG *
16// STBI_NO_BMP *
17// STBI_NO_PSD
18// STBI_NO_TGA *
19// STBI_NO_GIF *
20// STBI_NO_HDR *
21// STBI_NO_PIC *
22// STBI_NO_PNM *
23
24/******************************************************************************
25*
26* Struct and Enums
27*
28******************************************************************************/
29enum Item_type {
30 file = 0
31 folder
32 // archive format
33 zip = 16
34 archive_file
35 // graphic format, MUST stay after the other types!!
36 bmp = 32
37 jpg
38 png
39 gif
40 tga
41 ppm
42 pgm
43 pic
44 hdr
45}
46
47pub struct Item {
48pub mut:
49 path string
50 name string
51 size u64
52 i_type Item_type = .file
53 container_index int // used if the item is in a container (.zip, .rar, etc)
54 container_item_index int // index in the container if the item is contained
55 need_extract bool // if true need to extraction from the container
56 drawable bool // if true the image can be showed
57 n_item int //
58 rotation int // number of rotation of PI/2
59}
60
61struct Item_list {
62pub mut:
63 lst []Item
64 path_sep string
65 item_index int = -1 // image currently shown
66 n_item int // number of images scanned
67 loaded bool // flag that indicate that the list is ready to be used
68}
69
70/******************************************************************************
71*
72* Utility functions
73*
74******************************************************************************/
75[inline]
76fn modulo(x int, n int) int {
77 return (x % n + n) % n
78}
79
80[inline]
81fn get_extension(x string) Item_type {
82 // 4 char extension check
83 if x.len > 4 {
84 ext4 := x[x.len - 4..].to_lower()
85 match ext4 {
86 // containers
87 '.zip' { return .zip }
88 // graphic formats
89 '.jpg' { return .jpg }
90 '.png' { return .png }
91 '.bmp' { return .bmp }
92 '.gif' { return .gif }
93 '.tga' { return .tga }
94 '.ppm' { return .ppm }
95 '.pgm' { return .pgm }
96 '.pic' { return .pic }
97 '.hdr' { return .hdr }
98 else {}
99 }
100 }
101 // 5 char extension check
102 if x.len > 5 {
103 ext5 := x[x.len - 5..].to_lower()
104 if ext5 == '.jpeg' {
105 {
106 return .jpg
107 }
108 }
109 }
110 return .file
111}
112
113[inline]
114fn is_image(x Item_type) bool {
115 if int(x) >= int(Item_type.bmp) {
116 return true
117 }
118 return false
119}
120
121[inline]
122fn is_container(x Item_type) bool {
123 if x in [.zip, .folder] {
124 return true
125 }
126 return false
127}
128
129[inline]
130fn (item_list Item_list) is_inside_a_container() bool {
131 if item_list.lst.len <= 0 || item_list.n_item <= 0 {
132 return false
133 }
134 return item_list.lst[item_list.item_index].need_extract
135}
136
137[inline]
138fn (item_list Item_list) get_file_path() string {
139 if item_list.lst.len <= 0 || item_list.n_item <= 0 {
140 return ''
141 }
142 if item_list.lst[item_list.item_index].path.len > 0 {
143 return '${item_list.lst[item_list.item_index].path}${item_list.path_sep}${item_list.lst[item_list.item_index].name}'
144 }
145 return item_list.lst[item_list.item_index].name
146}
147
148/******************************************************************************
149*
150* Scan functions
151*
152******************************************************************************/
153fn (mut item_list Item_list) scan_folder(path string, in_index int) ! {
154 println('Scanning [${path}]')
155 mut folder_list := []string{}
156 lst := os.ls(path)!
157
158 // manage the single files
159 for c, x in lst {
160 pt := '${path}${item_list.path_sep}${x}'
161 mut item := Item{
162 path: path
163 name: x
164 container_index: in_index
165 container_item_index: c
166 }
167 if os.is_dir(pt) {
168 folder_list << x
169 } else {
170 ext := get_extension(x)
171 if ext == .zip {
172 item.i_type = .zip
173 item_list.lst << item
174 item_list.scan_zip(pt, item_list.lst.len - 1)!
175 continue
176 }
177 if is_image(ext) == true {
178 item_list.n_item += 1
179 item.n_item = item_list.n_item
180 item.i_type = ext
181 item.drawable = true
182 item_list.lst << item
183 continue
184 }
185 }
186 }
187
188 // manage the folders
189 for x in folder_list {
190 pt := '${path}${item_list.path_sep}${x}'
191 item := Item{
192 path: path
193 name: x
194 i_type: .folder
195 }
196 item_list.lst << item
197 item_list.scan_folder(pt, item_list.lst.len - 1)!
198 }
199 // println(item_list.lst.len)
200 // println("==================================")
201}
202
203fn (item_list Item_list) print_list() {
204 println('================================')
205 for x in item_list.lst {
206 if x.i_type == .folder {
207 print('[]')
208 }
209 if x.i_type == .zip {
210 print('[ZIP]')
211 }
212 println('${x.path} => ${x.container_index} ${x.container_item_index} ${x.name} ne:${x.need_extract}')
213 }
214 println('n_item: ${item_list.n_item} index: ${item_list.item_index}')
215 println('================================')
216}
217
218fn (mut item_list Item_list) get_items_list(args []string) {
219 item_list.loaded = false
220 println('Args: ${args}')
221
222 item_list.path_sep = $if windows { '\\' } $else { '/' }
223 for x in args {
224 // scan folder
225 if os.is_dir(x) {
226 mut item := Item{
227 path: x
228 name: x
229 container_index: item_list.lst.len
230 i_type: .folder
231 }
232 item_list.lst << item
233 item_list.scan_folder(x, item_list.lst.len - 1) or {
234 eprintln('ERROR: scanning folder [${x}]!')
235 continue
236 }
237 } else {
238 mut item := Item{
239 path: ''
240 name: x
241 container_index: -1
242 }
243 ext := get_extension(x)
244 // scan .zip
245 if ext == .zip {
246 item.i_type = .zip
247 item_list.lst << item
248 item_list.scan_zip(x, item_list.lst.len - 1) or {
249 eprintln('ERROR: scanning zip [${x}]!')
250 continue
251 }
252 continue
253 }
254 // single images
255 if is_image(ext) == true {
256 item_list.n_item += 1
257 item.n_item = item_list.n_item
258 item.i_type = ext
259 item.drawable = true
260 item_list.lst << item
261 continue
262 }
263 }
264 }
265 // debug call for list all the loaded items
266 // item_list.print_list()
267
268 println('Items: ${item_list.n_item}')
269 println('Scanning done.')
270
271 item_list.get_next_item(1)
272 item_list.loaded = true
273}
274
275/******************************************************************************
276*
277* Navigation functions
278*
279******************************************************************************/
280fn (mut item_list Item_list) get_next_item(in_inc int) {
281 // if empty exit
282 if item_list.lst.len <= 0 || item_list.n_item <= 0 {
283 return
284 }
285
286 inc := if in_inc > 0 { 1 } else { -1 }
287 mut i := item_list.item_index + in_inc
288 i = modulo(i, item_list.lst.len)
289 start := i
290 for {
291 if item_list.lst[i].drawable == true {
292 item_list.item_index = i
293 break
294 }
295 i = i + inc
296 i = modulo(i, item_list.lst.len)
297 // if we are in a loop break it
298 if i == start {
299 break
300 }
301 }
302 // println("Found: ${item_list.item_index}")
303}
304
305fn (mut item_list Item_list) go_to_next_container(in_inc int) {
306 // if empty exit
307 if item_list.lst.len <= 0 || item_list.n_item <= 0 {
308 return
309 }
310 inc := if in_inc > 0 { 1 } else { -1 }
311 mut i := item_list.item_index + in_inc
312 i = modulo(i, item_list.lst.len)
313 start := i
314 for {
315 // check if we found a folder
316 if is_container(item_list.lst[i].i_type) == true
317 && i != item_list.lst[item_list.item_index].container_index {
318 item_list.item_index = i
319 item_list.get_next_item(1)
320 break
321 }
322 // continue to search
323 i = i + inc
324 i = modulo(i, item_list.lst.len)
325 // if we are in a loop break it
326 if i == start {
327 break
328 }
329 }
330}
331
332/******************************************************************************
333*
334* Other functions
335*
336******************************************************************************/
337[inline]
338fn (mut item_list Item_list) rotate(in_inc int) {
339 item_list.lst[item_list.item_index].rotation += in_inc
340 if item_list.lst[item_list.item_index].rotation >= 4 {
341 item_list.lst[item_list.item_index].rotation = 0
342 }
343}