source: mainline/uspace/lib/ui/src/wdecor.c@ 20667af

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 20667af was 3583ffb, checked in by Jiri Svoboda <jiri@…>, 5 years ago

Revert "Create UI controls based on UI object…"

This was a mistake. Controls need ui_resource object, which must be
(at least currently) specific to a window and cannot be obtained from
ui_t.

  • Property mode set to 100644
File size: 8.4 KB
Line 
1/*
2 * Copyright (c) 2020 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 libui
30 * @{
31 */
32/**
33 * @file Window decoration
34 */
35
36#include <errno.h>
37#include <gfx/color.h>
38#include <gfx/context.h>
39#include <gfx/render.h>
40#include <gfx/text.h>
41#include <io/pos_event.h>
42#include <stdlib.h>
43#include <str.h>
44#include <ui/paint.h>
45#include <ui/pbutton.h>
46#include <ui/wdecor.h>
47#include "../private/resource.h"
48#include "../private/wdecor.h"
49
50static void ui_wdecor_btn_clicked(ui_pbutton_t *, void *);
51
52static ui_pbutton_cb_t ui_wdecor_btn_close_cb = {
53 .clicked = ui_wdecor_btn_clicked
54};
55
56/** Create new window decoration.
57 *
58 * @param resource UI resource
59 * @param caption Window caption
60 * @param rwdecor Place to store pointer to new window decoration
61 * @return EOK on success, ENOMEM if out of memory
62 */
63errno_t ui_wdecor_create(ui_resource_t *resource, const char *caption,
64 ui_wdecor_t **rwdecor)
65{
66 ui_wdecor_t *wdecor;
67 errno_t rc;
68
69 wdecor = calloc(1, sizeof(ui_wdecor_t));
70 if (wdecor == NULL)
71 return ENOMEM;
72
73 wdecor->caption = str_dup(caption);
74 if (wdecor->caption == NULL) {
75 free(wdecor);
76 return ENOMEM;
77 }
78
79 rc = ui_pbutton_create(resource, "X", &wdecor->btn_close);
80 if (rc != EOK) {
81 free(wdecor->caption);
82 free(wdecor);
83 return rc;
84 }
85
86 ui_pbutton_set_cb(wdecor->btn_close, &ui_wdecor_btn_close_cb,
87 (void *)wdecor);
88
89 wdecor->res = resource;
90 wdecor->active = true;
91 *rwdecor = wdecor;
92 return EOK;
93}
94
95/** Destroy window decoration.
96 *
97 * @param wdecor Window decoration or @c NULL
98 */
99void ui_wdecor_destroy(ui_wdecor_t *wdecor)
100{
101 if (wdecor == NULL)
102 return;
103
104 ui_pbutton_destroy(wdecor->btn_close);
105 free(wdecor->caption);
106 free(wdecor);
107}
108
109/** Set window decoration callbacks.
110 *
111 * @param wdecor Window decoration
112 * @param cb Window decoration callbacks
113 * @param arg Callback argument
114 */
115void ui_wdecor_set_cb(ui_wdecor_t *wdecor, ui_wdecor_cb_t *cb, void *arg)
116{
117 wdecor->cb = cb;
118 wdecor->arg = arg;
119}
120
121/** Set window decoration rectangle.
122 *
123 * @param wdecor Window decoration
124 * @param rect New window decoration rectangle
125 */
126void ui_wdecor_set_rect(ui_wdecor_t *wdecor, gfx_rect_t *rect)
127{
128 ui_wdecor_geom_t geom;
129
130 wdecor->rect = *rect;
131
132 ui_wdecor_get_geom(wdecor, &geom);
133 ui_pbutton_set_rect(wdecor->btn_close, &geom.btn_close_rect);
134}
135
136/** Set active flag.
137 *
138 * Active window is the one receiving keyboard events.
139 *
140 * @param wdecor Window decoration
141 * @param active @c true iff window is active
142 */
143void ui_wdecor_set_active(ui_wdecor_t *wdecor, bool active)
144{
145 wdecor->active = active;
146}
147
148/** Paint window decoration.
149 *
150 * @param wdecor Window decoration
151 * @return EOK on success or an error code
152 */
153errno_t ui_wdecor_paint(ui_wdecor_t *wdecor)
154{
155 errno_t rc;
156 gfx_rect_t rect;
157 gfx_rect_t trect;
158 gfx_text_fmt_t fmt;
159 gfx_coord2_t pos;
160 ui_wdecor_geom_t geom;
161
162 rect = wdecor->rect;
163 ui_wdecor_get_geom(wdecor, &geom);
164
165 rc = ui_paint_bevel(wdecor->res->gc, &rect,
166 wdecor->res->wnd_frame_hi_color,
167 wdecor->res->wnd_frame_sh_color, 1, &rect);
168 if (rc != EOK)
169 return rc;
170
171 rc = ui_paint_bevel(wdecor->res->gc, &rect,
172 wdecor->res->wnd_highlight_color,
173 wdecor->res->wnd_shadow_color, 1, &rect);
174 if (rc != EOK)
175 return rc;
176
177 rc = ui_paint_bevel(wdecor->res->gc, &rect,
178 wdecor->res->wnd_face_color,
179 wdecor->res->wnd_face_color, 2, &rect);
180 if (rc != EOK)
181 return rc;
182
183 trect = geom.title_bar_rect;
184
185 rc = ui_paint_bevel(wdecor->res->gc, &trect,
186 wdecor->res->wnd_shadow_color,
187 wdecor->res->wnd_highlight_color, 1, &trect);
188 if (rc != EOK)
189 return rc;
190
191 rc = gfx_set_color(wdecor->res->gc, wdecor->active ?
192 wdecor->res->tbar_act_bg_color :
193 wdecor->res->tbar_inact_bg_color);
194 if (rc != EOK)
195 return rc;
196
197 rc = gfx_fill_rect(wdecor->res->gc, &trect);
198 if (rc != EOK)
199 return rc;
200
201 gfx_text_fmt_init(&fmt);
202 fmt.halign = gfx_halign_center;
203 fmt.valign = gfx_valign_center;
204
205 pos.x = (trect.p0.x + trect.p1.x) / 2;
206 pos.y = (trect.p0.y + trect.p1.y) / 2;
207
208 rc = gfx_set_color(wdecor->res->gc, wdecor->active ?
209 wdecor->res->tbar_act_text_color :
210 wdecor->res->tbar_inact_text_color);
211 if (rc != EOK)
212 return rc;
213
214 rc = gfx_puttext(wdecor->res->font, &pos, &fmt, wdecor->caption);
215 if (rc != EOK)
216 return rc;
217
218 rc = ui_pbutton_paint(wdecor->btn_close);
219 if (rc != EOK)
220 return rc;
221
222 return EOK;
223}
224
225/** Send decoration close event.
226 *
227 * @param wdecor Window decoration
228 */
229void ui_wdecor_close(ui_wdecor_t *wdecor)
230{
231 if (wdecor->cb != NULL && wdecor->cb->close != NULL)
232 wdecor->cb->close(wdecor, wdecor->arg);
233}
234
235/** Send decoration move event.
236 *
237 * @param wdecor Window decoration
238 * @param pos Position where the title bar was pressed
239 */
240void ui_wdecor_move(ui_wdecor_t *wdecor, gfx_coord2_t *pos)
241{
242 if (wdecor->cb != NULL && wdecor->cb->move != NULL)
243 wdecor->cb->move(wdecor, wdecor->arg, pos);
244}
245
246/** Get window decoration geometry.
247 *
248 * @param wdecor Window decoration
249 * @param geom Structure to fill in with computed geometry
250 */
251void ui_wdecor_get_geom(ui_wdecor_t *wdecor, ui_wdecor_geom_t *geom)
252{
253 geom->interior_rect.p0.x = wdecor->rect.p0.x + 4;
254 geom->interior_rect.p0.y = wdecor->rect.p0.y + 4;
255 geom->interior_rect.p1.x = wdecor->rect.p1.x - 4;
256 geom->interior_rect.p1.y = wdecor->rect.p1.y - 4;
257
258 geom->title_bar_rect.p0 = geom->interior_rect.p0;
259 geom->title_bar_rect.p1.x = geom->interior_rect.p1.x;
260 geom->title_bar_rect.p1.y = geom->interior_rect.p0.y + 22;
261
262 geom->btn_close_rect.p0.x = geom->title_bar_rect.p1.x - 1 - 20;
263 geom->btn_close_rect.p0.y = geom->title_bar_rect.p0.y + 1;
264 geom->btn_close_rect.p1.x = geom->title_bar_rect.p1.x - 1;
265 geom->btn_close_rect.p1.y = geom->title_bar_rect.p0.y + 1 + 20;
266
267 geom->app_area_rect.p0.x = geom->interior_rect.p0.x;
268 geom->app_area_rect.p0.y = geom->title_bar_rect.p1.y;
269 geom->app_area_rect.p1 = geom->interior_rect.p1;
270}
271
272/** Get outer rectangle from application area rectangle.
273 *
274 * Note that this needs to work just based on a UI, without having an actual
275 * window decoration, since we need it in order to create the window
276 * and its decoration.
277 *
278 * @param app Application area rectangle
279 * @param rect Place to store (outer) window decoration rectangle
280 */
281void ui_wdecor_rect_from_app(gfx_rect_t *app, gfx_rect_t *rect)
282{
283 rect->p0.x = app->p0.x - 4;
284 rect->p0.y = app->p0.y - 22 - 4;
285 rect->p1.x = app->p1.x + 4;
286 rect->p1.y = app->p1.y + 4;
287}
288
289/** Handle window decoration position event.
290 *
291 * @param wdecor Window decoration
292 * @param pos_event Position event
293 */
294void ui_wdecor_pos_event(ui_wdecor_t *wdecor, pos_event_t *event)
295{
296 gfx_coord2_t pos;
297 ui_wdecor_geom_t geom;
298 ui_evclaim_t claim;
299
300 pos.x = event->hpos;
301 pos.y = event->vpos;
302
303 ui_wdecor_get_geom(wdecor, &geom);
304
305 claim = ui_pbutton_pos_event(wdecor->btn_close, event);
306 if (claim == ui_claimed)
307 return;
308
309 if (event->type == POS_PRESS &&
310 gfx_pix_inside_rect(&pos, &geom.title_bar_rect))
311 ui_wdecor_move(wdecor, &pos);
312}
313
314/** Window decoration close button was clicked.
315 *
316 * @param pbutton Close button
317 * @param arg Argument (ui_wdecor_t)
318 */
319static void ui_wdecor_btn_clicked(ui_pbutton_t *pbutton, void *arg)
320{
321 ui_wdecor_t *wdecor = (ui_wdecor_t *) arg;
322
323 (void) pbutton;
324 ui_wdecor_close(wdecor);
325}
326
327/** @}
328 */
Note: See TracBrowser for help on using the repository browser.