~ubuntu-branches/ubuntu/utopic/glame/utopic

« back to all changes in this revision

Viewing changes to src/gui/swapfilegui.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Kobras
  • Date: 2002-04-09 17:14:12 UTC
  • Revision ID: james.westby@ubuntu.com-20020409171412-jzpnov7mbz2w6zsr
Tags: upstream-0.6.2
ImportĀ upstreamĀ versionĀ 0.6.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * swapfilegui.c
 
3
 *
 
4
 * $Id: swapfilegui.c,v 1.70.2.5 2002/01/16 21:08:02 richi Exp $
 
5
 * 
 
6
 * Copyright (C) 2001 Richard Guenther, Johannes Hirche, Alexander Ehlert
 
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
 
 
24
#ifdef HAVE_CONFIG_H
 
25
#include <config.h>
 
26
#endif
 
27
 
 
28
#include <stdio.h>
 
29
#include <errno.h>
 
30
#include <gnome.h>
 
31
#include <xmlmemory.h>
 
32
#include <parser.h>
 
33
#include <libintl.h>
 
34
#include "glame_types.h"
 
35
#include "swapfile.h"
 
36
#include "gltreeitem.h"
 
37
#include "waveeditgui.h"
 
38
#include "filter.h"
 
39
#include "util/glame_gui_utils.h"
 
40
#include "clipboard.h"
 
41
#include "timeline/timeline.h"
 
42
#include "glscript.h"
 
43
#include "network_utils.h"
 
44
#include "importexport.h"
 
45
#include "swapfilegui.h"
 
46
 
 
47
 
 
48
/* GUI is single threaded, so we may have some global state.
 
49
 */
 
50
 
 
51
static SwapfileGui *active_swapfilegui = NULL;
 
52
 
 
53
 
 
54
/* Forward declarations. */
 
55
static int click_cb(GtkWidget *item, GdkEventButton *event,
 
56
                    gpointer data);
 
57
static void copyselected_cb(GtkWidget *menu, GlameTreeItem *item);
 
58
static void linkselected_cb(GtkWidget *menu, GlameTreeItem *item);
 
59
static void mergeparent_cb(GtkWidget *menu, GlameTreeItem *item);
 
60
static void flatten_cb(GtkWidget *menu, GlameTreeItem *item);
 
61
static void addgroup_cb(GtkWidget *menu, GlameTreeItem *item);
 
62
static void addclipboard_cb(GtkWidget *menu, GlameTreeItem *item);
 
63
static void addfile_cb(GtkWidget *menu, GlameTreeItem *item);
 
64
static void addstereo_cb(GtkWidget *menu, GlameTreeItem *item);
 
65
static void edit_cb(GtkWidget *menu, GlameTreeItem *item);
 
66
static void timeline_cb(GtkWidget *menu, GlameTreeItem *item);
 
67
static void import_cb(GtkWidget *menu, GlameTreeItem *item);
 
68
static void export_cb(GtkWidget *menu, GlameTreeItem *item);
 
69
static void delete_cb(GtkWidget *menu, GlameTreeItem *item);
 
70
static void handle_grp(glsig_handler_t *handler, long sig, va_list va);
 
71
static void group_cb(GtkWidget *menu, GlameTreeItem *item);
 
72
 
 
73
static GnomeUIInfo dummy1_menu[] = {
 
74
        GNOMEUIINFO_END
 
75
};
 
76
static GnomeUIInfo dummy2_menu[] = {
 
77
        GNOMEUIINFO_END
 
78
};
 
79
 
 
80
static GnomeUIInfo group_menu_data[] = {
 
81
        GNOMEUIINFO_SEPARATOR,
 
82
        GNOMEUIINFO_ITEM(N_("Edit"), NULL, edit_cb, NULL),
 
83
        GNOMEUIINFO_ITEM(N_("Timeline"), NULL, timeline_cb, NULL),
 
84
        GNOMEUIINFO_SEPARATOR,
 
85
        GNOMEUIINFO_ITEM(N_("Delete"), NULL, delete_cb, NULL),
 
86
        GNOMEUIINFO_SEPARATOR,
 
87
        GNOMEUIINFO_ITEM(N_("Add group"), NULL, addgroup_cb, NULL),
 
88
        GNOMEUIINFO_ITEM(N_("Add clipboard"), NULL, addclipboard_cb, NULL),
 
89
        GNOMEUIINFO_ITEM(N_("Add mono wave"), NULL, addfile_cb, NULL),
 
90
        GNOMEUIINFO_ITEM(N_("Add stereo wave"), NULL, addstereo_cb, NULL),
 
91
        GNOMEUIINFO_ITEM(N_("Link selected"), NULL, linkselected_cb, NULL),
 
92
        GNOMEUIINFO_ITEM(N_("Copy selected"), NULL, copyselected_cb, NULL),
 
93
        GNOMEUIINFO_SEPARATOR,
 
94
        GNOMEUIINFO_ITEM(N_("Merge with parent"), NULL, mergeparent_cb, NULL),
 
95
        GNOMEUIINFO_ITEM(N_("Flatten"), NULL, flatten_cb, NULL),
 
96
        GNOMEUIINFO_SEPARATOR,
 
97
        GNOMEUIINFO_SUBTREE(N_("Apply operation"), dummy1_menu),
 
98
        GNOMEUIINFO_SEPARATOR,
 
99
        GNOMEUIINFO_ITEM(N_("Import..."), NULL, import_cb, NULL),
 
100
        GNOMEUIINFO_ITEM(N_("Export..."), NULL, export_cb, NULL),
 
101
        GNOMEUIINFO_SEPARATOR,
 
102
        GNOMEUIINFO_END
 
103
};
 
104
#define GROUP_MENU_ADDGROUP_INDEX 6
 
105
#define GROUP_MENU_ADDCLIPBOARD_INDEX 7
 
106
#define GROUP_MENU_ADDMONO_INDEX 8
 
107
#define GROUP_MENU_ADDSTEREO_INDEX 9
 
108
#define GROUP_MENU_APPLYOP_INDEX 16
 
109
#define GROUP_MENU_IMPORT_INDEX 18
 
110
static GnomeUIInfo file_menu_data[] = {
 
111
        GNOMEUIINFO_SEPARATOR,
 
112
        GNOMEUIINFO_ITEM(N_("Edit"), NULL, edit_cb, NULL),
 
113
        GNOMEUIINFO_SEPARATOR,
 
114
        GNOMEUIINFO_ITEM(N_("Delete"), NULL, delete_cb, NULL),
 
115
        GNOMEUIINFO_SEPARATOR,
 
116
        GNOMEUIINFO_ITEM(N_("Group"), NULL, group_cb, NULL),
 
117
        GNOMEUIINFO_SEPARATOR,
 
118
        GNOMEUIINFO_SUBTREE(N_("Apply operation"), dummy2_menu),
 
119
        GNOMEUIINFO_SEPARATOR,
 
120
        GNOMEUIINFO_ITEM(N_("Export..."), NULL, export_cb, NULL),
 
121
        GNOMEUIINFO_SEPARATOR,
 
122
        GNOMEUIINFO_END
 
123
};
 
