Add to git.
[monolith.git] / src / ml_tabbed_layout.c
1 /* Monolith tabbed layout class.
2  * - by Richard W.M. Jones <rich@annexia.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *
18  * $Id: ml_tabbed_layout.c,v 1.1 2002/11/13 20:46:37 rich Exp $
19  */
20
21 #include "config.h"
22
23 #include <assert.h>
24
25 #include <pool.h>
26 #include <vector.h>
27
28 #include <pthr_iolib.h>
29
30 #include "ml_widget.h"
31 #include "monolith.h"
32 #include "ml_tabbed_layout.h"
33
34 static void repaint (void *, ml_session, const char *, io_handle);
35
36 struct ml_widget_operations tabbed_layout_ops =
37   {
38     repaint: repaint
39   };
40
41 struct ml_tabbed_layout
42 {
43   struct ml_widget_operations *ops;
44   pool pool;                    /* Pool for allocations. */
45   vector tabs;                  /* Vector of tabs. */
46   vector order;                 /* Display order (first = top). */
47 };
48
49 struct tab
50 {
51   const char *name;             /* Name of the tab. */
52   ml_widget w;                  /* Widget. */
53 }
54
55 ml_tabbed_layout
56 new_ml_tabbed_layout (pool pool)
57 {
58   ml_tabbed_layout w = pmalloc (pool, sizeof *w);
59
60   w->ops = &tabbed_layout_ops;
61   w->pool = pool;
62   w->tabs = new_vector (pool, struct tab);
63   w->order = new_vector (pool, int);
64
65   return w;
66 }
67
68 static inline void
69 add_tab_to_order (ml_tabbed_layout w, int index)
70 {
71   vector_push_back (w->order, index);
72 }
73
74 static inline void
75 del_tab_from_order (ml_tabbed_layout w, int index)
76 {
77   int n, i;
78
79   for (n = 0; n < vector_size (w->order); ++n)
80     {
81       vector_get (w->order, n, i);
82       if (i == index)
83         {
84           vector_erase (w->order, n);
85           break;
86         }
87     }
88 }
89
90 static inline void
91 increment_order (ml_tabbed_layout w, int first_index)
92 {
93   int n, i;
94
95   for (n = 0; n < vector_size (w->order); ++n)
96     {
97       vector_get (w->order, n, i);
98       if (i >= first_index)
99         {
100           i++;
101           vector_replace (w->order, n, i);
102         }
103     }
104 }
105
106 static inline void
107 decrement_order (ml_tabbed_layout w, int first_index)
108 {
109   int n, i;
110
111   for (n = 0; n < vector_size (w->order); ++n)
112     {
113       vector_get (w->order, n, i);
114       if (i >= first_index)
115         {
116           i++;
117           vector_replace (w->order, n, i);
118         }
119     }
120 }
121
122 void
123 ml_tabbed_layout_push_back (ml_tabbed_layout w, const char *name, ml_widget _w)
124 {
125   struct tab tab;
126
127   tab.name = name;
128   tab.w = _w;
129   vector_push_back (w->tabs, tab);
130
131   add_tab_to_order (w, vector_size (w->tabs) - 1);
132 }
133
134 ml_widget
135 ml_tabbed_layout_pop_back (ml_tabbed_layout w)
136 {
137   struct tab tab;
138
139   vector_pop_back (w->tabs, tab);
140   del_tab_from_order (w, vector_size (w->tabs));
141   return tab.w;
142 }
143
144 void
145 ml_tabbed_layout_push_front (ml_tabbed_layout w,
146                              const char *name, ml_widget _w)
147 {
148   struct tab tab;
149
150   tab.name = name;
151   tab.w = _w;
152   vector_push_front (w->tabs, tab);
153
154   increment_order (w, 0);
155   add_tab_to_order (w, 0);
156 }
157
158 ml_widget
159 ml_tabbed_layout_pop_front (ml_tabbed_layout w)
160 {
161   struct tab tab;
162
163   vector_pop_front (w->tabs, tab);
164   del_tab_from_order (w, vector_size (w->tabs));
165   decrement_order (w, 1);
166   return tab.w;
167 }
168
169 ml_widget
170 ml_tabbed_layout_get (ml_tabbed_layout w, int i)
171 {
172   struct tab tab;
173
174   vector_get (w->tabs, i, tab);
175   return tab.w;
176 }
177
178 void
179 ml_tabbed_layout_insert (ml_tabbed_layout w, int i,
180                          const char *name, ml_widget _w)
181 {
182   struct tab tab;
183
184   tab.name = name;
185   tab.w = _w;
186   vector_insert (w->tabs, i, tab);
187
188   increment_order (w, i);
189   add_tab_to_order (w, i);
190 }
191
192 void
193 ml_tabbed_layout_replace (ml_tabbed_layout w, int i,
194                           const char *name, ml_widget _w)
195 {
196   struct tab tab;
197
198   tab.name = name;
199   tab.w = _w;
200   vector_replace (w->tabs, i, tab);
201
202   ml_tabbed_layout_send_to_back (w, i);
203 }
204
205 void
206 ml_tabbed_layout_erase (ml_tabbed_layout w, int i)
207 {
208   vector_erase (w->tabs, i);
209   del_tab_from_order (w, i);
210   decrement_order (w, i+1);
211 }
212
213 void
214 ml_tabbed_layout_clear (ml_tabbed_layout w)
215 {
216   vector_clear (w->tabs);
217   vector_clear (w->order);
218 }
219
220 int
221 ml_tabbed_layout_size (ml_tabbed_layout w)
222 {
223   return vector_size (w->tabs);
224 }
225
226 void
227 ml_tabbed_layout_pack (ml_tabbed_layout w, const char *name, ml_widget _w)
228 {
229   ml_tabbed_layout_push_back (w, name, _w);
230 }
231
232 void
233 ml_tabbed_layout_bring_to_front (ml_tabbed_layout w, int i)
234 {
235   int i;
236
237   vector_pop_back (w->order, i);
238   vector_push_front (w->order, i);
239 }
240
241 void
242 ml_tabbed_layout_send_to_back (ml_tabbed_layout w, int i)
243 {
244   int i;
245
246   vector_pop_front (w->order, i);
247   vector_push_back (w->order, i);
248 }
249
250 int
251 ml_tabbed_layout_get_front_tab (ml_tabbed_layout w)
252 {
253   int i;
254
255   vector_get (w->order, 0, i);
256   return i;
257 }
258
259 /* This function verifies the integrity of the internal structures. We
260  * can remove it once the tabbed layout has become a bit more mature.
261  */
262 static inline void
263 verify_structures (ml_tabbed_layout w)
264 {
265   vector marks;
266   unsigned char c = 0;
267   int i, n;
268
269   assert (vector_size (w->tabs) == vector_size (w->order));
270
271   marks = new_vector (w->pool, unsigned char);
272   vector_fill (marks, c, vector_size (w->tabs));
273
274   for (n = 0; n < vector_size (w->order); ++n)
275     {
276       vector_get (w->order, n, i);
277       vector_get (marks, i, c);
278       assert (c == 0);
279       c = 1;
280       vector_replace (marks, i, c);
281     }
282 }
283
284 static void
285 repaint (void *vw, ml_session session, const char *windowid, io_handle io)
286 {
287   ml_tabbed_layout w = (ml_tabbed_layout) vw;
288   int i;
289
290   verify_structures (w);
291
292   XXX;
293
294   for (i = 0; i < vector_size (w->v); ++i)
295     {
296       ml_widget _w;
297
298       vector_get (w->v, i, _w);
299       ml_widget_repaint (_w, session, windowid, io);
300     }
301 }