1 /* gui_canvas.c - GUI container allowing manually placed components. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008,2009 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
21 #include <grub/misc.h>
23 #include <grub/gui_string_util.h>
25 /* TODO Add layering so that components can be properly overlaid. */
29 grub_gui_component_t component
;
30 struct component_node
*next
;
33 struct grub_gui_canvas
35 struct grub_gui_container container
;
37 grub_gui_container_t parent
;
38 grub_video_rect_t bounds
;
40 /* Component list (dummy head node). */
41 struct component_node components
;
44 typedef struct grub_gui_canvas
*grub_gui_canvas_t
;
47 canvas_destroy (void *vself
)
49 grub_gui_canvas_t self
= vself
;
50 struct component_node
*cur
;
51 struct component_node
*next
;
52 for (cur
= self
->components
.next
; cur
; cur
= next
)
54 /* Copy the 'next' pointer, since we need it for the next iteration,
55 and we're going to free the memory it is stored in. */
57 /* Destroy the child component. */
58 cur
->component
->ops
->destroy (cur
->component
);
59 /* Free the linked list node. */
66 canvas_get_id (void *vself
)
68 grub_gui_canvas_t self
= vself
;
73 canvas_is_instance (void *vself
__attribute__((unused
)), const char *type
)
75 return (grub_strcmp (type
, "component") == 0
76 || grub_strcmp (type
, "container") == 0);
80 canvas_paint (void *vself
, const grub_video_rect_t
*region
)
82 grub_gui_canvas_t self
= vself
;
83 struct component_node
*cur
;
84 grub_video_rect_t vpsave
;
86 grub_gui_set_viewport (&self
->bounds
, &vpsave
);
87 for (cur
= self
->components
.next
; cur
; cur
= cur
->next
)
90 grub_gui_component_t comp
;
93 comp
= cur
->component
;
95 w
= grub_fixed_sfs_multiply (self
->bounds
.width
, comp
->wfrac
) + comp
->w
;
96 h
= grub_fixed_sfs_multiply (self
->bounds
.height
, comp
->hfrac
) + comp
->h
;
97 x
= grub_fixed_sfs_multiply (self
->bounds
.width
, comp
->xfrac
) + comp
->x
;
98 y
= grub_fixed_sfs_multiply (self
->bounds
.height
, comp
->yfrac
) + comp
->y
;
100 if (comp
->ops
->get_minimal_size
)
104 comp
->ops
->get_minimal_size (comp
, &mw
, &mh
);
117 if (x
>= (signed) self
->bounds
.width
)
118 x
= self
->bounds
.width
- 32;
119 if (y
>= (signed) self
->bounds
.height
)
120 y
= self
->bounds
.height
- 32;
127 if (x
+ w
>= (signed) self
->bounds
.width
)
128 w
= self
->bounds
.width
- x
;
129 if (y
+ h
>= (signed) self
->bounds
.height
)
130 h
= self
->bounds
.height
- y
;
136 comp
->ops
->set_bounds (comp
, &r
);
138 /* Paint the child. */
139 if (grub_video_have_common_points (region
, &r
))
140 comp
->ops
->paint (comp
, region
);
142 grub_gui_restore_viewport (&vpsave
);
146 canvas_set_parent (void *vself
, grub_gui_container_t parent
)
148 grub_gui_canvas_t self
= vself
;
149 self
->parent
= parent
;
152 static grub_gui_container_t
153 canvas_get_parent (void *vself
)
155 grub_gui_canvas_t self
= vself
;
160 canvas_set_bounds (void *vself
, const grub_video_rect_t
*bounds
)
162 grub_gui_canvas_t self
= vself
;
163 self
->bounds
= *bounds
;
167 canvas_get_bounds (void *vself
, grub_video_rect_t
*bounds
)
169 grub_gui_canvas_t self
= vself
;
170 *bounds
= self
->bounds
;
174 canvas_set_property (void *vself
, const char *name
, const char *value
)
176 grub_gui_canvas_t self
= vself
;
177 if (grub_strcmp (name
, "id") == 0)
179 grub_free (self
->id
);
182 self
->id
= grub_strdup (value
);
193 canvas_add (void *vself
, grub_gui_component_t comp
)
195 grub_gui_canvas_t self
= vself
;
196 struct component_node
*node
;
197 node
= grub_malloc (sizeof (*node
));
199 return; /* Note: probably should handle the error. */
200 node
->component
= comp
;
201 node
->next
= self
->components
.next
;
202 self
->components
.next
= node
;
203 comp
->ops
->set_parent (comp
, (grub_gui_container_t
) self
);
207 canvas_remove (void *vself
, grub_gui_component_t comp
)
209 grub_gui_canvas_t self
= vself
;
210 struct component_node
*cur
;
211 struct component_node
*prev
;
212 prev
= &self
->components
;
213 for (cur
= self
->components
.next
; cur
; prev
= cur
, cur
= cur
->next
)
215 if (cur
->component
== comp
)
217 /* Unlink 'cur' from the list. */
218 prev
->next
= cur
->next
;
219 /* Free the node's memory (but don't destroy the component). */
221 /* Must not loop again, since 'cur' would be dereferenced! */
228 canvas_iterate_children (void *vself
,
229 grub_gui_component_callback cb
, void *userdata
)
231 grub_gui_canvas_t self
= vself
;
232 struct component_node
*cur
;
233 for (cur
= self
->components
.next
; cur
; cur
= cur
->next
)
234 cb (cur
->component
, userdata
);
237 static struct grub_gui_component_ops canvas_comp_ops
=
239 .destroy
= canvas_destroy
,
240 .get_id
= canvas_get_id
,
241 .is_instance
= canvas_is_instance
,
242 .paint
= canvas_paint
,
243 .set_parent
= canvas_set_parent
,
244 .get_parent
= canvas_get_parent
,
245 .set_bounds
= canvas_set_bounds
,
246 .get_bounds
= canvas_get_bounds
,
247 .set_property
= canvas_set_property
250 static struct grub_gui_container_ops canvas_ops
=
253 .remove
= canvas_remove
,
254 .iterate_children
= canvas_iterate_children
258 grub_gui_canvas_new (void)
260 grub_gui_canvas_t canvas
;
261 canvas
= grub_zalloc (sizeof (*canvas
));
264 canvas
->container
.ops
= &canvas_ops
;
265 canvas
->container
.component
.ops
= &canvas_comp_ops
;
266 return (grub_gui_container_t
) canvas
;