Implement simple, but impressive windowing system.
[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.1  2006/01/23 23:14:29  bernie
24  *#* Implement simple, but impressive windowing system.
25  *#*
26  *#*/
27
28 #include "win.h"
29
30 /**
31  * Map the contents of all child-windows into the bitmap of \a w.
32  *
33  * Please note that recursively draw children into their parent
34  * effectively damages the parent buffer.
35  */
36 void win_compose(Window *w)
37 {
38         Window *child;
39
40         /*
41          * Walk over all children, in back to front order and tell them
42          * to compose into us.
43          */
44         REVERSE_FOREACH_NODE(child, &w->children)
45         {
46                 /* Recursively compose child first. */
47                 win_compose(child);
48
49                 /* Draw child into our bitmap. */
50                 if (w->bitmap)
51                         gfx_blit(w->bitmap, &child->geom, child->bitmap, 0, 0);
52         }
53 }
54
55 /**
56  * Map window \a w into \a parent.
57  *
58  * The new window becomes the topmost window.
59  *
60  * \note Opening a window twice is illegal.
61  *
62  * \see win_close()
63  */
64 void win_open(Window *w, Window *parent)
65 {
66         ASSERT(!w->parent);
67         w->parent = parent;
68         ADDHEAD(&parent->children, &w->link);
69 }
70
71 /**
72  * Detach window from its parent.
73  *
74  * Closing a window causes it to become orphan of its
75  * parent.  Its content will no longer appear in its
76  * parent after the next refresh cycle.
77  *
78  * \note Closing a window that has not been previously
79  *       opened is illegal.
80  *
81  * \see win_open()
82  */
83 void win_close(Window *w)
84 {
85         ASSERT(w->parent);
86         REMOVE(&w->link);
87         w->parent = NULL;
88 }
89
90 /**
91  * Move window to the topmost position relative to its sibling.
92  *
93  * \see win_move(), win_resize(), win_setGeometry()
94  */
95 void win_raise(Window *w)
96 {
97         ASSERT(w->parent);
98         REMOVE(&w->link);
99         ADDHEAD(&w->parent->children, &w->link);
100 }
101
102 /**
103  * Set window position and size at the same time.
104  *
105  * This function is equivalent to subsequent calls to win_move()
106  * and win_resize() using the coordinates provided by the
107  * \a new_geom rectangle.
108  *
109  * \note The xmax and ymax members of \a new_geom are non-inclusive,
110  *       as usual for the Rect interface.
111  *
112  * \see win_move()
113  * \see win_resize()
114  */
115 void win_setGeometry(Window *w, Rect *new_geom)
116 {
117         // requires C99?
118         // memcpy(&w->geom, new_geom, sizeof(w->geom));
119         w->geom = *new_geom;
120 }
121
122 /**
123  * Move window to specified position.
124  *
125  * Move the window top-left corner to the pixel coordinates
126  * \a left and \a top, which are relative to the parent window.
127  *
128  * \note A window can also be moved outside the borders
129  *       of its parent, or at negative coordinates.
130  *
131  * \note It is allowed to move an orphan window.
132  */
133 void win_move(Window *w, coord_t left, coord_t top)
134 {
135         Rect r;
136
137         r.xmin = left;
138         r.ymin = top;
139         r.xmax = r.xmin + RECT_WIDTH(&w->geom);
140         r.ymax = r.ymin + RECT_WIDTH(&w->geom);
141
142         win_setGeometry(w, &r);
143 }
144
145 /**
146  * Resize the rectangle of a window.
147  *
148  * The window shrinks or grows to the specified size.
149  *
150  * \note Growing a window beyond the size of its
151  *       backing bitmap results in unspecified behavior.
152  *
153  * \note It is allowed to resize an orphan window.
154  */
155 void win_resize(Window *w, coord_t width, coord_t height)
156 {
157         Rect r;
158
159         r.xmin = w->geom.xmin;
160         r.ymin = w->geom.ymin;
161         r.xmax = r.xmin + width;
162         r.ymax = r.ymin + height;
163
164         win_setGeometry(w, &r);
165 }
166
167 /**
168  * Initialize a new window structure.
169  *
170  *
171  * The new window initial position is set to (0,0).
172  * The size is set to the size of the installed bitmap,
173  * or (0,0) if there's no backing store.
174  *
175  * \arg bm  The bitmap to install as backing store
176  *          for drawing into the window, or NULL if
177  *          the window is not drawable.
178  */
179 void win_create(Window *w, Bitmap *bm)
180 {
181         w->parent = NULL;
182         w->bitmap = bm;
183         w->geom.xmin = 0;
184         w->geom.ymin = 0;
185         if (bm)
186         {
187                 w->geom.xmax = bm->width;
188                 w->geom.ymax = bm->height;
189         }
190         LIST_INIT(&w->children);
191 }
192