~ubuntu-branches/ubuntu/natty/bluefish/natty

« back to all changes in this revision

Viewing changes to src/plugin_snippets/snippetsmenu.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Leidert (dale)
  • Date: 2010-06-29 21:40:10 UTC
  • mfrom: (1.1.6 upstream) (5.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20100629214010-2oxygudqcstn3zc6
Tags: 2.0.1-1
* New upstream release - the first release of the 2.0 series for Debian
  (closes: #570731; LP: #540126). This release fixes these reported issues:
  - Better settings handling (closes: #548272).
  - Improved filebrowser (LP: #45927).
  - Improved syntax highlighting engine (LP: #108628).
  - Improved file operations (LP: #181110).
  - Translated menu descriptions (LP: #371318, #371322). The chosen menu
    name is fine.
  - Improved browser commands and handling (LP: #158891, #348408).
* Updated and adjusted packaging files.
* debian/bluefish_icon.xpm: Renamed to debian/bluefish.xpm.
* debian/bluefish.install: Adjusted.
* debian/bluefish.menu (icon): Adjusted.
* debian/bluefish-data.install, debian/bluefish-plugins.install: Added.
* debian/control: Added bluefish-data, bluefish-dbg and bluefish-plugins.
  (Build-Depends): Dropped deprecated build-dependencies libaspell-dev,
  libgnomeui-dev, libgnomevfs2-dev, libpcre3-dev and dpatch. Added intltool,
  libtool, libenchant-dev and libgucharmap2-dev.
  (Standards-Version): Bumped to 3.8.4.
  (Depends, Suggests): Adjusted. Added gvfs-backends as dependency.
* debian/copyright: Updated.
* debian/rules: Rewritten. Dropped dpatch.
  (LDFLAGS): Dropped -Wl,-z,defs because of plugins.
  (config.status:): Adjusted configure switches.
  (install): Install to debian/tmp and list missing files.
  (binary-indep): Added for bluefish-data.
  (binary-arch): Adjusted. Put debugging symbols into bluefish-dbg.
* debian/watch: Added support for RCs.
* debian/README.Debian: Dropped (useless with 2.0).
* debian/README.source: Dropped together with dpatch.
* debian/patches/: Dropped (obsolete).
* debian/reportbug/: Dropped.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Bluefish HTML Editor
 
2
 * snippetsmenu.c - menubar that represents the treemodel as menu
 
3
 *
 
4
 * Copyright (C) 2009 Olivier Sessink
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
19
 */
 
20
/*#define DEBUG*/
 
21
#include <gtk/gtk.h>
 
22
#include "../bluefish.h"
 
23
#include "snippetsmenu.h"
 
24
 
 
25
 
 
26
static GtkMenuItem *menushell_nth_child(GtkMenuShell *menushell, guint n) {
 
27
        GtkMenuItem *menuitem;
 
28
        GList *list = gtk_container_get_children(GTK_CONTAINER(menushell));
 
29
        menuitem = g_list_nth_data(list, n);
 
30
        g_list_free(list);
 
31
        /*g_print("menushell_nth_child, return child %p for n=%d\n",menuitem,n);*/
 
32
        return menuitem;
 
33
}
 
34
 
 
35
/* this is an ugly hack to expose the treepath internals to this widget */
 
36
typedef struct {
 
37
        gint depth;
 
38
        gint *indices;  
 
39
} TreePath;
 
40
 
 
41
#define TREEPATH(var) ((TreePath *)(var))
 
42
 
 
43
static GtkMenuItem *menuitem_from_path(SnippetsMenu *sm, GtkTreePath *path) {
 
44
        gint i;
 
45
        GtkMenuItem *mitem=NULL;
 
46
        GtkMenuShell *mshell = (GtkMenuShell *)sm;
 
47
        if (!path) {
 
48
                DEBUG_MSG("menuitem_from_path, path=NULL, return NULL\n");
 
49
                return NULL;
 
50
        }
 
51
        /*DEBUG_MSG("menuitem_from_path, depth=%d\n",TREEPATH(path)->depth);*/
 
52
        for (i=0;mshell && i<TREEPATH(path)->depth;i++) {
 
53
                /* all menu's have a tearoff entry as first entry, except the main menu */
 
54
                mitem = menushell_nth_child(mshell, i==0?TREEPATH(path)->indices[i]:TREEPATH(path)->indices[i]+1);
 
55
                if (mitem)
 
56
                        mshell = (GtkMenuShell *)gtk_menu_item_get_submenu(mitem);
 
57
                else 
 
58
                        mshell = NULL;
 
59
        }
 
60
        DEBUG_MSG("indices[%d]=%d mitem=%p, mshell=%p\n",i,TREEPATH(path)->indices[i],mitem, mshell);
 
61
        /*g_print("return mitem=%p with label %s\n", mitem, gtk_label_get_text(GTK_LABEL(GTK_BIN(mitem)->child)));*/
 
62
        return mitem;
 
63
}
 
64
 
 
65
static void snippets_menu_row_inserted(GtkTreeModel * tree_model,
 
66
                                                                           GtkTreePath * path, GtkTreeIter * iter, gpointer user_data)
 
67
{
 
68
        SnippetsMenu *sm = user_data;
 
69
        GtkMenuItem *item, *newitem;
 
70
        GtkTreePath *parent;
 
71
        DEBUG_MSG("row inserted, path=%s\n", gtk_tree_path_to_string(path));
 
72
        parent = gtk_tree_path_copy(path);
 
73
        if (!gtk_tree_path_up(parent) || gtk_tree_path_get_depth(parent)==0) {
 
74
                GtkRequisition req;
 
75
                /* main menu entry ! */
 
76
                gtk_widget_size_request((GtkWidget *)sm,&req);
 
77
                DEBUG_MSG("have %d pixels in use, %d available\n",req.width, sm->maxwidth);
 
78
                if (req.width < (sm->maxwidth-100)) { /* reserve at least 100 pixels for any new entry */
 
79
                        newitem = (GtkMenuItem *) gtk_menu_item_new_with_label("");
 
80
                        gtk_menu_shell_insert((GtkMenuShell *)sm, (GtkWidget *)newitem, TREEPATH(path)->indices[0]);
 
81
                        gtk_widget_show((GtkWidget *)newitem);
 
82
                }
 
83
        } else {
 
84
                GtkMenuShell *mshell;
 
85
                item = menuitem_from_path(sm, parent);
 
86
                if (item) {
 
87
                        mshell = (GtkMenuShell *)gtk_menu_item_get_submenu(item);
 
88
                        DEBUG_MSG("row inserted, item=%p, mshell=%p\n",item, mshell);
 
89
                        if (!mshell) {
 
90
                                GtkMenuItem *tearoff;
 
91
                                mshell = (GtkMenuShell *)gtk_menu_new();
 
92
                                DEBUG_MSG("append mshell %p to item %p\n",mshell, item);
 
93
                                gtk_menu_item_set_submenu(item, (GtkWidget *)mshell);
 
94
                                tearoff = (GtkMenuItem *) gtk_tearoff_menu_item_new();
 
95
                                gtk_menu_shell_insert((GtkMenuShell *)mshell, (GtkWidget *)tearoff, 0);
 
96
                                gtk_widget_show((GtkWidget *)tearoff);
 
97
                        }
 
98
                        DEBUG_MSG("row inserted, insert in mshell=%p at position %d\n",mshell, TREEPATH(path)->indices[TREEPATH(path)->depth-1]+1);
 
99
                        newitem = (GtkMenuItem *) gtk_menu_item_new_with_label("");
 
100
                        /* add 1 to the index number for the tearoff item */
 
101
                        gtk_menu_shell_insert((GtkMenuShell *)mshell, (GtkWidget *)newitem, TREEPATH(path)->indices[TREEPATH(path)->depth-1]+1);
 
102
                        gtk_widget_show((GtkWidget *)newitem);
 
103
                }
 
104
        }
 
105
        gtk_tree_path_free(parent);
 
106
}
 
107
 
 
108
/*static void snippets_menu_rows_reordered(GtkTreeModel * tree_model,
 
109
                                                                                 GtkTreePath * path,
 
110
                                                                                 GtkTreeIter * iter, gint *neworder, gpointer user_data)
 
111
{
 
112
        / * an array of integers mapping the current position of each child to its 
 
113
        old position before the re-ordering, i.e. neworder[newpos] = oldpos. * /
 
114
        
 
115
        DEBUG_MSG("TODO rows reordered\n");
 
116
}
 
117
 
 
118
static void snippets_menu_row_has_child_toggled(GtkTreeModel * tree_model,
 
119
                                                                                                GtkTreePath * path, GtkTreeIter * iter, gpointer user_data)
 
120
{
 
121
        DEBUG_MSG("todo? or nothing todo? row has child toggled\n");
 
122
}
 
123
*/
 
124
static void snippets_menu_row_deleted(GtkTreeModel * tree_model, GtkTreePath * path, gpointer user_data)
 
125
{
 
126
        SnippetsMenu *sm = user_data;
 
127
        GtkMenuItem *mitem;
 
128
        DEBUG_MSG("row deleted\n");
 
129
        mitem = menuitem_from_path(sm, path);
 
130
        if (mitem) {
 
131
                gtk_widget_destroy((GtkWidget *)mitem);
 
132
        } else {
 
133
                DEBUG_MSG("row deleted, no mitem for path %s\n",gtk_tree_path_to_string(path)); 
 
134
        }
 
135
}
 
136
 
 
137
typedef struct {
 
138
        SnippetsMenu *sm;
 
139
        gpointer pointer;
 
140
} Tsmdata;
 
141
 
 
142
static void menuitem_activate(GtkMenuItem *mitem, gpointer user_data) {
 
143
        Tsmdata *smdata=user_data;
 
144
        smdata->sm->callback(smdata->sm->user_data, smdata->pointer);
 
145
}
 
146
 
 
147
static void smdata_free(gpointer smdata) {
 
148
        g_slice_free(Tsmdata, smdata);
 
149
}
 
150
 
 
151
static void snippets_menu_row_changed(GtkTreeModel * tree_model,
 
152
                                                                          GtkTreePath * path, GtkTreeIter * iter, gpointer user_data)
 
153
{
 
154
        SnippetsMenu *sm = user_data;
 
155
        GtkMenuItem *mitem;
 
156
        mitem = menuitem_from_path(sm, path);
 
157
        if (mitem) {
 
158
                gchar *name=NULL;
 
159
                gpointer pointer;
 
160
                Tsmdata *smdata;
 
161
                gtk_tree_model_get(tree_model, iter, sm->name_column, &name, sm->data_column, &pointer, -1);
 
162
                if (GTK_BIN(mitem)->child) {
 
163
                        g_signal_handlers_disconnect_matched(mitem, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, menuitem_activate, NULL);
 
164
                        gtk_label_set_text(GTK_LABEL(GTK_BIN(mitem)->child),name);
 
165
                }
 
166
                smdata = g_object_get_data(G_OBJECT(mitem),"smdata");
 
167
                if (!smdata) {
 
168
                        smdata = g_slice_new(Tsmdata);
 
169
                        smdata->sm = sm;
 
170
                        g_object_weak_ref(G_OBJECT(mitem),(GWeakNotify) smdata_free,smdata);
 
171
                        g_object_set_data(G_OBJECT(mitem),"smdata",smdata);
 
172
                }
 
173
                smdata->pointer = pointer;
 
174
                g_signal_connect(mitem, "activate", G_CALLBACK(menuitem_activate), smdata);
 
175
        } else {
 
176
                DEBUG_MSG("row changed, no mitem for path %s\n",gtk_tree_path_to_string(path)); 
 
177
        }
 
178
}
 
179
 
 
180
gboolean snippets_menu_set_model_foreach(GtkTreeModel *model,GtkTreePath *path,GtkTreeIter *iter,gpointer data) {
 
181
        snippets_menu_row_inserted(model,path,iter, data);
 
182
        snippets_menu_row_changed(model,path, iter, data);
 
183
        return FALSE;
 
184
}
 
185
void snippets_menu_set_model(SnippetsMenu * sm, GtkTreeModel * model, SnippetMenuCallback callback, gpointer user_data, gint name_column, gint data_column)
 
186
{
 
187
        sm->name_column = name_column;
 
188
        sm->data_column = data_column;
 
189
        sm->callback = callback;
 
190
        sm->user_data = user_data;
 
191
        g_signal_connect(model, "row-changed", G_CALLBACK(snippets_menu_row_changed), sm);
 
192
        g_signal_connect(model, "row-deleted", G_CALLBACK(snippets_menu_row_deleted), sm);
 
193
        /*g_signal_connect(model, "row-has-child-toggled", G_CALLBACK(snippets_menu_row_has_child_toggled), sm);
 
194
        g_signal_connect(model, "rows-reordered", G_CALLBACK(snippets_menu_rows_reordered), sm);*/
 
195
        g_signal_connect(model, "row-inserted", G_CALLBACK(snippets_menu_row_inserted), sm);
 
196
        
 
197
        gtk_tree_model_foreach(model, snippets_menu_set_model_foreach, sm);
 
198
}
 
199
 
 
200
 
 
201
/************ widget stuff *****************/
 
202
 
 
203
G_DEFINE_TYPE(SnippetsMenu, snippets_menu, GTK_TYPE_MENU_BAR)
 
204
 
 
205
static void snippets_menu_finalize(GObject * object)
 
206
{
 
207
        /*g_print("finalize\n");*/
 
208
}
 
209
 
 
210
static void snippets_menu_class_init(SnippetsMenuClass * klass)
 
211
{
 
212
        GObjectClass *object_class = G_OBJECT_CLASS(klass);
 
213
        /*GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);*/
 
214
        object_class->finalize = snippets_menu_finalize;
 
215
}
 
216
 
 
217
static void snippets_menu_init(SnippetsMenu * sm)
 
218
{
 
219
 
 
220
}
 
221
 
 
222
GtkWidget *snippets_menu_new(gint maxwidth)
 
223
{
 
224
        SnippetsMenu *sm = (SnippetsMenu *) g_object_new(SNIPPETS_TYPE_MENU, NULL);
 
225
        g_return_val_if_fail(sm != NULL, NULL);
 
226
        sm->maxwidth = maxwidth;
 
227
        return GTK_WIDGET(sm);
 
228
}