124
#define FILE_MENU_APPLYOP_INDEX 7
 
125
 
 
126
 
 
127
static void edit_tree_label_cb(GtkEntry* entry, GlameTreeItem* item)
 
128
{
 
129
        char *text = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
 
130
        /* Unlock accelerators. HACK(?) */
 
131
        gtk_signal_handler_unblock(GTK_OBJECT(active_swapfilegui->app),
 
132
                                   active_swapfilegui->accel_handler);
 
133
        gtk_container_remove(GTK_CONTAINER(item), GTK_WIDGET(entry));
 
134
        gtk_widget_destroy(GTK_WIDGET(entry));
 
135
        if (text) {
 
136
                gpsm_item_set_label(item->item, text);
 
137
                g_free(text);
 
138
        }
 
139
}
 
140
void edit_tree_label(GlameTreeItem * item)
 
141
{
 
142
        GtkWidget *label;
 
143
        GtkWidget *entry;
 
144
 
 
145
        /* Deselect item and replace GtkLabel with GtkEntry. */
 
146
        gtk_tree_item_deselect(GTK_TREE_ITEM(item));
 
147
        label = GTK_WIDGET((g_list_first(gtk_container_children(GTK_CONTAINER(item))))->data);
 
148
        gtk_container_remove(GTK_CONTAINER(item), label);
 
149
        entry = gtk_entry_new();
 
150
        gtk_entry_set_text(GTK_ENTRY(entry), gpsm_item_label(item->item));
 
151
        gtk_signal_connect(GTK_OBJECT(entry), "activate",
 
152
                           (GtkSignalFunc)edit_tree_label_cb, item);
 
153
        gtk_widget_show(entry);
 
154
        gtk_container_add(GTK_CONTAINER(item), entry);
 
155
        gtk_container_check_resize(GTK_CONTAINER(item));
 
156
        gtk_widget_grab_focus(GTK_WIDGET(entry));
 
157
        /* Block accelerators. HACK(?) */
 
158
        gtk_signal_handler_block(GTK_OBJECT(active_swapfilegui->app),
 
159
                                 active_swapfilegui->accel_handler);
 
160
}
 
161
 
 
162
static void deselect_all(SwapfileGui *gui)
 
163
{
 
164
        GList *selected;
 
165
 
 
166
        if (!gui)
 
167
                return;
 
168
 
 
169
        while ((selected = GTK_TREE_SELECTION(gui->tree))) {
 
170
                GlameTreeItem *i = GLAME_TREE_ITEM(selected->data);
 
171
                gtk_tree_unselect_child(i->tree, GTK_WIDGET(i));
 
172
        }
 
173
}
 
174
 
 
175
/* Menu event - Apply operation. */
 
176
static void applyop_cb(GtkWidget *bla, plugin_t *plugin)
 
177
{
 
178
        gpsm_item_t *item = active_swapfilegui->active_item->item;
 
179
        int (*operation)(gpsm_item_t *, long, long);
 
180
 
 
181
        if (!(operation = plugin_query(plugin, PLUGIN_GPSMOP))) {
 
182
                DPRINTF("No such operation %s\n", plugin_name(plugin));
 
183
                return;
 
184
        }
 
185
        DPRINTF("Executing operation %s on %s [%li, %li[\n",
 
186
                plugin_name(plugin), gpsm_item_label(item),
 
187
                (long)0, (long)gpsm_item_hsize(item));
 
188
 
 
189
        if (operation(item, 0, gpsm_item_hsize(item)) == -1)
 
190
                gnome_dialog_run_and_close(GNOME_DIALOG(
 
191
                        gnome_error_dialog(_("Error executing"))));
 
192
 
 
193
        DPRINTF("%s finished.\n", plugin_name(plugin));
 
194
        deselect_all(active_swapfilegui);
 
195
}
 
196
 
 
197
/* Somehow only select "operations" */
 
198
static int choose_ops(plugin_t *plugin)
 
199
{
 
200
        /* Only use filters, hide Import */
 
201
        if (!plugin_query(plugin, PLUGIN_GPSMOP)
 
202
            || strcmp(plugin_name(plugin), "import") == 0)
 
203
                return 0;
 
204
 
 
205
        return 1;
 
206
}
 
207
 
 
208
static int click_cb(GtkWidget *item, GdkEventButton *event,
 
209
                    gpointer data)
 
210
{
 
211
        GlameTreeItem *i = GLAME_TREE_ITEM(item);
 
212
        GtkWidget *menu, *op_menu;
 
213
 
 
214
        if (event->button == 1
 
215
            && event->type == GDK_2BUTTON_PRESS) {
 
216
                edit_tree_label(i);
 
217
                return TRUE;
 
218
        }
 
219
 
 
220
        if (event->button != 3
 
221
            || event->type != GDK_BUTTON_PRESS)
 
222
                return FALSE;
 
223
 
 
224
        if (GPSM_ITEM_IS_SWFILE(i->item)) {
 
225
                menu = gnome_popup_menu_new(file_menu_data);
 
226
                op_menu = GTK_WIDGET(glame_gui_build_plugin_menu(choose_ops, applyop_cb));
 
227
                gtk_widget_show(GTK_WIDGET(op_menu));
 
228
                gtk_menu_item_set_submenu(GTK_MENU_ITEM(file_menu_data[FILE_MENU_APPLYOP_INDEX].widget), GTK_WIDGET(op_menu));
 
229
 
 
230
        } else if (GPSM_ITEM_IS_GRP(i->item)) {
 
231
                menu = gnome_popup_menu_new(group_menu_data);
 
232
                op_menu = GTK_WIDGET(glame_gui_build_plugin_menu(choose_ops, applyop_cb));
 
233
                gtk_widget_show(GTK_WIDGET(op_menu));
 
234
                gtk_menu_item_set_submenu(GTK_MENU_ITEM(group_menu_data[GROUP_MENU_APPLYOP_INDEX].widget), GTK_WIDGET(op_menu));
 
235
                gtk_widget_set_sensitive(group_menu_data[GROUP_MENU_ADDGROUP_INDEX].widget,
 
236
                                         gpsm_grp_is_vbox((gpsm_grp_t *)i->item) ? TRUE : FALSE);
 
237
                gtk_widget_set_sensitive(group_menu_data[GROUP_MENU_ADDCLIPBOARD_INDEX].widget,
 
238
                                         gpsm_grp_is_vbox((gpsm_grp_t *)i->item) ? TRUE : FALSE);
 
239
                gtk_widget_set_sensitive(group_menu_data[GROUP_MENU_ADDMONO_INDEX].widget,
 
240
                                         gpsm_grp_is_vbox((gpsm_grp_t *)i->item) ? TRUE : FALSE);
 
241
                gtk_widget_set_sensitive(group_menu_data[GROUP_MENU_ADDSTEREO_INDEX].widget,
 
242
                                         gpsm_grp_is_vbox((gpsm_grp_t *)i->item) ? TRUE : FALSE);
 
243
                gtk_widget_set_sensitive(group_menu_data[GROUP_MENU_IMPORT_INDEX].widget,
 
244
                                         gpsm_grp_is_vbox((gpsm_grp_t *)i->item) || gpsm_grp_is_hbox((gpsm_grp_t *)i->item) ? TRUE : FALSE);
 
245
        } else
 
246
                return TRUE;
 
247
 
 
248
        gnome_popup_menu_do_popup(menu, NULL, NULL, event, i);
 
249
        return TRUE;
 
250
}
 
