source: trunk/third/gtkhtml3/src/htmlselect.c @ 19539

Revision 19539, 11.5 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19538, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*  This file is part of the GtkHTML library.
3
4    Copyright (C) 2000 Jonas Borgström <jonas_b@bitsmart.com>.
5    Copyright (C) 2000, 2001, 2002 Ximian, Inc.
6
7    This library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Library General Public
9    License as published by the Free Software Foundation; either
10    version 2 of the License, or (at your option) any later version.
11
12    This library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Library General Public License for more details.
16
17    You should have received a copy of the GNU Library General Public License
18    along with this library; see the file COPYING.LIB.  If not, write to
19    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.
21*/
22
23#include <config.h>
24
25/*
26  FIXME
27  we need to call deprecated GtkList, which is ised in non deprecated GtkCombo
28  remove following preprocessor hackery once gtk+ is fixed
29 */
30
31#ifdef GTK_DISABLE_DEPRECATED
32#undef GTK_DISABLE_DEPRECATED
33#include <gtk/gtklist.h>
34#define GTK_DISABLE_DEPRECATED 1
35#else
36#include <gtk/gtklist.h>
37#endif
38
39#include <gtk/gtkcombo.h>
40#include <gtk/gtkentry.h>
41#include <gtk/gtkscrolledwindow.h>
42#include <gtk/gtktreeview.h>
43#include <gtk/gtktreeselection.h>
44#include <gtk/gtktreemodel.h>
45#include <gtk/gtkcellrenderertext.h>
46#include "htmlselect.h"
47#include <string.h>
48
49HTMLSelectClass html_select_class;
50static HTMLEmbeddedClass *parent_class = NULL;
51
52static void
53free_strings (gpointer o, gpointer data)
54{
55        g_free (o);
56}
57
58static void
59destroy (HTMLObject *o)
60{
61        HTMLSelect *select;
62
63        select = HTML_SELECT (o);
64
65        if (select->default_selection)
66                g_list_free (select->default_selection);
67
68        if (select->values) {
69
70                g_list_foreach (select->values, free_strings, NULL);
71                g_list_free (select->values);
72        }
73
74        if (select->strings) {
75
76                g_list_foreach (select->strings, free_strings, NULL);
77                g_list_free (select->strings);
78        }
79
80        HTML_OBJECT_CLASS (parent_class)->destroy (o);
81}
82
83static void
84copy (HTMLObject *self,
85      HTMLObject *dest)
86{
87        /* FIXME TODO */
88        HTMLSelect *s = HTML_SELECT (self);
89        HTMLSelect *d = HTML_SELECT (dest);
90
91        (* HTML_OBJECT_CLASS (parent_class)->copy) (self,dest);
92
93       
94        /* FIXME g_warning ("HTMLSelect::copy() is not complete."); */
95        d->size =    s->size;
96        d->multi =   s->multi;
97       
98        d->values = NULL;
99        d->strings = NULL;
100        d->default_selection = NULL;
101
102        d->view = NULL;
103}
104
105static void
106draw (HTMLObject *o,
107      HTMLPainter *p,
108      gint x, gint y,
109      gint width, gint height,
110      gint tx, gint ty)
111{
112        HTMLSelect *select = HTML_SELECT (o);
113
114        if (select->needs_update) {
115                if (GTK_IS_COMBO (HTML_EMBEDDED (select)->widget)) {
116                        gtk_combo_set_popdown_strings (GTK_COMBO (HTML_EMBEDDED (o)->widget), select->strings);
117                        gtk_list_select_item (GTK_LIST (GTK_COMBO (HTML_EMBEDDED (o)->widget)->list), select->default_selected);
118                }
119        }
120
121        select->needs_update = FALSE;   
122
123        (* HTML_OBJECT_CLASS (parent_class)->draw) (o, p, x, y, width, height, tx, ty);
124}
125
126static void
127select_row (GtkTreeSelection *selection, GtkTreeModel *model, gint r)
128{
129        GtkTreeIter iter;
130        gchar *row;
131
132        row = g_strdup_printf ("%d", r);
133
134        if (gtk_tree_model_get_iter_from_string (model, &iter, row))
135                gtk_tree_selection_select_iter (selection, &iter);
136        g_free (row);
137}
138
139static void
140reset (HTMLEmbedded *e)
141{
142        HTMLSelect *s = HTML_SELECT(e);
143        GList *i = s->default_selection;
144        gint row = 0;
145
146        if (s->multi) {
147                GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (s->view));
148
149                gtk_tree_selection_unselect_all (selection);
150               
151                while (i) {
152                        if (i->data)
153                                select_row (selection, GTK_TREE_MODEL (s->store), row);
154
155                        i = i->next;
156                        row++;
157                }               
158        } else if (s->size > 1) {
159                GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (s->view));
160
161                select_row (selection, GTK_TREE_MODEL (s->store), s->default_selected);
162        } else {
163                gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (e->widget)->entry),
164                                    (gchar *) g_list_nth(s->strings, s->default_selected)->data);
165        }
166}
167
168struct EmbeddedSelectionInfo {
169        HTMLEmbedded *e;
170        GString *str;
171};
172
173static void
174add_selected (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
175{
176        struct EmbeddedSelectionInfo *info = data;
177        gchar *value, *ptr;
178
179        gtk_tree_model_get (model, iter, 0, &value, -1);
180
181        if (info->str->len)
182                info->str = g_string_append_c (info->str, '&');
183
184        ptr = html_embedded_encode_string (info->e->name);
185        info->str = g_string_append (info->str, ptr);
186        g_free (ptr);
187                                       
188        info->str = g_string_append_c (info->str, '=');
189                                       
190        ptr = html_embedded_encode_string (value);
191        info->str = g_string_append (info->str, ptr);
192        g_free (ptr);
193}
194
195static gchar *
196encode (HTMLEmbedded *e)
197{
198        HTMLSelect *s = HTML_SELECT(e);
199        GList *i;
200        GString *encoding = g_string_new ("");
201        const gchar *txt;
202        gchar *ptr;
203
204        if(strlen (e->name)) {
205                if (s->size > 1) {
206                        struct EmbeddedSelectionInfo info;
207
208                        info.e = e;
209                        info.str = encoding;
210                        gtk_tree_selection_selected_foreach (gtk_tree_view_get_selection (GTK_TREE_VIEW (s->view)),
211                                                             add_selected, &info);
212                        encoding = info.str;
213                } else {
214                        gint item;
215
216                        ptr = html_embedded_encode_string (e->name);
217                        encoding = g_string_assign (encoding, ptr);
218                        g_free (ptr);
219                        encoding = g_string_append_c (encoding, '=');
220
221                        txt = gtk_entry_get_text (GTK_ENTRY(GTK_COMBO(e->widget)->entry));
222                        i = s->strings;
223                        item = 0;
224
225                        while (i) {
226
227                                if (strcmp(txt, (gchar *)i->data) == 0) {
228
229                                        ptr = html_embedded_encode_string ((gchar *)g_list_nth (s->values, item)->data);
230                                        encoding = g_string_append (encoding, ptr);
231                                        g_free (ptr);
232                                       
233                                        break;
234                                }
235                                i = i->next;
236                                item++;
237                        }
238
239                }
240        }
241        ptr = encoding->str;
242        g_string_free(encoding, FALSE);
243       
244        return ptr;
245}
246
247void
248html_select_type_init (void)
249{
250        html_select_class_init (&html_select_class, HTML_TYPE_SELECT, sizeof (HTMLSelect));
251}
252
253void
254html_select_class_init (HTMLSelectClass *klass,
255                        HTMLType type,
256                        guint object_size)
257{
258        HTMLEmbeddedClass *element_class;
259        HTMLObjectClass *object_class;
260
261        element_class = HTML_EMBEDDED_CLASS (klass);
262        object_class = HTML_OBJECT_CLASS (klass);
263
264        html_embedded_class_init (element_class, type, object_size);
265
266        /* HTMLEmbedded methods.   */
267        element_class->reset = reset;
268        element_class->encode = encode;
269
270        /* HTMLObject methods.   */
271        object_class->destroy = destroy;
272        object_class->copy = copy;
273        object_class->draw = draw;
274
275        parent_class = &html_embedded_class;
276}
277
278void
279html_select_init (HTMLSelect *select,
280                      HTMLSelectClass *klass,
281                      GtkWidget *parent,
282                      gchar *name,
283                      gint size,
284                      gboolean multi)
285{
286
287        HTMLEmbedded *element;
288        HTMLObject *object;
289        GtkWidget *widget;
290
291        element = HTML_EMBEDDED (select);
292        object = HTML_OBJECT (select);
293
294        html_embedded_init (element, HTML_EMBEDDED_CLASS (klass),
295                           parent, name, NULL);
296
297        if (size > 1 || multi) {
298                GtkRequisition req;
299                GtkTreeIter iter;
300
301                select->store = gtk_list_store_new (1, G_TYPE_STRING);
302                select->view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (select->store));
303
304                gtk_tree_view_append_column (GTK_TREE_VIEW (select->view),
305                                             gtk_tree_view_column_new_with_attributes ("Labels",
306                                                                                       gtk_cell_renderer_text_new (),
307                                                                                       "text", 0, NULL));
308
309                if (multi)
310                        gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (select->view)),
311                                                     GTK_SELECTION_MULTIPLE);
312
313                widget = gtk_scrolled_window_new (NULL, NULL);
314                gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
315                gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
316
317                gtk_container_add (GTK_CONTAINER (widget), select->view);
318                gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (select->view), FALSE);
319                gtk_widget_show_all (widget);
320
321                gtk_list_store_append (select->store, &iter);
322                gtk_list_store_set (select->store, &iter, 0, "height", -1);
323                gtk_widget_size_request (select->view, &req);
324                gtk_widget_set_size_request (select->view, 120, req.height * size);
325                gtk_list_store_remove (select->store, &iter);
326        } else {
327                widget = gtk_combo_new ();
328                gtk_editable_set_editable (GTK_EDITABLE (GTK_COMBO(widget)->entry), FALSE);
329                gtk_widget_set_size_request ( GTK_WIDGET (widget), 120, -1);
330        }
331        html_embedded_set_widget (element, widget);
332
333        select->size = size;
334        select->multi = multi;
335        select->default_selected = 0;
336        select->values = NULL;
337        select->strings = NULL;
338        select->default_selection = NULL;
339        select->needs_update = TRUE;
340}
341
342HTMLObject *
343html_select_new (GtkWidget *parent,
344                     gchar *name,
345                     gint size,
346                     gboolean multi)
347{
348        HTMLSelect *ti;
349
350        ti = g_new0 (HTMLSelect, 1);
351        html_select_init (ti, &html_select_class,
352                              parent, name, size, multi);
353
354        return HTML_OBJECT (ti);
355}
356
357void
358html_select_add_option (HTMLSelect *select, gchar *value, gboolean selected)
359{
360        if(select->size > 1 || select->multi) {
361                GtkTreeIter iter;
362
363                gtk_list_store_append (select->store, &iter);
364                gtk_list_store_set (select->store, &iter, 0, value, -1);
365
366                if(selected) {
367
368                        select->default_selected = g_list_length (select->values) - 1;
369                        gtk_tree_selection_select_iter (gtk_tree_view_get_selection (GTK_TREE_VIEW (select->view)), &iter);
370                }
371        } else {
372                select->strings = g_list_append (select->strings, g_strdup (""));
373
374                select->needs_update = TRUE;
375                if (selected || g_list_length (select->strings) == 1)
376                        select->default_selected = g_list_length (select->strings) - 1;
377        }
378
379        select->values = g_list_append (select->values, g_strdup (value));
380
381        if(select->multi)
382                select->default_selection = g_list_append (select->default_selection, GINT_TO_POINTER(selected));
383}
384
385static char *
386longest_string (HTMLSelect *s)
387{
388        GList *i = s->strings;
389        gint max = 0;
390        gchar *str = NULL;
391
392        while (i) {
393                if (strlen(i->data) > max) {
394                        max = strlen (i->data);
395                        str = i->data;
396                }
397                i = i->next;
398        }
399        return str;
400}
401
402void
403html_select_set_text (HTMLSelect *select, gchar *text)
404{
405        GtkWidget *w = GTK_WIDGET (HTML_EMBEDDED (select)->widget);
406        gint item;
407
408        if (select->size > 1 || select->multi) {
409                GtkRequisition req;
410                GtkTreeIter iter;
411                gchar *row;
412                item = g_list_length (select->values) - 1;
413
414                row = g_strdup_printf ("%d", item);
415                gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (select->store), &iter, row);
416                gtk_list_store_set (select->store, &iter, 0, text, -1);
417                g_free (row);
418
419                gtk_widget_size_request (GTK_WIDGET (select->view), &req);
420                HTML_OBJECT (select)->width = req.width;
421
422                /* Add width of scrollbar */
423
424                if ((item + 1) > select->size && GTK_SCROLLED_WINDOW(w)->vscrollbar) {
425                        GtkRequisition req;
426
427                        gtk_widget_size_request (GTK_SCROLLED_WINDOW(w)->vscrollbar, &req);
428                        HTML_OBJECT (select)->width += req.width + 8;
429                }
430
431                gtk_widget_set_size_request (w, HTML_OBJECT(select)->width, -1);
432        } else {
433                w = HTML_EMBEDDED (select)->widget;
434                item = g_list_length (select->strings) - 1;
435
436                if (select->strings) {
437                        char *longest;
438                        GList *last = g_list_last (select->strings);
439                       
440                        g_free (last->data);
441                        last->data = g_strdup (text);
442
443                        select->needs_update = TRUE;
444                        gtk_entry_set_text (GTK_ENTRY(GTK_COMBO(w)->entry),
445                                            g_list_nth(select->strings, select->default_selected)->data);
446
447                        longest = longest_string (select);
448                        if (longest)
449                                gtk_entry_set_width_chars (GTK_ENTRY(GTK_COMBO(w)->entry),
450                                                           strlen (longest));
451                }
452
453                gtk_widget_set_size_request (w, -1, -1);
454        }
455
456        if (item >= 0 && g_list_nth (select->values, item)->data == NULL)
457                g_list_nth (select->values, item)->data = g_strdup(text);
458}
459
460
Note: See TracBrowser for help on using the repository browser.