Add to git.
[monolith.git] / examples / 05_popup_windows_and_frames.c
1 /* Demonstrate pop-up windows and frames.
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: 05_popup_windows_and_frames.c,v 1.6 2002/10/30 21:03:00 rich Exp $
19  */
20
21 #include <stdio.h>
22 #include <math.h>
23
24 #include <pool.h>
25 #include <pstring.h>
26 #include <pthr_cgi.h>
27
28 #include "monolith.h"
29 #include "ml_window.h"
30 #include "ml_button.h"
31 #include "ml_table_layout.h"
32 #include "ml_text_label.h"
33 #include "ml_form.h"
34 #include "ml_form_text.h"
35 #include "ml_form_submit.h"
36
37 /* Main entry point to the app. */
38 static void app_main (ml_session);
39
40 int
41 handle_request (rws_request rq)
42 {
43   return ml_entry_point (rq, app_main);
44 }
45
46 /* Private per-session data. */
47 struct data
48 {
49   /* Main window. */
50   ml_window main_win;
51   ml_table_layout main_tbl;
52   ml_text_label main_text;
53   ml_button main_b[3];
54
55   /* Area-of-circle window. */
56   ml_window circle_win;
57   ml_table_layout circle_tbl;
58   ml_text_label circle_text1, circle_text2, circle_ans;
59   ml_form circle_form;
60   ml_form_text circle_input;
61   ml_form_submit circle_submit;
62
63   /* Volume-of-cone window. */
64   ml_window cone_win;
65   ml_table_layout cone_tbl;
66   ml_text_label cone_text1, cone_text2, cone_text3, cone_ans;
67   ml_form cone_form;
68   ml_form_text cone_input1, cone_input2;
69   ml_form_submit cone_submit;
70
71   /* Frames window. */
72   ml_window frames_win;
73   ml_window frames_tl_win;
74   ml_window frames_bl_win;
75   ml_window frames_tr_win;
76   ml_window frames_br_win;
77   ml_text_label frames_tl_text;
78   ml_text_label frames_bl_text;
79   ml_text_label frames_tr_text;
80   ml_text_label frames_br_text;
81 };
82
83 static void circle (ml_session session, void *vp);
84 static void circle_calculate (ml_session session, void *vp);
85 static void cone (ml_session session, void *vp);
86 static void cone_calculate (ml_session session, void *vp);
87 static void frames (ml_session session, void *vp);
88 static void tl_frame (ml_session session, void *vp);
89 static void bl_frame (ml_session session, void *vp);
90 static void tr_frame (ml_session session, void *vp);
91 static void br_frame (ml_session session, void *vp);
92
93 static void
94 app_main (ml_session session)
95 {
96   pool pool = ml_session_pool (session);
97   struct data *data;
98
99   /* Create the per-session data area. */
100   data = pmalloc (pool, sizeof *data);
101
102   /* Create the top-level window. */
103   data->main_win = new_ml_window (session, pool);
104   data->main_tbl = new_ml_table_layout (pool, 2, 3);
105   data->main_text = new_ml_text_label (pool, "Select a demo");
106
107   /* Create some buttons to launch the different windows. */
108   data->main_b[0] = new_ml_button (pool, "Area of a circle");
109   ml_button_set_popup (data->main_b[0], "popupdemo_circle");
110   ml_button_set_popup_size (data->main_b[0], 300, 200);
111   ml_button_set_callback (data->main_b[0], circle, session, data);
112   data->main_b[1] = new_ml_button (pool, "Volume of a cone");
113   ml_button_set_popup (data->main_b[1], "popupdemo_cone");
114   ml_button_set_popup_size (data->main_b[1], 300, 200);
115   ml_button_set_callback (data->main_b[1], cone, session, data);
116   data->main_b[2] = new_ml_button (pool, "Frames demo");
117   ml_button_set_popup (data->main_b[2], "popupdemo_frames");
118   ml_button_set_popup_size (data->main_b[2], 640, 480);
119   ml_button_set_callback (data->main_b[2], frames, session, data);
120
121   /* Pack everything up. */
122   ml_table_layout_pack (data->main_tbl, data->main_text, 0, 0);
123   ml_table_layout_set_colspan (data->main_tbl, 0, 0, 3);
124   ml_table_layout_set_align (data->main_tbl, 0, 0, "center");
125   ml_table_layout_pack (data->main_tbl, data->main_b[0], 1, 0);
126   ml_table_layout_pack (data->main_tbl, data->main_b[1], 1, 1);
127   ml_table_layout_pack (data->main_tbl, data->main_b[2], 1, 2);
128   ml_window_pack (data->main_win, data->main_tbl);
129 }
130
131 static void
132 circle (ml_session session, void *vp)
133 {
134   pool pool = ml_session_pool (session);
135   struct data *data = (struct data *) vp;
136
137   /* Top-level window. */
138   data->circle_win = new_ml_window (session, pool);
139
140   /* Construct the form. */
141   data->circle_form = new_ml_form (pool);
142   data->circle_tbl = new_ml_table_layout (pool, 3, 2);
143   data->circle_text1 = new_ml_text_label (pool, "Radius:");
144   ml_table_layout_pack (data->circle_tbl, data->circle_text1, 0, 0);
145   data->circle_input = new_ml_form_text (pool, data->circle_form);
146   ml_table_layout_pack (data->circle_tbl, data->circle_input, 0, 1);
147   data->circle_submit = new_ml_form_submit (pool, data->circle_form,
148                                             "Calculate");
149   ml_table_layout_pack (data->circle_tbl, data->circle_submit, 1, 1);
150   data->circle_text2 = new_ml_text_label (pool, "Answer:");
151   ml_table_layout_pack (data->circle_tbl, data->circle_text2, 2, 0);
152   data->circle_ans = new_ml_text_label (pool, "");
153   ml_table_layout_pack (data->circle_tbl, data->circle_ans, 2, 1);
154
155   ml_form_pack (data->circle_form, data->circle_tbl);
156   ml_window_pack (data->circle_win, data->circle_form);
157
158   /* Set the callback for the form. */
159   ml_form_set_callback (data->circle_form, circle_calculate, session, data);
160 }
161
162 static void
163 circle_calculate (ml_session session, void *vp)
164 {
165   pool pool = ml_session_pool (session);
166   struct data *data = (struct data *) vp;
167   const char *r;
168   double radius, area;
169
170   r = ml_form_input_get_value (data->circle_input);
171   if (r && sscanf (r, "%lf", &radius) == 1)
172     {
173       area = M_PI * radius * radius;
174       ml_widget_set_property (data->circle_ans, "text",
175                               psprintf (pool, "%g", area));
176     }
177   else
178     {
179       ml_widget_set_property (data->circle_ans, "text", "Not a number!");
180     }
181 }
182
183 static void
184 cone (ml_session session, void *vp)
185 {
186   pool pool = ml_session_pool (session);
187   struct data *data = (struct data *) vp;
188
189   /* Top-level window. */
190   data->cone_win = new_ml_window (session, pool);
191
192   /* Construct the form. */
193   data->cone_form = new_ml_form (pool);
194   data->cone_tbl = new_ml_table_layout (pool, 4, 2);
195   data->cone_text1 = new_ml_text_label (pool, "Radius:");
196   ml_table_layout_pack (data->cone_tbl, data->cone_text1, 0, 0);
197   data->cone_input1 = new_ml_form_text (pool, data->cone_form);
198   ml_table_layout_pack (data->cone_tbl, data->cone_input1, 0, 1);
199   data->cone_text3 = new_ml_text_label (pool, "Height:");
200   ml_table_layout_pack (data->cone_tbl, data->cone_text3, 1, 0);
201   data->cone_input2 = new_ml_form_text (pool, data->cone_form);
202   ml_table_layout_pack (data->cone_tbl, data->cone_input2, 1, 1);
203   data->cone_submit = new_ml_form_submit (pool, data->cone_form,
204                                           "Calculate");
205   ml_table_layout_pack (data->cone_tbl, data->cone_submit, 2, 1);
206   data->cone_text2 = new_ml_text_label (pool, "Answer:");
207   ml_table_layout_pack (data->cone_tbl, data->cone_text2, 3, 0);
208   data->cone_ans = new_ml_text_label (pool, "");
209   ml_table_layout_pack (data->cone_tbl, data->cone_ans, 3, 1);
210
211   ml_form_pack (data->cone_form, data->cone_tbl);
212   ml_window_pack (data->cone_win, data->cone_form);
213
214   /* Set the callback for the form. */
215   ml_form_set_callback (data->cone_form, cone_calculate, session, data);
216 }
217
218 static void
219 cone_calculate (ml_session session, void *vp)
220 {
221   pool pool = ml_session_pool (session);
222   struct data *data = (struct data *) vp;
223   const char *r, *h;
224   double radius, height, vol;
225
226   r = ml_form_input_get_value (data->cone_input1);
227   h = ml_form_input_get_value (data->cone_input2);
228   if (r && sscanf (r, "%lf", &radius) == 1 &&
229       h && sscanf (h, "%lf", &height) == 1)
230     {
231       vol = M_PI * radius * radius * height / 3.0;
232       ml_widget_set_property (data->cone_ans, "text",
233                               psprintf (pool, "%g", vol));
234     }
235   else
236     {
237       ml_widget_set_property (data->cone_ans, "text", "Not a number!");
238     }
239 }
240
241 static void
242 frames (ml_session session, void *vp)
243 {
244   pool pool = ml_session_pool (session);
245   struct data *data = (struct data *) vp;
246   vector fs;
247   struct ml_frame_description f;
248
249   /* Create the top-level frameset. */
250   fs = new_vector (pool, struct ml_frame_description);
251
252   f.fn = tl_frame; f.data = data;
253   vector_push_back (fs, f);
254
255   f.fn = bl_frame; f.data = data;
256   vector_push_back (fs, f);
257
258   f.fn = tr_frame; f.data = data;
259   vector_push_back (fs, f);
260
261   f.fn = br_frame; f.data = data;
262   vector_push_back (fs, f);
263
264   data->frames_win = new_ml_frameset (session, pool, "60%,40%", "34%,66%", fs);
265 }
266
267 static void
268 tl_frame (ml_session session, void *vp)
269 {
270   pool pool = ml_session_pool (session);
271   struct data *data = (struct data *) vp;
272
273   data->frames_tl_win = new_ml_window (session, pool);
274   data->frames_tl_text = new_ml_text_label (pool, "Top left frame");
275   ml_window_pack (data->frames_tl_win, data->frames_tl_text);
276 }
277
278 static void
279 bl_frame (ml_session session, void *vp)
280 {
281   pool pool = ml_session_pool (session);
282   struct data *data = (struct data *) vp;
283
284   data->frames_bl_win = new_ml_window (session, pool);
285   data->frames_bl_text = new_ml_text_label (pool, "Bottom left frame");
286   ml_window_pack (data->frames_bl_win, data->frames_bl_text);
287 }
288
289 static void
290 tr_frame (ml_session session, void *vp)
291 {
292   pool pool = ml_session_pool (session);
293   struct data *data = (struct data *) vp;
294
295   data->frames_tr_win = new_ml_window (session, pool);
296   data->frames_tr_text = new_ml_text_label (pool, "Top right frame");
297   ml_window_pack (data->frames_tr_win, data->frames_tr_text);
298 }
299
300 static void
301 br_frame (ml_session session, void *vp)
302 {
303   pool pool = ml_session_pool (session);
304   struct data *data = (struct data *) vp;
305
306   data->frames_br_win = new_ml_window (session, pool);
307   data->frames_br_text = new_ml_text_label (pool, "Bottom right frame");
308   ml_window_pack (data->frames_br_win, data->frames_br_text);
309 }