251
 
 
252
/* Copy (COW, new swapfiles) all selected items as childs of the
 
253
 * current item. */
 
254
static void copyselected_cb(GtkWidget *menu, GlameTreeItem *item)
 
255
{
 
256
        GList *selected;
 
257
 
 
258
        if (!GPSM_ITEM_IS_GRP(item->item))
 
259
                return;
 
260
 
 
261
        selected = GTK_TREE_SELECTION(glame_tree_item_parent(item));
 
262
        while (selected) {
 
263
                GlameTreeItem *i = GLAME_TREE_ITEM(selected->data);
 
264
                gpsm_item_t *copy;
 
265
 
 
266
                /* Dont allow copying myself into myself. */
 
267
                if (item->item == i->item)
 
268
                        goto next;
 
269
 
 
270
                if (GPSM_ITEM_IS_SWFILE(i->item))
 
271
                        copy = (gpsm_item_t *)gpsm_swfile_cow((gpsm_swfile_t *)i->item);
 
272
                else if (GPSM_ITEM_IS_GRP(i->item))
 
273
                        copy = (gpsm_item_t *)gpsm_grp_cow((gpsm_grp_t *)i->item);
 
274
                else
 
275
                        goto next;
 
276
                if (gpsm_grp_is_vbox((gpsm_grp_t *)item->item))
 
277
                        gpsm_vbox_insert((gpsm_grp_t *)item->item, copy,
 
278
                                         0, gpsm_item_vsize(item->item));
 
279
                else if (gpsm_grp_is_hbox((gpsm_grp_t *)item->item))
 
280
                        gpsm_hbox_insert((gpsm_grp_t *)item->item, copy,
 
281
                                         gpsm_item_hsize(item->item), 0);
 
282
                else {
 
283
                        gnome_dialog_run_and_close(GNOME_DIALOG(
 
284
                                gnome_error_dialog(_("Cannot place item into irregular group"))));
 
285
                        gpsm_item_destroy(copy);
 
286
                        break;
 
287
                }
 
288
 
 
289
        next:
 
290
                selected = g_list_next(selected);
 
291
        }
 
292
 
 
293
        deselect_all(active_swapfilegui);
 
294
}
 
295
 
 
296
/* Link (just new items, same swapfile name) all selected items as
 
297
 * childs of the current item. */
 
298
static void linkselected_cb(GtkWidget *menu, GlameTreeItem *item)
 
299
{
 
300
        GList *selected;
 
301
 
 
302
        if (!GPSM_ITEM_IS_GRP(item->item))
 
303
                return;
 
304
 
 
305
        selected = GTK_TREE_SELECTION(glame_tree_item_parent(item));
 
306
        while (selected) {
 
307
                GlameTreeItem *i = GLAME_TREE_ITEM(selected->data);
 
308
                gpsm_item_t *copy;
 
309
 
 
310
                /* Dont allow copying myself into myself. */
 
311
                if (item->item == i->item)
 
312
                        goto next;
 
313
 
 
314
                if (GPSM_ITEM_IS_SWFILE(i->item))
 
315
                        copy = (gpsm_item_t *)gpsm_swfile_link((gpsm_swfile_t *)i->item);
 
316
                else if (GPSM_ITEM_IS_GRP(i->item))
 
317
                        copy = (gpsm_item_t *)gpsm_grp_link((gpsm_grp_t *)i->item);
 
318
                else
 
319
                        goto next;
 
320
                if (gpsm_grp_is_vbox((gpsm_grp_t *)item->item))
 
321
                        gpsm_vbox_insert((gpsm_grp_t *)item->item, copy,
 
322
                                         0, gpsm_item_vsize(item->item));
 
323
                else if (gpsm_grp_is_hbox((gpsm_grp_t *)item->item))
 
324
                        gpsm_hbox_insert((gpsm_grp_t *)item->item, copy,
 
325
                                         gpsm_item_hsize(item->item), 0);
 
326
                else {
 
327
                        gnome_dialog_run_and_close(GNOME_DIALOG(
 
328
                                gnome_error_dialog(_("Cannot place item into irregular group"))));
 
329
                        gpsm_item_destroy(copy);
 
330
                        break;
 
331
                }
 
332
 
 
333
        next:
 
334
                selected = g_list_next(selected);
 
335
        }
 
336
        deselect_all(active_swapfilegui);
 
337
}
 
338
 
 
339
/* Move all items in this group one level up in the tree
 
340
 * (and delete the group itself). */
 
341
static void mergeparent_cb(GtkWidget *menu, GlameTreeItem *item)
 
342
{
 
343
        struct glame_list_head *dummy;
 
344
        gpsm_grp_t *group, *parent;
 
345
        gpsm_item_t *i;
 
346
        long group_hpos, group_vpos;
 
347
 
 
348
        if (!GPSM_ITEM_IS_GRP(item->item))
 
349
                return;
 
350
        deselect_all(active_swapfilegui);
 
351
 
 
352
        group = (gpsm_grp_t *)item->item;
 
353
        parent = gpsm_item_parent(group);
 
354
        group_hpos = gpsm_item_hposition(group);
 
355
        group_vpos = gpsm_item_vposition(group);
 
356
        gpsm_item_remove((gpsm_item_t *)group);
 
357
 
 
358
        gpsm_grp_safe_foreach_item(group, dummy, i) {
 
359
                long hpos, vpos;
 
360
                hpos = gpsm_item_hposition(i) + group_hpos;
 
361
                vpos = gpsm_item_vposition(i) + group_vpos;
 
362
                gpsm_item_remove(i);
 
363
                gpsm_item_place(parent, i, hpos, vpos);
 
364
        }
 
365
        gpsm_item_destroy((gpsm_item_t *)group);
 
366
}
 
