source: mainline/uspace/lib/gui/grid.c@ 077bc931

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 077bc931 was 6d5e378, checked in by Martin Decky <martin@…>, 13 years ago

cherrypick GUI implementation (originally by Petr Koupy), with several major changes

  • for character-oriented devices a new output server and output protocol was created based on the original fb server
  • DDF visualizer drivers are pixel-oriented only
  • console and compositor can coexist in the same build
  • terminal widget is self-sufficient, no strange console nesting is needed
  • Property mode set to 100644
File size: 6.2 KB
Line 
1/*
2 * Copyright (c) 2012 Petr Koupy
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 gui
30 * @{
31 */
32/**
33 * @file
34 */
35
36#include <assert.h>
37#include <mem.h>
38#include <malloc.h>
39#include <surface.h>
40
41#include "window.h"
42#include "grid.h"
43
44static void paint_internal(widget_t *w)
45{
46 grid_t *grid = (grid_t *) w;
47
48 surface_t *surface = window_claim(grid->widget.window);
49 if (!surface) {
50 window_yield(grid->widget.window);
51 }
52
53 for (sysarg_t y = w->vpos; y < w->vpos + w->height; ++y) {
54 for (sysarg_t x = w->hpos; x < w->hpos + w->width; ++x) {
55 surface_put_pixel(surface, x, y, grid->background);
56 }
57 }
58
59 window_yield(grid->widget.window);
60}
61
62static widget_t **widget_at(grid_t *grid, size_t row, size_t col)
63{
64 if (row < grid->rows && col < grid->cols) {
65 return grid->layout + (row * grid->cols + col);
66 } else {
67 return NULL;
68 }
69}
70
71void deinit_grid(grid_t *grid)
72{
73 widget_deinit(&grid->widget);
74 free(grid->layout);
75}
76
77static void grid_destroy(widget_t *widget)
78{
79 grid_t *grid = (grid_t *) widget;
80
81 deinit_grid(grid);
82
83 free(grid);
84}
85
86static void grid_reconfigure(widget_t *widget)
87{
88 /* no-op */
89}
90
91static void grid_rearrange(widget_t *widget, sysarg_t hpos, sysarg_t vpos,
92 sysarg_t width, sysarg_t height)
93{
94 grid_t *grid = (grid_t *) widget;
95
96 widget_modify(widget, hpos, vpos, width, height);
97 paint_internal(widget);
98
99 sysarg_t cell_width = width / grid->cols;
100 sysarg_t cell_height = height / grid->rows;
101
102 list_foreach(widget->children, link) {
103 widget_t *child = list_get_instance(link, widget_t, link);
104
105 sysarg_t widget_hpos = 0;
106 sysarg_t widget_vpos = 0;
107 sysarg_t widget_width = 0;
108 sysarg_t widget_height = 0;
109
110 size_t r = 0;
111 size_t c = 0;
112 for (r = 0; r < grid->rows; ++r) {
113 bool found = false;
114 for (c = 0; c < grid->cols; ++c) {
115 widget_t **cell = widget_at(grid, r, c);
116 if (cell && *cell == child) {
117 found = true;
118 break;
119 }
120 }
121 if (found) {
122 break;
123 }
124 }
125
126 widget_hpos = cell_width * c + hpos;
127 widget_vpos = cell_height * r + vpos;
128
129 for (size_t _c = c; _c < grid->cols; ++_c) {
130 widget_t **cell = widget_at(grid, r, _c);
131 if (cell && *cell == child) {
132 widget_width += cell_width;
133 } else {
134 break;
135 }
136 }
137
138 for (size_t _r = r; _r < grid->rows; ++_r) {
139 widget_t **cell = widget_at(grid, _r, c);
140 if (cell && *cell == child) {
141 widget_height += cell_height;
142 } else {
143 break;
144 }
145 }
146
147 if (widget_width > 0 && widget_height > 0) {
148 child->rearrange(child,
149 widget_hpos, widget_vpos, widget_width, widget_height);
150 }
151 }
152}
153
154static void grid_repaint(widget_t *widget)
155{
156 paint_internal(widget);
157 list_foreach(widget->children, link) {
158 widget_t *child = list_get_instance(link, widget_t, link);
159 child->repaint(child);
160 }
161 window_damage(widget->window);
162}
163
164static void grid_handle_keyboard_event(widget_t *widget, kbd_event_t event)
165{
166 /* no-op */
167}
168
169static void grid_handle_position_event(widget_t *widget, pos_event_t event)
170{
171 grid_t *grid = (grid_t *) widget;
172
173 if ((widget->height / grid->rows) == 0) {
174 return;
175 }
176 if ((widget->width / grid->cols) == 0) {
177 return;
178 }
179
180 sysarg_t row = (event.vpos - widget->vpos) / (widget->height / grid->rows);
181 sysarg_t col = (event.hpos - widget->hpos) / (widget->width / grid->cols);
182
183 widget_t **cell = widget_at(grid, row, col);
184 if (cell && *cell) {
185 (*cell)->handle_position_event(*cell, event);
186 }
187}
188
189static void grid_add(grid_t *grid, widget_t *widget,
190 size_t row, size_t col, size_t rows, size_t cols)
191{
192 assert(row + rows <= grid->rows);
193 assert(col + cols <= grid->cols);
194
195 widget->parent = (widget_t *) grid;
196 list_append(&widget->link, &grid->widget.children);
197 widget->window = grid->widget.window;
198
199 for (size_t r = row; r < row + rows; ++r) {
200 for (size_t c = col; c < col + cols; ++c) {
201 widget_t **cell = widget_at(grid, r, c);
202 if (cell) {
203 *cell = widget;
204 }
205 }
206 }
207}
208
209bool init_grid(grid_t *grid,
210 widget_t *parent, size_t rows, size_t cols, pixel_t background)
211{
212 assert(rows > 0);
213 assert(cols > 0);
214
215 widget_t **layout = (widget_t **) malloc(rows * cols * sizeof(widget_t *));
216 if (!layout) {
217 return false;
218 }
219 memset(layout, 0, rows * cols * sizeof(widget_t *));
220
221 widget_init(&grid->widget, parent);
222
223 grid->widget.destroy = grid_destroy;
224 grid->widget.reconfigure = grid_reconfigure;
225 grid->widget.rearrange = grid_rearrange;
226 grid->widget.repaint = grid_repaint;
227 grid->widget.handle_keyboard_event = grid_handle_keyboard_event;
228 grid->widget.handle_position_event = grid_handle_position_event;
229
230 grid->add = grid_add;
231 grid->background = background;
232 grid->rows = rows;
233 grid->cols = cols;
234 grid->layout = layout;
235
236 return true;
237}
238
239grid_t *create_grid(widget_t *parent, size_t rows, size_t cols, pixel_t background)
240{
241 grid_t *grid = (grid_t *) malloc(sizeof(grid_t));
242 if (!grid) {
243 return NULL;
244 }
245
246 if (init_grid(grid, parent, rows, cols, background)) {
247 return grid;
248 } else {
249 free(grid);
250 return NULL;
251 }
252}
253
254/** @}
255 */
Note: See TracBrowser for help on using the repository browser.