2008-12-06 11:10:06 +00:00
/*
* toolbar . c - this file is part of Geany , a fast and lightweight IDE
*
2011-01-19 19:39:09 +00:00
* Copyright 2009 - 2011 Enrico Tröger < enrico ( dot ) troeger ( at ) uvena ( dot ) de >
* Copyright 2009 - 2011 Nick Treleaven < nick ( dot ) treleaven ( at ) btinternet ( dot ) com >
2008-12-06 11:10:06 +00:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
2010-03-18 13:13:11 +00:00
/**
* @ file toolbar . h
* Toolbar ( prefs ) .
2008-12-06 11:10:06 +00:00
*/
2010-03-18 13:13:11 +00:00
/* Utility functions to create the toolbar */
2008-12-06 11:10:06 +00:00
# include "geany.h"
# include "support.h"
# include "ui_utils.h"
# include "toolbar.h"
# include "callbacks.h"
# include "utils.h"
# include "dialogs.h"
2008-12-06 12:28:21 +00:00
# include "document.h"
2009-01-17 17:59:20 +00:00
# include "build.h"
2009-06-20 16:51:32 +00:00
# include "main.h"
2008-12-06 11:10:06 +00:00
# include "geanymenubuttonaction.h"
# include "geanyentryaction.h"
2009-06-28 10:42:46 +00:00
# include <string.h>
2009-06-25 17:21:45 +00:00
# include <glib/gstdio.h>
2008-12-06 11:10:06 +00:00
GeanyToolbarPrefs toolbar_prefs ;
static GtkUIManager * uim ;
static GtkActionGroup * group ;
2009-06-20 16:51:32 +00:00
static GSList * plugin_items = NULL ;
2008-12-06 11:10:06 +00:00
/* Available toolbar actions
* Fields : name , stock_id , label , accelerator , tooltip , callback */
const GtkActionEntry ui_entries [ ] = {
2009-06-20 16:51:32 +00:00
/* custom actions defined in toolbar_init(): "New", "Open", "SearchEntry", "GotoEntry", "Build" */
2008-12-06 11:10:06 +00:00
{ " Save " , GTK_STOCK_SAVE , NULL , NULL , N_ ( " Save the current file " ) , G_CALLBACK ( on_toolbutton_save_clicked ) } ,
2011-01-10 13:35:29 +00:00
{ " SaveAs " , GTK_STOCK_SAVE_AS , NULL , NULL , N_ ( " Save as " ) , G_CALLBACK ( on_save_as1_activate ) } ,
2009-07-18 14:44:51 +00:00
{ " SaveAll " , GEANY_STOCK_SAVE_ALL , NULL , NULL , N_ ( " Save all open files " ) , G_CALLBACK ( on_save_all1_activate ) } ,
2008-12-06 11:10:06 +00:00
{ " Reload " , GTK_STOCK_REVERT_TO_SAVED , NULL , NULL , N_ ( " Reload the current file from disk " ) , G_CALLBACK ( on_toolbutton_reload_clicked ) } ,
{ " Close " , GTK_STOCK_CLOSE , NULL , NULL , N_ ( " Close the current file " ) , G_CALLBACK ( on_toolbutton_close_clicked ) } ,
2008-12-09 20:31:38 +00:00
{ " CloseAll " , GEANY_STOCK_CLOSE_ALL , NULL , NULL , N_ ( " Close all open files " ) , G_CALLBACK ( on_toolbutton_close_all_clicked ) } ,
2008-12-06 11:10:06 +00:00
{ " Cut " , GTK_STOCK_CUT , NULL , NULL , N_ ( " Cut the current selection " ) , G_CALLBACK ( on_cut1_activate ) } ,
{ " Copy " , GTK_STOCK_COPY , NULL , NULL , N_ ( " Copy the current selection " ) , G_CALLBACK ( on_copy1_activate ) } ,
{ " Paste " , GTK_STOCK_PASTE , NULL , NULL , N_ ( " Paste the contents of the clipboard " ) , G_CALLBACK ( on_paste1_activate ) } ,
{ " Delete " , GTK_STOCK_DELETE , NULL , NULL , N_ ( " Delete the current selection " ) , G_CALLBACK ( on_delete1_activate ) } ,
{ " Undo " , GTK_STOCK_UNDO , NULL , NULL , N_ ( " Undo the last modification " ) , G_CALLBACK ( on_undo1_activate ) } ,
{ " Redo " , GTK_STOCK_REDO , NULL , NULL , N_ ( " Redo the last modification " ) , G_CALLBACK ( on_redo1_activate ) } ,
{ " NavBack " , GTK_STOCK_GO_BACK , NULL , NULL , N_ ( " Navigate back a location " ) , G_CALLBACK ( on_back_activate ) } ,
{ " NavFor " , GTK_STOCK_GO_FORWARD , NULL , NULL , N_ ( " Navigate forward a location " ) , G_CALLBACK ( on_forward_activate ) } ,
{ " Compile " , GTK_STOCK_CONVERT , N_ ( " Compile " ) , NULL , N_ ( " Compile the current file " ) , G_CALLBACK ( on_toolbutton_compile_clicked ) } ,
{ " Run " , GTK_STOCK_EXECUTE , NULL , NULL , N_ ( " Run or view the current file " ) , G_CALLBACK ( on_toolbutton_run_clicked ) } ,
{ " 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 ) } ,
{ " ZoomIn " , GTK_STOCK_ZOOM_IN , NULL , NULL , N_ ( " Zoom in the text " ) , G_CALLBACK ( on_zoom_in1_activate ) } ,
{ " ZoomOut " , GTK_STOCK_ZOOM_OUT , NULL , NULL , N_ ( " Zoom out the text " ) , G_CALLBACK ( on_zoom_out1_activate ) } ,
{ " UnIndent " , GTK_STOCK_UNINDENT , NULL , NULL , N_ ( " Decrease indentation " ) , G_CALLBACK ( on_menu_decrease_indent1_activate ) } ,
{ " Indent " , GTK_STOCK_INDENT , NULL , NULL , N_ ( " Increase indentation " ) , G_CALLBACK ( on_menu_increase_indent1_activate ) } ,
{ " Search " , GTK_STOCK_FIND , NULL , NULL , N_ ( " Find the entered text in the current file " ) , G_CALLBACK ( on_toolbutton_search_clicked ) } ,
{ " Goto " , GTK_STOCK_JUMP_TO , NULL , NULL , N_ ( " Jump to the entered line number " ) , G_CALLBACK ( on_toolbutton_goto_clicked ) } ,
2008-12-09 20:31:38 +00:00
{ " Preferences " , GTK_STOCK_PREFERENCES , NULL , NULL , N_ ( " Show the preferences dialog " ) , G_CALLBACK ( on_toolbutton_preferences_clicked ) } ,
2008-12-06 11:10:06 +00:00
{ " Quit " , GTK_STOCK_QUIT , NULL , NULL , N_ ( " Quit Geany " ) , G_CALLBACK ( on_toolbutton_quit_clicked ) } ,
2009-05-30 14:09:55 +00:00
{ " Print " , GTK_STOCK_PRINT , NULL , NULL , N_ ( " Print document " ) , G_CALLBACK ( on_print1_activate ) } ,
{ " Replace " , GTK_STOCK_FIND_AND_REPLACE , NULL , NULL , N_ ( " Replace text in the current document " ) , G_CALLBACK ( on_replace1_activate ) }
2008-12-06 11:10:06 +00:00
} ;
const guint ui_entries_n = G_N_ELEMENTS ( ui_entries ) ;
/* fallback UI definition */
const gchar * toolbar_markup =
" <ui> "
" <toolbar name='GeanyToolbar'> "
" <toolitem action='New'/> "
" <toolitem action='Open'/> "
" <toolitem action='Save'/> "
" <toolitem action='SaveAll'/> "
" <separator/> "
" <toolitem action='Reload'/> "
" <toolitem action='Close'/> "
" <separator/> "
" <toolitem action='NavBack'/> "
" <toolitem action='NavFor'/> "
" <separator/> "
" <toolitem action='Compile'/> "
2009-06-24 18:42:28 +00:00
" <toolitem action='Build'/> "
2008-12-06 11:10:06 +00:00
" <toolitem action='Run'/> "
" <separator/> "
" <toolitem action='Color'/> "
" <separator/> "
" <toolitem action='SearchEntry'/> "
" <toolitem action='Search'/> "
" <separator/> "
" <toolitem action='GotoEntry'/> "
" <toolitem action='Goto'/> "
" <separator/> "
" <toolitem action='Quit'/> "
" </toolbar> "
" </ui> " ;
2009-06-20 16:51:32 +00:00
/* Note: The returned widget pointer is only valid until the toolbar is reloaded. So, either
* update the widget pointer in this case ( i . e . request it again ) or better use
* toolbar_get_action_by_name ( ) instead . The action objects will remain the same even when the
* toolbar is reloaded . */
2008-12-06 11:10:06 +00:00
GtkWidget * toolbar_get_widget_by_name ( const gchar * name )
{
GtkWidget * widget ;
gchar * path ;
2009-04-15 22:47:33 +00:00
g_return_val_if_fail ( name ! = NULL , NULL ) ;
2008-12-06 11:10:06 +00:00
path = g_strconcat ( " /ui/GeanyToolbar/ " , name , NULL ) ;
widget = gtk_ui_manager_get_widget ( uim , path ) ;
g_free ( path ) ;
return widget ;
}
2009-06-20 16:51:32 +00:00
/* Note: The returned widget pointer is only valid until the toolbar is reloaded. See
* toolbar_get_widget_by_name for details ( ) . */
2008-12-06 11:10:06 +00:00
GtkWidget * toolbar_get_widget_child_by_name ( const gchar * name )
{
GtkWidget * widget = toolbar_get_widget_by_name ( name ) ;
2009-04-05 21:07:40 +00:00
if ( G_LIKELY ( widget ! = NULL ) )
2008-12-06 11:10:06 +00:00
return gtk_bin_get_child ( GTK_BIN ( widget ) ) ;
else
2009-04-05 21:07:40 +00:00
return NULL ;
2008-12-06 11:10:06 +00:00
}
GtkAction * toolbar_get_action_by_name ( const gchar * name )
{
2009-04-15 22:47:33 +00:00
g_return_val_if_fail ( name ! = NULL , NULL ) ;
2008-12-06 11:10:06 +00:00
return gtk_action_group_get_action ( group , name ) ;
}
2009-06-20 16:51:32 +00:00
static void toolbar_item_destroy_cb ( GtkWidget * widget , G_GNUC_UNUSED gpointer data )
{
plugin_items = g_slist_remove ( plugin_items , widget ) ;
}
void toolbar_item_ref ( GtkToolItem * item )
{
g_return_if_fail ( item ! = NULL ) ;
plugin_items = g_slist_append ( plugin_items , item ) ;
g_signal_connect ( item , " destroy " , G_CALLBACK ( toolbar_item_destroy_cb ) , NULL ) ;
}
2009-06-25 17:21:45 +00:00
static GtkWidget * toolbar_reload ( const gchar * markup )
2009-06-20 16:51:32 +00:00
{
gint i ;
GSList * l ;
GtkWidget * entry ;
GError * error = NULL ;
2011-04-13 12:59:20 +00:00
gchar * filename ;
2009-06-20 16:51:32 +00:00
static guint merge_id = 0 ;
GtkWidget * toolbar_new_file_menu = NULL ;
GtkWidget * toolbar_recent_files_menu = NULL ;
GtkWidget * toolbar_build_menu = NULL ;
/* Cleanup old toolbar */
if ( merge_id > 0 )
{
/* ref plugins toolbar items to keep them after we destroyed the toolbar */
foreach_slist ( l , plugin_items )
{
g_object_ref ( l - > data ) ;
gtk_container_remove ( GTK_CONTAINER ( main_widgets . toolbar ) , GTK_WIDGET ( l - > data ) ) ;
}
/* ref and hold the submenus of the New, Open and Build toolbar items */
toolbar_new_file_menu = geany_menu_button_action_get_menu (
GEANY_MENU_BUTTON_ACTION ( gtk_action_group_get_action ( group , " New " ) ) ) ;
g_object_ref ( toolbar_new_file_menu ) ;
toolbar_recent_files_menu = geany_menu_button_action_get_menu (
GEANY_MENU_BUTTON_ACTION ( gtk_action_group_get_action ( group , " Open " ) ) ) ;
g_object_ref ( toolbar_recent_files_menu ) ;
toolbar_build_menu = geany_menu_button_action_get_menu (
GEANY_MENU_BUTTON_ACTION ( gtk_action_group_get_action ( group , " Build " ) ) ) ;
g_object_ref ( toolbar_build_menu ) ;
/* Get rid of it! */
gtk_widget_destroy ( main_widgets . toolbar ) ;
gtk_ui_manager_remove_ui ( uim , merge_id ) ;
gtk_ui_manager_ensure_update ( uim ) ;
}
2009-06-25 17:21:45 +00:00
if ( markup ! = NULL )
2009-06-20 16:51:32 +00:00
{
2009-06-25 17:21:45 +00:00
merge_id = gtk_ui_manager_add_ui_from_string ( uim , markup , - 1 , & error ) ;
}
else
{
/* Load the toolbar UI XML file from disk (first from config dir, then try data dir) */
filename = utils_build_path ( app - > configdir , " ui_toolbar.xml " , NULL ) ;
2009-06-20 16:51:32 +00:00
merge_id = gtk_ui_manager_add_ui_from_file ( uim , filename , & error ) ;
if ( merge_id = = 0 )
{
2009-06-25 17:21:45 +00:00
if ( ! g_error_matches ( error , G_FILE_ERROR , G_FILE_ERROR_NOENT ) )
geany_debug ( " Loading user toolbar UI definition failed (%s). " , error - > message ) ;
2009-06-20 16:51:32 +00:00
g_error_free ( error ) ;
2009-06-25 17:21:45 +00:00
error = NULL ;
2011-04-13 12:59:20 +00:00
setptr ( filename , utils_build_path ( app - > datadir , " ui_toolbar.xml " , NULL ) ) ;
2009-06-25 17:21:45 +00:00
merge_id = gtk_ui_manager_add_ui_from_file ( uim , filename , & error ) ;
2009-06-20 16:51:32 +00:00
}
2011-04-13 12:59:20 +00:00
g_free ( filename ) ;
2009-06-20 16:51:32 +00:00
}
2009-06-25 17:21:45 +00:00
if ( error ! = NULL )
{
geany_debug ( " UI creation failed, using internal fallback definition. Error message: %s " ,
error - > message ) ;
g_error_free ( error ) ;
/* finally load the internally defined markup as fallback */
merge_id = gtk_ui_manager_add_ui_from_string ( uim , toolbar_markup , - 1 , NULL ) ;
}
2009-06-20 16:51:32 +00:00
main_widgets . toolbar = gtk_ui_manager_get_widget ( uim , " /ui/GeanyToolbar " ) ;
ui_init_toolbar_widgets ( ) ;
/* add the toolbar again to the main window */
if ( toolbar_prefs . append_to_menu )
{
GtkWidget * hbox_menubar = ui_lookup_widget ( main_widgets . window , " hbox_menubar " ) ;
gtk_box_pack_start ( GTK_BOX ( hbox_menubar ) , main_widgets . toolbar , TRUE , TRUE , 0 ) ;
gtk_box_reorder_child ( GTK_BOX ( hbox_menubar ) , main_widgets . toolbar , 1 ) ;
}
else
{
GtkWidget * box = ui_lookup_widget ( main_widgets . window , " vbox1 " ) ;
gtk_box_pack_start ( GTK_BOX ( box ) , main_widgets . toolbar , FALSE , FALSE , 0 ) ;
gtk_box_reorder_child ( GTK_BOX ( box ) , main_widgets . toolbar , 1 ) ;
}
gtk_widget_show ( main_widgets . toolbar ) ;
/* re-add und unref the plugin toolbar items */
i = toolbar_get_insert_position ( ) ;
foreach_slist ( l , plugin_items )
{
gtk_toolbar_insert ( GTK_TOOLBAR ( main_widgets . toolbar ) , l - > data , i ) ;
g_object_unref ( l - > data ) ;
i + + ;
}
/* re-add und unref the submenus of menu toolbar items */
if ( toolbar_new_file_menu ! = NULL )
{
geany_menu_button_action_set_menu ( GEANY_MENU_BUTTON_ACTION (
gtk_action_group_get_action ( group , " New " ) ) , toolbar_new_file_menu ) ;
g_object_unref ( toolbar_new_file_menu ) ;
}
if ( toolbar_recent_files_menu ! = NULL )
{
geany_menu_button_action_set_menu ( GEANY_MENU_BUTTON_ACTION (
gtk_action_group_get_action ( group , " Open " ) ) , toolbar_recent_files_menu ) ;
g_object_unref ( toolbar_recent_files_menu ) ;
}
if ( toolbar_build_menu ! = NULL )
{
geany_menu_button_action_set_menu ( GEANY_MENU_BUTTON_ACTION (
gtk_action_group_get_action ( group , " Build " ) ) , toolbar_build_menu ) ;
g_object_unref ( toolbar_build_menu ) ;
}
/* update button states */
if ( main_status . main_window_realized )
{
GeanyDocument * doc = document_get_current ( ) ;
2010-05-22 19:39:03 +00:00
gboolean doc_changed = ( doc ! = NULL ) ? doc - > changed : FALSE ;
2009-06-20 16:51:32 +00:00
ui_document_buttons_update ( ) ;
2010-05-22 19:39:03 +00:00
ui_save_buttons_toggle ( doc_changed ) ; /* update save all */
2009-06-20 16:51:32 +00:00
ui_update_popup_reundo_items ( doc ) ;
toolbar_apply_settings ( ) ;
}
/* Signals */
g_signal_connect ( main_widgets . toolbar , " button-press-event " ,
G_CALLBACK ( toolbar_popup_menu ) , NULL ) ;
g_signal_connect ( main_widgets . toolbar , " key-press-event " ,
G_CALLBACK ( on_escape_key_press_event ) , NULL ) ;
/* We don't need to disconnect those signals as this is done automatically when the entry
* widgets are destroyed , happens when the toolbar itself is destroyed . */
entry = toolbar_get_widget_child_by_name ( " SearchEntry " ) ;
if ( entry ! = NULL )
g_signal_connect ( entry , " motion-notify-event " , G_CALLBACK ( on_motion_event ) , NULL ) ;
entry = toolbar_get_widget_child_by_name ( " GotoEntry " ) ;
if ( entry ! = NULL )
g_signal_connect ( entry , " motion-notify-event " , G_CALLBACK ( on_motion_event ) , NULL ) ;
return main_widgets . toolbar ;
}
2010-04-11 21:56:34 +00:00
static void toolbar_notify_style_cb ( GObject * object , GParamSpec * arg1 , gpointer data )
{
const gchar * arg_name = g_param_spec_get_name ( arg1 ) ;
gint value ;
if ( toolbar_prefs . use_gtk_default_style & & utils_str_equal ( arg_name , " gtk-toolbar-style " ) )
{
value = ui_get_gtk_settings_integer ( arg_name , toolbar_prefs . icon_style ) ;
gtk_toolbar_set_style ( GTK_TOOLBAR ( main_widgets . toolbar ) , value ) ;
}
else if ( toolbar_prefs . use_gtk_default_icon & & utils_str_equal ( arg_name , " gtk-toolbar-size " ) )
{
value = ui_get_gtk_settings_integer ( arg_name , toolbar_prefs . icon_size ) ;
gtk_toolbar_set_icon_size ( GTK_TOOLBAR ( main_widgets . toolbar ) , value ) ;
}
}
2008-12-06 11:10:06 +00:00
GtkWidget * toolbar_init ( void )
{
GtkWidget * toolbar ;
GtkAction * action_new ;
GtkAction * action_open ;
2009-01-17 17:59:20 +00:00
GtkAction * action_build ;
2008-12-06 11:10:06 +00:00
GtkAction * action_searchentry ;
GtkAction * action_gotoentry ;
2010-04-11 21:56:34 +00:00
GtkSettings * gtk_settings ;
2008-12-06 11:10:06 +00:00
uim = gtk_ui_manager_new ( ) ;
group = gtk_action_group_new ( " GeanyToolbar " ) ;
gtk_action_group_set_translation_domain ( group , GETTEXT_PACKAGE ) ;
gtk_action_group_add_actions ( group , ui_entries , ui_entries_n , NULL ) ;
/* Create our custom actions */
2009-11-22 18:25:09 +00:00
action_new = geany_menu_button_action_new (
" New " , NULL ,
_ ( " Create a new file " ) ,
_ ( " Create a new file from a template " ) ,
GTK_STOCK_NEW ) ;
2008-12-06 11:10:06 +00:00
g_signal_connect ( action_new , " button-clicked " , G_CALLBACK ( on_toolbutton_new_clicked ) , NULL ) ;
gtk_action_group_add_action ( group , action_new ) ;
action_open = geany_menu_button_action_new (
2009-11-22 18:25:09 +00:00
" Open " , NULL ,
_ ( " Open an existing file " ) ,
_ ( " Open a recent file " ) ,
GTK_STOCK_OPEN ) ;
2008-12-06 11:10:06 +00:00
g_signal_connect ( action_open , " button-clicked " , G_CALLBACK ( on_toolbutton_open_clicked ) , NULL ) ;
gtk_action_group_add_action ( group , action_open ) ;
2009-01-17 17:59:20 +00:00
action_build = geany_menu_button_action_new (
2009-11-22 18:25:09 +00:00
" Build " , NULL ,
_ ( " Build the current file " ) ,
_ ( " Choose more build actions " ) ,
GEANY_STOCK_BUILD ) ;
2009-01-17 17:59:20 +00:00
g_signal_connect ( action_build , " button-clicked " ,
G_CALLBACK ( build_toolbutton_build_clicked ) , NULL ) ;
gtk_action_group_add_action ( group , action_build ) ;
2008-12-06 11:10:06 +00:00
action_searchentry = geany_entry_action_new (
" SearchEntry " , _ ( " Search " ) , _ ( " Find the entered text in the current file " ) , FALSE ) ;
g_signal_connect ( action_searchentry , " entry-activate " ,
2011-03-24 16:51:02 +00:00
G_CALLBACK ( on_toolbar_search_entry_activate ) , GINT_TO_POINTER ( FALSE ) ) ;
g_signal_connect ( action_searchentry , " entry-activate-backward " ,
G_CALLBACK ( on_toolbar_search_entry_activate ) , GINT_TO_POINTER ( TRUE ) ) ;
2008-12-06 11:10:06 +00:00
g_signal_connect ( action_searchentry , " entry-changed " ,
2011-03-24 16:51:02 +00:00
G_CALLBACK ( on_toolbar_search_entry_changed ) , NULL ) ;
2008-12-06 11:10:06 +00:00
gtk_action_group_add_action ( group , action_searchentry ) ;
action_gotoentry = geany_entry_action_new (
2009-03-05 13:03:51 +00:00
" GotoEntry " , _ ( " Goto " ) , _ ( " Jump to the entered line number " ) , TRUE ) ;
2008-12-06 11:10:06 +00:00
g_signal_connect ( action_gotoentry , " entry-activate " ,
G_CALLBACK ( on_toolbutton_goto_entry_activate ) , NULL ) ;
gtk_action_group_add_action ( group , action_gotoentry ) ;
gtk_ui_manager_insert_action_group ( uim , group , 0 ) ;
2009-06-25 17:21:45 +00:00
toolbar = toolbar_reload ( NULL ) ;
2008-12-06 11:10:06 +00:00
2010-04-11 21:56:34 +00:00
gtk_settings = gtk_widget_get_settings ( GTK_WIDGET ( toolbar ) ) ;
if ( gtk_settings ! = NULL )
{
g_signal_connect ( gtk_settings , " notify::gtk-toolbar-style " ,
G_CALLBACK ( toolbar_notify_style_cb ) , NULL ) ;
}
2008-12-06 11:10:06 +00:00
return toolbar ;
}
2009-03-29 16:15:35 +00:00
void toolbar_update_ui ( void )
{
static GtkWidget * hbox_menubar = NULL ;
static GtkWidget * menubar = NULL ;
2010-05-15 12:56:42 +00:00
GtkWidget * menubar_toolbar_separator = NULL ;
2009-03-29 16:15:35 +00:00
GtkWidget * parent ;
2010-05-15 12:56:42 +00:00
GtkToolItem * first_item ;
2009-03-29 16:15:35 +00:00
2009-04-15 22:47:33 +00:00
if ( menubar = = NULL )
2009-03-29 16:15:35 +00:00
{ /* cache widget pointers */
hbox_menubar = ui_lookup_widget ( main_widgets . window , " hbox_menubar " ) ;
menubar = ui_lookup_widget ( main_widgets . window , " menubar1 " ) ;
2010-05-15 12:56:42 +00:00
}
/* the separator between the menubar and the toolbar */
first_item = gtk_toolbar_get_nth_item ( GTK_TOOLBAR ( main_widgets . toolbar ) , 0 ) ;
if ( first_item ! = NULL & & GTK_IS_SEPARATOR_TOOL_ITEM ( first_item ) )
{
gtk_widget_destroy ( GTK_WIDGET ( first_item ) ) ;
2009-03-29 16:15:35 +00:00
}
parent = gtk_widget_get_parent ( main_widgets . toolbar ) ;
if ( toolbar_prefs . append_to_menu )
{
2009-04-15 22:47:33 +00:00
if ( parent ! = NULL )
2009-03-29 16:15:35 +00:00
{
if ( parent ! = hbox_menubar )
{ /* here we manually 'reparent' the toolbar, gtk_widget_reparent() doesn't
* like to do it */
g_object_ref ( main_widgets . toolbar ) ;
gtk_container_remove ( GTK_CONTAINER ( parent ) , main_widgets . toolbar ) ;
gtk_box_pack_start ( GTK_BOX ( hbox_menubar ) , main_widgets . toolbar , TRUE , TRUE , 0 ) ;
gtk_box_reorder_child ( GTK_BOX ( hbox_menubar ) , main_widgets . toolbar , 1 ) ;
g_object_unref ( main_widgets . toolbar ) ;
}
}
else
gtk_box_pack_start ( GTK_BOX ( hbox_menubar ) , main_widgets . toolbar , TRUE , TRUE , 0 ) ;
2010-05-15 12:56:42 +00:00
/* the separator between the menubar and the toolbar */
menubar_toolbar_separator = GTK_WIDGET ( gtk_separator_tool_item_new ( ) ) ;
gtk_widget_show ( menubar_toolbar_separator ) ;
gtk_toolbar_insert ( GTK_TOOLBAR ( main_widgets . toolbar ) ,
GTK_TOOL_ITEM ( menubar_toolbar_separator ) , 0 ) ;
2009-03-29 16:15:35 +00:00
}
else
{
GtkWidget * box = ui_lookup_widget ( main_widgets . window , " vbox1 " ) ;
2009-04-15 22:47:33 +00:00
if ( parent ! = NULL )
2009-03-29 16:15:35 +00:00
{
if ( parent ! = box )
{
g_object_ref ( main_widgets . toolbar ) ;
gtk_container_remove ( GTK_CONTAINER ( parent ) , main_widgets . toolbar ) ;
gtk_box_pack_start ( GTK_BOX ( box ) , main_widgets . toolbar , FALSE , FALSE , 0 ) ;
gtk_box_reorder_child ( GTK_BOX ( box ) , main_widgets . toolbar , 1 ) ;
g_object_unref ( main_widgets . toolbar ) ;
}
}
else
{
gtk_box_pack_start ( GTK_BOX ( box ) , main_widgets . toolbar , FALSE , FALSE , 0 ) ;
gtk_box_reorder_child ( GTK_BOX ( box ) , main_widgets . toolbar , 1 ) ;
}
}
/* we need to adjust the packing flags for the menubar to expand it if it is alone in the
* hbox and not expand it if the toolbar is appended */
gtk_box_set_child_packing ( GTK_BOX ( hbox_menubar ) , menubar ,
2011-10-11 20:42:09 -05:00
! ( toolbar_prefs . visible & & toolbar_prefs . append_to_menu ) , TRUE , 0 , GTK_PACK_START ) ;
2009-03-29 16:15:35 +00:00
}
2008-12-06 11:10:06 +00:00
/* Returns the position for adding new toolbar items. The returned position can be used
* to add new toolbar items with @ c gtk_toolbar_insert ( ) . The toolbar object can be accessed
* with @ a geany - > main_widgets - > toolbar .
2008-12-11 16:51:46 +00:00
* The position is always the last one before the Quit button or the very last position if the
* Quit button is not the last toolbar item .
2008-12-06 11:10:06 +00:00
*
2008-12-11 16:51:46 +00:00
* @ return The position for new toolbar items .
2008-12-06 11:10:06 +00:00
*/
gint toolbar_get_insert_position ( void )
{
GtkWidget * quit = toolbar_get_widget_by_name ( " Quit " ) ;
2008-12-11 16:51:46 +00:00
gint quit_pos = - 1 , pos ;
if ( quit ! = NULL )
quit_pos = gtk_toolbar_get_item_index ( GTK_TOOLBAR ( main_widgets . toolbar ) , GTK_TOOL_ITEM ( quit ) ) ;
pos = gtk_toolbar_get_n_items ( GTK_TOOLBAR ( main_widgets . toolbar ) ) ;
if ( quit_pos = = ( pos - 1 ) )
{
/* if the toolbar item before the quit button is a separator, insert new items before */
if ( GTK_IS_SEPARATOR_TOOL_ITEM ( gtk_toolbar_get_nth_item (
GTK_TOOLBAR ( main_widgets . toolbar ) , quit_pos - 1 ) ) )
{
return quit_pos - 1 ;
}
/* else return the position of the quit button to insert new items before */
return quit_pos ;
}
2008-12-06 11:10:06 +00:00
return pos ;
}
void toolbar_finalize ( void )
{
2010-05-15 13:14:38 +00:00
GeanyMenubuttonAction * open_action = GEANY_MENU_BUTTON_ACTION ( toolbar_get_action_by_name ( " Open " ) ) ;
g_object_unref ( geany_menu_button_action_get_menu ( open_action ) ) ;
geany_menu_button_action_set_menu ( open_action , NULL ) ;
2009-06-20 16:51:32 +00:00
/* unref'ing the GtkUIManager object will destroy all its widgets unless they were ref'ed */
2008-12-06 11:10:06 +00:00
g_object_unref ( uim ) ;
2009-06-20 16:51:32 +00:00
g_object_unref ( group ) ;
g_slist_free ( plugin_items ) ;
}
2009-07-21 22:10:42 +00:00
void toolbar_show_hide ( void )
{
ignore_callback = TRUE ;
gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM (
ui_lookup_widget ( main_widgets . window , " menu_show_toolbar1 " ) ) , toolbar_prefs . visible ) ;
ui_widget_show_hide ( main_widgets . toolbar , toolbar_prefs . visible ) ;
ignore_callback = FALSE ;
}
2010-04-11 21:56:08 +00:00
/* sets the icon style of the toolbar */
2010-04-11 21:56:23 +00:00
static void toolbar_set_icon_style ( void )
2009-06-20 16:51:32 +00:00
{
2010-04-11 21:56:08 +00:00
gint icon_style ;
icon_style = toolbar_prefs . icon_style ;
if ( toolbar_prefs . use_gtk_default_style )
icon_style = ui_get_gtk_settings_integer ( " gtk-toolbar-style " , toolbar_prefs . icon_style ) ;
gtk_toolbar_set_style ( GTK_TOOLBAR ( main_widgets . toolbar ) , icon_style ) ;
}
2009-06-20 16:51:32 +00:00
2010-04-11 21:56:08 +00:00
/* sets the icon size of the toolbar */
2010-04-11 21:56:23 +00:00
static void toolbar_set_icon_size ( void )
2010-04-11 21:56:08 +00:00
{
gint icon_size ;
icon_size = toolbar_prefs . icon_size ;
if ( toolbar_prefs . use_gtk_default_icon )
icon_size = ui_get_gtk_settings_integer ( " gtk-toolbar-icon-size " , toolbar_prefs . icon_size ) ;
gtk_toolbar_set_icon_size ( GTK_TOOLBAR ( main_widgets . toolbar ) , icon_size ) ;
}
void toolbar_apply_settings ( void )
{
toolbar_set_icon_style ( ) ;
toolbar_set_icon_size ( ) ;
2008-12-06 11:10:06 +00:00
}
2009-06-25 17:21:45 +00:00
2009-07-18 14:44:51 +00:00
# define TB_EDITOR_SEPARATOR _("Separator")
# define TB_EDITOR_SEPARATOR_LABEL _("--- Separator ---")
2009-06-25 17:21:45 +00:00
typedef struct
{
GtkWidget * dialog ;
GtkTreeView * tree_available ;
GtkTreeView * tree_used ;
GtkListStore * store_available ;
GtkListStore * store_used ;
GtkTreePath * last_drag_path ;
GtkTreeViewDropPosition last_drag_pos ;
GtkWidget * drag_source ;
} TBEditorWidget ;
static const GtkTargetEntry tb_editor_dnd_targets [ ] =
{
{ " GEANY_TB_EDITOR_ROW " , 0 , 0 }
} ;
static const gint tb_editor_dnd_targets_len = G_N_ELEMENTS ( tb_editor_dnd_targets ) ;
2009-07-18 14:44:51 +00:00
enum
{
TB_EDITOR_COL_ACTION ,
TB_EDITOR_COL_LABEL ,
2009-07-18 14:45:18 +00:00
TB_EDITOR_COL_ICON ,
2009-07-18 14:44:51 +00:00
TB_EDITOR_COLS_MAX
} ;
2009-06-25 17:21:45 +00:00
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 )
{
gint i ;
GSList * * actions = data ;
/* This is very basic parsing, stripped down any error checking, requires a valid UI markup. */
if ( utils_str_equal ( element_name , " separator " ) )
* actions = g_slist_append ( * actions , g_strdup ( TB_EDITOR_SEPARATOR ) ) ;
for ( i = 0 ; attribute_names [ i ] ! = NULL ; i + + )
{
if ( utils_str_equal ( attribute_names [ i ] , " action " ) )
{
* actions = g_slist_append ( * actions , g_strdup ( attribute_values [ i ] ) ) ;
}
}
}
2009-09-16 14:13:38 +00:00
2009-06-25 17:21:45 +00:00
static const GMarkupParser tb_editor_xml_parser =
{
tb_editor_handler_start_element , NULL , NULL , NULL , NULL
} ;
static GSList * tb_editor_parse_ui ( const gchar * buffer , gssize length , GError * * error )
{
GMarkupParseContext * context ;
GSList * list = NULL ;
context = g_markup_parse_context_new ( & tb_editor_xml_parser , 0 , & list , NULL ) ;
g_markup_parse_context_parse ( context , buffer , length , error ) ;
g_markup_parse_context_free ( context ) ;
return list ;
}
2009-07-18 14:45:18 +00:00
static void tb_editor_set_item_values ( const gchar * name , GtkListStore * store , GtkTreeIter * iter )
2009-07-18 14:44:51 +00:00
{
2009-07-18 14:45:18 +00:00
gchar * icon = NULL ;
gchar * label = NULL ;
gchar * label_clean = NULL ;
2009-07-18 14:44:51 +00:00
GtkAction * action ;
2009-07-18 14:45:18 +00:00
action = gtk_action_group_get_action ( group , name ) ;
2009-07-18 14:44:51 +00:00
if ( action = = NULL )
{
2009-07-18 14:45:18 +00:00
if ( utils_str_equal ( name , TB_EDITOR_SEPARATOR ) )
label_clean = g_strdup ( TB_EDITOR_SEPARATOR_LABEL ) ;
2009-07-18 14:44:51 +00:00
else
2009-07-18 14:45:18 +00:00
return ;
2009-07-18 14:44:51 +00:00
}
else
{
2009-07-18 14:45:18 +00:00
g_object_get ( action , " icon-name " , & icon , NULL ) ;
if ( icon = = NULL )
g_object_get ( action , " stock-id " , & icon , NULL ) ;
2009-07-18 14:44:51 +00:00
g_object_get ( action , " label " , & label , NULL ) ;
2009-07-18 14:45:18 +00:00
if ( label ! = NULL )
2009-07-23 11:00:32 +00:00
label_clean = utils_str_remove_chars ( g_strdup ( label ) , " _ " ) ;
2009-07-18 14:44:51 +00:00
}
2009-07-18 14:45:18 +00:00
gtk_list_store_set ( store , iter ,
TB_EDITOR_COL_ACTION , name ,
TB_EDITOR_COL_LABEL , label_clean ,
TB_EDITOR_COL_ICON , icon ,
- 1 ) ;
2009-07-18 14:44:51 +00:00
2009-07-18 14:45:18 +00:00
g_free ( icon ) ;
2009-07-18 14:44:51 +00:00
g_free ( label ) ;
2009-07-18 14:45:18 +00:00
g_free ( label_clean ) ;
2009-07-18 14:44:51 +00:00
}
2009-06-25 17:21:45 +00:00
static void tb_editor_scroll_to_iter ( GtkTreeView * treeview , GtkTreeIter * iter )
{
GtkTreePath * path = gtk_tree_model_get_path ( gtk_tree_view_get_model ( treeview ) , iter ) ;
gtk_tree_view_scroll_to_cell ( treeview , path , NULL , TRUE , 0.5 , 0.0 ) ;
gtk_tree_path_free ( path ) ;
}
static void tb_editor_free_path ( TBEditorWidget * tbw )
{
if ( tbw - > last_drag_path ! = NULL )
{
gtk_tree_path_free ( tbw - > last_drag_path ) ;
tbw - > last_drag_path = NULL ;
}
}
static void tb_editor_btn_remove_clicked_cb ( GtkWidget * button , TBEditorWidget * tbw )
{
GtkTreeModel * model_used ;
GtkTreeSelection * selection_used ;
GtkTreeIter iter_used , iter_new ;
2009-07-18 14:45:18 +00:00
gchar * action_name ;
2009-06-25 17:21:45 +00:00
selection_used = gtk_tree_view_get_selection ( tbw - > tree_used ) ;
if ( gtk_tree_selection_get_selected ( selection_used , & model_used , & iter_used ) )
{
2009-07-18 14:44:51 +00:00
gtk_tree_model_get ( model_used , & iter_used , TB_EDITOR_COL_ACTION , & action_name , - 1 ) ;
2009-06-25 17:21:45 +00:00
if ( gtk_list_store_remove ( tbw - > store_used , & iter_used ) )
gtk_tree_selection_select_iter ( selection_used , & iter_used ) ;
if ( ! utils_str_equal ( action_name , TB_EDITOR_SEPARATOR ) )
{
2009-07-18 14:45:18 +00:00
gtk_list_store_append ( tbw - > store_available , & iter_new ) ;
tb_editor_set_item_values ( action_name , tbw - > store_available , & iter_new ) ;
2009-06-25 17:21:45 +00:00
tb_editor_scroll_to_iter ( tbw - > tree_available , & iter_new ) ;
}
g_free ( action_name ) ;
}
}
static void tb_editor_btn_add_clicked_cb ( GtkWidget * button , TBEditorWidget * tbw )
{
GtkTreeModel * model_available ;
GtkTreeSelection * selection_available , * selection_used ;
GtkTreeIter iter_available , iter_new , iter_selected ;
2009-07-18 14:45:18 +00:00
gchar * action_name ;
2009-06-25 17:21:45 +00:00
selection_available = gtk_tree_view_get_selection ( tbw - > tree_available ) ;
if ( gtk_tree_selection_get_selected ( selection_available , & model_available , & iter_available ) )
{
2009-07-18 14:44:51 +00:00
gtk_tree_model_get ( model_available , & iter_available ,
TB_EDITOR_COL_ACTION , & action_name , - 1 ) ;
2009-06-25 17:21:45 +00:00
if ( ! utils_str_equal ( action_name , TB_EDITOR_SEPARATOR ) )
{
if ( gtk_list_store_remove ( tbw - > store_available , & iter_available ) )
gtk_tree_selection_select_iter ( selection_available , & iter_available ) ;
}
selection_used = gtk_tree_view_get_selection ( tbw - > tree_used ) ;
if ( gtk_tree_selection_get_selected ( selection_used , NULL , & iter_selected ) )
gtk_list_store_insert_before ( tbw - > store_used , & iter_new , & iter_selected ) ;
else
2009-07-18 14:45:18 +00:00
gtk_list_store_append ( tbw - > store_used , & iter_new ) ;
2009-06-25 17:21:45 +00:00
2009-07-18 14:45:18 +00:00
tb_editor_set_item_values ( action_name , tbw - > store_used , & iter_new ) ;
2009-06-25 17:21:45 +00:00
tb_editor_scroll_to_iter ( tbw - > tree_used , & iter_new ) ;
g_free ( action_name ) ;
}
}
static gboolean tb_editor_drag_motion_cb ( GtkWidget * widget , GdkDragContext * drag_context ,
gint x , gint y , guint ltime , TBEditorWidget * tbw )
{
if ( tbw - > last_drag_path ! = NULL )
gtk_tree_path_free ( tbw - > last_drag_path ) ;
gtk_tree_view_get_drag_dest_row ( GTK_TREE_VIEW ( widget ) ,
& ( tbw - > last_drag_path ) , & ( tbw - > last_drag_pos ) ) ;
return FALSE ;
}
static void tb_editor_drag_data_get_cb ( GtkWidget * widget , GdkDragContext * context ,
GtkSelectionData * data , guint info , guint ltime ,
TBEditorWidget * tbw )
{
GtkTreeIter iter ;
GtkTreeSelection * selection ;
GtkTreeModel * model ;
GdkAtom atom ;
gchar * name ;
selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( widget ) ) ;
if ( ! gtk_tree_selection_get_selected ( selection , & model , & iter ) )
return ;
2009-07-18 14:44:51 +00:00
gtk_tree_model_get ( model , & iter , TB_EDITOR_COL_ACTION , & name , - 1 ) ;
2011-03-24 22:00:18 +00:00
if ( G_UNLIKELY ( ! NZV ( name ) ) )
2009-07-04 09:22:49 +00:00
return ;
2009-06-25 17:21:45 +00:00
atom = gdk_atom_intern ( tb_editor_dnd_targets [ 0 ] . target , FALSE ) ;
gtk_selection_data_set ( data , atom , 8 , ( guchar * ) name , strlen ( name ) ) ;
g_free ( name ) ;
tbw - > drag_source = widget ;
}
static void tb_editor_drag_data_rcvd_cb ( GtkWidget * widget , GdkDragContext * context ,
gint x , gint y , GtkSelectionData * data , guint info ,
guint ltime , TBEditorWidget * tbw )
{
GtkTreeView * tree = GTK_TREE_VIEW ( widget ) ;
gboolean del = FALSE ;
if ( data - > length > = 0 & & data - > format = = 8 )
{
gboolean is_sep ;
gchar * text = NULL ;
text = ( gchar * ) data - > data ;
is_sep = utils_str_equal ( text , TB_EDITOR_SEPARATOR ) ;
/* If the source of the action is equal to the target, we do just re-order and so need
* to delete the separator to get it moved , not just copied . */
if ( is_sep & & widget = = tbw - > drag_source )
is_sep = FALSE ;
if ( tree ! = tbw - > tree_available | | ! is_sep )
{
2009-07-04 09:22:49 +00:00
GtkTreeIter iter , iter_before , * iter_before_ptr ;
2009-06-25 17:21:45 +00:00
GtkListStore * store = GTK_LIST_STORE ( gtk_tree_view_get_model ( tree ) ) ;
if ( tbw - > last_drag_path ! = NULL )
{
gtk_tree_model_get_iter ( GTK_TREE_MODEL ( store ) , & iter_before , tbw - > last_drag_path ) ;
2009-07-04 09:22:49 +00:00
if ( gtk_list_store_iter_is_valid ( store , & iter_before ) )
iter_before_ptr = & iter_before ;
else
iter_before_ptr = NULL ;
2009-06-25 17:21:45 +00:00
if ( tbw - > last_drag_pos = = GTK_TREE_VIEW_DROP_BEFORE | |
tbw - > last_drag_pos = = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE )
2009-07-04 09:22:49 +00:00
gtk_list_store_insert_before ( store , & iter , iter_before_ptr ) ;
2009-06-25 17:21:45 +00:00
else
2009-07-04 09:22:49 +00:00
gtk_list_store_insert_after ( store , & iter , iter_before_ptr ) ;
2009-06-25 17:21:45 +00:00
}
else
2009-07-18 14:45:18 +00:00
gtk_list_store_append ( store , & iter ) ;
2009-06-25 17:21:45 +00:00
2009-07-18 14:45:18 +00:00
tb_editor_set_item_values ( text , store , & iter ) ;
2009-06-25 17:21:45 +00:00
tb_editor_scroll_to_iter ( tree , & iter ) ;
}
if ( tree ! = tbw - > tree_used | | ! is_sep )
del = TRUE ;
}
tbw - > drag_source = NULL ; /* reset the value just to be sure */
tb_editor_free_path ( tbw ) ;
gtk_drag_finish ( context , TRUE , del , ltime ) ;
}
2009-07-18 14:45:05 +00:00
static gboolean tb_editor_foreach_used ( GtkTreeModel * model , GtkTreePath * path ,
GtkTreeIter * iter , gpointer data )
{
gchar * action_name ;
gtk_tree_model_get ( model , iter , TB_EDITOR_COL_ACTION , & action_name , - 1 ) ;
if ( utils_str_equal ( action_name , TB_EDITOR_SEPARATOR ) )
g_string_append_printf ( data , " \t \t <separator/> \n " ) ;
2011-03-24 22:00:18 +00:00
else if ( G_LIKELY ( NZV ( action_name ) ) )
2009-07-18 14:45:05 +00:00
g_string_append_printf ( data , " \t \t <toolitem action='%s' /> \n " , action_name ) ;
g_free ( action_name ) ;
return FALSE ;
}
static void tb_editor_write_markup ( TBEditorWidget * tbw )
{
/* <ui> must be the first tag, otherwise gtk_ui_manager_add_ui_from_string() will fail. */
const gchar * template = " <ui> \n <!-- \n \
This is Geany ' s toolbar UI definition . \ nThe DTD can be found at \ n \
http : / / library . gnome . org / devel / gtk / stable / GtkUIManager . html # GtkUIManager . description . \ n \ n \
You can re - order all items and freely add and remove available actions . \ n \
You cannot add new actions which are not listed in the documentation . \ n \
Everything you add or change must be inside the / ui / toolbar / path . \ n \ n \
For changes to take effect , you need to restart Geany . Alternatively you can use the toolbar \ n \
editor in Geany . \ n \ n \
A list of available actions can be found in the documentation included with Geany or \ n \
at http : / / www . geany . org / manual / current / index . html # customizing - the - toolbar . \ n - - > \ n \
\ t < toolbar name = ' GeanyToolbar ' > \ n " ;
2011-04-13 12:59:20 +00:00
gchar * filename ;
2009-07-18 14:45:05 +00:00
GString * str = g_string_new ( template ) ;
gtk_tree_model_foreach ( GTK_TREE_MODEL ( tbw - > store_used ) , tb_editor_foreach_used , str ) ;
g_string_append ( str , " \n \t </toolbar> \n </ui> \n " ) ;
toolbar_reload ( str - > str ) ;
2011-04-13 12:59:20 +00:00
filename = utils_build_path ( app - > configdir , " ui_toolbar.xml " , NULL ) ;
2009-07-18 14:45:05 +00:00
utils_write_file ( filename , str - > str ) ;
2011-04-13 12:59:20 +00:00
g_free ( filename ) ;
2009-07-18 14:45:05 +00:00
g_string_free ( str , TRUE ) ;
}
static void tb_editor_available_items_changed_cb ( GtkTreeModel * model , GtkTreePath * arg1 ,
GtkTreeIter * arg2 , TBEditorWidget * tbw )
{
tb_editor_write_markup ( tbw ) ;
}
static void tb_editor_available_items_deleted_cb ( GtkTreeModel * model , GtkTreePath * arg1 ,
TBEditorWidget * tbw )
{
tb_editor_write_markup ( tbw ) ;
}
2009-12-20 20:49:28 +00:00
static TBEditorWidget * tb_editor_create_dialog ( GtkWindow * parent )
2009-06-25 17:21:45 +00:00
{
GtkWidget * dialog , * vbox , * hbox , * vbox_buttons , * button_add , * button_remove ;
GtkWidget * swin_available , * swin_used , * tree_available , * tree_used , * label ;
2009-07-18 14:45:18 +00:00
GtkCellRenderer * text_renderer , * icon_renderer ;
2009-06-25 17:21:45 +00:00
GtkTreeViewColumn * column ;
TBEditorWidget * tbw = g_new ( TBEditorWidget , 1 ) ;
2009-12-20 20:49:28 +00:00
if ( parent = = NULL )
parent = GTK_WINDOW ( main_widgets . window ) ;
2009-07-04 09:31:02 +00:00
dialog = gtk_dialog_new_with_buttons ( _ ( " Customize Toolbar " ) ,
2009-12-20 20:49:28 +00:00
parent ,
2009-06-25 17:21:45 +00:00
GTK_DIALOG_DESTROY_WITH_PARENT ,
GTK_STOCK_CLOSE , GTK_RESPONSE_CLOSE , NULL ) ;
vbox = ui_dialog_vbox_new ( GTK_DIALOG ( dialog ) ) ;
gtk_box_set_spacing ( GTK_BOX ( vbox ) , 6 ) ;
gtk_widget_set_name ( dialog , " GeanyDialog " ) ;
gtk_window_set_default_size ( GTK_WINDOW ( dialog ) , - 1 , 400 ) ;
gtk_dialog_set_default_response ( GTK_DIALOG ( dialog ) , GTK_RESPONSE_CLOSE ) ;
2009-07-18 14:45:18 +00:00
tbw - > store_available = gtk_list_store_new ( TB_EDITOR_COLS_MAX ,
G_TYPE_STRING , G_TYPE_STRING , G_TYPE_STRING ) ;
tbw - > store_used = gtk_list_store_new ( TB_EDITOR_COLS_MAX ,
G_TYPE_STRING , G_TYPE_STRING , G_TYPE_STRING ) ;
2009-06-25 17:21:45 +00:00
label = gtk_label_new (
2009-07-07 12:21:18 +00:00
_ ( " Select items to be displayed on the toolbar. Items can be reordered by drag and drop. " ) ) ;
2009-07-18 14:44:51 +00:00
gtk_misc_set_alignment ( GTK_MISC ( label ) , 0.0 , 0.5 ) ;
2009-06-25 17:21:45 +00:00
tree_available = gtk_tree_view_new ( ) ;
gtk_tree_view_set_model ( GTK_TREE_VIEW ( tree_available ) , GTK_TREE_MODEL ( tbw - > store_available ) ) ;
gtk_tree_view_set_rules_hint ( GTK_TREE_VIEW ( tree_available ) , TRUE ) ;
gtk_tree_sortable_set_sort_column_id (
2009-07-18 14:44:51 +00:00
GTK_TREE_SORTABLE ( tbw - > store_available ) , TB_EDITOR_COL_LABEL , GTK_SORT_ASCENDING ) ;
2009-06-25 17:21:45 +00:00
2009-07-18 14:45:18 +00:00
icon_renderer = gtk_cell_renderer_pixbuf_new ( ) ;
column = gtk_tree_view_column_new_with_attributes (
NULL , icon_renderer , " stock-id " , TB_EDITOR_COL_ICON , NULL ) ;
gtk_tree_view_append_column ( GTK_TREE_VIEW ( tree_available ) , column ) ;
2009-06-25 17:21:45 +00:00
text_renderer = gtk_cell_renderer_text_new ( ) ;
column = gtk_tree_view_column_new_with_attributes (
2009-07-18 14:44:51 +00:00
_ ( " Available Items " ) , text_renderer , " text " , TB_EDITOR_COL_LABEL , NULL ) ;
2009-06-25 17:21:45 +00:00
gtk_tree_view_append_column ( GTK_TREE_VIEW ( tree_available ) , column ) ;
swin_available = gtk_scrolled_window_new ( NULL , NULL ) ;
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( swin_available ) ,
GTK_POLICY_NEVER , GTK_POLICY_AUTOMATIC ) ;
gtk_scrolled_window_set_shadow_type ( GTK_SCROLLED_WINDOW ( swin_available ) , GTK_SHADOW_ETCHED_IN ) ;
gtk_container_add ( GTK_CONTAINER ( swin_available ) , tree_available ) ;
tree_used = gtk_tree_view_new ( ) ;
gtk_tree_view_set_model ( GTK_TREE_VIEW ( tree_used ) , GTK_TREE_MODEL ( tbw - > store_used ) ) ;
gtk_tree_view_set_rules_hint ( GTK_TREE_VIEW ( tree_used ) , TRUE ) ;
gtk_tree_view_set_reorderable ( GTK_TREE_VIEW ( tree_used ) , TRUE ) ;
2009-07-18 14:45:18 +00:00
icon_renderer = gtk_cell_renderer_pixbuf_new ( ) ;
column = gtk_tree_view_column_new_with_attributes (
NULL , icon_renderer , " stock-id " , TB_EDITOR_COL_ICON , NULL ) ;
gtk_tree_view_append_column ( GTK_TREE_VIEW ( tree_used ) , column ) ;
2009-06-25 17:21:45 +00:00
text_renderer = gtk_cell_renderer_text_new ( ) ;
column = gtk_tree_view_column_new_with_attributes (
2009-07-18 14:44:51 +00:00
_ ( " Displayed Items " ) , text_renderer , " text " , TB_EDITOR_COL_LABEL , NULL ) ;
2009-06-25 17:21:45 +00:00
gtk_tree_view_append_column ( GTK_TREE_VIEW ( tree_used ) , column ) ;
swin_used = gtk_scrolled_window_new ( NULL , NULL ) ;
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( swin_used ) ,
GTK_POLICY_NEVER , GTK_POLICY_AUTOMATIC ) ;
gtk_scrolled_window_set_shadow_type ( GTK_SCROLLED_WINDOW ( swin_used ) , GTK_SHADOW_ETCHED_IN ) ;
gtk_container_add ( GTK_CONTAINER ( swin_used ) , tree_used ) ;
/* drag'n'drop */
gtk_tree_view_enable_model_drag_source ( GTK_TREE_VIEW ( tree_available ) , GDK_BUTTON1_MASK ,
tb_editor_dnd_targets , tb_editor_dnd_targets_len , GDK_ACTION_MOVE ) ;
gtk_tree_view_enable_model_drag_dest ( GTK_TREE_VIEW ( tree_available ) ,
tb_editor_dnd_targets , tb_editor_dnd_targets_len , GDK_ACTION_MOVE ) ;
g_signal_connect ( tree_available , " drag-data-get " ,
G_CALLBACK ( tb_editor_drag_data_get_cb ) , tbw ) ;
g_signal_connect ( tree_available , " drag-data-received " ,
G_CALLBACK ( tb_editor_drag_data_rcvd_cb ) , tbw ) ;
g_signal_connect ( tree_available , " drag-motion " ,
G_CALLBACK ( tb_editor_drag_motion_cb ) , tbw ) ;
gtk_tree_view_enable_model_drag_source ( GTK_TREE_VIEW ( tree_used ) , GDK_BUTTON1_MASK ,
tb_editor_dnd_targets , tb_editor_dnd_targets_len , GDK_ACTION_MOVE ) ;
gtk_tree_view_enable_model_drag_dest ( GTK_TREE_VIEW ( tree_used ) ,
tb_editor_dnd_targets , tb_editor_dnd_targets_len , GDK_ACTION_MOVE ) ;
g_signal_connect ( tree_used , " drag-data-get " ,
G_CALLBACK ( tb_editor_drag_data_get_cb ) , tbw ) ;
g_signal_connect ( tree_used , " drag-data-received " ,
G_CALLBACK ( tb_editor_drag_data_rcvd_cb ) , tbw ) ;
g_signal_connect ( tree_used , " drag-motion " ,
G_CALLBACK ( tb_editor_drag_motion_cb ) , tbw ) ;
button_add = ui_button_new_with_image ( GTK_STOCK_GO_FORWARD , NULL ) ;
button_remove = ui_button_new_with_image ( GTK_STOCK_GO_BACK , NULL ) ;
g_signal_connect ( button_add , " clicked " , G_CALLBACK ( tb_editor_btn_add_clicked_cb ) , tbw ) ;
g_signal_connect ( button_remove , " clicked " , G_CALLBACK ( tb_editor_btn_remove_clicked_cb ) , tbw ) ;
vbox_buttons = gtk_vbox_new ( FALSE , 6 ) ;
/* FIXME this is a little hack'ish, any better ideas? */
gtk_box_pack_start ( GTK_BOX ( vbox_buttons ) , gtk_label_new ( " " ) , TRUE , TRUE , 0 ) ;
gtk_box_pack_start ( GTK_BOX ( vbox_buttons ) , button_add , FALSE , FALSE , 0 ) ;
gtk_box_pack_start ( GTK_BOX ( vbox_buttons ) , button_remove , FALSE , FALSE , 0 ) ;
gtk_box_pack_start ( GTK_BOX ( vbox_buttons ) , gtk_label_new ( " " ) , TRUE , TRUE , 0 ) ;
hbox = gtk_hbox_new ( FALSE , 6 ) ;
gtk_box_pack_start ( GTK_BOX ( hbox ) , swin_available , TRUE , TRUE , 0 ) ;
gtk_box_pack_start ( GTK_BOX ( hbox ) , vbox_buttons , FALSE , FALSE , 0 ) ;
gtk_box_pack_start ( GTK_BOX ( hbox ) , swin_used , TRUE , TRUE , 0 ) ;
gtk_box_pack_start ( GTK_BOX ( vbox ) , label , FALSE , FALSE , 6 ) ;
gtk_box_pack_start ( GTK_BOX ( vbox ) , hbox , TRUE , TRUE , 0 ) ;
gtk_widget_show_all ( vbox ) ;
g_object_unref ( tbw - > store_available ) ;
g_object_unref ( tbw - > store_used ) ;
tbw - > dialog = dialog ;
tbw - > tree_available = GTK_TREE_VIEW ( tree_available ) ;
tbw - > tree_used = GTK_TREE_VIEW ( tree_used ) ;
tbw - > last_drag_path = NULL ;
return tbw ;
}
2009-12-20 20:49:28 +00:00
void toolbar_configure ( GtkWindow * parent )
2009-06-25 17:21:45 +00:00
{
2009-07-18 14:45:18 +00:00
gchar * markup ;
2009-06-25 17:21:45 +00:00
const gchar * name ;
GSList * sl , * used_items ;
GList * l , * all_items ;
2009-07-18 14:45:18 +00:00
GtkTreeIter iter ;
2009-06-25 17:21:45 +00:00
GtkTreePath * path ;
TBEditorWidget * tbw ;
/* read the current active toolbar items */
markup = gtk_ui_manager_get_ui ( uim ) ;
used_items = tb_editor_parse_ui ( markup , strlen ( markup ) , NULL ) ;
g_free ( markup ) ;
/* get all available actions */
all_items = gtk_action_group_list_actions ( group ) ;
/* create the GUI */
2009-12-20 20:49:28 +00:00
tbw = tb_editor_create_dialog ( parent ) ;
2009-06-25 17:21:45 +00:00
/* fill the stores */
2009-07-18 14:44:51 +00:00
gtk_list_store_insert_with_values ( tbw - > store_available , NULL , - 1 ,
TB_EDITOR_COL_ACTION , TB_EDITOR_SEPARATOR ,
TB_EDITOR_COL_LABEL , TB_EDITOR_SEPARATOR_LABEL ,
- 1 ) ;
2009-06-25 17:21:45 +00:00
foreach_list ( l , all_items )
{
name = gtk_action_get_name ( l - > data ) ;
if ( g_slist_find_custom ( used_items , name , ( GCompareFunc ) strcmp ) = = NULL )
2009-07-18 14:45:18 +00:00
{
gtk_list_store_append ( tbw - > store_available , & iter ) ;
tb_editor_set_item_values ( name , tbw - > store_available , & iter ) ;
}
2009-06-25 17:21:45 +00:00
}
foreach_slist ( sl , used_items )
{
2009-07-18 14:45:18 +00:00
gtk_list_store_append ( tbw - > store_used , & iter ) ;
tb_editor_set_item_values ( sl - > data , tbw - > store_used , & iter ) ;
2009-06-25 17:21:45 +00:00
}
/* select first item */
path = gtk_tree_path_new_from_string ( " 0 " ) ;
gtk_tree_selection_select_path ( gtk_tree_view_get_selection ( tbw - > tree_used ) , path ) ;
gtk_tree_path_free ( path ) ;
2009-07-18 14:45:30 +00:00
/* connect the changed signals after populating the store */
g_signal_connect ( tbw - > store_used , " row-changed " ,
G_CALLBACK ( tb_editor_available_items_changed_cb ) , tbw ) ;
g_signal_connect ( tbw - > store_used , " row-deleted " ,
G_CALLBACK ( tb_editor_available_items_deleted_cb ) , tbw ) ;
2009-06-25 17:21:45 +00:00
/* run it */
2009-07-18 14:45:05 +00:00
gtk_dialog_run ( GTK_DIALOG ( tbw - > dialog ) ) ;
2009-06-25 17:21:45 +00:00
gtk_widget_destroy ( tbw - > dialog ) ;
g_slist_foreach ( used_items , ( GFunc ) g_free , NULL ) ;
g_slist_free ( used_items ) ;
g_list_free ( all_items ) ;
tb_editor_free_path ( tbw ) ;
g_free ( tbw ) ;
}