source: mainline/uspace/app/nav/panel.c@ 901b302

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 901b302 was 54ddb59, checked in by Jiri Svoboda <jiri@…>, 3 years ago

Base navigator panel on UI file list

Free scrollbar!

  • Property mode set to 100644
File size: 9.4 KB
Line 
1/*
2 * Copyright (c) 2022 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 <errno.h>
38#include <gfx/render.h>
39#include <gfx/text.h>
40#include <stdlib.h>
41#include <task.h>
42#include <ui/control.h>
43#include <ui/filelist.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_kbd_event(void *, kbd_event_t *);
52static ui_evclaim_t panel_ctl_pos_event(void *, pos_event_t *);
53
54/** Panel control ops */
55static ui_control_ops_t panel_ctl_ops = {
56 .destroy = panel_ctl_destroy,
57 .paint = panel_ctl_paint,
58 .kbd_event = panel_ctl_kbd_event,
59 .pos_event = panel_ctl_pos_event
60};
61
62static void panel_flist_selected(ui_file_list_t *, void *, const char *);
63
64/** Panel file list callbacks */
65static ui_file_list_cb_t panel_flist_cb = {
66 .selected = panel_flist_selected
67};
68
69/** Create panel.
70 *
71 * @param window Containing window
72 * @param active @c true iff panel should be active
73 * @param rpanel Place to store pointer to new panel
74 * @return EOK on success or an error code
75 */
76errno_t panel_create(ui_window_t *window, bool active, panel_t **rpanel)
77{
78 panel_t *panel;
79 errno_t rc;
80
81 panel = calloc(1, sizeof(panel_t));
82 if (panel == NULL)
83 return ENOMEM;
84
85 rc = ui_control_new(&panel_ctl_ops, (void *)panel,
86 &panel->control);
87 if (rc != EOK) {
88 free(panel);
89 return rc;
90 }
91
92 rc = gfx_color_new_ega(0x07, &panel->color);
93 if (rc != EOK)
94 goto error;
95
96 rc = gfx_color_new_ega(0x0f, &panel->act_border_color);
97 if (rc != EOK)
98 goto error;
99
100 rc = ui_file_list_create(window, active, &panel->flist);
101 if (rc != EOK)
102 goto error;
103
104 ui_file_list_set_cb(panel->flist, &panel_flist_cb, (void *)panel);
105
106 panel->window = window;
107 panel->active = active;
108 *rpanel = panel;
109 return EOK;
110error:
111 if (panel->color != NULL)
112 gfx_color_delete(panel->color);
113 if (panel->act_border_color != NULL)
114 gfx_color_delete(panel->act_border_color);
115 if (panel->flist != NULL)
116 ui_file_list_destroy(panel->flist);
117 ui_control_delete(panel->control);
118 free(panel);
119 return rc;
120}
121
122/** Destroy panel.
123 *
124 * @param panel Panel
125 */
126void panel_destroy(panel_t *panel)
127{
128 gfx_color_delete(panel->color);
129 gfx_color_delete(panel->act_border_color);
130 ui_control_delete(panel->control);
131 free(panel);
132}
133
134/** Set panel callbacks.
135 *
136 * @param panel Panel
137 * @param cb Callbacks
138 * @param arg Argument to callback functions
139 */
140void panel_set_cb(panel_t *panel, panel_cb_t *cb, void *arg)
141{
142 panel->cb = cb;
143 panel->cb_arg = arg;
144}
145
146/** Paint panel.
147 *
148 * @param panel Panel
149 */
150errno_t panel_paint(panel_t *panel)
151{
152 gfx_context_t *gc = ui_window_get_gc(panel->window);
153 ui_resource_t *res = ui_window_get_res(panel->window);
154 ui_box_style_t bstyle;
155 gfx_color_t *bcolor;
156 ui_control_t *ctl;
157 errno_t rc;
158
159 rc = gfx_set_color(gc, panel->color);
160 if (rc != EOK)
161 return rc;
162
163 rc = gfx_fill_rect(gc, &panel->rect);
164 if (rc != EOK)
165 return rc;
166
167 if (panel->active) {
168 bstyle = ui_box_double;
169 bcolor = panel->act_border_color;
170 } else {
171 bstyle = ui_box_single;
172 bcolor = panel->color;
173 }
174
175 rc = ui_paint_text_box(res, &panel->rect, bstyle, bcolor);
176 if (rc != EOK)
177 return rc;
178
179 ctl = ui_file_list_ctl(panel->flist);
180 rc = ui_control_paint(ctl);
181 if (rc != EOK)
182 return rc;
183
184 rc = gfx_update(gc);
185 if (rc != EOK)
186 return rc;
187
188 return EOK;
189}
190
191/** Handle panel keyboard event.
192 *
193 * @param panel Panel
194 * @param event Keyboard event
195 * @return ui_claimed iff event was claimed
196 */
197ui_evclaim_t panel_kbd_event(panel_t *panel, kbd_event_t *event)
198{
199 ui_control_t *ctl;
200
201 if (!panel->active)
202 return ui_unclaimed;
203
204 ctl = ui_file_list_ctl(panel->flist);
205 return ui_control_kbd_event(ctl, event);
206}
207
208/** Handle panel position event.
209 *
210 * @param panel Panel
211 * @param event Position event
212 * @return ui_claimed iff event was claimed
213 */
214ui_evclaim_t panel_pos_event(panel_t *panel, pos_event_t *event)
215{
216 gfx_coord2_t pos;
217 ui_control_t *ctl;
218
219 pos.x = event->hpos;
220 pos.y = event->vpos;
221 if (!gfx_pix_inside_rect(&pos, &panel->rect))
222 return ui_unclaimed;
223
224 if (!panel->active && event->type == POS_PRESS)
225 panel_activate_req(panel);
226
227 ctl = ui_file_list_ctl(panel->flist);
228 return ui_control_pos_event(ctl, event);
229}
230
231/** Get base control for panel.
232 *
233 * @param panel Panel
234 * @return Base UI control
235 */
236ui_control_t *panel_ctl(panel_t *panel)
237{
238 return panel->control;
239}
240
241/** Set panel rectangle.
242 *
243 * @param panel Panel
244 * @param rect Rectangle
245 */
246void panel_set_rect(panel_t *panel, gfx_rect_t *rect)
247{
248 gfx_rect_t irect;
249
250 panel->rect = *rect;
251
252 irect.p0.x = panel->rect.p0.x + 1;
253 irect.p0.y = panel->rect.p0.y + 1;
254 irect.p1.x = panel->rect.p1.x;
255 irect.p1.y = panel->rect.p1.y - 1;
256
257 ui_file_list_set_rect(panel->flist, &irect);
258}
259
260/** Determine if panel is active.
261 *
262 * @param panel Panel
263 * @return @c true iff panel is active
264 */
265bool panel_is_active(panel_t *panel)
266{
267 return panel->active;
268}
269
270/** Activate panel.
271 *
272 * @param panel Panel
273 *
274 * @return EOK on success or an error code
275 */
276errno_t panel_activate(panel_t *panel)
277{
278 errno_t rc;
279
280 rc = ui_file_list_activate(panel->flist);
281 if (rc != EOK)
282 return rc;
283
284 panel->active = true;
285 (void) panel_paint(panel);
286 return EOK;
287}
288
289/** Deactivate panel.
290 *
291 * @param panel Panel
292 */
293void panel_deactivate(panel_t *panel)
294{
295 ui_file_list_deactivate(panel->flist);
296 panel->active = false;
297 (void) panel_paint(panel);
298}
299
300/** Destroy panel control.
301 *
302 * @param arg Argument (panel_t *)
303 */
304void panel_ctl_destroy(void *arg)
305{
306 panel_t *panel = (panel_t *) arg;
307
308 panel_destroy(panel);
309}
310
311/** Paint panel control.
312 *
313 * @param arg Argument (panel_t *)
314 * @return EOK on success or an error code
315 */
316errno_t panel_ctl_paint(void *arg)
317{
318 panel_t *panel = (panel_t *) arg;
319
320 return panel_paint(panel);
321}
322
323/** Handle panel control keyboard event.
324 *
325 * @param arg Argument (panel_t *)
326 * @param kbd_event Keyboard event
327 * @return @c ui_claimed iff the event is claimed
328 */
329ui_evclaim_t panel_ctl_kbd_event(void *arg, kbd_event_t *event)
330{
331 panel_t *panel = (panel_t *) arg;
332
333 return panel_kbd_event(panel, event);
334}
335
336/** Handle panel control position event.
337 *
338 * @param arg Argument (panel_t *)
339 * @param pos_event Position event
340 * @return @c ui_claimed iff the event is claimed
341 */
342ui_evclaim_t panel_ctl_pos_event(void *arg, pos_event_t *event)
343{
344 panel_t *panel = (panel_t *) arg;
345
346 return panel_pos_event(panel, event);
347}
348
349/** Read directory into panel entry list.
350 *
351 * @param panel Panel
352 * @param dirname Directory path
353 * @return EOK on success or an error code
354 */
355errno_t panel_read_dir(panel_t *panel, const char *dirname)
356{
357 return ui_file_list_read_dir(panel->flist, dirname);
358}
359
360/** Request panel activation.
361 *
362 * Call back to request panel activation.
363 *
364 * @param panel Panel
365 */
366void panel_activate_req(panel_t *panel)
367{
368 if (panel->cb != NULL && panel->cb->activate_req != NULL)
369 panel->cb->activate_req(panel->cb_arg, panel);
370}
371
372/** Open panel file entry.
373 *
374 * Perform Open action on a file entry (i.e. try running it).
375 *
376 * @param panel Panel
377 * @param fname File name
378 *
379 * @return EOK on success or an error code
380 */
381static errno_t panel_open_file(panel_t *panel, const char *fname)
382{
383 task_id_t id;
384 task_wait_t wait;
385 task_exit_t texit;
386 int retval;
387 errno_t rc;
388 ui_t *ui;
389
390 ui = ui_window_get_ui(panel->window);
391
392 /* Free up and clean console for the child task. */
393 rc = ui_suspend(ui);
394 if (rc != EOK)
395 return rc;
396
397 rc = task_spawnl(&id, &wait, fname, fname, NULL);
398 if (rc != EOK)
399 goto error;
400
401 rc = task_wait(&wait, &texit, &retval);
402 if ((rc != EOK) || (texit != TASK_EXIT_NORMAL))
403 goto error;
404
405 /* Resume UI operation */
406 rc = ui_resume(ui);
407 if (rc != EOK)
408 return rc;
409
410 (void) ui_paint(ui_window_get_ui(panel->window));
411 return EOK;
412error:
413 (void) ui_resume(ui);
414 (void) ui_paint(ui_window_get_ui(panel->window));
415 return rc;
416}
417
418/** File in panel file list was selected.
419 *
420 * @param flist File list
421 * @param arg Argument (panel_t *)
422 * @param fname File name
423 */
424static void panel_flist_selected(ui_file_list_t *flist, void *arg,
425 const char *fname)
426{
427 panel_t *panel = (panel_t *)arg;
428
429 (void) panel_open_file(panel, fname);
430}
431
432/** @}
433 */
Note: See TracBrowser for help on using the repository browser.