367
 
 
368
/* Flatten the group using gpsm_flatten and replace it with the
 
369
 * flattened group. */
 
370
static void flatten_cb(GtkWidget *menu, GlameTreeItem *item)
 
371
{
 
372
        gpsm_grp_t *group, *parent;
 
373
        gpsm_item_t *old;
 
374
        long hpos, vpos;
 
375
 
 
376
        if (!GPSM_ITEM_IS_GRP(item->item))
 
377
                return;
 
378
        old = item->item;
 
379
 
 
380
        /* Flatten the active group. */
 
381
        if (!(group = gpsm_flatten(old))) {
 
382
                DPRINTF("gpsm_flatten failed!?\n");
 
383
                return;
 
384
        }
 
385
 
 
386
        /* Destroy the active group and insert the flattened one. */
 
387
        parent = gpsm_item_parent(old);
 
388
        hpos = gpsm_item_hposition(old);
 
389
        vpos = gpsm_item_vposition(old);
 
390
        gpsm_item_destroy(old);
 
391
        gpsm_item_place(parent, (gpsm_item_t *)group, hpos, vpos);
 
392
        deselect_all(active_swapfilegui);
 
393
}
 
394
 
 
395
/* Append an empty mono wave (without group) to the current vbox. */
 
396
static void addfile_cb(GtkWidget *menu, GlameTreeItem *item)
 
397
{
 
398
        gpsm_swfile_t *swfile;
 
399
        GlameTreeItem *grpw;
 
400
 
 
401
        if (!GPSM_ITEM_IS_GRP(item->item)
 
402
            || !gpsm_grp_is_vbox((gpsm_grp_t *)item->item))
 
403
                return;
 
404
 
 
405
        /* Create new gpsm swfile and insert it. */
 
406
        swfile = gpsm_newswfile(_("Unnamed"));
 
407
        gpsm_vbox_insert((gpsm_grp_t *)item->item,
 
408
                         (gpsm_item_t *)swfile,
 
409
                         0, gpsm_item_vsize(item->item));
 
410
 
 
411
        /* Expand the parent widget. */
 
412
        gtk_tree_item_expand(GTK_TREE_ITEM(item));
 
413
 
 
414
        /* Find out which widget it got and open an edit field. */
 
415
        grpw = glame_tree_find_gpsm_item(GTK_OBJECT(item), (gpsm_item_t *)swfile);
 
416
        if (grpw)
 
417
                edit_tree_label(grpw);
 
418
        deselect_all(active_swapfilegui);
 
419
}
 
420
 
 
421
/* Append an empty stereo wave (with group) to the current vbox. */
 
422
static void addstereo_cb(GtkWidget *menu, GlameTreeItem *item)
 
423
{
 
424
        gpsm_swfile_t *left, *right;
 
425
        gpsm_grp_t *grp;
 
426
        GlameTreeItem *grpw;
 
427
 
 
428
        if (!GPSM_ITEM_IS_GRP(item->item)
 
429
            || !gpsm_grp_is_vbox((gpsm_grp_t *)item->item))
 
430
                return;
 
431
 
 
432
        /* Create new group and two gpsm swfiles and insert it. */
 
433
        grp = gpsm_newgrp(_("Unnamed"));
 
434
        left = gpsm_newswfile(_("left"));
 
435
        gpsm_swfile_set_position(left, FILTER_PIPEPOS_LEFT);
 
436
        right = gpsm_newswfile(_("right"));
 
437
        gpsm_swfile_set_position(right, FILTER_PIPEPOS_RIGHT);
 
438
        gpsm_vbox_insert(grp, (gpsm_item_t *)left, 0, 0);
 
439
        gpsm_vbox_insert(grp, (gpsm_item_t *)right, 0, 1);
 
440
        gpsm_vbox_insert((gpsm_grp_t *)item->item,
 
441
                         (gpsm_item_t *)grp,
 
442
                         0, gpsm_item_vsize(item->item));
 
443
 
 
444
        /* Expand the parent widget. */
 
445
        gtk_tree_item_expand(GTK_TREE_ITEM(item));
 
446
 
 
447
        /* Find out which widget it got and open an edit field. */
 
448
        grpw = glame_tree_find_gpsm_item(GTK_OBJECT(item), (gpsm_item_t *)grp);
 
449
        if (grpw)
 
450
                edit_tree_label(grpw);
 
451
        deselect_all(active_swapfilegui);
 
452
}
 
453
 
 
454
static void group_cb(GtkWidget *menu, GlameTreeItem *item)
 
455
{
 
456
        gpsm_grp_t *grp, *parent;
 
457
        gpsm_item_t *it;
 
458
        long hpos, vpos;
 
459
        GlameTreeItem *grpw;
 
460
        GtkObject *tree;
 
461
 
 
462
        if (!GPSM_ITEM_IS_SWFILE(item->item))
 
463
                return;
 
464
 
 
465
        /* Create new gpsm group, move item into it and re-insert
 
466
         * it at old item position. */
 
467
        parent = gpsm_item_parent(item->item);
 
468
        tree = GTK_OBJECT(item->tree);
 
469
        grp = gpsm_newgrp(gpsm_item_label(item->item));
 
470
        it = item->item;
 
471
        hpos = gpsm_item_hposition(it);
 
472
        vpos = gpsm_item_vposition(it);
 
473
        gpsm_item_remove(it);
 
474
        gpsm_item_place(grp, it, 0, 0);
 
475
        gpsm_item_place(parent, (gpsm_item_t *)grp, hpos, vpos);
 
476
 
 
477
        /* Find out which widget it got and open an edit field. */
 
478
        grpw = glame_tree_find_gpsm_item(GTK_OBJECT(tree), (gpsm_item_t *)grp);
 
479
        if (grpw)
 
480
                edit_tree_label(grpw);
 
481
        deselect_all(active_swapfilegui);
 
482
}
 
483
 
 
484
static void addgroup_cb(GtkWidget *menu, GlameTreeItem *item)
 
485
{
 
486
        gpsm_grp_t *grp;
 
487
        GlameTreeItem *grpw;
 
488
 
 
489
        if (!GPSM_ITEM_IS_GRP(item->item)
 
490
            || !gpsm_grp_is_vbox((gpsm_grp_t *)item->item))
 
491
                return;
 
492
 
 
493
        /* Create new gpsm group. */
 
494
        grp = gpsm_newgrp(_("Unnamed"));
 
495
        gpsm_vbox_insert((gpsm_grp_t *)item->item, (gpsm_item_t *)grp,
 
496
                         0, gpsm_item_vsize(item->item));
 
497
 
 
498
        /* Expand the parent widget. */
 
499
        gtk_tree_item_expand(GTK_TREE_ITEM(item));
 
500
 
 
501
        /* Find out which widget it got and open an edit field. */
 
502
        grpw = glame_tree_find_gpsm_item(GTK_OBJECT(item), (gpsm_item_t *)grp);
 
503
        if (grpw)
 
504
                edit_tree_label(grpw);
 
505
        deselect_all(active_swapfilegui);
 
506
}
 
