geany  1.38
About: Geany is a text editor (using GTK2) with basic features of an integrated development environment (syntax highlighting, code folding, symbol name auto-completion, ...). F: office T: editor programming GTK+ IDE
  Fossies Dox: geany-1.38.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

toolbar.c
Go to the documentation of this file.
1/*
2 * toolbar.c - this file is part of Geany, a fast and lightweight IDE
3 *
4 * Copyright 2009 The Geany contributors
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 along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21/**
22 * @file toolbar.h
23 * Toolbar (prefs).
24 */
25/* Utility functions to create the toolbar */
26
27#ifdef HAVE_CONFIG_H
28# include "config.h"
29#endif
30
31#include "toolbar.h"
32
33#include "app.h"
34#include "build.h"
35#include "callbacks.h"
36#include "document.h"
37#include "geanyentryaction.h"
39#include "main.h"
40#include "support.h"
41#include "ui_utils.h"
42#include "utils.h"
43
44#include <string.h>
45#include <glib/gstdio.h>
46
47
49static GtkUIManager *uim;
50static GtkActionGroup *group;
51static GSList *plugin_items = NULL;
52
53/* Available toolbar actions
54 * Fields: name, stock_id, label, accelerator, tooltip, callback */
55static const GtkActionEntry ui_entries[] = {
56 /* custom actions defined in toolbar_init(): "New", "Open", "SearchEntry", "GotoEntry", "Build" */
57 { "Save", GTK_STOCK_SAVE, NULL, NULL, N_("Save the current file"), G_CALLBACK(on_save1_activate) },
58 { "SaveAs", GTK_STOCK_SAVE_AS, NULL, NULL, N_("Save as"), G_CALLBACK(on_save_as1_activate) },
59 { "SaveAll", GEANY_STOCK_SAVE_ALL, NULL, NULL, N_("Save all open files"), G_CALLBACK(on_save_all1_activate) },
60 { "Reload", GTK_STOCK_REVERT_TO_SAVED, NULL, NULL, N_("Reload the current file from disk"), G_CALLBACK(on_toolbutton_reload_clicked) },
61 { "Close", GTK_STOCK_CLOSE, NULL, NULL, N_("Close the current file"), G_CALLBACK(on_close1_activate) },
62 { "CloseAll", GEANY_STOCK_CLOSE_ALL, NULL, NULL, N_("Close all open files"), G_CALLBACK(on_close_all1_activate) },
63 { "Cut", GTK_STOCK_CUT, NULL, NULL, N_("Cut the current selection"), G_CALLBACK(on_cut1_activate) },
64 { "Copy", GTK_STOCK_COPY, NULL, NULL, N_("Copy the current selection"), G_CALLBACK(on_copy1_activate) },
65 { "Paste", GTK_STOCK_PASTE, NULL, NULL, N_("Paste the contents of the clipboard"), G_CALLBACK(on_paste1_activate) },
66 { "Delete", GTK_STOCK_DELETE, NULL, NULL, N_("Delete the current selection"), G_CALLBACK(on_delete1_activate) },
67 { "Undo", GTK_STOCK_UNDO, NULL, NULL, N_("Undo the last modification"), G_CALLBACK(on_undo1_activate) },
68 { "Redo", GTK_STOCK_REDO, NULL, NULL, N_("Redo the last modification"), G_CALLBACK(on_redo1_activate) },
69 { "NavBack", GTK_STOCK_GO_BACK, NULL, NULL, N_("Navigate back a location"), G_CALLBACK(on_toolbutton_back_activate) },
70 { "NavFor", GTK_STOCK_GO_FORWARD, NULL, NULL, N_("Navigate forward a location"), G_CALLBACK(on_toolbutton_forward_activate) },
71 { "Compile", GTK_STOCK_CONVERT, N_("Compile"), NULL, N_("Compile the current file"), G_CALLBACK(on_toolbutton_compile_clicked) },
72 { "Run", GTK_STOCK_EXECUTE, NULL, NULL, N_("Run or view the current file"), G_CALLBACK(on_toolbutton_run_clicked) },
73 { "Color", GTK_STOCK_SELECT_COLOR, N_("Color Chooser"), NULL, N_("Open a color chooser dialog, to interactively pick colors from a palette"), G_CALLBACK(on_show_color_chooser1_activate) },
74 { "ZoomIn", GTK_STOCK_ZOOM_IN, NULL, NULL, N_("Zoom in the text"), G_CALLBACK(on_zoom_in1_activate) },
75 { "ZoomOut", GTK_STOCK_ZOOM_OUT, NULL, NULL, N_("Zoom out the text"), G_CALLBACK(on_zoom_out1_activate) },
76 { "UnIndent", GTK_STOCK_UNINDENT, NULL, NULL, N_("Decrease indentation"), G_CALLBACK(on_menu_decrease_indent1_activate) },
77 { "Indent", GTK_STOCK_INDENT, NULL, NULL, N_("Increase indentation"), G_CALLBACK(on_menu_increase_indent1_activate) },
78 { "Search", GTK_STOCK_FIND, NULL, NULL, N_("Find the entered text in the current file"), G_CALLBACK(on_toolbutton_search_clicked) },
79 { "Goto", GTK_STOCK_JUMP_TO, NULL, NULL, N_("Jump to the entered line number"), G_CALLBACK(on_toolbutton_goto_clicked) },
80 { "Preferences", GTK_STOCK_PREFERENCES, NULL, NULL, N_("Show the preferences dialog"), G_CALLBACK(on_preferences1_activate) },
81 { "Quit", GTK_STOCK_QUIT, NULL, NULL, N_("Quit Geany"), G_CALLBACK(on_quit1_activate) },
82 { "Print", GTK_STOCK_PRINT, NULL, NULL, N_("Print document"), G_CALLBACK(on_print1_activate) },
83 { "Replace", GTK_STOCK_FIND_AND_REPLACE, NULL, NULL, N_("Replace text in the current document"), G_CALLBACK(on_replace1_activate) }
84};
85static const guint ui_entries_n = G_N_ELEMENTS(ui_entries);
86
87
88/* fallback UI definition */
89static const gchar *toolbar_markup =
90"<ui>"
91 "<toolbar name='GeanyToolbar'>"
92 "<toolitem action='New'/>"
93 "<toolitem action='Open'/>"
94 "<toolitem action='Save'/>"
95 "<toolitem action='SaveAll'/>"
96 "<separator/>"
97 "<toolitem action='Reload'/>"
98 "<toolitem action='Close'/>"
99 "<separator/>"
100 "<toolitem action='NavBack'/>"
101 "<toolitem action='NavFor'/>"
102 "<separator/>"
103 "<toolitem action='Compile'/>"
104 "<toolitem action='Build'/>"
105 "<toolitem action='Run'/>"
106 "<separator/>"
107 "<toolitem action='Color'/>"
108 "<separator/>"
109 "<toolitem action='SearchEntry'/>"
110 "<toolitem action='Search'/>"
111 "<separator/>"
112 "<toolitem action='GotoEntry'/>"
113 "<toolitem action='Goto'/>"
114 "<separator/>"
115 "<toolitem action='Quit'/>"
116 "</toolbar>"
117"</ui>";
118
119
120/* Note: The returned widget pointer is only valid until the toolbar is reloaded. So, either
121 * update the widget pointer in this case (i.e. request it again) or better use
122 * toolbar_get_action_by_name() instead. The action objects will remain the same even when the
123 * toolbar is reloaded. */
124GtkWidget *toolbar_get_widget_by_name(const gchar *name)
125{
126 GtkWidget *widget;
127 gchar *path;
128
129 g_return_val_if_fail(name != NULL, NULL);
130
131 path = g_strconcat("/ui/GeanyToolbar/", name, NULL);
132 widget = gtk_ui_manager_get_widget(uim, path);
133
134 g_free(path);
135 return widget;
136}
137
138
139/* Note: The returned widget pointer is only valid until the toolbar is reloaded. See
140 * toolbar_get_widget_by_name for details(). */
142{
143 GtkWidget *widget = toolbar_get_widget_by_name(name);
144
145 if (G_LIKELY(widget != NULL))
146 return gtk_bin_get_child(GTK_BIN(widget));
147 else
148 return NULL;
149}
150
151
152GtkAction *toolbar_get_action_by_name(const gchar *name)
153{
154 g_return_val_if_fail(name != NULL, NULL);
155
156 return gtk_action_group_get_action(group, name);
157}
158
159
160static void toolbar_item_destroy_cb(GtkWidget *widget, G_GNUC_UNUSED gpointer data)
161{
162 plugin_items = g_slist_remove(plugin_items, widget);
163}
164
165
166void toolbar_item_ref(GtkToolItem *item)
167{
168 g_return_if_fail(item != NULL);
169
170 plugin_items = g_slist_append(plugin_items, item);
171 g_signal_connect(item, "destroy", G_CALLBACK(toolbar_item_destroy_cb), NULL);
172}
173
174
175static GtkWidget *toolbar_reload(const gchar *markup)
176{
177 gint i;
178 GSList *l;
179 GtkWidget *entry;
180 GError *error = NULL;
181 gchar *filename;
182 static guint merge_id = 0;
183 GtkWidget *toolbar_new_file_menu = NULL;
184 GtkWidget *toolbar_recent_files_menu = NULL;
185 GtkWidget *toolbar_build_menu = NULL;
186
187 /* Cleanup old toolbar */
188 if (merge_id > 0)
189 {
190 /* ref plugins toolbar items to keep them after we destroyed the toolbar */
192 {
193 g_object_ref(l->data);
194 gtk_container_remove(GTK_CONTAINER(main_widgets.toolbar), GTK_WIDGET(l->data));
195 }
196 /* ref and hold the submenus of the New, Open and Build toolbar items */
197 toolbar_new_file_menu = geany_menu_button_action_get_menu(
198 GEANY_MENU_BUTTON_ACTION(gtk_action_group_get_action(group, "New")));
199 g_object_ref(toolbar_new_file_menu);
200 toolbar_recent_files_menu = geany_menu_button_action_get_menu(
201 GEANY_MENU_BUTTON_ACTION(gtk_action_group_get_action(group, "Open")));
202 g_object_ref(toolbar_recent_files_menu);
203 toolbar_build_menu = geany_menu_button_action_get_menu(
204 GEANY_MENU_BUTTON_ACTION(gtk_action_group_get_action(group, "Build")));
205 g_object_ref(toolbar_build_menu);
206
207 /* Get rid of it! */
208 gtk_widget_destroy(main_widgets.toolbar);
209
210 gtk_ui_manager_remove_ui(uim, merge_id);
211 gtk_ui_manager_ensure_update(uim);
212 }
213
214 if (markup != NULL)
215 {
216 merge_id = gtk_ui_manager_add_ui_from_string(uim, markup, -1, &error);
217 }
218 else
219 {
220 /* Load the toolbar UI XML file from disk (first from config dir, then try data dir) */
221 filename = g_build_filename(app->configdir, "ui_toolbar.xml", NULL);
222 merge_id = gtk_ui_manager_add_ui_from_file(uim, filename, &error);
223 if (merge_id == 0)
224 {
225 if (! g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
226 geany_debug("Loading user toolbar UI definition failed (%s).", error->message);
227 g_error_free(error);
228 error = NULL;
229
230 SETPTR(filename, g_build_filename(app->datadir, "ui_toolbar.xml", NULL));
231 merge_id = gtk_ui_manager_add_ui_from_file(uim, filename, &error);
232 }
233 g_free(filename);
234 }
235 if (error != NULL)
236 {
237 geany_debug("UI creation failed, using internal fallback definition. Error message: %s",
238 error->message);
239 g_error_free(error);
240 /* finally load the internally defined markup as fallback */
241 merge_id = gtk_ui_manager_add_ui_from_string(uim, toolbar_markup, -1, NULL);
242 }
243 main_widgets.toolbar = gtk_ui_manager_get_widget(uim, "/ui/GeanyToolbar");
245
246 /* add the toolbar again to the main window */
248 {
249 GtkWidget *hbox_menubar = ui_lookup_widget(main_widgets.window, "hbox_menubar");
250 gtk_box_pack_start(GTK_BOX(hbox_menubar), main_widgets.toolbar, TRUE, TRUE, 0);
251 gtk_box_reorder_child(GTK_BOX(hbox_menubar), main_widgets.toolbar, 1);
252 }
253 else
254 {
255 GtkWidget *box = ui_lookup_widget(main_widgets.window, "vbox1");
256
257 gtk_box_pack_start(GTK_BOX(box), main_widgets.toolbar, FALSE, FALSE, 0);
258 gtk_box_reorder_child(GTK_BOX(box), main_widgets.toolbar, 1);
259 }
260 gtk_widget_show(main_widgets.toolbar);
261
262 /* re-add und unref the plugin toolbar items */
265 {
266 gtk_toolbar_insert(GTK_TOOLBAR(main_widgets.toolbar), l->data, i);
267 g_object_unref(l->data);
268 i++;
269 }
270 /* re-add und unref the submenus of menu toolbar items */
271 if (toolbar_new_file_menu != NULL)
272 {
274 gtk_action_group_get_action(group, "New")), toolbar_new_file_menu);
275 g_object_unref(toolbar_new_file_menu);
276 }
277 if (toolbar_recent_files_menu != NULL)
278 {
280 gtk_action_group_get_action(group, "Open")), toolbar_recent_files_menu);
281 g_object_unref(toolbar_recent_files_menu);
282 }
283 if (toolbar_build_menu != NULL)
284 {
286 gtk_action_group_get_action(group, "Build")), toolbar_build_menu);
287 g_object_unref(toolbar_build_menu);
288 }
289
290 /* update button states */
291 if (main_status.main_window_realized)
292 {
294 gboolean doc_changed = (doc != NULL) ? doc->changed : FALSE;
295
297 ui_save_buttons_toggle(doc_changed); /* update save all */
299
301 }
302
303 /* Signals */
304 g_signal_connect(main_widgets.toolbar, "button-press-event",
305 G_CALLBACK(toolbar_popup_menu), NULL);
306 g_signal_connect(main_widgets.toolbar, "key-press-event",
307 G_CALLBACK(on_escape_key_press_event), NULL);
308
309 /* We don't need to disconnect those signals as this is done automatically when the entry
310 * widgets are destroyed, happens when the toolbar itself is destroyed. */
312 if (entry != NULL)
313 g_signal_connect(entry, "motion-notify-event", G_CALLBACK(on_motion_event), NULL);
315 if (entry != NULL)
316 g_signal_connect(entry, "motion-notify-event", G_CALLBACK(on_motion_event), NULL);
317
318 return main_widgets.toolbar;
319}
320
321
322static void toolbar_notify_style_cb(GObject *object, GParamSpec *arg1, gpointer data)
323{
324 const gchar *arg_name = g_param_spec_get_name(arg1);
325 gint value;
326
327 if (toolbar_prefs.use_gtk_default_style && utils_str_equal(arg_name, "gtk-toolbar-style"))
328 {
330 gtk_toolbar_set_style(GTK_TOOLBAR(main_widgets.toolbar), value);
331 }
332 else if (toolbar_prefs.use_gtk_default_icon && utils_str_equal(arg_name, "gtk-toolbar-size"))
333 {
335 gtk_toolbar_set_icon_size(GTK_TOOLBAR(main_widgets.toolbar), value);
336 }
337}
338
339
340GtkWidget *toolbar_init(void)
341{
342 GtkWidget *toolbar;
343 GtkAction *action_new;
344 GtkAction *action_open;
345 GtkAction *action_build;
346 GtkAction *action_searchentry;
347 GtkAction *action_gotoentry;
348 GtkSettings *gtk_settings;
349
350 uim = gtk_ui_manager_new();
351 group = gtk_action_group_new("GeanyToolbar");
352
353 gtk_action_group_set_translation_domain(group, GETTEXT_PACKAGE);
354 gtk_action_group_add_actions(group, ui_entries, ui_entries_n, NULL);
355
356 /* Create our custom actions */
357 action_new = geany_menu_button_action_new(
358 "New", NULL,
359 _("Create a new file"),
360 _("Create a new file from a template"),
361 GTK_STOCK_NEW);
362 g_signal_connect(action_new, "button-clicked", G_CALLBACK(on_new1_activate), NULL);
363 gtk_action_group_add_action(group, action_new);
364
365 action_open = geany_menu_button_action_new(
366 "Open", NULL,
367 _("Open an existing file"),
368 _("Open a recent file"),
369 GTK_STOCK_OPEN);
370 g_signal_connect(action_open, "button-clicked", G_CALLBACK(on_open1_activate), NULL);
371 gtk_action_group_add_action(group, action_open);
372
373 action_build = geany_menu_button_action_new(
374 "Build", NULL,
375 _("Build the current file"),
376 _("Choose more build actions"),
378 g_signal_connect(action_build, "button-clicked",
380 gtk_action_group_add_action(group, action_build);
381
382 action_searchentry = geany_entry_action_new(
383 "SearchEntry", _("Search Field"), _("Find the entered text in the current file"), FALSE);
384 g_signal_connect(action_searchentry, "entry-activate",
385 G_CALLBACK(on_toolbar_search_entry_activate), GINT_TO_POINTER(FALSE));
386 g_signal_connect(action_searchentry, "entry-activate-backward",
387 G_CALLBACK(on_toolbar_search_entry_activate), GINT_TO_POINTER(TRUE));
388 g_signal_connect(action_searchentry, "entry-changed",
390 gtk_action_group_add_action(group, action_searchentry);
391
392 action_gotoentry = geany_entry_action_new(
393 "GotoEntry", _("Goto Field"), _("Jump to the entered line number"), TRUE);
394 g_signal_connect(action_gotoentry, "entry-activate",
396 gtk_action_group_add_action(group, action_gotoentry);
397
398 gtk_ui_manager_insert_action_group(uim, group, 0);
399
400 toolbar = toolbar_reload(NULL);
401 gtk_style_context_add_class(gtk_widget_get_style_context(toolbar), "primary-toolbar");
402
403 gtk_settings = gtk_widget_get_settings(GTK_WIDGET(toolbar));
404 if (gtk_settings != NULL)
405 {
406 g_signal_connect(gtk_settings, "notify::gtk-toolbar-style",
407 G_CALLBACK(toolbar_notify_style_cb), NULL);
408 }
409
410 return toolbar;
411}
412
413
415{
416 static GtkWidget *hbox_menubar = NULL;
417 static GtkWidget *menubar = NULL;
418 GtkWidget *parent;
419 GtkToolItem *first_item;
420
421 if (menubar == NULL)
422 { /* cache widget pointers */
423 hbox_menubar = ui_lookup_widget(main_widgets.window, "hbox_menubar");
424 menubar = ui_lookup_widget(main_widgets.window, "menubar1");
425 }
426 /* the separator between the menubar and the toolbar */
427 first_item = gtk_toolbar_get_nth_item(GTK_TOOLBAR(main_widgets.toolbar), 0);
428 if (first_item != NULL && GTK_IS_SEPARATOR_TOOL_ITEM(first_item))
429 {
430 gtk_widget_destroy(GTK_WIDGET(first_item));
431 }
432
433 parent = gtk_widget_get_parent(main_widgets.toolbar);
434
436 {
437 GtkWidget *menubar_toolbar_separator;
438
439 if (parent != NULL)
440 {
441 if (parent != hbox_menubar)
442 { /* here we manually 'reparent' the toolbar, gtk_widget_reparent() doesn't
443 * like to do it */
444 g_object_ref(main_widgets.toolbar);
445
446 gtk_container_remove(GTK_CONTAINER(parent), main_widgets.toolbar);
447 gtk_box_pack_start(GTK_BOX(hbox_menubar), main_widgets.toolbar, TRUE, TRUE, 0);
448 gtk_box_reorder_child(GTK_BOX(hbox_menubar), main_widgets.toolbar, 1);
449
450 g_object_unref(main_widgets.toolbar);
451 }
452 }
453 else
454 gtk_box_pack_start(GTK_BOX(hbox_menubar), main_widgets.toolbar, TRUE, TRUE, 0);
455
456 /* the separator between the menubar and the toolbar */
457 menubar_toolbar_separator = GTK_WIDGET(gtk_separator_tool_item_new());
458 gtk_widget_show(menubar_toolbar_separator);
459 gtk_toolbar_insert(GTK_TOOLBAR(main_widgets.toolbar),
460 GTK_TOOL_ITEM(menubar_toolbar_separator), 0);
461 }
462 else
463 {
464 GtkWidget *box = ui_lookup_widget(main_widgets.window, "vbox1");
465
466 if (parent != NULL)
467 {
468 if (parent != box)
469 {
470 g_object_ref(main_widgets.toolbar);
471
472 gtk_container_remove(GTK_CONTAINER(parent), main_widgets.toolbar);
473 gtk_box_pack_start(GTK_BOX(box), main_widgets.toolbar, FALSE, FALSE, 0);
474 gtk_box_reorder_child(GTK_BOX(box), main_widgets.toolbar, 1);
475
476 g_object_unref(main_widgets.toolbar);
477 }
478 }
479 else
480 {
481 gtk_box_pack_start(GTK_BOX(box), main_widgets.toolbar, FALSE, FALSE, 0);
482 gtk_box_reorder_child(GTK_BOX(box), main_widgets.toolbar, 1);
483 }
484 }
485 /* we need to adjust the packing flags for the menubar to expand it if it is alone in the
486 * hbox and not expand it if the toolbar is appended */
487 gtk_box_set_child_packing(GTK_BOX(hbox_menubar), menubar,
488 ! (toolbar_prefs.visible && toolbar_prefs.append_to_menu), TRUE, 0, GTK_PACK_START);
489}
490
491
492/* Returns the position for adding new toolbar items. The returned position can be used
493 * to add new toolbar items with @c gtk_toolbar_insert(). The toolbar object can be accessed
494 * with @a geany->main_widgets->toolbar.
495 * The position is always the last one before the Quit button or the very last position if the
496 * Quit button is not the last toolbar item.
497 *
498 * @return The position for new toolbar items.
499 */
501{
502 GtkWidget *quit = toolbar_get_widget_by_name("Quit");
503 gint quit_pos = -1, pos;
504
505 if (quit != NULL)
506 quit_pos = gtk_toolbar_get_item_index(GTK_TOOLBAR(main_widgets.toolbar), GTK_TOOL_ITEM(quit));
507
508 pos = gtk_toolbar_get_n_items(GTK_TOOLBAR(main_widgets.toolbar));
509 if (quit_pos == (pos - 1))
510 {
511 /* if the toolbar item before the quit button is a separator, insert new items before */
512 if (GTK_IS_SEPARATOR_TOOL_ITEM(gtk_toolbar_get_nth_item(
513 GTK_TOOLBAR(main_widgets.toolbar), quit_pos - 1)))
514 {
515 return quit_pos - 1;
516 }
517 /* else return the position of the quit button to insert new items before */
518 return quit_pos;
519 }
520
521 return pos;
522}
523
524
526{
528 g_object_unref(geany_menu_button_action_get_menu(open_action));
530
531 /* unref'ing the GtkUIManager object will destroy all its widgets unless they were ref'ed */
532 g_object_unref(uim);
533 g_object_unref(group);
534
535 g_slist_free(plugin_items);
536}
537
538
540{
541 ignore_callback = TRUE;
542 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
543 ui_lookup_widget(main_widgets.window, "menu_show_toolbar1")), toolbar_prefs.visible);
545 ignore_callback = FALSE;
546}
547
548
549/* sets the icon style of the toolbar */
550static void toolbar_set_icon_style(void)
551{
552 gint icon_style;
553
554 icon_style = toolbar_prefs.icon_style;
555
557 icon_style = ui_get_gtk_settings_integer("gtk-toolbar-style", toolbar_prefs.icon_style);
558
559 gtk_toolbar_set_style(GTK_TOOLBAR(main_widgets.toolbar), icon_style);
560}
561
562
563/* sets the icon size of the toolbar */
564static void toolbar_set_icon_size(void)
565{
566 gint icon_size;
567
568 icon_size = toolbar_prefs.icon_size;
569
571 icon_size = ui_get_gtk_settings_integer("gtk-toolbar-icon-size", toolbar_prefs.icon_size);
572
573 gtk_toolbar_set_icon_size(GTK_TOOLBAR(main_widgets.toolbar), icon_size);
574}
575
576
578{
581}
582
583
584#define TB_EDITOR_SEPARATOR _("Separator")
585#define TB_EDITOR_SEPARATOR_LABEL _("--- Separator ---")
586typedef struct
587{
588 GtkWidget *dialog;
589
590 GtkTreeView *tree_available;
591 GtkTreeView *tree_used;
592
593 GtkListStore *store_available;
594 GtkListStore *store_used;
595
596 GtkTreePath *last_drag_path;
597 GtkTreeViewDropPosition last_drag_pos;
598
599 GtkWidget *drag_source;
601
602static const GtkTargetEntry tb_editor_dnd_targets[] =
603{
604 { "GEANY_TB_EDITOR_ROW", 0, 0 }
605};
606static const gint tb_editor_dnd_targets_len = G_N_ELEMENTS(tb_editor_dnd_targets);
607
608enum
609{
615
616static void tb_editor_handler_start_element(GMarkupParseContext *context, const gchar *element_name,
617 const gchar **attribute_names,
618 const gchar **attribute_values, gpointer data,
619 GError **error)
620{
621 gint i;
622 GSList **actions = data;
623
624 /* This is very basic parsing, stripped down any error checking, requires a valid UI markup. */
625 if (utils_str_equal(element_name, "separator"))
626 *actions = g_slist_append(*actions, g_strdup(TB_EDITOR_SEPARATOR));
627
628 for (i = 0; attribute_names[i] != NULL; i++)
629 {
630 if (utils_str_equal(attribute_names[i], "action"))
631 {
632 *actions = g_slist_append(*actions, g_strdup(attribute_values[i]));
633 }
634 }
635}
636
637
638static const GMarkupParser tb_editor_xml_parser =
639{
641};
642
643
644static GSList *tb_editor_parse_ui(const gchar *buffer, gssize length, GError **error)
645{
646 GMarkupParseContext *context;
647 GSList *list = NULL;
648
649 context = g_markup_parse_context_new(&tb_editor_xml_parser, 0, &list, NULL);
650 g_markup_parse_context_parse(context, buffer, length, error);
651 g_markup_parse_context_free(context);
652
653 return list;
654}
655
656
657static void tb_editor_set_item_values(const gchar *name, GtkListStore *store, GtkTreeIter *iter)
658{
659 gchar *icon = NULL;
660 gchar *label = NULL;
661 gchar *label_clean = NULL;
662 GtkAction *action;
663
664 action = gtk_action_group_get_action(group, name);
665 if (action == NULL)
666 {
668 label_clean = g_strdup(TB_EDITOR_SEPARATOR_LABEL);
669 else
670 return;
671 }
672 else
673 {
674 g_object_get(action, "icon-name", &icon, NULL);
675 if (icon == NULL)
676 g_object_get(action, "stock-id", &icon, NULL);
677
678 g_object_get(action, "label", &label, NULL);
679 if (label != NULL)
680 label_clean = utils_str_remove_chars(g_strdup(label), "_");
681 }
682
683 gtk_list_store_set(store, iter,
685 TB_EDITOR_COL_LABEL, label_clean,
686 TB_EDITOR_COL_ICON, icon,
687 -1);
688
689 g_free(icon);
690 g_free(label);
691 g_free(label_clean);
692}
693
694
695static void tb_editor_scroll_to_iter(GtkTreeView *treeview, GtkTreeIter *iter)
696{
697 GtkTreePath *path = gtk_tree_model_get_path(gtk_tree_view_get_model(treeview), iter);
698 gtk_tree_view_scroll_to_cell(treeview, path, NULL, TRUE, 0.5, 0.0);
699 gtk_tree_path_free(path);
700}
701
702
704{
705 if (tbw->last_drag_path != NULL)
706 {
707 gtk_tree_path_free(tbw->last_drag_path);
708 tbw->last_drag_path = NULL;
709 }
710}
711
712
713static void tb_editor_btn_remove_clicked_cb(GtkWidget *button, TBEditorWidget *tbw)
714{
715 GtkTreeModel *model_used;
716 GtkTreeSelection *selection_used;
717 GtkTreeIter iter_used, iter_new;
718 gchar *action_name;
719
720 selection_used = gtk_tree_view_get_selection(tbw->tree_used);
721 if (gtk_tree_selection_get_selected(selection_used, &model_used, &iter_used))
722 {
723 gtk_tree_model_get(model_used, &iter_used, TB_EDITOR_COL_ACTION, &action_name, -1);
724 if (gtk_list_store_remove(tbw->store_used, &iter_used))
725 gtk_tree_selection_select_iter(selection_used, &iter_used);
726
727 if (! utils_str_equal(action_name, TB_EDITOR_SEPARATOR))
728 {
729 gtk_list_store_append(tbw->store_available, &iter_new);
730 tb_editor_set_item_values(action_name, tbw->store_available, &iter_new);
732 }
733
734 g_free(action_name);
735 }
736}
737
738
739static void tb_editor_btn_add_clicked_cb(GtkWidget *button, TBEditorWidget *tbw)
740{
741 GtkTreeModel *model_available;
742 GtkTreeSelection *selection_available, *selection_used;
743 GtkTreeIter iter_available, iter_new, iter_selected;
744 gchar *action_name;
745
746 selection_available = gtk_tree_view_get_selection(tbw->tree_available);
747 if (gtk_tree_selection_get_selected(selection_available, &model_available, &iter_available))
748 {
749 gtk_tree_model_get(model_available, &iter_available,
750 TB_EDITOR_COL_ACTION, &action_name, -1);
751 if (! utils_str_equal(action_name, TB_EDITOR_SEPARATOR))
752 {
753 if (gtk_list_store_remove(tbw->store_available, &iter_available))
754 gtk_tree_selection_select_iter(selection_available, &iter_available);
755 }
756
757 selection_used = gtk_tree_view_get_selection(tbw->tree_used);
758 if (gtk_tree_selection_get_selected(selection_used, NULL, &iter_selected))
759 gtk_list_store_insert_before(tbw->store_used, &iter_new, &iter_selected);
760 else
761 gtk_list_store_append(tbw->store_used, &iter_new);
762
763 tb_editor_set_item_values(action_name, tbw->store_used, &iter_new);
764 tb_editor_scroll_to_iter(tbw->tree_used, &iter_new);
765
766 g_free(action_name);
767 }
768}
769
770
771static gboolean tb_editor_drag_motion_cb(GtkWidget *widget, GdkDragContext *drag_context,
772 gint x, gint y, guint ltime, TBEditorWidget *tbw)
773{
774 if (tbw->last_drag_path != NULL)
775 gtk_tree_path_free(tbw->last_drag_path);
776 gtk_tree_view_get_drag_dest_row(GTK_TREE_VIEW(widget),
777 &(tbw->last_drag_path), &(tbw->last_drag_pos));
778
779 return FALSE;
780}
781
782
783static void tb_editor_drag_data_get_cb(GtkWidget *widget, GdkDragContext *context,
784 GtkSelectionData *data, guint info, guint ltime,
785 TBEditorWidget *tbw)
786{
787 GtkTreeIter iter;
788 GtkTreeSelection *selection;
789 GtkTreeModel *model;
790 GdkAtom atom;
791 gchar *name;
792
793 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
794 if (! gtk_tree_selection_get_selected(selection, &model, &iter))
795 return;
796
797 gtk_tree_model_get(model, &iter, TB_EDITOR_COL_ACTION, &name, -1);
798 if (G_UNLIKELY(EMPTY(name)))
799 {
800 g_free(name);
801 return;
802 }
803
804 atom = gdk_atom_intern(tb_editor_dnd_targets[0].target, FALSE);
805 gtk_selection_data_set(data, atom, 8, (guchar*) name, strlen(name));
806
807 g_free(name);
808
809 tbw->drag_source = widget;
810}
811
812
813static void tb_editor_drag_data_rcvd_cb(GtkWidget *widget, GdkDragContext *context,
814 gint x, gint y, GtkSelectionData *data, guint info,
815 guint ltime, TBEditorWidget *tbw)
816{
817 GtkTreeView *tree = GTK_TREE_VIEW(widget);
818 gboolean del = FALSE;
819
820 if (gtk_selection_data_get_length(data) >= 0 && gtk_selection_data_get_format(data) == 8)
821 {
822 gboolean is_sep;
823 gchar *text = NULL;
824
825 text = (gchar*) gtk_selection_data_get_data(data);
827 /* If the source of the action is equal to the target, we do just re-order and so need
828 * to delete the separator to get it moved, not just copied. */
829 if (is_sep && widget == tbw->drag_source)
830 is_sep = FALSE;
831
832 if (tree != tbw->tree_available || ! is_sep)
833 {
834 GtkTreeIter iter, iter_before, *iter_before_ptr;
835 GtkListStore *store = GTK_LIST_STORE(gtk_tree_view_get_model(tree));
836
837 if (tbw->last_drag_path != NULL)
838 {
839 gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter_before, tbw->last_drag_path);
840
841 if (gtk_list_store_iter_is_valid(store, &iter_before))
842 iter_before_ptr = &iter_before;
843 else
844 iter_before_ptr = NULL;
845
846 if (tbw->last_drag_pos == GTK_TREE_VIEW_DROP_BEFORE ||
847 tbw->last_drag_pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)
848 gtk_list_store_insert_before(store, &iter, iter_before_ptr);
849 else
850 gtk_list_store_insert_after(store, &iter, iter_before_ptr);
851 }
852 else
853 gtk_list_store_append(store, &iter);
854
855 tb_editor_set_item_values(text, store, &iter);
856 tb_editor_scroll_to_iter(tree, &iter);
857 }
858 if (tree != tbw->tree_used || ! is_sep)
859 del = TRUE;
860 }
861
862 tbw->drag_source = NULL; /* reset the value just to be sure */
864 gtk_drag_finish(context, TRUE, del, ltime);
865}
866
867
868static gboolean tb_editor_foreach_used(GtkTreeModel *model, GtkTreePath *path,
869 GtkTreeIter *iter, gpointer data)
870{
871 gchar *action_name;
872
873 gtk_tree_model_get(model, iter, TB_EDITOR_COL_ACTION, &action_name, -1);
874
875 if (utils_str_equal(action_name, TB_EDITOR_SEPARATOR))
876 g_string_append_printf(data, "\t\t<separator/>\n");
877 else if (G_LIKELY(!EMPTY(action_name)))
878 g_string_append_printf(data, "\t\t<toolitem action='%s' />\n", action_name);
879
880 g_free(action_name);
881 return FALSE;
882}
883
884
886{
887 /* <ui> must be the first tag, otherwise gtk_ui_manager_add_ui_from_string() will fail. */
888 const gchar *template = "<ui>\n<!--\n\
889This is Geany's toolbar UI definition.\nThe DTD can be found at \n\
890http://library.gnome.org/devel/gtk/stable/GtkUIManager.html#GtkUIManager.description.\n\n\
891You can re-order all items and freely add and remove available actions.\n\
892You cannot add new actions which are not listed in the documentation.\n\
893Everything you add or change must be inside the /ui/toolbar/ path.\n\n\
894For changes to take effect, you need to restart Geany. Alternatively you can use the toolbar\n\
895editor in Geany.\n\n\
896A list of available actions can be found in the documentation included with Geany or\n\
897at https://www.geany.org/manual/current/index.html#customizing-the-toolbar.\n-->\n\
898\t<toolbar name='GeanyToolbar'>\n";
899 gchar *filename;
900 GString *str = g_string_new(template);
901
902 gtk_tree_model_foreach(GTK_TREE_MODEL(tbw->store_used), tb_editor_foreach_used, str);
903
904 g_string_append(str, "\n\t</toolbar>\n</ui>\n");
905
906 toolbar_reload(str->str);
907
908 filename = g_build_filename(app->configdir, "ui_toolbar.xml", NULL);
909 utils_write_file(filename, str->str);
910 g_free(filename);
911
912 g_string_free(str, TRUE);
913}
914
915
916static void tb_editor_available_items_changed_cb(GtkTreeModel *model, GtkTreePath *arg1,
917 GtkTreeIter *arg2, TBEditorWidget *tbw)
918{
920}
921
922
923static void tb_editor_available_items_deleted_cb(GtkTreeModel *model, GtkTreePath *arg1,
924 TBEditorWidget *tbw)
925{
927}
928
929
930static TBEditorWidget *tb_editor_create_dialog(GtkWindow *parent)
931{
932 GtkWidget *dialog, *vbox, *hbox, *vbox_buttons, *button_add, *button_remove;
933 GtkWidget *swin_available, *swin_used, *tree_available, *tree_used, *label;
934 GtkCellRenderer *text_renderer, *icon_renderer;
935 GtkTreeViewColumn *column;
936 TBEditorWidget *tbw = g_new(TBEditorWidget, 1);
937
938 if (parent == NULL)
939 parent = GTK_WINDOW(main_widgets.window);
940
941 dialog = gtk_dialog_new_with_buttons(_("Customize Toolbar"),
942 parent,
943 GTK_DIALOG_DESTROY_WITH_PARENT,
944 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
945 vbox = ui_dialog_vbox_new(GTK_DIALOG(dialog));
946 gtk_box_set_spacing(GTK_BOX(vbox), 6);
947 gtk_widget_set_name(dialog, "GeanyDialog");
948 gtk_window_set_default_size(GTK_WINDOW(dialog), -1, 400);
949 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE);
950
951 tbw->store_available = gtk_list_store_new(TB_EDITOR_COLS_MAX,
952 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
953 tbw->store_used = gtk_list_store_new(TB_EDITOR_COLS_MAX,
954 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
955
956 label = gtk_label_new(
957 _("Select items to be displayed on the toolbar. Items can be reordered by drag and drop."));
958 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
959
960 tree_available = gtk_tree_view_new();
961 gtk_tree_view_set_model(GTK_TREE_VIEW(tree_available), GTK_TREE_MODEL(tbw->store_available));
962 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree_available), TRUE);
963 gtk_tree_sortable_set_sort_column_id(
964 GTK_TREE_SORTABLE(tbw->store_available), TB_EDITOR_COL_LABEL, GTK_SORT_ASCENDING);
965
966 icon_renderer = gtk_cell_renderer_pixbuf_new();
967 column = gtk_tree_view_column_new_with_attributes(
968 NULL, icon_renderer, "stock-id", TB_EDITOR_COL_ICON, NULL);
969 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_available), column);
970
971 text_renderer = gtk_cell_renderer_text_new();
972 column = gtk_tree_view_column_new_with_attributes(
973 _("Available Items"), text_renderer, "text", TB_EDITOR_COL_LABEL, NULL);
974 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_available), column);
975
976 swin_available = gtk_scrolled_window_new(NULL, NULL);
977 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin_available),
978 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
979 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(swin_available), GTK_SHADOW_IN);
980 gtk_container_add(GTK_CONTAINER(swin_available), tree_available);
981
982 tree_used = gtk_tree_view_new();
983 gtk_tree_view_set_model(GTK_TREE_VIEW(tree_used), GTK_TREE_MODEL(tbw->store_used));
984 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree_used), TRUE);
985 gtk_tree_view_set_reorderable(GTK_TREE_VIEW(tree_used), TRUE);
986
987 icon_renderer = gtk_cell_renderer_pixbuf_new();
988 column = gtk_tree_view_column_new_with_attributes(
989 NULL, icon_renderer, "stock-id", TB_EDITOR_COL_ICON, NULL);
990 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_used), column);
991
992 text_renderer = gtk_cell_renderer_text_new();
993 column = gtk_tree_view_column_new_with_attributes(
994 _("Displayed Items"), text_renderer, "text", TB_EDITOR_COL_LABEL, NULL);
995 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_used), column);
996
997 swin_used = gtk_scrolled_window_new(NULL, NULL);
998 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin_used),
999 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1000 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(swin_used), GTK_SHADOW_IN);
1001 gtk_container_add(GTK_CONTAINER(swin_used), tree_used);
1002
1003 /* drag'n'drop */
1004 gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(tree_available), GDK_BUTTON1_MASK,
1006 gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(tree_available),
1008 g_signal_connect(tree_available, "drag-data-get",
1009 G_CALLBACK(tb_editor_drag_data_get_cb), tbw);
1010 g_signal_connect(tree_available, "drag-data-received",
1011 G_CALLBACK(tb_editor_drag_data_rcvd_cb), tbw);
1012 g_signal_connect(tree_available, "drag-motion",
1013 G_CALLBACK(tb_editor_drag_motion_cb), tbw);
1014
1015 gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(tree_used), GDK_BUTTON1_MASK,
1017 gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(tree_used),
1019 g_signal_connect(tree_used, "drag-data-get",
1020 G_CALLBACK(tb_editor_drag_data_get_cb), tbw);
1021 g_signal_connect(tree_used, "drag-data-received",
1022 G_CALLBACK(tb_editor_drag_data_rcvd_cb), tbw);
1023 g_signal_connect(tree_used, "drag-motion",
1024 G_CALLBACK(tb_editor_drag_motion_cb), tbw);
1025
1026
1027 button_add = ui_button_new_with_image(GTK_STOCK_GO_FORWARD, NULL);
1028 button_remove = ui_button_new_with_image(GTK_STOCK_GO_BACK, NULL);
1029 g_signal_connect(button_add, "clicked", G_CALLBACK(tb_editor_btn_add_clicked_cb), tbw);
1030 g_signal_connect(button_remove, "clicked", G_CALLBACK(tb_editor_btn_remove_clicked_cb), tbw);
1031
1032 vbox_buttons = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
1033 /* FIXME this is a little hack'ish, any better ideas? */
1034 gtk_box_pack_start(GTK_BOX(vbox_buttons), gtk_label_new(""), TRUE, TRUE, 0);
1035 gtk_box_pack_start(GTK_BOX(vbox_buttons), button_add, FALSE, FALSE, 0);
1036 gtk_box_pack_start(GTK_BOX(vbox_buttons), button_remove, FALSE, FALSE, 0);
1037 gtk_box_pack_start(GTK_BOX(vbox_buttons), gtk_label_new(""), TRUE, TRUE, 0);
1038
1039 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
1040 gtk_box_pack_start(GTK_BOX(hbox), swin_available, TRUE, TRUE, 0);
1041 gtk_box_pack_start(GTK_BOX(hbox), vbox_buttons, FALSE, FALSE, 0);
1042 gtk_box_pack_start(GTK_BOX(hbox), swin_used, TRUE, TRUE, 0);
1043
1044 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 6);
1045 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
1046
1047 gtk_widget_show_all(vbox);
1048
1049 g_object_unref(tbw->store_available);
1050 g_object_unref(tbw->store_used);
1051
1052 tbw->dialog = dialog;
1053 tbw->tree_available = GTK_TREE_VIEW(tree_available);
1054 tbw->tree_used = GTK_TREE_VIEW(tree_used);
1055
1056 tbw->last_drag_path = NULL;
1057
1058 return tbw;
1059}
1060
1061
1062void toolbar_configure(GtkWindow *parent)
1063{
1064 gchar *markup;
1065 GSList *sl, *used_items;
1066 GList *l, *all_items;
1067 GtkTreePath *path;
1068 TBEditorWidget *tbw;
1069
1070 /* read the current active toolbar items */
1071 markup = gtk_ui_manager_get_ui(uim);
1072 used_items = tb_editor_parse_ui(markup, -1, NULL);
1073 g_free(markup);
1074
1075 /* get all available actions */
1076 all_items = gtk_action_group_list_actions(group);
1077
1078 /* create the GUI */
1079 tbw = tb_editor_create_dialog(parent);
1080
1081 /* fill the stores */
1082 gtk_list_store_insert_with_values(tbw->store_available, NULL, -1,
1085 -1);
1086 foreach_list(l, all_items)
1087 {
1088 const gchar *name = gtk_action_get_name(l->data);
1089
1090 if (g_slist_find_custom(used_items, name, (GCompareFunc) strcmp) == NULL)
1091 {
1092 GtkTreeIter iter;
1093
1094 gtk_list_store_append(tbw->store_available, &iter);
1096 }
1097 }
1098 foreach_slist(sl, used_items)
1099 {
1100 GtkTreeIter iter;
1101
1102 gtk_list_store_append(tbw->store_used, &iter);
1103 tb_editor_set_item_values(sl->data, tbw->store_used, &iter);
1104 }
1105 /* select first item */
1106 path = gtk_tree_path_new_from_string("0");
1107 gtk_tree_selection_select_path(gtk_tree_view_get_selection(tbw->tree_used), path);
1108 gtk_tree_path_free(path);
1109
1110 /* connect the changed signals after populating the store */
1111 g_signal_connect(tbw->store_used, "row-changed",
1112 G_CALLBACK(tb_editor_available_items_changed_cb), tbw);
1113 g_signal_connect(tbw->store_used, "row-deleted",
1114 G_CALLBACK(tb_editor_available_items_deleted_cb), tbw);
1115
1116 /* run it */
1117 gtk_dialog_run(GTK_DIALOG(tbw->dialog));
1118
1119 gtk_widget_destroy(tbw->dialog);
1120
1121 g_slist_foreach(used_items, (GFunc) g_free, NULL);
1122 g_slist_free(used_items);
1123 g_list_free(all_items);
1125 g_free(tbw);
1126}
Contains the GeanyApp.
void build_toolbutton_build_clicked(GtkAction *action, gpointer unused)
Definition: build.c:1705
const gchar * label
Definition: build.c:2676
Interface to the Build menu functionality.
void on_replace1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:902
void on_save_all1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:125
void on_delete1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:291
void on_menu_increase_indent1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:1331
gboolean on_escape_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
Definition: callbacks.c:1674
void on_paste1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:273
void on_zoom_in1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:449
void on_toolbutton_forward_activate(GtkAction *menuitem, gpointer user_data)
Definition: callbacks.c:1600
void on_toolbutton_back_activate(GtkAction *menuitem, gpointer user_data)
Definition: callbacks.c:1606
void on_toolbutton_run_clicked(GtkAction *action, gpointer user_data)
Definition: callbacks.c:1204
void on_show_color_chooser1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:848
void on_save1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:108
gboolean toolbar_popup_menu(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
Definition: callbacks.c:586
void on_undo1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:211
void on_close_all1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:153
void on_copy1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:256
void on_open1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:322
void on_cut1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:239
void on_toolbutton_goto_clicked(GtkAction *action, gpointer user_data)
Definition: callbacks.c:972
void on_new1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:92
void on_zoom_out1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:460
void on_preferences1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:308
void on_redo1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:225
void on_toolbar_search_entry_activate(GtkAction *action, const gchar *text, gpointer user_data)
Definition: callbacks.c:413
void on_menu_decrease_indent1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:1340
void on_save_as1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:119
void on_toolbutton_compile_clicked(GtkAction *action, gpointer user_data)
Definition: callbacks.c:862
void on_toolbutton_search_clicked(GtkAction *action, gpointer user_data)
Definition: callbacks.c:420
gboolean on_motion_event(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
Definition: callbacks.c:1612
void on_quit1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:168
void on_toolbutton_reload_clicked(GtkAction *action, gpointer user_data)
Definition: callbacks.c:329
void on_print1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:1219
void on_close1_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: callbacks.c:159
void on_toolbar_search_entry_changed(GtkAction *action, const gchar *text, gpointer user_data)
Definition: callbacks.c:406
void on_toolbutton_goto_entry_activate(GtkAction *action, const gchar *text, gpointer user_data)
Definition: callbacks.c:956
gboolean ignore_callback
Definition: libmain.c:87
GeanyDocument * document_get_current(void)
Finds the current document.
Definition: document.c:371
const gchar * name
Definition: document.c:3219
Document related actions: new, save, open, etc.
gchar * text
Definition: editor.c:83
gint pos
Definition: editor.c:87
void error(const errorSelection selection, const char *const format,...)
Definition: error.c:53
tokenInfo * list
GtkAction * geany_entry_action_new(const gchar *name, const gchar *label, const gchar *tooltip, gboolean numeric)
GtkAction * geany_menu_button_action_new(const gchar *name, const gchar *label, const gchar *tooltip, const gchar *tooltip_arrow, const gchar *stock_id)
GtkWidget * geany_menu_button_action_get_menu(GeanyMenubuttonAction *action)
void geany_menu_button_action_set_menu(GeanyMenubuttonAction *action, GtkWidget *menu)
#define GEANY_MENU_BUTTON_ACTION(obj)
GeanyApp * app
Definition: libmain.c:86
GeanyStatus main_status
Definition: libmain.c:89
void geany_debug(gchar const *format,...)
Definition: log.c:67
Main program-related commands.
#define NULL
Definition: rbtree.h:150
GtkWidget * entry
Definition: search.c:118
const gchar filename[]
Definition: stash-example.c:4
GtkWidget * dialog
gtk_container_add(GTK_CONTAINER(dialog->vbox), check_button)
gtk_widget_show_all(dialog)
gchar * configdir
User configuration directory, usually ~/.config/geany.
Definition: app.h:45
gchar * datadir
Definition: app.h:46
Structure for representing an open tab with all its properties.
Definition: document.h:81
gboolean changed
Whether this document has been changed since it was last saved.
Definition: document.h:107
GtkWidget * window
Main window.
Definition: ui_utils.h:80
GtkWidget * toolbar
Main toolbar.
Definition: ui_utils.h:81
Toolbar settings.
Definition: toolbar.h:30
GtkToolbarStyle icon_style
Icon style.
Definition: toolbar.h:33
gboolean visible
Definition: toolbar.h:31
gboolean use_gtk_default_icon
Definition: toolbar.h:35
gboolean use_gtk_default_style
Definition: toolbar.h:34
gboolean append_to_menu
Definition: toolbar.h:36
GtkIconSize icon_size
Definition: toolbar.h:32
GtkWidget * drag_source
Definition: toolbar.c:599
GtkListStore * store_used
Definition: toolbar.c:594
GtkListStore * store_available
Definition: toolbar.c:593
GtkTreeView * tree_used
Definition: toolbar.c:591
GtkTreePath * last_drag_path
Definition: toolbar.c:596
GtkWidget * dialog
Definition: toolbar.c:588
GtkTreeViewDropPosition last_drag_pos
Definition: toolbar.c:597
GtkTreeView * tree_available
Definition: toolbar.c:590
Defines internationalization macros.
#define _(String)
Definition: support.h:42
#define N_(String)
Definition: support.h:43
#define GETTEXT_PACKAGE
Definition: support.h:37
void toolbar_show_hide(void)
Definition: toolbar.c:539
static const GtkActionEntry ui_entries[]
Definition: toolbar.c:55
static const GtkTargetEntry tb_editor_dnd_targets[]
Definition: toolbar.c:602
static void tb_editor_handler_start_element(GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer data, GError **error)
Definition: toolbar.c:616
#define TB_EDITOR_SEPARATOR_LABEL
Definition: toolbar.c:585
static void tb_editor_drag_data_get_cb(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *data, guint info, guint ltime, TBEditorWidget *tbw)
Definition: toolbar.c:783
GtkWidget * toolbar_get_widget_by_name(const gchar *name)
Definition: toolbar.c:124
static void tb_editor_available_items_changed_cb(GtkTreeModel *model, GtkTreePath *arg1, GtkTreeIter *arg2, TBEditorWidget *tbw)
Definition: toolbar.c:916
@ TB_EDITOR_COL_ACTION
Definition: toolbar.c:610
@ TB_EDITOR_COLS_MAX
Definition: toolbar.c:613
@ TB_EDITOR_COL_ICON
Definition: toolbar.c:612
@ TB_EDITOR_COL_LABEL
Definition: toolbar.c:611
GeanyToolbarPrefs toolbar_prefs
Definition: toolbar.c:48
#define TB_EDITOR_SEPARATOR
Definition: toolbar.c:584
static GSList * plugin_items
Definition: toolbar.c:51
static void tb_editor_scroll_to_iter(GtkTreeView *treeview, GtkTreeIter *iter)
Definition: toolbar.c:695
static GtkWidget * toolbar_reload(const gchar *markup)
Definition: toolbar.c:175
static const GMarkupParser tb_editor_xml_parser
Definition: toolbar.c:638
static gboolean tb_editor_foreach_used(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
Definition: toolbar.c:868
void toolbar_configure(GtkWindow *parent)
Definition: toolbar.c:1062
static void tb_editor_available_items_deleted_cb(GtkTreeModel *model, GtkTreePath *arg1, TBEditorWidget *tbw)
Definition: toolbar.c:923
static void toolbar_notify_style_cb(GObject *object, GParamSpec *arg1, gpointer data)
Definition: toolbar.c:322
static const gint tb_editor_dnd_targets_len
Definition: toolbar.c:606
void toolbar_finalize(void)
Definition: toolbar.c:525
static GSList * tb_editor_parse_ui(const gchar *buffer, gssize length, GError **error)
Definition: toolbar.c:644
static const gchar * toolbar_markup
Definition: toolbar.c:89
static GtkUIManager * uim
Definition: toolbar.c:49
static void toolbar_set_icon_size(void)
Definition: toolbar.c:564
static gboolean tb_editor_drag_motion_cb(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, guint ltime, TBEditorWidget *tbw)
Definition: toolbar.c:771
static void toolbar_item_destroy_cb(GtkWidget *widget, G_GNUC_UNUSED gpointer data)
Definition: toolbar.c:160
static void tb_editor_btn_add_clicked_cb(GtkWidget *button, TBEditorWidget *tbw)
Definition: toolbar.c:739
static void tb_editor_write_markup(TBEditorWidget *tbw)
Definition: toolbar.c:885
static void tb_editor_set_item_values(const gchar *name, GtkListStore *store, GtkTreeIter *iter)
Definition: toolbar.c:657
static const guint ui_entries_n
Definition: toolbar.c:85
GtkWidget * toolbar_get_widget_child_by_name(const gchar *name)
Definition: toolbar.c:141
void toolbar_item_ref(GtkToolItem *item)
Definition: toolbar.c:166
static TBEditorWidget * tb_editor_create_dialog(GtkWindow *parent)
Definition: toolbar.c:930
static GtkActionGroup * group
Definition: toolbar.c:50
static void toolbar_set_icon_style(void)
Definition: toolbar.c:550
static void tb_editor_free_path(TBEditorWidget *tbw)
Definition: toolbar.c:703
void toolbar_update_ui(void)
Definition: toolbar.c:414
static void tb_editor_btn_remove_clicked_cb(GtkWidget *button, TBEditorWidget *tbw)
Definition: toolbar.c:713
gint toolbar_get_insert_position(void)
Definition: toolbar.c:500
static void tb_editor_drag_data_rcvd_cb(GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint info, guint ltime, TBEditorWidget *tbw)
Definition: toolbar.c:813
GtkAction * toolbar_get_action_by_name(const gchar *name)
Definition: toolbar.c:152
GtkWidget * toolbar_init(void)
Definition: toolbar.c:340
void toolbar_apply_settings(void)
Definition: toolbar.c:577
Toolbar (prefs).
void ui_init_toolbar_widgets(void)
Definition: ui_utils.c:2232
void ui_widget_show_hide(GtkWidget *widget, gboolean show)
Definition: ui_utils.c:987
gint ui_get_gtk_settings_integer(const gchar *property_name, gint default_value)
Reads an integer from the GTK default settings registry (see http://library.gnome....
Definition: ui_utils.c:3022
GtkWidget * ui_dialog_vbox_new(GtkDialog *dialog)
Makes a fixed border for dialogs without increasing the button box border.
Definition: ui_utils.c:1499
void ui_save_buttons_toggle(gboolean enable)
Definition: ui_utils.c:830
GeanyMainWidgets main_widgets
Definition: ui_utils.c:72
void ui_document_buttons_update(void)
Definition: ui_utils.c:946
GtkWidget * ui_button_new_with_image(const gchar *stock_id, const gchar *text)
Creates a GtkButton with custom text and a stock image similar to gtk_button_new_from_stock().
Definition: ui_utils.c:1552
GtkWidget * ui_lookup_widget(GtkWidget *widget, const gchar *widget_name)
Returns a widget from a name in a component, usually created by Glade.
Definition: ui_utils.c:2743
void ui_update_popup_reundo_items(GeanyDocument *doc)
Definition: ui_utils.c:453
User Interface general utility functions.
#define GEANY_STOCK_CLOSE_ALL
Definition: ui_utils.h:97
#define GEANY_STOCK_SAVE_ALL
Definition: ui_utils.h:96
#define GEANY_STOCK_BUILD
Definition: ui_utils.h:98
gint utils_write_file(const gchar *filename, const gchar *text)
Writes text into a file named filename.
Definition: utils.c:209
gchar * utils_str_remove_chars(gchar *string, const gchar *chars)
Removes characters from a string, in place.
Definition: utils.c:1847
gboolean utils_str_equal(const gchar *a, const gchar *b)
NULL-safe string comparison.
Definition: utils.c:599
General utility functions, non-GTK related.
#define foreach_slist(node, list)
Iterates all the nodes in list.
Definition: utils.h:121
#define foreach_list(node, list)
Iterates all the nodes in list.
Definition: utils.h:115
#define SETPTR(ptr, result)
Assigns result to ptr, then frees the old value.
Definition: utils.h:50
#define EMPTY(ptr)
Returns TRUE if ptr is NULL or *ptr is FALSE.
Definition: utils.h:38