Add to git.
[monolith.git] / src / ml_button.c
1 /* Monolith button 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_button.c,v 1.8 2003/01/11 16:39:09 rich Exp $
19  */
20
21 #include "config.h"
22
23 #ifdef HAVE_STRING_H
24 #include <string.h>
25 #endif
26
27 #include <pool.h>
28 #include <pstring.h>
29 #include <pthr_iolib.h>
30
31 #include "monolith.h"
32 #include "ml_widget.h"
33 #include "ml_smarttext.h"
34 #include "ml_button.h"
35
36 static void repaint (void *, ml_session, const char *, io_handle);
37 static struct ml_widget_property properties[];
38
39 struct ml_widget_operations button_ops =
40   {
41     repaint: repaint,
42     properties: properties,
43   };
44
45 struct ml_button
46 {
47   struct ml_widget_operations *ops;
48   pool pool;                    /* Pool for allocations. */
49   const char *text;             /* HTML printed for the button. */
50   const char *title;            /* Tool tip (NULL for none). */
51   const char *clazz;            /* Class (NULL for default). */
52   const char *style;            /* Style: default, key, compact, link */
53   const char *colour;           /* Button colour (NULL for default). */
54   const char *action_id;        /* Action. */
55   const char *target;           /* Button target (NULL for no popup). */
56   int popup_w, popup_h;         /* Popup window size. */
57 };
58
59 static struct ml_widget_property properties[] =
60   {
61     { name: "text",
62       offset: ml_offsetof (struct ml_button, text),
63       type: ML_PROP_STRING },
64     { name: "title",
65       offset: ml_offsetof (struct ml_button, title),
66       type: ML_PROP_STRING },
67     { name: "button.style",
68       offset: ml_offsetof (struct ml_button, style),
69       type: ML_PROP_STRING },
70     { name: "color",
71       offset: ml_offsetof (struct ml_button, colour),
72       type: ML_PROP_STRING },
73     { name: "class",
74       offset: ml_offsetof (struct ml_button, clazz),
75       type: ML_PROP_STRING },
76     { 0 }
77   };
78
79 ml_button
80 new_ml_button (pool pool, const char *text)
81 {
82   ml_button w = pmalloc (pool, sizeof *w);
83
84   w->ops = &button_ops;
85   w->pool = pool;
86   w->text = text;
87   w->title = 0;
88   w->clazz = 0;
89   w->style = 0;
90   w->colour = 0;
91   w->action_id = 0;
92   w->target = 0;
93   w->popup_w = w->popup_h = 0;
94
95   return w;
96 }
97
98 void
99 ml_button_set_callback (ml_button w,
100                         void (*fn)(ml_session, void *),
101                         ml_session session, void *data)
102 {
103   if (w->action_id)
104     ml_unregister_action (session, w->action_id);
105   w->action_id = 0;
106
107   if (fn)
108     w->action_id = ml_register_action (session, fn, data);
109 }
110
111 void
112 ml_button_set_popup (ml_button w, const char *name)
113 {
114   w->target = name;
115 }
116
117 void
118 ml_button_set_popup_size (ml_button w, int width, int height)
119 {
120   w->popup_w = width;
121   w->popup_h = height;
122 }
123
124 static inline const char *
125 get_class (ml_button w)
126 {
127   if (!w->clazz)
128     {
129       if (w->style == 0 || strcmp (w->style, "default") == 0)
130         return "ml_button";
131       else if (strcmp (w->style, "key") == 0)
132         return "ml_button_key";
133       else if (strcmp (w->style, "compact") == 0)
134         return "ml_button_compact";
135       else if (strcmp (w->style, "link") == 0)
136         return "ml_button_link";
137       else
138         abort ();               /* Unknown button.style for button. */
139     }
140
141   return w->clazz;
142 }
143
144 static void
145 repaint (void *vw, ml_session session, const char *windowid, io_handle io)
146 {
147   ml_button w = (ml_button) vw;
148
149   if (w->text)
150     {
151       const char *clazz = get_class (w);
152
153       if (w->action_id)
154         {
155           pool tmp = new_subpool (w->pool);
156
157           /* XXX Link should not contain ml_window parameter if w->target
158            * is set.
159            */
160           const char *link =
161             psprintf (tmp, "%s?ml_action=%s&ml_window=%s",
162                       ml_session_script_name (session),
163                       w->action_id,
164                       windowid);
165
166           io_fprintf (io, "<a class=\"%s\" href=\"%s\"", clazz, link);
167
168           if (w->title)
169             {
170               io_fputs (" title=\"", io);
171               ml_plaintext_print (io, w->title);
172               io_fputc ('"', io);
173             }
174
175           if (w->colour)
176             io_fprintf (io, " style=\"color: %s\"", w->colour);
177
178           if (w->target)
179             {
180               io_fprintf (io, " target=\"%s\"", w->target);
181               if (w->popup_w != 0 && w->popup_h != 0)
182                 {
183                   io_fprintf (io, " onclick=\"open ('%s', '%s', "
184                               "'width=%d,height=%d,scrollbars=1'); "
185                               "return false;\"",
186                               link, w->target, w->popup_w, w->popup_h);
187                 }
188             }
189
190           if (!w->style || strcmp (w->style, "compact") != 0)
191             io_fprintf (io, ">%s</a>", w->text);
192           else
193             io_fprintf (io, ">[%s]</a>", w->text);
194
195           delete_pool (tmp);
196         }
197       else
198         io_fprintf (io, "<span class=\"%s\">%s</span>", clazz, w->text);
199     }
200 }