507
 
 
508
static void addclipboard_cb(GtkWidget *menu, GlameTreeItem *item)
 
509
{
 
510
        gpsm_grp_t *grp;
 
511
        GlameTreeItem *grpw;
 
512
 
 
513
        if (!GPSM_ITEM_IS_GRP(item->item)
 
514
            || !gpsm_grp_is_vbox((gpsm_grp_t *)item->item))
 
515
                return;
 
516
 
 
517
        /* Create new gpsm group. */
 
518
        if (!(grp = clipboard_get())) {
 
519
                gnome_dialog_run_and_close(GNOME_DIALOG(
 
520
                        gnome_error_dialog(_("Clipboard is empty"))));
 
521
                return;
 
522
        }
 
523
        gpsm_vbox_insert((gpsm_grp_t *)item->item, (gpsm_item_t *)grp,
 
524
                         0, gpsm_item_vsize(item->item));
 
525
 
 
526
        /* Expand the parent widget. */
 
527
        gtk_tree_item_expand(GTK_TREE_ITEM(item));
 
528
 
 
529
        /* Find out which widget it got and open an edit field. */
 
530
        grpw = glame_tree_find_gpsm_item(GTK_OBJECT(item), (gpsm_item_t *)grp);
 
531
        if (grpw)
 
532
                edit_tree_label(grpw);
 
533
        deselect_all(active_swapfilegui);
 
534
}
 
535
 
 
536
static void delete_cb(GtkWidget *menu, GlameTreeItem *item)
 
537
{
 
538
        gpsm_grp_t *deleted;
 
539
 
 
540
        deselect_all(active_swapfilegui);
 
541
        if (!(deleted = gpsm_find_grp_label(gpsm_root(), NULL, GPSM_GRP_DELETED_LABEL))) {
 
542
                deleted = gpsm_newgrp(GPSM_GRP_DELETED_LABEL);
 
543
                gpsm_item_place(gpsm_root(), (gpsm_item_t *)deleted,
 
544
                                0, GPSM_GRP_DELETED_VPOS);
 
545
        } else if ((gpsm_item_t *)deleted == item->item) {
 
546
                gpsm_item_destroy((gpsm_item_t *)deleted);
 
547
                return;
 
548
        }
 
549
        gpsm_item_place(deleted, item->item,
 
550
                        0, gpsm_item_vsize(deleted));
 
551
}
 
552
 
 
553
static void edit_cb(GtkWidget *menu, GlameTreeItem *item)
 
554
{
 
555
        WaveeditGui *we;
 
556
                
 
557
        we = glame_waveedit_gui_new(gpsm_item_label(item->item), item->item);
 
558
        if (!we) {
 
559
                gnome_dialog_run_and_close(GNOME_DIALOG(
 
560
                        gnome_error_dialog(_("Cannot open wave editor"))));
 
561
                return;
 
562
        }
 
563
        gtk_quit_add_destroy(1, GTK_OBJECT(we));
 
564
        gtk_widget_show_all(GTK_WIDGET(we));
 
565
        deselect_all(active_swapfilegui);
 
566
}
 
567
 
 
568
static void timeline_cb(GtkWidget *menu, GlameTreeItem *item)
 
569
{
 
570
        static int warning_shown = 0;
 
571
        GtkWidget *tl;
 
572
                
 
573
        tl = glame_timeline_new_with_window(gpsm_item_label(item->item),
 
574
                                            (gpsm_grp_t *)item->item);
 
575
        if (!tl) {
 
576
                gnome_dialog_run_and_close(GNOME_DIALOG(
 
577
                        gnome_error_dialog(_("Cannot open timeline"))));
 
578
                return;
 
579
        }
 
580
        gtk_quit_add_destroy(1, GTK_OBJECT(tl));
 
581
        gtk_widget_show_all(tl);
 
582
        deselect_all(active_swapfilegui);
 
583
        if (!warning_shown) {
 
584
                gnome_dialog_run_and_close(GNOME_DIALOG(
 
585
                        gnome_warning_dialog_parented(_("The timeline is highly experimental\nand may cause unexpected effects\nwithin other parts of GLAME.\nBe warned."), GTK_WINDOW(tl))));
 
586
                warning_shown = 1;
 
587
        }
 
588
}
 
589
 
 
590
void changeString_cb(GtkEditable *wid, char *returnbuffer)
 
591
{
 
592
        strncpy(returnbuffer, gtk_editable_get_chars(wid, 0, -1), 100);
 
593
}
 
594
static void export_cb(GtkWidget *menu, GlameTreeItem *item)
 
595
{
 
596
        glame_export_dialog(item->item, NULL);
 
597
        deselect_all(active_swapfilegui);
 
598
}
 
599
 
 
600
static void import_cb(GtkWidget *menu, GlameTreeItem *item)
 
601
{
 
602
        gpsm_item_t *imported;
 
603
 
 
604
        imported = glame_import_dialog(NULL);
 
605
        if (!imported)
 
606
                return;
 
607
 
 
608
        if (gpsm_grp_is_vbox((gpsm_grp_t *)item->item)
 
609
            && gpsm_vbox_insert((gpsm_grp_t *)item->item, imported,
 
610
                                0, gpsm_item_vsize(item->item)) == 0)
 
611
                return;
 
612
        if (gpsm_grp_is_hbox((gpsm_grp_t *)item->item)
 
613
            && gpsm_hbox_insert((gpsm_grp_t *)item->item, imported,
 
614
                                gpsm_item_hsize(item->item), 0) == 0)
 
615
                return;
 
616
 
 
617
        gnome_dialog_run_and_close(GNOME_DIALOG(gnome_error_dialog(
 
618
                _("Cannot place imported wave"))));
 
619
        gpsm_item_destroy(imported);
 
620
}
 
621
 
 
622
 
 
623
/*
 
624
 * Drag & Drop state-machine.
 
625
 * FIXME: better grab/release the pointer
 
626
 */
 
627
extern GtkWidget *glame_appbar;
 
628
static void drag_start_stop_cb(GtkWidget *widget, GdkEventButton *event,
 
629
                               GlameTreeItem *item)
 
