1 /*
2 
3 Copyright (c) 2001-2007 Michael Terry
4 Copyright (c) 2013-2014 Arthur Borsboom
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 3 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 
20 */
21 
22 #include "../config.h"
23 
24 #include <glib/gi18n.h>
25 
26 #include "xpad-toolbar.h"
27 #include "xpad-app.h"
28 #include "xpad-grip-tool-item.h"
29 
30 struct XpadToolbarPrivate
31 {
32 	gboolean move_removed;
33 	guint move_index;
34 	guint move_motion_handler;
35 	guint move_button_release_handler;
36 	guint move_key_press_handler;
37 	XpadPad *pad;
38 };
39 
40 G_DEFINE_TYPE_WITH_PRIVATE (XpadToolbar, xpad_toolbar, GTK_TYPE_TOOLBAR)
41 
42 enum {
43 	XPAD_BUTTON_TYPE_SEPARATOR,
44 	XPAD_BUTTON_TYPE_BUTTON,
45 	XPAD_BUTTON_TYPE_TOGGLE
46 };
47 
48 typedef struct
49 {
50 	const gchar *name;
51 	const gchar *icon_name;
52 	guint signal;
53 	guint type;
54 	const gchar *desc;
55 	const gchar *menu_desc;
56 } XpadToolbarButton;
57 
58 enum
59 {
60 	ACTIVATE_NEW,
61 	ACTIVATE_CLOSE,
62 	ACTIVATE_UNDO,
63 	ACTIVATE_REDO,
64 	ACTIVATE_CUT,
65 	ACTIVATE_COPY,
66 	ACTIVATE_PASTE,
67 	ACTIVATE_DELETE,
68 	ACTIVATE_CLEAR,
69 	ACTIVATE_PREFERENCES,
70 	ACTIVATE_PROPERTIES,
71 	ACTIVATE_QUIT,
72 	POPUP,
73 	POPDOWN,
74 	LAST_SIGNAL
75 };
76 
77 static const XpadToolbarButton buttons[] =
78 {
79 	{"Clear", "edit-clear", ACTIVATE_CLEAR, XPAD_BUTTON_TYPE_BUTTON, N_("Clear Pad Contents"), N_("Add C_lear button")},
80 	{"Close", "window-close", ACTIVATE_CLOSE, XPAD_BUTTON_TYPE_BUTTON, N_("Close and Save Pad"), N_("Add _Close button")},
81 	{"Copy", "edit-copy", ACTIVATE_COPY, XPAD_BUTTON_TYPE_BUTTON, N_("Copy to Clipboard"), N_("Add C_opy button")},
82 	{"Cut", "edit-cut", ACTIVATE_CUT, XPAD_BUTTON_TYPE_BUTTON, N_("Cut to Clipboard"), N_("Add C_ut button")},
83 	{"Delete", "edit-delete", ACTIVATE_DELETE, XPAD_BUTTON_TYPE_BUTTON, N_("Delete Pad"), N_("Add _Delete button")},
84 	{"New", "document-new", ACTIVATE_NEW, XPAD_BUTTON_TYPE_BUTTON, N_("Open New Pad"), N_("Add _New button")},
85 	{"Paste", "edit-paste", ACTIVATE_PASTE, XPAD_BUTTON_TYPE_BUTTON, N_("Paste from Clipboard"), N_("Add Pa_ste button")},
86 	{"Preferences", "preferences-system", ACTIVATE_PREFERENCES, XPAD_BUTTON_TYPE_BUTTON, N_("Edit Preferences"), N_("Add Pr_eferences button")},
87 	{"Properties", "document-properties", ACTIVATE_PROPERTIES, XPAD_BUTTON_TYPE_BUTTON, N_("Edit Pad Properties"), N_("Add Proper_ties button")},
88 	{"Redo", "edit-redo", ACTIVATE_REDO, XPAD_BUTTON_TYPE_BUTTON, N_("Redo"), N_("Add _Redo button")},
89 	{"Quit", "application-exit", ACTIVATE_QUIT, XPAD_BUTTON_TYPE_BUTTON, N_("Close All Pads"), N_("Add Close _All button")},
90 	{"Undo", "edit-undo", ACTIVATE_UNDO, XPAD_BUTTON_TYPE_BUTTON, N_("Undo"), N_("Add _Undo button")},
91 	{"Separator", NULL, 0, XPAD_BUTTON_TYPE_SEPARATOR, NULL, N_("Add Se_parator")}
92 };
93 
94 static void xpad_toolbar_constructed (GObject *object);
95 static void xpad_toolbar_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
96 static void xpad_toolbar_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
97 static void xpad_toolbar_dispose (GObject *object);
98 static const XpadToolbarButton *xpad_toolbar_button_lookup (XpadToolbar *toolbar, const gchar *name);
99 static GtkToolItem *xpad_toolbar_button_to_item (XpadToolbar *toolbar, const XpadToolbarButton *button);
100 static void xpad_toolbar_button_activated (GtkToolButton *button);
101 static void xpad_toolbar_change_buttons (XpadToolbar *toolbar);
102 static void xpad_toolbar_add_button (GtkMenuItem *menu_item, XpadSettings *settings);
103 static gboolean xpad_toolbar_popup_context_menu (GtkToolbar *toolbar, gint x, gint y, gint button);
104 
105 static guint signals[LAST_SIGNAL] = { 0 };
106 
107 enum
108 {
109 	PROP_0,
110 	PROP_PAD,
111 	LAST_PROP
112 };
113 
114 GtkWidget *
xpad_toolbar_new(XpadPad * pad)115 xpad_toolbar_new (XpadPad *pad)
116 {
117 	return GTK_WIDGET (g_object_new (XPAD_TYPE_TOOLBAR, "pad", pad, NULL));
118 }
119 
120 static void
xpad_toolbar_class_init(XpadToolbarClass * klass)121 xpad_toolbar_class_init (XpadToolbarClass *klass)
122 {
123 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
124 	GtkToolbarClass *gtktoolbar_class = GTK_TOOLBAR_CLASS (klass);
125 
126 	gobject_class->constructed = xpad_toolbar_constructed;
127 	gobject_class->set_property = xpad_toolbar_set_property;
128 	gobject_class->get_property = xpad_toolbar_get_property;
129 	gobject_class->dispose = xpad_toolbar_dispose;
130 	gtktoolbar_class->popup_context_menu = xpad_toolbar_popup_context_menu;
131 
132 	signals[ACTIVATE_NEW] =
133 		g_signal_new ("activate-new",
134 		              G_OBJECT_CLASS_TYPE (gobject_class),
135 		              G_SIGNAL_RUN_LAST,
136 		              G_STRUCT_OFFSET (XpadToolbarClass, activate_new),
137 		              NULL, NULL,
138 		              g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
139 
140 	signals[ACTIVATE_CLOSE] =
141 		g_signal_new ("activate-close",
142 		              G_OBJECT_CLASS_TYPE (gobject_class),
143 		              G_SIGNAL_RUN_LAST,
144 		              G_STRUCT_OFFSET (XpadToolbarClass, activate_close),
145 		              NULL, NULL,
146 		              g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
147 
148 	signals[ACTIVATE_UNDO] =
149 		g_signal_new ("activate-undo",
150 		              G_OBJECT_CLASS_TYPE (gobject_class),
151 		              G_SIGNAL_RUN_LAST,
152 		              G_STRUCT_OFFSET (XpadToolbarClass, activate_undo),
153 		              NULL, NULL,
154 		              g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
155 
156 	signals[ACTIVATE_REDO] =
157 		g_signal_new ("activate-redo",
158 		              G_OBJECT_CLASS_TYPE (gobject_class),
159 		              G_SIGNAL_RUN_LAST,
160 		              G_STRUCT_OFFSET (XpadToolbarClass, activate_redo),
161 		              NULL, NULL,
162 		              g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
163 
164 	signals[ACTIVATE_CUT] =
165 		g_signal_new ("activate-cut",
166 		              G_OBJECT_CLASS_TYPE (gobject_class),
167 		              G_SIGNAL_RUN_LAST,
168 		              G_STRUCT_OFFSET (XpadToolbarClass, activate_cut),
169 		              NULL, NULL,
170 		              g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
171 
172 	signals[ACTIVATE_COPY] =
173 		g_signal_new ("activate-copy",
174 		              G_OBJECT_CLASS_TYPE (gobject_class),
175 		              G_SIGNAL_RUN_LAST,
176 		              G_STRUCT_OFFSET (XpadToolbarClass, activate_copy),
177 		              NULL, NULL,
178 		              g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
179 
180 	signals[ACTIVATE_PASTE] =
181 		g_signal_new ("activate-paste",
182 		              G_OBJECT_CLASS_TYPE (gobject_class),
183 		              G_SIGNAL_RUN_LAST,
184 		              G_STRUCT_OFFSET (XpadToolbarClass, activate_paste),
185 		              NULL, NULL,
186 		              g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
187 
188 	signals[ACTIVATE_QUIT] =
189 		g_signal_new ("activate-quit",
190 		              G_OBJECT_CLASS_TYPE (gobject_class),
191 		              G_SIGNAL_RUN_LAST,
192 		              G_STRUCT_OFFSET (XpadToolbarClass, activate_quit),
193 		              NULL, NULL,
194 		              g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
195 
196 	signals[ACTIVATE_CLEAR] =
197 		g_signal_new ("activate-clear",
198 		              G_OBJECT_CLASS_TYPE (gobject_class),
199 		              G_SIGNAL_RUN_LAST,
200 		              G_STRUCT_OFFSET (XpadToolbarClass, activate_clear),
201 		              NULL, NULL,
202 		              g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
203 
204 	signals[ACTIVATE_PROPERTIES] =
205 		g_signal_new ("activate-properties",
206 		              G_OBJECT_CLASS_TYPE (gobject_class),
207 		              G_SIGNAL_RUN_LAST,
208 		              G_STRUCT_OFFSET (XpadToolbarClass, activate_properties),
209 		              NULL, NULL,
210 		              g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
211 
212 	signals[ACTIVATE_PREFERENCES] =
213 		g_signal_new ("activate-preferences",
214 		              G_OBJECT_CLASS_TYPE (gobject_class),
215 		              G_SIGNAL_RUN_LAST,
216 		              G_STRUCT_OFFSET (XpadToolbarClass, activate_preferences),
217 		              NULL, NULL,
218 		              g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
219 
220 	signals[ACTIVATE_DELETE] =
221 		g_signal_new ("activate-delete",
222 		              G_OBJECT_CLASS_TYPE (gobject_class),
223 		              G_SIGNAL_RUN_LAST,
224 		              G_STRUCT_OFFSET (XpadToolbarClass, activate_delete),
225 		              NULL, NULL,
226 		              g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
227 
228 	signals[POPUP] =
229 		g_signal_new ("popup",
230 		              G_OBJECT_CLASS_TYPE (gobject_class),
231 		              G_SIGNAL_RUN_LAST,
232 		              G_STRUCT_OFFSET (XpadToolbarClass, popup),
233 		              NULL, NULL,
234 		              g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GTK_TYPE_MENU);
235 
236 	signals[POPDOWN] =
237 		g_signal_new ("popdown",
238 		              G_OBJECT_CLASS_TYPE (gobject_class),
239 		              G_SIGNAL_RUN_LAST,
240 		              G_STRUCT_OFFSET (XpadToolbarClass, popdown),
241 		              NULL, NULL,
242 		              g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GTK_TYPE_MENU);
243 
244 	g_object_class_install_property (gobject_class,
245 					 PROP_PAD,
246 					 g_param_spec_pointer ("pad",
247 									"Pad",
248 									"Pad associated with this toolbar",
249 									G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
250 }
251 
252 static void
xpad_toolbar_init(XpadToolbar * toolbar)253 xpad_toolbar_init (XpadToolbar *toolbar)
254 {
255 	toolbar->priv = xpad_toolbar_get_instance_private(toolbar);
256 
257 	toolbar->priv->move_motion_handler = 0;
258 	toolbar->priv->move_button_release_handler = 0;
259 	toolbar->priv->move_key_press_handler = 0;
260 
261 	g_object_set (toolbar,
262 	              "icon-size", GTK_ICON_SIZE_MENU,
263 	              "show-arrow", FALSE,
264 	              "toolbar-style", GTK_TOOLBAR_ICONS,
265 	              NULL);
266 }
267 
xpad_toolbar_constructed(GObject * object)268 static void xpad_toolbar_constructed (GObject *object)
269 {
270 	XpadSettings *settings;
271 	XpadToolbar *toolbar = XPAD_TOOLBAR (object);
272 
273 	xpad_toolbar_change_buttons (toolbar);
274 
275 	/* Add CSS style class, so the styling can be overridden by a GTK theme */
276 	GtkStyleContext *context = gtk_widget_get_style_context(GTK_WIDGET (toolbar));
277 	gtk_style_context_add_class(context, "XpadToolbar");
278 
279 	g_object_get (toolbar->priv->pad, "settings", &settings, NULL);
280 	g_signal_connect_swapped (settings, "change-buttons", G_CALLBACK (xpad_toolbar_change_buttons), toolbar);
281 }
282 
283 static void
xpad_toolbar_dispose(GObject * object)284 xpad_toolbar_dispose (GObject *object)
285 {
286 	XpadToolbar *toolbar = XPAD_TOOLBAR (object);
287 
288 	g_clear_object (&toolbar->priv->pad);
289 
290 	G_OBJECT_CLASS (xpad_toolbar_parent_class)->dispose (object);
291 }
292 
293 void
xpad_toolbar_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)294 xpad_toolbar_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
295 {
296 	XpadToolbar *toolbar = XPAD_TOOLBAR (object);
297 
298 	switch (prop_id)
299 	{
300 	case PROP_PAD:
301 		g_clear_object (&toolbar->priv->pad);
302 
303 		if (G_VALUE_HOLDS_POINTER (value) && G_IS_OBJECT (g_value_get_pointer (value))) {
304 			toolbar->priv->pad = g_value_get_pointer (value);
305 			g_object_ref (toolbar->priv->pad);
306 		}
307 
308 		break;
309 
310 	default:
311 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
312 		break;
313 	 }
314 }
315 
316 void
xpad_toolbar_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)317 xpad_toolbar_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
318 {
319 	XpadToolbar *toolbar = XPAD_TOOLBAR (object);
320 
321 	switch (prop_id)
322 	{
323 	case PROP_PAD:
324 		g_value_set_pointer (value, toolbar->priv->pad);
325 		break;
326 
327 	default:
328 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
329 		break;
330 	}
331 }
332 
333 static const XpadToolbarButton *
xpad_toolbar_button_lookup(XpadToolbar * toolbar,const gchar * name)334 xpad_toolbar_button_lookup (XpadToolbar *toolbar, const gchar *name)
335 {
336 	/* A dirty way to silence the compiler for these unused variables. */
337 	(void) toolbar;
338 
339 	guint i;
340 	for (i = 0; i < G_N_ELEMENTS (buttons); i++)
341 		if (!g_ascii_strcasecmp (name, buttons[i].name))
342 			return &buttons[i];
343 
344 	return NULL;
345 }
346 
347 static GtkToolItem *
xpad_toolbar_button_to_item(XpadToolbar * toolbar,const XpadToolbarButton * button)348 xpad_toolbar_button_to_item (XpadToolbar *toolbar, const XpadToolbarButton *button)
349 {
350 	GtkToolItem *item = GTK_TOOL_ITEM (g_object_get_data (G_OBJECT (toolbar), button->name));
351 
352 	if (item)
353 		return item;
354 
355 	switch (button->type)
356 	{
357 	case XPAD_BUTTON_TYPE_BUTTON:
358 		item = gtk_tool_button_new (NULL, button->name);
359 		gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (item), button->icon_name);
360 		g_signal_connect (item, "clicked", G_CALLBACK (xpad_toolbar_button_activated), NULL);
361 		break;
362 	case XPAD_BUTTON_TYPE_TOGGLE:
363 		item = gtk_tool_button_new (NULL, button->name);
364 		gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (item), button->icon_name);
365 		g_signal_connect (item, "toggled", G_CALLBACK (xpad_toolbar_button_activated), NULL);
366 		break;
367 	case XPAD_BUTTON_TYPE_SEPARATOR:
368 		item = GTK_TOOL_ITEM (gtk_separator_tool_item_new ());
369 		break;
370 	default:
371 		return NULL;
372 	}
373 
374 	g_object_set_data (G_OBJECT (item), "xpad-toolbar", toolbar);
375 	g_object_set_data (G_OBJECT (item), "xpad-tb", (gpointer) button);
376 
377 	g_object_set_data (G_OBJECT (toolbar), button->name, item);
378 
379 	if (button->desc)
380 		gtk_tool_item_set_tooltip_text (item, _(button->desc));
381 
382 	return item;
383 }
384 
385 static void
xpad_toolbar_button_activated(GtkToolButton * button)386 xpad_toolbar_button_activated (GtkToolButton *button)
387 {
388 	XpadToolbar *toolbar;
389 	const XpadToolbarButton *tb;
390 
391 	toolbar = XPAD_TOOLBAR (g_object_get_data (G_OBJECT (button), "xpad-toolbar"));
392 	tb = (const XpadToolbarButton *) g_object_get_data (G_OBJECT (button), "xpad-tb");
393 
394 	g_signal_emit (toolbar, signals[tb->signal], 0);
395 }
396 
397 static void
xpad_toolbar_change_buttons(XpadToolbar * toolbar)398 xpad_toolbar_change_buttons (XpadToolbar *toolbar)
399 {
400 	GList *list, *temp;
401 	const GSList *slist, *stemp;
402 	guint i = 0, j = 0;
403 	GtkToolItem *item;
404 	XpadSettings *settings;
405 
406 	list = gtk_container_get_children (GTK_CONTAINER (toolbar));
407 
408 	for (temp = list; temp; temp = temp->next)
409 		gtk_widget_destroy (temp->data);
410 
411 	g_list_free (list);
412 	g_list_free (temp);
413 
414 	for (j = 0; j < G_N_ELEMENTS (buttons); j++)
415 		g_object_set_data (G_OBJECT (toolbar), buttons[j].name, NULL);
416 
417 	g_object_get (toolbar->priv->pad, "settings", &settings, NULL);
418 
419 	slist = xpad_settings_get_toolbar_buttons (settings);
420 
421 	for (stemp = slist; stemp; stemp = stemp->next)
422 	{
423 		const XpadToolbarButton *button;
424 
425 		button = xpad_toolbar_button_lookup (toolbar, stemp->data);
426 
427 		if (button->type == XPAD_BUTTON_TYPE_SEPARATOR)
428 			item = gtk_separator_tool_item_new ();
429 		else if (button->type == XPAD_BUTTON_TYPE_BUTTON)
430 			item = xpad_toolbar_button_to_item (toolbar, button);
431 		else
432 			continue;
433 
434 		if (item)
435 		{
436 			g_object_set_data (G_OBJECT (item), "xpad-button-num", GINT_TO_POINTER (i));
437 			gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
438 			gtk_widget_show_all (GTK_WIDGET (item));
439 			i++;
440 		}
441 	}
442 
443 	item = gtk_separator_tool_item_new ();
444 	g_object_set_data (G_OBJECT (item), "xpad-button-num", GINT_TO_POINTER (i));
445 	gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (item), FALSE);
446 	gtk_tool_item_set_expand (item, TRUE);
447 	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
448 	gtk_widget_show_all (GTK_WIDGET (item));
449 	i++;
450 
451 	item = xpad_grip_tool_item_new ();
452 	g_object_set_data (G_OBJECT (item), "xpad-button-num", GINT_TO_POINTER (i));
453 	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
454 	gtk_widget_show_all (GTK_WIDGET (item));
455 	i++;
456 
457 	if (toolbar->priv->pad)
458 	{
459 		xpad_pad_notify_has_selection (toolbar->priv->pad);
460 		xpad_pad_notify_clipboard_owner_changed (toolbar->priv->pad);
461 	}
462 }
463 
464 static void
xpad_toolbar_add_button(GtkMenuItem * menu_item,XpadSettings * settings)465 xpad_toolbar_add_button (GtkMenuItem *menu_item, XpadSettings *settings)
466 {
467 	xpad_settings_add_toolbar_button (settings, gtk_menu_item_get_accel_path (menu_item) + 2);
468 }
469 
470 static void
menu_deactivated(GtkWidget * menu,GtkToolbar * toolbar)471 menu_deactivated (GtkWidget *menu, GtkToolbar *toolbar)
472 {
473 	g_signal_emit (toolbar, signals[POPDOWN], 0, menu);
474 }
475 
476 static gboolean
xpad_toolbar_popup_context_menu(GtkToolbar * toolbar,gint x,gint y,gint button)477 xpad_toolbar_popup_context_menu (GtkToolbar *toolbar, gint x, gint y, gint button)
478 {
479 	/* A dirty way to silence the compiler for these unused variables. */
480 	(void) x;
481 	(void) y;
482 
483 	guint i;
484 	gboolean is_button = FALSE;
485 	XpadSettings *settings;
486 
487 	g_object_get (XPAD_TOOLBAR (toolbar)->priv->pad, "settings", &settings, NULL);
488 	const GSList *current_buttons = xpad_settings_get_toolbar_buttons (settings);
489 	GtkMenu *menu = GTK_MENU (gtk_menu_new ());
490 
491 	for (i = 0; i < G_N_ELEMENTS (buttons); i++)
492 	{
493 		const GSList *j;
494 		GtkWidget *item;
495 
496 		for (j = current_buttons; j; j = j->next)
497 			if (g_ascii_strcasecmp (j->data, "Separator") && !g_ascii_strcasecmp (j->data, buttons[i].name))
498 				break;
499 
500 		if (j)
501 		{
502 			is_button = TRUE;
503 			continue;
504 		}
505 
506 		item = gtk_menu_item_new_with_mnemonic (buttons[i].menu_desc);
507 		/* Ugly workaround by abusing the accel_path to get the variable passed to the next function */
508 		gtk_menu_item_set_accel_path (GTK_MENU_ITEM (item), g_strdup_printf ("</%s", buttons[i].name));
509 		g_signal_connect (item, "activate", G_CALLBACK (xpad_toolbar_add_button), settings);
510 		gtk_menu_attach (menu, item, 0, 1, i, i + 1);
511 		gtk_widget_show (item);
512 	}
513 
514 	if (is_button)
515 	{
516 		GtkWidget *item;
517 
518 		item = gtk_menu_item_new_with_mnemonic (N_("Remove All _Buttons"));
519 		g_signal_connect_swapped (item, "activate", G_CALLBACK (xpad_settings_remove_all_toolbar_buttons), settings);
520 		gtk_menu_attach (menu, item, 0, 1, i, i + 1);
521 		gtk_widget_show (item);
522 
523 		i++;
524 
525 		item = gtk_menu_item_new_with_mnemonic (N_("Remo_ve Last Button"));
526 		g_signal_connect_swapped (item, "activate", G_CALLBACK (xpad_settings_remove_last_toolbar_button), settings);
527 		gtk_menu_attach (menu, item, 0, 1, i, i + 1);
528 		gtk_widget_show (item);
529 	}
530 
531 	g_signal_connect (menu, "deactivate", G_CALLBACK (menu_deactivated), toolbar);
532 
533 	gtk_menu_popup_at_pointer (menu, NULL);
534 
535 	g_signal_emit (toolbar, signals[POPUP], 0, menu);
536 
537 	return TRUE;
538 }
539 
540 static void
xpad_toolbar_enable_button(XpadToolbar * toolbar,const XpadToolbarButton * button,gboolean enable)541 xpad_toolbar_enable_button (XpadToolbar *toolbar, const XpadToolbarButton *button, gboolean enable)
542 {
543 	g_return_if_fail (button);
544 	GtkToolItem *item = xpad_toolbar_button_to_item (toolbar, button);
545 	if (item)
546 		gtk_widget_set_sensitive (GTK_WIDGET (item), enable);
547 }
548 
549 void
xpad_toolbar_enable_undo_button(XpadToolbar * toolbar,gboolean enable)550 xpad_toolbar_enable_undo_button (XpadToolbar *toolbar, gboolean enable)
551 {
552 	const XpadToolbarButton *button = xpad_toolbar_button_lookup (toolbar, "Undo");
553 	xpad_toolbar_enable_button (toolbar, button, enable);
554 }
555 
556 void
xpad_toolbar_enable_redo_button(XpadToolbar * toolbar,gboolean enable)557 xpad_toolbar_enable_redo_button (XpadToolbar *toolbar, gboolean enable)
558 {
559 	const XpadToolbarButton *button = xpad_toolbar_button_lookup (toolbar, "Redo");
560 	xpad_toolbar_enable_button (toolbar, button, enable);
561 }
562 
563 void
xpad_toolbar_enable_cut_button(XpadToolbar * toolbar,gboolean enable)564 xpad_toolbar_enable_cut_button (XpadToolbar *toolbar, gboolean enable)
565 {
566 	const XpadToolbarButton *button = xpad_toolbar_button_lookup (toolbar, "Cut");
567 	xpad_toolbar_enable_button (toolbar, button, enable);
568 }
569 
570 void
xpad_toolbar_enable_copy_button(XpadToolbar * toolbar,gboolean enable)571 xpad_toolbar_enable_copy_button (XpadToolbar *toolbar, gboolean enable)
572 {
573 	const XpadToolbarButton *button = xpad_toolbar_button_lookup (toolbar, "Copy");
574 	xpad_toolbar_enable_button (toolbar, button, enable);
575 }
576 
577 void
xpad_toolbar_enable_paste_button(XpadToolbar * toolbar,gboolean enable)578 xpad_toolbar_enable_paste_button (XpadToolbar *toolbar, gboolean enable)
579 {
580 	const XpadToolbarButton *button = xpad_toolbar_button_lookup (toolbar, "Paste");
581 	xpad_toolbar_enable_button (toolbar, button, enable);
582 }
583