]> git.sur5r.net Git - glabels/blob - glabels2/src/wdgt-text-entry.c
New document merge API.
[glabels] / glabels2 / src / wdgt-text-entry.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  wdgt_text_entry.c:  text entry widget module
5  *
6  *  Copyright (C) 2001-2002  Jim Evins <evins@snaught.com>.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  */
22
23 #include <config.h>
24
25 #include "wdgt-text-entry.h"
26 #include "merge.h"
27 #include "text-node.h"
28 #include "marshal.h"
29
30 #include "debug.h"
31
32 /*===========================================*/
33 /* Private types                             */
34 /*===========================================*/
35
36 enum {
37         CHANGED,
38         LAST_SIGNAL
39 };
40
41 typedef void (*glWdgtTextEntrySignal) (GObject * object, gpointer data);
42
43 /*===========================================*/
44 /* Private globals                           */
45 /*===========================================*/
46
47 static glHigVBoxClass *parent_class;
48
49 static gint wdgt_text_entry_signals[LAST_SIGNAL] = { 0 };
50
51 /*===========================================*/
52 /* Local function prototypes                 */
53 /*===========================================*/
54
55 static void gl_wdgt_text_entry_class_init    (glWdgtTextEntryClass *class);
56 static void gl_wdgt_text_entry_instance_init (glWdgtTextEntry      *text_entry);
57 static void gl_wdgt_text_entry_finalize      (GObject              *object);
58 static void gl_wdgt_text_entry_construct     (glWdgtTextEntry      *text_entry,
59                                               glMerge              *merge);
60
61 static void changed_cb (glWdgtTextEntry *text_entry);
62 static void insert_cb  (glWdgtTextEntry *text_entry);
63 \f
64 /****************************************************************************/
65 /* Boilerplate Object stuff.                                                */
66 /****************************************************************************/
67 guint
68 gl_wdgt_text_entry_get_type (void)
69 {
70         static guint wdgt_text_entry_type = 0;
71
72         if (!wdgt_text_entry_type) {
73                 GTypeInfo wdgt_text_entry_info = {
74                         sizeof (glWdgtTextEntryClass),
75                         NULL,
76                         NULL,
77                         (GClassInitFunc) gl_wdgt_text_entry_class_init,
78                         NULL,
79                         NULL,
80                         sizeof (glWdgtTextEntry),
81                         0,
82                         (GInstanceInitFunc) gl_wdgt_text_entry_instance_init,
83                 };
84
85                 wdgt_text_entry_type =
86                         g_type_register_static (gl_hig_vbox_get_type (),
87                                                 "glWdgtTextEntry",
88                                                 &wdgt_text_entry_info, 0);
89         }
90
91         return wdgt_text_entry_type;
92 }
93
94 static void
95 gl_wdgt_text_entry_class_init (glWdgtTextEntryClass * class)
96 {
97         GObjectClass *object_class;
98
99         gl_debug (DEBUG_WDGT, "START");
100
101         object_class = (GObjectClass *) class;
102
103         parent_class = g_type_class_peek_parent (class);
104
105         object_class->finalize = gl_wdgt_text_entry_finalize;
106
107         wdgt_text_entry_signals[CHANGED] =
108             g_signal_new ("changed",
109                           G_OBJECT_CLASS_TYPE(object_class),
110                           G_SIGNAL_RUN_LAST,
111                           G_STRUCT_OFFSET (glWdgtTextEntryClass, changed),
112                           NULL, NULL,
113                           gl_marshal_VOID__VOID, G_TYPE_NONE, 0);
114
115         gl_debug (DEBUG_WDGT, "END");
116 }
117
118 static void
119 gl_wdgt_text_entry_instance_init (glWdgtTextEntry *text_entry)
120 {
121         gl_debug (DEBUG_WDGT, "START");
122
123         text_entry->text_entry    = NULL;
124
125         text_entry->key_combo     = NULL;
126         text_entry->key_entry     = NULL;
127         text_entry->insert_button = NULL;
128
129         gl_debug (DEBUG_WDGT, "END");
130 }
131
132 static void
133 gl_wdgt_text_entry_finalize (GObject *object)
134 {
135         glWdgtTextEntry      *text_entry;
136         glWdgtTextEntryClass *class;
137
138         gl_debug (DEBUG_WDGT, "START");
139
140         g_return_if_fail (object != NULL);
141         g_return_if_fail (GL_IS_WDGT_TEXT_ENTRY (object));
142
143         text_entry = GL_WDGT_TEXT_ENTRY (object);
144
145         G_OBJECT_CLASS (parent_class)->finalize (object);
146
147         gl_debug (DEBUG_WDGT, "END");
148 }
149
150 /****************************************************************************/
151 /* New widget.                                                              */
152 /****************************************************************************/
153 GtkWidget *
154 gl_wdgt_text_entry_new (glMerge *merge)
155 {
156         glWdgtTextEntry *text_entry;
157
158         gl_debug (DEBUG_WDGT, "START");
159
160         text_entry = g_object_new (gl_wdgt_text_entry_get_type (), NULL);
161
162         gl_wdgt_text_entry_construct (text_entry, merge);
163
164         gl_debug (DEBUG_WDGT, "END");
165
166         return GTK_WIDGET (text_entry);
167 }
168
169 /*--------------------------------------------------------------------------*/
170 /* PRIVATE.  Construct composite widget.                                    */
171 /*--------------------------------------------------------------------------*/
172 static void
173 gl_wdgt_text_entry_construct (glWdgtTextEntry *text_entry,
174                               glMerge         *merge)
175 {
176         GtkWidget *wvbox, *whbox, *wscroll;
177         GList *keys;
178
179         gl_debug (DEBUG_WDGT, "START");
180
181         wvbox = GTK_WIDGET (text_entry);
182
183         /* ---- Entry line ---- */
184         whbox = gl_hig_hbox_new ();
185         gl_hig_vbox_add_widget (GL_HIG_VBOX(wvbox), whbox);
186
187         /* Text Label */
188         text_entry->edit_label = gtk_label_new (_("Edit text:"));
189         gtk_misc_set_alignment (GTK_MISC (text_entry->edit_label), 0, 0);
190         gl_hig_hbox_add_widget (GL_HIG_HBOX(whbox), text_entry->edit_label);
191
192         /* Actual text entry widget */
193         wscroll = gtk_scrolled_window_new (NULL, NULL);
194         gtk_widget_set_size_request (wscroll, -1, 70);
195         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (wscroll),
196                                         GTK_POLICY_AUTOMATIC,
197                                         GTK_POLICY_AUTOMATIC);
198         gl_hig_hbox_add_widget_justify (GL_HIG_HBOX(whbox), wscroll);
199         text_entry->text_entry = gtk_text_view_new ();
200         text_entry->text_buffer =
201                 gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_entry->text_entry));
202         gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (wscroll),
203                                                text_entry->text_entry);
204         g_signal_connect_swapped (G_OBJECT (text_entry->text_buffer),
205                                   "changed", G_CALLBACK (changed_cb),
206                                   G_OBJECT (text_entry));
207
208         /* ---- Merge field line ---- */
209         whbox = gl_hig_hbox_new ();
210         gl_hig_vbox_add_widget (GL_HIG_VBOX(wvbox), whbox);
211
212         /* Insert merge field label */
213         text_entry->key_label = gtk_label_new (_("Key:"));
214         gtk_misc_set_alignment (GTK_MISC (text_entry->key_label), 0, 0.5);
215         gl_hig_hbox_add_widget (GL_HIG_HBOX(whbox), text_entry->key_label);
216
217         /* Key entry widget */
218         text_entry->key_combo = gtk_combo_new ();
219         keys = gl_merge_get_key_list (merge);
220         if (keys != NULL)
221                 gtk_combo_set_popdown_strings (GTK_COMBO (text_entry->key_combo),
222                                                keys);
223         gl_merge_free_key_list (&keys);
224         text_entry->key_entry = GTK_COMBO (text_entry->key_combo)->entry;
225         gtk_entry_set_editable (GTK_ENTRY (text_entry->key_entry), FALSE);
226         gtk_widget_set_size_request (text_entry->key_combo, 200, -1);
227         gl_hig_hbox_add_widget (GL_HIG_HBOX(whbox), text_entry->key_combo);
228
229         /* Insert button */
230         text_entry->insert_button =
231             gtk_button_new_with_label (_("Insert merge field"));
232         g_signal_connect_swapped (G_OBJECT (text_entry->insert_button),
233                                   "clicked", G_CALLBACK (insert_cb),
234                                   G_OBJECT (text_entry));
235         gl_hig_hbox_add_widget (GL_HIG_HBOX(whbox), text_entry->insert_button);
236
237         gl_debug (DEBUG_WDGT, "END");
238 }
239
240 /*--------------------------------------------------------------------------*/
241 /* PRIVATE.  Callback for when text has changed.                            */
242 /*--------------------------------------------------------------------------*/
243 static void
244 changed_cb (glWdgtTextEntry *text_entry)
245 {
246         gl_debug (DEBUG_WDGT, "START");
247
248         /* Emit our "changed" signal */
249         g_signal_emit (G_OBJECT (text_entry),
250                        wdgt_text_entry_signals[CHANGED], 0);
251
252         gl_debug (DEBUG_WDGT, "END");
253 }
254
255 /*--------------------------------------------------------------------------*/
256 /* PRIVATE.  Callback to insert field into text buffer.                     */
257 /*--------------------------------------------------------------------------*/
258 static void
259 insert_cb (glWdgtTextEntry *text_entry)
260 {
261         GtkTextBuffer *buffer;
262         gchar *key, *field;
263
264         gl_debug (DEBUG_WDGT, "START");
265
266         key =
267             gtk_editable_get_chars (GTK_EDITABLE (text_entry->key_entry), 0,
268                                     -1);
269         field = g_strdup_printf ("FIELD{%s}", key);
270
271         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_entry->text_entry));
272         gtk_text_buffer_insert_at_cursor (buffer, field, -1);
273
274         g_free (field);
275         g_free (key);
276
277
278         gl_debug (DEBUG_WDGT, "END");
279 }
280
281 /****************************************************************************/
282 /* Set new field definitions.                                               */
283 /****************************************************************************/
284 void
285 gl_wdgt_text_entry_set_field_defs (glWdgtTextEntry *text_entry,
286                                    glMerge         *merge)
287 {
288         GList *keys;
289
290         keys = gl_merge_get_key_list (merge);
291         if ( keys != NULL ) {
292                 gtk_combo_set_popdown_strings (GTK_COMBO (text_entry->key_combo),
293                                                keys);
294                 gl_merge_free_key_list (&keys);
295         } else {
296                 keys = g_list_append (keys, "");
297                 gtk_combo_set_popdown_strings (GTK_COMBO (text_entry->key_combo),
298                                                keys);
299                 g_list_free (keys);
300         }
301 }
302
303 /****************************************************************************/
304 /* Get widget data.                                                         */
305 /****************************************************************************/
306 GList *
307 gl_wdgt_text_entry_get_text (glWdgtTextEntry *text_entry)
308 {
309         GtkTextBuffer *buffer;
310         gchar *text;
311         GList *lines;
312         GtkTextIter start, end;
313
314         gl_debug (DEBUG_WDGT, "START");
315
316         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_entry->text_entry));
317
318         gtk_text_buffer_get_bounds (buffer, &start, &end);
319
320         text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
321
322         lines = gl_text_node_lines_new_from_text (text);
323
324         g_free (text);
325
326         gl_debug (DEBUG_WDGT, "END");
327
328         return lines;
329 }
330
331 /****************************************************************************/
332 /* Set widget data.                                                         */
333 /****************************************************************************/
334 void
335 gl_wdgt_text_entry_set_text (glWdgtTextEntry *text_entry,
336                              gboolean         merge_flag,
337                              GList           *lines)
338 {
339         GtkTextBuffer *buffer;
340         gchar *text;
341
342         gl_debug (DEBUG_WDGT, "START");
343
344         gtk_widget_set_sensitive (text_entry->key_combo, merge_flag);
345         gtk_widget_set_sensitive (text_entry->insert_button, merge_flag);
346
347         text = gl_text_node_lines_expand (lines, NULL);
348
349         g_signal_handlers_block_by_func (G_OBJECT(text_entry->text_buffer),
350                                          changed_cb, text_entry);
351         gtk_text_buffer_set_text (text_entry->text_buffer, text, -1);
352         g_signal_handlers_unblock_by_func (G_OBJECT(text_entry->text_buffer),
353                                            changed_cb, text_entry);
354
355         gl_debug (DEBUG_WDGT, "END");
356 }
357
358 /*****************************************************************************/
359 /* Set size group for internal labels                                        */
360 /*****************************************************************************/
361 void
362 gl_wdgt_text_entry_set_label_size_group (glWdgtTextEntry *text_entry,
363                                          GtkSizeGroup    *label_size_group)
364 {
365         gtk_size_group_add_widget (label_size_group, text_entry->edit_label);
366         gtk_size_group_add_widget (label_size_group, text_entry->key_label);
367 }
368