630
{
 
631
        static GlameTreeItem *drag_widget = NULL;
 
632
        static int mode = -1;
 
633
        static int cursor_type = -1;
 
634
        static GdkCursor *cursor = NULL;
 
635
        GdkEventButton *bevent = (GdkEventButton *)event;
 
636
        GdkEventCrossing *cevent = (GdkEventCrossing *)event;
 
637
        gpsm_item_t *source, *dest;
 
638
        gpsm_grp_t *parent;
 
639
 
 
640
        if (event->type == GDK_BUTTON_PRESS) {
 
641
                if (bevent->button != 1)
 
642
                        return;
 
643
 
 
644
                /* drag&drop start */
 
645
                drag_widget = NULL;
 
646
                mode = -1;
 
647
                if (bevent->state & GDK_SHIFT_MASK) {
 
648
                        DPRINTF("SHIFT modifier\n");
 
649
                        mode = 1;
 
650
                        gnome_appbar_push(GNOME_APPBAR(glame_appbar),
 
651
                                          _("Drop into hbox"));
 
652
                } else if (bevent->state & GDK_CONTROL_MASK) {
 
653
                        DPRINTF("CTRL modifier\n");
 
654
                        mode = 2;
 
655
                        gnome_appbar_push(GNOME_APPBAR(glame_appbar),
 
656
                                          _("Drop into vbox"));
 
657
                } else {
 
658
                        DPRINTF("illegal modifier\n");
 
659
                        return; /* modifier not valid */
 
660
                }
 
661
                drag_widget = item;
 
662
 
 
663
        } else if (event->type == GDK_BUTTON_RELEASE) {
 
664
                if (bevent->button != 1)
 
665
                        return;
 
666
 
 
667
                /* drag&drop end */
 
668
                if (!drag_widget)
 
669
                        return; /* spurious event - ignore */
 
670
                gnome_appbar_pop(GNOME_APPBAR(glame_appbar));
 
671
                if (cursor) {
 
672
                        cursor_type = -1;
 
673
                        gdk_window_set_cursor(GTK_WIDGET(active_swapfilegui)->window, NULL);
 
674
                        gdk_cursor_destroy(cursor);
 
675
                        cursor = NULL;
 
676
                }
 
677
                if (drag_widget == item)
 
678
                        return; /* nop */
 
679
 
 
680
                source = drag_widget->item;
 
681
                dest = item->item;
 
682
                DPRINTF("drag&drop: %s on %s\n",
 
683
                        gpsm_item_label(drag_widget->item),
 
684
                        gpsm_item_label(item->item));
 
685
 
 
686
                if (mode == 1) {
 
687
                        /* Mode 1 - hbox insertion either before
 
688
                         * dropped item or at tail (if dropped
 
689
                         * on group). */
 
690
                        if (GPSM_ITEM_IS_GRP(dest)) {
 
691
                                if (gpsm_hbox_insert((gpsm_grp_t *)dest, source,
 
692
                                                     gpsm_item_hsize(dest), 0) == -1)
 
693
                                        DPRINTF("insertion failed\n");
 
694
                        } else {
 
695
                                if (gpsm_hbox_insert(gpsm_item_parent(dest), source,
 
696
                                                     gpsm_item_hposition(dest), 0) == -1)
 
697
                                        DPRINTF("insertion failed\n");
 
698
                        }
 
699
                } else if (mode == 2) {
 
700
                        /* Mode 2 - vbox insertion either before
 
701
                         * dropped item or at tail (if dropped
 
702
                         * on group). */
 
703
                        if (GPSM_ITEM_IS_GRP(dest)) {
 
704
                                if (gpsm_vbox_insert((gpsm_grp_t *)dest, source,
 
705
                                                     0, gpsm_item_vsize(dest)) == -1)
 
706
                                        DPRINTF("insertion failed\n");
 
707
                        } else {
 
708
                                if (gpsm_vbox_insert(gpsm_item_parent(dest), source,
 
709
                                                     0, gpsm_item_vposition(dest)) == -1)
 
710
                                        DPRINTF("insertion failed\n");
 
711
                        }
 
712
                }
 
713
 
 
714
                drag_widget = NULL;
 
715
                mode = -1;
 
716
 
 
717
        } else if (event->type == GDK_LEAVE_NOTIFY
 
718
                   && ((GdkEventCrossing *)event)->mode == GDK_CROSSING_NORMAL) {
 
719
                /* active_swapfilegui->active_item = NULL; */
 
720
 
 
721
        } else if (event->type == GDK_ENTER_NOTIFY) {
 
722
                int ok = 1;
 
723
                active_swapfilegui->active_item = item;
 
724
                if ((!drag_widget || !(cevent->state & GDK_BUTTON1_MASK))
 
725
                     && cursor) {
 
726
                        cursor_type = -1;
 
727
                        gdk_window_set_cursor(GTK_WIDGET(active_swapfilegui)->window, NULL);
 
728
                        gdk_cursor_destroy(cursor);
 
729
                        cursor = NULL;
 
730
                        drag_widget = NULL;
 
731
                        mode = -1;
 
732
                }
 
733
                if (!drag_widget)
 
734
                        return;
 
735
 
 
736
                if (GPSM_ITEM_IS_GRP(item->item))
 
737
                        parent = (gpsm_grp_t *)item->item;
 
738
                else
 
739
                        parent = gpsm_item_parent(item->item);
 
740
                if ((mode == 1 && !gpsm_grp_is_hbox(parent))
 
741
                    || (mode == 2 && !gpsm_grp_is_vbox(parent)))
 
742
                        ok = 0;
 
743
 
 
744
                if (cursor_type == ok)
 
745
                        return;
 
746
 
 
747
                cursor_type = ok;
 
748
                if (ok) {
 
749
                        GdkCursor *c;
 
750
                        c = gdk_cursor_new(GDK_HAND2);
 
751
                        gdk_window_set_cursor(GTK_WIDGET(active_swapfilegui)->window, c);
 
752
                        if (cursor)
 
753
                                gdk_cursor_destroy(cursor);
 
754
                        cursor = c;
 
755
                } else {
 
756
                        GdkCursor *c;
 
757
                        c = gdk_cursor_new(GDK_CIRCLE);
 
758
                        gdk_window_set_cursor(GTK_WIDGET(active_swapfilegui)->window, c);
 
759
                        if (cursor)
 
760
                                gdk_cursor_destroy(cursor);
 
761
                        cursor = c;
 
762
                }
 
763
        }
 
764
}
 
765
 
 
766
 
 
767
static void handle_swfile(glsig_handler_t *handler, long sig, va_list va)
 
768
{
 
769
        switch (sig) {
 
770
        case GPSM_SIG_ITEM_CHANGED: {
 
771
                GlameTreeItem *itemw = GLAME_TREE_ITEM(glsig_handler_private(handler));
 
772
                gpsm_item_t *item;
 
773
 
 
774
                GLSIGH_GETARGS1(va, item);
 
775
                if (itemw->item != item)
 
776
                        DERROR("Wrong itemw->item");
 
777
 
 
778
                /* Update the item widget. */
 
779
                glame_tree_item_update(GLAME_TREE_ITEM(itemw));
 
780
                break;
 
781
        }
 
782
        default:
 
783
                DPRINTF("Unhandled signal in swfile handler (%li)\n", sig);
 
784
        }
 
785
}
 
