source: mainline/uspace/app/nav/panel.c

Last change on this file was b336bfd8, checked in by Jiri Svoboda <jiri@…>, 5 months ago

Start text editor if open action is used on .txt file.

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