1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2010,2011,2012 Nedko Arnaudov <nedko@arnaudov.name>
7 **************************************************************************
8 * This file contains dynamic menu related code
9 **************************************************************************
11 * LADI Session Handler is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * LADI Session Handler is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
23 * or write to the Free Software Foundation, Inc.,
24 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include "gtk_builder.h"
29 #include "../common/catdup.h"
34 GtkWidget
* menu_item
;
43 ladish_dynmenu_item_activate_callback item_activate_callback
,
44 void (* data_free
)()),
46 ladish_dynmenu_item_activate_callback item_activate_callback
;
48 gulong activate_signal_id
;
52 struct ladish_dynmenu_item_data
57 ladish_dynmenu_item_activate_callback item_activate_callback
;
60 void on_activate_item(GtkMenuItem
* UNUSED(item
), struct ladish_dynmenu_item_data
* data_ptr
)
62 //log_info("on_activate_item('%s')", gtk_label_get_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(data_ptr->item)))));
64 data_ptr
->item_activate_callback(
65 gtk_label_get_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(data_ptr
->item
)))),
69 #define data_ptr ((struct ladish_dynmenu_item_data *)data)
71 void free_item_data(gpointer data
, GClosure
* UNUSED(closure
))
73 //log_info("data_ptr %p deallocate", data_ptr);
75 if (data_ptr
->data
!= NULL
)
77 if (data_ptr
->data_free
!= NULL
)
79 data_ptr
->data_free(data_ptr
->data
);
91 #define dynmenu_ptr ((struct ladish_dynmenu *)context)
95 ladish_dynmenu_add_entry(
99 ladish_dynmenu_item_activate_callback item_activate_callback
,
100 void (* data_free
)())
102 struct ladish_dynmenu_item_data
* data_ptr
;
108 ASSERT(data
== NULL
);
109 ASSERT(item_activate_callback
== NULL
);
110 ASSERT(data_free
== NULL
);
111 item
= gtk_separator_menu_item_new();
112 gtk_widget_show(item
);
113 gtk_menu_shell_append(GTK_MENU_SHELL(dynmenu_ptr
->menu
), item
);
117 data_ptr
= malloc(sizeof(struct ladish_dynmenu_item_data
));
118 if (data_ptr
== NULL
)
120 log_error("Allocation of memory for dynmenu item data struct failed.");
124 //log_info("data_ptr %p allocated", data_ptr);
125 data_ptr
->data
= data
;
126 data_ptr
->data_free
= data_free
;
127 data_ptr
->item_activate_callback
= item_activate_callback
!= NULL
? item_activate_callback
: dynmenu_ptr
->item_activate_callback
;
129 data_ptr
->item
= gtk_menu_item_new_with_label(name
);
130 //log_info("refcount == %d", (unsigned int)G_OBJECT(item)->ref_count); // refcount == 2 because of the label
131 gtk_widget_set_sensitive(data_ptr
->item
, dynmenu_ptr
->add_sensitive
);
132 gtk_widget_show(data_ptr
->item
);
133 gtk_menu_shell_append(GTK_MENU_SHELL(dynmenu_ptr
->menu
), data_ptr
->item
);
134 g_signal_connect_data(
135 G_OBJECT(data_ptr
->item
),
137 G_CALLBACK(on_activate_item
),
143 dynmenu_ptr
->count
++;
146 static void remove_dynmenu_menu_entry(GtkWidget
* item
, gpointer context
)
150 label
= gtk_bin_get_child(GTK_BIN(item
));
152 //log_debug("removing dynmenu item \"%s\"", gtk_menu_item_get_label(GTK_MENU_ITEM(item));
153 // gtk_menu_item_get_label() requries gtk 2.16
154 log_debug("removing dynmenu item \"%s\"", gtk_label_get_text(GTK_LABEL(label
)));
156 gtk_container_remove(GTK_CONTAINER(item
), label
); /* destroy the label and drop the item refcount by one */
157 //log_info("refcount == %d", (unsigned int)G_OBJECT(item)->ref_count);
158 gtk_container_remove(GTK_CONTAINER(dynmenu_ptr
->menu
), item
); /* drop the refcount of item by one and thus destroy it */
159 dynmenu_ptr
->count
--;
164 static void menu_dynmenu_clear(struct ladish_dynmenu
* dynmenu_ptr
)
166 gtk_container_foreach(GTK_CONTAINER(dynmenu_ptr
->menu
), remove_dynmenu_menu_entry
, dynmenu_ptr
);
167 ASSERT(dynmenu_ptr
->count
== 0);
168 dynmenu_ptr
->count
= 0;
171 static void populate_dynmenu_menu(GtkMenuItem
* menu_item
, struct ladish_dynmenu
* dynmenu_ptr
)
176 if (!gtk_widget_get_sensitive(GTK_WIDGET(menu_item
)))
181 menu_dynmenu_clear(dynmenu_ptr
);
182 dynmenu_ptr
->add_sensitive
= true;
183 if (!dynmenu_ptr
->fill_callback(ladish_dynmenu_add_entry
, dynmenu_ptr
))
185 menu_dynmenu_clear(dynmenu_ptr
);
186 prefix
= _("Error filling ");
188 else if (dynmenu_ptr
->count
== 0)
190 prefix
= _("Empty ");
197 text
= catdup(prefix
, dynmenu_ptr
->description
);
199 dynmenu_ptr
->add_sensitive
= false;
200 ladish_dynmenu_add_entry(dynmenu_ptr
, text
!= NULL
? text
: prefix
, NULL
, NULL
, NULL
);
202 free(text
); /* free(NULL) is safe */
206 ladish_dynmenu_create(
207 const char * menu_item
,
216 ladish_dynmenu_item_activate_callback item_activate_callback
,
217 void (* data_free
)()),
219 const char * description
,
220 ladish_dynmenu_item_activate_callback item_activate_callback
,
221 ladish_dynmenu_handle
* dynmenu_handle_ptr
)
223 struct ladish_dynmenu
* dynmenu_ptr
;
225 dynmenu_ptr
= malloc(sizeof(struct ladish_dynmenu
));
226 if (dynmenu_ptr
== NULL
)
228 log_error("Allocation of ladish_dynmenu struct failed");
232 dynmenu_ptr
->description
= strdup(description
);
233 if (dynmenu_ptr
->description
== NULL
)
235 log_error("strdup('%s') failed for dynmenu description string", description
);
240 dynmenu_ptr
->count
= 0;
241 dynmenu_ptr
->menu_item
= get_gtk_builder_widget(menu_item
);
242 dynmenu_ptr
->menu
= get_gtk_builder_widget(menu
);
243 dynmenu_ptr
->fill_callback
= fill_callback
;
244 dynmenu_ptr
->item_activate_callback
= item_activate_callback
;
245 gtk_menu_item_set_submenu(GTK_MENU_ITEM(dynmenu_ptr
->menu_item
), dynmenu_ptr
->menu
);
246 dynmenu_ptr
->activate_signal_id
= g_signal_connect(G_OBJECT(dynmenu_ptr
->menu_item
), "activate", G_CALLBACK(populate_dynmenu_menu
), dynmenu_ptr
);
248 *dynmenu_handle_ptr
= (ladish_dynmenu_handle
)dynmenu_ptr
;
252 #define dynmenu_ptr ((struct ladish_dynmenu *)dynmenu_handle)
255 ladish_dynmenu_fill_external(
256 ladish_dynmenu_handle dynmenu_handle
,
259 GtkWidget
* menu_backup
;
262 menu_backup
= dynmenu_ptr
->menu
;
263 count_backup
= dynmenu_ptr
->count
;
265 dynmenu_ptr
->menu
= GTK_WIDGET(menu
);
266 dynmenu_ptr
->add_sensitive
= true;
268 dynmenu_ptr
->fill_callback(ladish_dynmenu_add_entry
, dynmenu_ptr
);
270 dynmenu_ptr
->menu
= menu_backup
;
271 dynmenu_ptr
->count
= count_backup
;
275 ladish_dynmenu_destroy(
276 ladish_dynmenu_handle dynmenu_handle
)
278 if (g_signal_handler_is_connected(G_OBJECT(dynmenu_ptr
->menu_item
), dynmenu_ptr
->activate_signal_id
))
280 g_signal_handler_disconnect(G_OBJECT(dynmenu_ptr
->menu_item
), dynmenu_ptr
->activate_signal_id
);
283 free(dynmenu_ptr
->description
);