786
 
 
787
static void handle_grp_add_treeitem(GtkObject *tree, gpsm_item_t *item)
 
788
{
 
789
        GlameTreeItem *itemw, *nextw;
 
790
        gpsm_item_t *next;
 
791
 
 
792
        if (!tree || !item
 
793
            || !(GPSM_ITEM_IS_SWFILE(item) || GPSM_ITEM_IS_GRP(item)))
 
794
                return;
 
795
 
 
796
        /* Construct the item widget and register signal handlers
 
797
         * to the new item. */
 
798
        itemw = GLAME_TREE_ITEM(glame_tree_item_new(item));
 
799
        if (GPSM_ITEM_IS_GRP(item)) {
 
800
                itemw->handler = glsig_add_handler(
 
801
                        gpsm_item_emitter(item),
 
802
                        GPSM_SIG_GRP_NEWITEM|GPSM_SIG_GRP_REMOVEITEM|GPSM_SIG_ITEM_CHANGED,
 
803
                        handle_grp, itemw);
 
804
                /* drag&drop handlers */
 
805
                gtk_signal_connect(GTK_OBJECT(itemw), "button_press_event",
 
806
                                   (GtkSignalFunc)drag_start_stop_cb, itemw);
 
807
                gtk_signal_connect(GTK_OBJECT(itemw), "button_release_event",
 
808
                                   (GtkSignalFunc)drag_start_stop_cb, itemw);
 
809
                gtk_signal_connect(GTK_OBJECT(itemw), "enter_notify_event",
 
810
                                   (GtkSignalFunc)drag_start_stop_cb, itemw);
 
811
                gtk_signal_connect(GTK_OBJECT(itemw), "leave_notify_event",
 
812
                                   (GtkSignalFunc)drag_start_stop_cb, itemw);
 
813
        } else if (GPSM_ITEM_IS_SWFILE(item)) {
 
814
                itemw->handler = glsig_add_handler(
 
815
                        gpsm_item_emitter(item), GPSM_SIG_ITEM_CHANGED,
 
816
                        handle_swfile, itemw);
 
817
                /* drag&drop handlers */
 
818
                gtk_signal_connect(GTK_OBJECT(itemw), "button_press_event",
 
819
                                   (GtkSignalFunc)drag_start_stop_cb, itemw);
 
820
                gtk_signal_connect(GTK_OBJECT(itemw), "button_release_event",
 
821
                                   (GtkSignalFunc)drag_start_stop_cb, itemw);
 
822
                gtk_signal_connect(GTK_OBJECT(itemw), "enter_notify_event",
 
823
                                   (GtkSignalFunc)drag_start_stop_cb, itemw);
 
824
                gtk_signal_connect(GTK_OBJECT(itemw), "leave_notify_event",
 
825
                                   (GtkSignalFunc)drag_start_stop_cb, itemw);
 
826
        }
 
827
 
 
828
        /* Register gtk handlers and append the item widget. */
 
829
        gtk_signal_connect_after(GTK_OBJECT(itemw), "button_press_event",
 
830
                                 (GtkSignalFunc)click_cb,(gpointer)NULL);
 
831
 
 
832
        /* Look where we want to add the item (match gpsm list order). */
 
833
        if (!gpsm_item_parent(item)
 
834
            || !(next = gpsm_grp_next(gpsm_item_parent(item), item))
 
835
            || !(nextw = glame_tree_find_gpsm_item(tree, next)))
 
836
                glame_tree_append(tree, itemw);
 
837
        else
 
838
                glame_tree_insert(tree, itemw,
 
839
                                  gtk_tree_child_position(
 
840
                                          nextw->tree, GTK_WIDGET(nextw)));
 
841
 
 
842
        glame_tree_item_update(itemw);
 
843
 
 
844
        /* If item is a group we need to recurse down the items. */
 
845
        if (GPSM_ITEM_IS_GRP(item)) {
 
846
                gpsm_item_t *it;
 
847
                gpsm_grp_foreach_item(item, it)
 
848
                        handle_grp_add_treeitem(GTK_OBJECT(itemw), it);
 
849
        }
 
850
 
 
851
        gtk_widget_show(GTK_WIDGET(itemw));
 
852
}
 
853
static void handle_grp(glsig_handler_t *handler, long sig, va_list va)
 
854
{
 
855
        switch (sig) {
 
856
        case GPSM_SIG_ITEM_CHANGED: {
 
857
                GlameTreeItem *itemw = GLAME_TREE_ITEM(glsig_handler_private(handler));
 
858
                gpsm_item_t *item;
 
859
 
 
860
                GLSIGH_GETARGS1(va, item);
 
861
                if (itemw->item != item)
 
862
                        DERROR("Wrong itemw->item");
 
863
 
 
864
                /* Update the item widget. */
 
865
                glame_tree_item_update(GLAME_TREE_ITEM(itemw));
 
866
                break;
 
867
        }
 
868
        case GPSM_SIG_GRP_REMOVEITEM: {
 
869
                GtkObject *tree = GTK_OBJECT(glsig_handler_private(handler));
 
870
                GlameTreeItem *itemw;
 
871
                gpsm_grp_t *group;
 
872
                gpsm_item_t *item;
 
873
 
 
874
                GLSIGH_GETARGS2(va, group, item);
 
875
 
 
876
                /* Remove the item widget, if it is still there. */
 
877
                if ((itemw = glame_tree_find_gpsm_item(tree, item)))
 
878
                        glame_tree_remove(GLAME_TREE_ITEM(itemw));
 
879
 
 
880
                /* Note, that our signal handler will be deleted by
 
881
                 * the widgets destroy method. (hopefully gtk is sane here) */
 
882
 
 
883
                break;
 
884
        }
 
885
        case GPSM_SIG_GRP_NEWITEM: {
 
886
                GtkObject *tree = GTK_OBJECT(glsig_handler_private(handler));
 
887
                gpsm_grp_t *group;
 
888
                gpsm_item_t *item;
 
889
 
 
890
                GLSIGH_GETARGS2(va, group, item);
 
891
                if (GLAME_IS_TREE_ITEM(tree)
 
892
                    && GLAME_TREE_ITEM(tree)->item != (gpsm_item_t *)group)
 
893
                        DERROR("Wrong tree->item");
 
894
 
 
895
                /* Insert item (and subitems, if necessary). */
 
896
                handle_grp_add_treeitem(tree, item);
 
897
 
 
898
                break;
 
899
        }
 
900
        default:
 
901
                DPRINTF("Unhandled signal in grp handler (%li)\n", sig);
 
902
        }
 
903
}
 
904
 
 
905
static void handle_enterleave(GtkWidget *tree, GdkEventCrossing *event,
 
906
                              SwapfileGui *swapfile)
 
