Replaced ISLISTEMPTY with LIST_EMPTY
[bertos.git] / gfx / win.c
1 /**
2  * \file
3  * <!--
4  * Copyright 2006 Develer S.r.l. (http://www.develer.com/)
5  * This file is part of DevLib - See README.devlib for information.
6  * -->
7  *
8  * \version $Id$
9  *
10  * \author Bernardo Innocenti <bernie@develer.com>
11  *
12  * \brief Very simple hierarchical windowing system.
13  *
14  * All functions in this module are to be intended as methods
15  * of the Window class.  Please see its documentation
16  * for a module-wise introduction.
17  *
18  * \see struct Window
19  */
20
21 /*#*
22  *#* $Log$
23  *#* Revision 1.4  2006/07/19 12:56:26  bernie
24  *#* Convert to new Doxygen style.
25  *#*
26  *#* Revision 1.3  2006/02/10 12:25:41  bernie
27  *#* Add missing header.
28  *#*
29  *#* Revision 1.2  2006/01/26 00:36:48  bernie
30  *#* Const correctness for some new functions.
31  *#*
32  *#* Revision 1.1  2006/01/23 23:14:29  bernie
33  *#* Implement simple, but impressive windowing system.
34  *#*
35  *#*/
36
37 #include "win.h"
38 #include <mware/list.h>
39
40 /**
41  * Map the contents of all child-windows into the bitmap of \a w.
42  *
43  * Please note that recursively draw children into their parent
44  * effectively damages the parent buffer.
45  */
46 void win_compose(Window *w)
47 {
48         Window *child;
49
50         /*
51          * Walk over all children, in back to front order and tell them
52          * to compose into us.
53          */
54         REVERSE_FOREACH_NODE(child, &w->children)
55         {
56                 /* Recursively compose child first. */
57                 win_compose(child);
58
59                 /* Draw child into our bitmap. */
60                 if (w->bitmap)
61                         gfx_blit(w->bitmap, &child->geom, child->bitmap, 0, 0);
62         }
63 }
64
65 /**
66  * Map window \a w into \a parent.
67  *
68  * The new window becomes the topmost window.
69  *
70  * \note Opening a window twice is illegal.
71  *
72  * \see win_close()
73  */
74 void win_open(Window *w, Window *parent)
75 {
76         ASSERT(!w->parent);
77         w->parent = parent;
78         ADDHEAD(&parent->children, &w->link);
79 }
80
81 /**
82  * Detach window from its parent.
83  *
84  * Closing a window causes it to become orphan of its
85  * parent.  Its content will no longer appear in its
86  * parent after the next refresh cycle.
87  *
88  * \note Closing a window that has not been previously
89  *       opened is illegal.
90  *
91  * \see win_open()
92  */
93 void win_close(Window *w)
94 {
95         ASSERT(w->parent);
96         REMOVE(&w->link);
97         w->parent = NULL;
98 }
99
100 /**
101  * Move window to the topmost position relative to its sibling.
102  *
103  * \see win_move(), win_resize(), win_setGeometry()
104  */
105 void win_raise(Window *w)
106 {
107         ASSERT(w->parent);
108         REMOVE(&w->link);
109         ADDHEAD(&w->parent->children, &w->link);
110 }
111
112 /**
113  * Set window position and size at the same time.
114  *
115  * This function is equivalent to subsequent calls to win_move()
116  * and win_resize() using the coordinates provided by the
117  * \a new_geom rectangle.
118  *
119  * \note The xmax and ymax members of \a new_geom are non-inclusive,
120  *       as usual for the Rect interface.
121  *
122  * \see win_move()
123  * \see win_resize()
124  */
125 void win_setGeometry(Window *w, const Rect *new_geom)
126 {
127         // requires C99?
128         // memcpy(&w->geom, new_geom, sizeof(w->geom));
129         w->geom = *new_geom;
130 }
131
132 /**
133  * Move window to specified position.
134  *
135  * Move the window top-left corner to the pixel coordinates
136  * \a left and \a top, which are relative to the parent window.
137  *
138  * \note A window can also be moved outside the borders
139  *       of its parent, or at negative coordinates.
140  *
141  * \note It is allowed to move an orphan window.
142  */
143 void win_move(Window *w, coord_t left, coord_t top)
144 {
145         Rect r;
146
147         r.xmin = left;
148         r.ymin = top;
149         r.xmax = r.xmin + RECT_WIDTH(&w->geom);
150         r.ymax = r.ymin + RECT_WIDTH(&w->geom);
151
152         win_setGeometry(w, &r);
153 }
154
155 /**
156  * Resize the rectangle of a window.
157  *
158  * The window shrinks or grows to the specified size.
159  *
160  * \note Growing a window beyond the size of its
161  *       backing bitmap results in unspecified behavior.
162  *
163  * \note It is allowed to resize an orphan window.
164  */
165 void win_resize(Window *w, coord_t width, coord_t height)
166 {
167         Rect r;
168
169         r.xmin = w->geom.xmin;
170         r.ymin = w->geom.ymin;
171         r.xmax = r.xmin + width;
172         r.ymax = r.ymin + height;
173
174         win_setGeometry(w, &r);
175 }
176
177 /**
178  * Initialize a new window structure.
179  *
180  *
181  * The new window initial position is set to (0,0).
182  * The size is set to the size of the installed bitmap,
183  * or (0,0) if there's no backing store.
184  *
185  * \arg bm  The bitmap to install as backing store
186  *          for drawing into the window, or NULL if
187  *          the window is not drawable.
188  */
189 void win_create(Window *w, Bitmap *bm)
190 {
191         w->parent = NULL;
192         w->bitmap = bm;
193         w->geom.xmin = 0;
194         w->geom.ymin = 0;
195         if (bm)
196         {
197                 w->geom.xmax = bm->width;
198                 w->geom.ymax = bm->height;
199         }
200         LIST_INIT(&w->children);
201 }
202