source: mainline/uspace/app/nav/panel.c@ 0e80e40

serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 0e80e40 was 0e80e40, checked in by jxsvoboda <5887334+jxsvoboda@…>, 4 years ago

Read and display directory contents

  • Property mode set to 100644
File size: 8.0 KB
Line 
1/*
2 * Copyright (c) 2021 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup nav
30 * @{
31 */
32/** @file Navigator panel.
33 *
34 * Displays a file listing.
35 */
36
37#include <dirent.h>
38#include <errno.h>
39#include <gfx/render.h>
40#include <gfx/text.h>
41#include <stdlib.h>
42#include <str.h>
43#include <ui/control.h>
44#include <ui/paint.h>
45#include <ui/resource.h>
46#include "panel.h"
47#include "nav.h"
48
49static void panel_ctl_destroy(void *);
50static errno_t panel_ctl_paint(void *);
51static ui_evclaim_t panel_ctl_pos_event(void *, pos_event_t *);
52
53/** Panel control ops */
54ui_control_ops_t panel_ctl_ops = {
55 .destroy = panel_ctl_destroy,
56 .paint = panel_ctl_paint,
57 .pos_event = panel_ctl_pos_event
58};
59
60/** Create panel.
61 *
62 * @param window Containing window
63 * @param rpanel Place to store pointer to new panel
64 * @return EOK on success or an error code
65 */
66errno_t panel_create(ui_window_t *window, panel_t **rpanel)
67{
68 panel_t *panel;
69 errno_t rc;
70
71 panel = calloc(1, sizeof(panel_t));
72 if (panel == NULL)
73 return ENOMEM;
74
75 rc = ui_control_new(&panel_ctl_ops, (void *)panel,
76 &panel->control);
77 if (rc != EOK) {
78 free(panel);
79 return rc;
80 }
81
82 rc = gfx_color_new_ega(0x07, &panel->color);
83 if (rc != EOK)
84 goto error;
85
86 rc = gfx_color_new_ega(0x30, &panel->curs_color);
87 if (rc != EOK)
88 goto error;
89
90 panel->window = window;
91 list_initialize(&panel->entries);
92 *rpanel = panel;
93 return EOK;
94error:
95 if (panel->color != NULL)
96 gfx_color_delete(panel->color);
97 if (panel->curs_color != NULL)
98 gfx_color_delete(panel->curs_color);
99 ui_control_delete(panel->control);
100 free(panel);
101 return rc;
102}
103
104/** Destroy panel.
105 *
106 * @param panel Panel
107 */
108void panel_destroy(panel_t *panel)
109{
110 gfx_color_delete(panel->color);
111 gfx_color_delete(panel->curs_color);
112 panel_clear_entries(panel);
113 ui_control_delete(panel->control);
114 free(panel);
115}
116
117/** Paint panel.
118 *
119 * @param panel Panel
120 */
121errno_t panel_paint(panel_t *panel)
122{
123 gfx_context_t *gc = ui_window_get_gc(panel->window);
124 ui_resource_t *res = ui_window_get_res(panel->window);
125 gfx_font_t *font = ui_resource_get_font(res);
126 gfx_text_fmt_t fmt;
127 panel_entry_t *entry;
128 gfx_coord2_t pos;
129 gfx_rect_t rect;
130 errno_t rc;
131
132 gfx_text_fmt_init(&fmt);
133
134 rc = gfx_set_color(gc, panel->color);
135 if (rc != EOK)
136 return rc;
137
138 rc = gfx_fill_rect(gc, &panel->rect);
139 if (rc != EOK)
140 return rc;
141
142 rc = ui_paint_text_box(res, &panel->rect, ui_box_single,
143 panel->color);
144 if (rc != EOK)
145 return rc;
146
147 pos.x = panel->rect.p0.x + 1;
148 pos.y = panel->rect.p0.y + 1;
149
150 entry = panel->page;
151 while (entry != NULL && pos.y < panel->rect.p1.y - 1) {
152 if (entry == panel->cursor) {
153 /* Draw cursor background */
154 rect.p0 = pos;
155 rect.p1.x = panel->rect.p1.x - 1;
156 rect.p1.y = rect.p0.y + 1;
157
158 rc = gfx_set_color(gc, panel->curs_color);
159 if (rc != EOK)
160 return rc;
161
162 rc = gfx_fill_rect(gc, &rect);
163 if (rc != EOK)
164 return rc;
165
166 fmt.color = panel->curs_color;
167 } else {
168 fmt.color = panel->color;
169 }
170
171 rc = gfx_puttext(font, &pos, &fmt, entry->name);
172 if (rc != EOK)
173 return rc;
174
175 pos.y++;
176 entry = panel_next(entry);
177 }
178
179 rc = gfx_update(gc);
180 if (rc != EOK)
181 return rc;
182
183 return EOK;
184}
185
186/** Handle panel position event.
187 *
188 * @param panel Panel
189 * @param event Position event
190 * @return ui_claimed iff event was claimed
191 */
192ui_evclaim_t panel_pos_event(panel_t *panel, pos_event_t *event)
193{
194 return ui_unclaimed;
195}
196
197/** Get base control for panel.
198 *
199 * @param panel Panel
200 * @return Base UI control
201 */
202ui_control_t *panel_ctl(panel_t *panel)
203{
204 return panel->control;
205}
206
207/** Set panel rectangle.
208 *
209 * @param panel Panel
210 * @param rect Rectangle
211 */
212void panel_set_rect(panel_t *panel, gfx_rect_t *rect)
213{
214 panel->rect = *rect;
215}
216
217/** Destroy panel control.
218 *
219 * @param arg Argument (panel_t *)
220 */
221void panel_ctl_destroy(void *arg)
222{
223 panel_t *panel = (panel_t *) arg;
224
225 panel_destroy(panel);
226}
227
228/** Paint panel control.
229 *
230 * @param arg Argument (panel_t *)
231 * @return EOK on success or an error code
232 */
233errno_t panel_ctl_paint(void *arg)
234{
235 panel_t *panel = (panel_t *) arg;
236
237 return panel_paint(panel);
238}
239
240/** Handle panel control position event.
241 *
242 * @param arg Argument (panel_t *)
243 * @param pos_event Position event
244 * @return @c ui_claimed iff the event is claimed
245 */
246ui_evclaim_t panel_ctl_pos_event(void *arg, pos_event_t *event)
247{
248 panel_t *panel = (panel_t *) arg;
249
250 return panel_pos_event(panel, event);
251}
252
253/** Append new panel entry.
254 *
255 * @param panel Panel
256 * @param name File name
257 * @param size File size;
258 * @return EOK on success or an error code
259 */
260errno_t panel_entry_append(panel_t *panel, const char *name, uint64_t size)
261{
262 panel_entry_t *entry;
263
264 entry = calloc(1, sizeof(panel_entry_t));
265 if (entry == NULL)
266 return ENOMEM;
267
268 entry->panel = panel;
269 entry->name = str_dup(name);
270 if (entry->name == NULL) {
271 free(entry);
272 return ENOMEM;
273 }
274
275 entry->size = size;
276 link_initialize(&entry->lentries);
277 list_append(&entry->lentries, &panel->entries);
278 return EOK;
279}
280
281/** Delete panel entry.
282 *
283 * @param entry Panel entry
284 */
285void panel_entry_delete(panel_entry_t *entry)
286{
287 if (entry->panel->cursor == entry)
288 entry->panel->cursor = NULL;
289 if (entry->panel->page == entry)
290 entry->panel->page = NULL;
291
292 list_remove(&entry->lentries);
293 free(entry->name);
294 free(entry);
295}
296
297/** Clear panel entry list.
298 *
299 * @param panel Panel
300 */
301void panel_clear_entries(panel_t *panel)
302{
303 panel_entry_t *entry;
304
305 entry = panel_first(panel);
306 while (entry != NULL) {
307 panel_entry_delete(entry);
308 entry = panel_first(panel);
309 }
310}
311
312/** Read directory into panel entry list.
313 *
314 * @param panel Panel
315 * @param dirname Directory path
316 * @return EOK on success or an error code
317 */
318errno_t panel_read_dir(panel_t *panel, const char *dirname)
319{
320 DIR *dir;
321 struct dirent *dirent;
322 errno_t rc;
323
324 dir = opendir(dirname);
325 if (dir == NULL)
326 return errno;
327
328 dirent = readdir(dir);
329 while (dirent != NULL) {
330 rc = panel_entry_append(panel, dirent->d_name, 1);
331 if (rc != EOK)
332 goto error;
333 dirent = readdir(dir);
334 }
335
336 closedir(dir);
337
338 panel->cursor = panel_first(panel);
339 panel->page = panel_first(panel);
340 return EOK;
341error:
342 closedir(dir);
343 return rc;
344}
345
346/** Return first panel entry.
347 *
348 * @panel Panel
349 * @return First panel entry or @c NULL if there are no entries
350 */
351panel_entry_t *panel_first(panel_t *panel)
352{
353 link_t *link;
354
355 link = list_first(&panel->entries);
356 if (link == NULL)
357 return NULL;
358
359 return list_get_instance(link, panel_entry_t, lentries);
360}
361
362/** Return next panel entry.
363 *
364 * @param cur Current entry
365 * @return Next entry or @c NULL if @a cur is the last entry
366 */
367panel_entry_t *panel_next(panel_entry_t *cur)
368{
369 link_t *link;
370
371 link = list_next(&cur->lentries, &cur->panel->entries);
372 if (link == NULL)
373 return NULL;
374
375 return list_get_instance(link, panel_entry_t, lentries);
376}
377
378/** @}
379 */
Note: See TracBrowser for help on using the repository browser.