907
{
 
908
        if (event->type == GDK_ENTER_NOTIFY)
 
909
                active_swapfilegui = swapfile;
 
910
}
 
911
 
 
912
 
 
913
/*
 
914
 * Externally visible API and the SwapfileGui object (with guile access).
 
915
 */
 
916
 
 
917
static SCM gls_swapfilegui_root_item()
 
918
{
 
919
        if (!active_swapfilegui)
 
920
                return SCM_BOOL_F;
 
921
        return gpsmitem2scm((gpsm_item_t *)active_swapfilegui->root);
 
922
}
 
923
 
 
924
static SCM gls_swapfilegui_active_item()
 
925
{
 
926
        if (!active_swapfilegui)
 
927
                return SCM_BOOL_F;
 
928
        if (!active_swapfilegui->active_item)
 
929
                return gpsmitem2scm((gpsm_item_t *)active_swapfilegui->root);
 
930
        return gpsmitem2scm((gpsm_item_t *)active_swapfilegui->active_item->item);
 
931
}
 
932
 
 
933
static SCM gls_swapfilegui_selected_items()
 
934
{
 
935
        GList *selected;
 
936
        SCM s_items = SCM_LIST0;
 
937
        if (!active_swapfilegui)
 
938
                return s_items;
 
939
        selected = GTK_TREE_SELECTION(active_swapfilegui->tree);
 
940
        while (selected) {
 
941
                GlameTreeItem *i = GLAME_TREE_ITEM(selected->data);
 
942
                s_items = gh_cons(gpsmitem2scm(i->item), s_items);
 
943
                selected = g_list_next(selected);
 
944
        }
 
945
        return s_items;
 
946
}
 
947
 
 
948
void glame_swapfilegui_init()
 
949
{
 
950
        gh_new_procedure0_0("swapfilegui-root-item",
 
951
                            gls_swapfilegui_root_item);
 
952
        gh_new_procedure0_0("swapfilegui-active-item",
 
953
                            gls_swapfilegui_active_item);
 
954
        gh_new_procedure0_0("swapfilegui-selected-items",
 
955
                            gls_swapfilegui_selected_items);
 
956
}
 
957
 
 
958
static void swapfile_gui_destroy(GtkObject *object)
 
959
{
 
960
        SwapfileGui *swapfile = SWAPFILE_GUI(object);
 
961
        GtkEventBox* parent_class;
 
962
        parent_class = gtk_type_class(GTK_TYPE_EVENT_BOX);
 
963
        GTK_OBJECT_CLASS(parent_class)->destroy(GTK_OBJECT(swapfile));
 
964
        if (swapfile->gpsm_handler)
 
965
                glsig_delete_handler(swapfile->gpsm_handler);
 
966
}
 
967
 
 
968
static void swapfile_gui_class_init(SwapfileGuiClass *class)
 
969
{
 
970
        GtkObjectClass *object_class;
 
971
        object_class = GTK_OBJECT_CLASS(class);
 
972
        object_class->destroy = swapfile_gui_destroy;
 
973
}
 
974
 
 
975
static void swapfile_gui_init(SwapfileGui *swapfile)
 
976
{
 
977
        swapfile->gpsm_handler = NULL;
 
978
        swapfile->root = NULL;
 
979
        swapfile->tree = NULL;
 
980
        swapfile->active_item = NULL;
 
981
        swapfile->accel_handler = 0;
 
982
        swapfile->app = NULL;
 
983
}
 
984
 
 
985
GtkType swapfile_gui_get_type(void)
 
986
{
 
987
        static GtkType swapfile_gui_type = 0;
 
988
        
 
989
        if (!swapfile_gui_type){
 
990
                GtkTypeInfo swapfile_gui_info = {
 
991
                        "SwapfileGui",
 
992
                        sizeof(SwapfileGui),
 
993
                        sizeof(SwapfileGuiClass),
 
994
                        (GtkClassInitFunc)swapfile_gui_class_init,
 
995
                        (GtkObjectInitFunc)swapfile_gui_init,
 
996
                        NULL,NULL,(GtkClassInitFunc)NULL,};
 
997
                swapfile_gui_type = gtk_type_unique(
 
998
                        GTK_TYPE_EVENT_BOX, &swapfile_gui_info);
 
999
                gtk_type_set_chunk_alloc(swapfile_gui_type, 8);
 
1000
        }
 
1001
 
 
1002
        return swapfile_gui_type;
 
1003
}
 
1004
 
 
1005
SwapfileGui *glame_swapfile_widget_new(gpsm_grp_t *root)
 
1006
{
 
1007
        SwapfileGui *swapfile;
 
1008
        gpsm_item_t *item;
 
1009
 
 
1010
        if (!root)
 
1011
                return NULL;
 
1012
 
 
1013
        /* Create the toplevel objects. */
 
1014
        swapfile = SWAPFILE_GUI(gtk_type_new(swapfile_gui_get_type()));
 
1015
        swapfile->root = root;
 
1016
        swapfile->tree = gtk_tree_new();
 
1017
        gtk_container_add(GTK_CONTAINER(swapfile), swapfile->tree);
 
1018
        gtk_tree_set_view_mode(GTK_TREE(swapfile->tree), GTK_TREE_VIEW_LINE);
 
1019
        gtk_tree_set_view_lines(GTK_TREE(swapfile->tree), TRUE);
 
1020
        gtk_tree_set_selection_mode(GTK_TREE(swapfile->tree),
 
1021
                                    GTK_SELECTION_MULTIPLE);
 
1022
        /* SINGLE   -- single
 
1023
           BROWSE   -- single
 
1024
           MULTIPLE -- multiple
 
1025
           EXTENDED -- none
 
1026
        */
 
1027
 
 
1028
        /* Add the root group and cause "newitem" signals to be sent
 
1029
         * for each item. */
 
1030
        swapfile->gpsm_handler = glsig_add_handler(gpsm_item_emitter(root),
 
1031
                          GPSM_SIG_GRP_NEWITEM|GPSM_SIG_GRP_REMOVEITEM,
 
1032
                          handle_grp, swapfile->tree);
 
1033
 
 
1034
        /* Track the active swapfilegui via enter/leave events. */
 
1035
        gtk_signal_connect(GTK_OBJECT(swapfile), "enter_notify_event",
 
1036
                           (GtkSignalFunc)handle_enterleave, swapfile);
 
1037
 
 
1038
        /* Add all existing childs of the root group to the tree. */
 
1039
        gpsm_grp_foreach_item(root, item)
 
1040
                handle_grp_add_treeitem(GTK_OBJECT(swapfile->tree), item);
 
1041
 
 
1042
        gtk_widget_show(swapfile->tree);
 
1043
        active_swapfilegui = swapfile;
 
1044
        return swapfile;
 
1045
}