aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarco Pesenti Gritti <marco@it.gnome.org>2003-01-21 02:57:20 +0800
committerMarco Pesenti Gritti <mpeseng@src.gnome.org>2003-01-21 02:57:20 +0800
commitc2beffd03405e6db4295afd6c2982388b808cb2e (patch)
tree819e50881626c5109ccdba5abb158585a3ca148b
parent822ca51797e05edbe42b80f1a33a70a7327d732e (diff)
downloadgsoc2013-epiphany-c2beffd03405e6db4295afd6c2982388b808cb2e.tar
gsoc2013-epiphany-c2beffd03405e6db4295afd6c2982388b808cb2e.tar.gz
gsoc2013-epiphany-c2beffd03405e6db4295afd6c2982388b808cb2e.tar.bz2
gsoc2013-epiphany-c2beffd03405e6db4295afd6c2982388b808cb2e.tar.lz
gsoc2013-epiphany-c2beffd03405e6db4295afd6c2982388b808cb2e.tar.xz
gsoc2013-epiphany-c2beffd03405e6db4295afd6c2982388b808cb2e.tar.zst
gsoc2013-epiphany-c2beffd03405e6db4295afd6c2982388b808cb2e.zip
Merge eog-menu-api branch
2003-01-20 Marco Pesenti Gritti <marco@it.gnome.org> * Merge eog-menu-api branch
-rw-r--r--ChangeLog166
-rw-r--r--TODO4
-rw-r--r--configure.in2
-rw-r--r--data/ui/Makefile.am5
-rw-r--r--data/ui/epiphany-toolbar.xml.in15
-rw-r--r--data/ui/epiphany-ui.xml.in568
-rw-r--r--lib/Makefile.am4
-rw-r--r--lib/egg/Makefile.am59
-rw-r--r--lib/egg/egg-accel-dialog.c332
-rw-r--r--lib/egg/egg-accel-dialog.h43
-rw-r--r--lib/egg/egg-action-group.c297
-rw-r--r--lib/egg/egg-action-group.h71
-rw-r--r--lib/egg/egg-action.c961
-rw-r--r--lib/egg/egg-action.h81
-rw-r--r--lib/egg/egg-markup.c438
-rw-r--r--lib/egg/egg-markup.h30
-rw-r--r--lib/egg/egg-menu-merge.c1316
-rw-r--r--lib/egg/egg-menu-merge.h100
-rw-r--r--lib/egg/egg-menu.h13
-rw-r--r--lib/egg/egg-radio-action.c194
-rw-r--r--lib/egg/egg-radio-action.h34
-rw-r--r--lib/egg/egg-toggle-action.c197
-rw-r--r--lib/egg/egg-toggle-action.h38
-rw-r--r--lib/egg/eggmarshalers.c277
-rw-r--r--lib/egg/eggmarshalers.h60
-rw-r--r--lib/egg/eggmarshalers.list6
-rw-r--r--lib/egg/eggradiotoolbutton.c121
-rw-r--r--lib/egg/eggradiotoolbutton.h57
-rw-r--r--lib/egg/eggseparatortoolitem.c86
-rw-r--r--lib/egg/eggseparatortoolitem.h50
-rw-r--r--lib/egg/eggtoggletoolbutton.c192
-rw-r--r--lib/egg/eggtoggletoolbutton.h64
-rw-r--r--lib/egg/eggtoolbar.c1850
-rw-r--r--lib/egg/eggtoolbar.h242
-rw-r--r--lib/egg/eggtoolbutton.c670
-rw-r--r--lib/egg/eggtoolbutton.h74
-rw-r--r--lib/egg/eggtoolitem.c416
-rw-r--r--lib/egg/eggtoolitem.h98
-rw-r--r--lib/egg/prop-editor.h31
-rw-r--r--lib/ephy-gui.c6
-rw-r--r--lib/toolbar/Makefile.am44
-rw-r--r--lib/widgets/Makefile.am3
-rw-r--r--lib/widgets/ephy-arrow-toolbutton.c234
-rw-r--r--lib/widgets/ephy-arrow-toolbutton.h59
-rw-r--r--lib/widgets/ephy-location-entry.c4
-rw-r--r--lib/widgets/ephy-location-entry.h4
-rw-r--r--lib/widgets/ephy-spinner.c4
-rw-r--r--src/Makefile.am12
-rw-r--r--src/ephy-favicon-action.c252
-rw-r--r--src/ephy-favicon-action.h49
-rw-r--r--src/ephy-favorites-menu.c104
-rw-r--r--src/ephy-favorites-menu.h3
-rw-r--r--src/ephy-location-action.c181
-rw-r--r--src/ephy-location-action.h51
-rw-r--r--src/ephy-navigation-action.c336
-rw-r--r--src/ephy-navigation-action.h56
-rw-r--r--src/ephy-navigation-button.c612
-rw-r--r--src/ephy-navigation-button.h79
-rw-r--r--src/ephy-shell.c3
-rw-r--r--src/ephy-spinner-action.c183
-rw-r--r--src/ephy-spinner-action.h49
-rw-r--r--src/ephy-tab.c77
-rw-r--r--src/ephy-tab.h2
-rw-r--r--src/ephy-tbi.c191
-rw-r--r--src/ephy-tbi.h70
-rw-r--r--src/ephy-window.c667
-rw-r--r--src/ephy-window.h12
-rw-r--r--src/popup-commands.c364
-rw-r--r--src/popup-commands.h86
-rwxr-xr-xsrc/ppview-toolbar.c169
-rw-r--r--src/ppview-toolbar.h6
-rwxr-xr-xsrc/statusbar.c159
-rw-r--r--src/statusbar.h14
-rwxr-xr-xsrc/toolbar.c636
-rw-r--r--src/toolbar.h26
-rw-r--r--src/window-commands.c377
-rw-r--r--src/window-commands.h233
77 files changed, 11569 insertions, 3110 deletions
diff --git a/ChangeLog b/ChangeLog
index 10c5ba5d8..eef09ea1f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2003-01-20 Marco Pesenti Gritti <marco@it.gnome.org>
+ * Merge eog-menu-api branch
+
+2003-01-20 Marco Pesenti Gritti <marco@it.gnome.org>
+
* embed/ephy-embed-event.c: (free_g_value),
(ephy_embed_event_init), (ephy_embed_event_get_property):
* embed/ephy-embed-event.h:
@@ -40,6 +44,168 @@
* embed/mozilla/FilePicker.cpp: Api change
+2003-01-20 Marco Pesenti Gritti <marco@it.gnome.org>
+
+ * data/ui/epiphany-ui.xml.in:
+ * src/ephy-spinner-action.c: (create_tool_item):
+ * src/ephy-tab.c: (ephy_tab_init), (ephy_tab_finalize),
+ (ephy_tab_get_event), (ephy_tab_set_event),
+ (ephy_tab_show_embed_popup), (ephy_tab_dom_mouse_down_cb):
+ * src/ephy-tab.h:
+ * src/ephy-window.c: (setup_window), (ephy_window_init),
+ (ephy_window_finalize), (ephy_window_get_active_embed):
+ * src/ephy-window.h:
+ * src/popup-commands.c: (get_event_info),
+ (popup_cmd_link_in_new_window), (popup_cmd_link_in_new_tab),
+ (popup_cmd_image_in_new_tab), (popup_cmd_image_in_new_window),
+ (popup_cmd_add_link_bookmark), (popup_cmd_frame_in_new_tab),
+ (popup_cmd_frame_in_new_window), (popup_cmd_copy_to_clipboard),
+ (popup_cmd_copy_page_location), (popup_cmd_copy_email),
+ (popup_cmd_copy_link_location), (save_property_url),
+ (popup_cmd_open_link), (popup_cmd_download_link),
+ (popup_cmd_save_image_as), (background_download_completed),
+ (popup_cmd_set_image_as_background),
+ (popup_cmd_copy_image_location), (popup_cmd_save_background_as),
+ (popup_cmd_open_frame), (popup_cmd_open_image):
+ * src/popup-commands.h:
+
+ Implement context menus
+
+2003-01-19 Marco Pesenti Gritti <marco@it.gnome.org>
+
+ * lib/widgets/ephy-spinner.c: (ephy_spinner_expose):
+ * src/ephy-favicon-action.c: (create_tool_item),
+ (each_url_get_data_binder), (favicon_drag_data_get_cb),
+ (ephy_favicon_action_sync_icon), (connect_proxy),
+ (ephy_favicon_action_set_property),
+ (ephy_favicon_action_get_property),
+ (ephy_favicon_action_class_init), (ephy_favicon_action_init):
+ * src/ephy-favicon-action.h:
+ * src/ephy-location-action.c: (ephy_location_action_get_widget):
+ * src/ephy-location-action.h:
+ * src/ephy-navigation-action.c:
+ * src/ephy-spinner-action.c: (ephy_spinner_action_sync_throbbing),
+ (create_tool_item), (connect_proxy),
+ (ephy_spinner_action_set_property),
+ (ephy_spinner_action_get_property),
+ (ephy_spinner_action_class_init), (ephy_spinner_action_init):
+ * src/ephy-spinner-action.h:
+ * src/ephy-window.c: (setup_window), (update_nav_control):
+ * src/toolbar.c: (toolbar_setup_actions),
+ (toolbar_activate_location), (toolbar_spinner_start),
+ (toolbar_spinner_stop), (toolbar_set_location),
+ (toolbar_update_favicon), (toolbar_get_location),
+ (toolbar_update_navigation_actions):
+ * src/toolbar.h:
+
+ Complete toolbar implementation.
+
+2003-01-18 Marco Pesenti Gritti <marco@it.gnome.org>
+
+ * lib/ephy-gui.c: (ephy_gui_menu_position_under_widget):
+ * lib/widgets/ephy-arrow-toolbutton.c: (popup_menu_under_arrow):
+ * src/ephy-location-action.c: (create_tool_item),
+ (location_url_activate_cb), (connect_proxy),
+ (ephy_location_action_class_init):
+ * src/ephy-location-action.h:
+ * src/ephy-shell.c: (ephy_shell_get_autocompletion):
+ * src/ephy-spinner-action.c: (create_tool_item):
+ * src/toolbar.c: (toolbar_setup_widgets), (go_location_cb),
+ (toolbar_setup_actions):
+
+ Make location and navigation buttons works correctly.
+
+2003-01-18 Marco Pesenti Gritti <marco@it.gnome.org>
+
+ * data/ui/Makefile.am:
+ * lib/widgets/Makefile.am:
+ * lib/widgets/ephy-arrow-toolbutton.c:
+ (ephy_arrow_toolbutton_get_type),
+ (ephy_arrow_toolbutton_class_init), (button_state_changed_cb),
+ (popup_menu_under_arrow), (menu_deactivated_cb),
+ (arrow_button_press_event_cb), (arrow_key_press_event_cb),
+ (ephy_arrow_toolbutton_init), (ephy_arrow_toolbutton_finalize),
+ (ephy_arrow_toolbutton_get_menu):
+ * lib/widgets/ephy-arrow-toolbutton.h:
+ * src/Makefile.am:
+ * src/ephy-navigation-action.c: (ephy_navigation_action_get_type),
+ (new_history_menu_item), (activate_back_or_forward_menu_item_cb),
+ (activate_up_menu_item_cb), (setup_back_or_forward_menu),
+ (setup_up_menu), (menu_activated_cb), (connect_proxy),
+ (ephy_navigation_action_set_property),
+ (ephy_navigation_action_get_property),
+ (ephy_navigation_action_class_init), (ephy_navigation_action_init):
+ * src/ephy-navigation-action.h:
+ * src/ephy-window.c: (ephy_window_init):
+ * src/toolbar.c: (toolbar_setup_actions), (toolbar_set_window),
+ (toolbar_init):
+
+ Implement back/forward
+
+2003-01-17 Marco Pesenti Gritti <marco@it.gnome.org>
+
+ * data/ui/Makefile.am:
+ * data/ui/epiphany-ui.xml.in:
+ * src/Makefile.am:
+ * src/ephy-window.c: (add_widget), (setup_window),
+ (ephy_window_init), (ephy_window_set_chrome):
+ * src/toolbar.c: (toolbar_setup_widgets), (add_widget),
+ (toolbar_set_window), (toolbar_setup_actions), (toolbar_init),
+ (toolbar_finalize), (toolbar_set_visibility):
+
+ Make some toolbar widgets work again
+
+2003-01-16 Marco Pesenti Gritti <marco@it.gnome.org>
+
+ * configure.in:
+ * data/ui/Makefile.am:
+ * data/ui/epiphany-ui.xml.in:
+ * embed/mozilla/GlobalHistory.cpp:
+ * lib/Makefile.am:
+ * src/Makefile.am:
+ * src/ephy-favorites-menu.c: (ephy_favorites_menu_init),
+ (ephy_favorites_menu_clean), (ephy_favorites_menu_finalize_impl),
+ (ephy_favorites_menu_set_property), (ephy_favorites_menu_rebuild):
+ * src/ephy-favorites-menu.h:
+ * src/ephy-nautilus-view.c: (gnv_bonobo_control_activate_cb),
+ (gnv_popup_cmd_frame_in_new_window):
+ * src/ephy-window.c: (add_widget), (setup_window),
+ (setup_popup_factory), (ephy_window_init), (ephy_window_finalize),
+ (ephy_window_set_chrome), (ephy_window_activate_location),
+ (update_status_message), (update_progress), (update_security),
+ (update_nav_control), (update_location_control),
+ (update_favicon_control), (update_spinner_control),
+ (save_old_embed_status), (ephy_window_get_toolbar):
+ * src/ppview-toolbar.c: (ppview_toolbar_set_window),
+ (ppview_toolbar_init), (ppview_toolbar_finalize),
+ (toolbar_update_sensitivity), (toolbar_cmd_ppv_goto_first),
+ (toolbar_cmd_ppv_goto_last), (toolbar_cmd_ppv_go_back),
+ (toolbar_cmd_ppv_go_forward), (toolbar_cmd_ppv_close):
+ * src/ppview-toolbar.h:
+ * src/statusbar.c: (statusbar_get_type), (statusbar_class_init),
+ (create_statusbar_security_icon), (create_statusbar_progress),
+ (statusbar_init), (statusbar_new), (statusbar_set_message):
+ * src/statusbar.h:
+ * src/toolbar.c: (toolbar_get_type), (toolbar_class_init),
+ (toolbar_setup_favicon), (toolbar_setup_location_entry),
+ (toolbar_set_window), (toolbar_init), (toolbar_finalize),
+ (toolbar_set_visibility), (toolbar_button_set_sensitive),
+ (toolbar_get_location):
+ * src/toolbar.h:
+ * src/window-commands.c:
+ * src/window-commands.h:
+
+ More menu work ...
+
+2003-01-14 Marco Pesenti Gritti <marco@it.gnome.org>
+
+ * src/ephy-window.c:
+ * src/ephy-window.h:
+ * src/window-commands.c:
+ * src/window-commands.h:
+
+ Some work on the new menu stuff
+
2003-01-13 Marco Pesenti Gritti <marco@it.gnome.org>
* embed/mozilla/FilePicker.cpp:
diff --git a/TODO b/TODO
index a4e53a542..973f85867 100644
--- a/TODO
+++ b/TODO
@@ -2,12 +2,10 @@ To do:
- implement phoenix like popup blocking / make popups less annoying
- loading feedback on tabs
-- create print preview toolbar only when necessary
- embed dialogs crashes when the window has been closed
- save bookmarks dialog state (current keyword)
- show bookmarks updated content
- temporary bookmarks, maybe an expire checkbox in new bookmark dialog ?
-- titles in history for hosts too
Done:
@@ -24,3 +22,5 @@ Done:
* history scoring for autocompletion
* urls like www.gnome.org and gnome.org should use same folder in history
* drop items from history when they are not visited since some time
+* create print preview toolbar only when necessary
+* titles in history for hosts too
diff --git a/configure.in b/configure.in
index 9922826b9..6f5d36651 100644
--- a/configure.in
+++ b/configure.in
@@ -162,8 +162,8 @@ data/art/Makefile
data/ui/Makefile
data/starthere/Makefile
lib/Makefile
+lib/egg/Makefile
lib/widgets/Makefile
-lib/toolbar/Makefile
embed/Makefile
embed/mozilla/Makefile
src/Makefile
diff --git a/data/ui/Makefile.am b/data/ui/Makefile.am
index 658ebf3f1..c56bceda3 100644
--- a/data/ui/Makefile.am
+++ b/data/ui/Makefile.am
@@ -1,6 +1,7 @@
-uixmldir = $(datadir)/gnome-2.0/ui
+uixmldir = $(pkgdatadir)
uixml_in_files = epiphany-ui.xml.in \
- nautilus-epiphany-view.xml.in
+ nautilus-epiphany-view.xml.in \
+ epiphany-toolbar.xml.in
uixml_DATA = $(uixml_in_files:.xml.in=.xml)
diff --git a/data/ui/epiphany-toolbar.xml.in b/data/ui/epiphany-toolbar.xml.in
new file mode 100644
index 000000000..0a46f0fe8
--- /dev/null
+++ b/data/ui/epiphany-toolbar.xml.in
@@ -0,0 +1,15 @@
+<Root>
+<dockitem name="toolbar1">
+ <toolitem name="ViewBackTItem" verb="NavigationBack"/>
+ <toolitem name="ViewForwardTItem" verb="NavigationForward"/>
+ <toolitem name="ViewStopTItem" verb="ViewStop"/>
+ <toolitem name="ViewReloadTItem" verb="ViewReload"/>
+ <separator name="ToolbarSep1"/>
+ <toolitem name="GoHomeTItem" verb="GoHome"/>
+ <separator name="ToolbarSep2"/>
+ <toolitem name="FaviconTItem" verb="Favicon"/>
+ <toolitem name="LocationTItem" verb="Location"/>
+ <toolitem name="SpinnerTItem" verb="Spinner"/>
+</dockitem>
+</Root>
+
diff --git a/data/ui/epiphany-ui.xml.in b/data/ui/epiphany-ui.xml.in
index 0927957a5..2a47b0252 100644
--- a/data/ui/epiphany-ui.xml.in
+++ b/data/ui/epiphany-ui.xml.in
@@ -1,458 +1,150 @@
<Root>
-
-<commands>
- <cmd name="FileOpen" _label="Open"
- _tip="Open a file" pixtype="stock" pixname="gtk-open" accel="*Control*O"/>
-
- <cmd name="FileSaveAs" _label="Save As"
- _tip="Save the current file with a different name"
- pixtype="stock" pixname="gtk-save-as"
- accel="*Shift**Control*S"/>
-
- <cmd name="FilePrint" _label="Print"
- _tip="Print the current file" pixtype="stock" pixname="gtk-print"
- accel="*Control*P"/>
-
- <cmd name="FileCloseTab" _tip="Close the current tab"
- pixtype="stock" pixname="gtk-close"/>
-
- <cmd name="FileCloseWindow" _tip="Close the current window"/>
-
- <cmd name="EditCut" _label="Cut" _tip="Cut the selection"
- pixtype="stock" pixname="gtk-cut"/>
-
- <cmd name="EditCopy" _label="Copy"
- _tip="Copy the selection" pixtype="stock" pixname="gtk-copy"/>
-
- <cmd name="EditPaste" _label="Paste"
- _tip="Paste the clipboard" pixtype="stock" pixname="gtk-paste"/>
-
- <cmd name="EditSelectAll" _label="Select All" _tip="Select the entire document"
- accel="*Control*A"/>
-
- <cmd name="EditFind" _label="Find" _tip="Search for a string"
- pixtype="stock" pixname="gtk-find" accel="*Control*F"/>
-
- <cmd name="Zoom In" _label="Zoom In"
- _tip="Show the contents in more detail"/>
- <cmd name="Zoom Out" _label="Zoom Out"
- _tip="Show the contents in less detail"/>
- <cmd name="Zoom Normal" _label="Normal Size"
- _tip="Show the contents at the normal size"/>
-
- <cmd name="SettingsPreferences" _label="Preferences" _tip="Configure the application"
- pixtype="stock" pixname="gtk-preferences"/>
-
- <cmd name="SettingsToolbarEditor" _label="Toolbar" _tip="Edit the main toolbar"/>
-
- <cmd name="HelpContents" _label="Contents" _tip="Open the Epiphany manual"
- accel="F1"/>
-
- <cmd name="About" _label="About..." _tip="About this application"
- pixtype="stock" pixname="About"/>
-
- <cmd name="BookmarksAddDefault" _label="Add bookmark"
- _tip="Add a bookmark to the default folder"/>
-
- <cmd name="BookmarksEdit" _label="Edit bookmarks"
- _tip="Open a bookmarks editor"/>
-
- <cmd name="GoBack" _label="_Back"
- sensitive="0"/>
-
- <cmd name="GoUp" _label="_Up"
- sensitive="0"/>
-
- <cmd name="GoHome" _label="_Home"/>
-
- <cmd name="GoMyportal" _label="_My portal"/>
-
- <cmd name="GoForward" _label="_Forward"
- sensitive="0"/>
-
- <cmd name="GoStop" _label="_Stop"
- sensitive="0"
- _tip="Stop current data transfer"/>
-
- <cmd name="GoReload" _label="_Reload"
- _tip="Display the latest content of the current page"/>
-
- <cmd name="GoGo" _label="_Go"
- _tip="Load the URL in the location entry"/>
-
- <cmd name="EPOpenLink" _label="Open"/>
-
- <cmd name="EPOpenInNewWindow" _label="Open in New Window"/>
-
- <cmd name="EPOpenInNewTab" _label="Open in New Tab"/>
-
- <cmd name="EPCopyLinkLocation" _label="Copy Link Location"/>
-
- <cmd name="EPCopyEmail" _label="Copy Email Address"/>
-
- <cmd name="EPDownloadLink" _label="Download Link"/>
-
- <cmd name="EPAddBookmark" _label="Add Bookmark"/>
-
- <cmd name="EPOpenImage" _label="Open Image"/>
-
- <cmd name="EPOpenImageInNewWindow" _label="Open Image in New Window"/>
-
- <cmd name="EPOpenImageInNewTab" _label="Open Image in New Tab"/>
-
- <cmd name="EPSaveImageAs" _label="Save Image As..."/>
-
- <cmd name="EPSetImageAsBackground" _label="Use Image as Background"/>
-
- <cmd name="EPCopyImageLocation" _label="Copy Image Location"/>
-
- <cmd name="DPCopyLocation" _label="Copy Page location"/>
-
- <cmd name="DPOpenFrame" _label="Open Frame"/>
-
- <cmd name="DPOpenFrameInNewWindow" _label="Open Frame in New Window"/>
-
- <cmd name="DPOpenFrameInNewTab" _label="Open Frame in New Tab"/>
-
- <cmd name="DPReloadFrame" _label="Reload Frame"/>
-
- <cmd name="DPAddFrameBookmark" _label="Add Bookmark for Frame"/>
-
- <cmd name="DPSavePageAs" _label="Save Page As..."/>
-
- <cmd name="DPSaveBackgroundAs" _label="Save Background As..."/>
-
- <cmd name="DPAddPageBookmark" verb="Add Bookmark"/>
-
- <cmd name="PPVGotoFirst" _label="First"/>
-
- <cmd name="PPVGotoLast" _label="Last"/>
-
- <cmd name="PPVGoBack" _label="Previous"/>
-
- <cmd name="PPVGoForward" _label="Next"/>
-
-</commands>
-
-<keybindings>
- <accel name="*Control*S" verb="FileSaveAs"/>
-</keybindings>
-
<menu>
-
-<submenu name="File" _label="_File">
-
- <menuitem name="FileNewWindow" verb=""
- _label="_New Window"
- pixtype="stock" pixname="gtk-new"
- accel="*Control*n"/>
-
- <menuitem name="FileNewTab" verb="" _label="New _Tab" accel="*Control*t"/>
-
- <menuitem name="FileOpen" verb="" _label="_Open..."/>
-
- <separator/>
-
- <menuitem name="FileSaveAs" verb="" _label="Save _As..."/>
-
- <separator/>
-
- <menuitem name="FilePrint" verb="" _label="_Print..."/>
- <menuitem name="FileSendTo" verb=""
- pixtype="stock" pixname="epiphany-send-link"
- _label="S_end To..."/>
-
- <separator/>
-
- <menuitem name="BookmarksAddDefault" verb="" _label="_Add Bookmark"
- _tip="Add a bookmark for the current location to the default folder"
- pixtype="stock" pixname="gtk-add" accel="*Control*d"/>
-
- <separator/>
-
- <menuitem name="FileCloseTab" verb="" _label="_Close Tab" accel="*Control*W"/>
-
- <menuitem name="FileCloseWindow" verb="" _label="Close _Window" accel="*Shift**Control*W"/>
-
+<submenu name="FileMenu" verb="File">
+ <menuitem name="FileNewWindowMenu" verb="FileNewWindow"/>
+ <menuitem name="FileNewTabMenu" verb="FileNewTab"/>
+ <menuitem name="FileOpenMenu" verb="FileOpen"/>
+ <separator name="FileSep1"/>
+ <menuitem name="FileSaveAsMenu" verb="FileSaveAs"/>
+ <separator name="FileSep2"/>
+ <menuitem name="FilePrintMenu" verb="FilePrint"/>
+ <menuitem name="FileSendToMenu" verb="FileSendTo"/>
+ <separator name="FileSep3"/>
+ <menuitem name="FileAddBookmarkMenu" verb="FileAddBookmark"/>
+ <separator name="FileSep4"/>
+ <menuitem name="FileCloseTabMenu" verb="FileCloseTab"/>
+ <menuitem name="FileCloseWindowMenu" verb="FileCloseWindow"/>
</submenu>
-<submenu name="Edit" _label="_Edit">
-
- <menuitem name="EditCut" verb="" _label="Cu_t" accel="*Control*X"/>
-
- <menuitem name="EditCopy" verb="" _label="_Copy" accel="*Control*c"/>
-
- <menuitem name="EditPaste" verb="" _label="_Paste" accel="*Control*v"/>
-
- <separator/>
-
- <menuitem name="EditSelectAll" verb="" _label="Select _All"/>
-
- <separator/>
-
- <menuitem name="EditFind" verb="" _label="_Find..."/>
- <menuitem name="EditFindNext" verb=""
- accel="*Control*G" _label="Find Ne_xt"/>
- <menuitem name="EditFindPrev" verb=""
- accel="*Shift**Control*G" _label="Find Pre_vious"/>
-
- <separator/>
-
- <menuitem name="PDM" verb="ToolsPDM" _label="P_ersonal Data"/>
-
- <menuitem name="EditToolbar"
- _label="T_oolbar"
- verb="SettingsToolbarEditor"/>
-
- <menuitem name="EditPrefs"
- _label="P_references"
- _tip="Edit Ephy preferences"
- pixtype="stock" pixname="gtk-preferences"
- verb="EditPrefs"/>
+<submenu name="EditMenu" verb="Edit">
+ <menuitem name="EditCutMenu" verb="EditCut"/>
+ <menuitem name="EditCopyMenu" verb="EditCopy"/>
+ <menuitem name="EditPasteMenu" verb="EditPaste"/>
+ <separator name="EditSep1"/>
+ <menuitem name="EditSelectAllMenu" verb="EditSelectAll"/>
+ <separator name="EditSep2"/>
+ <menuitem name="EditFindMenu" verb="EditFind"/>
+ <menuitem name="EditFindNextMenu" verb="EditFindNext"/>
+ <menuitem name="EditFindPrevMenu" verb="EditFindPrev"/>
+ <separator name="EditSep3"/>
+ <menuitem name="EditPersonalDataMenu" verb="EditPersonalData"/>
+ <menuitem name="EditToolbarMenu" verb="EditToolbar"/>
+ <menuitem name="EditPrefsMenu" verb="EditPrefs"/>
</submenu>
-<submenu name="View" _label="_View">
-
- <menuitem name="GoStop"
- pixtype="stock" pixname="gtk-stop"
- verb="" accel="Escape"/>
-
- <menuitem name="GoReload"
- pixtype="stock" pixname="gtk-refresh"
- verb="" accel="*Control*R"/>
-
- <separator/>
-
- <menuitem name="View Toolbar" id="View Toolbar" type="toggle"
- _label="_Toolbar" verb="" accel="*Shift**Control*T"/>
-
- <menuitem name="View Statusbar" id="View Statusbar"
- type="toggle" _label="St_atusbar" verb=""/>
-
- <menuitem name="View Fullscreen" id="View Fullscreen"
- type="toggle" _label="_Fullscreen" verb="" accel="F11"/>
-
- <separator/>
-
- <menuitem name="Zoom In"
- _label="Zoom _In" accel="*Control*plus"
- pixtype="stock" pixname="zoom-in"
- verb="Zoom In"/>
-
- <menuitem name="Zoom Out"
- _label="Zoom _Out" accel="*Control*minus"
- pixtype="stock" pixname="zoom-out"
- verb="Zoom Out"/>
-
- <menuitem name="Zoom Normal"
- _label="_Normal Size"
- pixtype="stock" pixname="zoom-100"
- verb="Zoom Normal"/>
-
- <separator/>
-
- <placeholder name="EncodingMenuPlaceholder"/>
-
- <menuitem name="Page Source"
- _label="_Page Source"
- verb="ViewPageSource"/>
-
+<submenu name="ViewMenu" verb="View">
+ <menuitem name="ViewStopMenu" verb="ViewStop"/>
+ <menuitem name="ViewReloadMenu" verb="ViewReload"/>
+ <separator name="ViewSep1"/>
+ <menuitem name="ViewStatusbarMenu" verb="ViewStatusbar"/>
+ <menuitem name="ViewFullscreenMenu" verb="ViewFullscreen"/>
+ <separator name="ViewSep2"/>
+ <menuitem name="ViewZoomInMenu" verb="ViewZoomIn"/>
+ <menuitem name="ViewZoomOutMenu" verb="ViewZoomOut"/>
+ <menuitem name="ViewZoomNormalMenu" verb="ViewZoomNormal"/>
+ <separator name="ViewSep3"/>
+ <placeholder name="ViewEncodingPlaceholder"/>
+ <menuitem name="ViewPageSourceMenu" verb="ViewPageSource"/>
</submenu>
-<submenu name="Go" _label="_Go">
- <menuitem name="GoBack"
- pixtype="stock" pixname="gtk-go-back"
- verb="" accel="*Alt*Left"/>
-
- <menuitem name="GoForward"
- pixtype="stock" pixname="gtk-go-forward"
- verb="" accel="*Alt*Right"/>
-
- <menuitem name="GoUp"
- pixtype="stock" pixname="gtk-go-up"
- verb="" accel="*Alt*Up"/>
-
- <separator/>
-
- <menuitem name="GoHome"
- pixtype="stock" pixname="gtk-home"
- verb="" accel="*Alt*Home"/>
-
- <menuitem name="GoLocation" _label="_Location..."
- verb="" accel="*Ctrl*l"/>
-
- <separator/>
-
- <menuitem name="History" verb="ToolsHistory"
- _label="_History" accel="*Control*H"/>
-
- <menuitem name="BookmarksEdit" verb="" _label="_Bookmarks"
- accel="*Control*b"/>
-
- <placeholder name="Favorites" delimit="top"/>
+<submenu name="GoMenu" verb="Go">
+ <menuitem name="GoBackMenu" verb="GoBack"/>
+ <menuitem name="GoForwardMenu" verb="GoForward"/>
+ <menuitem name="GoUpMenu" verb="GoUp"/>
+ <separator name="GoSep1"/>
+ <menuitem name="GoHomeMenu" verb="GoHome"/>
+ <menuitem name="GoLocationMenu" verb="GoLocation"/>
+ <separator name="GoSep2"/>
+ <menuitem name="GoHistoryMenu" verb="GoHistory"/>
+ <menuitem name="GoBookmarksMenu" verb="GoBookmarks"/>
+ <placeholder name="GoFavorites">
+ <separator name="GoSep3"/>
+ </placeholder>
</submenu>
-<submenu name="Tabs" _label="_Tabs">
- <menuitem name="Previous Tab" verb="TabsPrevious" _label="_Previous Tab"
- accel="*Control*Page_Up"/>
- <menuitem name="Next Tab" verb="TabsNext" _label="_Next Tab"
- accel="*Control*Page_Down"/>
- <separator/>
- <menuitem name="Tab Left" verb="TabsMoveLeft" _label="Move Tab _Left"
- accel="*Shift**Control*Page_Up"/>
- <menuitem name="Tab Right" verb="TabsMoveRight" _label="Move Tab _Right"
- accel="*Shift**Control*Page_Down"/>
- <menuitem name="Move Tab to New Window" verb="TabsDetach" _label="_Detach Tab"
- accel="*Shift**Control*m"/>
+<submenu name="TabsMenu" verb="Tabs">
+ <menuitem name="TabsPreviousMenu" verb="TabsPrevious"/>
+ <menuitem name="TabsNextMenu" verb="TabsNext"/>
+ <separator name="TabsSep1"/>
+ <menuitem name="TabsMoveLeftMenu" verb="TabsMoveLeft"/>
+ <menuitem name="TabsMoveRightMenu" verb="TabsMoveRight"/>
+ <menuitem name="TabsDetachMenu" verb="TabsDetach"/>
</submenu>
-<submenu name="Help" _label="_Help">
-
- <menuitem name="HelpContents" verb=""
- pixtype="stock" pixname="gtk-help"
- _label="_Contents"/>
-
- <menuitem name="About" verb="" _label="_About"/>
-
+<submenu name="HelpMenu" verb="Help">
+ <menuitem name="HelpAboutMenu" verb="HelpAbout"/>
</submenu>
-
</menu>
<popups>
+<popup name="EphyEmbedInputPopup" verb="FakeToplevel">
+ <menuitem name="EditCutIP" verb="EditCut"/>
+ <menuitem name="EditCopyIP" verb="EditCopy"/>
+ <menuitem name="EditPasteIP" verb="EditPaste"/>
+</popup>
+
+<popup name="EphyDocumentPopup" verb="FakeToplevel">
+ <menuitem name="GoBackDP" verb="GoBack"/>
+ <menuitem name="GoForwardDP" verb="GoForward"/>
+ <menuitem name="GoReloadDP" verb="ViewReload"/>
+ <separator name="DPSep1"/>
+ <menuitem name="SavePageAsDP" verb="FileSaveAs"/>
+ <menuitem name="SaveBackgroundAsDP" verb="SaveBackgroundAs"/>
+ <menuitem name="AddPageBookmarkDP" verb="FileAddBookmark"/>
+ <menuitem name="CopyPageLocationDP" verb="CopyPageLocation"/>
+</popup>
+
+<popup name="EphyFramedDocumentPopup" verb="FakeToplevel">
+ <menuitem name="GoBackFDP" verb="GoBack"/>
+ <menuitem name="GoForwardFDP" verb="GoForward"/>
+ <menuitem name="GoReloadFDP" verb="ViewReload"/>
+ <separator name="FDPSep1"/>
+ <menuitem name="SavePageAsFDP" verb="FileSaveAs"/>
+ <menuitem name="SaveBackgroundAsFDP" verb="SaveBackgroundAs"/>
+ <menuitem name="AddPageBookmarkFDP" verb="FileAddBookmark"/>
+ <menuitem name="CopyPageLocationFDP" verb="CopyPageLocation"/>
+ <separator name="FDBSep2"/>
+ <menuitem name="OpenFrameFDP" verb="OpenFrame"/>
+ <menuitem name="OpenFrameInNewWindowFDP" verb="OpenFrameInNewWindow"/>
+ <menuitem name="OpenFrameInNewTabFDP" verb="OpenFrameInNewTab"/>
+</popup>
+
+<popup name="EphyLinkPopup" verb="FakeToplevel">
+ <menuitem name="OpenLinkLP" verb="OpenLink"/>
+ <menuitem name="OpenLinkInNewWindowLP" verb="OpenLinkInNewWindow"/>
+ <menuitem name="OpenLinkInNewTabLP" verb="OpenLinkInNewTab"/>
+ <menuitem name="DownloadLinkLP" verb="DownloadLink"/>
+ <menuitem name="AddLinkBookmarkLP" verb="AddLinkBookmark"/>
+ <menuitem name="CopyLinkLocationLP" verb="CopyLinkLocation"/>
+ <menuitem name="CopyEmailLinkLP" verb="CopyEmail"/>
+</popup>
+
+<popup name="EphyImagePopup" verb="FakeToplevel">
+ <menuitem name="OpenImageIP" verb="OpenImage"/>
+ <menuitem name="OpenImageInNewWindowIP" verb="OpenImageInNewWindow"/>
+ <menuitem name="OpenImageInNewTabIP" verb="OpenImageInNewTab"/>
+ <menuitem name="SaveImageAsIP" verb="SaveImageAs"/>
+ <menuitem name="SetImageAsBackgroundIP" verb="SetImageAsBackground"/>
+ <menuitem name="CopyImageLocationIP" verb="CopyImageLocation"/>
+</popup>
+
+<popup name="EphyImageLinkPopup" verb="FakeToplevel">
+ <menuitem name="OpenLinkILP" verb="OpenLink"/>
+ <menuitem name="OpenLinkInNewWindowILP" verb="OpenLinkInNewWindow"/>
+ <menuitem name="OpenLinkInNewTabILP" verb="OpenLinkInNewTab"/>
+ <menuitem name="DownloadLinkILP" verb="DownloadLink"/>
+ <menuitem name="AddLinkBookmarkILP" verb="AddLinkBookmark"/>
+ <menuitem name="CopyLinkLocationILP" verb="CopyLinkLocation"/>
+ <menuitem name="CopyEmailLinkILP" verb="CopyEmail"/>
+ <separator name="LPSep1"/>
+ <menuitem name="OpenImageILP" verb="OpenImage"/>
+ <menuitem name="OpenImageInNewWindowILP" verb="OpenImageInNewWindow"/>
+ <menuitem name="OpenImageInNewTabILP" verb="OpenImageInNewTab"/>
+ <menuitem name="SaveImageAsILP" verb="SaveImageAs"/>
+ <menuitem name="SetImageAsBackgroundILP" verb="SetImageAsBackground"/>
+ <menuitem name="CopyImageLocationILP" verb="CopyImageLocation"/>
+</popup>
- <popup name="EphyEmbedInputPopup">
- <menuitem name="EditCut"
- pixtype="stock" pixname="gtk-cut"
- verb=""/>
- <menuitem name="EditCopy"
- pixtype="stock" pixname="gtk-copy"
- verb=""/>
- <menuitem name="EditPaste"
- pixtype="stock" pixname="gtk-paste"
- verb=""/>
- </popup>
-
- <popup name="EphyEmbedDocumentPopup">
- <placeholder name="NavigationItems">
- <menuitem name="GoBack"
- pixtype="stock" pixname="gtk-go-back"
- verb=""/>
-
- <menuitem name="GoForward"
- pixtype="stock" pixname="gtk-go-forward"
- verb=""/>
-
- <menuitem name="GoReload"
- pixtype="stock" pixname="gtk-refresh"
- verb=""/>
-
- <separator/>
- </placeholder>
-
- <menuitem name="DPSavePageAs"
- pixtype="stock" pixname="gtk-save"
- verb=""/>
-
- <menuitem name="DPSaveBackgroundAs" verb=""/>
-
- <menuitem name="DPViewSource" _label="Page Source"
- verb="ViewPageSource"/>
-
- <menuitem name="DPAddPageBookmark"
- verb=""/>
-
- <menuitem name="DPCopyLocation"
- pixtype="stock" pixname="gtk-copy"
- verb=""/>
-
- <placeholder name="FrameItems">
- <separator/>
- <menuitem name="DPOpenFrame" verb=""/>
- <menuitem name="DPOpenFrameInNewWindow" verb=""/>
- <menuitem name="DPOpenFrameInNewTab" verb=""/>
- <menuitem name="DPReloadFrame" verb=""/>
- <menuitem name="DPAddFrameBookmark" verb=""/>
- </placeholder>
- </popup>
-
- <popup name="EphyEmbedElementPopup">
- <placeholder name="LinkItems">
- <menuitem name="EPOpenLink"
- pixtype="stock" pixname="gtk-open"
- verb=""/>
-
- <menuitem name="EPOpenInNewWindow" verb=""/>
-
- <menuitem name="EPOpenInNewTab" verb=""/>
-
- <menuitem name="EPDownloadLink" verb=""/>
-
- <menuitem name="EPAddBookmark"
- pixtype="stock" pixname="gtk-add"
- verb=""/>
-
- <menuitem name="EPCopyLinkLocation"
- pixtype="stock" pixname="gtk-copy"
- verb=""/>
- </placeholder>
- <placeholder name="EmailLinkItems">
- <menuitem name="EPCopyEmail"
- pixtype="stock" pixname="gtk-copy"
- verb=""/>
- </placeholder>
- <placeholder name="BetweenElements1">
- <separator/>
- </placeholder>
-
- <placeholder name="ImageItems">
- <menuitem name="EPOpenImage"
- pixtype="stock" pixname="gtk-open"
- verb=""/>
-
- <menuitem name="EPOpenImageInNewWindow" verb=""/>
- <menuitem name="EPOpenImageInNewTab" verb=""/>
-
- <menuitem name="EPSaveImageAs"
- pixtype="stock" pixname="gtk-save"
- verb=""/>
-
- <menuitem name="EPSetImageAsBackground" verb=""/>
-
- <menuitem name="EPCopyImageLocation"
- pixtype="stock" pixname="gtk-copy"
- verb=""/>
- </placeholder>
- </popup>
</popups>
-
-<dockitem name="Toolbar" behavior="exclusive" config="0">
-</dockitem>
-
-<dockitem name="PrintPreview" behavior="exclusive">
- <toolitem name="PPVGotoFirst"
- pixtype="stock" pixname="gtk-goto-first"
- verb="PPVGotoFirst"/>
- <toolitem name="PPVGoBack"
- pixtype="stock" pixname="gtk-go-back"
- verb="PPVGoBack"/>
- <toolitem name="PPVGoForward"
- pixtype="stock" pixname="gtk-go-forward"
- priority="1"
- verb="PPVGoForward"/>
- <toolitem name="PPVGotoLast"
- pixtype="stock" pixname="gtk-goto-last"
- verb="PPVGotoLast"/>
- <toolitem name="Close" _label="Close"
- pixtype="stock" pixname="gtk-close"
- priority="1"
- verb="PPVClose"/>
-</dockitem>
-
-<status resize_grip="0">
- <item name="main"/>
- <control name="SecurityIconWrapper"/>
- <control name="ProgressWrapper"/>
-</status>
-
</Root>
diff --git a/lib/Makefile.am b/lib/Makefile.am
index d131235bb..7d324f0e9 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = widgets toolbar
+SUBDIRS = widgets egg
INCLUDES = \
$(WARN_CFLAGS) \
@@ -59,7 +59,7 @@ libephy_la_SOURCES = \
libephy_la_LIBADD = \
$(top_builddir)/lib/widgets/libephywidgets.la \
- $(top_builddir)/lib/toolbar/libephytoolbar.la
+ $(top_builddir)/lib/egg/libegg.la
BUILT_SOURCES=ephy-marshal.c ephy-marshal.h
diff --git a/lib/egg/Makefile.am b/lib/egg/Makefile.am
new file mode 100644
index 000000000..93abfd0d3
--- /dev/null
+++ b/lib/egg/Makefile.am
@@ -0,0 +1,59 @@
+INCLUDES = \
+ $(EPIPHANY_DEPENDENCY_CFLAGS) \
+ -DGTK_DISABLE_DEPRECATED \
+ -DGDK_DISABLE_DEPRECATED \
+ -DG_DISABLE_DEPRECATED
+
+noinst_LTLIBRARIES = libegg.la
+
+libegg_la_SOURCES = \
+ egg-action.c \
+ egg-action-group.c \
+ egg-toggle-action.c \
+ egg-radio-action.c \
+ egg-markup.c \
+ egg-menu-merge.c \
+ egg-accel-dialog.c \
+ eggradiotoolbutton.c \
+ eggtoggletoolbutton.c \
+ eggtoolitem.c \
+ eggseparatortoolitem.c \
+ eggtoolbar.c \
+ eggtoolbutton.c \
+ eggmarshalers.c
+
+noinst_HEADERS = \
+ egg-menu.h \
+ egg-action.h \
+ egg-action-group.h \
+ egg-toggle-action.h \
+ egg-radio-action.h \
+ egg-markup.h \
+ egg-menu-merge.h \
+ egg-accel-dialog.h \
+ eggradiotoolbutton.h \
+ eggtoggletoolbutton.h \
+ eggtoolitem.h \
+ eggseparatortoolitem.h \
+ eggtoolbar.h \
+ eggtoolbutton.h
+
+eggmarshalers.h:
+ cd $(srcdir) \
+ && $(GLIB_GENMARSHAL) --prefix=_egg_marshal eggmarshalers.list --header > xgen-emh \
+ && cp xgen-emh eggmarshalers.h \
+ && rm -f xgen-emh xgen-emh~
+
+eggmarshalers.c:
+ cd $(srcdir) \
+ && $(GLIB_GENMARSHAL) --prefix=_egg_marshal eggmarshalers.list --body > xgen-emc \
+ && cp xgen-emc eggmarshalers.c \
+ && rm -f xgen-emc xgen-emc~
+
+egg-marshal.c: eggmarshalers.h eggmarshalers.c
+
+noinst_HEADERS = \
+ eggmarshalers.h
+
+EXTRA_DIST= \
+ eggmarshalers.list
diff --git a/lib/egg/egg-accel-dialog.c b/lib/egg/egg-accel-dialog.c
new file mode 100644
index 000000000..4173cbf02
--- /dev/null
+++ b/lib/egg/egg-accel-dialog.c
@@ -0,0 +1,332 @@
+#include "egg-accel-dialog.h"
+
+static void egg_accel_dialog_init (EggAccelDialog *self);
+static void egg_accel_dialog_class_init (EggAccelDialogClass *class);
+
+GType
+egg_accel_dialog_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EggAccelDialogClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) egg_accel_dialog_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+
+ sizeof (EggAccelDialog),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) egg_accel_dialog_init,
+ };
+
+ type = g_type_register_static (GTK_TYPE_DIALOG,
+ "EggAccelDialog",
+ &type_info, 0);
+ }
+ return type;
+}
+
+static void
+egg_accel_dialog_class_init (EggAccelDialogClass *class)
+{
+}
+
+static void accel_path_selection_changed (GtkTreeSelection *selection,
+ EggAccelDialog *self);
+static void accel_path_set (GtkWidget *button, EggAccelDialog *self);
+static void accel_path_reset (GtkWidget *button, EggAccelDialog *self);
+
+static void
+egg_accel_dialog_init (EggAccelDialog *self)
+{
+ GtkCellRenderer *renderer;
+ GtkWidget *swin;
+ GtkWidget *table;
+
+ /* set up the list store for all the accelerators */
+ self->accel_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (self->accel_store),
+ 0, GTK_SORT_ASCENDING);
+ egg_accel_dialog_rescan_accels (self);
+
+
+ swin = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (self)->vbox), swin,
+ TRUE, TRUE, 0);
+ gtk_widget_show (swin);
+
+ /* set up a two column view of the model in browse selection mode */
+ self->accel_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(self->accel_store));
+ gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (self->accel_view), TRUE);
+ gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (self->accel_view)),
+ GTK_SELECTION_BROWSE);
+ g_signal_connect_object (gtk_tree_view_get_selection (GTK_TREE_VIEW (self->accel_view)),
+ "changed", G_CALLBACK (accel_path_selection_changed),
+ G_OBJECT (self), 0);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (G_OBJECT (renderer), "xalign", 0.0, NULL);
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (self->accel_view),
+ -1, "Path", renderer,
+ "text", 0,
+ NULL);
+ gtk_tree_view_column_set_sort_column_id (gtk_tree_view_get_column (GTK_TREE_VIEW (self->accel_view), 0), 0);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (G_OBJECT (renderer), "xalign", 0.0, NULL);
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (self->accel_view),
+ -1, "Accel", renderer,
+ "text", 1,
+ NULL);
+ gtk_tree_view_column_set_sort_column_id (gtk_tree_view_get_column (GTK_TREE_VIEW (self->accel_view), 1), 1);
+
+ gtk_container_add (GTK_CONTAINER (swin), self->accel_view);
+ gtk_widget_show (self->accel_view);
+
+ table = gtk_table_new (2, 4, FALSE);
+ gtk_container_set_border_width (GTK_CONTAINER (table), 2);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 2);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 2);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (self)->vbox), table, FALSE,TRUE, 0);
+ gtk_widget_show (table);
+
+ /* widgets for editing accels */
+ self->shift_toggle = gtk_check_button_new_with_mnemonic ("S_hift");
+ gtk_table_attach (GTK_TABLE (table), self->shift_toggle,
+ 0, 1, 0, 1,
+ GTK_FILL, GTK_FILL, 0, 0);
+ gtk_widget_show (self->shift_toggle);
+ self->ctrl_toggle = gtk_check_button_new_with_mnemonic ("_Ctrl");
+ gtk_table_attach (GTK_TABLE (table), self->ctrl_toggle,
+ 1, 2, 0, 1,
+ GTK_FILL, GTK_FILL, 0, 0);
+ gtk_widget_show (self->ctrl_toggle);
+ self->alt_toggle = gtk_check_button_new_with_mnemonic ("_Alt");
+ gtk_table_attach (GTK_TABLE (table), self->alt_toggle,
+ 2, 3, 0, 1,
+ GTK_FILL, GTK_FILL, 0, 0);
+ gtk_widget_show (self->alt_toggle);
+ self->key_entry = gtk_entry_new ();
+ gtk_table_attach (GTK_TABLE (table), self->key_entry,
+ 0, 3, 1, 2,
+ GTK_FILL|GTK_EXPAND, GTK_FILL, 0, 0);
+ gtk_widget_show (self->key_entry);
+
+ /* buttons for changing path */
+ self->set_button = gtk_button_new_with_mnemonic ("_Set");
+ gtk_table_attach (GTK_TABLE (table), self->set_button,
+ 3, 4, 0, 1,
+ GTK_FILL, GTK_FILL, 0, 0);
+ gtk_widget_show (self->set_button);
+ self->reset_button = gtk_button_new_with_mnemonic ("_Reset");
+ gtk_table_attach (GTK_TABLE (table), self->reset_button,
+ 3, 4, 1, 2,
+ GTK_FILL, GTK_FILL, 0, 0);
+ /*gtk_widget_show (self->reset_button);*/
+
+ g_signal_connect_object (self->set_button, "clicked",
+ G_CALLBACK (accel_path_set), G_OBJECT (self), 0);
+ g_signal_connect_object (self->reset_button, "clicked",
+ G_CALLBACK (accel_path_reset), G_OBJECT (self), 0);
+
+
+ self->ok_button = gtk_dialog_add_button (GTK_DIALOG (self),
+ GTK_STOCK_OK,
+ GTK_RESPONSE_OK);
+ gtk_widget_grab_default (self->ok_button);
+}
+
+static void
+accel_map_foreach (gpointer data,
+ const gchar *accel_path,
+ guint accel_key,
+ guint accel_mods,
+ gboolean changed)
+{
+ EggAccelDialog *self = data;
+ GtkTreeIter iter;
+ gchar *accel_name;
+
+ gtk_list_store_append (self->accel_store, &iter);
+ if (accel_key != 0)
+ accel_name = gtk_accelerator_name (accel_key, accel_mods);
+ else
+ accel_name = "";
+
+ gtk_list_store_set (self->accel_store, &iter,
+ 0, accel_path,
+ 1, accel_name,
+ -1);
+ if (accel_key != 0)
+ g_free(accel_name);
+}
+
+void
+egg_accel_dialog_rescan_accels (EggAccelDialog *self)
+{
+ g_return_if_fail (EGG_IS_ACCEL_DIALOG (self));
+
+ gtk_list_store_clear (self->accel_store);
+ gtk_accel_map_foreach (self, accel_map_foreach);
+}
+
+/* make sure the currently selected accel is up to date */
+static void
+refresh_selected_row (EggAccelDialog *self)
+{
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+
+ g_return_if_fail (EGG_IS_ACCEL_DIALOG (self));
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->accel_view));
+ if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
+ char *accel_path;
+
+ /* get the accel path for the selected row */
+ gtk_tree_model_get (GTK_TREE_MODEL (self->accel_store), &iter,
+ 0, &accel_path, -1);
+ if (accel_path) {
+ GtkAccelKey key;
+
+ if (gtk_accel_map_lookup_entry (accel_path, &key)) {
+ char *accel_name;
+
+ accel_name = gtk_accelerator_name (key.accel_key, key.accel_mods);
+ gtk_list_store_set (self->accel_store, &iter, 1, accel_name, -1);
+ g_free (accel_name);
+ }
+ g_free (accel_path);
+ }
+ }
+}
+
+static void
+accel_path_selection_changed (GtkTreeSelection *selection,
+ EggAccelDialog *self)
+{
+ GtkTreeIter iter;
+
+ /* just make sure the selected row is up to date */
+ refresh_selected_row (self);
+
+ if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
+ char *accel_path;
+
+ /* get the accel path for the selected row */
+ gtk_tree_model_get (GTK_TREE_MODEL (self->accel_store), &iter,
+ 0, &accel_path, -1);
+ if (accel_path) {
+ GtkAccelKey key;
+
+ if (gtk_accel_map_lookup_entry (accel_path, &key)) {
+ gchar *keyname;
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->shift_toggle),
+ (key.accel_mods & GDK_SHIFT_MASK)!=0);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->ctrl_toggle),
+ (key.accel_mods & GDK_CONTROL_MASK)!=0);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->alt_toggle),
+ (key.accel_mods & GDK_MOD1_MASK)!=0);
+ keyname = gdk_keyval_name (key.accel_key);
+ if (keyname)
+ gtk_entry_set_text (GTK_ENTRY (self->key_entry), keyname);
+ else
+ gtk_entry_set_text (GTK_ENTRY (self->key_entry), "");
+ }
+ }
+ g_free (accel_path);
+ }
+}
+
+static void
+accel_path_set (GtkWidget *button, EggAccelDialog *self)
+{
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ gboolean changed = FALSE;
+
+ g_return_if_fail (EGG_IS_ACCEL_DIALOG (self));
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->accel_view));
+ if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
+ char *accel_path;
+
+ /* get the accel path for the selected row */
+ gtk_tree_model_get (GTK_TREE_MODEL (self->accel_store), &iter,
+ 0, &accel_path, -1);
+ if (accel_path) {
+ GdkModifierType accel_mods = 0;
+ const gchar *key_name;
+ guint accel_key = 0;
+
+ /* get modifiers */
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(self->shift_toggle)))
+ accel_mods |= GDK_SHIFT_MASK;
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(self->ctrl_toggle)))
+ accel_mods |= GDK_CONTROL_MASK;
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(self->alt_toggle)))
+ accel_mods |= GDK_MOD1_MASK;
+
+ key_name = gtk_entry_get_text (GTK_ENTRY (self->key_entry));
+ /* check to see if entyr is empty -- if so, unset accel */
+ if (key_name[0] != '\0') {
+ accel_key = gdk_keyval_from_name (key_name);
+
+ if (accel_key) {
+ changed = gtk_accel_map_change_entry (accel_path,
+ accel_key, accel_mods,
+ TRUE);
+ }
+ } else
+ changed = gtk_accel_map_change_entry (accel_path, 0, 0, TRUE);
+
+ g_free (accel_path);
+ }
+ }
+ if (!changed)
+ gdk_beep ();
+ accel_path_selection_changed (selection, self);
+}
+
+static void
+accel_path_reset (GtkWidget *button, EggAccelDialog *self)
+{
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ gboolean changed = FALSE;
+
+ g_return_if_fail (EGG_IS_ACCEL_DIALOG (self));
+
+ g_message ("don't know how to reset to defaults :(");
+ return;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->accel_view));
+ if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
+ char *accel_path;
+
+ /* get the accel path for the selected row */
+ gtk_tree_model_get (GTK_TREE_MODEL (self->accel_store), &iter,
+ 0, &accel_path, -1);
+ if (accel_path) {
+ changed = gtk_accel_map_change_entry (accel_path, 0, 0, TRUE);
+ g_free (accel_path);
+ }
+ }
+ if (!changed)
+ gdk_beep ();
+ accel_path_selection_changed (selection, self);
+}
+
+GtkWidget *
+egg_accel_dialog_new (void)
+{
+ return g_object_new(EGG_TYPE_ACCEL_DIALOG, NULL);
+}
diff --git a/lib/egg/egg-accel-dialog.h b/lib/egg/egg-accel-dialog.h
new file mode 100644
index 000000000..8aa2fc435
--- /dev/null
+++ b/lib/egg/egg-accel-dialog.h
@@ -0,0 +1,43 @@
+#ifndef EGG_ACCEL_DIALOG_H
+#define EGG_ACCEL_DIALOG_H
+
+#include <gtk/gtk.h>
+
+#define EGG_TYPE_ACCEL_DIALOG (egg_accel_dialog_get_type ())
+#define EGG_ACCEL_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_ACCEL_DIALOG, EggAccelDialog))
+#define EGG_ACCEL_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_ACCEL_DIALOG, EggAccelDialogClass))
+#define EGG_IS_ACCEL_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_ACCEL_DIALOG))
+#define EGG_IS_ACCEL_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EGG_TYPE_ACCEL_DIALOG))
+#define EGG_ACCEL_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_ACCEL_DIALOG, EggAccelDialogClass))
+
+typedef struct _EggAccelDialog EggAccelDialog;
+typedef struct _EggAccelDialogClass EggAccelDialogClass;
+
+struct _EggAccelDialog {
+ GtkDialog parent;
+
+ GtkListStore *accel_store;
+
+ GtkWidget *accel_view;
+
+ GtkWidget *shift_toggle;
+ GtkWidget *ctrl_toggle;
+ GtkWidget *alt_toggle;
+ GtkWidget *key_entry;
+
+ GtkWidget *set_button;
+ GtkWidget *reset_button;
+
+ GtkWidget *ok_button;
+};
+
+struct _EggAccelDialogClass {
+ GtkDialogClass parent_class;
+};
+
+GType egg_accel_dialog_get_type (void);
+GtkWidget *egg_accel_dialog_new (void);
+
+void egg_accel_dialog_rescan_accels (EggAccelDialog *accel_dialog);
+
+#endif
diff --git a/lib/egg/egg-action-group.c b/lib/egg/egg-action-group.c
new file mode 100644
index 000000000..b1aba64a5
--- /dev/null
+++ b/lib/egg/egg-action-group.c
@@ -0,0 +1,297 @@
+#include "egg-action-group.h"
+#include "egg-toggle-action.h"
+#include "egg-radio-action.h"
+
+#ifndef _
+# define _(s) (s)
+#endif
+
+static void egg_action_group_init (EggActionGroup *self);
+static void egg_action_group_class_init (EggActionGroupClass *class);
+
+GType
+egg_action_group_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EggActionGroupClass),
+ (GBaseInitFunc) egg_action_group_init,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) egg_action_group_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+
+ sizeof (EggActionGroup),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) egg_action_group_init,
+ };
+
+ type = g_type_register_static (G_TYPE_OBJECT, "EggActionGroup",
+ &type_info, 0);
+ }
+
+ return type;
+}
+
+static GObjectClass *parent_class = NULL;
+static void egg_action_group_finalize (GObject *object);
+static EggAction *egg_action_group_real_get_action (EggActionGroup *self,
+ const gchar *name);
+
+static void
+egg_action_group_class_init (EggActionGroupClass *class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (class);
+ parent_class = g_type_class_peek_parent (class);
+
+ object_class->finalize = egg_action_group_finalize;
+ class->get_action = egg_action_group_real_get_action;
+}
+
+static void
+egg_action_group_init (EggActionGroup *self)
+{
+ self->name = NULL;
+ self->actions = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_object_unref);
+}
+
+/**
+ * egg_action_group_new:
+ * @name: the name of the action group
+ *
+ * Creates a new EggActionGroup object.
+ *
+ * Returns: the new EggActionGroup
+ */
+EggActionGroup *
+egg_action_group_new(const gchar *name)
+{
+ EggActionGroup *self;
+
+ self = g_object_new (EGG_TYPE_ACTION_GROUP, NULL);
+ self->name = g_strdup (name);
+
+ return self;
+}
+
+static void
+egg_action_group_finalize (GObject *object)
+{
+ EggActionGroup *self;
+
+ self = EGG_ACTION_GROUP (object);
+
+ g_free (self->name);
+ self->name = NULL;
+
+ g_hash_table_destroy (self->actions);
+ self->actions = NULL;
+
+ if (parent_class->finalize)
+ (* parent_class->finalize) (object);
+}
+
+static EggAction *
+egg_action_group_real_get_action (EggActionGroup *self,
+ const gchar *action_name)
+{
+ return g_hash_table_lookup (self->actions, action_name);
+}
+
+/**
+ * egg_action_group_get_name:
+ * @action_group: the action group
+ *
+ * Returns: the name of the EggActionGroup
+ */
+const gchar *
+egg_action_group_get_name (EggActionGroup *action_group)
+{
+ g_return_val_if_fail (EGG_IS_ACTION_GROUP (action_group), NULL);
+
+ return action_group->name;
+}
+
+/**
+ * egg_action_group_get_action:
+ * @action_group: the action group
+ * @action_name: the name of the action
+ *
+ * This function looks up an action in the action group by name.
+ *
+ * Returns: the action, or NULL if no action by that name exists
+ */
+EggAction *
+egg_action_group_get_action (EggActionGroup *action_group,
+ const gchar *action_name)
+{
+ g_return_val_if_fail (EGG_IS_ACTION_GROUP (action_group), NULL);
+ g_return_val_if_fail (EGG_ACTION_GROUP_GET_CLASS (action_group)->get_action != NULL, NULL);
+
+ return (* EGG_ACTION_GROUP_GET_CLASS (action_group)->get_action)
+ (action_group, action_name);
+}
+
+/**
+ * egg_action_group_add_action:
+ * @action_group: the action group
+ * @action: an action
+ *
+ * This function adds an action object to the action group.
+ */
+void
+egg_action_group_add_action (EggActionGroup *action_group,
+ EggAction *action)
+{
+ g_return_if_fail (EGG_IS_ACTION_GROUP (action_group));
+ g_return_if_fail (EGG_IS_ACTION (action));
+ g_return_if_fail (action->name != NULL);
+
+ g_hash_table_insert (action_group->actions, g_strdup (action->name),
+ g_object_ref (action));
+}
+
+/**
+ * egg_action_group_removes_action:
+ * @action_group: the action group
+ * @action: an action
+ *
+ * This function removes an action object to the action group.
+ */
+void
+egg_action_group_remove_action (EggActionGroup *action_group,
+ EggAction *action)
+{
+ g_return_if_fail (EGG_IS_ACTION_GROUP (action_group));
+ g_return_if_fail (EGG_IS_ACTION (action));
+ g_return_if_fail (action->name != NULL);
+
+ /* extra protection to make sure action->name is valid */
+ g_object_ref (action);
+ g_hash_table_remove (action_group->actions, action->name);
+ g_object_unref (action);
+}
+
+static void
+add_single_action (gpointer key, gpointer value, gpointer user_data)
+{
+ GList **list = user_data;
+
+ *list = g_list_prepend (*list, value);
+}
+
+/**
+ * egg_action_group_list_actions:
+ * @action_group: the action group
+ *
+ * Lists the actions in the action group.
+ *
+ * Returns: an allocated list of the action objects in the action group
+ */
+GList *
+egg_action_group_list_actions (EggActionGroup *action_group)
+{
+ GList *actions = NULL;
+
+ g_hash_table_foreach (action_group->actions, add_single_action, &actions);
+
+ return g_list_reverse (actions);
+}
+
+
+/**
+ * egg_action_group_add_actions:
+ * @action_group: the action group
+ * @entries: an array of action descriptions
+ * @n_entries: the number of entries
+ *
+ * This is a convenience routine to create a number of actions and add
+ * them to the action group. Each member of the array describes an
+ * action to create.
+ */
+void
+egg_action_group_add_actions (EggActionGroup *action_group,
+ EggActionGroupEntry *entries,
+ guint n_entries)
+{
+ guint i;
+
+ for (i = 0; i < n_entries; i++)
+ {
+ EggAction *action;
+ GType action_type;
+ gchar *accel_path;
+
+ switch (entries[i].entry_type) {
+ case NORMAL_ACTION:
+ action_type = EGG_TYPE_ACTION;
+ break;
+ case TOGGLE_ACTION:
+ action_type = EGG_TYPE_TOGGLE_ACTION;
+ break;
+ case RADIO_ACTION:
+ action_type = EGG_TYPE_RADIO_ACTION;
+ break;
+ default:
+ g_warning ("unsupported action type");
+ action_type = EGG_TYPE_ACTION;
+ }
+
+ action = g_object_new (action_type,
+ "name", entries[i].name,
+ "label", _(entries[i].label),
+ "tooltip", _(entries[i].tooltip),
+ "stock_id", entries[i].stock_id,
+ NULL);
+
+ if (entries[i].entry_type == RADIO_ACTION &&
+ entries[i].extra_data != NULL)
+ {
+ EggAction *radio_action;
+ GSList *group;
+
+ radio_action =
+ egg_action_group_get_action (EGG_ACTION_GROUP (action_group),
+ entries[i].extra_data);
+ if (radio_action)
+ {
+ group = egg_radio_action_get_group (EGG_RADIO_ACTION (radio_action));
+ egg_radio_action_set_group (EGG_RADIO_ACTION (action), group);
+ }
+ else
+ g_warning (G_STRLOC " could not look up `%s'", entries[i].extra_data);
+ }
+
+ if (entries[i].callback)
+ g_signal_connect (action, "activate",
+ entries[i].callback, entries[i].user_data);
+
+ /* set the accel path for the menu item */
+ accel_path = g_strconcat ("<Actions>/", action_group->name, "/",
+ entries[i].name, NULL);
+ if (entries[i].accelerator)
+ {
+ guint accel_key = 0;
+ GdkModifierType accel_mods;
+
+ gtk_accelerator_parse (entries[i].accelerator, &accel_key,
+ &accel_mods);
+ if (accel_key)
+ gtk_accel_map_add_entry (accel_path, accel_key, accel_mods);
+ }
+
+ egg_action_set_accel_path (action, accel_path);
+ g_free(accel_path);
+
+ egg_action_group_add_action (action_group, action);
+ g_object_unref (action);
+ }
+}
diff --git a/lib/egg/egg-action-group.h b/lib/egg/egg-action-group.h
new file mode 100644
index 000000000..2ee05dcec
--- /dev/null
+++ b/lib/egg/egg-action-group.h
@@ -0,0 +1,71 @@
+#ifndef EGG_ACTION_GROUP_H
+#define EGG_ACTION_GROUP_H
+
+#include <gtk/gtk.h>
+#include <egg-action.h>
+
+#define EGG_TYPE_ACTION_GROUP (egg_action_group_get_type ())
+#define EGG_ACTION_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_ACTION_GROUP, EggActionGroup))
+#define EGG_ACTION_GROUP_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), EGG_TYPE_ACTION_GROUP, EggActionGroupClass))
+#define EGG_IS_ACTION_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_ACTION_GROUP))
+#define EGG_IS_ACTION_GROUP_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), EGG_TYPE_ACTION_GROUP))
+#define EGG_ACTION_GROUP_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), EGG_TYPE_ACTION_GROUP, EggActionGroupClass))
+
+typedef struct _EggActionGroup EggActionGroup;
+typedef struct _EggActionGroupClass EggActionGroupClass;
+typedef struct _EggActionGroupEntry EggActionGroupEntry;
+
+struct _EggActionGroup
+{
+ GObject parent;
+
+ gchar *name;
+ GHashTable *actions;
+};
+
+struct _EggActionGroupClass
+{
+ GObjectClass parent_class;
+
+ EggAction *(* get_action) (EggActionGroup *action_group,
+ const gchar *action_name);
+};
+
+typedef enum {
+ NORMAL_ACTION,
+ TOGGLE_ACTION,
+ RADIO_ACTION
+} EggActionGroupEntryType;
+
+struct _EggActionGroupEntry {
+ gchar *name;
+ gchar *label;
+ gchar *stock_id;
+ gchar *accelerator;
+ gchar *tooltip;
+
+ GCallback callback;
+ gpointer user_data;
+
+ EggActionGroupEntryType entry_type;
+ gchar *extra_data;
+};
+
+GType egg_action_group_get_type (void);
+
+EggActionGroup *egg_action_group_new (const gchar *name);
+
+const gchar *egg_action_group_get_name (EggActionGroup *action_group);
+EggAction *egg_action_group_get_action (EggActionGroup *action_group,
+ const gchar *action_name);
+GList *egg_action_group_list_actions (EggActionGroup *action_group);
+void egg_action_group_add_action (EggActionGroup *action_group,
+ EggAction *action);
+void egg_action_group_remove_action (EggActionGroup *action_group,
+ EggAction *action);
+
+void egg_action_group_add_actions (EggActionGroup *action_group,
+ EggActionGroupEntry *entries,
+ guint n_entries);
+
+#endif
diff --git a/lib/egg/egg-action.c b/lib/egg/egg-action.c
new file mode 100644
index 000000000..360ba358e
--- /dev/null
+++ b/lib/egg/egg-action.c
@@ -0,0 +1,961 @@
+#include "egg-action.h"
+#include "eggtoolbutton.h"
+
+#ifndef _
+# define _(s) (s)
+#endif
+
+/* some code for making arbitrary GtkButtons that act like toolbar
+ * buttons */
+static GtkWidget *tool_button_new (GType button_type,
+ const gchar *text,
+ GtkWidget *icon);
+static GtkWidget *tool_button_get_label (GtkWidget *button);
+static GtkWidget *tool_button_get_icon (GtkWidget *button);
+
+enum {
+ ACTIVATE,
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+ PROP_NAME,
+ PROP_LABEL,
+ PROP_SHORT_LABEL,
+ PROP_TOOLTIP,
+ PROP_STOCK_ID,
+ PROP_SENSITIVE,
+ PROP_VISIBLE,
+};
+
+static void egg_action_init (EggAction *action);
+static void egg_action_class_init (EggActionClass *class);
+
+static GQuark accel_path_id = 0;
+static const gchar *accel_path_key = "EggAction::accel_path";
+
+GType
+egg_action_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EggActionClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) egg_action_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+
+ sizeof (EggAction),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) egg_action_init,
+ };
+
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "EggAction",
+ &type_info, 0);
+ }
+ return type;
+}
+
+static void egg_action_finalize (GObject *object);
+static void egg_action_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void egg_action_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static GtkWidget *create_menu_item (EggAction *action);
+static GtkWidget *create_tool_item (EggAction *action);
+static void connect_proxy (EggAction *action,
+ GtkWidget *proxy);
+static void disconnect_proxy (EggAction *action,
+ GtkWidget *proxy);
+
+static GObjectClass *parent_class = NULL;
+static guint action_signals[LAST_SIGNAL] = { 0 };
+
+
+static void
+egg_action_class_init (EggActionClass *class)
+{
+ GObjectClass *object_class;
+
+ accel_path_id = g_quark_from_static_string(accel_path_key);
+
+ parent_class = g_type_class_peek_parent (class);
+ object_class = G_OBJECT_CLASS(class);
+
+ object_class->finalize = egg_action_finalize;
+ object_class->set_property = egg_action_set_property;
+ object_class->get_property = egg_action_get_property;
+
+ class->activate = NULL;
+
+ class->create_menu_item = create_menu_item;
+ class->create_tool_item = create_tool_item;
+ class->connect_proxy = connect_proxy;
+ class->disconnect_proxy = disconnect_proxy;
+
+ class->menu_item_type = GTK_TYPE_IMAGE_MENU_ITEM;
+ class->toolbar_item_type = EGG_TYPE_TOOL_BUTTON;
+
+ g_object_class_install_property (object_class,
+ PROP_NAME,
+ g_param_spec_string ("name",
+ _("Name"),
+ _("A unique name for the action."),
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_LABEL,
+ g_param_spec_string ("label",
+ _("Label"),
+ _("The label used for menu items and buttons that activate this action."),
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_SHORT_LABEL,
+ g_param_spec_string ("short_label",
+ _("Short label"),
+ _("A shorter label that may be used on toolbar buttons."),
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_TOOLTIP,
+ g_param_spec_string ("tooltip",
+ _("Tooltip"),
+ _("A tooltip for this action."),
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_STOCK_ID,
+ g_param_spec_string ("stock_id",
+ _("Stock Icon"),
+ _("The stock icon displayed in widgets representing this action."),
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_SENSITIVE,
+ g_param_spec_boolean ("sensitive",
+ _("Sensitive"),
+ _("Whether the action is enabled."),
+ TRUE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_VISIBLE,
+ g_param_spec_boolean ("visible",
+ _("Visible"),
+ _("Whether the action is visible."),
+ TRUE,
+ G_PARAM_READWRITE));
+
+ action_signals[ACTIVATE] =
+ g_signal_new ("activate",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
+ G_STRUCT_OFFSET (EggActionClass, activate), NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+
+static void
+egg_action_init (EggAction *action)
+{
+ action->name = NULL;
+ action->label = NULL;
+ action->short_label = NULL;
+ action->tooltip = NULL;
+ action->stock_id = NULL;
+
+ action->sensitive = TRUE;
+ action->visible = TRUE;
+
+ action->label_set = FALSE;
+ action->short_label_set = FALSE;
+
+ action->accel_quark = 0;
+
+ action->proxies = NULL;
+}
+
+static void
+egg_action_finalize (GObject *object)
+{
+ EggAction *action;
+
+ action = EGG_ACTION (object);
+
+ g_free (action->name);
+ g_free (action->label);
+ g_free (action->short_label);
+ g_free (action->tooltip);
+ g_free (action->stock_id);
+}
+
+static void
+egg_action_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EggAction *action;
+
+ action = EGG_ACTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_NAME:
+ g_free (action->name);
+ action->name = g_value_dup_string (value);
+ break;
+ case PROP_LABEL:
+ g_free (action->label);
+ action->label = g_value_dup_string (value);
+ action->label_set = (action->label != NULL);
+ /* if label is unset, then use the label from the stock item */
+ if (!action->label_set && action->stock_id)
+ {
+ GtkStockItem stock_item;
+
+ if (gtk_stock_lookup(action->stock_id, &stock_item))
+ action->label = g_strdup(stock_item.label);
+ }
+ /* if short_label is unset, set short_label=label */
+ if (!action->short_label_set)
+ {
+ g_free(action->short_label);
+ action->short_label = g_strdup(action->label);
+ g_object_notify(object, "short_label");
+ }
+ break;
+ case PROP_SHORT_LABEL:
+ g_free (action->short_label);
+ action->short_label = g_value_dup_string (value);
+ action->short_label_set = (action->short_label != NULL);
+ /* if short_label is unset, then use the value of label */
+ if (!action->short_label_set)
+ {
+ action->short_label = g_strdup(action->label);
+ }
+ break;
+ case PROP_TOOLTIP:
+ g_free (action->tooltip);
+ action->tooltip = g_value_dup_string (value);
+ break;
+ case PROP_STOCK_ID:
+ g_free (action->stock_id);
+ action->stock_id = g_value_dup_string (value);
+ /* update label and short_label if appropriate */
+ if (!action->label_set)
+ {
+ GtkStockItem stock_item;
+
+ g_free(action->label);
+ if (gtk_stock_lookup(action->stock_id, &stock_item))
+ action->label = g_strdup(stock_item.label);
+ else
+ action->label = NULL;
+ g_object_notify(object, "label");
+ }
+ if (!action->short_label_set)
+ {
+ g_free(action->short_label);
+ action->short_label = g_strdup(action->label);
+ g_object_notify(object, "short_label");
+ }
+ break;
+ case PROP_SENSITIVE:
+ action->sensitive = g_value_get_boolean (value);
+ break;
+ case PROP_VISIBLE:
+ action->visible = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+egg_action_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EggAction *action;
+
+ action = EGG_ACTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_NAME:
+ g_value_set_string (value, action->name);
+ break;
+ case PROP_LABEL:
+ g_value_set_string (value, action->label);
+ break;
+ case PROP_SHORT_LABEL:
+ g_value_set_string (value, action->short_label);
+ break;
+ case PROP_TOOLTIP:
+ g_value_set_string (value, action->tooltip);
+ break;
+ case PROP_STOCK_ID:
+ g_value_set_string (value, action->stock_id);
+ break;
+ case PROP_SENSITIVE:
+ g_value_set_boolean (value, action->sensitive);
+ break;
+ case PROP_VISIBLE:
+ g_value_set_boolean (value, action->visible);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GtkWidget *
+create_menu_item (EggAction *action)
+{
+ GType menu_item_type;
+
+ menu_item_type = EGG_ACTION_GET_CLASS (action)->menu_item_type;
+
+ return g_object_new (menu_item_type, NULL);
+}
+
+static GtkWidget *
+create_tool_item (EggAction *action)
+{
+ GType toolbar_item_type;
+
+ toolbar_item_type = EGG_ACTION_GET_CLASS (action)->toolbar_item_type;
+
+ return g_object_new (toolbar_item_type, NULL);
+}
+
+static void
+egg_action_remove_proxy (GtkWidget *widget, EggAction *action)
+{
+ action->proxies = g_slist_remove (action->proxies, widget);
+}
+
+static void
+egg_action_sync_property (EggAction *action, GParamSpec *pspec,
+ GtkWidget *proxy)
+{
+ const gchar *property;
+ GValue value = { 0, };
+
+ property = g_param_spec_get_name (pspec);
+
+ g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ g_object_get_property (G_OBJECT (action), property, &value);
+
+ g_object_set_property (G_OBJECT (proxy), property, &value);
+ g_value_unset (&value);
+}
+
+static void
+egg_action_sync_label (EggAction *action, GParamSpec *pspec, GtkWidget *proxy)
+{
+ GtkWidget *label = NULL;
+
+ g_return_if_fail (GTK_IS_MENU_ITEM (proxy));
+ label = GTK_BIN(proxy)->child;
+
+ if (GTK_IS_LABEL (label))
+ gtk_label_set_label (GTK_LABEL (label), action->label);
+}
+
+static void
+egg_action_sync_short_label (EggAction *action, GParamSpec *pspec,
+ GtkWidget *proxy)
+{
+ GValue value = { 0, };
+
+ g_value_init(&value, G_TYPE_STRING);
+ g_object_get_property (G_OBJECT (action), "short_label", &value);
+
+ g_object_set_property (G_OBJECT (proxy), "label", &value);
+ g_value_unset (&value);
+}
+
+static void
+egg_action_sync_stock_id (EggAction *action, GParamSpec *pspec,
+ GtkWidget *proxy)
+{
+ GtkWidget *image = NULL;
+
+ if (GTK_IS_IMAGE_MENU_ITEM (proxy))
+ {
+ image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (proxy));
+
+ if (GTK_IS_IMAGE (image))
+ gtk_image_set_from_stock (GTK_IMAGE (image),
+ action->stock_id, GTK_ICON_SIZE_MENU);
+ }
+}
+
+static GtkWidget *
+egg_action_create_menu_proxy (EggToolItem *tool_item, EggAction *action)
+{
+ return egg_action_create_menu_item (action);
+}
+
+static void
+connect_proxy (EggAction *action, GtkWidget *proxy)
+{
+ g_object_ref (action);
+ g_object_set_data_full (G_OBJECT (proxy), "egg-action", action,
+ g_object_unref);
+
+ /* add this widget to the list of proxies */
+ action->proxies = g_slist_prepend (action->proxies, proxy);
+ g_signal_connect (proxy, "destroy",
+ G_CALLBACK (egg_action_remove_proxy), action);
+
+ g_signal_connect_object (action, "notify::sensitive",
+ G_CALLBACK (egg_action_sync_property), proxy, 0);
+ gtk_widget_set_sensitive (proxy, action->sensitive);
+
+ g_signal_connect_object (action, "notify::visible",
+ G_CALLBACK (egg_action_sync_property), proxy, 0);
+ if (action->visible)
+ gtk_widget_show (proxy);
+ else
+ gtk_widget_hide (proxy);
+
+ if (GTK_IS_MENU_ITEM (proxy))
+ {
+ GtkWidget *label;
+ /* menu item specific synchronisers ... */
+
+ label = GTK_BIN (proxy)->child;
+
+ /* make sure label is a label */
+ if (label && !GTK_IS_LABEL (label))
+ {
+ gtk_container_remove (GTK_CONTAINER(proxy), label);
+ label = NULL;
+ }
+ if (!label)
+ {
+ label = g_object_new (GTK_TYPE_ACCEL_LABEL,
+ "use_underline", TRUE,
+ "xalign", 0.0,
+ "visible", TRUE,
+ "parent", proxy,
+ "accel_widget", proxy,
+ NULL);
+ }
+ gtk_label_set_label (GTK_LABEL (label), action->label);
+ g_signal_connect_object (action, "notify::label",
+ G_CALLBACK (egg_action_sync_label), proxy, 0);
+
+ if (GTK_IS_IMAGE_MENU_ITEM (proxy))
+ {
+ GtkWidget *image;
+
+ image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (proxy));
+ if (image && !GTK_IS_IMAGE(image))
+ {
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (proxy),NULL);
+ image = NULL;
+ }
+ if (!image)
+ {
+ image = gtk_image_new_from_stock (NULL,
+ GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (proxy),
+ image);
+ gtk_widget_show (image);
+ }
+ gtk_image_set_from_stock (GTK_IMAGE (image),
+ action->stock_id, GTK_ICON_SIZE_MENU);
+ g_signal_connect_object (action, "notify::stock_id",
+ G_CALLBACK (egg_action_sync_stock_id),
+ proxy, 0);
+ }
+
+ if (action->accel_quark)
+ {
+ gtk_menu_item_set_accel_path (GTK_MENU_ITEM (proxy),
+ g_quark_to_string (action->accel_quark));
+ }
+
+ g_signal_connect_object (proxy, "activate",
+ G_CALLBACK (egg_action_activate), action,
+ G_CONNECT_SWAPPED);
+ }
+ else if (EGG_IS_TOOL_BUTTON (proxy))
+ {
+ GtkWidget *label;
+ GtkWidget *icon;
+ /* toolbar button specific synchronisers ... */
+
+ /* synchronise the label */
+ g_object_set (G_OBJECT (proxy),
+ "label", action->short_label,
+ "use_underline", TRUE,
+ NULL);
+ g_signal_connect_object (action, "notify::short_label",
+ G_CALLBACK (egg_action_sync_short_label),
+ proxy, 0);
+
+ g_object_set (G_OBJECT (proxy), "stock_id", action->stock_id, NULL);
+ g_signal_connect_object (action, "notify::stock_id",
+ G_CALLBACK (egg_action_sync_property), proxy, 0);
+
+ g_signal_connect_object (proxy, "create_menu_proxy",
+ G_CALLBACK (egg_action_create_menu_proxy),
+ action, 0);
+
+ g_signal_connect_object (proxy, "clicked",
+ G_CALLBACK (egg_action_activate), action,
+ G_CONNECT_SWAPPED);
+ }
+}
+
+static void
+disconnect_proxy (EggAction *action, GtkWidget *proxy)
+{
+ static guint notify_id = 0;
+
+ if (!notify_id)
+ notify_id = g_signal_lookup ("notify", G_TYPE_OBJECT);
+
+ g_object_set_data (G_OBJECT (proxy), "egg-action", NULL);
+
+ /* remove proxy from list of proxies */
+ g_signal_handlers_disconnect_by_func (proxy,
+ G_CALLBACK (egg_action_remove_proxy),
+ action);
+ egg_action_remove_proxy (proxy, action);
+
+ /* disconnect the activate handler */
+ g_signal_handlers_disconnect_by_func (proxy,
+ G_CALLBACK (egg_action_activate),
+ action);
+
+ /* disconnect handlers for notify::* signals */
+ g_signal_handlers_disconnect_by_func (proxy,
+ G_CALLBACK (egg_action_sync_property),
+ action);
+
+ g_signal_handlers_disconnect_by_func (action,
+ G_CALLBACK (egg_action_sync_stock_id), proxy);
+
+ /* menu item specific synchronisers ... */
+ g_signal_handlers_disconnect_by_func (action,
+ G_CALLBACK (egg_action_sync_label),
+ proxy);
+
+ gtk_menu_item_set_accel_path (GTK_MENU_ITEM (proxy), NULL);
+
+ /* toolbar button specific synchronisers ... */
+ g_signal_handlers_disconnect_by_func (action,
+ G_CALLBACK (egg_action_sync_short_label),
+ proxy);
+ g_signal_handlers_disconnect_by_func (proxy,
+ G_CALLBACK (egg_action_create_menu_proxy),
+ action);
+}
+
+/**
+ * egg_action_activate:
+ * @action: the action object
+ *
+ * Calling this function will emit the "activate" signal on the
+ * specified action. It gets called by the proxy widgets when they
+ * get activated.
+ *
+ * It can also be used to manually activate an action.
+ */
+void
+egg_action_activate (EggAction *action)
+{
+ g_signal_emit (action, action_signals[ACTIVATE], 0);
+}
+
+/**
+ * egg_action_create_icon:
+ * @action: the action object
+ * @icon_size: the size of the icon that should be created.
+ *
+ * This function is intended for use by action implementations to
+ * create icons displayed in the proxy widgets.
+ *
+ * Returns: a widget that displays the icon for this action.
+ */
+GtkWidget *
+egg_action_create_icon (EggAction *action, GtkIconSize icon_size)
+{
+ if (action->stock_id)
+ return gtk_image_new_from_stock (action->stock_id, icon_size);
+ else
+ return NULL;
+}
+
+/**
+ * egg_action_create_menu_item:
+ * @action: the action object
+ *
+ * This function creates a menu item widget that proxies for the given
+ * action.
+ *
+ * Returns: a menu item connected to the action.
+ */
+GtkWidget *
+egg_action_create_menu_item (EggAction *action)
+{
+ GtkWidget *menu_item;
+
+ menu_item = (* EGG_ACTION_GET_CLASS (action)->create_menu_item) (action);
+
+ (* EGG_ACTION_GET_CLASS (action)->connect_proxy) (action, menu_item);
+
+ return menu_item;
+}
+
+/**
+ * egg_action_create_tool_item:
+ * @action: the action object
+ *
+ * This function creates a toolbar item widget that proxies for the
+ * given action.
+ *
+ * Returns: a toolbar item connected to the action.
+ */
+GtkWidget *
+egg_action_create_tool_item (EggAction *action)
+{
+ GtkWidget *button;
+
+ button = (* EGG_ACTION_GET_CLASS (action)->create_tool_item) (action);
+
+ (* EGG_ACTION_GET_CLASS (action)->connect_proxy) (action, button);
+
+ return button;
+}
+
+/**
+ * egg_action_connect_proxy:
+ * @action: the action object
+ * @proxy: the proxy widget
+ *
+ * This function connects a widget to an action object as a proxy. It
+ * will synchronise various properties of the action with the widget
+ * (such as label text, icon, tooltip, etc), and attaches a callback
+ * so that the action gets activated when the proxy widget does.
+ *
+ * If the widget is already connected to an action, it is disconnected
+ * first.
+ */
+void
+egg_action_connect_proxy (EggAction *action,
+ GtkWidget *proxy)
+{
+ EggAction *prev_action;
+
+ g_return_if_fail (EGG_IS_ACTION (action));
+ g_return_if_fail (GTK_IS_WIDGET (proxy));
+
+ prev_action = g_object_get_data (G_OBJECT (proxy), "egg-action");
+
+ if (prev_action)
+ {
+ (* EGG_ACTION_GET_CLASS (action)->disconnect_proxy) (action, proxy);
+ }
+
+ (* EGG_ACTION_GET_CLASS (action)->connect_proxy) (action, proxy);
+}
+
+/**
+ * egg_action_disconnect_proxy:
+ * @action: the action object
+ * @proxy: the proxy widget
+ *
+ * This disconnects a proxy widget from an action. It does not
+ * destroy the widget, however.
+ */
+void
+egg_action_disconnect_proxy (EggAction *action,
+ GtkWidget *proxy)
+{
+ EggAction *prev_action;
+
+ g_return_if_fail (EGG_IS_ACTION (action));
+ g_return_if_fail (GTK_IS_WIDGET (proxy));
+
+ g_return_if_fail (g_object_get_data (G_OBJECT (proxy), "egg-action") != action);
+
+ (* EGG_ACTION_GET_CLASS (action)->disconnect_proxy) (action, proxy);
+}
+
+/**
+ * egg_action_block_activate_from:
+ * @action: the action object
+ * @proxy: a proxy widget
+ *
+ * Calling this function disables calls to the egg_action_activate()
+ * function by signals on the given proxy widget. This is used to
+ * break notification loops for things like check or radio actions.
+ *
+ * This function is intended for use by action implementations.
+ */
+void
+egg_action_block_activate_from (EggAction *action, GtkWidget *proxy)
+{
+ g_return_if_fail (EGG_IS_ACTION (action));
+
+ g_signal_handlers_block_by_func (proxy, G_CALLBACK (egg_action_activate),
+ action);
+}
+
+/**
+ * egg_action_unblock_activate_from:
+ * @action: the action object
+ * @proxy: a proxy widget
+ *
+ * Calling this function re-enables calls to the egg_action_activate()
+ * function by signals on the given proxy widget. This undoes the
+ * blocking done by egg_action_block_activate_from().
+ *
+ * This function is intended for use by action implementations.
+ */
+void
+egg_action_unblock_activate_from (EggAction *action, GtkWidget *proxy)
+{
+ g_return_if_fail (EGG_IS_ACTION (action));
+
+ g_signal_handlers_unblock_by_func (proxy, G_CALLBACK (egg_action_activate),
+ action);
+}
+
+/**
+ * egg_action_set_accel_path:
+ * @action: the action object
+ * @accel_path: the accelerator path
+ *
+ * Sets the accel path for this action. All proxy widgets associated
+ * with the action will have this accel path, so that their
+ * accelerators are consistent.
+ */
+void
+egg_action_set_accel_path (EggAction *action, const gchar *accel_path)
+{
+ action->accel_quark = g_quark_from_string(accel_path);
+}
+
+/* ---- code to create sort-of-toolbar-buttons ---- */
+
+static GtkWidget *
+tool_button_get_label (GtkWidget *button)
+{
+ g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
+
+ return g_object_get_data (G_OBJECT (button), "tool-button-label");
+}
+
+static GtkWidget *
+tool_button_get_icon (GtkWidget *button)
+{
+ g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
+
+ return g_object_get_data (G_OBJECT (button), "tool-button-icon");
+}
+
+static void
+tool_button_parent_set (GtkWidget *button, GtkWidget *old_parent)
+{
+ GtkWidget *box;
+ GtkWidget *label;
+ GtkWidget *icon;
+
+ box = g_object_get_data (G_OBJECT (button), "tool-button-box");
+ label = g_object_get_data (G_OBJECT (button), "tool-button-label");
+ icon = g_object_get_data (G_OBJECT (button), "tool-button-icon");
+
+ if (button->parent && GTK_IS_TOOLBAR (button->parent))
+ {
+ GtkReliefStyle relief = GTK_RELIEF_NORMAL;
+ GList *tmp;
+
+ /* set button relief to match toolbar */
+ gtk_widget_style_get (GTK_WIDGET (button->parent),
+ "button_relief", &relief, NULL);
+ gtk_button_set_relief (GTK_BUTTON (button), relief);
+
+ /* set the button style */
+ switch (gtk_toolbar_get_style (GTK_TOOLBAR (button->parent)))
+ {
+ case GTK_TOOLBAR_ICONS:
+ if (icon && !GTK_WIDGET_VISIBLE (icon))
+ gtk_widget_show (icon);
+ if (label && GTK_WIDGET_VISIBLE (label))
+ gtk_widget_hide (label);
+ break;
+
+ case GTK_TOOLBAR_TEXT:
+ if (icon && GTK_WIDGET_VISIBLE (icon))
+ gtk_widget_hide (icon);
+ if (label && !GTK_WIDGET_VISIBLE (label))
+ gtk_widget_show (label);
+ break;
+
+ case GTK_TOOLBAR_BOTH:
+ if (icon && !GTK_WIDGET_VISIBLE (icon))
+ gtk_widget_show (icon);
+ if (label && !GTK_WIDGET_VISIBLE (label))
+ gtk_widget_show (label);
+
+ if (GTK_IS_HBOX (box))
+ {
+ if (icon)
+ {
+ g_object_ref (icon);
+ gtk_container_remove (GTK_CONTAINER (box), icon);
+ }
+ if (label)
+ {
+ g_object_ref (label);
+ gtk_container_remove (GTK_CONTAINER (box), label);
+ }
+ gtk_container_remove (GTK_CONTAINER (button), box);
+ box = gtk_vbox_new (FALSE, 0);
+
+ gtk_widget_show (box);
+
+ if (label)
+ {
+ gtk_box_pack_end (GTK_BOX (box), label, FALSE, FALSE, 0);
+ g_object_unref (label);
+ }
+ if (icon)
+ {
+ gtk_box_pack_end (GTK_BOX (box), icon, FALSE, FALSE, 0);
+ g_object_unref (label);
+ }
+ gtk_container_add (GTK_CONTAINER (button), box);
+ g_object_set_data (G_OBJECT (button), "tool-button-box", box);
+ }
+ break;
+
+ case GTK_TOOLBAR_BOTH_HORIZ:
+ if (icon && !GTK_WIDGET_VISIBLE (icon))
+ gtk_widget_show (icon);
+ if (label && !GTK_WIDGET_VISIBLE (label))
+ gtk_widget_show (label);
+
+ if (GTK_IS_VBOX (box))
+ {
+ if (icon)
+ {
+ g_object_ref (icon);
+ gtk_container_remove (GTK_CONTAINER (box), icon);
+ }
+ if (label)
+ {
+ g_object_ref (label);
+ gtk_container_remove (GTK_CONTAINER (box), label);
+ }
+ gtk_container_remove (GTK_CONTAINER (button), box);
+ box = gtk_hbox_new (FALSE, 0);
+
+ gtk_widget_show (box);
+
+ if (label)
+ {
+ gtk_box_pack_end (GTK_BOX (box), label, FALSE, FALSE, 0);
+ g_object_unref (label);
+ }
+ if (icon)
+ {
+ gtk_box_pack_end (GTK_BOX (box), icon, FALSE, FALSE, 0);
+ g_object_unref (label);
+ }
+ gtk_container_add (GTK_CONTAINER (button), box);
+ g_object_set_data (G_OBJECT (button), "tool-button-box", box);
+ }
+ break;
+ }
+
+ /* set the icon size */
+ icon = tool_button_get_icon (button);
+ if (GTK_IS_IMAGE (icon) &&
+ gtk_image_get_storage_type (GTK_IMAGE (icon)) == GTK_IMAGE_STOCK)
+ {
+ gchar *stock_id;
+
+ gtk_image_get_stock (GTK_IMAGE (icon), &stock_id, NULL);
+ stock_id = g_strdup (stock_id);
+ gtk_image_set_from_stock (GTK_IMAGE (icon), stock_id,
+ GTK_TOOLBAR (button->parent)->icon_size);
+ g_free (stock_id);
+ }
+
+ /* gross hack!!! */
+ for (tmp = GTK_TOOLBAR (button->parent)->children; tmp; tmp = tmp->next)
+ {
+ GtkToolbarChild *tool_child = tmp->data;
+
+ if (tool_child->widget == button)
+ {
+ tool_child->type = GTK_TOOLBAR_CHILD_BUTTON;
+ tool_child->icon = icon;
+ tool_child->label = label;
+ break;
+ }
+ }
+ }
+}
+
+static GtkWidget *
+tool_button_new (GType button_type, const gchar *text, GtkWidget *icon)
+{
+ GtkWidget *button;
+ GtkWidget *vbox;
+ GtkWidget *label;
+
+ g_return_val_if_fail (g_type_is_a (button_type, GTK_TYPE_BUTTON), NULL);
+
+ button = g_object_new (button_type, NULL);
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (button), vbox);
+ gtk_widget_show (vbox);
+
+ label = gtk_label_new (text);
+ gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), button);
+ gtk_box_pack_end (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+
+ if (!icon)
+ icon = gtk_image_new();
+ gtk_box_pack_end (GTK_BOX (vbox), icon, FALSE, FALSE, 0);
+
+ g_object_set_data (G_OBJECT (button), "tool-button-box", vbox);
+ g_object_set_data (G_OBJECT (button), "tool-button-label", label);
+ g_object_set_data (G_OBJECT (button), "tool-button-icon", icon);
+
+ g_signal_connect (button, "parent_set",
+ G_CALLBACK (tool_button_parent_set), NULL);
+
+ GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS);
+
+ return button;
+}
diff --git a/lib/egg/egg-action.h b/lib/egg/egg-action.h
new file mode 100644
index 000000000..7acf59210
--- /dev/null
+++ b/lib/egg/egg-action.h
@@ -0,0 +1,81 @@
+#ifndef EGG_ACTION_H
+#define EGG_ACTION_H
+
+#include <gtk/gtk.h>
+
+#define EGG_TYPE_ACTION (egg_action_get_type ())
+#define EGG_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_ACTION, EggAction))
+#define EGG_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_ACTION, EggActionClass))
+#define EGG_IS_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_ACTION))
+#define EGG_IS_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EGG_TYPE_ACTION))
+#define EGG_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_ACTION, EggActionClass))
+
+typedef struct _EggAction EggAction;
+typedef struct _EggActionClass EggActionClass;
+
+struct _EggAction
+{
+ GObject object;
+
+ gchar *name;
+ gchar *label;
+ gchar *short_label;
+ gchar *tooltip;
+ gchar *stock_id; /* icon */
+
+ guint sensitive : 1;
+ guint visible : 1;
+ guint label_set : 1; /* these two used so we can set label */
+ guint short_label_set : 1; /* based on stock id */
+
+ /* accelerator */
+ GQuark accel_quark;
+
+ /* list of proxy widgets */
+ GSList *proxies;
+};
+
+struct _EggActionClass
+{
+ GObjectClass parent_class;
+
+ /* activation signal */
+ void (* activate) (EggAction *action);
+
+ GType menu_item_type;
+ GType toolbar_item_type;
+
+ /* widget creation routines (not signals) */
+ GtkWidget *(* create_menu_item) (EggAction *action);
+ GtkWidget *(* create_tool_item) (EggAction *action);
+ void (* connect_proxy) (EggAction *action,
+ GtkWidget *proxy);
+ void (* disconnect_proxy) (EggAction *action,
+ GtkWidget *proxy);
+};
+
+GType egg_action_get_type (void);
+
+void egg_action_activate (EggAction *action);
+
+GtkWidget *egg_action_create_icon (EggAction *action,
+ GtkIconSize icon_size);
+GtkWidget *egg_action_create_menu_item (EggAction *action);
+GtkWidget *egg_action_create_tool_item (EggAction *action);
+void egg_action_connect_proxy (EggAction *action,
+ GtkWidget *proxy);
+void egg_action_disconnect_proxy (EggAction *action,
+ GtkWidget *proxy);
+
+/* protected ... for use by child actions */
+void egg_action_block_activate_from (EggAction *action,
+ GtkWidget *proxy);
+void egg_action_unblock_activate_from (EggAction *action,
+ GtkWidget *proxy);
+
+/* protected ... for use by action groups */
+void egg_action_set_accel_path (EggAction *action,
+ const gchar *accel_path);
+
+
+#endif
diff --git a/lib/egg/egg-markup.c b/lib/egg/egg-markup.c
new file mode 100644
index 000000000..feae85a00
--- /dev/null
+++ b/lib/egg/egg-markup.c
@@ -0,0 +1,438 @@
+#include <string.h>
+#include "egg-markup.h"
+#include "eggtoolbar.h"
+
+#ifndef _
+# define _(String) (String)
+# define N_(String) (String)
+#endif
+
+typedef enum {
+ STATE_START,
+ STATE_ROOT,
+ STATE_MENU,
+ STATE_TOOLBAR,
+ STATE_POPUPS,
+ STATE_ITEM,
+ STATE_END
+} ParseState;
+
+typedef struct _ParseContext ParseContext;
+struct _ParseContext
+{
+ /* parser state information */
+ ParseState state;
+ ParseState prev_state;
+
+ /* function to call when we finish off a toplevel widget */
+ EggWidgetFunc widget_func;
+ gpointer user_data;
+
+ /* GdkAccelGroup to use for menus */
+ GtkAccelGroup *accel_group;
+
+ /* info about the widget we are constructing at the moment */
+ GtkWidget *top;
+ gchar *type;
+ gchar *name;
+
+ /* the current container we are working on */
+ GtkWidget *current;
+
+ /* the ActionGroup used to create menu items */
+ EggActionGroup *action_group;
+};
+
+static void
+start_element_handler (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data,
+ GError **error)
+{
+ ParseContext *ctx = user_data;
+ gboolean raise_error = TRUE;
+ gchar *error_attr = NULL;
+
+ switch (element_name[0])
+ {
+ case 'R':
+ if (ctx->state == STATE_START && !strcmp(element_name, "Root"))
+ {
+ ctx->state = STATE_ROOT;
+ raise_error = FALSE;
+ }
+ break;
+ case 'm':
+ if (ctx->state == STATE_ROOT && !strcmp(element_name, "menu"))
+ {
+ ctx->state = STATE_MENU;
+
+ ctx->top = ctx->current = gtk_menu_bar_new();
+ ctx->type = "menu";
+ ctx->name = NULL;
+
+ raise_error = FALSE;
+ }
+ else if (ctx->state == STATE_MENU && !strcmp(element_name, "menuitem"))
+ {
+ gint i;
+ const gchar *action_name = NULL;
+ EggAction *action = NULL;
+
+ ctx->state = STATE_ITEM;
+
+ for (i = 0; attribute_names[i] != NULL; i++)
+ {
+ if (!strcmp(attribute_names[i], "verb"))
+ {
+ action_name = attribute_values[i];
+ action = egg_action_group_get_action(ctx->action_group,
+ action_name);
+ }
+ }
+
+ if (action)
+ {
+ GtkWidget *widget = egg_action_create_menu_item(action);
+
+ gtk_container_add(GTK_CONTAINER(ctx->current), widget);
+ gtk_widget_show(widget);
+ }
+ else
+ {
+ g_warning("could not find action '%s'",
+ action_name ? action_name : "(null)");
+ }
+
+ raise_error = FALSE;
+ }
+ break;
+ case 'd':
+ if (ctx->state == STATE_ROOT && !strcmp(element_name, "dockitem"))
+ {
+ gint i;
+
+ ctx->state = STATE_TOOLBAR;
+
+ ctx->top = ctx->current = egg_toolbar_new();
+ ctx->type = "toolbar";
+ for (i = 0; attribute_names[i] != NULL; i++)
+ {
+ if (!strcmp(attribute_names[i], "name"))
+ ctx->name = g_strdup(attribute_values[i]);
+ }
+
+ raise_error = FALSE;
+ }
+ break;
+ case 'p':
+ if (ctx->state == STATE_ROOT && !strcmp(element_name, "popups"))
+ {
+ ctx->state = STATE_POPUPS;
+ raise_error = FALSE;
+ }
+ else if (ctx->state == STATE_POPUPS &&!strcmp(element_name, "popup"))
+ {
+ gint i;
+
+ ctx->state = STATE_MENU;
+
+ ctx->top = ctx->current = gtk_menu_new();
+ gtk_menu_set_accel_group(GTK_MENU(ctx->current), ctx->accel_group);
+ ctx->type = "popup";
+ for (i = 0; attribute_names[i] != NULL; i++)
+ {
+ if (!strcmp(attribute_names[i], "name"))
+ {
+ ctx->name = g_strdup(attribute_values[i]);
+ gtk_menu_set_title(GTK_MENU(ctx->current), ctx->name);
+ }
+ else if (!strcmp(attribute_names[i], "tearoff"))
+ {
+ GtkWidget *tearoff = gtk_tearoff_menu_item_new();
+
+ gtk_container_add(GTK_CONTAINER(ctx->current), tearoff);
+ gtk_widget_show(tearoff);
+ }
+ }
+
+ raise_error = FALSE;
+ }
+ break;
+ case 's':
+ if (ctx->state == STATE_MENU && !strcmp(element_name, "submenu"))
+ {
+ gint i;
+ const gchar *label = NULL;
+ gboolean tearoff = FALSE;
+ GtkWidget *widget;
+
+ ctx->state = STATE_MENU;
+ for (i = 0; attribute_names[i] != NULL; i++)
+ {
+ if (!strcmp(attribute_names[i], "label"))
+ label = g_strdup(attribute_values[i]);
+ else if (!strcmp(attribute_names[i], "tearoff"))
+ tearoff = TRUE;
+ }
+ widget = gtk_menu_item_new_with_label(label);
+ gtk_label_set_use_underline(GTK_LABEL(GTK_BIN(widget)->child), TRUE);
+ gtk_container_add(GTK_CONTAINER(ctx->current), widget);
+ gtk_widget_show(widget);
+
+ ctx->current = gtk_menu_new();
+ gtk_menu_set_accel_group(GTK_MENU(ctx->current), ctx->accel_group);
+ gtk_menu_set_title(GTK_MENU(ctx->current), label);
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(widget), ctx->current);
+
+ if (tearoff)
+ {
+ GtkWidget *tearoff = gtk_tearoff_menu_item_new();
+
+ gtk_container_add(GTK_CONTAINER(ctx->current), tearoff);
+ gtk_widget_show(tearoff);
+ }
+
+ raise_error = FALSE;
+ }
+ else if ((ctx->state == STATE_MENU || ctx->state == STATE_TOOLBAR) &&
+ !strcmp(element_name, "separator"))
+ {
+ ctx->state = STATE_ITEM;
+
+ if (GTK_IS_MENU_SHELL(ctx->current))
+ {
+ GtkWidget *widget = gtk_separator_menu_item_new();
+ gtk_container_add(GTK_CONTAINER(ctx->current), widget);
+ gtk_widget_show(widget);
+ }
+ else /* toolbar */
+ {
+ EggToolItem *item = egg_tool_item_new ();
+ egg_toolbar_insert_tool_item (EGG_TOOLBAR(ctx->current), item, -1);
+ gtk_widget_show (GTK_WIDGET (item));
+ }
+
+ raise_error = FALSE;
+ }
+ break;
+ case 't':
+ if (ctx->state == STATE_TOOLBAR && !strcmp(element_name, "toolitem"))
+ {
+ gint i;
+ const gchar *action_name = NULL;
+ EggAction *action = NULL;
+
+ ctx->state = STATE_ITEM;
+
+ for (i = 0; attribute_names[i] != NULL; i++)
+ {
+ if (!strcmp(attribute_names[i], "verb"))
+ {
+ action_name = attribute_values[i];
+ action = egg_action_group_get_action(ctx->action_group,
+ action_name);
+ }
+ }
+
+ if (action)
+ {
+ GtkWidget *widget = egg_action_create_tool_item (action);
+
+ gtk_container_add (GTK_CONTAINER (ctx->current), widget);
+ }
+ else
+ {
+ g_warning("could not find action '%s'",
+ action_name ? action_name : "(null)");
+ }
+
+ raise_error = FALSE;
+ }
+ break;
+ };
+
+ if (raise_error)
+ {
+ gint line_number, char_number;
+
+ g_markup_parse_context_get_position (context,
+ &line_number, &char_number);
+
+ if (error_attr)
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
+ _("Unknown attribute '%s' on line %d char %d"),
+ error_attr,
+ line_number, char_number);
+ else
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+ _("Unknown tag '%s' on line %d char %d"),
+ element_name,
+ line_number, char_number);
+ }
+}
+
+static void
+end_element_handler (GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error)
+{
+ ParseContext *ctx = user_data;
+ GtkWidget *widget;
+
+ switch (ctx->state)
+ {
+ case STATE_START:
+ g_warning("shouldn't get any end tags at this point");
+ /* should do a GError here */
+ break;
+ case STATE_ROOT:
+ ctx->state = STATE_END;
+ break;
+ case STATE_MENU:
+ widget = GTK_IS_MENU(ctx->current) ?
+ gtk_menu_get_attach_widget(GTK_MENU(ctx->current)) : NULL;
+ if (widget) /* not back to the toplevel ... */
+ {
+ ctx->current = widget->parent;
+ ctx->state = STATE_MENU;
+ }
+ else
+ {
+ if (GTK_IS_MENU(ctx->current)) /* must be a popup */
+ ctx->state = STATE_POPUPS;
+ else
+ ctx->state = STATE_ROOT;
+
+ /* notify */
+ (* ctx->widget_func)(ctx->top, ctx->type, ctx->name, ctx->user_data);
+ ctx->top = NULL;
+ ctx->type = NULL;
+ g_free(ctx->name);
+ ctx->name = NULL;
+ ctx->current = NULL;
+ }
+ break;
+ case STATE_TOOLBAR:
+ ctx->state = STATE_ROOT;
+
+ /* notify */
+ (* ctx->widget_func)(ctx->top, ctx->type, ctx->name, ctx->user_data);
+ ctx->top = NULL;
+ ctx->type = NULL;
+ g_free(ctx->name);
+ ctx->name = NULL;
+ ctx->current = NULL;
+ break;
+ case STATE_POPUPS:
+ ctx->state = STATE_ROOT;
+ break;
+ case STATE_ITEM:
+ if (GTK_IS_MENU_SHELL(ctx->current))
+ ctx->state = STATE_MENU;
+ else
+ ctx->state = STATE_TOOLBAR;
+ break;
+ case STATE_END:
+ g_warning("shouldn't get any end tags at this point");
+ /* should do a GError here */
+ break;
+ }
+}
+
+static void
+cleanup (GMarkupParseContext *context,
+ GError *error,
+ gpointer user_data)
+{
+ ParseContext *ctx = user_data;
+
+ gtk_widget_destroy(ctx->top);
+ ctx->top = NULL;
+ ctx->type = NULL;
+ g_free(ctx->name);
+ ctx->name = NULL;
+ ctx->current = NULL;
+}
+
+
+static GMarkupParser ui_parser = {
+ start_element_handler,
+ end_element_handler,
+ NULL,
+ NULL,
+ cleanup
+};
+
+
+gboolean
+egg_create_from_string (EggActionGroup *action_group,
+ EggWidgetFunc widget_func, gpointer user_data,
+ GtkAccelGroup *accel_group,
+ const gchar *buffer, guint length,
+ GError **error)
+{
+ ParseContext ctx = { 0 };
+ GMarkupParseContext *context;
+ gboolean res = TRUE;
+
+ g_return_val_if_fail(EGG_IS_ACTION_GROUP(action_group), FALSE);
+ g_return_val_if_fail(widget_func != NULL, FALSE);
+ g_return_val_if_fail(GTK_IS_ACCEL_GROUP(accel_group), FALSE);
+ g_return_val_if_fail(buffer != NULL, FALSE);
+
+ ctx.state = STATE_START;
+ ctx.widget_func = widget_func;
+ ctx.user_data = user_data;
+ ctx.accel_group = accel_group;
+ ctx.top = NULL;
+ ctx.type = NULL;
+ ctx.name = NULL;
+ ctx.current = NULL;
+ ctx.action_group = action_group;
+
+ context = g_markup_parse_context_new(&ui_parser, 0, &ctx, NULL);
+ if (length < 0)
+ length = strlen(buffer);
+
+ if (g_markup_parse_context_parse(context, buffer, length, error))
+ {
+ if (!g_markup_parse_context_end_parse(context, error))
+ res = FALSE;
+ }
+ else
+ res = FALSE;
+
+ g_markup_parse_context_free (context);
+
+ return res;
+}
+
+gboolean
+egg_create_from_file (EggActionGroup *action_group,
+ EggWidgetFunc widget_func,
+ gpointer user_data,
+ GtkAccelGroup *accel_group,
+ const gchar *filename,
+ GError **error)
+{
+ gchar *buffer;
+ gint length;
+ gboolean res;
+
+ if (!g_file_get_contents (filename, &buffer, &length, error))
+ return FALSE;
+
+ res = egg_create_from_string(action_group, widget_func, user_data,
+ accel_group, buffer, length, error);
+ g_free(buffer);
+
+ return res;
+}
diff --git a/lib/egg/egg-markup.h b/lib/egg/egg-markup.h
new file mode 100644
index 000000000..15524189f
--- /dev/null
+++ b/lib/egg/egg-markup.h
@@ -0,0 +1,30 @@
+#ifndef EGG_MARKUP_H
+#define EGG_MARKUP_H
+
+#include <gtk/gtk.h>
+#include <egg-action.h>
+#include <egg-action-group.h>
+
+
+/* this stuff can go away once I am finished with the merge code */
+
+typedef void (*EggWidgetFunc) (GtkWidget *widget,
+ const gchar *type,
+ const gchar *name,
+ gpointer user_data);
+
+gboolean egg_create_from_string (EggActionGroup *action_group,
+ EggWidgetFunc widget_func,
+ gpointer user_data,
+ GtkAccelGroup *accel_group,
+ const gchar *buffer, guint length,
+ GError **error);
+
+gboolean egg_create_from_file (EggActionGroup *action_group,
+ EggWidgetFunc widget_func,
+ gpointer user_data,
+ GtkAccelGroup *accel_group,
+ const gchar *filename,
+ GError **error);
+
+#endif
diff --git a/lib/egg/egg-menu-merge.c b/lib/egg/egg-menu-merge.c
new file mode 100644
index 000000000..17895ca99
--- /dev/null
+++ b/lib/egg/egg-menu-merge.c
@@ -0,0 +1,1316 @@
+#include <string.h>
+#include "egg-menu-merge.h"
+#include "eggtoolbar.h"
+#include "eggseparatortoolitem.h"
+
+#ifndef _
+# define _(string) (string)
+#endif
+
+#define NODE_INFO(node) ((EggMenuMergeNode *)node->data)
+
+typedef struct {
+ guint merge_id;
+ GQuark action_quark;
+} NodeUIReference;
+
+static void egg_menu_merge_class_init (EggMenuMergeClass *class);
+static void egg_menu_merge_init (EggMenuMerge *merge);
+
+static void egg_menu_merge_queue_update (EggMenuMerge *self);
+static void egg_menu_merge_dirty_all (EggMenuMerge *self);
+
+static GNode *get_child_node (EggMenuMerge *self, GNode *parent,
+ const gchar *childname,
+ gint childname_length,
+ EggMenuMergeNodeType node_type,
+ gboolean create, gboolean top);
+static GNode *egg_menu_merge_get_node (EggMenuMerge *self,
+ const gchar *path,
+ EggMenuMergeNodeType node_type,
+ gboolean create);
+static guint egg_menu_merge_next_merge_id (EggMenuMerge *self);
+
+static void egg_menu_merge_node_prepend_ui_reference (EggMenuMergeNode *node,
+ guint merge_id,
+ GQuark action_quark);
+static void egg_menu_merge_node_remove_ui_reference (EggMenuMergeNode *node,
+ guint merge_id);
+
+enum {
+ ADD_WIDGET,
+ REMOVE_WIDGET,
+ LAST_SIGNAL
+};
+
+static guint merge_signals[LAST_SIGNAL] = { 0 };
+
+static GMemChunk *merge_node_chunk = NULL;
+
+GType
+egg_menu_merge_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EggMenuMergeClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) egg_menu_merge_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+
+ sizeof (EggMenuMerge),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) egg_menu_merge_init,
+ };
+
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "EggMenuMerge",
+ &type_info, 0);
+ }
+ return type;
+}
+
+static void
+egg_menu_merge_class_init (EggMenuMergeClass *class)
+{
+ if (!merge_node_chunk)
+ merge_node_chunk = g_mem_chunk_create(EggMenuMergeNode, 64,
+ G_ALLOC_AND_FREE);
+
+ merge_signals[ADD_WIDGET] =
+ g_signal_new ("add_widget",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
+ G_STRUCT_OFFSET (EggMenuMergeClass, add_widget), NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_WIDGET);
+ merge_signals[REMOVE_WIDGET] =
+ g_signal_new ("remove_widget",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
+ G_STRUCT_OFFSET (EggMenuMergeClass, remove_widget), NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_WIDGET);
+
+}
+
+
+static void
+egg_menu_merge_init (EggMenuMerge *self)
+{
+ guint merge_id;
+ GNode *node;
+
+ self->accel_group = gtk_accel_group_new();
+
+ self->root_node = NULL;
+ self->action_groups = NULL;
+
+ self->last_merge_id = 0;
+
+
+ merge_id = egg_menu_merge_next_merge_id(self);
+ node = get_child_node(self, NULL, "Root", 4,
+ EGG_MENU_MERGE_ROOT, TRUE, FALSE);
+ egg_menu_merge_node_prepend_ui_reference(NODE_INFO(node), merge_id, 0);
+ node = get_child_node(self, self->root_node, "popups", 6,
+ EGG_MENU_MERGE_POPUPS, TRUE, FALSE);
+ egg_menu_merge_node_prepend_ui_reference(NODE_INFO(node), merge_id, 0);
+}
+
+EggMenuMerge *
+egg_menu_merge_new (void)
+{
+ return g_object_new(EGG_TYPE_MENU_MERGE, NULL);
+}
+
+void
+egg_menu_merge_insert_action_group (EggMenuMerge *self,
+ EggActionGroup *action_group, gint pos)
+{
+ g_return_if_fail (EGG_IS_MENU_MERGE(self));
+ g_return_if_fail (EGG_IS_ACTION_GROUP(action_group));
+ g_return_if_fail (g_list_find(self->action_groups, action_group) == NULL);
+
+ g_object_ref(action_group);
+ self->action_groups = g_list_insert(self->action_groups, action_group, pos);
+
+ /* dirty all nodes, as action bindings may change */
+ egg_menu_merge_dirty_all(self);
+}
+
+void
+egg_menu_merge_remove_action_group (EggMenuMerge *self,
+ EggActionGroup *action_group)
+{
+ g_return_if_fail (EGG_IS_MENU_MERGE(self));
+ g_return_if_fail (EGG_IS_ACTION_GROUP(action_group));
+ g_return_if_fail (g_list_find(self->action_groups, action_group) != NULL);
+
+ self->action_groups = g_list_remove(self->action_groups, action_group);
+ g_object_unref(action_group);
+
+ /* dirty all nodes, as action bindings may change */
+ egg_menu_merge_dirty_all(self);
+}
+
+GtkWidget *
+egg_menu_merge_get_widget (EggMenuMerge *self, const gchar *path)
+{
+ GNode *node;
+
+ /* ensure that there are no pending updates before we get the
+ * widget */
+ egg_menu_merge_ensure_update(self);
+
+ node = egg_menu_merge_get_node(self, path, EGG_MENU_MERGE_UNDECIDED, FALSE);
+ return NODE_INFO(node)->proxy;
+}
+
+static GNode *
+get_child_node(EggMenuMerge *self, GNode *parent,
+ const gchar *childname, gint childname_length,
+ EggMenuMergeNodeType node_type,
+ gboolean create, gboolean top)
+{
+ GNode *child = NULL;
+
+ g_return_val_if_fail(parent == NULL ||
+ (NODE_INFO(parent)->type != EGG_MENU_MERGE_MENUITEM &&
+ NODE_INFO(parent)->type != EGG_MENU_MERGE_TOOLITEM), NULL);
+
+ if (parent)
+ {
+ if (childname)
+ {
+ for (child = parent->children; child != NULL; child = child->next)
+ {
+ if (strlen(NODE_INFO(child)->name) == childname_length &&
+ !strncmp(NODE_INFO(child)->name, childname, childname_length))
+ {
+ /* if undecided about node type, set it */
+ if (NODE_INFO(child)->type == EGG_MENU_MERGE_UNDECIDED)
+ NODE_INFO(child)->type = node_type;
+
+ /* warn about type mismatch */
+ if (NODE_INFO(child)->type != EGG_MENU_MERGE_UNDECIDED &&
+ NODE_INFO(child)->type != node_type)
+ g_warning("node type doesn't match %d (%s is type %d)",
+ node_type, NODE_INFO(child)->name,
+ NODE_INFO(child)->type);
+
+ return child;
+ }
+ }
+ }
+ if (!child && create)
+ {
+ EggMenuMergeNode *mnode;
+
+ mnode = g_chunk_new0(EggMenuMergeNode, merge_node_chunk);
+ mnode->type = node_type;
+ mnode->name = g_strndup(childname, childname_length);
+ mnode->dirty = TRUE;
+
+ if (top)
+ child = g_node_prepend_data(parent, mnode);
+ else
+ child = g_node_append_data(parent, mnode);
+ }
+ }
+ else
+ {
+ /* handle root node */
+ if (self->root_node)
+ {
+ child = self->root_node;
+ if (strncmp(NODE_INFO(child)->name, childname, childname_length) !=0)
+ g_warning("root node name '%s' doesn't match '%s'",
+ childname, NODE_INFO(child)->name);
+ if (NODE_INFO(child)->type != EGG_MENU_MERGE_ROOT)
+ g_warning("base element must be of type ROOT");
+ }
+ else if (create)
+ {
+ EggMenuMergeNode *mnode;
+
+ mnode = g_chunk_new0(EggMenuMergeNode, merge_node_chunk);
+ mnode->type = node_type;
+ mnode->name = g_strndup(childname, childname_length);
+ mnode->dirty = TRUE;
+
+ child = self->root_node = g_node_new(mnode);
+ }
+ }
+
+ return child;
+}
+
+static GNode *
+egg_menu_merge_get_node(EggMenuMerge *self, const gchar *path,
+ EggMenuMergeNodeType node_type, gboolean create)
+{
+ const gchar *pos, *end;
+ GNode *parent, *node;
+
+ end = path + strlen(path);
+ pos = path;
+ parent = node = NULL;
+ while (pos < end)
+ {
+ const gchar *slash;
+ gsize length;
+
+ slash = strchr(pos, '/');
+ if (slash)
+ length = slash - pos;
+ else
+ length = strlen(pos);
+
+ node = get_child_node(self, parent, pos, length, EGG_MENU_MERGE_UNDECIDED,
+ create, FALSE);
+ if (!node)
+ return NULL;
+
+ pos += length + 1; /* move past the node name and the slash too */
+ parent = node;
+ }
+
+ if (NODE_INFO(node)->type == EGG_MENU_MERGE_UNDECIDED)
+ NODE_INFO(node)->type = node_type;
+ return node;
+}
+
+static guint
+egg_menu_merge_next_merge_id (EggMenuMerge *self)
+{
+ self->last_merge_id++;
+
+ return self->last_merge_id;
+}
+
+static void
+egg_menu_merge_node_prepend_ui_reference (EggMenuMergeNode *node,
+ guint merge_id, GQuark action_quark)
+{
+ NodeUIReference *reference;
+
+ reference = g_new (NodeUIReference, 1);
+ reference->action_quark = action_quark;
+ reference->merge_id = merge_id;
+
+ /* Prepend the reference */
+ node->uifiles = g_list_prepend (node->uifiles, reference);
+
+ node->dirty = TRUE;
+}
+
+static void
+egg_menu_merge_node_remove_ui_reference (EggMenuMergeNode *node,
+ guint merge_id)
+{
+ GList *p;
+
+ for (p = node->uifiles; p != NULL; p = p->next)
+ {
+ NodeUIReference *reference = p->data;
+
+ if (reference->merge_id == merge_id)
+ {
+ node->uifiles = g_list_remove_link (node->uifiles, p);
+ node->dirty = TRUE;
+ g_free (reference);
+
+ break;
+ }
+ }
+}
+
+/* -------------------- The UI file parser -------------------- */
+
+typedef enum {
+ STATE_START,
+ STATE_ROOT,
+ STATE_MENU,
+ STATE_TOOLBAR,
+ STATE_POPUPS,
+ STATE_MENUITEM,
+ STATE_TOOLITEM,
+ STATE_END
+} ParseState;
+
+typedef struct _ParseContext ParseContext;
+struct _ParseContext
+{
+ ParseState state;
+ ParseState prev_state;
+
+ EggMenuMerge *self;
+
+ GNode *current;
+
+ guint merge_id;
+};
+
+static void
+start_element_handler (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data,
+ GError **error)
+{
+ ParseContext *ctx = user_data;
+ EggMenuMerge *self = ctx->self;
+
+ gint i;
+ const gchar *node_name;
+ GQuark verb_quark;
+ gboolean top;
+
+ gboolean raise_error = TRUE;
+ gchar *error_attr = NULL;
+
+ //g_message("starting element %s", element_name);
+
+ /* work out a name for this node. Either the name attribute, or
+ * element name */
+ node_name = element_name;
+ verb_quark = 0;
+ top = FALSE;
+ for (i = 0; attribute_names[i] != NULL; i++)
+ {
+ if (!strcmp(attribute_names[i], "name"))
+ {
+ node_name = attribute_values[i];
+ }
+ else if (!strcmp(attribute_names[i], "verb"))
+ {
+ verb_quark = g_quark_from_string(attribute_values[i]);
+ }
+ else if (!strcmp(attribute_names[i], "pos"))
+ {
+ top = !strcmp(attribute_values[i], "top");
+ }
+ }
+ /* if no verb, then set it to the node's name */
+ if (verb_quark == 0)
+ verb_quark = g_quark_from_string(node_name);
+
+ switch (element_name[0])
+ {
+ case 'R':
+ if (ctx->state == STATE_START && !strcmp(element_name, "Root"))
+ {
+ ctx->state = STATE_ROOT;
+ ctx->current = self->root_node;
+ raise_error = FALSE;
+
+ egg_menu_merge_node_prepend_ui_reference (NODE_INFO (ctx->current),
+ ctx->merge_id, verb_quark);
+ }
+ break;
+ case 'm':
+ if (ctx->state == STATE_ROOT && !strcmp(element_name, "menu"))
+ {
+ ctx->state = STATE_MENU;
+ ctx->current = get_child_node(self, ctx->current,
+ node_name, strlen(node_name),
+ EGG_MENU_MERGE_MENUBAR,
+ TRUE, FALSE);
+ if (NODE_INFO(ctx->current)->action_name == 0)
+ NODE_INFO(ctx->current)->action_name = verb_quark;
+
+ egg_menu_merge_node_prepend_ui_reference (NODE_INFO (ctx->current),
+ ctx->merge_id, verb_quark);
+ NODE_INFO(ctx->current)->dirty = TRUE;
+
+ raise_error = FALSE;
+ }
+ else if (ctx->state == STATE_MENU && !strcmp(element_name, "menuitem"))
+ {
+ GNode *node;
+
+ ctx->state = STATE_MENUITEM;
+ node = get_child_node(self, ctx->current,
+ node_name, strlen(node_name),
+ EGG_MENU_MERGE_MENUITEM,
+ TRUE, top);
+ if (NODE_INFO(node)->action_name == 0)
+ NODE_INFO(node)->action_name = verb_quark;
+
+ egg_menu_merge_node_prepend_ui_reference (NODE_INFO (node),
+ ctx->merge_id, verb_quark);
+ NODE_INFO(node)->dirty = TRUE;
+
+ raise_error = FALSE;
+ }
+ break;
+ case 'd':
+ if (ctx->state == STATE_ROOT && !strcmp(element_name, "dockitem"))
+ {
+ ctx->state = STATE_TOOLBAR;
+ ctx->current = get_child_node(self, ctx->current,
+ node_name, strlen(node_name),
+ EGG_MENU_MERGE_TOOLBAR,
+ TRUE, FALSE);
+ if (NODE_INFO(ctx->current)->action_name == 0)
+ NODE_INFO(ctx->current)->action_name = verb_quark;
+
+ egg_menu_merge_node_prepend_ui_reference (NODE_INFO (ctx->current),
+ ctx->merge_id, verb_quark);
+ NODE_INFO(ctx->current)->dirty = TRUE;
+
+ raise_error = FALSE;
+ }
+ break;
+ case 'p':
+ if (ctx->state == STATE_ROOT && !strcmp(element_name, "popups"))
+ {
+ ctx->state = STATE_POPUPS;
+ ctx->current = get_child_node(self, ctx->current,
+ node_name, strlen(node_name),
+ EGG_MENU_MERGE_POPUPS,
+ TRUE, FALSE);
+
+ egg_menu_merge_node_prepend_ui_reference (NODE_INFO (ctx->current),
+ ctx->merge_id, verb_quark);
+ NODE_INFO(ctx->current)->dirty = TRUE;
+
+ raise_error = FALSE;
+ }
+ else if (ctx->state == STATE_POPUPS && !strcmp(element_name, "popup"))
+ {
+ ctx->state = STATE_MENU;
+ ctx->current = get_child_node(self, ctx->current,
+ node_name, strlen(node_name),
+ EGG_MENU_MERGE_MENU,
+ TRUE, FALSE);
+ if (NODE_INFO(ctx->current)->action_name == 0)
+ NODE_INFO(ctx->current)->action_name = verb_quark;
+
+ egg_menu_merge_node_prepend_ui_reference (NODE_INFO (ctx->current),
+ ctx->merge_id, verb_quark);
+ NODE_INFO(ctx->current)->dirty = TRUE;
+
+ raise_error = FALSE;
+ }
+ else if ((ctx->state == STATE_MENU || ctx->state == STATE_TOOLBAR) &&
+ !strcmp(element_name, "placeholder"))
+ {
+ if (ctx->state == STATE_MENU)
+ ctx->current = get_child_node(self, ctx->current,
+ node_name, strlen(node_name),
+ EGG_MENU_MERGE_MENU_PLACEHOLDER,
+ TRUE, top);
+ else
+ ctx->current = get_child_node(self, ctx->current,
+ node_name, strlen(node_name),
+ EGG_MENU_MERGE_TOOLBAR_PLACEHOLDER,
+ TRUE, top);
+
+ egg_menu_merge_node_prepend_ui_reference (NODE_INFO (ctx->current),
+ ctx->merge_id, verb_quark);
+ NODE_INFO(ctx->current)->dirty = TRUE;
+
+ raise_error = FALSE;
+ }
+ break;
+ case 's':
+ if (ctx->state == STATE_MENU && !strcmp(element_name, "submenu"))
+ {
+ ctx->state = STATE_MENU;
+ ctx->current = get_child_node(self, ctx->current,
+ node_name, strlen(node_name),
+ EGG_MENU_MERGE_MENU,
+ TRUE, top);
+ if (NODE_INFO(ctx->current)->action_name == 0)
+ NODE_INFO(ctx->current)->action_name = verb_quark;
+
+ egg_menu_merge_node_prepend_ui_reference (NODE_INFO (ctx->current),
+ ctx->merge_id, verb_quark);
+ NODE_INFO(ctx->current)->dirty = TRUE;
+
+ raise_error = FALSE;
+ }
+ else if ((ctx->state == STATE_MENU || ctx->state == STATE_TOOLBAR) &&
+ !strcmp(element_name, "separator"))
+ {
+ GNode *node;
+
+ if (ctx->state == STATE_MENU)
+ ctx->state = STATE_MENUITEM;
+ else
+ ctx->state = STATE_TOOLITEM;
+ node = get_child_node(self, ctx->current,
+ node_name, strlen(node_name),
+ EGG_MENU_MERGE_SEPARATOR,
+ TRUE, top);
+ if (NODE_INFO(node)->action_name == 0)
+ NODE_INFO(node)->action_name = verb_quark;
+
+ egg_menu_merge_node_prepend_ui_reference (NODE_INFO (node),
+ ctx->merge_id, verb_quark);
+ NODE_INFO(node)->dirty = TRUE;
+
+ raise_error = FALSE;
+ }
+ break;
+ case 't':
+ if (ctx->state == STATE_TOOLBAR && !strcmp(element_name, "toolitem"))
+ {
+ GNode *node;
+
+ ctx->state = STATE_TOOLITEM;
+ node = get_child_node(self, ctx->current,
+ node_name, strlen(node_name),
+ EGG_MENU_MERGE_TOOLITEM,
+ TRUE, top);
+ if (NODE_INFO(node)->action_name == 0)
+ NODE_INFO(node)->action_name = verb_quark;
+
+ egg_menu_merge_node_prepend_ui_reference (NODE_INFO (node),
+ ctx->merge_id, verb_quark);
+ NODE_INFO(node)->dirty = TRUE;
+
+ raise_error = FALSE;
+ }
+ break;
+ default:
+ break;
+ }
+ if (raise_error)
+ {
+ gint line_number, char_number;
+
+ g_markup_parse_context_get_position (context,
+ &line_number, &char_number);
+ if (error_attr)
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
+ _("Unknown attribute '%s' on line %d char %d"),
+ error_attr,
+ line_number, char_number);
+ else
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+ _("Unknown tag '%s' on line %d char %d"),
+ element_name,
+ line_number, char_number);
+ }
+}
+
+static void
+end_element_handler (GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error)
+{
+ ParseContext *ctx = user_data;
+ EggMenuMerge *self = ctx->self;
+
+ //g_message("ending element %s (state=%d)", element_name, ctx->state);
+
+ switch (ctx->state)
+ {
+ case STATE_START:
+ g_warning("shouldn't get any end tags in start state");
+ /* should we GError here? */
+ break;
+ case STATE_ROOT:
+ if (ctx->current != self->root_node)
+ g_warning("we are in STATE_ROOT, but the current node isn't the root");
+ ctx->current = NULL;
+ ctx->state = STATE_END;
+ break;
+ case STATE_MENU:
+ ctx->current = ctx->current->parent;
+ if (NODE_INFO(ctx->current)->type == EGG_MENU_MERGE_ROOT) /* menubar */
+ ctx->state = STATE_ROOT;
+ else if (NODE_INFO(ctx->current)->type == EGG_MENU_MERGE_POPUPS) /* popup */
+ ctx->state = STATE_POPUPS;
+ /* else, stay in STATE_MENU state */
+ break;
+ case STATE_TOOLBAR:
+ ctx->current = ctx->current->parent;
+ /* we conditionalise this test, in case we are closing off a
+ * placeholder */
+ if (NODE_INFO(ctx->current)->type == EGG_MENU_MERGE_ROOT)
+ ctx->state = STATE_ROOT;
+ /* else, stay in STATE_TOOLBAR state */
+ break;
+ case STATE_POPUPS:
+ ctx->current = ctx->current->parent;
+ ctx->state = STATE_ROOT;
+ break;
+ case STATE_MENUITEM:
+ ctx->state = STATE_MENU;
+ break;
+ case STATE_TOOLITEM:
+ ctx->state = STATE_TOOLBAR;
+ break;
+ case STATE_END:
+ g_warning("shouldn't get any end tags at this point");
+ /* should do an error here */
+ break;
+ }
+}
+
+static void
+cleanup (GMarkupParseContext *context,
+ GError *error,
+ gpointer user_data)
+{
+ ParseContext *ctx = user_data;
+ EggMenuMerge *self = ctx->self;
+
+ ctx->current = NULL;
+ /* should also walk through the tree and get rid of nodes related to
+ * this UI file's tag */
+
+ egg_menu_merge_remove_ui (self, ctx->merge_id);
+}
+
+static GMarkupParser ui_parser = {
+ start_element_handler,
+ end_element_handler,
+ NULL,
+ NULL,
+ cleanup
+};
+
+guint
+egg_menu_merge_add_ui_from_string (EggMenuMerge *self,
+ const gchar *buffer, guint length,
+ GError **error)
+{
+ ParseContext ctx = { 0 };
+ GMarkupParseContext *context;
+ gboolean res = TRUE;
+
+ g_return_val_if_fail(EGG_IS_MENU_MERGE(self), FALSE);
+ g_return_val_if_fail(buffer != NULL, FALSE);
+
+ ctx.state = STATE_START;
+ ctx.self = self;
+ ctx.current = NULL;
+ ctx.merge_id = egg_menu_merge_next_merge_id (self);
+
+ context = g_markup_parse_context_new(&ui_parser, 0, &ctx, NULL);
+ if (length < 0)
+ length = strlen(buffer);
+
+ if (g_markup_parse_context_parse(context, buffer, length, error))
+ {
+ if (!g_markup_parse_context_end_parse(context, error))
+ res = FALSE;
+ }
+ else
+ res = FALSE;
+
+ g_markup_parse_context_free (context);
+
+ egg_menu_merge_queue_update(self);
+
+ if (res)
+ return ctx.merge_id;
+ return 0;
+}
+
+guint
+egg_menu_merge_add_ui_from_file (EggMenuMerge *self,
+ const gchar *filename,
+ GError **error)
+{
+ gchar *buffer;
+ gint length;
+ guint res;
+
+ if (!g_file_get_contents (filename, &buffer, &length, error))
+ return 0;
+
+ res = egg_menu_merge_add_ui_from_string(self, buffer, length, error);
+ g_free(buffer);
+
+ return res;
+}
+
+static gboolean
+remove_ui (GNode *node, gpointer user_data)
+{
+ guint merge_id = GPOINTER_TO_UINT (user_data);
+
+ egg_menu_merge_node_remove_ui_reference (NODE_INFO (node), merge_id);
+
+ return FALSE; /* continue */
+}
+
+void
+egg_menu_merge_remove_ui (EggMenuMerge *self, guint merge_id)
+{
+ g_node_traverse(self->root_node, G_POST_ORDER, G_TRAVERSE_ALL, -1,
+ remove_ui, GUINT_TO_POINTER (merge_id));
+
+ egg_menu_merge_queue_update(self);
+}
+
+/* -------------------- Updates -------------------- */
+
+
+static EggAction *
+get_action_by_name (EggMenuMerge *merge, const char *action_name)
+{
+ GList *tmp;
+
+ if (!action_name)
+ return NULL;
+
+ /* lookup name */
+ for (tmp = merge->action_groups; tmp != NULL; tmp = tmp->next)
+ {
+ EggActionGroup *action_group = tmp->data;
+ EggAction *action;
+
+ action = egg_action_group_get_action (action_group, action_name);
+
+ if (action)
+ return action;
+ }
+
+ return NULL;
+}
+
+static gboolean
+find_menu_position (GNode *node, GtkWidget **menushell_p, gint *pos_p)
+{
+ GtkWidget *menushell;
+ gint pos;
+
+ g_return_val_if_fail(node != NULL, FALSE);
+ g_return_val_if_fail(NODE_INFO(node)->type == EGG_MENU_MERGE_MENU ||
+ NODE_INFO(node)->type == EGG_MENU_MERGE_MENU_PLACEHOLDER ||
+ NODE_INFO(node)->type == EGG_MENU_MERGE_MENUITEM ||
+ NODE_INFO(node)->type == EGG_MENU_MERGE_SEPARATOR,
+ FALSE);
+
+ /* first sibling -- look at parent */
+ if (node->prev == NULL)
+ {
+ GNode *parent;
+
+ parent = node->parent;
+ switch (NODE_INFO(parent)->type)
+ {
+ case EGG_MENU_MERGE_MENUBAR:
+ menushell = NODE_INFO(parent)->proxy;
+ pos = 0;
+ break;
+ case EGG_MENU_MERGE_MENU:
+ menushell = NODE_INFO(parent)->proxy;
+ if (GTK_IS_MENU_ITEM(menushell))
+ menushell = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menushell));
+ pos = 0;
+ break;
+ case EGG_MENU_MERGE_MENU_PLACEHOLDER:
+ menushell = gtk_widget_get_parent(NODE_INFO(parent)->proxy);
+ g_return_val_if_fail(GTK_IS_MENU_SHELL(menushell), FALSE);
+ pos = g_list_index(GTK_MENU_SHELL(menushell)->children,
+ NODE_INFO(parent)->proxy) + 1;
+ break;
+ default:
+ g_warning("%s: bad parent node type %d", G_STRLOC,
+ NODE_INFO(parent)->type);
+ return FALSE;
+ }
+ }
+ else
+ {
+ GtkWidget *prev_child;
+ GNode *sibling;
+
+ sibling = node->prev;
+ if (NODE_INFO(sibling)->type == EGG_MENU_MERGE_MENU_PLACEHOLDER)
+ prev_child = NODE_INFO(sibling)->extra; /* second Separator */
+ else
+ prev_child = NODE_INFO(sibling)->proxy;
+
+ g_return_val_if_fail(GTK_IS_WIDGET(prev_child), FALSE);
+ menushell = gtk_widget_get_parent(prev_child);
+ g_return_val_if_fail(GTK_IS_MENU_SHELL(menushell), FALSE);
+
+ pos = g_list_index(GTK_MENU_SHELL(menushell)->children, prev_child) + 1;
+ }
+
+ if (menushell_p)
+ *menushell_p = menushell;
+ if (pos_p)
+ *pos_p = pos;
+
+ return TRUE;
+}
+
+static gboolean
+find_toolbar_position (GNode *node, GtkWidget **toolbar_p, gint *pos_p)
+{
+ GtkWidget *toolbar;
+ gint pos;
+
+ g_return_val_if_fail(node != NULL, FALSE);
+ g_return_val_if_fail(NODE_INFO(node)->type == EGG_MENU_MERGE_TOOLBAR ||
+ NODE_INFO(node)->type == EGG_MENU_MERGE_TOOLBAR_PLACEHOLDER ||
+ NODE_INFO(node)->type == EGG_MENU_MERGE_TOOLITEM ||
+ NODE_INFO(node)->type == EGG_MENU_MERGE_SEPARATOR,
+ FALSE);
+
+ /* first sibling -- look at parent */
+ if (node->prev == NULL)
+ {
+ GNode *parent;
+
+ parent = node->parent;
+ switch (NODE_INFO(parent)->type)
+ {
+ case EGG_MENU_MERGE_TOOLBAR:
+ toolbar = NODE_INFO(parent)->proxy;
+ pos = 0;
+ break;
+ case EGG_MENU_MERGE_TOOLBAR_PLACEHOLDER:
+ toolbar = gtk_widget_get_parent(NODE_INFO(parent)->proxy);
+ g_return_val_if_fail(EGG_IS_TOOLBAR(toolbar), FALSE);
+ pos = g_list_index(egg_toolbar_get_tool_items(EGG_TOOLBAR(toolbar)),
+ NODE_INFO(parent)->proxy) + 1;
+ break;
+ default:
+ g_warning("%s: bad parent node type %d", G_STRLOC,
+ NODE_INFO(parent)->type);
+ return FALSE;
+ }
+ }
+ else
+ {
+ GtkWidget *prev_child;
+ GNode *sibling;
+
+ sibling = node->prev;
+ if (NODE_INFO(sibling)->type == EGG_MENU_MERGE_TOOLBAR_PLACEHOLDER)
+ prev_child = NODE_INFO(sibling)->extra; /* second Separator */
+ else
+ prev_child = NODE_INFO(sibling)->proxy;
+
+ g_return_val_if_fail(GTK_IS_WIDGET(prev_child), FALSE);
+ toolbar = gtk_widget_get_parent(prev_child);
+ g_return_val_if_fail(EGG_IS_TOOLBAR(toolbar), FALSE);
+
+ pos = g_list_index(egg_toolbar_get_tool_items(EGG_TOOLBAR(toolbar)),
+ prev_child) + 1;
+ }
+
+ if (toolbar_p)
+ *toolbar_p = toolbar;
+ if (pos_p)
+ *pos_p = pos;
+
+ return TRUE;
+}
+
+static void
+update_node (EggMenuMerge *self, GNode *node)
+{
+ EggMenuMergeNode *info;
+ GNode *child;
+ EggAction *action;
+ GList *tmp;
+
+ g_return_if_fail (node != NULL);
+ g_return_if_fail (NODE_INFO(node) != NULL);
+
+ info = NODE_INFO(node);
+
+ if (NODE_INFO(node)->dirty)
+ {
+ const gchar *action_name;
+ NodeUIReference *ref;
+
+ if (info->uifiles == NULL) {
+ /* We may need to remove this node.
+ * This must be done in post order
+ */
+ goto recurse_children;
+ }
+
+ ref = info->uifiles->data;
+ action_name = g_quark_to_string (ref->action_quark);
+ action = get_action_by_name (self, action_name);
+
+ NODE_INFO(node)->dirty = FALSE;
+
+ /* Check if the node doesn't have an action and must have an action */
+ if (action == NULL &&
+ info->type != EGG_MENU_MERGE_MENUBAR &&
+ info->type != EGG_MENU_MERGE_TOOLBAR &&
+ info->type != EGG_MENU_MERGE_SEPARATOR &&
+ info->type != EGG_MENU_MERGE_MENU_PLACEHOLDER &&
+ info->type != EGG_MENU_MERGE_TOOLBAR_PLACEHOLDER)
+ {
+ /* FIXME: Should we warn here? */
+ goto recurse_children;
+ }
+
+ /* If the widget already has a proxy and the action hasn't changed, then
+ * we don't have to do anything.
+ */
+ if (info->proxy != NULL &&
+ action == info->action)
+ {
+ goto recurse_children;
+ }
+
+ if (info->action)
+ g_object_unref (info->action);
+ info->action = action;
+ if (info->action)
+ g_object_ref (info->action);
+
+ switch (info->type)
+ {
+ case EGG_MENU_MERGE_MENUBAR:
+ if (info->proxy == NULL)
+ {
+ info->proxy = gtk_menu_bar_new ();
+ gtk_widget_show (info->proxy);
+ g_signal_emit (self, merge_signals[ADD_WIDGET], 0, info->proxy);
+ }
+ break;
+ case EGG_MENU_MERGE_MENU:
+ {
+ GtkWidget *prev_submenu = NULL;
+ /* remove the proxy if it is of the wrong type ... */
+ if (info->proxy && G_OBJECT_TYPE(info->proxy) !=
+ EGG_ACTION_GET_CLASS(info->action)->menu_item_type)
+ {
+ prev_submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(info->proxy));
+ if (prev_submenu)
+ {
+ g_object_ref (prev_submenu);
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(info->proxy),NULL);
+ }
+ gtk_container_remove(GTK_CONTAINER(info->proxy->parent),
+ info->proxy);
+ info->proxy = NULL;
+ }
+ /* create proxy if needed ... */
+ if (info->proxy == NULL)
+ {
+ GtkWidget *menushell;
+ gint pos;
+ GNode *parent;
+
+ parent = node->parent;
+
+ if (parent && NODE_INFO (parent)->type == EGG_MENU_MERGE_POPUPS)
+ {
+ info->proxy = gtk_menu_new();
+ }
+ else if (find_menu_position(node, &menushell, &pos))
+ {
+ GtkWidget *menu;
+ info->proxy = egg_action_create_menu_item (info->action);
+ menu = gtk_menu_new();
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(info->proxy), menu);
+ gtk_menu_set_accel_group (GTK_MENU (menu), self->accel_group);
+ gtk_menu_shell_insert (GTK_MENU_SHELL (menushell),
+ info->proxy, pos);
+ }
+ }
+ else
+ {
+ egg_action_connect_proxy (info->action, info->proxy);
+ }
+ if (prev_submenu)
+ {
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (info->proxy),
+ prev_submenu);
+ g_object_unref (prev_submenu);
+ }
+ }
+ break;
+ case EGG_MENU_MERGE_UNDECIDED:
+ g_warning("found 'undecided node!");
+ break;
+ case EGG_MENU_MERGE_ROOT:
+ break;
+ case EGG_MENU_MERGE_TOOLBAR:
+ if (info->proxy == NULL)
+ {
+ info->proxy = egg_toolbar_new ();
+ gtk_widget_show (info->proxy);
+ g_signal_emit (self, merge_signals[ADD_WIDGET], 0, info->proxy);
+ }
+ break;
+ case EGG_MENU_MERGE_MENU_PLACEHOLDER:
+ /* create menu items for placeholders if necessary ... */
+ if (!GTK_IS_SEPARATOR_MENU_ITEM (info->proxy) ||
+ !GTK_IS_SEPARATOR_MENU_ITEM (info->extra))
+ {
+ if (info->proxy)
+ gtk_container_remove(GTK_CONTAINER(info->proxy->parent),
+ info->proxy);
+ if (info->extra)
+ gtk_container_remove(GTK_CONTAINER(info->extra->parent),
+ info->extra);
+ info->proxy = NULL;
+ info->extra = NULL;
+ }
+ if (info->proxy == NULL)
+ {
+ GtkWidget *menushell;
+ gint pos;
+
+ if (find_menu_position(node, &menushell, &pos))
+ {
+ NODE_INFO(node)->proxy = gtk_separator_menu_item_new();
+ gtk_menu_shell_insert(GTK_MENU_SHELL(menushell),
+ NODE_INFO(node)->proxy, pos);
+ //gtk_widget_show(NODE_INFO(node)->proxy);
+
+ NODE_INFO(node)->extra = gtk_separator_menu_item_new();
+ gtk_menu_shell_insert(GTK_MENU_SHELL(menushell),
+ NODE_INFO(node)->extra, pos+1);
+ //gtk_widget_show(NODE_INFO(node)->extra);
+ }
+ }
+ break;
+ case EGG_MENU_MERGE_TOOLBAR_PLACEHOLDER:
+ /* create toolbar items for placeholders if necessary ... */
+ if (!EGG_IS_SEPARATOR_TOOL_ITEM (info->proxy) ||
+ !EGG_IS_SEPARATOR_TOOL_ITEM (info->extra))
+ {
+ if (info->proxy)
+ gtk_container_remove(GTK_CONTAINER(info->proxy->parent),
+ info->proxy);
+ if (info->extra)
+ gtk_container_remove(GTK_CONTAINER(info->extra->parent),
+ info->extra);
+ info->proxy = NULL;
+ info->extra = NULL;
+ }
+ if (info->proxy == NULL)
+ {
+ GtkWidget *toolbar;
+ gint pos;
+
+ if (find_toolbar_position(node, &toolbar, &pos))
+ {
+ EggToolItem *item;
+
+ item = egg_separator_tool_item_new();
+ egg_toolbar_insert_tool_item(EGG_TOOLBAR(toolbar), item, pos);
+ NODE_INFO(node)->proxy = GTK_WIDGET (item);
+ //gtk_widget_show(NODE_INFO(node)->proxy);
+
+ item = egg_separator_tool_item_new();
+ egg_toolbar_insert_tool_item(EGG_TOOLBAR(toolbar), item, pos+1);
+ NODE_INFO(node)->extra = GTK_WIDGET (item);
+ //gtk_widget_show(NODE_INFO(node)->extra);
+ }
+ }
+ break;
+ case EGG_MENU_MERGE_POPUPS:
+ break;
+ case EGG_MENU_MERGE_MENUITEM:
+ /* remove the proxy if it is of the wrong type ... */
+ if (info->proxy && G_OBJECT_TYPE(info->proxy) !=
+ EGG_ACTION_GET_CLASS(info->action)->menu_item_type)
+ {
+ gtk_container_remove(GTK_CONTAINER(info->proxy->parent),
+ info->proxy);
+ info->proxy = NULL;
+ }
+ /* create proxy if needed ... */
+ if (info->proxy == NULL)
+ {
+ GtkWidget *menushell;
+ gint pos;
+
+ if (find_menu_position(node, &menushell, &pos))
+ {
+ info->proxy = egg_action_create_menu_item (info->action);
+
+ gtk_menu_shell_insert (GTK_MENU_SHELL (menushell),
+ info->proxy, pos);
+ }
+ }
+ else
+ {
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(info->proxy), NULL);
+ egg_action_connect_proxy (info->action, info->proxy);
+ }
+ break;
+ case EGG_MENU_MERGE_TOOLITEM:
+ /* remove the proxy if it is of the wrong type ... */
+ if (info->proxy && G_OBJECT_TYPE(info->proxy) !=
+ EGG_ACTION_GET_CLASS(info->action)->toolbar_item_type)
+ {
+ gtk_container_remove(GTK_CONTAINER(info->proxy->parent),
+ info->proxy);
+ info->proxy = NULL;
+ }
+ /* create proxy if needed ... */
+ if (info->proxy == NULL)
+ {
+ GtkWidget *toolbar;
+ gint pos;
+
+ if (find_toolbar_position(node, &toolbar, &pos))
+ {
+ info->proxy = egg_action_create_tool_item (info->action);
+
+ egg_toolbar_insert_tool_item (EGG_TOOLBAR (toolbar),
+ EGG_TOOL_ITEM (info->proxy), pos);
+ }
+ }
+ else
+ {
+ egg_action_connect_proxy (info->action, info->proxy);
+ }
+ break;
+ case EGG_MENU_MERGE_SEPARATOR:
+ if (NODE_INFO (node->parent)->type == EGG_MENU_MERGE_TOOLBAR ||
+ NODE_INFO (node->parent)->type == EGG_MENU_MERGE_TOOLBAR_PLACEHOLDER)
+ {
+ GtkWidget *toolbar;
+ gint pos;
+
+ if (EGG_IS_SEPARATOR_TOOL_ITEM(info->proxy))
+ {
+ gtk_container_remove(GTK_CONTAINER(info->proxy->parent),
+ info->proxy);
+ info->proxy = NULL;
+ }
+
+ if (find_toolbar_position(node, &toolbar, &pos))
+ {
+ EggToolItem *item = egg_separator_tool_item_new();
+ egg_toolbar_insert_tool_item (EGG_TOOLBAR (toolbar), item, pos);
+ info->proxy = GTK_WIDGET (item);
+ gtk_widget_show(info->proxy);
+ }
+ }
+ else
+ {
+ GtkWidget *menushell;
+ gint pos;
+
+ if (GTK_IS_SEPARATOR_MENU_ITEM(info->proxy))
+ {
+ gtk_container_remove(GTK_CONTAINER(info->proxy->parent),
+ info->proxy);
+ info->proxy = NULL;
+ }
+
+ if (find_menu_position(node, &menushell, &pos))
+ {
+ info->proxy = gtk_separator_menu_item_new();
+ gtk_menu_shell_insert (GTK_MENU_SHELL (menushell),
+ info->proxy, pos);
+ gtk_widget_show(info->proxy);
+ }
+ }
+ break;
+ }
+
+ /* if this node has a widget, but it is the wrong type, remove it */
+ }
+
+ recurse_children:
+ /* process children */
+ child = node->children;
+ while (child)
+ {
+ GNode *current;
+
+ current = child;
+ child = current->next;
+ update_node (self, current);
+ }
+
+ /* handle cleanup of dead nodes */
+ if (node->children == NULL && NODE_INFO(node)->uifiles == NULL)
+ {
+ if (NODE_INFO(node)->proxy)
+ gtk_widget_destroy(NODE_INFO(node)->proxy);
+ if ((NODE_INFO(node)->type == EGG_MENU_MERGE_MENU_PLACEHOLDER ||
+ NODE_INFO(node)->type == EGG_MENU_MERGE_TOOLBAR_PLACEHOLDER) &&
+ NODE_INFO(node)->extra)
+ gtk_widget_destroy(NODE_INFO(node)->extra);
+ g_chunk_free(NODE_INFO(node), merge_node_chunk);
+ g_node_destroy(node);
+ }
+}
+
+static gboolean
+do_updates(EggMenuMerge *self)
+{
+ /* this function needs to check through the tree for dirty nodes.
+ * For such nodes, it needs to do the following:
+ *
+ * 1) check if they are referenced by any loaded UI files anymore.
+ * In which case, the proxy widget should be destroyed, unless
+ * there are any subnodes.
+ *
+ * 2) lookup the action for this node again. If it is different to
+ * the current one (or if no previous action has been looked up),
+ * the proxy is reconnected to the new action (or a new proxy widget
+ * is created and added to the parent container).
+ */
+
+ g_message("do_updates");
+
+ update_node (self, self->root_node);
+
+ self->update_tag = 0;
+ return FALSE;
+}
+
+static void
+egg_menu_merge_queue_update (EggMenuMerge *self)
+{
+ if (self->update_tag != 0)
+ return;
+
+ self->update_tag = g_idle_add((GSourceFunc)do_updates, self);
+}
+
+void
+egg_menu_merge_ensure_update (EggMenuMerge *self)
+{
+ if (self->update_tag != 0)
+ {
+ g_source_remove(self->update_tag);
+ do_updates(self);
+ }
+}
+
+static gboolean
+dirty_traverse_func (GNode *node, gpointer data)
+{
+ NODE_INFO(node)->dirty = TRUE;
+ return FALSE;
+}
+
+static void
+egg_menu_merge_dirty_all (EggMenuMerge *self)
+{
+ g_node_traverse(self->root_node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
+ dirty_traverse_func, NULL);
+ egg_menu_merge_queue_update(self);
+}
diff --git a/lib/egg/egg-menu-merge.h b/lib/egg/egg-menu-merge.h
new file mode 100644
index 000000000..f4c440706
--- /dev/null
+++ b/lib/egg/egg-menu-merge.h
@@ -0,0 +1,100 @@
+#ifndef EGG_MENU_MERGE_H
+#define EGG_MENU_MERGE_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <egg-action.h>
+#include <egg-action-group.h>
+
+#define EGG_TYPE_MENU_MERGE (egg_menu_merge_get_type ())
+#define EGG_MENU_MERGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_MENU_MERGE, EggMenuMerge))
+#define EGG_MENU_MERGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_MENU_MERGE, EggMenuMergeClass))
+#define EGG_IS_MENU_MERGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_MENU_MERGE))
+#define EGG_IS_MENU_MERGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EGG_TYPE_MENU_MERGE))
+#define EGG_MENU_MERGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_MENU_MERGE, EggMenuMergeClass))
+
+typedef struct _EggMenuMerge EggMenuMerge;
+typedef struct _EggMenuMergeClass EggMenuMergeClass;
+typedef struct _EggMenuMergeNode EggMenuMergeNode;
+
+typedef enum {
+ EGG_MENU_MERGE_UNDECIDED,
+ EGG_MENU_MERGE_ROOT,
+ EGG_MENU_MERGE_MENUBAR,
+ EGG_MENU_MERGE_MENU,
+ EGG_MENU_MERGE_TOOLBAR,
+ EGG_MENU_MERGE_MENU_PLACEHOLDER,
+ EGG_MENU_MERGE_TOOLBAR_PLACEHOLDER,
+ EGG_MENU_MERGE_POPUPS,
+ EGG_MENU_MERGE_MENUITEM,
+ EGG_MENU_MERGE_TOOLITEM,
+ EGG_MENU_MERGE_SEPARATOR,
+} EggMenuMergeNodeType;
+
+struct _EggMenuMerge {
+ GObject parent;
+
+ GtkAccelGroup *accel_group;
+
+ GNode *root_node;
+ GList *action_groups;
+
+ guint last_merge_id;
+
+ guint update_tag;
+};
+
+struct _EggMenuMergeClass {
+ GObjectClass parent_class;
+
+ void (* add_widget) (EggMenuMerge *merge, GtkWidget *widget);
+ void (* remove_widget) (EggMenuMerge *merge, GtkWidget *widget);
+};
+
+struct _EggMenuMergeNode {
+ EggMenuMergeNodeType type;
+
+ const gchar *name;
+
+ GQuark action_name;
+ EggAction *action;
+ GtkWidget *proxy;
+ GtkWidget *extra; /*GtkMenu for submenus, second separator for placeholders*/
+
+ GList *uifiles;
+
+ guint dirty : 1;
+};
+
+GType egg_menu_merge_get_type (void);
+EggMenuMerge *egg_menu_merge_new (void);
+
+/* these two functions will dirty all merge nodes, as they may need to
+ * be connected up to different actions */
+void egg_menu_merge_insert_action_group (EggMenuMerge *self,
+ EggActionGroup *action_group,
+ gint pos);
+void egg_menu_merge_remove_action_group (EggMenuMerge *self,
+ EggActionGroup*action_group);
+
+
+GtkWidget *egg_menu_merge_get_widget (EggMenuMerge *self,
+ const gchar *path);
+
+/* these two functions are for adding UI elements to the merged user
+ * interface */
+guint egg_menu_merge_add_ui_from_string (EggMenuMerge *self,
+ const gchar *buffer,
+ guint length,
+ GError **error);
+guint egg_menu_merge_add_ui_from_file (EggMenuMerge *self,
+ const gchar *filename,
+ GError **error);
+void egg_menu_merge_remove_ui (EggMenuMerge *self,
+ guint merge_id);
+
+void egg_menu_merge_ensure_update (EggMenuMerge *self);
+
+
+#endif /* EGG_MENU_MERGE_H */
diff --git a/lib/egg/egg-menu.h b/lib/egg/egg-menu.h
new file mode 100644
index 000000000..eb71ef66d
--- /dev/null
+++ b/lib/egg/egg-menu.h
@@ -0,0 +1,13 @@
+#ifndef EGG_MENU_H
+#define EGG_MENU_H
+
+#include <libegg/menu/egg-action.h>
+#include <libegg/menu/egg-toggle-action.h>
+#include <libegg/menu/egg-radio-action.h>
+#include <libegg/menu/egg-action-group.h>
+
+#include <libegg/menu/egg-menu-merge.h>
+
+#include <libegg/menu/egg-accel-dialog.h>
+
+#endif
diff --git a/lib/egg/egg-radio-action.c b/lib/egg/egg-radio-action.c
new file mode 100644
index 000000000..888448c50
--- /dev/null
+++ b/lib/egg/egg-radio-action.c
@@ -0,0 +1,194 @@
+#include "egg-radio-action.h"
+
+static void egg_radio_action_init (EggRadioAction *action);
+static void egg_radio_action_class_init (EggRadioActionClass *class);
+
+GType
+egg_radio_action_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EggRadioActionClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) egg_radio_action_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+
+ sizeof (EggRadioAction),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) egg_radio_action_init,
+ };
+
+ type = g_type_register_static (EGG_TYPE_TOGGLE_ACTION,
+ "EggRadioAction",
+ &type_info, 0);
+ }
+ return type;
+}
+
+static void egg_radio_action_finalize (GObject *object);
+static void egg_radio_action_activate (EggAction *action);
+
+static GObjectClass *parent_class = NULL;
+
+static void
+egg_radio_action_class_init (EggRadioActionClass *class)
+{
+ GObjectClass *object_class;
+ EggActionClass *action_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ object_class = G_OBJECT_CLASS (class);
+ action_class = EGG_ACTION_CLASS (class);
+
+ object_class->finalize = egg_radio_action_finalize;
+
+ action_class->activate = egg_radio_action_activate;
+}
+
+static void
+egg_radio_action_init (EggRadioAction *action)
+{
+ action->group = g_slist_prepend (NULL, action);
+}
+
+static void
+egg_radio_action_finalize (GObject *object)
+{
+ EggRadioAction *action;
+ GSList *tmp_list;
+
+ g_return_if_fail (EGG_IS_RADIO_ACTION (object));
+
+ action = EGG_RADIO_ACTION (object);
+
+ action->group = g_slist_remove (action->group, action);
+
+ tmp_list = action->group;
+
+ while (tmp_list)
+ {
+ EggRadioAction *tmp_action = tmp_list->data;
+
+ tmp_list = tmp_list->next;
+ tmp_action->group = action->group;
+ }
+
+ if (parent_class->finalize)
+ (* parent_class->finalize) (object);
+}
+
+static void
+egg_radio_action_activate (EggAction *action)
+{
+ EggRadioAction *radio_action;
+ EggToggleAction *toggle_action;
+ EggToggleAction *tmp_action;
+ GSList *tmp_list;
+
+ g_return_if_fail (EGG_IS_RADIO_ACTION (action));
+
+ radio_action = EGG_RADIO_ACTION (action);
+ toggle_action = EGG_TOGGLE_ACTION (action);
+
+ if (toggle_action->active)
+ {
+ tmp_list = radio_action->group;
+
+ while (tmp_list)
+ {
+ tmp_action = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ if (tmp_action->active && (tmp_action != toggle_action))
+ {
+ toggle_action->active = !toggle_action->active;
+ break;
+ }
+ }
+ }
+ else
+ {
+ toggle_action->active = !toggle_action->active;
+
+ tmp_list = radio_action->group;
+ while (tmp_list)
+ {
+ tmp_action = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ if (tmp_action->active && (tmp_action != toggle_action))
+ {
+ egg_action_activate (EGG_ACTION (tmp_action));
+ break;
+ }
+ }
+ }
+
+ egg_toggle_action_toggled (toggle_action);
+}
+
+/**
+ * egg_radio_action_get_group:
+ * @action: the action object
+ *
+ * Returns: the list representing the radio group for this object
+ */
+GSList *
+egg_radio_action_get_group (EggRadioAction *action)
+{
+ g_return_val_if_fail (EGG_IS_RADIO_ACTION (action), NULL);
+
+ return action->group;
+}
+
+/**
+ * egg_radio_action_set_group:
+ * @action: the action object
+ * @group: a list representing a radio group
+ *
+ * Sets the radio group for the radio action object.
+ */
+void
+egg_radio_action_set_group (EggRadioAction *action, GSList *group)
+{
+ g_return_if_fail (EGG_IS_RADIO_ACTION (action));
+ g_return_if_fail (!g_slist_find (group, action));
+
+ if (action->group)
+ {
+ GSList *slist;
+
+ action->group = g_slist_remove (action->group, action);
+
+ for (slist = action->group; slist; slist = slist->next)
+ {
+ EggRadioAction *tmp_action = slist->data;
+
+ tmp_action->group = action->group;
+ }
+ }
+
+ action->group = g_slist_prepend (group, action);
+
+ if (group)
+ {
+ GSList *slist;
+
+ for (slist = action->group; slist; slist = slist->next)
+ {
+ EggRadioAction *tmp_action = slist->data;
+
+ tmp_action->group = action->group;
+ }
+ }
+ else
+ {
+ EGG_TOGGLE_ACTION (action)->active = TRUE;
+ }
+}
diff --git a/lib/egg/egg-radio-action.h b/lib/egg/egg-radio-action.h
new file mode 100644
index 000000000..6fe097be5
--- /dev/null
+++ b/lib/egg/egg-radio-action.h
@@ -0,0 +1,34 @@
+#ifndef EGG_RADIO_ACTION_H
+#define EGG_RADIO_ACTION_H
+
+#include <gtk/gtk.h>
+#include <egg-action.h>
+#include <egg-toggle-action.h>
+
+#define EGG_TYPE_RADIO_ACTION (egg_radio_action_get_type ())
+#define EGG_RADIO_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_RADIO_ACTION, EggRadioAction))
+#define EGG_RADIO_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_RADIO_ACTION, EggRadioActionClass))
+#define EGG_IS_RADIO_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_RADIO_ACTION))
+#define EGG_IS_RADIO_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EGG_TYPE_RADIO_ACTION))
+#define EGG_RADIO_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_RADIO_ACTION, EggRadioActionClass))
+
+typedef struct _EggRadioAction EggRadioAction;
+typedef struct _EggRadioActionClass EggRadioActionClass;
+
+struct _EggRadioAction {
+ EggToggleAction parent;
+
+ GSList *group;
+};
+
+struct _EggRadioActionClass {
+ EggToggleActionClass parent_class;
+};
+
+GType egg_radio_action_get_type (void);
+
+GSList *egg_radio_action_get_group (EggRadioAction *action);
+void egg_radio_action_set_group (EggRadioAction *action,
+ GSList *group);
+
+#endif
diff --git a/lib/egg/egg-toggle-action.c b/lib/egg/egg-toggle-action.c
new file mode 100644
index 000000000..6c0c0b442
--- /dev/null
+++ b/lib/egg/egg-toggle-action.c
@@ -0,0 +1,197 @@
+#include "egg-toggle-action.h"
+#include "eggtoggletoolbutton.h"
+
+enum {
+ TOGGLED,
+ LAST_SIGNAL
+};
+
+static void egg_toggle_action_init (EggToggleAction *action);
+static void egg_toggle_action_class_init (EggToggleActionClass *class);
+
+GType
+egg_toggle_action_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EggToggleActionClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) egg_toggle_action_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+
+ sizeof (EggToggleAction),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) egg_toggle_action_init,
+ };
+
+ type = g_type_register_static (EGG_TYPE_ACTION,
+ "EggToggleAction",
+ &type_info, 0);
+ }
+ return type;
+}
+
+static void egg_toggle_action_activate (EggAction *action);
+static void egg_toggle_action_real_toggled (EggToggleAction *action);
+static void connect_proxy (EggAction *action,
+ GtkWidget *proxy);
+static void disconnect_proxy (EggAction *action,
+ GtkWidget *proxy);
+
+static GObjectClass *parent_class = NULL;
+static guint action_signals[LAST_SIGNAL] = { 0 };
+
+static void
+egg_toggle_action_class_init (EggToggleActionClass *class)
+{
+ EggActionClass *action_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ action_class = EGG_ACTION_CLASS (class);
+
+ action_class->activate = egg_toggle_action_activate;
+ action_class->connect_proxy = connect_proxy;
+ action_class->disconnect_proxy = disconnect_proxy;
+
+ action_class->menu_item_type = GTK_TYPE_CHECK_MENU_ITEM;
+ action_class->toolbar_item_type = EGG_TYPE_TOGGLE_TOOL_BUTTON;
+
+ class->toggled = egg_toggle_action_real_toggled;
+
+ action_signals[TOGGLED] =
+ g_signal_new ("toggled",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EggToggleActionClass, toggled),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+egg_toggle_action_init (EggToggleAction *action)
+{
+ action->active = FALSE;
+}
+
+static void
+egg_toggle_action_activate (EggAction *action)
+{
+ EggToggleAction *toggle_action;
+
+ g_return_if_fail (EGG_IS_TOGGLE_ACTION (action));
+
+ toggle_action = EGG_TOGGLE_ACTION (action);
+
+ toggle_action->active = !toggle_action->active;
+
+ egg_toggle_action_toggled (toggle_action);
+}
+
+static void
+egg_toggle_action_real_toggled (EggToggleAction *action)
+{
+ GSList *slist;
+
+ g_return_if_fail (EGG_IS_TOGGLE_ACTION (action));
+
+ for (slist = EGG_ACTION (action)->proxies; slist; slist = slist->next)
+ {
+ GtkWidget *proxy = slist->data;
+
+ egg_action_block_activate_from (EGG_ACTION (action), proxy);
+ if (GTK_IS_CHECK_MENU_ITEM (proxy))
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (proxy),
+ action->active);
+ else if (EGG_IS_TOGGLE_TOOL_BUTTON (proxy))
+ egg_toggle_tool_button_set_active (EGG_TOGGLE_TOOL_BUTTON (proxy),
+ action->active);
+ else {
+ g_warning ("Don't know how to toggle `%s' widgets",
+ G_OBJECT_TYPE_NAME (proxy));
+ }
+ egg_action_unblock_activate_from (EGG_ACTION (action), proxy);
+ }
+}
+
+static void
+connect_proxy (EggAction *action, GtkWidget *proxy)
+{
+ EggToggleAction *toggle_action;
+
+ toggle_action = EGG_TOGGLE_ACTION (action);
+
+ /* do this before hand, so that we don't call the "activate" handler */
+ if (GTK_IS_MENU_ITEM (proxy))
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (proxy),
+ toggle_action->active);
+ else if (EGG_IS_TOGGLE_TOOL_BUTTON (proxy))
+ egg_toggle_tool_button_set_active (EGG_TOGGLE_TOOL_BUTTON (proxy),
+ toggle_action->active);
+
+ (* EGG_ACTION_CLASS (parent_class)->connect_proxy) (action, proxy);
+}
+
+static void
+disconnect_proxy (EggAction *action, GtkWidget *proxy)
+{
+ EggToggleAction *toggle_action;
+
+ toggle_action = EGG_TOGGLE_ACTION (action);
+
+ (* EGG_ACTION_CLASS (parent_class)->disconnect_proxy) (action, proxy);
+}
+
+/**
+ * egg_toggle_action_toggled:
+ * @action: the action object
+ *
+ * Emits the "toggled" signal on the toggle action.
+ */
+void
+egg_toggle_action_toggled (EggToggleAction *action)
+{
+ g_return_if_fail (EGG_IS_TOGGLE_ACTION (action));
+
+ g_signal_emit (action, action_signals[TOGGLED], 0);
+}
+
+/**
+ * egg_toggle_action_set_active:
+ * @action: the action object
+ * @is_active: whether the action should be checked or not
+ *
+ * Sets the checked state on the toggle action.
+ */
+void
+egg_toggle_action_set_active (EggToggleAction *action, gboolean is_active)
+{
+ g_return_if_fail (EGG_IS_TOGGLE_ACTION (action));
+
+ is_active = is_active != 0;
+
+ if (action->active != is_active)
+ {
+ egg_action_activate (EGG_ACTION (action));
+ }
+}
+
+/**
+ * egg_toggle_action_get_active:
+ * @action: the action object
+ *
+ * Returns: the checked state of the toggle action
+ */
+gboolean
+egg_toggle_action_get_active (EggToggleAction *action)
+{
+ g_return_val_if_fail (EGG_IS_TOGGLE_ACTION (action), FALSE);
+
+ return action->active;
+}
diff --git a/lib/egg/egg-toggle-action.h b/lib/egg/egg-toggle-action.h
new file mode 100644
index 000000000..4a5293bfe
--- /dev/null
+++ b/lib/egg/egg-toggle-action.h
@@ -0,0 +1,38 @@
+#ifndef EGG_TOGGLE_ACTION_H
+#define EGG_TOGGLE_ACTION_H
+
+#include <gtk/gtk.h>
+#include <egg-action.h>
+
+#define EGG_TYPE_TOGGLE_ACTION (egg_toggle_action_get_type ())
+#define EGG_TOGGLE_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_TOGGLE_ACTION, EggToggleAction))
+#define EGG_TOGGLE_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_TOGGLE_ACTION, EggToggleActionClass))
+#define EGG_IS_TOGGLE_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_TOGGLE_ACTION))
+#define EGG_IS_TOGGLE_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EGG_TYPE_TOGGLE_ACTION))
+#define EGG_TOGGLE_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_TOGGLE_ACTION, EggToggleActionClass))
+
+typedef struct _EggToggleAction EggToggleAction;
+typedef struct _EggToggleActionClass EggToggleActionClass;
+
+struct _EggToggleAction
+{
+ EggAction parent;
+
+ guint active : 1;
+};
+
+struct _EggToggleActionClass
+{
+ EggActionClass parent_class;
+
+ void (* toggled) (EggToggleAction *action);
+};
+
+GType egg_toggle_action_get_type (void);
+
+void egg_toggle_action_toggled (EggToggleAction *action);
+void egg_toggle_action_set_active (EggToggleAction *action,
+ gboolean is_active);
+gboolean egg_toggle_action_get_active (EggToggleAction *action);
+
+#endif
diff --git a/lib/egg/eggmarshalers.c b/lib/egg/eggmarshalers.c
new file mode 100644
index 000000000..3cc9b963e
--- /dev/null
+++ b/lib/egg/eggmarshalers.c
@@ -0,0 +1,277 @@
+
+#include <glib-object.h>
+
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v) g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v) g_value_get_int (v)
+#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
+#define g_marshal_value_peek_long(v) g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
+#define g_marshal_value_peek_float(v) g_value_get_float (v)
+#define g_marshal_value_peek_double(v) g_value_get_double (v)
+#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v) g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v) g_value_get_object (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ * Do not access GValues directly in your code. Instead, use the
+ * g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
+#define g_marshal_value_peek_char(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v) (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v) (v)->data[0].v_int
+#define g_marshal_value_peek_flags(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_float(v) (v)->data[0].v_float
+#define g_marshal_value_peek_double(v) (v)->data[0].v_double
+#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* VOID:OBJECT,OBJECT (eggmarshalers.list:1) */
+void
+_egg_marshal_VOID__OBJECT_OBJECT (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ gpointer data2);
+ register GMarshalFunc_VOID__OBJECT_OBJECT callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_object (param_values + 1),
+ g_marshal_value_peek_object (param_values + 2),
+ data2);
+}
+
+/* VOID:OBJECT,STRING,LONG,LONG (eggmarshalers.list:2) */
+void
+_egg_marshal_VOID__OBJECT_STRING_LONG_LONG (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__OBJECT_STRING_LONG_LONG) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ glong arg_3,
+ glong arg_4,
+ gpointer data2);
+ register GMarshalFunc_VOID__OBJECT_STRING_LONG_LONG callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 5);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__OBJECT_STRING_LONG_LONG) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_object (param_values + 1),
+ g_marshal_value_peek_string (param_values + 2),
+ g_marshal_value_peek_long (param_values + 3),
+ g_marshal_value_peek_long (param_values + 4),
+ data2);
+}
+
+/* VOID:OBJECT,LONG (eggmarshalers.list:3) */
+void
+_egg_marshal_VOID__OBJECT_LONG (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__OBJECT_LONG) (gpointer data1,
+ gpointer arg_1,
+ glong arg_2,
+ gpointer data2);
+ register GMarshalFunc_VOID__OBJECT_LONG callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__OBJECT_LONG) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_object (param_values + 1),
+ g_marshal_value_peek_long (param_values + 2),
+ data2);
+}
+
+/* VOID:OBJECT,STRING,STRING (eggmarshalers.list:4) */
+void
+_egg_marshal_VOID__OBJECT_STRING_STRING (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__OBJECT_STRING_STRING) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ gpointer arg_3,
+ gpointer data2);
+ register GMarshalFunc_VOID__OBJECT_STRING_STRING callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 4);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__OBJECT_STRING_STRING) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_object (param_values + 1),
+ g_marshal_value_peek_string (param_values + 2),
+ g_marshal_value_peek_string (param_values + 3),
+ data2);
+}
+
+/* BOOLEAN:VOID (eggmarshalers.list:5) */
+void
+_egg_marshal_BOOLEAN__VOID (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef gboolean (*GMarshalFunc_BOOLEAN__VOID) (gpointer data1,
+ gpointer data2);
+ register GMarshalFunc_BOOLEAN__VOID callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+ gboolean v_return;
+
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 1);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_BOOLEAN__VOID) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ data2);
+
+ g_value_set_boolean (return_value, v_return);
+}
+
+/* OBJECT:VOID (eggmarshalers.list:6) */
+void
+_egg_marshal_OBJECT__VOID (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef GObject* (*GMarshalFunc_OBJECT__VOID) (gpointer data1,
+ gpointer data2);
+ register GMarshalFunc_OBJECT__VOID callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+ GObject* v_return;
+
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 1);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_OBJECT__VOID) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ data2);
+
+ g_value_set_object_take_ownership (return_value, v_return);
+}
+
diff --git a/lib/egg/eggmarshalers.h b/lib/egg/eggmarshalers.h
new file mode 100644
index 000000000..dac29f1d1
--- /dev/null
+++ b/lib/egg/eggmarshalers.h
@@ -0,0 +1,60 @@
+
+#ifndef ___egg_marshal_MARSHAL_H__
+#define ___egg_marshal_MARSHAL_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* VOID:OBJECT,OBJECT (eggmarshalers.list:1) */
+extern void _egg_marshal_VOID__OBJECT_OBJECT (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* VOID:OBJECT,STRING,LONG,LONG (eggmarshalers.list:2) */
+extern void _egg_marshal_VOID__OBJECT_STRING_LONG_LONG (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* VOID:OBJECT,LONG (eggmarshalers.list:3) */
+extern void _egg_marshal_VOID__OBJECT_LONG (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* VOID:OBJECT,STRING,STRING (eggmarshalers.list:4) */
+extern void _egg_marshal_VOID__OBJECT_STRING_STRING (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* BOOLEAN:VOID (eggmarshalers.list:5) */
+extern void _egg_marshal_BOOLEAN__VOID (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* OBJECT:VOID (eggmarshalers.list:6) */
+extern void _egg_marshal_OBJECT__VOID (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+G_END_DECLS
+
+#endif /* ___egg_marshal_MARSHAL_H__ */
+
diff --git a/lib/egg/eggmarshalers.list b/lib/egg/eggmarshalers.list
new file mode 100644
index 000000000..03890af58
--- /dev/null
+++ b/lib/egg/eggmarshalers.list
@@ -0,0 +1,6 @@
+VOID:OBJECT,OBJECT
+VOID:OBJECT,STRING,LONG,LONG
+VOID:OBJECT,LONG
+VOID:OBJECT,STRING,STRING
+BOOLEAN:VOID
+OBJECT:VOID
diff --git a/lib/egg/eggradiotoolbutton.c b/lib/egg/eggradiotoolbutton.c
new file mode 100644
index 000000000..ec14990b8
--- /dev/null
+++ b/lib/egg/eggradiotoolbutton.c
@@ -0,0 +1,121 @@
+/* eggradiotoolbutton.c
+ *
+ * Copyright (C) 2002 Anders Carlsson <andersca@codefactory.se>
+ * Copyright (C) 2002 James Henstridge <james@daa.com.au>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "eggradiotoolbutton.h"
+#include <gtk/gtkradiobutton.h>
+
+#ifndef _
+# define _(s) (s)
+#endif
+
+static void egg_radio_tool_button_init (EggRadioToolButton *button);
+static void egg_radio_tool_button_class_init (EggRadioToolButtonClass *klass);
+
+GType
+egg_radio_tool_button_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EggRadioToolButtonClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) egg_radio_tool_button_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+ sizeof (EggRadioToolButton),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) egg_radio_tool_button_init
+ };
+
+ type = g_type_register_static (EGG_TYPE_TOGGLE_TOOL_BUTTON,
+ "EggRadioToolButton", &type_info, 0);
+ }
+ return type;
+}
+
+
+static void
+egg_radio_tool_button_class_init (EggRadioToolButtonClass *klass)
+{
+ EggToolButtonClass *toolbutton_class;
+
+ toolbutton_class = (EggToolButtonClass *)klass;
+
+ toolbutton_class->button_type = GTK_TYPE_RADIO_BUTTON;
+}
+
+static void
+egg_radio_tool_button_init (EggRadioToolButton *button)
+{
+ gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (EGG_TOOL_BUTTON (button)->button), FALSE);
+}
+
+EggToolItem *
+egg_radio_tool_button_new (GSList *group)
+{
+ EggRadioToolButton *button;
+
+ button = g_object_new (EGG_TYPE_RADIO_TOOL_BUTTON,
+ NULL);
+
+ egg_radio_tool_button_set_group (button, group);
+
+ return EGG_TOOL_ITEM (button);
+}
+
+EggToolItem *
+egg_radio_tool_button_new_from_stock (GSList *group,
+ const gchar *stock_id)
+{
+ EggRadioToolButton *button;
+
+ button = g_object_new (EGG_TYPE_RADIO_TOOL_BUTTON,
+ "stock_id", stock_id,
+ "use_underline", TRUE,
+ NULL);
+
+
+ egg_radio_tool_button_set_group (button, group);
+
+ return EGG_TOOL_ITEM (button);
+}
+
+GSList *
+egg_radio_tool_button_get_group (EggRadioToolButton *button)
+{
+ g_return_val_if_fail (EGG_IS_RADIO_TOOL_BUTTON (button), NULL);
+
+ return gtk_radio_button_get_group (GTK_RADIO_BUTTON (EGG_TOOL_BUTTON (button)->button));
+}
+
+void
+egg_radio_tool_button_set_group (EggRadioToolButton *button,
+ GSList *group)
+{
+ g_return_if_fail (EGG_IS_RADIO_TOOL_BUTTON (button));
+
+ gtk_radio_button_set_group (GTK_RADIO_BUTTON (EGG_TOOL_BUTTON (button)->button), group);
+}
+
diff --git a/lib/egg/eggradiotoolbutton.h b/lib/egg/eggradiotoolbutton.h
new file mode 100644
index 000000000..44f6a4c1f
--- /dev/null
+++ b/lib/egg/eggradiotoolbutton.h
@@ -0,0 +1,57 @@
+/* eggradiotoolbutton.h
+ *
+ * Copyright (C) 2002 Anders Carlsson <andersca@codefactory.se>
+ * Copyright (C) 2002 James Henstridge <james@daa.com.au>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_RADIO_TOOL_BUTTON_H__
+#define __EGG_RADIO_TOOL_BUTTON_H__
+
+#include "eggtoggletoolbutton.h"
+
+#define EGG_TYPE_RADIO_TOOL_BUTTON (egg_radio_tool_button_get_type ())
+#define EGG_RADIO_TOOL_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_RADIO_TOOL_BUTTON, EggRadioToolButton))
+#define EGG_RADIO_TOOL_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_RADIO_TOOL_BUTTON, EggRadioToolButtonClass))
+#define EGG_IS_RADIO_TOOL_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_RADIO_TOOL_BUTTON))
+#define EGG_IS_RADIO_TOOL_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EGG_TYPE_RADIO_TOOL_BUTTON))
+#define EGG_RADIO_TOOL_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_RADIO_TOOL_BUTTON, EggRadioToolButtonClass))
+
+typedef struct _EggRadioToolButton EggRadioToolButton;
+typedef struct _EggRadioToolButtonClass EggRadioToolButtonClass;
+
+struct _EggRadioToolButton
+{
+ EggToggleToolButton parent;
+};
+
+struct _EggRadioToolButtonClass
+{
+ EggToggleToolButtonClass parent_class;
+};
+
+GType egg_radio_tool_button_get_type (void) G_GNUC_CONST;
+EggToolItem *egg_radio_tool_button_new (GSList *group);
+EggToolItem *egg_radio_tool_button_new_from_stock (GSList *group,
+ const gchar *stock_id);
+
+GSList *egg_radio_tool_button_get_group (EggRadioToolButton *button);
+void egg_radio_tool_button_set_group (EggRadioToolButton *button,
+ GSList *group);
+
+
+#endif /* __EGG_RADIO_TOOL_BUTTON_H__ */
diff --git a/lib/egg/eggseparatortoolitem.c b/lib/egg/eggseparatortoolitem.c
new file mode 100644
index 000000000..e3fe098fc
--- /dev/null
+++ b/lib/egg/eggseparatortoolitem.c
@@ -0,0 +1,86 @@
+#include <gtk/gtkseparatormenuitem.h>
+#include "eggseparatortoolitem.h"
+
+#ifndef _
+# define _(s) (s)
+#endif
+
+static void egg_separator_tool_item_init (EggSeparatorToolItem *self);
+static void egg_separator_tool_item_class_init (EggSeparatorToolItemClass*class);
+
+static void egg_separator_tool_item_add (GtkContainer *container,
+ GtkWidget *child);
+static GtkWidget *egg_separator_tool_item_create_menu_proxy (EggToolItem *self);
+
+static GObjectClass *parent_class = NULL;
+
+
+GType
+egg_separator_tool_item_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EggSeparatorToolItemClass),
+ (GBaseInitFunc) 0,
+ (GBaseFinalizeFunc) 0,
+ (GClassInitFunc) egg_separator_tool_item_class_init,
+ (GClassFinalizeFunc) 0,
+ NULL,
+ sizeof (EggSeparatorToolItem),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) egg_separator_tool_item_init
+ };
+
+ type = g_type_register_static (EGG_TYPE_TOOL_ITEM,
+ "EggSeparatorToolItem", &type_info, 0);
+ }
+ return type;
+}
+
+
+static void
+egg_separator_tool_item_class_init (EggSeparatorToolItemClass *class)
+{
+ GtkContainerClass *container_class;
+ EggToolItemClass *toolitem_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ container_class = (GtkContainerClass *)class;
+ toolitem_class = (EggToolItemClass *)class;
+
+ container_class->add = egg_separator_tool_item_add;
+ toolitem_class->create_menu_proxy = egg_separator_tool_item_create_menu_proxy;
+}
+
+static void
+egg_separator_tool_item_init (EggSeparatorToolItem *self)
+{
+}
+
+static void
+egg_separator_tool_item_add (GtkContainer *container, GtkWidget *child)
+{
+ g_warning("attempt to add a child to an EggSeparatorToolItem");
+}
+
+static GtkWidget *
+egg_separator_tool_item_create_menu_proxy (EggToolItem *item)
+{
+ return gtk_separator_menu_item_new ();
+}
+
+
+EggToolItem *
+egg_separator_tool_item_new (void)
+{
+ EggToolItem *self;
+
+ self = g_object_new (EGG_TYPE_SEPARATOR_TOOL_ITEM,
+ NULL);
+
+ return self;
+}
diff --git a/lib/egg/eggseparatortoolitem.h b/lib/egg/eggseparatortoolitem.h
new file mode 100644
index 000000000..2947b981b
--- /dev/null
+++ b/lib/egg/eggseparatortoolitem.h
@@ -0,0 +1,50 @@
+/* eggtoggletoolbutton.h
+ *
+ * Copyright (C) 2002 Anders Carlsson <andersca@codefactory.se>
+ * Copyright (C) 2002 James Henstridge <james@daa.com.au>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_SEPARATOR_TOOL_ITEM_H__
+#define __EGG_SEPARATOR_TOOL_ITEM_H__
+
+#include "eggtoolitem.h"
+
+#define EGG_TYPE_SEPARATOR_TOOL_ITEM (egg_separator_tool_item_get_type ())
+#define EGG_SEPARATOR_TOOL_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SEPARATOR_TOOL_ITEM, EggSeparatorToolItem))
+#define EGG_SEPARATOR_TOOL_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SEPARATOR_TOOL_ITEM, EggSeparatorToolItemClass))
+#define EGG_IS_SEPARATOR_TOOL_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SEPARATOR_TOOL_ITEM))
+#define EGG_IS_SEPARATOR_TOOL_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EGG_TYPE_SEPARATOR_TOOL_ITEM))
+#define EGG_SEPARATOR_TOOL_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_SEPARATOR_TOOL_ITEM, EggSeparatorToolItemClass))
+
+typedef struct _EggSeparatorToolItem EggSeparatorToolItem;
+typedef struct _EggSeparatorToolItemClass EggSeparatorToolItemClass;
+
+struct _EggSeparatorToolItem
+{
+ EggToolItem parent;
+};
+
+struct _EggSeparatorToolItemClass
+{
+ EggToolItemClass parent_class;
+};
+
+GType egg_separator_tool_item_get_type (void) G_GNUC_CONST;
+EggToolItem *egg_separator_tool_item_new (void);
+
+#endif /* __EGG_SEPARATOR_TOOL_ITEM_H__ */
diff --git a/lib/egg/eggtoggletoolbutton.c b/lib/egg/eggtoggletoolbutton.c
new file mode 100644
index 000000000..c694eb9ad
--- /dev/null
+++ b/lib/egg/eggtoggletoolbutton.c
@@ -0,0 +1,192 @@
+/* eggtoggletoolbutton.c
+ *
+ * Copyright (C) 2002 Anders Carlsson <andersca@codefactory.se>
+ * Copyright (C) 2002 James Henstridge <james@daa.com.au>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "eggtoggletoolbutton.h"
+#include <gtk/gtkcheckmenuitem.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtktogglebutton.h>
+
+#ifndef _
+# define _(s) (s)
+#endif
+
+enum {
+ TOGGLED,
+ LAST_SIGNAL
+};
+
+static void egg_toggle_tool_button_init (EggToggleToolButton *button);
+static void egg_toggle_tool_button_class_init (EggToggleToolButtonClass *klass);
+
+static GtkWidget *egg_toggle_tool_button_create_menu_proxy (EggToolItem *button);
+
+
+static void button_toggled (GtkWidget *widget,
+ EggToggleToolButton *button);
+
+
+
+static GObjectClass *parent_class = NULL;
+static guint toggle_signals[LAST_SIGNAL] = { 0 };
+
+GType
+egg_toggle_tool_button_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EggToggleToolButtonClass),
+ (GBaseInitFunc) 0,
+ (GBaseFinalizeFunc) 0,
+ (GClassInitFunc) egg_toggle_tool_button_class_init,
+ (GClassFinalizeFunc) 0,
+ NULL,
+ sizeof (EggToggleToolButton),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) egg_toggle_tool_button_init
+ };
+
+ type = g_type_register_static (EGG_TYPE_TOOL_BUTTON,
+ "EggToggleToolButton", &type_info, 0);
+ }
+ return type;
+}
+
+
+static void
+egg_toggle_tool_button_class_init (EggToggleToolButtonClass *klass)
+{
+ EggToolItemClass *toolitem_class;
+ EggToolButtonClass *toolbutton_class;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ toolitem_class = (EggToolItemClass *)klass;
+ toolbutton_class = (EggToolButtonClass *)klass;
+
+ toolitem_class->create_menu_proxy = egg_toggle_tool_button_create_menu_proxy;
+ toolbutton_class->button_type = GTK_TYPE_TOGGLE_BUTTON;
+
+ toggle_signals[TOGGLED] =
+ g_signal_new ("toggled",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EggToggleToolButtonClass, toggled),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+egg_toggle_tool_button_init (EggToggleToolButton *button)
+{
+ g_signal_connect_object (EGG_TOOL_BUTTON (button)->button, "toggled",
+ G_CALLBACK (button_toggled), button, 0);
+}
+
+static GtkWidget *
+egg_toggle_tool_button_create_menu_proxy (EggToolItem *item)
+{
+ EggToggleToolButton *button = EGG_TOGGLE_TOOL_BUTTON (item);
+ GtkWidget *menu_item;
+ const char *label;
+
+ label = gtk_label_get_text (GTK_LABEL (EGG_TOOL_BUTTON (button)->label));
+
+ menu_item = gtk_check_menu_item_new_with_mnemonic (label);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item),
+ button->active);
+ g_signal_connect_object (menu_item, "activate",
+ G_CALLBACK (gtk_button_clicked),
+ EGG_TOOL_BUTTON (button)->button,
+ G_CONNECT_SWAPPED);
+
+ return menu_item;
+}
+
+static void
+button_toggled (GtkWidget *widget,
+ EggToggleToolButton *button)
+{
+ gboolean toggle_active;
+
+ toggle_active = GTK_TOGGLE_BUTTON (widget)->active;
+ if (toggle_active != button->active)
+ {
+ button->active = toggle_active;
+ g_signal_emit (G_OBJECT (button), toggle_signals[TOGGLED], 0);
+ }
+}
+
+EggToolItem *
+egg_toggle_tool_button_new (void)
+{
+ EggToolButton *button;
+
+ button = g_object_new (EGG_TYPE_TOGGLE_TOOL_BUTTON,
+ NULL);
+
+ return EGG_TOOL_ITEM (button);
+}
+
+EggToolItem *
+egg_toggle_tool_button_new_from_stock (const gchar *stock_id)
+{
+ EggToolButton *button;
+
+ button = g_object_new (EGG_TYPE_TOGGLE_TOOL_BUTTON,
+ "stock_id", stock_id,
+ "use_underline", TRUE,
+ NULL);
+
+ return EGG_TOOL_ITEM (button);
+}
+
+void
+egg_toggle_tool_button_toggled (EggToggleToolButton *button)
+{
+ g_return_if_fail (EGG_IS_TOGGLE_TOOL_BUTTON (button));
+
+ gtk_toggle_button_toggled (GTK_TOGGLE_BUTTON(EGG_TOOL_BUTTON(button)->button));
+}
+
+void
+egg_toggle_tool_button_set_active (EggToggleToolButton *button,
+ gboolean is_active)
+{
+ g_return_if_fail (EGG_IS_TOGGLE_TOOL_BUTTON (button));
+
+ is_active = is_active != FALSE;
+
+ if (button->active != is_active)
+ gtk_button_clicked (GTK_BUTTON (EGG_TOOL_BUTTON (button)->button));
+}
+
+gboolean
+egg_toggle_tool_button_get_active (EggToggleToolButton *button)
+{
+ g_return_val_if_fail (EGG_IS_TOGGLE_TOOL_BUTTON (button), FALSE);
+
+ return button->active;
+}
diff --git a/lib/egg/eggtoggletoolbutton.h b/lib/egg/eggtoggletoolbutton.h
new file mode 100644
index 000000000..587d42257
--- /dev/null
+++ b/lib/egg/eggtoggletoolbutton.h
@@ -0,0 +1,64 @@
+/* eggtoggletoolbutton.h
+ *
+ * Copyright (C) 2002 Anders Carlsson <andersca@codefactory.se>
+ * Copyright (C) 2002 James Henstridge <james@daa.com.au>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_TOGGLE_TOOL_BUTTON_H__
+#define __EGG_TOGGLE_TOOL_BUTTON_H__
+
+#include "eggtoolbutton.h"
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_TOGGLE_TOOL_BUTTON (egg_toggle_tool_button_get_type ())
+#define EGG_TOGGLE_TOOL_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_TOGGLE_TOOL_BUTTON, EggToggleToolButton))
+#define EGG_TOGGLE_TOOL_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_TOGGLE_TOOL_BUTTON, EggToggleToolButtonClass))
+#define EGG_IS_TOGGLE_TOOL_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_TOGGLE_TOOL_BUTTON))
+#define EGG_IS_TOGGLE_TOOL_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EGG_TYPE_TOGGLE_TOOL_BUTTON))
+#define EGG_TOGGLE_TOOL_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_TOGGLE_TOOL_BUTTON, EggToggleToolButtonClass))
+
+typedef struct _EggToggleToolButton EggToggleToolButton;
+typedef struct _EggToggleToolButtonClass EggToggleToolButtonClass;
+
+struct _EggToggleToolButton
+{
+ EggToolButton parent;
+
+ guint active : 1;
+};
+
+struct _EggToggleToolButtonClass
+{
+ EggToolButtonClass parent_class;
+
+ void (* toggled) (EggToggleToolButton *button);
+};
+
+GType egg_toggle_tool_button_get_type (void) G_GNUC_CONST;
+EggToolItem *egg_toggle_tool_button_new (void);
+EggToolItem *egg_toggle_tool_button_new_from_stock (const gchar *stock_id);
+
+void egg_toggle_tool_button_toggled (EggToggleToolButton *button);
+void egg_toggle_tool_button_set_active (EggToggleToolButton *button,
+ gboolean is_active);
+gboolean egg_toggle_tool_button_get_active (EggToggleToolButton *button);
+
+G_END_DECLS
+
+#endif /* __EGG_TOGGLE_TOOL_BUTTON_H__ */
diff --git a/lib/egg/eggtoolbar.c b/lib/egg/eggtoolbar.c
new file mode 100644
index 000000000..3f90fed6a
--- /dev/null
+++ b/lib/egg/eggtoolbar.c
@@ -0,0 +1,1850 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * GtkToolbar copyright (C) Federico Mena
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include <gtk/gtkarrow.h>
+#include "eggtoolbar.h"
+#include "eggradiotoolbutton.h"
+#include "eggseparatortoolitem.h"
+#include <gtk/gtkmenu.h>
+#include <gtk/gtkradiobutton.h>
+#include <gtk/gtktoolbar.h>
+
+#define DEFAULT_IPADDING 0
+#define DEFAULT_SPACE_SIZE 5
+#define DEFAULT_SPACE_STYLE GTK_TOOLBAR_SPACE_LINE
+
+#define DEFAULT_ICON_SIZE GTK_ICON_SIZE_LARGE_TOOLBAR
+#define DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_BOTH
+
+#define SPACE_LINE_DIVISION 10
+#define SPACE_LINE_START 3
+#define SPACE_LINE_END 7
+
+#define TOOLBAR_ITEM_VISIBLE(item) \
+(GTK_WIDGET_VISIBLE (item) && \
+((toolbar->orientation == GTK_ORIENTATION_HORIZONTAL && item->visible_horizontal) || \
+ (toolbar->orientation == GTK_ORIENTATION_VERTICAL && item->visible_vertical)))
+
+#ifndef _
+# define _(s) (s)
+#endif
+
+enum {
+ PROP_0,
+ PROP_ORIENTATION,
+ PROP_TOOLBAR_STYLE,
+ PROP_SHOW_ARROW
+};
+
+enum {
+ ORIENTATION_CHANGED,
+ STYLE_CHANGED,
+ LAST_SIGNAL
+};
+
+static void egg_toolbar_init (EggToolbar *toolbar);
+static void egg_toolbar_class_init (EggToolbarClass *klass);
+
+static void egg_toolbar_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void egg_toolbar_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static gint egg_toolbar_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void egg_toolbar_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void egg_toolbar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void egg_toolbar_style_set (GtkWidget *widget,
+ GtkStyle *prev_style);
+static gboolean egg_toolbar_focus (GtkWidget *widget,
+ GtkDirectionType dir);
+static void egg_toolbar_screen_changed (GtkWidget *widget,
+ GdkScreen *previous_screen);
+
+static void egg_toolbar_add (GtkContainer *container,
+ GtkWidget *widget);
+static void egg_toolbar_remove (GtkContainer *container,
+ GtkWidget *widget);
+static void egg_toolbar_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data);
+static GType egg_toolbar_child_type (GtkContainer *container);
+
+
+static void egg_toolbar_real_orientation_changed (EggToolbar *toolbar,
+ GtkOrientation orientation);
+static void egg_toolbar_real_style_changed (EggToolbar *toolbar,
+ GtkToolbarStyle style);
+
+static void egg_toolbar_button_press (GtkWidget *button,
+ GdkEventButton *event,
+ EggToolbar *toolbar);
+static void egg_toolbar_update_button_relief (EggToolbar *toolbar);
+static GtkReliefStyle get_button_relief (EggToolbar *toolbar);
+static gint get_space_size (EggToolbar *toolbar);
+static GtkToolbarSpaceStyle get_space_style (EggToolbar *toolbar);
+
+static GtkWidget *egg_toolbar_internal_insert_element (EggToolbar *toolbar,
+ EggToolbarChildType type,
+ GtkWidget *widget,
+ const char *text,
+ const char *tooltip_text,
+ const char *tooltip_private_text,
+ GtkWidget *icon,
+ GtkSignalFunc callback,
+ gpointer user_data,
+ gint position,
+ gboolean use_stock);
+
+
+#define PRIVATE_KEY "egg-toolbar-private"
+
+#define EGG_TOOLBAR_GET_PRIVATE(toolbar) (g_object_get_data (G_OBJECT (toolbar), PRIVATE_KEY))
+
+typedef struct
+{
+ GList *items;
+ GList *first_non_fitting_item;
+
+ gint total_button_maxw;
+ gint total_button_maxh;
+
+ GtkWidget *button;
+ GtkWidget *arrow;
+
+ gboolean show_arrow;
+} EggToolbarPrivate;
+
+static GtkContainerClass *parent_class = NULL;
+static guint toolbar_signals [LAST_SIGNAL] = { 0 };
+
+GType
+egg_toolbar_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EggToolbarClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) egg_toolbar_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+ sizeof (EggToolbar),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) egg_toolbar_init,
+ };
+
+ type = g_type_register_static (GTK_TYPE_CONTAINER,
+ "EggToolbar",
+ &type_info, 0);
+ }
+
+ return type;
+}
+
+static void
+egg_toolbar_class_init (EggToolbarClass *klass)
+{
+ GObjectClass *gobject_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ gobject_class = (GObjectClass *)klass;
+ widget_class = (GtkWidgetClass *)klass;
+ container_class = (GtkContainerClass *)klass;
+
+ gobject_class->set_property = egg_toolbar_set_property;
+ gobject_class->get_property = egg_toolbar_get_property;
+
+ widget_class->expose_event = egg_toolbar_expose;
+ widget_class->size_request = egg_toolbar_size_request;
+ widget_class->size_allocate = egg_toolbar_size_allocate;
+ widget_class->style_set = egg_toolbar_style_set;
+ widget_class->focus = egg_toolbar_focus;
+ widget_class->screen_changed = egg_toolbar_screen_changed;
+
+ container_class->add = egg_toolbar_add;
+ container_class->remove = egg_toolbar_remove;
+ container_class->forall = egg_toolbar_forall;
+ container_class->child_type = egg_toolbar_child_type;
+
+ klass->orientation_changed = egg_toolbar_real_orientation_changed;
+ klass->style_changed = egg_toolbar_real_style_changed;
+
+ toolbar_signals[ORIENTATION_CHANGED] =
+ g_signal_new ("orientation_changed",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EggToolbarClass, orientation_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__ENUM,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_ORIENTATION);
+ toolbar_signals[STYLE_CHANGED] =
+ g_signal_new ("style_changed",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EggToolbarClass, style_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__ENUM,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_TOOLBAR_STYLE);
+
+ g_object_class_install_property (gobject_class,
+ PROP_ORIENTATION,
+ g_param_spec_enum ("orientation",
+ _("Orientation"),
+ _("The orientation of the toolbar"),
+ GTK_TYPE_ORIENTATION,
+ GTK_ORIENTATION_HORIZONTAL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_TOOLBAR_STYLE,
+ g_param_spec_enum ("toolbar_style",
+ _("Toolbar Style"),
+ _("How to draw the toolbar"),
+ GTK_TYPE_TOOLBAR_STYLE,
+ GTK_TOOLBAR_ICONS,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_SHOW_ARROW,
+ g_param_spec_boolean ("show_arrow",
+ _("Show Arrow"),
+ _("If an arrow should be shown if the toolbar doesn't fit"),
+ FALSE,
+ G_PARAM_READWRITE));
+
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_int ("space_size",
+ _("Spacer size"),
+ _("Size of spacers"),
+ 0,
+ G_MAXINT,
+ DEFAULT_SPACE_SIZE,
+ G_PARAM_READABLE));
+
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_int ("internal_padding",
+ _("Internal padding"),
+ _("Amount of border space between the toolbar shadow and the buttons"),
+ 0,
+ G_MAXINT,
+ DEFAULT_IPADDING,
+ G_PARAM_READABLE));
+
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_enum ("space_style",
+ _("Space style"),
+ _("Whether spacers are vertical lines or just blank"),
+ GTK_TYPE_TOOLBAR_SPACE_STYLE,
+ DEFAULT_SPACE_STYLE,
+ G_PARAM_READABLE));
+
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_enum ("button_relief",
+ _("Button relief"),
+ _("Type of bevel around toolbar buttons"),
+ GTK_TYPE_RELIEF_STYLE,
+ GTK_RELIEF_NONE,
+ G_PARAM_READABLE));
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_enum ("shadow_type",
+ _("Shadow type"),
+ _("Style of bevel around the toolbar"),
+ GTK_TYPE_SHADOW_TYPE,
+ GTK_SHADOW_OUT,
+ G_PARAM_READABLE));
+
+ gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-style",
+ _("Toolbar style"),
+ _("Whether default toolbars have text only, text and icons, icons only, etc."),
+ GTK_TYPE_TOOLBAR_STYLE,
+ DEFAULT_TOOLBAR_STYLE,
+ G_PARAM_READWRITE));
+
+ gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-icon-size",
+ _("Toolbar icon size"),
+ _("Size of icons in default toolbars"),
+ GTK_TYPE_ICON_SIZE,
+ DEFAULT_ICON_SIZE,
+ G_PARAM_READWRITE));
+}
+
+static void
+egg_toolbar_init (EggToolbar *toolbar)
+{
+ EggToolbarPrivate *priv;
+
+ GTK_WIDGET_SET_FLAGS (toolbar, GTK_NO_WINDOW);
+ GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_CAN_FOCUS);
+
+ priv = g_new0 (EggToolbarPrivate, 1);
+ g_object_set_data (G_OBJECT (toolbar), PRIVATE_KEY, priv);
+
+ toolbar->orientation = GTK_ORIENTATION_HORIZONTAL;
+ toolbar->style = GTK_TOOLBAR_ICONS;
+ toolbar->tooltips = gtk_tooltips_new ();
+ g_object_ref (toolbar->tooltips);
+ gtk_object_sink (GTK_OBJECT (toolbar->tooltips));
+
+ priv->button = gtk_toggle_button_new ();
+ g_signal_connect (priv->button, "button_press_event",
+ G_CALLBACK (egg_toolbar_button_press), toolbar);
+ gtk_button_set_relief (GTK_BUTTON (priv->button),
+ get_button_relief (toolbar));
+ GTK_WIDGET_UNSET_FLAGS (priv->button, GTK_CAN_FOCUS);
+
+ priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
+ gtk_widget_show (priv->arrow);
+ gtk_container_add (GTK_CONTAINER (priv->button), priv->arrow);
+
+ gtk_widget_set_parent (priv->button, GTK_WIDGET (toolbar));
+}
+
+static void
+egg_toolbar_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EggToolbar *toolbar = EGG_TOOLBAR (object);
+
+ switch (prop_id)
+ {
+ case PROP_ORIENTATION:
+ egg_toolbar_set_orientation (toolbar, g_value_get_enum (value));
+ break;
+ case PROP_TOOLBAR_STYLE:
+ egg_toolbar_set_style (toolbar, g_value_get_enum (value));
+ break;
+ case PROP_SHOW_ARROW:
+ egg_toolbar_set_show_arrow (toolbar, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+egg_toolbar_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EggToolbar *toolbar = EGG_TOOLBAR (object);
+ EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar);
+
+ switch (prop_id)
+ {
+ case PROP_ORIENTATION:
+ g_value_set_enum (value, toolbar->orientation);
+ break;
+ case PROP_TOOLBAR_STYLE:
+ g_value_set_enum (value, toolbar->style);
+ break;
+ case PROP_SHOW_ARROW:
+ g_value_set_boolean (value, priv->show_arrow);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+egg_toolbar_paint_space_line (GtkWidget *widget,
+ GdkRectangle *area,
+ EggToolItem *item)
+{
+ EggToolbar *toolbar;
+ GtkAllocation *allocation;
+ gint space_size;
+
+ g_return_if_fail (GTK_BIN (item)->child == NULL);
+
+ toolbar = EGG_TOOLBAR (widget);
+
+ allocation = &GTK_WIDGET (item)->allocation;
+ space_size = get_space_size (toolbar);
+
+ if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ gtk_paint_vline (widget->style, widget->window,
+ GTK_WIDGET_STATE (widget), area, widget,
+ "toolbar",
+ allocation->y + allocation->height *
+ SPACE_LINE_START / SPACE_LINE_DIVISION,
+ allocation->y + allocation->height *
+ SPACE_LINE_END / SPACE_LINE_DIVISION,
+ allocation->x + (space_size-widget->style->xthickness)/2);
+ else if (toolbar->orientation == GTK_ORIENTATION_VERTICAL)
+ gtk_paint_hline (widget->style, widget->window,
+ GTK_WIDGET_STATE (widget), area, widget,
+ "toolbar",
+ allocation->x + allocation->width *
+ SPACE_LINE_START / SPACE_LINE_DIVISION,
+ allocation->x + allocation->width *
+ SPACE_LINE_END / SPACE_LINE_DIVISION,
+ allocation->y + (space_size-widget->style->ythickness)/2);
+}
+
+static gint
+egg_toolbar_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ EggToolbar *toolbar = EGG_TOOLBAR (widget);
+ EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar);
+
+ GList *items;
+ gint border_width;
+
+ border_width = GTK_CONTAINER (widget)->border_width;
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ GtkShadowType shadow_type;
+
+ gtk_widget_style_get (widget, "shadow_type", &shadow_type, NULL);
+
+ gtk_paint_box (widget->style,
+ widget->window,
+ GTK_WIDGET_STATE (widget),
+ shadow_type,
+ &event->area, widget, "toolbar",
+ widget->allocation.x + border_width,
+ widget->allocation.y + border_width,
+ widget->allocation.width - border_width,
+ widget->allocation.height - border_width);
+
+ }
+
+ items = priv->items;
+ while (items)
+ {
+ EggToolItem *item = EGG_TOOL_ITEM (items->data);
+
+ if (GTK_BIN (item)->child)
+ gtk_container_propagate_expose (GTK_CONTAINER (widget),
+ GTK_WIDGET (item),
+ event);
+ else if (GTK_WIDGET_MAPPED (item) && get_space_style (toolbar) == GTK_TOOLBAR_SPACE_LINE)
+ egg_toolbar_paint_space_line (widget, &event->area, item);
+
+ items = items->next;
+ }
+
+ gtk_container_propagate_expose (GTK_CONTAINER (widget),
+ priv->button,
+ event);
+
+ return FALSE;
+}
+
+static void
+egg_toolbar_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ EggToolbar *toolbar = EGG_TOOLBAR (widget);
+ EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar);
+ GList *items;
+ gint nbuttons, ipadding;
+ gint button_maxw, button_maxh;
+ gint total_button_maxw, total_button_maxh;
+ gint space_size;
+ GtkRequisition child_requisition;
+
+ requisition->width = GTK_CONTAINER (toolbar)->border_width * 2;
+ requisition->height = GTK_CONTAINER (toolbar)->border_width * 2;
+ nbuttons = 0;
+ button_maxw = 0;
+ button_maxh = 0;
+ total_button_maxw = 0;
+ total_button_maxh = 0;
+ items = priv->items;
+ space_size = get_space_size (toolbar);
+
+ if (priv->show_arrow)
+ {
+ /* When we enable the arrow we only want to be the
+ * size of the arrows plus the size of any items that
+ * are pack-end.
+ */
+
+ items = priv->items;
+
+ while (items)
+ {
+ EggToolItem *item = EGG_TOOL_ITEM (items->data);
+
+ if (TOOLBAR_ITEM_VISIBLE (item))
+ {
+ gtk_widget_size_request (GTK_WIDGET (item), &child_requisition);
+
+ total_button_maxw = MAX (total_button_maxw, child_requisition.width);
+ total_button_maxh = MAX (total_button_maxh, child_requisition.height);
+
+ if (item->homogeneous)
+ {
+ if (item->pack_end)
+ nbuttons++;
+ button_maxw = MAX (button_maxw, child_requisition.width);
+ button_maxh = MAX (button_maxh, child_requisition.height);
+ }
+ else if (item->pack_end)
+ {
+ if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ requisition->width += child_requisition.width;
+ else
+ requisition->height += child_requisition.height;
+ }
+ if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ requisition->height = MAX (requisition->height, child_requisition.height);
+ else
+ requisition->width = MAX (requisition->width, child_requisition.width);
+ }
+
+ items = items->next;
+ }
+
+ /* Add the arrow */
+ gtk_widget_size_request (priv->button, &child_requisition);
+
+ if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ requisition->width += child_requisition.width;
+ requisition->height = MAX (requisition->height, child_requisition.height);
+ }
+ else
+ {
+ requisition->height += child_requisition.height;
+ requisition->width = MAX (requisition->width, child_requisition.width);
+ }
+ }
+ else
+ {
+ items = priv->items;
+
+ while (items)
+ {
+ EggToolItem *item = EGG_TOOL_ITEM (items->data);
+
+ if (!TOOLBAR_ITEM_VISIBLE (item))
+ {
+ items = items->next;
+ continue;
+ }
+
+ if (!GTK_BIN (item)->child)
+ {
+ if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ requisition->width += space_size;
+ else
+ requisition->height += space_size;
+ }
+ else
+ {
+ gtk_widget_size_request (GTK_WIDGET (item), &child_requisition);
+
+ total_button_maxw = MAX (total_button_maxw, child_requisition.width);
+ total_button_maxh = MAX (total_button_maxh, child_requisition.height);
+
+ if (item->homogeneous)
+ {
+ nbuttons++;
+ button_maxw = MAX (button_maxw, child_requisition.width);
+ button_maxh = MAX (button_maxh, child_requisition.height);
+ }
+ else
+ {
+ if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ requisition->width += child_requisition.width;
+ requisition->height = MAX (requisition->height, child_requisition.height);
+ }
+ else
+ {
+ requisition->height += child_requisition.height;
+ requisition->width = MAX (requisition->width, child_requisition.width);
+ }
+ }
+ }
+
+ items = items->next;
+ }
+ }
+
+ if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ requisition->width += nbuttons * button_maxw;
+ requisition->height = MAX (requisition->height, button_maxh);
+ }
+ else
+ {
+ requisition->width = MAX (requisition->width, button_maxw);
+ requisition->height += nbuttons * button_maxh;
+ }
+
+ /* Extra spacing */
+ gtk_widget_style_get (widget, "internal_padding", &ipadding, NULL);
+
+ requisition->width += 2 * ipadding;
+ requisition->height += 2 * ipadding;
+
+ priv->total_button_maxw = total_button_maxw;
+ priv->total_button_maxh = total_button_maxh;
+
+ toolbar->button_maxw = button_maxw;
+ toolbar->button_maxh = button_maxh;
+}
+
+static void
+egg_toolbar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ EggToolbar *toolbar = EGG_TOOLBAR (widget);
+ EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar);
+ GList *items;
+ GtkAllocation child_allocation;
+ gint ipadding, space_size;
+ gint border_width, edge_position;
+ gint available_width, available_height;
+ gint available_size, total_size;
+ GtkRequisition child_requisition;
+ gint remaining_size;
+ gint number_expandable, expandable_size;
+ gboolean first_expandable;
+
+ widget->allocation = *allocation;
+ border_width = GTK_CONTAINER (widget)->border_width;
+ total_size = 0;
+ number_expandable = 0;
+ space_size = get_space_size (toolbar);
+
+ gtk_widget_style_get (widget, "internal_padding", &ipadding, NULL);
+ border_width += ipadding;
+
+ available_width = allocation->width - 2 * border_width;
+ available_height = allocation->height - 2 * border_width;
+ if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ edge_position = allocation->x + allocation->width - border_width;
+ available_size = available_width;
+ }
+ else
+ {
+ edge_position = allocation->y + allocation->height - border_width;
+ available_size = available_height;
+ }
+
+ items = g_list_last (priv->items);
+
+ while (items)
+ {
+ EggToolItem *item = EGG_TOOL_ITEM (items->data);
+
+ if (!item->pack_end || !TOOLBAR_ITEM_VISIBLE (item))
+ {
+ items = items->prev;
+ continue;
+ }
+
+ if (!GTK_BIN (item)->child)
+ {
+ if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ child_allocation.width = space_size;
+ child_allocation.height = available_height;
+ child_allocation.x = edge_position - child_allocation.width;
+ child_allocation.y = allocation->y + (allocation->height - child_allocation.height) / 2;
+
+ gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation);
+
+ edge_position -= child_allocation.width;
+ available_size -= child_allocation.width;
+ }
+ else
+ {
+ child_allocation.width = available_width;
+ child_allocation.height = space_size;
+ child_allocation.x = allocation->x + (allocation->width - child_allocation.width) / 2;
+ child_allocation.y = edge_position - child_allocation.height;
+
+ gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation);
+
+ edge_position -= child_allocation.height;
+ available_size -= child_allocation.height;
+ }
+ }
+ else
+ {
+ gtk_widget_get_child_requisition (GTK_WIDGET (item), &child_requisition);
+
+ if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ if (item->homogeneous)
+ child_allocation.width = toolbar->button_maxw;
+ else
+ child_allocation.width = child_requisition.width;
+ child_allocation.height = available_height;
+ child_allocation.y = allocation->y + (allocation->height - child_allocation.height) / 2;
+ child_allocation.x = edge_position - child_allocation.width;
+
+ gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation);
+
+ edge_position -= child_allocation.width;
+ available_size -= child_allocation.width;
+ }
+ else
+ {
+ if (item->homogeneous)
+ child_allocation.height = toolbar->button_maxh;
+ else
+ child_allocation.height = child_requisition.height;
+
+ child_allocation.width = available_width;
+ child_allocation.x = allocation->x + (allocation->width - child_allocation.width) / 2;
+ child_allocation.y = edge_position - child_allocation.height;
+
+ gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation);
+
+ edge_position -= child_allocation.height;
+ available_size -= child_allocation.height;
+ }
+ }
+
+ items = items->prev;
+ }
+
+ /* Now go through the items and see if they fit */
+ items = priv->items;
+
+ while (items)
+ {
+ EggToolItem *item = EGG_TOOL_ITEM (items->data);
+
+ if (item->pack_end || !TOOLBAR_ITEM_VISIBLE (item))
+ {
+ items = items->next;
+ continue;
+ }
+
+ if (item->expandable)
+ number_expandable += 1;
+
+ if (!GTK_BIN (item)->child)
+ {
+ total_size += space_size;
+ }
+ else
+ {
+ if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ gtk_widget_get_child_requisition (GTK_WIDGET (item), &child_requisition);
+
+ if (item->homogeneous)
+ total_size += toolbar->button_maxw;
+ else
+ total_size += child_requisition.width;
+ }
+ else
+ {
+ gtk_widget_get_child_requisition (GTK_WIDGET (item), &child_requisition);
+
+ if (item->homogeneous)
+ total_size += toolbar->button_maxh;
+ else
+ total_size += child_requisition.height;
+ }
+ }
+ items = items->next;
+ }
+
+ /* Check if we need to allocate and show the arrow */
+ if (available_size < total_size)
+ {
+ if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ gtk_widget_get_child_requisition (priv->button, &child_requisition);
+ available_size -= child_requisition.width;
+
+ child_allocation.width = child_requisition.width;
+ child_allocation.height = priv->total_button_maxh;
+ child_allocation.y = allocation->y + (allocation->height - child_allocation.height) / 2;
+ child_allocation.x = edge_position - child_allocation.width;
+ }
+ else
+ {
+ gtk_widget_get_child_requisition (priv->button, &child_requisition);
+ available_size -= child_requisition.width;
+
+ child_allocation.height = child_requisition.height;
+ child_allocation.width = priv->total_button_maxw;
+ child_allocation.x = allocation->x + (allocation->width - child_allocation.width) / 2;
+ child_allocation.y = edge_position - child_allocation.height;
+ }
+
+ gtk_widget_size_allocate (priv->button, &child_allocation);
+ gtk_widget_show (priv->button);
+ }
+ else
+ gtk_widget_hide (priv->button);
+
+ /* Finally allocate the remaining items */
+ items = priv->items;
+ child_allocation.x = allocation->x + border_width;
+ child_allocation.y = allocation->y + border_width;
+ remaining_size = MAX (0, available_size - total_size);
+ total_size = 0;
+ first_expandable = TRUE;
+
+ while (items)
+ {
+ EggToolItem *item = EGG_TOOL_ITEM (items->data);
+
+ if (item->pack_end || !TOOLBAR_ITEM_VISIBLE (item))
+ {
+ items = items->next;
+ continue;
+ }
+
+ if (!GTK_BIN (item)->child)
+ {
+ if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ child_allocation.width = space_size;
+ child_allocation.height = available_height;
+ child_allocation.y = allocation->y + (allocation->height - child_allocation.height) / 2;
+ total_size += child_allocation.width;
+
+ if (total_size > available_size)
+ break;
+
+ gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation);
+ gtk_widget_map (GTK_WIDGET (item));
+
+ child_allocation.x += child_allocation.width;
+ }
+ else
+ {
+ child_allocation.width = available_width;
+ child_allocation.height = space_size;
+ child_allocation.x = allocation->x + (allocation->width - child_allocation.width) / 2;
+ total_size += child_allocation.height;
+
+ if (total_size > available_size)
+ break;
+
+ gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation);
+ gtk_widget_map (GTK_WIDGET (item));
+
+ child_allocation.y += child_allocation.height;
+ }
+ }
+ else
+ {
+ gtk_widget_get_child_requisition (GTK_WIDGET (item), &child_requisition);
+
+ if (item->expandable)
+ {
+ expandable_size = remaining_size / number_expandable;
+
+ if (first_expandable)
+ {
+ expandable_size += remaining_size % number_expandable;
+ first_expandable = FALSE;
+ }
+ }
+ else
+ expandable_size = 0;
+
+ if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ if (item->homogeneous)
+ child_allocation.width = toolbar->button_maxw;
+ else
+ child_allocation.width = child_requisition.width;
+
+ child_allocation.height = available_height;
+ child_allocation.width += expandable_size;
+ child_allocation.y = allocation->y + (allocation->height - child_allocation.height) / 2;
+ total_size += child_allocation.width;
+ }
+ else
+ {
+ if (item->homogeneous)
+ child_allocation.height = toolbar->button_maxh;
+ else
+ child_allocation.height = child_requisition.height;
+
+ child_allocation.width = available_width;
+ child_allocation.height += expandable_size;
+ child_allocation.x = allocation->x + (allocation->width - child_allocation.width) / 2;
+ total_size += child_allocation.height;
+ }
+
+ if (total_size > available_size)
+ break;
+
+ gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation);
+ gtk_widget_map (GTK_WIDGET (item));
+
+ if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ child_allocation.x += child_allocation.width;
+ else
+ child_allocation.y += child_allocation.height;
+
+ }
+
+ items = items->next;
+ }
+
+ /* Unmap the remaining items */
+ priv->first_non_fitting_item = items;
+ while (items)
+ {
+ EggToolItem *item = EGG_TOOL_ITEM (items->data);
+
+ gtk_widget_unmap (GTK_WIDGET (item));
+ items = items->next;
+ }
+}
+
+static void
+egg_toolbar_style_set (GtkWidget *widget,
+ GtkStyle *prev_style)
+{
+ if (prev_style)
+ egg_toolbar_update_button_relief (EGG_TOOLBAR (widget));
+}
+
+static gboolean
+egg_toolbar_focus (GtkWidget *widget,
+ GtkDirectionType dir)
+{
+ /* Focus can't go in toolbars */
+
+ return FALSE;
+}
+
+static void
+style_change_notify (EggToolbar *toolbar)
+{
+ if (!toolbar->style_set)
+ {
+ /* pretend it was set, then unset, thus reverting to new default */
+ toolbar->style_set = TRUE;
+ egg_toolbar_unset_style (toolbar);
+ }
+}
+
+static void
+icon_size_change_notify (EggToolbar *toolbar)
+{
+ if (!toolbar->icon_size_set)
+ {
+ /* pretend it was set, then unset, thus reverting to new default */
+ toolbar->icon_size_set = TRUE;
+ egg_toolbar_unset_icon_size (toolbar);
+ }
+}
+
+static GtkSettings *
+toolbar_get_settings (EggToolbar *toolbar)
+{
+ return g_object_get_data (G_OBJECT (toolbar), "egg-toolbar-settings");
+}
+
+static void
+egg_toolbar_screen_changed (GtkWidget *widget,
+ GdkScreen *previous_screen)
+{
+ EggToolbar *toolbar = EGG_TOOLBAR (widget);
+ GtkSettings *old_settings = toolbar_get_settings (toolbar);
+ GtkSettings *settings;
+
+ if (gtk_widget_has_screen (GTK_WIDGET (toolbar)))
+ settings = gtk_widget_get_settings (GTK_WIDGET (toolbar));
+ else
+ settings = NULL;
+
+ if (settings == old_settings)
+ return;
+
+ if (old_settings)
+ {
+ g_signal_handler_disconnect (old_settings, toolbar->style_set_connection);
+ g_signal_handler_disconnect (old_settings, toolbar->icon_size_connection);
+
+ g_object_unref (old_settings);
+ }
+
+ if (settings)
+ {
+ toolbar->style_set_connection =
+ g_signal_connect_swapped (settings,
+ "notify::gtk-toolbar-style",
+ G_CALLBACK (style_change_notify),
+ toolbar);
+ toolbar->icon_size_connection =
+ g_signal_connect_swapped (settings,
+ "notify::gtk-toolbar-icon-size",
+ G_CALLBACK (icon_size_change_notify),
+ toolbar);
+
+ g_object_ref (settings);
+ g_object_set_data (G_OBJECT (toolbar), "egg-toolbar-settings", settings);
+ }
+ else
+ g_object_set_data (G_OBJECT (toolbar), "egg-toolbar-settings", NULL);
+
+ style_change_notify (toolbar);
+ icon_size_change_notify (toolbar);
+}
+
+
+static void
+egg_toolbar_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ g_return_if_fail (EGG_IS_TOOLBAR (container));
+ g_return_if_fail (EGG_IS_TOOL_ITEM (widget));
+
+ egg_toolbar_append_tool_item (EGG_TOOLBAR (container),
+ EGG_TOOL_ITEM (widget));
+}
+
+static void
+egg_toolbar_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ g_return_if_fail (EGG_IS_TOOLBAR (container));
+ g_return_if_fail (EGG_IS_TOOL_ITEM (widget));
+
+ egg_toolbar_remove_tool_item (EGG_TOOLBAR (container),
+ EGG_TOOL_ITEM (widget));
+}
+
+static void
+egg_toolbar_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ EggToolbar *toolbar = EGG_TOOLBAR (container);
+ EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar);
+ GList *items;
+
+ g_return_if_fail (callback != NULL);
+
+ items = priv->items;
+
+ while (items)
+ {
+ EggToolItem *item = EGG_TOOL_ITEM (items->data);
+
+ items = items->next;
+ (*callback) (GTK_WIDGET (item), callback_data);
+ }
+
+ if (include_internals)
+ (* callback) (priv->button, callback_data);
+}
+
+static GType
+egg_toolbar_child_type (GtkContainer *container)
+{
+ return EGG_TYPE_TOOL_ITEM;
+}
+
+static void
+egg_toolbar_real_orientation_changed (EggToolbar *toolbar,
+ GtkOrientation orientation)
+{
+ EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar);
+
+ GList *items;
+
+ if (toolbar->orientation != orientation)
+ {
+ toolbar->orientation = orientation;
+
+ items = priv->items;
+ while (items)
+ {
+ EggToolItem *item = EGG_TOOL_ITEM (items->data);
+
+ egg_tool_item_set_orientation (item, orientation);
+
+ items = items->next;
+ }
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_DOWN, GTK_SHADOW_NONE);
+ else
+ gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
+
+ gtk_widget_queue_resize (GTK_WIDGET (toolbar));
+ g_object_notify (G_OBJECT (toolbar), "orientation");
+ }
+}
+
+static void
+egg_toolbar_real_style_changed (EggToolbar *toolbar,
+ GtkToolbarStyle style)
+{
+ EggToolbarPrivate *priv;
+ GList *items;
+
+ priv = EGG_TOOLBAR_GET_PRIVATE (toolbar);
+
+ if (toolbar->style != style)
+ {
+ toolbar->style = style;
+
+ items = priv->items;
+
+ while (items)
+ {
+ EggToolItem *item = EGG_TOOL_ITEM (items->data);
+
+ egg_tool_item_set_toolbar_style (item, style);
+
+ items = items->next;
+ }
+
+ gtk_widget_queue_resize (GTK_WIDGET (toolbar));
+ g_object_notify (G_OBJECT (toolbar), "toolbar_style");
+ }
+}
+
+static void
+menu_position_func (GtkMenu *menu,
+ gint *x,
+ gint *y,
+ gboolean *push_in,
+ gpointer user_data)
+{
+ EggToolbar *toolbar = EGG_TOOLBAR (user_data);
+ EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar);
+ GtkRequisition req;
+
+ gdk_window_get_origin (GTK_BUTTON (priv->button)->event_window, x, y);
+ gtk_widget_size_request (priv->button, &req);
+
+ if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ *y += priv->button->allocation.height;
+ *x += priv->button->allocation.width - req.width;
+ }
+ else
+ {
+ *x += priv->button->allocation.width;
+ *y += priv->button->allocation.height - req.height;
+ }
+
+ *push_in = TRUE;
+}
+
+static void
+menu_deactivated (GtkWidget *menu, GtkWidget *button)
+{
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
+}
+
+static void
+egg_toolbar_button_press (GtkWidget *button,
+ GdkEventButton *event,
+ EggToolbar *toolbar)
+{
+ EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar);
+ GtkWidget *menu;
+ GtkWidget *menu_item;
+ GList *items;
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
+
+ menu = gtk_menu_new ();
+ g_signal_connect (menu, "deactivate", G_CALLBACK (menu_deactivated), button);
+
+ items = priv->first_non_fitting_item;
+ while (items)
+ {
+ EggToolItem *item = EGG_TOOL_ITEM (items->data);
+
+ if (TOOLBAR_ITEM_VISIBLE (item) && !item->pack_end)
+ {
+ menu_item = NULL;
+ g_signal_emit_by_name (item, "create_menu_proxy", &menu_item);
+
+ if (menu_item)
+ {
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+ }
+ }
+ items = items->next;
+ }
+
+ gtk_widget_show_all (menu);
+
+ gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
+ menu_position_func, toolbar,
+ event->button, event->time);
+}
+
+static void
+egg_toolbar_update_button_relief (EggToolbar *toolbar)
+{
+ EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar);
+ GtkReliefStyle relief;
+ GList *items;
+
+ relief = get_button_relief (toolbar);
+
+ items = priv->items;
+ while (items)
+ {
+ EggToolItem *item = EGG_TOOL_ITEM (items->data);
+
+ egg_tool_item_set_relief_style (item, relief);
+
+ items = items->next;
+ }
+
+ gtk_button_set_relief (GTK_BUTTON (priv->button), relief);
+}
+
+static GtkReliefStyle
+get_button_relief (EggToolbar *toolbar)
+{
+ GtkReliefStyle button_relief = GTK_RELIEF_NORMAL;
+
+ gtk_widget_ensure_style (GTK_WIDGET (toolbar));
+
+ gtk_widget_style_get (GTK_WIDGET (toolbar),
+ "button_relief", &button_relief,
+ NULL);
+
+ return button_relief;
+}
+
+static gint
+get_space_size (EggToolbar *toolbar)
+{
+ gint space_size = DEFAULT_SPACE_SIZE;
+
+ gtk_widget_style_get (GTK_WIDGET (toolbar),
+ "space_size", &space_size,
+ NULL);
+
+ return space_size;
+}
+
+static GtkToolbarSpaceStyle
+get_space_style (EggToolbar *toolbar)
+{
+ GtkToolbarSpaceStyle space_style = DEFAULT_SPACE_STYLE;
+
+ gtk_widget_style_get (GTK_WIDGET (toolbar),
+ "space_style", &space_style,
+ NULL);
+
+
+ return space_style;
+}
+
+GtkWidget *
+egg_toolbar_new (void)
+{
+ EggToolbar *toolbar;
+
+ toolbar = g_object_new (EGG_TYPE_TOOLBAR, NULL);
+
+ return GTK_WIDGET (toolbar);
+}
+
+void
+egg_toolbar_append_tool_item (EggToolbar *toolbar,
+ EggToolItem *item)
+{
+ g_return_if_fail (EGG_IS_TOOLBAR (toolbar));
+ g_return_if_fail (EGG_IS_TOOL_ITEM (item));
+
+ egg_toolbar_insert_tool_item (toolbar, item, toolbar->num_children);
+}
+
+void
+egg_toolbar_prepend_tool_item (EggToolbar *toolbar,
+ EggToolItem *item)
+{
+ g_return_if_fail (EGG_IS_TOOLBAR (toolbar));
+ g_return_if_fail (EGG_IS_TOOL_ITEM (item));
+
+ egg_toolbar_insert_tool_item (toolbar, item, 0);
+}
+
+void
+egg_toolbar_remove_tool_item (EggToolbar *toolbar,
+ EggToolItem *item)
+{
+ EggToolbarPrivate *priv;
+ GList *tmp;
+
+ g_return_if_fail (EGG_IS_TOOLBAR (toolbar));
+ g_return_if_fail (EGG_IS_TOOL_ITEM (item));
+
+ priv = EGG_TOOLBAR_GET_PRIVATE (toolbar);
+
+ for (tmp = priv->items; tmp != NULL; tmp = tmp->next)
+ {
+ GtkWidget *child = tmp->data;
+
+ if (child == GTK_WIDGET (item))
+ {
+ gboolean was_visible;
+
+ was_visible = GTK_WIDGET_VISIBLE (item);
+ gtk_widget_unparent (GTK_WIDGET (item));
+
+ priv->items = g_list_remove_link (priv->items, tmp);
+ toolbar->num_children--;
+
+ if (was_visible && GTK_WIDGET_VISIBLE (toolbar))
+ gtk_widget_queue_resize (GTK_WIDGET (toolbar));
+
+ break;
+ }
+ }
+}
+
+void
+egg_toolbar_insert_tool_item (EggToolbar *toolbar,
+ EggToolItem *item,
+ gint pos)
+{
+ EggToolbarPrivate *priv;
+
+ g_return_if_fail (EGG_IS_TOOLBAR (toolbar));
+ g_return_if_fail (EGG_IS_TOOL_ITEM (item));
+
+ priv = EGG_TOOLBAR_GET_PRIVATE (toolbar);
+
+ priv->items = g_list_insert (priv->items, item, pos);
+ toolbar->num_children++;
+
+ egg_tool_item_set_orientation (item, toolbar->orientation);
+ egg_tool_item_set_toolbar_style (item, toolbar->style);
+ egg_tool_item_set_relief_style (item, get_button_relief (toolbar));
+
+ gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (toolbar));
+ GTK_WIDGET_UNSET_FLAGS (item, GTK_CAN_FOCUS);
+}
+
+void
+egg_toolbar_set_orientation (EggToolbar *toolbar,
+ GtkOrientation orientation)
+{
+ g_return_if_fail (EGG_IS_TOOLBAR (toolbar));
+
+ g_signal_emit (toolbar, toolbar_signals[ORIENTATION_CHANGED], 0, orientation);
+}
+
+GtkOrientation
+egg_toolbar_get_orientation (EggToolbar *toolbar)
+{
+ g_return_val_if_fail (EGG_IS_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL);
+
+ return toolbar->orientation;
+}
+
+void
+egg_toolbar_set_style (EggToolbar *toolbar,
+ GtkToolbarStyle style)
+{
+ g_return_if_fail (EGG_IS_TOOLBAR (toolbar));
+
+ toolbar->style_set = TRUE;
+ g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
+}
+
+GtkToolbarStyle
+egg_toolbar_get_style (EggToolbar *toolbar)
+{
+ g_return_val_if_fail (EGG_IS_TOOLBAR (toolbar), DEFAULT_TOOLBAR_STYLE);
+
+ return toolbar->style;
+}
+
+void
+egg_toolbar_unset_style (EggToolbar *toolbar)
+{
+ GtkToolbarStyle style;
+
+ g_return_if_fail (EGG_IS_TOOLBAR (toolbar));
+
+ if (toolbar->style_set)
+ {
+ GtkSettings *settings = toolbar_get_settings (toolbar);
+
+ if (settings)
+ g_object_get (settings,
+ "gtk-toolbar-style", &style,
+ NULL);
+ else
+ style = DEFAULT_TOOLBAR_STYLE;
+
+ if (style != toolbar->style)
+ g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
+
+ toolbar->style_set = FALSE;
+ }
+}
+
+void
+egg_toolbar_set_tooltips (EggToolbar *toolbar,
+ gboolean enable)
+{
+ g_return_if_fail (EGG_IS_TOOLBAR (toolbar));
+
+ if (enable)
+ gtk_tooltips_enable (toolbar->tooltips);
+ else
+ gtk_tooltips_disable (toolbar->tooltips);
+}
+
+gboolean
+egg_toolbar_get_tooltips (EggToolbar *toolbar)
+{
+ g_return_val_if_fail (EGG_IS_TOOLBAR (toolbar), FALSE);
+
+ return toolbar->tooltips->enabled;
+}
+
+GList*
+egg_toolbar_get_tool_items (EggToolbar *toolbar)
+{
+ EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar);
+
+ g_return_val_if_fail (EGG_IS_TOOLBAR (toolbar), FALSE);
+
+ return priv->items;
+}
+
+void
+egg_toolbar_set_icon_size (EggToolbar *toolbar,
+ GtkIconSize icon_size)
+{
+ GList *items;
+ EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar);
+
+ g_return_if_fail (EGG_IS_TOOLBAR (toolbar));
+
+ toolbar->icon_size_set = TRUE;
+
+ if (toolbar->icon_size == icon_size)
+ return;
+
+ toolbar->icon_size = icon_size;
+
+ items = priv->items;
+
+ while (items)
+ {
+ EggToolItem *item = EGG_TOOL_ITEM (items->data);
+
+ egg_tool_item_set_icon_size (item, icon_size);
+
+ items = items->next;
+ }
+
+ gtk_widget_queue_resize (GTK_WIDGET (toolbar));
+}
+
+GtkIconSize
+egg_toolbar_get_icon_size (EggToolbar *toolbar)
+{
+ g_return_val_if_fail (EGG_IS_TOOLBAR (toolbar), DEFAULT_ICON_SIZE);
+
+ return toolbar->icon_size;
+}
+
+void
+egg_toolbar_unset_icon_size (EggToolbar *toolbar)
+{
+ GtkIconSize size;
+
+ if (toolbar->icon_size_set)
+ {
+ GtkSettings *settings = toolbar_get_settings (toolbar);
+
+ if (settings)
+ g_object_get (settings,
+ "gtk-toolbar-icon-size", &size,
+ NULL);
+ else
+ size = DEFAULT_ICON_SIZE;
+
+ if (size != toolbar->icon_size)
+ egg_toolbar_set_icon_size (toolbar, size);
+
+ toolbar->icon_size_set = FALSE;
+ }
+}
+
+
+void
+egg_toolbar_set_show_arrow (EggToolbar *toolbar,
+ gboolean show_arrow)
+{
+ EggToolbarPrivate *priv;
+
+ g_return_if_fail (EGG_IS_TOOLBAR (toolbar));
+
+ priv = EGG_TOOLBAR_GET_PRIVATE (toolbar);
+ show_arrow = show_arrow != FALSE;
+
+ if (priv->show_arrow != show_arrow)
+ {
+ priv->show_arrow = show_arrow;
+
+ if (!priv->show_arrow)
+ gtk_widget_hide (priv->button);
+
+ gtk_widget_queue_resize (GTK_WIDGET (toolbar));
+ g_object_notify (G_OBJECT (toolbar), "show_arrow");
+ }
+}
+
+gboolean
+egg_toolbar_get_show_arrow (EggToolbar *toolbar)
+{
+ EggToolbarPrivate *priv;
+
+ g_return_val_if_fail (EGG_IS_TOOLBAR (toolbar), FALSE);
+
+ priv = EGG_TOOLBAR_GET_PRIVATE (toolbar);
+
+ return priv->show_arrow;
+}
+
+GtkWidget *
+egg_toolbar_append_item (EggToolbar *toolbar,
+ const char *text,
+ const char *tooltip_text,
+ const char *tooltip_private_text,
+ GtkWidget *icon,
+ GtkSignalFunc callback,
+ gpointer user_data)
+{
+ return egg_toolbar_insert_element (toolbar, EGG_TOOLBAR_CHILD_BUTTON,
+ NULL, text,
+ tooltip_text, tooltip_private_text,
+ icon, callback, user_data,
+ toolbar->num_children);
+}
+
+GtkWidget *
+egg_toolbar_prepend_item (EggToolbar *toolbar,
+ const char *text,
+ const char *tooltip_text,
+ const char *tooltip_private_text,
+ GtkWidget *icon,
+ GtkSignalFunc callback,
+ gpointer user_data)
+{
+ return egg_toolbar_insert_element (toolbar, EGG_TOOLBAR_CHILD_BUTTON,
+ NULL, text,
+ tooltip_text, tooltip_private_text,
+ icon, callback, user_data,
+ 0);
+}
+
+GtkWidget *
+egg_toolbar_insert_item (EggToolbar *toolbar,
+ const char *text,
+ const char *tooltip_text,
+ const char *tooltip_private_text,
+ GtkWidget *icon,
+ GtkSignalFunc callback,
+ gpointer user_data,
+ gint position)
+{
+ return egg_toolbar_insert_element (toolbar, EGG_TOOLBAR_CHILD_BUTTON,
+ NULL, text,
+ tooltip_text, tooltip_private_text,
+ icon, callback, user_data,
+ position);
+}
+
+GtkWidget*
+egg_toolbar_insert_stock (EggToolbar *toolbar,
+ const gchar *stock_id,
+ const char *tooltip_text,
+ const char *tooltip_private_text,
+ GtkSignalFunc callback,
+ gpointer user_data,
+ gint position)
+{
+ return egg_toolbar_internal_insert_element (toolbar, EGG_TOOLBAR_CHILD_BUTTON,
+ NULL, stock_id,
+ tooltip_text, tooltip_private_text,
+ NULL, callback, user_data,
+ position, TRUE);
+}
+
+void
+egg_toolbar_append_space (EggToolbar *toolbar)
+{
+ egg_toolbar_insert_element (toolbar, EGG_TOOLBAR_CHILD_SPACE,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, NULL, NULL,
+ toolbar->num_children);
+}
+
+void
+egg_toolbar_prepend_space (EggToolbar *toolbar)
+{
+ egg_toolbar_insert_element (toolbar, EGG_TOOLBAR_CHILD_SPACE,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, NULL, NULL,
+ 0);
+}
+
+void
+egg_toolbar_insert_space (EggToolbar *toolbar,
+ gint position)
+{
+ egg_toolbar_insert_element (toolbar, EGG_TOOLBAR_CHILD_SPACE,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, NULL, NULL,
+ position);
+}
+
+void
+egg_toolbar_append_widget (EggToolbar *toolbar,
+ GtkWidget *widget,
+ const gchar *tooltip_text,
+ const gchar *tooltip_private_text)
+{
+ egg_toolbar_insert_element (toolbar, EGG_TOOLBAR_CHILD_WIDGET,
+ widget, NULL,
+ tooltip_text, tooltip_private_text,
+ NULL, NULL, NULL,
+ toolbar->num_children);
+}
+
+void
+egg_toolbar_prepend_widget (EggToolbar *toolbar,
+ GtkWidget *widget,
+ const gchar *tooltip_text,
+ const gchar *tooltip_private_text)
+{
+ egg_toolbar_insert_element (toolbar, EGG_TOOLBAR_CHILD_WIDGET,
+ widget, NULL,
+ tooltip_text, tooltip_private_text,
+ NULL, NULL, NULL,
+ 0);
+}
+
+void
+egg_toolbar_insert_widget (EggToolbar *toolbar,
+ GtkWidget *widget,
+ const char *tooltip_text,
+ const char *tooltip_private_text,
+ gint position)
+{
+ egg_toolbar_insert_element (toolbar, EGG_TOOLBAR_CHILD_WIDGET,
+ widget, NULL,
+ tooltip_text, tooltip_private_text,
+ NULL, NULL, NULL,
+ position);
+}
+
+GtkWidget*
+egg_toolbar_append_element (EggToolbar *toolbar,
+ GtkToolbarChildType type,
+ GtkWidget *widget,
+ const char *text,
+ const char *tooltip_text,
+ const char *tooltip_private_text,
+ GtkWidget *icon,
+ GtkSignalFunc callback,
+ gpointer user_data)
+{
+ return egg_toolbar_insert_element (toolbar, type, widget, text,
+ tooltip_text, tooltip_private_text,
+ icon, callback, user_data,
+ toolbar->num_children);
+}
+
+GtkWidget *
+egg_toolbar_prepend_element (EggToolbar *toolbar,
+ GtkToolbarChildType type,
+ GtkWidget *widget,
+ const char *text,
+ const char *tooltip_text,
+ const char *tooltip_private_text,
+ GtkWidget *icon,
+ GtkSignalFunc callback,
+ gpointer user_data)
+{
+ return egg_toolbar_insert_element (toolbar, type, widget, text,
+ tooltip_text, tooltip_private_text,
+ icon, callback, user_data, 0);
+}
+
+GtkWidget *
+egg_toolbar_insert_element (EggToolbar *toolbar,
+ EggToolbarChildType type,
+ GtkWidget *widget,
+ const char *text,
+ const char *tooltip_text,
+ const char *tooltip_private_text,
+ GtkWidget *icon,
+ GtkSignalFunc callback,
+ gpointer user_data,
+ gint position)
+{
+ return egg_toolbar_internal_insert_element (toolbar, type, widget, text,
+ tooltip_text, tooltip_private_text,
+ icon, callback, user_data, position, FALSE);
+}
+
+static GtkWidget *
+egg_toolbar_internal_insert_element (EggToolbar *toolbar,
+ EggToolbarChildType type,
+ GtkWidget *widget,
+ const char *text,
+ const char *tooltip_text,
+ const char *tooltip_private_text,
+ GtkWidget *icon,
+ GtkSignalFunc callback,
+ gpointer user_data,
+ gint position,
+ gboolean use_stock)
+{
+ EggToolbarChild *child;
+ EggToolItem *item = NULL;
+
+ g_return_val_if_fail (EGG_IS_TOOLBAR (toolbar), NULL);
+
+ if (type == EGG_TOOLBAR_CHILD_WIDGET)
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+ else if (type != EGG_TOOLBAR_CHILD_RADIOBUTTON)
+ g_return_val_if_fail (widget == NULL, NULL);
+
+ child = g_new (EggToolbarChild, 1);
+
+ child->type = type;
+ child->icon = NULL;
+ child->label = NULL;
+
+ switch (type)
+ {
+ case EGG_TOOLBAR_CHILD_SPACE:
+ item = egg_separator_tool_item_new ();
+ child->widget = NULL;
+ break;
+
+ case EGG_TOOLBAR_CHILD_WIDGET:
+ item = egg_tool_item_new ();
+ child->widget = widget;
+ gtk_container_add (GTK_CONTAINER (item), child->widget);
+
+ break;
+
+ case EGG_TOOLBAR_CHILD_BUTTON:
+ item = egg_tool_button_new ();
+ child->widget = EGG_TOOL_BUTTON (item)->button;
+ break;
+
+ case EGG_TOOLBAR_CHILD_TOGGLEBUTTON:
+ item = egg_toggle_tool_button_new ();
+ child->widget = EGG_TOOL_BUTTON (item)->button;
+ break;
+
+ case EGG_TOOLBAR_CHILD_RADIOBUTTON:
+ item = egg_radio_tool_button_new (widget
+ ? gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget))
+ : NULL);
+ child->widget = EGG_TOOL_BUTTON (item)->button;
+ break;
+ }
+
+ /*
+ * We need to connect to the button's clicked callback because some
+ * programs may rely on that the widget in the callback is a GtkButton
+ */
+ if (callback)
+ g_signal_connect (child->widget, "clicked",
+ callback, user_data);
+
+ if (type == EGG_TOOLBAR_CHILD_BUTTON ||
+ type == EGG_TOOLBAR_CHILD_RADIOBUTTON ||
+ type == EGG_TOOLBAR_CHILD_TOGGLEBUTTON)
+ {
+ if (text)
+ {
+ child->label = EGG_TOOL_BUTTON (item)->label;
+
+ if (use_stock)
+ g_object_set (G_OBJECT (item), "stock_id", text, NULL);
+ else
+ egg_tool_button_set_label (EGG_TOOL_BUTTON (item), text);
+ }
+
+ if (icon)
+ {
+ child->icon = icon;
+ egg_tool_button_set_icon_widget (EGG_TOOL_BUTTON (item), icon);
+ }
+
+ }
+
+ if ((type != GTK_TOOLBAR_CHILD_SPACE) && tooltip_text)
+ egg_tool_item_set_tooltip (item, toolbar->tooltips,
+ tooltip_text, tooltip_private_text);
+
+ toolbar->children = g_list_insert (toolbar->children, child, position);
+ egg_toolbar_insert_tool_item (toolbar, item, position);
+
+ return child->widget;
+}
diff --git a/lib/egg/eggtoolbar.h b/lib/egg/eggtoolbar.h
new file mode 100644
index 000000000..5420b9dfa
--- /dev/null
+++ b/lib/egg/eggtoolbar.h
@@ -0,0 +1,242 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * GtkToolbar copyright (C) Federico Mena
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#ifndef __EGG_TOOLBAR_H__
+#define __EGG_TOOLBAR_H__
+
+#include <gdk/gdk.h>
+#include <gtk/gtkcontainer.h>
+#include <gtk/gtkenums.h>
+#include <gtk/gtktooltips.h>
+
+#include "eggtoolitem.h"
+
+/* Not needed, retained for compatibility -Yosh */
+#include <gtk/gtkpixmap.h>
+#include <gtk/gtksignal.h>
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_TOOLBAR (egg_toolbar_get_type ())
+#define EGG_TOOLBAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_TOOLBAR, EggToolbar))
+#define EGG_TOOLBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_TOOLBAR, EggToolbarClass))
+#define EGG_IS_TOOLBAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_TOOLBAR))
+#define EGG_IS_TOOLBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_TOOLBAR))
+#define EGG_TOOLBAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_TOOLBAR, EggToolbarClass))
+
+#ifndef EGG_DISABLE_DEPRECATED
+typedef enum
+{
+ EGG_TOOLBAR_CHILD_SPACE,
+ EGG_TOOLBAR_CHILD_BUTTON,
+ EGG_TOOLBAR_CHILD_TOGGLEBUTTON,
+ EGG_TOOLBAR_CHILD_RADIOBUTTON,
+ EGG_TOOLBAR_CHILD_WIDGET
+} EggToolbarChildType;
+
+typedef struct _EggToolbarChild EggToolbarChild;
+
+struct _EggToolbarChild
+{
+ EggToolbarChildType type;
+ GtkWidget *widget;
+ GtkWidget *icon;
+ GtkWidget *label;
+};
+
+#endif /* EGG_DISABLE_DEPRECATED */
+typedef struct _EggToolbar EggToolbar;
+typedef struct _EggToolbarClass EggToolbarClass;
+
+struct _EggToolbar
+{
+ GtkContainer container;
+
+ gint num_children;
+ GList *children;
+ GtkOrientation orientation;
+ GtkToolbarStyle style;
+ GtkIconSize icon_size;
+
+ GtkTooltips *tooltips;
+
+ gint button_maxw;
+ gint button_maxh;
+
+ guint style_set_connection;
+ guint icon_size_connection;
+
+ guint style_set : 1;
+ guint icon_size_set : 1;
+};
+
+struct _EggToolbarClass
+{
+ GtkContainerClass parent_class;
+
+ void (* orientation_changed) (EggToolbar *toolbar,
+ GtkOrientation orientation);
+ void (* style_changed) (EggToolbar *toolbar,
+ GtkToolbarStyle style);
+
+ /* Padding for future expansion */
+ void (*_gtk_reserved1) (void);
+ void (*_gtk_reserved2) (void);
+ void (*_gtk_reserved3) (void);
+ void (*_gtk_reserved4) (void);
+};
+
+GType egg_toolbar_get_type (void) G_GNUC_CONST;
+GtkWidget* egg_toolbar_new (void);
+
+void egg_toolbar_append_tool_item (EggToolbar *toolbar,
+ EggToolItem *item);
+void egg_toolbar_prepend_tool_item (EggToolbar *toolbar,
+ EggToolItem *item);
+void egg_toolbar_insert_tool_item (EggToolbar *toolbar,
+ EggToolItem *item,
+ gint pos);
+void egg_toolbar_remove_tool_item (EggToolbar *toolbar,
+ EggToolItem *item);
+
+/* Style functions */
+void egg_toolbar_set_show_arrow (EggToolbar *toolbar,
+ gboolean show_arrow);
+void egg_toolbar_set_orientation (EggToolbar *toolbar,
+ GtkOrientation orientation);
+void egg_toolbar_set_style (EggToolbar *toolbar,
+ GtkToolbarStyle style);
+void egg_toolbar_set_icon_size (EggToolbar *toolbar,
+ GtkIconSize icon_size);
+void egg_toolbar_set_tooltips (EggToolbar *toolbar,
+ gboolean enable);
+void egg_toolbar_unset_style (EggToolbar *toolbar);
+void egg_toolbar_unset_icon_size (EggToolbar *toolbar);
+gboolean egg_toolbar_get_show_arrow (EggToolbar *toolbar);
+GtkOrientation egg_toolbar_get_orientation (EggToolbar *toolbar);
+GtkToolbarStyle egg_toolbar_get_style (EggToolbar *toolbar);
+GtkIconSize egg_toolbar_get_icon_size (EggToolbar *toolbar);
+gboolean egg_toolbar_get_tooltips (EggToolbar *toolbar);
+GList* egg_toolbar_get_tool_items (EggToolbar *toolbar);
+
+
+
+#ifndef EGG_DISABLE_DEPRECATED
+/* Simple button items */
+GtkWidget* egg_toolbar_append_item (EggToolbar *toolbar,
+ const char *text,
+ const char *tooltip_text,
+ const char *tooltip_private_text,
+ GtkWidget *icon,
+ GtkSignalFunc callback,
+ gpointer user_data);
+GtkWidget* egg_toolbar_prepend_item (EggToolbar *toolbar,
+ const char *text,
+ const char *tooltip_text,
+ const char *tooltip_private_text,
+ GtkWidget *icon,
+ GtkSignalFunc callback,
+ gpointer user_data);
+GtkWidget* egg_toolbar_insert_item (EggToolbar *toolbar,
+ const char *text,
+ const char *tooltip_text,
+ const char *tooltip_private_text,
+ GtkWidget *icon,
+ GtkSignalFunc callback,
+ gpointer user_data,
+ gint position);
+
+/* Stock Items */
+GtkWidget* egg_toolbar_insert_stock (EggToolbar *toolbar,
+ const gchar *stock_id,
+ const char *tooltip_text,
+ const char *tooltip_private_text,
+ GtkSignalFunc callback,
+ gpointer user_data,
+ gint position);
+
+/* Space Items */
+void egg_toolbar_append_space (EggToolbar *toolbar);
+void egg_toolbar_prepend_space (EggToolbar *toolbar);
+void egg_toolbar_insert_space (EggToolbar *toolbar,
+ gint position);
+/* FIXME: Write this function */
+void egg_toolbar_remove_space (EggToolbar *toolbar,
+ gint position);
+/* Any element type */
+GtkWidget* egg_toolbar_append_element (EggToolbar *toolbar,
+ EggToolbarChildType type,
+ GtkWidget *widget,
+ const char *text,
+ const char *tooltip_text,
+ const char *tooltip_private_text,
+ GtkWidget *icon,
+ GtkSignalFunc callback,
+ gpointer user_data);
+
+GtkWidget* egg_toolbar_prepend_element (EggToolbar *toolbar,
+ EggToolbarChildType type,
+ GtkWidget *widget,
+ const char *text,
+ const char *tooltip_text,
+ const char *tooltip_private_text,
+ GtkWidget *icon,
+ GtkSignalFunc callback,
+ gpointer user_data);
+
+GtkWidget* egg_toolbar_insert_element (EggToolbar *toolbar,
+ EggToolbarChildType type,
+ GtkWidget *widget,
+ const char *text,
+ const char *tooltip_text,
+ const char *tooltip_private_text,
+ GtkWidget *icon,
+ GtkSignalFunc callback,
+ gpointer user_data,
+ gint position);
+
+/* Generic Widgets */
+void egg_toolbar_append_widget (EggToolbar *toolbar,
+ GtkWidget *widget,
+ const char *tooltip_text,
+ const char *tooltip_private_text);
+void egg_toolbar_prepend_widget (EggToolbar *toolbar,
+ GtkWidget *widget,
+ const char *tooltip_text,
+ const char *tooltip_private_text);
+void egg_toolbar_insert_widget (EggToolbar *toolbar,
+ GtkWidget *widget,
+ const char *tooltip_text,
+ const char *tooltip_private_text,
+ gint position);
+
+#endif /* EGG_DISABLE_DEPRECATED */
+
+
+G_END_DECLS
+
+#endif /* __EGG_TOOLBAR_H__ */
diff --git a/lib/egg/eggtoolbutton.c b/lib/egg/eggtoolbutton.c
new file mode 100644
index 000000000..7c6e8e865
--- /dev/null
+++ b/lib/egg/eggtoolbutton.c
@@ -0,0 +1,670 @@
+/* eggtoolbutton.c
+ *
+ * Copyright (C) 2002 Anders Carlsson <andersca@codefactory.se>
+ * Copyright (C) 2002 James Henstridge <james@daa.com.au>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "eggtoolbutton.h"
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkiconfactory.h>
+#include <gtk/gtkimage.h>
+#include <gtk/gtkimagemenuitem.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtkvbox.h>
+
+#include <string.h>
+
+#ifndef _
+# define _(s) (s)
+#endif
+
+enum {
+ PROP_0,
+ PROP_LABEL,
+ PROP_USE_UNDERLINE,
+ PROP_STOCK_ID,
+ PROP_ICON_SET,
+ PROP_ICON_WIDGET,
+};
+
+static void egg_tool_button_init (EggToolButton *button,
+ EggToolButtonClass *klass);
+static void egg_tool_button_class_init (EggToolButtonClass *klass);
+
+
+static void egg_tool_button_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void egg_tool_button_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void egg_tool_button_finalize (GObject *object);
+
+static void egg_tool_button_show_all (GtkWidget *widget);
+
+static GtkWidget *egg_tool_button_create_menu_proxy (EggToolItem *item);
+static void egg_tool_button_set_orientation (EggToolItem *tool_item,
+ GtkOrientation orientation);
+static void egg_tool_button_set_icon_size (EggToolItem *tool_item,
+ GtkIconSize icon_size);
+static void egg_tool_button_set_toolbar_style (EggToolItem *tool_item,
+ GtkToolbarStyle style);
+static void egg_tool_button_set_relief_style (EggToolItem *tool_item,
+ GtkReliefStyle style);
+static void egg_tool_button_set_tooltip (EggToolItem *tool_item,
+ GtkTooltips *tooltips,
+ const gchar *tip_text,
+ const gchar *tip_private);
+static void button_clicked (GtkWidget *widget,
+ EggToolButton *button);
+
+static GObjectClass *parent_class = NULL;
+
+GType
+egg_tool_button_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EggToolButtonClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) egg_tool_button_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+ sizeof (EggToolButton),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) egg_tool_button_init,
+ };
+
+ type = g_type_register_static (EGG_TYPE_TOOL_ITEM,
+ "EggToolButton",
+ &type_info, 0);
+ }
+ return type;
+}
+
+static void
+egg_tool_button_class_init (EggToolButtonClass *klass)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ EggToolItemClass *tool_item_class;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class = (GObjectClass *)klass;
+ widget_class = (GtkWidgetClass *)klass;
+ tool_item_class = (EggToolItemClass *)klass;
+
+ object_class->set_property = egg_tool_button_set_property;
+ object_class->get_property = egg_tool_button_get_property;
+ object_class->finalize = egg_tool_button_finalize;
+
+ widget_class->show_all = egg_tool_button_show_all;
+
+ tool_item_class->create_menu_proxy = egg_tool_button_create_menu_proxy;
+ tool_item_class->set_orientation = egg_tool_button_set_orientation;
+ tool_item_class->set_icon_size = egg_tool_button_set_icon_size;
+ tool_item_class->set_toolbar_style = egg_tool_button_set_toolbar_style;
+ tool_item_class->set_relief_style = egg_tool_button_set_relief_style;
+ tool_item_class->set_tooltip = egg_tool_button_set_tooltip;
+
+ klass->button_type = GTK_TYPE_BUTTON;
+
+ g_object_class_install_property (object_class,
+ PROP_LABEL,
+ g_param_spec_string ("label",
+ _("Label"),
+ _("Text to show in the item."),
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_USE_UNDERLINE,
+ g_param_spec_boolean ("use_underline",
+ _("Use underline"),
+ _("Interpret underlines in the item label."),
+ FALSE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_STOCK_ID,
+ g_param_spec_string ("stock_id",
+ _("Stock Id"),
+ _("The stock icon displayed on the item."),
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_ICON_SET,
+ g_param_spec_boxed ("icon_set",
+ _("Icon set"),
+ _("Icon set to use to draw the item's icon."),
+ GTK_TYPE_ICON_SET,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_ICON_WIDGET,
+ g_param_spec_object ("icon_widget",
+ _("Icon widget"),
+ _("Icon widget to display in the item."),
+ GTK_TYPE_WIDGET,
+ G_PARAM_READWRITE));
+}
+
+static void
+egg_tool_button_init (EggToolButton *button, EggToolButtonClass *klass)
+{
+ EggToolItem *toolitem = EGG_TOOL_ITEM (button);
+
+ toolitem->homogeneous = TRUE;
+
+ /* create button */
+ button->button = g_object_new (klass->button_type, NULL);
+ GTK_WIDGET_UNSET_FLAGS (button->button, GTK_CAN_FOCUS);
+ g_signal_connect_object (button->button, "clicked",
+ G_CALLBACK (button_clicked), button, 0);
+
+ button->box = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (button->button), button->box);
+ gtk_widget_show (button->box);
+
+#if 0
+ button->icon = gtk_image_new();
+ gtk_box_pack_start (GTK_BOX (button->box), button->icon, TRUE, TRUE, 0);
+ gtk_widget_show (button->icon);
+#endif
+
+ button->label = gtk_label_new (NULL);
+ gtk_label_set_use_underline (GTK_LABEL (button->label), TRUE);
+ gtk_box_pack_start (GTK_BOX (button->box), button->label, FALSE, TRUE, 0);
+ gtk_widget_show (button->label);
+
+ gtk_container_add (GTK_CONTAINER (button), button->button);
+ gtk_widget_show (button->button);
+}
+
+static gchar *
+elide_underscores (const gchar *original)
+{
+ gchar *q, *result;
+ const gchar *p;
+ gboolean last_underscore;
+
+ q = result = g_malloc (strlen (original) + 1);
+ last_underscore = FALSE;
+
+ for (p = original; *p; p++)
+ {
+ if (!last_underscore && *p == '_')
+ last_underscore = TRUE;
+ else
+ {
+ last_underscore = FALSE;
+ *q++ = *p;
+ }
+ }
+
+ *q = '\0';
+
+ return result;
+}
+
+static void
+egg_tool_button_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EggToolButton *button = EGG_TOOL_BUTTON (object);
+ GtkStockItem stock_item;
+ GtkIconSet *icon_set;
+ gchar *label_no_mnemonic = NULL;
+
+ switch (prop_id)
+ {
+ case PROP_LABEL:
+ egg_tool_button_set_label (button, g_value_get_string (value));
+ break;
+ case PROP_USE_UNDERLINE:
+ gtk_label_set_use_underline (GTK_LABEL (button->label),
+ g_value_get_boolean (value));
+ break;
+ case PROP_STOCK_ID:
+ g_free (button->stock_id);
+ button->stock_id = g_value_dup_string (value);
+ if (!button->label_set)
+ {
+ if (gtk_stock_lookup (button->stock_id, &stock_item))
+ {
+ label_no_mnemonic = elide_underscores (stock_item.label);
+ gtk_label_set_label (GTK_LABEL (button->label), label_no_mnemonic);
+ g_free (label_no_mnemonic);
+ }
+ }
+ if (!button->icon_set)
+ {
+ if (button->icon && !GTK_IS_IMAGE (button->icon))
+ {
+ gtk_container_remove (GTK_CONTAINER (button->box), button->icon);
+ button->icon = NULL;
+ }
+ if (!button->icon)
+ {
+ button->icon = gtk_image_new ();
+ gtk_box_pack_start (GTK_BOX (button->box), button->icon,
+ TRUE, TRUE, 0);
+ gtk_box_reorder_child (GTK_BOX (button->box), button->icon, 0);
+ }
+ gtk_image_set_from_stock (GTK_IMAGE (button->icon), button->stock_id,
+ EGG_TOOL_ITEM (button)->icon_size);
+ }
+ break;
+ case PROP_ICON_SET:
+ if (button->icon && !GTK_IS_IMAGE (button->icon))
+ {
+ gtk_container_remove (GTK_CONTAINER (button->box), button->icon);
+ button->icon = NULL;
+ }
+ if (!button->icon)
+ {
+ button->icon = gtk_image_new ();
+ gtk_box_pack_start (GTK_BOX (button->box), button->icon,
+ TRUE, TRUE, 0);
+ gtk_box_reorder_child (GTK_BOX (button->box), button->icon, 0);
+ }
+ icon_set = g_value_get_boxed (value);
+ button->icon_set = (icon_set != NULL);
+ if (!button->icon_set && button->stock_id)
+ gtk_image_set_from_stock (GTK_IMAGE (button->icon), button->stock_id,
+ EGG_TOOL_ITEM (button)->icon_size);
+ else
+ gtk_image_set_from_icon_set (GTK_IMAGE (button->icon), icon_set,
+ EGG_TOOL_ITEM (button)->icon_size);
+ break;
+ case PROP_ICON_WIDGET:
+ egg_tool_button_set_icon_widget (button, g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+egg_tool_button_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EggToolButton *button = EGG_TOOL_BUTTON (object);
+
+ switch (prop_id)
+ {
+ case PROP_LABEL:
+ if (button->label_set)
+ g_value_set_string (value,
+ gtk_label_get_label (GTK_LABEL (button->label)));
+ break;
+ case PROP_USE_UNDERLINE:
+ g_value_set_boolean (value,
+ gtk_label_get_use_underline (GTK_LABEL (button->label)));
+ break;
+ case PROP_STOCK_ID:
+ g_value_set_string (value, button->stock_id);
+ break;
+ case PROP_ICON_SET:
+ if (GTK_IS_IMAGE (button->icon) &&
+ GTK_IMAGE (button->icon)->storage_type == GTK_IMAGE_ICON_SET)
+ {
+ GtkIconSet *icon_set;
+ gtk_image_get_icon_set (GTK_IMAGE (button->icon), &icon_set, NULL);
+ g_value_set_boxed (value, icon_set);
+ }
+ else
+ g_value_set_boxed (value, NULL);
+ break;
+ case PROP_ICON_WIDGET:
+ g_value_set_object (value, button->icon);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+egg_tool_button_finalize (GObject *object)
+{
+ EggToolButton *button = EGG_TOOL_BUTTON (object);
+
+ g_free (button->stock_id);
+ button->stock_id = NULL;
+
+ parent_class->finalize (object);
+}
+
+static void
+egg_tool_button_show_all (GtkWidget *widget)
+{
+ EggToolButton *button = EGG_TOOL_BUTTON (widget);
+
+ switch (EGG_TOOL_ITEM (widget)->style)
+ {
+ case GTK_TOOLBAR_ICONS:
+ if (button->icon) gtk_widget_show_all (button->icon);
+ gtk_widget_hide (button->label);
+ gtk_widget_show (button->box);
+ gtk_widget_show (button->button);
+ break;
+ case GTK_TOOLBAR_TEXT:
+ if (button->icon) gtk_widget_hide (button->icon);
+ gtk_widget_show_all (button->label);
+ gtk_widget_show (button->box);
+ gtk_widget_show (button->button);
+ break;
+ case GTK_TOOLBAR_BOTH:
+ case GTK_TOOLBAR_BOTH_HORIZ:
+ gtk_widget_show_all (button->button);
+ }
+
+ gtk_widget_show (GTK_WIDGET (button));
+}
+
+static GtkWidget *
+egg_tool_button_create_menu_proxy (EggToolItem *item)
+{
+ EggToolButton *button = EGG_TOOL_BUTTON (item);
+ GtkWidget *menu_item;
+ GtkWidget *image;
+ const char *label;
+
+ label = gtk_label_get_text (GTK_LABEL (button->label));
+
+ menu_item = gtk_image_menu_item_new_with_label (label);
+
+ if (GTK_IS_IMAGE (button->icon))
+ {
+ image = gtk_image_new ();
+
+ if (GTK_IMAGE (button->icon)->storage_type == GTK_IMAGE_STOCK)
+ {
+ gchar *stock_id;
+
+ gtk_image_get_stock (GTK_IMAGE (button->icon),
+ &stock_id, NULL);
+ gtk_image_set_from_stock (GTK_IMAGE (image), stock_id,
+ GTK_ICON_SIZE_MENU);
+ }
+ else if (GTK_IMAGE (button->icon)->storage_type == GTK_IMAGE_ICON_SET)
+ {
+ GtkIconSet *icon_set;
+
+ gtk_image_get_icon_set (GTK_IMAGE (button->icon), &icon_set, NULL);
+ gtk_image_set_from_icon_set (GTK_IMAGE (image), icon_set,
+ GTK_ICON_SIZE_MENU);
+ }
+ else
+ {
+ g_warning ("FIXME: Add more cases here");
+ }
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), image);
+ }
+
+ g_signal_connect_object (menu_item, "activate",
+ G_CALLBACK (gtk_button_clicked),
+ EGG_TOOL_BUTTON (button)->button,
+ G_CONNECT_SWAPPED);
+
+ return menu_item;
+}
+
+static void
+egg_tool_button_set_orientation (EggToolItem *tool_item,
+ GtkOrientation orientation)
+{
+ if (tool_item->orientation != orientation)
+ {
+ tool_item->orientation = orientation;
+ }
+}
+
+static void
+egg_tool_button_set_icon_size (EggToolItem *tool_item,
+ GtkIconSize icon_size)
+{
+ if (tool_item->icon_size != icon_size)
+ {
+ EggToolButton *button = EGG_TOOL_BUTTON (tool_item);
+ char *stock_id;
+
+ if (button->icon && GTK_IS_IMAGE (button->icon) &&
+ gtk_image_get_storage_type (GTK_IMAGE (button->icon)) == GTK_IMAGE_STOCK)
+ {
+ gtk_image_get_stock (GTK_IMAGE (button->icon), &stock_id, NULL);
+ stock_id = g_strdup (stock_id);
+ gtk_image_set_from_stock (GTK_IMAGE (button->icon),
+ stock_id,
+ icon_size);
+ g_free (stock_id);
+ }
+ tool_item->icon_size = icon_size;
+ }
+}
+
+static void
+egg_tool_button_set_toolbar_style (EggToolItem *tool_item,
+ GtkToolbarStyle style)
+{
+ EggToolButton *button = EGG_TOOL_BUTTON (tool_item);
+
+ if (tool_item->style != style)
+ {
+ tool_item->style = style;
+
+ switch (tool_item->style)
+ {
+ case GTK_TOOLBAR_ICONS:
+ gtk_widget_hide (button->label);
+ if (button->icon) {
+ gtk_box_set_child_packing (GTK_BOX (button->box), button->icon,
+ TRUE, TRUE, 0, GTK_PACK_START);
+ gtk_widget_show (button->icon);
+ }
+ break;
+ case GTK_TOOLBAR_TEXT:
+ gtk_box_set_child_packing (GTK_BOX (button->box), button->label,
+ TRUE, TRUE, 0, GTK_PACK_START);
+ gtk_widget_show (button->label);
+ if (button->icon)
+ gtk_widget_hide (button->icon);
+ break;
+ case GTK_TOOLBAR_BOTH:
+ if (GTK_IS_HBOX (button->box))
+ {
+ GtkWidget *vbox;
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (vbox);
+
+ if (button->icon)
+ {
+ g_object_ref (button->icon);
+ gtk_container_remove (GTK_CONTAINER (button->box), button->icon);
+ gtk_box_pack_start (GTK_BOX (vbox), button->icon,
+ TRUE, TRUE, 0);
+ g_object_unref (button->icon);
+ }
+
+ g_object_ref (button->label);
+ gtk_container_remove (GTK_CONTAINER (button->box), button->label);
+ gtk_box_pack_start (GTK_BOX (vbox), button->label, FALSE, TRUE, 0);
+ g_object_unref (button->label);
+
+ gtk_container_remove (GTK_CONTAINER (button->button), button->box);
+ button->box = vbox;
+ gtk_container_add (GTK_CONTAINER (button->button), button->box);
+ }
+
+ gtk_box_set_child_packing (GTK_BOX (button->box), button->label,
+ FALSE, TRUE, 0, GTK_PACK_START);
+ gtk_widget_show (button->label);
+ if (button->icon) {
+ gtk_box_set_child_packing (GTK_BOX (button->box), button->icon,
+ TRUE, TRUE, 0, GTK_PACK_START);
+ gtk_widget_show (button->icon);
+ }
+ break;
+ case GTK_TOOLBAR_BOTH_HORIZ:
+ if (GTK_IS_VBOX (button->box))
+ {
+ GtkWidget *hbox;
+
+ hbox = gtk_hbox_new (FALSE, 0);
+ gtk_widget_show (hbox);
+
+ if (button->icon)
+ {
+ g_object_ref (button->icon);
+ gtk_container_remove (GTK_CONTAINER (button->box), button->icon);
+ gtk_box_pack_start (GTK_BOX (hbox), button->icon,
+ TRUE, TRUE, 0);
+ g_object_unref (button->icon);
+ }
+
+ g_object_ref (button->label);
+ gtk_container_remove (GTK_CONTAINER (button->box), button->label);
+ gtk_box_pack_start (GTK_BOX (hbox), button->label, FALSE, TRUE, 0);
+ g_object_unref (button->label);
+
+ gtk_container_remove (GTK_CONTAINER (button->button), button->box);
+ button->box = hbox;
+ gtk_container_add (GTK_CONTAINER (button->button), button->box);
+ }
+
+ gtk_box_set_child_packing (GTK_BOX (button->box), button->label,
+ TRUE, TRUE, 0, GTK_PACK_START);
+ gtk_widget_show (button->label);
+ if (button->icon) {
+ gtk_box_set_child_packing (GTK_BOX (button->box), button->icon,
+ FALSE, TRUE, 0, GTK_PACK_START);
+ gtk_widget_show (button->icon);
+ }
+ break;
+ }
+ }
+}
+
+static void
+egg_tool_button_set_relief_style (EggToolItem *tool_item,
+ GtkReliefStyle style)
+{
+ gtk_button_set_relief (GTK_BUTTON (EGG_TOOL_BUTTON (tool_item)->button), style);
+}
+
+static void
+egg_tool_button_set_tooltip (EggToolItem *tool_item,
+ GtkTooltips *tooltips,
+ const gchar *tip_text,
+ const gchar *tip_private)
+{
+ gtk_tooltips_set_tip (tooltips, EGG_TOOL_BUTTON (tool_item)->button,
+ tip_text, tip_private);
+}
+
+static void
+button_clicked (GtkWidget *widget, EggToolButton *button)
+{
+ g_signal_emit_by_name (button, "clicked");
+}
+
+EggToolItem *
+egg_tool_button_new_from_stock (const gchar *stock_id)
+{
+ EggToolButton *button;
+
+ button = g_object_new (EGG_TYPE_TOOL_BUTTON,
+ "stock_id", stock_id,
+ "use_underline", TRUE,
+ NULL);
+
+ return EGG_TOOL_ITEM (button);
+}
+
+EggToolItem *
+egg_tool_button_new (void)
+{
+ EggToolButton *button;
+
+ button = g_object_new (EGG_TYPE_TOOL_BUTTON,
+ NULL);
+
+ return EGG_TOOL_ITEM (button);
+}
+
+void
+egg_tool_button_set_icon_widget (EggToolButton *button,
+ GtkWidget *icon)
+{
+ g_return_if_fail (EGG_IS_TOOL_BUTTON (button));
+ g_return_if_fail (GTK_IS_WIDGET (icon));
+
+ if (button->icon)
+ gtk_container_remove (GTK_CONTAINER (button->box), button->icon);
+ button->icon = NULL;
+
+ button->icon_set = (icon != NULL);
+ if (icon)
+ {
+ button->icon = icon;
+ gtk_box_pack_start (GTK_BOX (button->box), button->icon,
+ TRUE, TRUE, 0);
+ gtk_box_reorder_child (GTK_BOX (button->box), button->icon, 0);
+ }
+ else if (button->stock_id)
+ {
+ button->icon = gtk_image_new_from_stock (button->stock_id,
+ EGG_TOOL_ITEM (button)->icon_size);
+ gtk_box_pack_start (GTK_BOX (button->box), button->icon,
+ TRUE, TRUE, 0);
+ }
+}
+
+void
+egg_tool_button_set_label (EggToolButton *button,
+ const gchar *label)
+{
+ gchar *label_no_mnemonic = NULL;
+ GtkStockItem stock_item;
+
+ g_return_if_fail (EGG_IS_TOOL_BUTTON (button));
+ g_return_if_fail (label != NULL);
+
+ button->label_set = (label != NULL);
+
+ if (label)
+ label_no_mnemonic = elide_underscores (label);
+ else if (button->stock_id && gtk_stock_lookup (button->stock_id, &stock_item))
+ label_no_mnemonic = elide_underscores (stock_item.label);
+
+ gtk_label_set_label (GTK_LABEL (button->label), label_no_mnemonic);
+ g_free (label_no_mnemonic);
+}
+
diff --git a/lib/egg/eggtoolbutton.h b/lib/egg/eggtoolbutton.h
new file mode 100644
index 000000000..cb0c0b15e
--- /dev/null
+++ b/lib/egg/eggtoolbutton.h
@@ -0,0 +1,74 @@
+/* eggtoolbutton.h
+ *
+ * Copyright (C) 2002 Anders Carlsson <andersca@codefactory.se>
+ * Copyright (C) 2002 James Henstridge <james@daa.com.au>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_TOOL_BUTTON_H__
+#define __EGG_TOOL_BUTTON_H__
+
+#include "eggtoolitem.h"
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_TOOL_BUTTON (egg_tool_button_get_type ())
+#define EGG_TOOL_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_TOOL_BUTTON, EggToolButton))
+#define EGG_TOOL_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_TOOL_BUTTON, EggToolButtonClass))
+#define EGG_IS_TOOL_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_TOOL_BUTTON))
+#define EGG_IS_TOOL_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EGG_TYPE_TOOL_BUTTON))
+#define EGG_TOOL_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_TOOL_BUTTON, EggToolButtonClass))
+
+typedef struct _EggToolButton EggToolButton;
+typedef struct _EggToolButtonClass EggToolButtonClass;
+
+struct _EggToolButton
+{
+ EggToolItem parent;
+
+ /*< private >*/
+ GtkWidget *button;
+ GtkWidget *box;
+ GtkWidget *label;
+ GtkWidget *icon;
+
+ gchar *stock_id;
+ guint label_set : 1;
+ guint icon_set : 1;
+};
+
+struct _EggToolButtonClass
+{
+ EggToolItemClass parent_class;
+
+ GType button_type;
+};
+
+GType egg_tool_button_get_type (void);
+EggToolItem *egg_tool_button_new (void);
+EggToolItem *egg_tool_button_new_from_stock (const gchar *stock_id);
+
+
+void egg_tool_button_set_icon_widget (EggToolButton *button,
+ GtkWidget *icon);
+void egg_tool_button_set_label (EggToolButton *button,
+ const gchar *label);
+
+
+G_END_DECLS
+
+#endif /* __EGG_TOOL_BUTTON_H__ */
diff --git a/lib/egg/eggtoolitem.c b/lib/egg/eggtoolitem.c
new file mode 100644
index 000000000..0bb234286
--- /dev/null
+++ b/lib/egg/eggtoolitem.c
@@ -0,0 +1,416 @@
+/* eggtoolitem.c
+ *
+ * Copyright (C) 2002 Anders Carlsson <andersca@codefactory.se>
+ * Copyright (C) 2002 James Henstridge <james@daa.com.au>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "eggtoolitem.h"
+#include "eggmarshalers.h"
+
+#ifndef _
+# define _(s) (s)
+#endif
+
+enum {
+ CLICKED,
+ CREATE_MENU_PROXY,
+ SET_ORIENTATION,
+ SET_ICON_SIZE,
+ SET_TOOLBAR_STYLE,
+ SET_RELIEF_STYLE,
+ SET_TOOLTIP,
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+ PROP_VISIBLE_HORIZONTAL,
+ PROP_VISIBLE_VERTICAL,
+ PROP_HOMOGENEOUS,
+ PROP_ORIENTATION
+};
+
+static void egg_tool_item_init (EggToolItem *toolitem);
+static void egg_tool_item_class_init (EggToolItemClass *class);
+
+static void egg_tool_item_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void egg_tool_item_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static void egg_tool_item_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void egg_tool_item_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+
+static GtkWidget *egg_tool_item_create_menu_proxy (EggToolItem *item);
+
+
+static GObjectClass *parent_class = NULL;
+static guint toolitem_signals[LAST_SIGNAL] = { 0 };
+
+GType
+egg_tool_item_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EggToolItemClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) egg_tool_item_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+
+ sizeof (EggToolItem),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) egg_tool_item_init,
+ };
+
+ type = g_type_register_static (GTK_TYPE_BIN,
+ "EggToolItem",
+ &type_info, 0);
+ }
+ return type;
+}
+
+static gboolean
+create_proxy_accumulator (GSignalInvocationHint *hint,
+ GValue *return_accumulator,
+ const GValue *handler_return,
+ gpointer user_data)
+{
+ GObject *proxy;
+ gboolean continue_emission;
+
+ proxy = g_value_get_object(handler_return);
+ g_value_set_object(return_accumulator, proxy);
+ continue_emission = (proxy == NULL);
+
+ return continue_emission;
+}
+
+static void
+egg_tool_item_class_init (EggToolItemClass *klass)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ parent_class = g_type_class_peek_parent (klass);
+ object_class = (GObjectClass *)klass;
+ widget_class = (GtkWidgetClass *)klass;
+
+ object_class->set_property = egg_tool_item_set_property;
+ object_class->get_property = egg_tool_item_get_property;
+
+ widget_class->size_request = egg_tool_item_size_request;
+ widget_class->size_allocate = egg_tool_item_size_allocate;
+
+ klass->create_menu_proxy = egg_tool_item_create_menu_proxy;
+
+ g_object_class_install_property (object_class,
+ PROP_VISIBLE_HORIZONTAL,
+ g_param_spec_boolean ("visible_horizontal",
+ _("Visible when horizontal"),
+ _("Whether the toolbar item is visible when the toolbar is in a horizontal orientation."),
+ TRUE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_VISIBLE_VERTICAL,
+ g_param_spec_boolean ("visible_vertical",
+ _("Visible when vertical"),
+ _("Whether the toolbar item is visible when the toolbar is in a vertical orientation."),
+ TRUE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_HOMOGENEOUS,
+ g_param_spec_boolean ("homogeneous",
+ _("Homogeneous size"),
+ _("Whether the toolbar item should be the same size as other homogeneous items."),
+ FALSE,
+ G_PARAM_READWRITE));
+
+ toolitem_signals[CLICKED] =
+ g_signal_new ("clicked",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EggToolItemClass, clicked),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ toolitem_signals[CREATE_MENU_PROXY] =
+ g_signal_new ("create_menu_proxy",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggToolItemClass, create_menu_proxy),
+ create_proxy_accumulator, NULL,
+ _egg_marshal_OBJECT__VOID,
+ GTK_TYPE_WIDGET, 0);
+ toolitem_signals[SET_ORIENTATION] =
+ g_signal_new ("set_orientation",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggToolItemClass, set_orientation),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__ENUM,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_ORIENTATION);
+ toolitem_signals[SET_ICON_SIZE] =
+ g_signal_new ("set_icon_size",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggToolItemClass, set_icon_size),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__ENUM,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_ICON_SIZE);
+ toolitem_signals[SET_TOOLBAR_STYLE] =
+ g_signal_new ("set_toolbar_style",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggToolItemClass, set_toolbar_style),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__ENUM,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_TOOLBAR_STYLE);
+ toolitem_signals[SET_RELIEF_STYLE] =
+ g_signal_new ("set_relief_style",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggToolItemClass, set_relief_style),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__ENUM,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_RELIEF_STYLE);
+ toolitem_signals[SET_TOOLTIP] =
+ g_signal_new ("set_tooltip",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggToolItemClass, set_tooltip),
+ NULL, NULL,
+ _egg_marshal_VOID__OBJECT_STRING_STRING,
+ G_TYPE_NONE, 3,
+ GTK_TYPE_TOOLTIPS,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+
+}
+
+static void
+egg_tool_item_init (EggToolItem *toolitem)
+{
+ toolitem->visible_horizontal = TRUE;
+ toolitem->visible_vertical = TRUE;
+ toolitem->homogeneous = FALSE;
+
+ toolitem->orientation = GTK_ORIENTATION_HORIZONTAL;
+ toolitem->icon_size = GTK_ICON_SIZE_LARGE_TOOLBAR;
+ toolitem->style = GTK_TOOLBAR_BOTH;
+}
+
+static void
+egg_tool_item_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EggToolItem *toolitem = EGG_TOOL_ITEM (object);
+
+ switch (prop_id)
+ {
+ case PROP_VISIBLE_HORIZONTAL:
+ toolitem->visible_horizontal = g_value_get_boolean (value);
+ break;
+ case PROP_VISIBLE_VERTICAL:
+ toolitem->visible_vertical = g_value_get_boolean (value);
+ break;
+ case PROP_HOMOGENEOUS:
+ toolitem->homogeneous = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+egg_tool_item_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EggToolItem *toolitem = EGG_TOOL_ITEM (object);
+
+ switch (prop_id)
+ {
+ case PROP_VISIBLE_HORIZONTAL:
+ g_value_set_boolean (value, toolitem->visible_horizontal);
+ break;
+ case PROP_VISIBLE_VERTICAL:
+ g_value_set_boolean (value, toolitem->visible_vertical);
+ break;
+ case PROP_HOMOGENEOUS:
+ g_value_set_boolean (value, toolitem->homogeneous);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+egg_tool_item_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkBin *bin = GTK_BIN (widget);
+
+ if (bin->child)
+ gtk_widget_size_request (bin->child, requisition);
+
+ requisition->width += GTK_CONTAINER (widget)->border_width * 2;
+ requisition->height += GTK_CONTAINER (widget)->border_width * 2;
+}
+
+static void
+egg_tool_item_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkBin *bin = GTK_BIN (widget);
+ GtkAllocation child_allocation;
+
+ widget->allocation = *allocation;
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
+ {
+ child_allocation.x = allocation->x + GTK_CONTAINER (widget)->border_width;
+ child_allocation.y = allocation->y + GTK_CONTAINER (widget)->border_width;
+ child_allocation.width = allocation->width - GTK_CONTAINER (widget)->border_width * 2;
+ child_allocation.height = allocation->height - GTK_CONTAINER (widget)->border_width * 2;
+
+ gtk_widget_size_allocate (bin->child, &child_allocation);
+ }
+}
+
+static GtkWidget *
+egg_tool_item_create_menu_proxy (EggToolItem *item)
+{
+ if (GTK_BIN (item)->child)
+ return NULL;
+ else
+ return gtk_separator_menu_item_new ();
+}
+
+EggToolItem *
+egg_tool_item_new (void)
+{
+ EggToolItem *item;
+
+ item = g_object_new (EGG_TYPE_TOOL_ITEM, NULL);
+
+ return item;
+}
+
+void
+egg_tool_item_set_orientation (EggToolItem *tool_item,
+ GtkOrientation orientation)
+{
+ g_return_if_fail (EGG_IS_TOOL_ITEM (tool_item));
+
+ g_signal_emit (tool_item, toolitem_signals[SET_ORIENTATION], 0, orientation);
+}
+
+void
+egg_tool_item_set_icon_size (EggToolItem *tool_item,
+ GtkIconSize icon_size)
+{
+ g_return_if_fail (EGG_IS_TOOL_ITEM (tool_item));
+
+ g_signal_emit (tool_item, toolitem_signals[SET_ICON_SIZE], 0, icon_size);
+}
+
+void
+egg_tool_item_set_toolbar_style (EggToolItem *tool_item,
+ GtkToolbarStyle style)
+{
+ g_return_if_fail (EGG_IS_TOOL_ITEM (tool_item));
+
+ g_signal_emit (tool_item, toolitem_signals[SET_TOOLBAR_STYLE], 0, style);
+}
+
+void
+egg_tool_item_set_relief_style (EggToolItem *tool_item,
+ GtkReliefStyle style)
+{
+ g_return_if_fail (EGG_IS_TOOL_ITEM (tool_item));
+
+ g_signal_emit (tool_item, toolitem_signals[SET_RELIEF_STYLE], 0, style);
+}
+
+void
+egg_tool_item_set_expandable (EggToolItem *tool_item,
+ gboolean expandable)
+{
+ if ((expandable && tool_item->expandable) ||
+ (!expandable && !tool_item->expandable))
+ return;
+
+ tool_item->expandable = expandable;
+ gtk_widget_queue_resize (GTK_WIDGET (tool_item));
+}
+
+void
+egg_tool_item_set_pack_end (EggToolItem *tool_item,
+ gboolean pack_end)
+{
+ if ((pack_end && tool_item->pack_end) ||
+ (!pack_end && !tool_item->pack_end))
+ return;
+
+ tool_item->pack_end = pack_end;
+ gtk_widget_queue_resize (GTK_WIDGET (tool_item));
+}
+
+void
+egg_tool_item_set_homogeneous (EggToolItem *tool_item,
+ gboolean homogeneous)
+{
+ if ((homogeneous && tool_item->homogeneous) ||
+ (!homogeneous && !tool_item->homogeneous))
+ return;
+
+ tool_item->homogeneous = homogeneous;
+ gtk_widget_queue_resize (GTK_WIDGET (tool_item));
+}
+
+void
+egg_tool_item_set_tooltip (EggToolItem *tool_item,
+ GtkTooltips *tooltips,
+ const gchar *tip_text,
+ const gchar *tip_private)
+{
+ g_return_if_fail (EGG_IS_TOOL_ITEM (tool_item));
+
+ g_signal_emit (tool_item, toolitem_signals[SET_TOOLTIP], 0,
+ tooltips, tip_text, tip_private);
+}
diff --git a/lib/egg/eggtoolitem.h b/lib/egg/eggtoolitem.h
new file mode 100644
index 000000000..222e095f9
--- /dev/null
+++ b/lib/egg/eggtoolitem.h
@@ -0,0 +1,98 @@
+/* eggtoolitem.c
+ *
+ * Copyright (C) 2002 Anders Carlsson <andersca@codefactory.se>
+ * Copyright (C) 2002 James Henstridge <james@daa.com.au>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_TOOL_ITEM_H__
+#define __EGG_TOOL_ITEM_H__
+
+#include <gtk/gtkbin.h>
+#include <gtk/gtktooltips.h>
+
+#define EGG_TYPE_TOOL_ITEM (egg_tool_item_get_type ())
+#define EGG_TOOL_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_TOOL_ITEM, EggToolItem))
+#define EGG_TOOL_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_TOOL_ITEM, EggToolItemClass))
+#define EGG_IS_TOOL_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_TOOL_ITEM))
+#define EGG_IS_TOOL_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EGG_TYPE_TOOL_ITEM))
+#define EGG_TOOL_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_TOOL_ITEM, EggToolItemClass))
+
+typedef struct _EggToolItem EggToolItem;
+typedef struct _EggToolItemClass EggToolItemClass;
+
+struct _EggToolItem
+{
+ GtkBin parent;
+
+ GtkOrientation orientation;
+ GtkIconSize icon_size;
+ GtkToolbarStyle style;
+
+ gchar *tip_text;
+ gchar *tip_private;
+
+ guint visible_horizontal : 1;
+ guint visible_vertical : 1;
+ guint homogeneous : 1;
+ guint expandable : 1;
+ guint pack_end : 1;
+};
+
+struct _EggToolItemClass
+{
+ GtkBinClass parent_class;
+
+ void (* clicked) (EggToolItem *tool_item);
+ GtkWidget *(* create_menu_proxy) (EggToolItem *tool_item);
+ void (* set_orientation) (EggToolItem *tool_item,
+ GtkOrientation orientation);
+ void (* set_icon_size) (EggToolItem *tool_item,
+ GtkIconSize icon_size);
+ void (* set_toolbar_style) (EggToolItem *tool_item,
+ GtkToolbarStyle style);
+ void (* set_relief_style) (EggToolItem *tool_item,
+ GtkReliefStyle relief_style);
+ void (* set_tooltip) (EggToolItem *tool_item,
+ GtkTooltips *tooltips,
+ const gchar *tip_text,
+ const gchar *tip_private);
+};
+
+GType egg_tool_item_get_type (void);
+EggToolItem *egg_tool_item_new (void);
+
+void egg_tool_item_set_orientation (EggToolItem *tool_item,
+ GtkOrientation orientation);
+void egg_tool_item_set_icon_size (EggToolItem *tool_item,
+ GtkIconSize icon_size);
+void egg_tool_item_set_toolbar_style (EggToolItem *tool_item,
+ GtkToolbarStyle style);
+void egg_tool_item_set_relief_style (EggToolItem *tool_item,
+ GtkReliefStyle style);
+void egg_tool_item_set_homogeneous (EggToolItem *tool_item,
+ gboolean homogeneous);
+void egg_tool_item_set_expandable (EggToolItem *tool_item,
+ gboolean expandable);
+void egg_tool_item_set_pack_end (EggToolItem *tool_item,
+ gboolean pack_end);
+void egg_tool_item_set_tooltip (EggToolItem *tool_item,
+ GtkTooltips *tooltips,
+ const gchar *tip_text,
+ const gchar *tip_private);
+
+#endif /* __EGG_TOOL_ITEM_H__ */
diff --git a/lib/egg/prop-editor.h b/lib/egg/prop-editor.h
new file mode 100644
index 000000000..1f86d9be1
--- /dev/null
+++ b/lib/egg/prop-editor.h
@@ -0,0 +1,31 @@
+/* prop-editor.h
+ * Copyright (C) 2000 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <gtk/gtkwidget.h>
+
+#ifndef __PROP_EDITOR_H__
+#define __PROP_EDITOR_H__
+
+G_BEGIN_DECLS
+
+GtkWidget *create_prop_editor (GObject *object,
+ GType type);
+
+G_END_DECLS
+
+#endif /* __PROP_EDITOR_H__ */
diff --git a/lib/ephy-gui.c b/lib/ephy-gui.c
index fe4018d38..90d282b3d 100644
--- a/lib/ephy-gui.c
+++ b/lib/ephy-gui.c
@@ -39,13 +39,12 @@ ephy_gui_menu_position_under_widget (GtkMenu *menu,
gpointer user_data)
{
GtkWidget *w = GTK_WIDGET (user_data);
- gint width, height;
gint screen_width, screen_height;
GtkRequisition requisition;
- gdk_drawable_get_size (w->window, &width, &height);
gdk_window_get_origin (w->window, x, y);
- *y = *y + height;
+ *x += w->allocation.x;
+ *y += w->allocation.y + w->allocation.height;
gtk_widget_size_request (GTK_WIDGET (menu), &requisition);
@@ -54,6 +53,7 @@ ephy_gui_menu_position_under_widget (GtkMenu *menu,
*x = CLAMP (*x, 0, MAX (0, screen_width - requisition.width));
*y = CLAMP (*y, 0, MAX (0, screen_height - requisition.height));
+ g_print ("result %d\n", *y);
}
/**
diff --git a/lib/toolbar/Makefile.am b/lib/toolbar/Makefile.am
deleted file mode 100644
index d616b1ef5..000000000
--- a/lib/toolbar/Makefile.am
+++ /dev/null
@@ -1,44 +0,0 @@
-INCLUDES = \
- -I$(top_srcdir)/lib \
- -I$(top_srcdir)/lib/widgets \
- $(WARN_CFLAGS) \
- $(EPIPHANY_DEPENDENCY_CFLAGS) \
- -DSHARE_DIR=\"$(pkgdatadir)\" \
- -DG_DISABLE_DEPRECATED \
- -DGDK_DISABLE_DEPRECATED \
- -DGTK_DISABLE_DEPRECATED \
- -DGDK_PIXBUF_DISABLE_DEPRECATED \
- -DGNOME_DISABLE_DEPRECATED
-
-noinst_LTLIBRARIES = libephytoolbar.la
-
-libephytoolbar_la_SOURCES = \
- ephy-toolbar.h \
- ephy-toolbar.c \
- ephy-toolbar-bonobo-view.c \
- ephy-toolbar-bonobo-view.h \
- ephy-toolbar-editor.h \
- ephy-toolbar-editor.c \
- ephy-toolbar-item.h \
- ephy-toolbar-item.c \
- ephy-toolbar-item-factory.h \
- ephy-toolbar-item-factory.c \
- ephy-toolbar-tree-model.h \
- ephy-toolbar-tree-model.c \
- ephy-tb-button.c \
- ephy-tb-button.h \
- ephy-tbi-favicon.h \
- ephy-tbi-favicon.c \
- ephy-tbi-location.h \
- ephy-tbi-location.c \
- ephy-tbi-navigation-history.h \
- ephy-tbi-navigation-history.c \
- ephy-tbi-separator.h \
- ephy-tbi-separator.c \
- ephy-tbi-spinner.h \
- ephy-tbi-spinner.c \
- ephy-tbi-std-toolitem.h \
- ephy-tbi-std-toolitem.c \
- ephy-tbi-zoom.h \
- ephy-tbi-zoom.c
-
diff --git a/lib/widgets/Makefile.am b/lib/widgets/Makefile.am
index 9ffe03f72..23aad4b01 100644
--- a/lib/widgets/Makefile.am
+++ b/lib/widgets/Makefile.am
@@ -1,5 +1,6 @@
INCLUDES = \
-I$(top_srcdir)/lib \
+ -I$(top_srcdir)/lib/egg \
$(WARN_CFLAGS) \
$(EPIPHANY_DEPENDENCY_CFLAGS) \
-DSHARE_DIR=\"$(pkgdatadir)\" \
@@ -16,6 +17,8 @@ libephywidgets_la_SOURCES = \
eggtreemodelfilter.h \
eggtreemultidnd.c \
eggtreemultidnd.h \
+ ephy-arrow-toolbutton.c \
+ ephy-arrow-toolbutton.h \
ephy-autocompletion-window.c \
ephy-autocompletion-window.h \
ephy-ellipsizing-label.c \
diff --git a/lib/widgets/ephy-arrow-toolbutton.c b/lib/widgets/ephy-arrow-toolbutton.c
new file mode 100644
index 000000000..abc5ed4f2
--- /dev/null
+++ b/lib/widgets/ephy-arrow-toolbutton.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2002 Christophe Fergeau
+ *
+ * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "ephy-arrow-toolbutton.h"
+#include "ephy-marshal.h"
+#include "ephy-gui.h"
+#include "ephy-debug.h"
+
+#include <gtk/gtkarrow.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtktogglebutton.h>
+#include <gtk/gtkmenu.h>
+#include <gtk/gtkmain.h>
+
+struct EphyArrowToolButtonPrivate
+{
+ GtkWidget *arrow_widget;
+ GtkWidget *button;
+ GtkMenu *menu;
+};
+
+enum EphyArrowToolButtonSignalsEnum {
+ EPHY_ARROW_TOOL_BUTTON_MENU_ACTIVATED,
+ EPHY_ARROW_TOOL_BUTTON_LAST_SIGNAL
+};
+
+/* GObject boilerplate code */
+static void ephy_arrow_toolbutton_init (EphyArrowToolButton *arrow_toolbutton);
+static void ephy_arrow_toolbutton_class_init (EphyArrowToolButtonClass *klass);
+static void ephy_arrow_toolbutton_finalize (GObject *object);
+
+static GObjectClass *parent_class = NULL;
+
+static gint EphyArrowToolButtonSignals[EPHY_ARROW_TOOL_BUTTON_LAST_SIGNAL];
+
+GType
+ephy_arrow_toolbutton_get_type (void)
+{
+ static GType ephy_arrow_toolbutton_type = 0;
+
+ if (ephy_arrow_toolbutton_type == 0)
+ {
+ static const GTypeInfo our_info =
+ {
+ sizeof (EphyArrowToolButtonClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) ephy_arrow_toolbutton_class_init,
+ NULL,
+ NULL, /* class_data */
+ sizeof (EphyArrowToolButton),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) ephy_arrow_toolbutton_init
+ };
+
+ ephy_arrow_toolbutton_type = g_type_register_static (EGG_TYPE_TOOL_BUTTON,
+ "EphyArrowToolButton",
+ &our_info, 0);
+ }
+
+ return ephy_arrow_toolbutton_type;
+}
+
+static void
+ephy_arrow_toolbutton_class_init (EphyArrowToolButtonClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->finalize = ephy_arrow_toolbutton_finalize;
+
+ EphyArrowToolButtonSignals[EPHY_ARROW_TOOL_BUTTON_MENU_ACTIVATED] =
+ g_signal_new
+ ("menu-activated", G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP,
+ G_STRUCT_OFFSET (EphyArrowToolButtonClass, menu_activated),
+ NULL, NULL,
+ ephy_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+button_state_changed_cb (GtkWidget *widget,
+ GtkStateType previous_state,
+ EphyArrowToolButton *b)
+{
+ EphyArrowToolButtonPrivate *p = b->priv;
+ GtkWidget *button;
+ GtkStateType state = GTK_WIDGET_STATE (widget);
+ GtkStateType other;
+
+ if (state == GTK_STATE_ACTIVE ||
+ state == GTK_STATE_SELECTED ||
+ state == GTK_STATE_INSENSITIVE)
+ {
+ return;
+ }
+
+ button = (widget == p->arrow_widget) ? p->button : p->arrow_widget;
+ other = GTK_WIDGET_STATE (button);
+
+ if (state != other)
+ {
+ gtk_widget_set_state (button, state);
+ }
+}
+
+static void
+popup_menu_under_arrow (EphyArrowToolButton *b, GdkEventButton *event)
+{
+ EphyArrowToolButtonPrivate *p = b->priv;
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (p->arrow_widget), TRUE);
+ LOG ("Emit menu activated signal");
+ g_signal_emit (b, EphyArrowToolButtonSignals[EPHY_ARROW_TOOL_BUTTON_MENU_ACTIVATED], 0);
+ gtk_menu_popup (p->menu, NULL, NULL, ephy_gui_menu_position_under_widget, b,
+ event ? event->button : 0,
+ event ? event->time : gtk_get_current_event_time ());
+}
+
+static void
+menu_deactivated_cb (GtkMenuShell *ms, EphyArrowToolButton *b)
+{
+ EphyArrowToolButtonPrivate *p = b->priv;
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (p->arrow_widget), FALSE);
+}
+
+static gboolean
+arrow_button_press_event_cb (GtkWidget *widget, GdkEventButton *event, EphyArrowToolButton *b)
+{
+ popup_menu_under_arrow (b, event);
+ return TRUE;
+}
+
+static gboolean
+arrow_key_press_event_cb (GtkWidget *widget, GdkEventKey *event, EphyArrowToolButton *b)
+{
+ if (event->keyval == GDK_space
+ || event->keyval == GDK_KP_Space
+ || event->keyval == GDK_Return
+ || event->keyval == GDK_KP_Enter
+ || event->keyval == GDK_Menu)
+ {
+ popup_menu_under_arrow (b, NULL);
+ }
+
+ return FALSE;
+}
+
+static void
+ephy_arrow_toolbutton_init (EphyArrowToolButton *arrowtb)
+{
+ GtkWidget *hbox;
+ GtkWidget *arrow;
+ GtkWidget *arrow_button;
+ GtkWidget *real_button;
+
+ arrowtb->priv = g_new (EphyArrowToolButtonPrivate, 1);
+
+ egg_tool_item_set_homogeneous (EGG_TOOL_ITEM (arrowtb), FALSE);
+
+ hbox = gtk_hbox_new (FALSE, 0);
+ gtk_widget_show (hbox);
+ real_button = EGG_TOOL_BUTTON (arrowtb)->button;
+ g_object_ref (real_button);
+ gtk_container_remove (GTK_CONTAINER (arrowtb), real_button);
+ gtk_container_add (GTK_CONTAINER (hbox), real_button);
+ gtk_container_add (GTK_CONTAINER (arrowtb), hbox);
+
+ arrow_button = gtk_toggle_button_new ();
+ gtk_widget_show (arrow_button);
+ arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
+ gtk_widget_show (arrow);
+ gtk_button_set_relief (GTK_BUTTON (arrow_button), GTK_RELIEF_NONE);
+ gtk_container_add (GTK_CONTAINER (arrow_button), arrow);
+
+ gtk_box_pack_end (GTK_BOX (hbox), arrow_button,
+ FALSE, FALSE, 0);
+
+ arrowtb->priv->button = real_button;
+ arrowtb->priv->arrow_widget = arrow_button;
+
+ arrowtb->priv->menu = GTK_MENU (gtk_menu_new ());
+ g_signal_connect (arrowtb->priv->menu, "deactivate",
+ G_CALLBACK (menu_deactivated_cb), arrowtb);
+
+ g_signal_connect (real_button, "state_changed",
+ G_CALLBACK (button_state_changed_cb),
+ arrowtb);
+ g_signal_connect (arrow_button, "state_changed",
+ G_CALLBACK (button_state_changed_cb),
+ arrowtb);
+ g_signal_connect (arrow_button, "key_press_event",
+ G_CALLBACK (arrow_key_press_event_cb),
+ arrowtb);
+ g_signal_connect (arrow_button, "button_press_event",
+ G_CALLBACK (arrow_button_press_event_cb),
+ arrowtb);
+}
+
+static void
+ephy_arrow_toolbutton_finalize (GObject *object)
+{
+ EphyArrowToolButton *arrow_toolbutton = EPHY_ARROW_TOOLBUTTON (object);
+
+ gtk_widget_destroy (GTK_WIDGET (arrow_toolbutton->priv->menu));
+
+ g_free (arrow_toolbutton->priv);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+GtkMenuShell *
+ephy_arrow_toolbutton_get_menu (EphyArrowToolButton *b)
+{
+ return GTK_MENU_SHELL (b->priv->menu);
+}
diff --git a/lib/widgets/ephy-arrow-toolbutton.h b/lib/widgets/ephy-arrow-toolbutton.h
new file mode 100644
index 000000000..7352d6c1a
--- /dev/null
+++ b/lib/widgets/ephy-arrow-toolbutton.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2002 Christophe Fergeau
+ *
+ * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef EPHY_ARROW_TOOLBUTTON_H
+#define EPHY_ARROW_TOOLBUTTON_H
+
+#include <glib.h>
+#include <gtk/gtkmenushell.h>
+
+#include "eggtoolbutton.h"
+
+G_BEGIN_DECLS
+
+typedef struct EphyArrowToolButtonClass EphyArrowToolButtonClass;
+
+#define EPHY_ARROW_TOOLBUTTON_TYPE (ephy_arrow_toolbutton_get_type ())
+#define EPHY_ARROW_TOOLBUTTON(obj) (GTK_CHECK_CAST ((obj), EPHY_ARROW_TOOLBUTTON_TYPE, EphyArrowToolButton))
+#define EPHY_ARROW_TOOLBUTTON_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), EPHY_ARROW_TOOLBUTTON_TYPE, EphyArrowToolButtonClass))
+#define IS_EPHY_ARROW_TOOLBUTTON(obj) (GTK_CHECK_TYPE ((obj), EPHY_ARROW_TOOLBUTTON_TYPE))
+#define IS_EPHY_ARROW_TOOLBUTTON_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), EPHY_ARROW_TOOLBUTTON))
+
+typedef struct EphyArrowToolButton EphyArrowToolButton;
+typedef struct EphyArrowToolButtonPrivate EphyArrowToolButtonPrivate;
+
+struct EphyArrowToolButton
+{
+ EggToolButton parent;
+ EphyArrowToolButtonPrivate *priv;
+};
+
+struct EphyArrowToolButtonClass
+{
+ EggToolButtonClass parent_class;
+
+ void (*menu_activated) (EphyArrowToolButton *b);
+};
+
+GType ephy_arrow_toolbutton_get_type (void);
+
+GtkMenuShell *ephy_arrow_toolbutton_get_menu (EphyArrowToolButton *b);
+
+G_END_DECLS;
+
+#endif /* EPHY_ARROW_TOOLBUTTON_H */
diff --git a/lib/widgets/ephy-location-entry.c b/lib/widgets/ephy-location-entry.c
index d2702c6b4..5a947a7b2 100644
--- a/lib/widgets/ephy-location-entry.c
+++ b/lib/widgets/ephy-location-entry.c
@@ -158,10 +158,10 @@ ephy_location_entry_finalize_impl (GObject *o)
G_OBJECT_CLASS (gtk_hbox_class)->finalize (o);
}
-EphyLocationEntry *
+GtkWidget *
ephy_location_entry_new (void)
{
- return EPHY_LOCATION_ENTRY (g_object_new (EPHY_TYPE_LOCATION_ENTRY, NULL));
+ return GTK_WIDGET (g_object_new (EPHY_TYPE_LOCATION_ENTRY, NULL));
}
static void
diff --git a/lib/widgets/ephy-location-entry.h b/lib/widgets/ephy-location-entry.h
index eebacc770..d292ffb0c 100644
--- a/lib/widgets/ephy-location-entry.h
+++ b/lib/widgets/ephy-location-entry.h
@@ -63,10 +63,10 @@ struct _EphyLocationEntry
};
GType ephy_location_entry_get_type (void);
-EphyLocationEntry * ephy_location_entry_new (void);
+GtkWidget *ephy_location_entry_new (void);
void ephy_location_entry_set_location (EphyLocationEntry *w,
const gchar *new_location);
-gchar * ephy_location_entry_get_location (EphyLocationEntry *w);
+gchar *ephy_location_entry_get_location (EphyLocationEntry *w);
void ephy_location_entry_set_autocompletion (EphyLocationEntry *w,
EphyAutocompletion *ac);
void ephy_location_entry_activate (EphyLocationEntry *w);
diff --git a/lib/widgets/ephy-spinner.c b/lib/widgets/ephy-spinner.c
index e4462f889..d1caf8fba 100644
--- a/lib/widgets/ephy-spinner.c
+++ b/lib/widgets/ephy-spinner.c
@@ -396,8 +396,8 @@ ephy_spinner_expose (GtkWidget *widget, GdkEventExpose *event)
height = gdk_pixbuf_get_height (pixbuf);
/* Compute the offsets for the image centered on our allocation */
- x_offset = widget->allocation.x + (widget->allocation.width - width) / 2;
- y_offset = widget->allocation.y + (widget->allocation.height - height) / 2;
+ x_offset = (widget->allocation.width - width) / 2;
+ y_offset = (widget->allocation.height - height) / 2;
pix_area.x = x_offset;
pix_area.y = y_offset;
diff --git a/src/Makefile.am b/src/Makefile.am
index e2b4a65e2..875926c3b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,6 +3,7 @@ SUBDIRS = bookmarks
INCLUDES = \
-I$(top_srcdir)/embed \
-I$(top_srcdir)/lib \
+ -I$(top_srcdir)/lib/egg \
-I$(top_srcdir)/lib/widgets \
-I$(top_srcdir)/lib/toolbar \
-I$(top_srcdir)/src/bookmarks \
@@ -45,19 +46,22 @@ epiphany_SOURCES = \
appearance-prefs.h \
ephy-automation.c \
ephy-automation.h \
+ ephy-favicon-action.c \
+ ephy-favicon-action.h \
ephy-favorites-menu.c \
ephy-favorites-menu.h \
ephy-history-model.c \
ephy-history-model.h \
+ ephy-location-action.c \
+ ephy-location-action.h \
ephy-main.c \
- ephy-navigation-button.c \
- ephy-navigation-button.h \
+ ephy-navigation-action.c \
ephy-shell.c \
ephy-shell.h \
+ ephy-spinner-action.c \
+ ephy-spinner-action.h \
ephy-tab.c \
ephy-tab.h \
- ephy-tbi.c \
- ephy-tbi.h \
ephy-window.c \
ephy-window.h \
general-prefs.c \
diff --git a/src/ephy-favicon-action.c b/src/ephy-favicon-action.c
new file mode 100644
index 000000000..9fa68acf2
--- /dev/null
+++ b/src/ephy-favicon-action.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2003 Marco Pesenti Gritti
+ *
+ * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "ephy-favicon-action.h"
+#include "eggtoolitem.h"
+#include "ephy-window.h"
+#include "ephy-tab.h"
+#include "ephy-dnd.h"
+#include "ephy-favicon-cache.h"
+#include "ephy-shell.h"
+
+struct EphyFaviconActionPrivate
+{
+ EphyWindow *window;
+ char *icon;
+};
+
+enum
+{
+ PROP_0,
+ PROP_WINDOW,
+ PROP_ICON
+};
+
+static void ephy_favicon_action_init (EphyFaviconAction *action);
+static void ephy_favicon_action_class_init (EphyFaviconActionClass *class);
+
+static GObjectClass *parent_class = NULL;
+
+GType
+ephy_favicon_action_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EphyFaviconActionClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) ephy_favicon_action_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+ sizeof (EphyFaviconAction),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) ephy_favicon_action_init,
+ };
+
+ type = g_type_register_static (EGG_TYPE_ACTION,
+ "EphyFaviconAction",
+ &type_info, 0);
+ }
+ return type;
+}
+
+static GtkWidget *
+create_tool_item (EggAction *action)
+{
+ GtkWidget *image;
+ GtkWidget *ebox;
+ GtkWidget *item;
+
+ item = (* EGG_ACTION_CLASS (parent_class)->create_tool_item) (action);
+
+ ebox = gtk_event_box_new ();
+ image = gtk_image_new ();
+ gtk_container_add (GTK_CONTAINER (ebox), image);
+ gtk_container_set_border_width (GTK_CONTAINER (ebox), 2);
+ gtk_container_add (GTK_CONTAINER (item), ebox);
+ gtk_widget_show (image);
+ gtk_widget_show (ebox);
+
+ g_object_set_data (G_OBJECT (item), "image", image);
+
+ return item;
+}
+
+static void
+each_url_get_data_binder (EphyDragEachSelectedItemDataGet iteratee,
+ gpointer iterator_context, gpointer data)
+{
+ const char *location;
+ EphyTab *tab;
+ EphyWindow *window = EPHY_WINDOW(iterator_context);
+
+ tab = ephy_window_get_active_tab (window);
+ location = ephy_tab_get_location (tab);
+
+ iteratee (location, -1, -1, -1, -1, data);
+}
+
+static void
+favicon_drag_data_get_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint32 time,
+ EphyWindow *window)
+{
+ g_assert (widget != NULL);
+ g_return_if_fail (context != NULL);
+
+ ephy_dnd_drag_data_get (widget, context, selection_data,
+ info, time, window, each_url_get_data_binder);
+}
+
+static void
+ephy_favicon_action_sync_icon (EggAction *action, GParamSpec *pspec,
+ GtkWidget *proxy)
+{
+ EphyFaviconAction *fav_action = EPHY_FAVICON_ACTION (action);
+ char *url;
+ GtkWidget *image;
+ GdkPixbuf *pixbuf = NULL;
+ EphyFaviconCache *cache;
+
+ cache = ephy_embed_shell_get_favicon_cache (EPHY_EMBED_SHELL (ephy_shell));
+
+ url = fav_action->priv->icon;
+ image = GTK_WIDGET (g_object_get_data (G_OBJECT (proxy), "image"));
+
+ if (url)
+ {
+ pixbuf = ephy_favicon_cache_get (cache, url);
+ }
+
+ if (pixbuf)
+ {
+ gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf);
+ }
+ else
+ {
+ gtk_image_set_from_stock (GTK_IMAGE (image),
+ GTK_STOCK_JUMP_TO,
+ GTK_ICON_SIZE_MENU);
+ }
+}
+
+static void
+connect_proxy (EggAction *action, GtkWidget *proxy)
+{
+ ephy_dnd_url_drag_source_set (proxy);
+
+ g_signal_connect (proxy,
+ "drag_data_get",
+ G_CALLBACK (favicon_drag_data_get_cb),
+ EPHY_FAVICON_ACTION (action)->priv->window);
+ g_signal_connect_object (action, "notify::icon",
+ G_CALLBACK (ephy_favicon_action_sync_icon),
+ proxy, 0);
+
+ (* EGG_ACTION_CLASS (parent_class)->connect_proxy) (action, proxy);
+}
+
+static void
+ephy_favicon_action_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EphyFaviconAction *fav;
+
+ fav = EPHY_FAVICON_ACTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_WINDOW:
+ fav->priv->window = EPHY_WINDOW (g_value_get_object (value));
+ break;
+ case PROP_ICON:
+ g_free (fav->priv->icon);
+ fav->priv->icon = g_strdup (g_value_get_string (value));
+ g_object_notify(object, "icon");
+ break;
+ }
+}
+
+static void
+ephy_favicon_action_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EphyFaviconAction *fav;
+
+ fav = EPHY_FAVICON_ACTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_WINDOW:
+ g_value_set_object (value, fav->priv->window);
+ break;
+ case PROP_ICON:
+ g_value_set_object (value, fav->priv->icon);
+ break;
+ }
+}
+
+static void
+ephy_favicon_action_class_init (EphyFaviconActionClass *class)
+{
+ EggActionClass *action_class;
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->set_property = ephy_favicon_action_set_property;
+ object_class->get_property = ephy_favicon_action_get_property;
+
+ parent_class = g_type_class_peek_parent (class);
+ action_class = EGG_ACTION_CLASS (class);
+
+ action_class->toolbar_item_type = EGG_TYPE_TOOL_ITEM;
+ action_class->create_tool_item = create_tool_item;
+ action_class->connect_proxy = connect_proxy;
+
+ g_object_class_install_property (object_class,
+ PROP_WINDOW,
+ g_param_spec_object ("window",
+ "Window",
+ "The window",
+ G_TYPE_OBJECT,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_ICON,
+ g_param_spec_string ("icon",
+ "Icon",
+ "The icon",
+ NULL,
+ G_PARAM_READWRITE));
+}
+
+static void
+ephy_favicon_action_init (EphyFaviconAction *action)
+{
+ action->priv = g_new0 (EphyFaviconActionPrivate, 1);
+ action->priv->icon = NULL;
+}
diff --git a/src/ephy-favicon-action.h b/src/ephy-favicon-action.h
new file mode 100644
index 000000000..31f6c3d82
--- /dev/null
+++ b/src/ephy-favicon-action.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2003 Marco Pesenti Gritti
+ *
+ * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef EPHY_FAVICON_ACTION_H
+#define EPHY_FAVICON_ACTION_H
+
+#include <gtk/gtk.h>
+#include <egg-action.h>
+
+#define EPHY_TYPE_FAVICON_ACTION (ephy_favicon_action_get_type ())
+#define EPHY_FAVICON_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPHY_TYPE_FAVICON_ACTION, EphyFaviconAction))
+#define EPHY_FAVICON_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EPHY_TYPE_FAVICON_ACTION, EphyFaviconActionClass))
+#define EPHY_IS_FAVICON_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPHY_TYPE_FAVICON_ACTION))
+#define EPHY_IS_FAVICON_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EPHY_TYPE_FAVICON_ACTION))
+#define EPHY_FAVICON_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_FAVICON_ACTION, EphyFaviconActionClass))
+
+typedef struct _EphyFaviconAction EphyFaviconAction;
+typedef struct _EphyFaviconActionClass EphyFaviconActionClass;
+typedef struct EphyFaviconActionPrivate EphyFaviconActionPrivate;
+
+struct _EphyFaviconAction
+{
+ EggAction parent;
+ EphyFaviconActionPrivate *priv;
+};
+
+struct _EphyFaviconActionClass
+{
+ EggActionClass parent_class;
+};
+
+GType ephy_favicon_action_get_type (void);
+
+#endif
diff --git a/src/ephy-favorites-menu.c b/src/ephy-favorites-menu.c
index b463663c2..8a557a7ad 100644
--- a/src/ephy-favorites-menu.c
+++ b/src/ephy-favorites-menu.c
@@ -23,7 +23,7 @@
#include "ephy-favorites-menu.h"
#include "ephy-gobject-misc.h"
#include "ephy-string.h"
-#include "ephy-bonobo-extensions.h"
+#include "egg-menu-merge.h"
#include "ephy-marshal.h"
#include "ephy-shell.h"
#include "ephy-debug.h"
@@ -39,9 +39,10 @@
*/
struct _EphyFavoritesMenuPrivate
{
- gchar *path;
EphyWindow *window;
EphyBookmarks *bookmarks;
+ EggActionGroup *action_group;
+ guint ui_id;
};
typedef struct
@@ -109,18 +110,35 @@ ephy_favorites_menu_init (EphyFavoritesMenu *wrhm)
wrhm->priv = p;
wrhm->priv->bookmarks = ephy_shell_get_bookmarks (ephy_shell);
+ wrhm->priv->ui_id = -1;
+ wrhm->priv->action_group = NULL;
}
static void
-ephy_favorites_menu_finalize_impl (GObject *o)
+ephy_favorites_menu_clean (EphyFavoritesMenu *wrhm)
{
- EphyFavoritesMenu *wrhm = EPHY_FAVORITES_MENU (o);
EphyFavoritesMenuPrivate *p = wrhm->priv;
+ EggMenuMerge *merge = EGG_MENU_MERGE (p->window->ui_merge);
+
+ if (p->ui_id >= 0)
+ {
+ egg_menu_merge_remove_ui (merge, p->ui_id);
+ }
- if (p->path)
+ if (p->action_group != NULL)
{
- g_free (p->path);
+ egg_menu_merge_remove_action_group (merge, p->action_group);
+ g_object_unref (p->action_group);
}
+}
+
+static void
+ephy_favorites_menu_finalize_impl (GObject *o)
+{
+ EphyFavoritesMenu *wrhm = EPHY_FAVORITES_MENU (o);
+ EphyFavoritesMenuPrivate *p = wrhm->priv;
+
+ ephy_favorites_menu_clean (wrhm);
g_free (p);
@@ -139,6 +157,7 @@ ephy_favorites_menu_set_property (GObject *object,
{
case PROP_EPHY_WINDOW:
m->priv->window = g_value_get_object (value);
+ ephy_favorites_menu_rebuild (m);
break;
}
}
@@ -168,26 +187,6 @@ ephy_favorites_menu_new (EphyWindow *window)
return ret;
}
-void
-ephy_favorites_menu_set_path (EphyFavoritesMenu *wrhm,
- const gchar *path)
-{
- EphyFavoritesMenuPrivate *p;
-
- g_return_if_fail (EPHY_IS_FAVORITES_MENU (wrhm));
- g_return_if_fail (path != NULL);
-
- p = wrhm->priv;
-
- if (p->path)
- {
- g_free (p->path);
- }
- p->path = g_strdup (path);
-
- ephy_favorites_menu_update (wrhm);
-}
-
static void
ephy_favorites_menu_verb_cb (BonoboUIComponent *uic,
FavoriteData *data,
@@ -204,11 +203,7 @@ ephy_favorites_menu_rebuild (EphyFavoritesMenu *wrhm)
gint i;
EphyNode *fav;
GPtrArray *children;
- BonoboUIComponent *uic = BONOBO_UI_COMPONENT (p->window->ui_component);
-
- if (!p->path) return;
-
- ephy_bonobo_clear_path (uic, p->path);
+ EggMenuMerge *merge = EGG_MENU_MERGE (p->window->ui_merge);
LOG ("Rebuilding recent history menu")
@@ -216,17 +211,22 @@ ephy_favorites_menu_rebuild (EphyFavoritesMenu *wrhm)
children = ephy_node_get_children (fav);
xml = g_string_new (NULL);
- g_string_append_printf (xml, "<placeholder name=\"wrhm%x\">\n", (guint) wrhm);
+ g_string_append (xml, "<Root><menu><submenu name=\"GoMenu\">"
+ "<placeholder name=\"GoFavorites\">");
+
+ p->action_group = egg_action_group_new ("FavoritesActions");
+ egg_menu_merge_insert_action_group (merge, p->action_group, 0);
for (i = 0; i < children->len; i++)
{
- char *verb = g_strdup_printf ("Wrhm%xn%d", (guint) wrhm, i);
+ char *verb = g_strdup_printf ("GoFav%d", i);
char *title_s;
const char *title;
const char *url;
xmlChar *label_x;
EphyNode *child;
FavoriteData *data;
+ EggAction *action;
child = g_ptr_array_index (children, i);
title = ephy_node_get_property_string (child, EPHY_NODE_BMK_PROP_TITLE);
@@ -234,21 +234,32 @@ ephy_favorites_menu_rebuild (EphyFavoritesMenu *wrhm)
title_s = ephy_string_shorten (title, MAX_LABEL_LENGTH);
label_x = xmlEncodeSpecialChars (NULL, title_s);
+ data = g_new0 (FavoriteData, 1);
+ data->window = wrhm->priv->window;
+ data->url = url;
+
+ action = g_object_new (EGG_TYPE_ACTION,
+ "name", verb,
+ "label", label_x,
+ "tooltip", "Hello",
+ "stock_id", NULL,
+ NULL);
+ g_signal_connect_closure
+ (action, "activate",
+ g_cclosure_new (G_CALLBACK (ephy_favorites_menu_verb_cb),
+ data,
+ (GClosureNotify)g_free),
+ FALSE);
+ egg_action_group_add_action (p->action_group, action);
+ g_object_unref (action);
+
g_string_append (xml, "<menuitem name=\"");
g_string_append (xml, verb);
- g_string_append (xml, "\" label=\"");
- g_string_append (xml, label_x);
+ g_string_append (xml, "Menu");
g_string_append (xml, "\" verb=\"");
g_string_append (xml, verb);
g_string_append (xml, "\"/>\n");
- data = g_new0 (FavoriteData, 1);
- data->window = wrhm->priv->window;
- data->url = url;
- bonobo_ui_component_add_verb_full (uic, verb, g_cclosure_new
- (G_CALLBACK (ephy_favorites_menu_verb_cb), data,
- (GClosureNotify)g_free));
-
xmlFree (label_x);
g_free (title_s);
g_free (verb);
@@ -256,13 +267,16 @@ ephy_favorites_menu_rebuild (EphyFavoritesMenu *wrhm)
ephy_node_thaw (fav);
- g_string_append (xml, "</placeholder>\n");
+ g_string_append (xml, "</placeholder></submenu></menu></Root>");
if (children->len > 0)
{
- bonobo_ui_component_set (uic, p->path,
- xml->str, NULL);
+ GError *error = NULL;
+
+ p->ui_id = egg_menu_merge_add_ui_from_string
+ (merge, xml->str, -1, &error);
}
+
g_string_free (xml, TRUE);
}
diff --git a/src/ephy-favorites-menu.h b/src/ephy-favorites-menu.h
index b76e8d2d8..228cbcef8 100644
--- a/src/ephy-favorites-menu.h
+++ b/src/ephy-favorites-menu.h
@@ -59,8 +59,5 @@ EphyFavoritesMenu *ephy_favorites_menu_new (EphyWindow *window);
void ephy_favorites_menu_update (EphyFavoritesMenu *wrhm);
-void ephy_favorites_menu_set_path (EphyFavoritesMenu *wrhm,
- const gchar *path);
-
#endif
diff --git a/src/ephy-location-action.c b/src/ephy-location-action.c
new file mode 100644
index 000000000..07f7e6c2b
--- /dev/null
+++ b/src/ephy-location-action.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2003 Marco Pesenti Gritti
+ *
+ * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "ephy-location-action.h"
+#include "ephy-location-entry.h"
+#include "ephy-shell.h"
+#include "ephy-debug.h"
+#include "eggtoolitem.h"
+
+static void ephy_location_action_init (EphyLocationAction *action);
+static void ephy_location_action_class_init (EphyLocationActionClass *class);
+
+enum
+{
+ GO_LOCATION,
+ LAST_SIGNAL
+};
+
+static GObjectClass *parent_class = NULL;
+
+static guint ephy_location_action_signals[LAST_SIGNAL] = { 0 };
+
+GType
+ephy_location_action_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EphyLocationActionClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) ephy_location_action_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+ sizeof (EphyLocationAction),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) ephy_location_action_init,
+ };
+
+ type = g_type_register_static (EGG_TYPE_ACTION,
+ "EphyLocationAction",
+ &type_info, 0);
+ }
+ return type;
+}
+
+static GtkWidget *
+create_tool_item (EggAction *action)
+{
+ GtkWidget *item;
+ GtkWidget *location;
+
+ LOG ("Create location toolitem")
+
+ item = (* EGG_ACTION_CLASS (parent_class)->create_tool_item) (action);
+
+ location = ephy_location_entry_new ();
+ gtk_container_add (GTK_CONTAINER (item), location);
+ egg_tool_item_set_expandable (EGG_TOOL_ITEM (item), TRUE);
+ gtk_widget_show (location);
+
+ LOG ("Create location toolitem: Done.")
+
+ return item;
+}
+
+static void
+location_url_activate_cb (EphyLocationEntry *entry,
+ const char *content,
+ const char *target,
+ EphyLocationAction *action)
+{
+ EphyBookmarks *bookmarks;
+ LOG ("Location url activated")
+ bookmarks = ephy_shell_get_bookmarks (ephy_shell);
+
+ if (!content)
+ {
+ LOG ("Go to %s", target);
+ g_signal_emit (action,
+ ephy_location_action_signals[GO_LOCATION],
+ 0, target);
+ }
+ else
+ {
+ char *url;
+
+ url = ephy_bookmarks_solve_smart_url
+ (bookmarks, target, content);
+ g_return_if_fail (url != NULL);
+ LOG ("Go to %s", url);
+ g_signal_emit (action,
+ ephy_location_action_signals[GO_LOCATION],
+ 0, url);
+ g_free (url);
+ }
+}
+
+static void
+connect_proxy (EggAction *action, GtkWidget *proxy)
+{
+ EphyAutocompletion *ac = ephy_shell_get_autocompletion (ephy_shell);
+ EphyLocationEntry *e;
+
+ LOG ("Connect location proxy")
+
+ e = EPHY_LOCATION_ENTRY (GTK_BIN (proxy)->child);
+ ephy_location_entry_set_autocompletion (e, ac);
+
+ g_signal_connect (e, "activated",
+ GTK_SIGNAL_FUNC(location_url_activate_cb),
+ action);
+
+ (* EGG_ACTION_CLASS (parent_class)->connect_proxy) (action, proxy);
+}
+
+static void
+ephy_location_action_class_init (EphyLocationActionClass *class)
+{
+ EggActionClass *action_class;
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ parent_class = g_type_class_peek_parent (class);
+ action_class = EGG_ACTION_CLASS (class);
+
+ action_class->toolbar_item_type = EGG_TYPE_TOOL_ITEM;
+ action_class->create_tool_item = create_tool_item;
+ action_class->connect_proxy = connect_proxy;
+
+ ephy_location_action_signals[GO_LOCATION] =
+ g_signal_new ("go_location",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EphyLocationActionClass, go_location),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_STRING);
+}
+
+static void
+ephy_location_action_init (EphyLocationAction *action)
+{
+}
+
+GtkWidget *
+ephy_location_action_get_widget (EphyLocationAction *action)
+{
+ GSList *slist;
+
+ slist = EGG_ACTION (action)->proxies;
+
+ if (slist)
+ {
+ return GTK_BIN (slist->data)->child;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
diff --git a/src/ephy-location-action.h b/src/ephy-location-action.h
new file mode 100644
index 000000000..daa609aee
--- /dev/null
+++ b/src/ephy-location-action.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2003 Marco Pesenti Gritti
+ *
+ * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef EPHY_LOCATION_ACTION_H
+#define EPHY_LOCATION_ACTION_H
+
+#include <gtk/gtk.h>
+#include <egg-action.h>
+
+#define EPHY_TYPE_LOCATION_ACTION (ephy_location_action_get_type ())
+#define EPHY_LOCATION_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPHY_TYPE_LOCATION_ACTION, EphyLocationAction))
+#define EPHY_LOCATION_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EPHY_TYPE_LOCATION_ACTION, EphyLocationActionClass))
+#define EPHY_IS_LOCATION_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPHY_TYPE_LOCATION_ACTION))
+#define EPHY_IS_LOCATION_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EPHY_TYPE_LOCATION_ACTION))
+#define EPHY_LOCATION_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_LOCATION_ACTION, EphyLocationActionClass))
+
+typedef struct _EphyLocationAction EphyLocationAction;
+typedef struct _EphyLocationActionClass EphyLocationActionClass;
+
+struct _EphyLocationAction
+{
+ EggAction parent;
+};
+
+struct _EphyLocationActionClass
+{
+ EggActionClass parent_class;
+
+ void (*go_location) (EphyLocationAction *action, char *location);
+};
+
+GType ephy_location_action_get_type (void);
+
+GtkWidget *ephy_location_action_get_widget (EphyLocationAction *action);
+
+#endif
diff --git a/src/ephy-navigation-action.c b/src/ephy-navigation-action.c
new file mode 100644
index 000000000..3aeaef386
--- /dev/null
+++ b/src/ephy-navigation-action.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2003 Marco Pesenti Gritti
+ *
+ * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "ephy-navigation-action.h"
+#include "ephy-arrow-toolbutton.h"
+#include "ephy-window.h"
+#include "ephy-debug.h"
+
+static void ephy_navigation_action_init (EphyNavigationAction *action);
+static void ephy_navigation_action_class_init (EphyNavigationActionClass *class);
+
+static GObjectClass *parent_class = NULL;
+
+struct EphyNavigationActionPrivate
+{
+ EphyWindow *window;
+ EphyNavigationDirection direction;
+};
+
+enum
+{
+ PROP_0,
+ PROP_DIRECTION,
+ PROP_WINDOW
+};
+
+GType
+ephy_navigation_action_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EphyNavigationActionClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) ephy_navigation_action_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+ sizeof (EphyNavigationAction),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) ephy_navigation_action_init,
+ };
+
+ type = g_type_register_static (EGG_TYPE_ACTION,
+ "EphyNavigationAction",
+ &type_info, 0);
+ }
+ return type;
+}
+
+static GtkWidget *
+new_history_menu_item (gchar *origtext,
+ const GdkPixbuf *ico)
+{
+ GtkWidget *item = gtk_image_menu_item_new ();
+ GtkWidget *hb = gtk_hbox_new (FALSE, 0);
+ GtkWidget *label = gtk_label_new (origtext);
+
+ gtk_box_pack_start (GTK_BOX (hb), label, FALSE, FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (item), hb);
+
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
+ gtk_image_new_from_pixbuf ((GdkPixbuf *) ico));
+
+ gtk_widget_show_all (item);
+
+ return item;
+}
+
+static void
+activate_back_or_forward_menu_item_cb (GtkWidget *menu, EphyWindow *window)
+{
+ EphyEmbed *embed;
+ int go_nth;
+
+ embed = ephy_window_get_active_embed (window);
+ g_return_if_fail (embed != NULL);
+
+ go_nth = (int)g_object_get_data (G_OBJECT(menu), "go_nth");
+
+ ephy_embed_shistory_go_nth (embed, go_nth);
+}
+
+static void
+activate_up_menu_item_cb (GtkWidget *menu, EphyWindow *window)
+{
+ EphyEmbed *embed;
+ int go_nth;
+ GSList *l;
+ gchar *url;
+
+ embed = ephy_window_get_active_embed (window);
+ g_return_if_fail (embed != NULL);
+
+ go_nth = (int)g_object_get_data (G_OBJECT(menu), "go_nth");
+
+ ephy_embed_get_go_up_list (embed, &l);
+
+ url = g_slist_nth_data (l, go_nth);
+ if (url)
+ {
+ ephy_embed_load_url (embed, url);
+ }
+
+ g_slist_foreach (l, (GFunc) g_free, NULL);
+ g_slist_free (l);
+}
+
+static void
+setup_back_or_forward_menu (EphyWindow *window, GtkMenuShell *ms, EphyNavigationDirection dir)
+{
+ int pos, count;
+ EphyEmbed *embed;
+ int start, end;
+
+ embed = ephy_window_get_active_embed (window);
+ g_return_if_fail (embed != NULL);
+
+ ephy_embed_shistory_get_pos (embed, &pos);
+ ephy_embed_shistory_count (embed, &count);
+
+ if (count == 0) return;
+
+ if (dir == EPHY_NAVIGATION_DIRECTION_BACK)
+ {
+ start = pos - 1;
+ end = -1;
+ }
+ else
+ {
+ start = pos + 1;
+ end = count;
+ }
+
+ while (start != end)
+ {
+ char *title, *url;
+ GtkWidget *item;
+ ephy_embed_shistory_get_nth (embed, start, FALSE, &url, &title);
+ item = new_history_menu_item (title ? title : url, NULL);
+ gtk_menu_shell_append (ms, item);
+ g_object_set_data (G_OBJECT (item), "go_nth", GINT_TO_POINTER (start));
+ g_signal_connect (item, "activate",
+ G_CALLBACK (activate_back_or_forward_menu_item_cb), window);
+ gtk_widget_show_all (item);
+
+ g_free (url);
+ g_free (title);
+
+ if (start < end)
+ {
+ start++;
+ }
+ else
+ {
+ start--;
+ }
+ }
+}
+
+static void
+setup_up_menu (EphyWindow *window, GtkMenuShell *ms)
+{
+ EphyEmbed *embed;
+ GSList *l;
+ GSList *li;
+ int count = 0;
+
+ embed = ephy_window_get_active_embed (window);
+ g_return_if_fail (embed != NULL);
+
+ ephy_embed_get_go_up_list (embed, &l);
+
+ for (li = l; li; li = li->next)
+ {
+ char *url = li->data;
+ GtkWidget *item;
+
+ item = new_history_menu_item (url, NULL);
+ gtk_menu_shell_append (ms, item);
+ g_object_set_data (G_OBJECT(item), "go_nth", GINT_TO_POINTER (count));
+ g_signal_connect (item, "activate",
+ G_CALLBACK (activate_up_menu_item_cb), window);
+ gtk_widget_show_all (item);
+ count ++;
+ }
+
+ g_slist_foreach (l, (GFunc) g_free, NULL);
+ g_slist_free (l);
+}
+
+static void
+menu_activated_cb (EphyArrowToolButton *w, EphyNavigationAction *b)
+{
+ EphyNavigationActionPrivate *p = b->priv;
+ GtkMenuShell *ms = ephy_arrow_toolbutton_get_menu (w);
+ EphyWindow *win = b->priv->window;
+ GList *children;
+ GList *li;
+
+ LOG ("Show navigation menu")
+
+ children = gtk_container_get_children (GTK_CONTAINER (ms));
+ for (li = children; li; li = li->next)
+ {
+ gtk_container_remove (GTK_CONTAINER (ms), li->data);
+ }
+ g_list_free (children);
+
+ switch (p->direction)
+ {
+ case EPHY_NAVIGATION_DIRECTION_UP:
+ setup_up_menu (win, ms);
+ break;
+ case EPHY_NAVIGATION_DIRECTION_FORWARD:
+ case EPHY_NAVIGATION_DIRECTION_BACK:
+ setup_back_or_forward_menu (win, ms, p->direction);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static void
+connect_proxy (EggAction *action, GtkWidget *proxy)
+{
+ LOG ("Connect navigation action proxy")
+
+ g_signal_connect (proxy, "menu-activated",
+ G_CALLBACK (menu_activated_cb), action);
+
+ (* EGG_ACTION_CLASS (parent_class)->connect_proxy) (action, proxy);
+}
+
+static void
+ephy_navigation_action_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EphyNavigationAction *nav;
+
+ nav = EPHY_NAVIGATION_ACTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_DIRECTION:
+ nav->priv->direction = g_value_get_int (value);
+ break;
+ case PROP_WINDOW:
+ nav->priv->window = EPHY_WINDOW (g_value_get_object (value));
+ break;
+ }
+}
+
+static void
+ephy_navigation_action_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EphyNavigationAction *nav;
+
+ nav = EPHY_NAVIGATION_ACTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_DIRECTION:
+ g_value_set_int (value, nav->priv->direction);
+ break;
+ case PROP_WINDOW:
+ g_value_set_object (value, nav->priv->window);
+ break;
+ }
+}
+
+static void
+ephy_navigation_action_class_init (EphyNavigationActionClass *class)
+{
+ EggActionClass *action_class;
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->set_property = ephy_navigation_action_set_property;
+ object_class->get_property = ephy_navigation_action_get_property;
+
+ parent_class = g_type_class_peek_parent (class);
+ action_class = EGG_ACTION_CLASS (class);
+
+ action_class->toolbar_item_type = EPHY_ARROW_TOOLBUTTON_TYPE;
+ action_class->connect_proxy = connect_proxy;
+
+ g_object_class_install_property (object_class,
+ PROP_DIRECTION,
+ g_param_spec_int ("direction",
+ "Direction",
+ "Direction",
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_WINDOW,
+ g_param_spec_object ("window",
+ "Window",
+ "The navigation window",
+ G_TYPE_OBJECT,
+ G_PARAM_READWRITE));
+
+}
+
+static void
+ephy_navigation_action_init (EphyNavigationAction *action)
+{
+ action->priv = g_new0 (EphyNavigationActionPrivate, 1);
+}
+
+
diff --git a/src/ephy-navigation-action.h b/src/ephy-navigation-action.h
new file mode 100644
index 000000000..0e6c23dbe
--- /dev/null
+++ b/src/ephy-navigation-action.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2003 Marco Pesenti Gritti
+ *
+ * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef EPHY_NAVIGATION_ACTION_H
+#define EPHY_NAVIGATION_ACTION_H
+
+#include <gtk/gtk.h>
+#include <egg-action.h>
+
+#define EPHY_TYPE_NAVIGATION_ACTION (ephy_navigation_action_get_type ())
+#define EPHY_NAVIGATION_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPHY_TYPE_NAVIGATION_ACTION, EphyNavigationAction))
+#define EPHY_NAVIGATION_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EPHY_TYPE_NAVIGATION_ACTION, EphyNavigationActionClass))
+#define EPHY_IS_NAVIGATION_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPHY_TYPE_NAVIGATION_ACTION))
+#define EPHY_IS_NAVIGATION_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EPHY_TYPE_NAVIGATION_ACTION))
+#define EPHY_NAVIGATION_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_NAVIGATION_ACTION, EphyNavigationActionClass))
+
+typedef struct _EphyNavigationAction EphyNavigationAction;
+typedef struct _EphyNavigationActionClass EphyNavigationActionClass;
+typedef struct EphyNavigationActionPrivate EphyNavigationActionPrivate;
+
+typedef enum
+{
+ EPHY_NAVIGATION_DIRECTION_UP,
+ EPHY_NAVIGATION_DIRECTION_BACK,
+ EPHY_NAVIGATION_DIRECTION_FORWARD
+} EphyNavigationDirection;
+
+struct _EphyNavigationAction
+{
+ EggAction parent;
+ EphyNavigationActionPrivate *priv;
+};
+
+struct _EphyNavigationActionClass
+{
+ EggActionClass parent_class;
+};
+
+GType ephy_navigation_action_get_type (void);
+
+#endif
diff --git a/src/ephy-navigation-button.c b/src/ephy-navigation-button.c
deleted file mode 100644
index d0d80af7f..000000000
--- a/src/ephy-navigation-button.c
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- * Copyright (C) 2002 Ricardo Fernández Pascual
- *
- * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "ephy-gobject-misc.h"
-#include "ephy-marshal.h"
-#include "ephy-tb-button.h"
-#include "ephy-gui.h"
-#include "ephy-string.h"
-#include "ephy-navigation-button.h"
-#include "ephy-debug.h"
-
-#include <gtk/gtkstock.h>
-#include <string.h>
-#include <libgnome/gnome-i18n.h>
-
-/**
- * Private data
- */
-struct _EphyNavigationButtonPrivate
-{
- EphyTbButton *widget;
- EphyNavigationDirection direction;
- gboolean show_arrow;
- gboolean sensitive;
-};
-
-enum
-{
- TOOLBAR_ITEM_STYLE_PROP,
- TOOLBAR_ITEM_ORIENTATION_PROP,
- TOOLBAR_ITEM_WANT_LABEL_PROP
-};
-
-/**
- * Private functions, only availble from this file
- */
-static void ephy_navigation_button_class_init (EphyNavigationButtonClass *klass);
-static void ephy_navigation_button_init (EphyNavigationButton *tb);
-static void ephy_navigation_button_finalize_impl (GObject *o);
-static GtkWidget * ephy_navigation_button_get_widget_impl (EphyTbItem *i);
-static GdkPixbuf * ephy_navigation_button_get_icon_impl (EphyTbItem *i);
-static gchar * ephy_navigation_button_get_name_human_impl (EphyTbItem *i);
-static gchar * ephy_navigation_button_to_string_impl (EphyTbItem *i);
-static EphyTbItem * ephy_navigation_button_clone_impl (EphyTbItem *i);
-static void ephy_navigation_button_parse_properties_impl (EphyTbItem *i, const gchar *props);
-static void ephy_navigation_button_menu_activated_cb (EphyTbButton *w, EphyNavigationButton *b);
-static void ephy_navigation_button_clicked_cb (GtkWidget *w, EphyNavigationButton *b);
-
-
-static gpointer ephy_tb_item_class;
-
-/**
- * TbiZoom object
- */
-
-MAKE_GET_TYPE (ephy_navigation_button, "EphyNavigationButton", EphyNavigationButton,
- ephy_navigation_button_class_init,
- ephy_navigation_button_init, EPHY_TYPE_TBI);
-
-static void
-ephy_navigation_button_class_init (EphyNavigationButtonClass *klass)
-{
- G_OBJECT_CLASS (klass)->finalize = ephy_navigation_button_finalize_impl;
-
- EPHY_TB_ITEM_CLASS (klass)->get_widget = ephy_navigation_button_get_widget_impl;
- EPHY_TB_ITEM_CLASS (klass)->get_icon = ephy_navigation_button_get_icon_impl;
- EPHY_TB_ITEM_CLASS (klass)->get_name_human = ephy_navigation_button_get_name_human_impl;
- EPHY_TB_ITEM_CLASS (klass)->to_string = ephy_navigation_button_to_string_impl;
- EPHY_TB_ITEM_CLASS (klass)->clone = ephy_navigation_button_clone_impl;
- EPHY_TB_ITEM_CLASS (klass)->parse_properties = ephy_navigation_button_parse_properties_impl;
-
- ephy_tb_item_class = g_type_class_peek_parent (klass);
-}
-
-static void
-ephy_navigation_button_init (EphyNavigationButton *tbi)
-{
- EphyNavigationButtonPrivate *p = g_new0 (EphyNavigationButtonPrivate, 1);
- tbi->priv = p;
-
- p->direction = EPHY_NAVIGATION_DIRECTION_UP;
- p->show_arrow = TRUE;
- p->sensitive = TRUE;
-}
-
-EphyNavigationButton *
-ephy_navigation_button_new (void)
-{
- EphyNavigationButton *ret = g_object_new (EPHY_TYPE_NAVIGATION_BUTTON, NULL);
- return ret;
-}
-
-static void
-ephy_navigation_button_finalize_impl (GObject *o)
-{
- EphyNavigationButton *it = EPHY_NAVIGATION_BUTTON (o);
- EphyNavigationButtonPrivate *p = it->priv;
-
- if (p->widget)
- {
- g_object_unref (p->widget);
- }
-
- g_free (p);
-
- LOG ("EphyNavigationButton finalized")
-
- G_OBJECT_CLASS (ephy_tb_item_class)->finalize (o);
-}
-
-static void
-ephy_navigation_button_setup_widget (EphyNavigationButton *b)
-{
- EphyNavigationButtonPrivate *p = b->priv;
- const gchar *label;
- const gchar *tip;
- gboolean prio;
-
- if (!p->widget)
- {
- ephy_navigation_button_get_widget_impl (EPHY_TB_ITEM (b));
- }
- g_assert (EPHY_IS_TB_BUTTON (p->widget));
-
- switch (p->direction)
- {
- case EPHY_NAVIGATION_DIRECTION_UP:
- label = "gtk-go-up";
- tip = _("Go up");
- prio = FALSE;
- break;
- case EPHY_NAVIGATION_DIRECTION_BACK:
- label = "gtk-go-back";
- tip = _("Go back");
- prio = TRUE;
- break;
- case EPHY_NAVIGATION_DIRECTION_FORWARD:
- label = "gtk-go-forward";
- tip = _("Go forward");
- prio = FALSE;
- break;
- default:
- g_assert_not_reached ();
- label = NULL;
- tip = NULL;
- prio = FALSE;
- break;
- }
-
- ephy_tb_button_set_label (p->widget, label);
- ephy_tb_button_set_tooltip_text (p->widget, tip);
- ephy_tb_button_set_priority (p->widget, prio);
- ephy_tb_button_set_show_arrow (p->widget, p->show_arrow);
- ephy_tb_button_set_sensitivity (p->widget, p->sensitive);
-}
-
-static GtkWidget *
-ephy_navigation_button_get_widget_impl (EphyTbItem *i)
-{
- EphyNavigationButton *iz = EPHY_NAVIGATION_BUTTON (i);
- EphyNavigationButtonPrivate *p = iz->priv;
-
- if (!p->widget)
- {
- p->widget = ephy_tb_button_new ();
- g_object_ref (p->widget);
- ephy_tb_button_set_use_stock (p->widget, TRUE);
- ephy_tb_button_set_enable_menu (p->widget, TRUE);
-
- ephy_navigation_button_setup_widget (iz);
-
- gtk_widget_show (GTK_WIDGET (p->widget));
-
- g_signal_connect (p->widget, "menu-activated",
- G_CALLBACK (ephy_navigation_button_menu_activated_cb), i);
- g_signal_connect (ephy_tb_button_get_button (p->widget), "clicked",
- G_CALLBACK (ephy_navigation_button_clicked_cb), i);
- }
-
- return GTK_WIDGET (p->widget);
-}
-
-static GdkPixbuf *
-ephy_navigation_button_get_icon_impl (EphyTbItem *i)
-{
- EphyNavigationButtonPrivate *p = EPHY_NAVIGATION_BUTTON (i)->priv;
-
- static GdkPixbuf *pb_up = NULL;
- static GdkPixbuf *pb_back = NULL;
- static GdkPixbuf *pb_forward = NULL;
-
- if (!pb_up)
- {
- /* what's the easier way? */
- GtkWidget *b = gtk_button_new ();
- pb_up = gtk_widget_render_icon (b,
- GTK_STOCK_GO_UP,
- GTK_ICON_SIZE_SMALL_TOOLBAR,
- NULL);
- pb_back = gtk_widget_render_icon (b,
- GTK_STOCK_GO_BACK,
- GTK_ICON_SIZE_SMALL_TOOLBAR,
- NULL);
- pb_forward = gtk_widget_render_icon (b,
- GTK_STOCK_GO_FORWARD,
- GTK_ICON_SIZE_SMALL_TOOLBAR,
- NULL);
- gtk_widget_destroy (b);
- }
-
- switch (p->direction)
- {
- case EPHY_NAVIGATION_DIRECTION_BACK:
- return g_object_ref (pb_back);
- break;
- case EPHY_NAVIGATION_DIRECTION_FORWARD:
- return g_object_ref (pb_forward);
- break;
- case EPHY_NAVIGATION_DIRECTION_UP:
- return g_object_ref (pb_up);
- break;
- default:
- g_assert_not_reached ();
- return NULL;
- }
-}
-
-static gchar *
-ephy_navigation_button_get_name_human_impl (EphyTbItem *i)
-{
- EphyNavigationButtonPrivate *p = EPHY_NAVIGATION_BUTTON (i)->priv;
- const gchar *ret;
-
- switch (p->direction)
- {
- case EPHY_NAVIGATION_DIRECTION_BACK:
- ret = p->show_arrow
- ? _("Back (with menu)")
- : _("Back");
- break;
- case EPHY_NAVIGATION_DIRECTION_FORWARD:
- ret = p->show_arrow
- ? _("Forward (with menu)")
- : _("Forward");
- break;
- case EPHY_NAVIGATION_DIRECTION_UP:
- ret = p->show_arrow
- ? _("Up (with menu)")
- : _("Up");
- break;
- default:
- g_assert_not_reached ();
- ret = "Error: unexpected direction";
- break;
- }
-
- return g_strdup (ret);
-}
-
-static gchar *
-ephy_navigation_button_to_string_impl (EphyTbItem *i)
-{
- EphyNavigationButtonPrivate *p = EPHY_NAVIGATION_BUTTON (i)->priv;
-
- /* if it had any properties, the string should include them */
- const char *sdir;
-
- switch (p->direction)
- {
- case EPHY_NAVIGATION_DIRECTION_BACK:
- sdir = "back";
- break;
- case EPHY_NAVIGATION_DIRECTION_FORWARD:
- sdir = "forward";
- break;
- case EPHY_NAVIGATION_DIRECTION_UP:
- sdir = "up";
- break;
- default:
- g_assert_not_reached ();
- sdir = "unknown";
- }
-
- return g_strdup_printf ("%s=navigation_button(direction=%s,arrow=%s)",
- i->id, sdir, p->show_arrow ? "TRUE" : "FALSE");
-}
-
-static EphyTbItem *
-ephy_navigation_button_clone_impl (EphyTbItem *i)
-{
- EphyTbItem *ret = EPHY_TB_ITEM (ephy_navigation_button_new ());
- EphyNavigationButtonPrivate *p = EPHY_NAVIGATION_BUTTON (i)->priv;
-
- ephy_tb_item_set_id (ret, i->id);
-
- ephy_navigation_button_set_direction (EPHY_NAVIGATION_BUTTON (ret), p->direction);
- ephy_navigation_button_set_show_arrow (EPHY_NAVIGATION_BUTTON (ret), p->show_arrow);
-
- return ret;
-}
-
-static void
-ephy_navigation_button_parse_properties_impl (EphyTbItem *it, const gchar *props)
-{
- EphyNavigationButton *b = EPHY_NAVIGATION_BUTTON (it);
-
- /* we have two properties, the direction and the arrow */
- const gchar *direc_prop;
- const gchar *show_arrow_prop;
-
- direc_prop = strstr (props, "direction=");
- if (direc_prop)
- {
- direc_prop += strlen ("direction=");
- if (!strncmp (direc_prop, "back", 4))
- {
- ephy_navigation_button_set_direction (b, EPHY_NAVIGATION_DIRECTION_BACK);
- }
- else if (!strncmp (direc_prop, "forward", 4))
- {
- ephy_navigation_button_set_direction (b, EPHY_NAVIGATION_DIRECTION_FORWARD);
- }
- else if (!strncmp (direc_prop, "up", 2))
- {
- ephy_navigation_button_set_direction (b, EPHY_NAVIGATION_DIRECTION_UP);
- }
- }
-
- show_arrow_prop = strstr (props, "arrow=");
- if (show_arrow_prop)
- {
- show_arrow_prop += strlen ("arrow=");
- if (show_arrow_prop[0] == 'T')
- {
- ephy_navigation_button_set_show_arrow (b, TRUE);
- }
- else
- {
- ephy_navigation_button_set_show_arrow (b, FALSE);
- }
- }
-}
-
-
-void
-ephy_navigation_button_set_direction (EphyNavigationButton *b,
- EphyNavigationDirection d)
-{
- EphyNavigationButtonPrivate *p = b->priv;
- p->direction = d;
- ephy_navigation_button_setup_widget (b);
-}
-
-void
-ephy_navigation_button_set_show_arrow (EphyNavigationButton *b,
- gboolean value)
-{
- EphyNavigationButtonPrivate *p = b->priv;
- p->show_arrow = value;
- if (p->widget)
- {
- ephy_tb_button_set_show_arrow (p->widget, p->show_arrow);
- }
- else
- {
- ephy_navigation_button_get_widget_impl (EPHY_TB_ITEM (b));
- }
-}
-
-EphyNavigationDirection
-ephy_navigation_button_get_direction (EphyNavigationButton *b)
-{
- return b->priv->direction;
-}
-
-void
-ephy_navigation_button_set_sensitive (EphyNavigationButton *b, gboolean s)
-{
- EphyNavigationButtonPrivate *p = b->priv;
- p->sensitive = s;
- if (p->widget)
- {
- ephy_tb_button_set_sensitivity (p->widget, s);
- }
- else
- {
- ephy_navigation_button_get_widget_impl (EPHY_TB_ITEM (b));
- }
-}
-
-static void
-ephy_navigation_button_clicked_cb (GtkWidget *w, EphyNavigationButton *b)
-{
- EphyNavigationButtonPrivate *p = b->priv;
- EphyWindow *window;
- EphyEmbed *embed;
-
- window = ephy_tbi_get_window (EPHY_TBI (b));
- g_return_if_fail (window != NULL);
-
- embed = ephy_window_get_active_embed (window);
- g_return_if_fail (embed != NULL);
-
- switch (p->direction)
- {
- case EPHY_NAVIGATION_DIRECTION_UP:
- ephy_embed_go_up (embed);
- break;
- case EPHY_NAVIGATION_DIRECTION_BACK:
- ephy_embed_go_back (embed);
- break;
- case EPHY_NAVIGATION_DIRECTION_FORWARD:
- ephy_embed_go_forward (embed);
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-}
-
-/* TODO: clean all this, it came from toolbar.c and is messy */
-
-static GtkWidget *
-new_history_menu_item (gchar *origtext,
- const GdkPixbuf *ico)
-{
- GtkWidget *item = gtk_image_menu_item_new ();
- GtkWidget *hb = gtk_hbox_new (FALSE, 0);
- GtkWidget *label = gtk_label_new (origtext);
-
- gtk_box_pack_start (GTK_BOX (hb), label, FALSE, FALSE, 0);
- gtk_container_add (GTK_CONTAINER (item), hb);
-
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
- gtk_image_new_from_pixbuf ((GdkPixbuf *) ico));
-
- gtk_widget_show_all (item);
-
- return item;
-}
-
-static void
-activate_back_or_forward_menu_item_cb (GtkWidget *menu, EphyWindow *window)
-{
- EphyEmbed *embed;
- int go_nth;
-
- embed = ephy_window_get_active_embed (window);
- g_return_if_fail (embed != NULL);
-
- go_nth = (int)g_object_get_data (G_OBJECT(menu), "go_nth");
-
- ephy_embed_shistory_go_nth (embed, go_nth);
-}
-
-static void
-activate_up_menu_item_cb (GtkWidget *menu, EphyWindow *window)
-{
- EphyEmbed *embed;
- int go_nth;
- GSList *l;
- gchar *url;
-
- embed = ephy_window_get_active_embed (window);
- g_return_if_fail (embed != NULL);
-
- go_nth = (int)g_object_get_data (G_OBJECT(menu), "go_nth");
-
- ephy_embed_get_go_up_list (embed, &l);
-
- url = g_slist_nth_data (l, go_nth);
- if (url)
- {
- ephy_embed_load_url (embed, url);
- }
-
- g_slist_foreach (l, (GFunc) g_free, NULL);
- g_slist_free (l);
-}
-
-static void
-setup_back_or_forward_menu (EphyWindow *window, GtkMenuShell *ms, EphyNavigationDirection dir)
-{
- int pos, count;
- EphyEmbed *embed;
- int start, end;
-
- embed = ephy_window_get_active_embed (window);
- g_return_if_fail (embed != NULL);
-
- ephy_embed_shistory_get_pos (embed, &pos);
- ephy_embed_shistory_count (embed, &count);
-
- if (count == 0) return;
-
- if (dir == EPHY_NAVIGATION_DIRECTION_BACK)
- {
- start = pos - 1;
- end = -1;
- }
- else
- {
- start = pos + 1;
- end = count;
- }
-
- while (start != end)
- {
- char *title, *url;
- GtkWidget *item;
- ephy_embed_shistory_get_nth (embed, start, FALSE, &url, &title);
- item = new_history_menu_item (title ? title : url, NULL);
- gtk_menu_shell_append (ms, item);
- g_object_set_data (G_OBJECT (item), "go_nth", GINT_TO_POINTER (start));
- g_signal_connect (item, "activate",
- G_CALLBACK (activate_back_or_forward_menu_item_cb), window);
- gtk_widget_show_all (item);
-
- g_free (url);
- g_free (title);
-
- if (start < end)
- {
- start++;
- }
- else
- {
- start--;
- }
- }
-}
-
-static void
-setup_up_menu (EphyWindow *window, GtkMenuShell *ms)
-{
- EphyEmbed *embed;
- GSList *l;
- GSList *li;
- int count = 0;
-
- embed = ephy_window_get_active_embed (window);
- g_return_if_fail (embed != NULL);
-
- ephy_embed_get_go_up_list (embed, &l);
-
- for (li = l; li; li = li->next)
- {
- char *url = li->data;
- GtkWidget *item;
-
- item = new_history_menu_item (url, NULL);
- gtk_menu_shell_append (ms, item);
- g_object_set_data (G_OBJECT(item), "go_nth", GINT_TO_POINTER (count));
- g_signal_connect (item, "activate",
- G_CALLBACK (activate_up_menu_item_cb), window);
- gtk_widget_show_all (item);
- count ++;
- }
-
- g_slist_foreach (l, (GFunc) g_free, NULL);
- g_slist_free (l);
-}
-
-static void
-ephy_navigation_button_menu_activated_cb (EphyTbButton *w, EphyNavigationButton *b)
-{
- EphyNavigationButtonPrivate *p = b->priv;
- GtkMenuShell *ms = ephy_tb_button_get_menu (p->widget);
- EphyWindow *win = ephy_tbi_get_window (EPHY_TBI (b));
- GList *children;
- GList *li;
-
- children = gtk_container_get_children (GTK_CONTAINER (ms));
- for (li = children; li; li = li->next)
- {
- gtk_container_remove (GTK_CONTAINER (ms), li->data);
- }
- g_list_free (children);
-
- switch (p->direction)
- {
- case EPHY_NAVIGATION_DIRECTION_UP:
- setup_up_menu (win, ms);
- break;
- case EPHY_NAVIGATION_DIRECTION_FORWARD:
- case EPHY_NAVIGATION_DIRECTION_BACK:
- setup_back_or_forward_menu (win, ms, p->direction);
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-}
diff --git a/src/ephy-navigation-button.h b/src/ephy-navigation-button.h
deleted file mode 100644
index 036ec6d7e..000000000
--- a/src/ephy-navigation-button.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2002 Ricardo Fernández Pascual
- *
- * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef EPHY_NAVIGATION_BUTTON_H
-#define EPHY_NAVIGATION_BUTTON_H
-
-#include "ephy-tbi.h"
-
-G_BEGIN_DECLS
-
-/* object forward declarations */
-
-typedef struct _EphyNavigationButton EphyNavigationButton;
-typedef struct _EphyNavigationButtonClass EphyNavigationButtonClass;
-typedef struct _EphyNavigationButtonPrivate EphyNavigationButtonPrivate;
-
-/**
- * TbiZoom object
- */
-
-#define EPHY_TYPE_NAVIGATION_BUTTON (ephy_navigation_button_get_type())
-#define EPHY_NAVIGATION_BUTTON(object) (G_TYPE_CHECK_INSTANCE_CAST((object), \
- EPHY_TYPE_NAVIGATION_BUTTON, EphyNavigationButton))
-#define EPHY_NAVIGATION_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EPHY_TYPE_NAVIGATION_BUTTON,\
- EphyNavigationButtonClass))
-#define EPHY_IS_NAVIGATION_BUTTON(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), \
- EPHY_TYPE_NAVIGATION_BUTTON))
-#define EPHY_IS_NAVIGATION_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EPHY_TYPE_NAVIGATION_BUTTON))
-#define EPHY_NAVIGATION_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_NAVIGATION_BUTTON,\
- EphyNavigationButtonClass))
-
-typedef enum
-{
- EPHY_NAVIGATION_DIRECTION_UP,
- EPHY_NAVIGATION_DIRECTION_BACK,
- EPHY_NAVIGATION_DIRECTION_FORWARD
-} EphyNavigationDirection;
-
-struct _EphyNavigationButtonClass
-{
- EphyTbiClass parent_class;
-};
-
-/* Remember: fields are public read-only */
-struct _EphyNavigationButton
-{
- EphyTbi parent_object;
- EphyNavigationButtonPrivate *priv;
-};
-
-/* this class is abstract */
-
-GType ephy_navigation_button_get_type (void);
-EphyNavigationButton * ephy_navigation_button_new (void);
-void ephy_navigation_button_set_direction (EphyNavigationButton *a,
- EphyNavigationDirection d);
-void ephy_navigation_button_set_show_arrow (EphyNavigationButton *b,
- gboolean value);
-EphyNavigationDirection ephy_navigation_button_get_direction (EphyNavigationButton *b);
-void ephy_navigation_button_set_sensitive (EphyNavigationButton *b, gboolean s);
-
-G_END_DECLS
-
-#endif
diff --git a/src/ephy-shell.c b/src/ephy-shell.c
index feeb4d388..11954632d 100644
--- a/src/ephy-shell.c
+++ b/src/ephy-shell.c
@@ -509,6 +509,7 @@ ephy_shell_get_autocompletion (EphyShell *gs)
};
EphyHistory *gh = ephy_embed_shell_get_global_history (EPHY_EMBED_SHELL (gs));
+ EphyBookmarks *bmk = ephy_shell_get_bookmarks (gs);
EphyFilesystemAutocompletion *fa = ephy_filesystem_autocompletion_new ();
p->autocompletion = ephy_autocompletion_new ();
ephy_autocompletion_set_prefixes (p->autocompletion, prefixes);
@@ -518,7 +519,7 @@ ephy_shell_get_autocompletion (EphyShell *gs)
ephy_autocompletion_add_source (p->autocompletion,
EPHY_AUTOCOMPLETION_SOURCE (fa));
ephy_autocompletion_add_source (p->autocompletion,
- EPHY_AUTOCOMPLETION_SOURCE (gs->priv->bookmarks));
+ EPHY_AUTOCOMPLETION_SOURCE (bmk));
g_object_unref (gh);
g_object_unref (fa);
diff --git a/src/ephy-spinner-action.c b/src/ephy-spinner-action.c
new file mode 100644
index 000000000..3e990f49b
--- /dev/null
+++ b/src/ephy-spinner-action.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2003 Marco Pesenti Gritti
+ *
+ * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "ephy-spinner-action.h"
+#include "ephy-spinner.h"
+#include "eggtoolitem.h"
+
+static void ephy_spinner_action_init (EphySpinnerAction *action);
+static void ephy_spinner_action_class_init (EphySpinnerActionClass *class);
+
+struct EphySpinnerActionPrivate
+{
+ gboolean throbbing;
+};
+
+enum
+{
+ PROP_0,
+ PROP_THROBBING
+};
+
+static GObjectClass *parent_class = NULL;
+
+GType
+ephy_spinner_action_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EphySpinnerActionClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) ephy_spinner_action_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+ sizeof (EphySpinnerAction),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) ephy_spinner_action_init,
+ };
+
+ type = g_type_register_static (EGG_TYPE_ACTION,
+ "EphySpinnerAction",
+ &type_info, 0);
+ }
+ return type;
+}
+
+static void
+ephy_spinner_action_sync_throbbing (EggAction *action, GParamSpec *pspec,
+ GtkWidget *proxy)
+{
+ EphySpinner *spinner;
+
+ spinner = EPHY_SPINNER (g_object_get_data (G_OBJECT (proxy), "spinner"));
+
+ if (EPHY_SPINNER_ACTION (action)->priv->throbbing)
+ {
+ ephy_spinner_start (spinner);
+ }
+ else
+ {
+ ephy_spinner_stop (spinner);
+ }
+}
+
+static GtkWidget *
+create_tool_item (EggAction *action)
+{
+ GtkWidget *item;
+ GtkWidget *spinner;
+ GtkWidget *button;
+
+ item = (* EGG_ACTION_CLASS (parent_class)->create_tool_item) (action);
+
+ button = gtk_button_new ();
+ gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+ gtk_widget_show (button);
+ gtk_container_add (GTK_CONTAINER (item), button);
+ spinner = ephy_spinner_new ();
+ ephy_spinner_set_small_mode (EPHY_SPINNER (spinner), TRUE);
+ gtk_container_add (GTK_CONTAINER (button), spinner);
+ egg_tool_item_set_pack_end (EGG_TOOL_ITEM (item), TRUE);
+ egg_tool_item_set_homogeneous (EGG_TOOL_ITEM (item), FALSE);
+ gtk_widget_show (spinner);
+ g_object_set_data (G_OBJECT (item), "spinner", spinner);
+
+ return item;
+}
+
+static void
+connect_proxy (EggAction *action, GtkWidget *proxy)
+{
+ g_signal_connect_object (action, "notify::throbbing",
+ G_CALLBACK (ephy_spinner_action_sync_throbbing),
+ proxy, 0);
+
+ (* EGG_ACTION_CLASS (parent_class)->connect_proxy) (action, proxy);
+}
+static void
+ephy_spinner_action_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EphySpinnerAction *spin;
+
+ spin = EPHY_SPINNER_ACTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_THROBBING:
+ spin->priv->throbbing = g_value_get_boolean (value);
+ g_object_notify(object, "throbbing");
+ break;
+ }
+}
+
+static void
+ephy_spinner_action_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EphySpinnerAction *spin;
+
+ spin = EPHY_SPINNER_ACTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_THROBBING:
+ g_value_set_boolean (value, spin->priv->throbbing);
+ break;
+ }
+}
+
+static void
+ephy_spinner_action_class_init (EphySpinnerActionClass *class)
+{
+ EggActionClass *action_class;
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ parent_class = g_type_class_peek_parent (class);
+ action_class = EGG_ACTION_CLASS (class);
+
+ action_class->toolbar_item_type = EGG_TYPE_TOOL_ITEM;
+ action_class->create_tool_item = create_tool_item;
+ action_class->connect_proxy = connect_proxy;
+
+ object_class->set_property = ephy_spinner_action_set_property;
+ object_class->get_property = ephy_spinner_action_get_property;
+
+ g_object_class_install_property (object_class,
+ PROP_THROBBING,
+ g_param_spec_boolean ("throbbing",
+ "Throbbing",
+ "Throbbing",
+ FALSE,
+ G_PARAM_READWRITE));
+}
+
+static void
+ephy_spinner_action_init (EphySpinnerAction *action)
+{
+ action->priv = g_new0 (EphySpinnerActionPrivate, 1);
+}
diff --git a/src/ephy-spinner-action.h b/src/ephy-spinner-action.h
new file mode 100644
index 000000000..adb9d76c2
--- /dev/null
+++ b/src/ephy-spinner-action.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2003 Marco Pesenti Gritti
+ *
+ * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef EPHY_SPINNER_ACTION_H
+#define EPHY_SPINNER_ACTION_H
+
+#include <gtk/gtk.h>
+#include <egg-action.h>
+
+#define EPHY_TYPE_SPINNER_ACTION (ephy_spinner_action_get_type ())
+#define EPHY_SPINNER_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPHY_TYPE_SPINNER_ACTION, EphySpinnerAction))
+#define EPHY_SPINNER_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EPHY_TYPE_SPINNER_ACTION, EphySpinnerActionClass))
+#define EPHY_IS_SPINNER_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPHY_TYPE_SPINNER_ACTION))
+#define EPHY_IS_SPINNER_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EPHY_TYPE_SPINNER_ACTION))
+#define EPHY_SPINNER_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_SPINNER_ACTION, EphySpinnerActionClass))
+
+typedef struct _EphySpinnerAction EphySpinnerAction;
+typedef struct _EphySpinnerActionClass EphySpinnerActionClass;
+typedef struct EphySpinnerActionPrivate EphySpinnerActionPrivate;
+
+struct _EphySpinnerAction
+{
+ EggAction parent;
+ EphySpinnerActionPrivate *priv;
+};
+
+struct _EphySpinnerActionClass
+{
+ EggActionClass parent_class;
+};
+
+GType ephy_spinner_action_get_type (void);
+
+#endif
diff --git a/src/ephy-tab.c b/src/ephy-tab.c
index 7561bb476..98f04fad1 100644
--- a/src/ephy-tab.c
+++ b/src/ephy-tab.c
@@ -22,11 +22,11 @@
#include "ephy-tab.h"
#include "ephy-shell.h"
-#include "ephy-embed-popup-bw.h"
#include "eel-gconf-extensions.h"
#include "ephy-prefs.h"
#include "ephy-embed-prefs.h"
#include "ephy-debug.h"
+#include "egg-menu-merge.h"
#include <bonobo/bonobo-i18n.h>
#include <libgnomevfs/gnome-vfs-uri.h>
@@ -39,12 +39,15 @@
#include <gtk/gtkiconfactory.h>
#include <gtk/gtkstyle.h>
#include <gtk/gtkselection.h>
+#include <gtk/gtkmain.h>
+#include <gtk/gtkmenu.h>
#include <string.h>
struct EphyTabPrivate
{
EphyEmbed *embed;
EphyWindow *window;
+ EphyEmbedEvent *event;
gboolean is_active;
TabLoadStatus load_status;
char status_message[255];
@@ -195,6 +198,7 @@ ephy_tab_init (EphyTab *tab)
tab->priv->embed = ephy_embed_new (G_OBJECT(shell));
tab->priv->window = NULL;
+ tab->priv->event = NULL;
tab->priv->is_active = FALSE;
*tab->priv->status_message = '\0';
*tab->priv->link_message = '\0';
@@ -280,6 +284,11 @@ ephy_tab_finalize (GObject *object)
g_idle_remove_by_data (tab->priv->embed);
+ if (tab->priv->event)
+ {
+ g_object_unref (tab->priv->event);
+ }
+
g_free (tab->priv);
G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -346,6 +355,12 @@ ephy_tab_get_window (EphyTab *tab)
return tab->priv->window;
}
+EphyEmbedEvent *
+ephy_tab_get_event (EphyTab *tab)
+{
+ return tab->priv->event;
+}
+
static void
ephy_tab_update_color (EphyTab *tab)
{
@@ -813,24 +828,68 @@ ephy_tab_dom_mouse_click_cb (EphyEmbed *embed,
}
static void
+ephy_tab_set_event (EphyTab *tab,
+ EphyEmbedEvent *event)
+{
+ if (tab->priv->event) g_object_unref (tab->priv->event);
+ g_object_ref (event);
+ tab->priv->event = event;
+}
+
+static void
ephy_tab_show_embed_popup (EphyTab *tab, EphyEmbedEvent *event)
{
- EphyEmbedPopup *popup;
+ EmbedEventContext context;
+ const char *popup;
+ const GValue *value;
+ gboolean framed;
EphyWindow *window;
- EphyEmbed *embed;
+ char *path;
+ GtkWidget *widget;
window = ephy_tab_get_window (tab);
- embed = ephy_tab_get_embed (tab);
- popup = EPHY_EMBED_POPUP (ephy_window_get_popup_factory (window));
- ephy_embed_popup_set_event (popup, event);
- ephy_embed_popup_show (popup, embed);
+ ephy_embed_event_get_property (event, "framed_page", &value);
+ framed = g_value_get_int (value);
+
+ ephy_embed_event_get_context (event, &context);
+
+ if ((context & EMBED_CONTEXT_LINK) &&
+ (context & EMBED_CONTEXT_IMAGE))
+ {
+ popup = "EphyImageLinkPopup";
+ }
+ else if (context & EMBED_CONTEXT_LINK)
+ {
+ popup = "EphyLinkPopup";
+ }
+ else if (context & EMBED_CONTEXT_IMAGE)
+ {
+ popup = "EphyImagePopup";
+ }
+ else
+ {
+ popup = framed ? "EphyFramedDocumentPopup" :
+ "EphyDocumentPopup";
+ }
+
+ path = g_strconcat ("/popups/", popup, NULL);
+ g_print (path);
+ widget = egg_menu_merge_get_widget (EGG_MENU_MERGE (window->ui_merge),
+ path);
+ g_free (path);
+
+ g_return_if_fail (widget != NULL);
+
+ ephy_tab_set_event (tab, event);
+ gtk_menu_popup (GTK_MENU (widget), NULL, NULL, NULL, NULL, 2,
+ gtk_get_current_event_time ());
}
static gint
ephy_tab_dom_mouse_down_cb (EphyEmbed *embed,
- EphyEmbedEvent *event,
- EphyTab *tab)
+ EphyEmbedEvent *event,
+ EphyTab *tab)
{
EphyWindow *window;
int button;
diff --git a/src/ephy-tab.h b/src/ephy-tab.h
index fe679f553..82f6d16a6 100644
--- a/src/ephy-tab.h
+++ b/src/ephy-tab.h
@@ -102,6 +102,8 @@ void ephy_tab_get_size (EphyTab *tab,
void ephy_tab_update_control (EphyTab *tab,
TabControlID id);
+EphyEmbedEvent *ephy_tab_get_event (EphyTab *tab);
+
G_END_DECLS
#endif
diff --git a/src/ephy-tbi.c b/src/ephy-tbi.c
deleted file mode 100644
index 4a8993c46..000000000
--- a/src/ephy-tbi.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2002 Ricardo Fernández Pascual
- *
- * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "ephy-gobject-misc.h"
-#include "ephy-marshal.h"
-#include "ephy-bonobo-extensions.h"
-#include "ephy-tbi.h"
-#include "ephy-debug.h"
-
-#include <string.h>
-#include <libgnome/gnome-i18n.h>
-
-/**
- * Private data
- */
-struct _EphyTbiPrivate
-{
-};
-
-/**
- * Private functions, only availble from this file
- */
-static void ephy_tbi_class_init (EphyTbiClass *klass);
-static void ephy_tbi_init (EphyTbi *tb);
-static void ephy_tbi_finalize_impl (GObject *o);
-static GtkWidget * ephy_tbi_get_widget_impl (EphyTbItem *i);
-static GdkPixbuf * ephy_tbi_get_icon_impl (EphyTbItem *i);
-static gchar * ephy_tbi_get_name_human_impl (EphyTbItem *i);
-static gchar * ephy_tbi_to_string_impl (EphyTbItem *i);
-static gboolean ephy_tbi_is_unique_impl (EphyTbItem *i);
-static EphyTbItem * ephy_tbi_clone_impl (EphyTbItem *i);
-static void ephy_tbi_parse_properties_impl (EphyTbItem *i, const gchar *props);
-static void ephy_tbi_add_to_bonobo_tb_impl (EphyTbItem *i,
- BonoboUIComponent *ui,
- const char *container_path,
- guint index);
-
-
-static gpointer ephy_tb_item_class;
-
-/**
- * EphyTbi object
- */
-
-MAKE_GET_TYPE (ephy_tbi, "EphyTbi", EphyTbi, ephy_tbi_class_init,
- ephy_tbi_init, EPHY_TYPE_TB_ITEM);
-
-static void
-ephy_tbi_class_init (EphyTbiClass *klass)
-{
- G_OBJECT_CLASS (klass)->finalize = ephy_tbi_finalize_impl;
-
- EPHY_TB_ITEM_CLASS (klass)->get_widget = ephy_tbi_get_widget_impl;
- EPHY_TB_ITEM_CLASS (klass)->get_icon = ephy_tbi_get_icon_impl;
- EPHY_TB_ITEM_CLASS (klass)->get_name_human = ephy_tbi_get_name_human_impl;
- EPHY_TB_ITEM_CLASS (klass)->to_string = ephy_tbi_to_string_impl;
- EPHY_TB_ITEM_CLASS (klass)->is_unique = ephy_tbi_is_unique_impl;
- EPHY_TB_ITEM_CLASS (klass)->clone = ephy_tbi_clone_impl;
- EPHY_TB_ITEM_CLASS (klass)->parse_properties = ephy_tbi_parse_properties_impl;
- EPHY_TB_ITEM_CLASS (klass)->add_to_bonobo_tb = ephy_tbi_add_to_bonobo_tb_impl;
-
- ephy_tb_item_class = g_type_class_peek_parent (klass);
-}
-
-static void
-ephy_tbi_init (EphyTbi *tbi)
-{
- tbi->window = NULL;
-}
-
-static void
-ephy_tbi_finalize_impl (GObject *o)
-{
- EphyTbi *it = EPHY_TBI (o);
-
- if (it->window)
- {
- g_object_remove_weak_pointer (G_OBJECT (it->window),
- (gpointer *) &it->window);
- }
-
- LOG ("EphyTbi finalized")
-
- G_OBJECT_CLASS (ephy_tb_item_class)->finalize (o);
-}
-
-static GtkWidget *
-ephy_tbi_get_widget_impl (EphyTbItem *i)
-{
- /* this class is abstract */
- g_assert_not_reached ();
-
- return NULL;
-}
-
-static GdkPixbuf *
-ephy_tbi_get_icon_impl (EphyTbItem *i)
-{
- return NULL;
-}
-
-static gchar *
-ephy_tbi_get_name_human_impl (EphyTbItem *i)
-{
- /* this class is abstract */
- g_assert_not_reached ();
-
- return NULL;
-}
-
-static gchar *
-ephy_tbi_to_string_impl (EphyTbItem *i)
-{
- /* this class is abstract */
- g_assert_not_reached ();
-
- return NULL;
-}
-
-static gboolean
-ephy_tbi_is_unique_impl (EphyTbItem *i)
-{
- return TRUE;
-}
-
-static EphyTbItem *
-ephy_tbi_clone_impl (EphyTbItem *i)
-{
- /* you can't clone this directly because this class is abstract */
- g_assert_not_reached ();
- return NULL;
-}
-
-static void
-ephy_tbi_add_to_bonobo_tb_impl (EphyTbItem *i, BonoboUIComponent *ui,
- const char *container_path, guint index)
-{
- GtkWidget *w = ephy_tb_item_get_widget (i);
- gtk_widget_show (w);
- ephy_bonobo_add_numbered_widget (ui, w, index, container_path);
-}
-
-static void
-ephy_tbi_parse_properties_impl (EphyTbItem *it, const gchar *props)
-{
- /* we have no properties */
-}
-
-void
-ephy_tbi_set_window (EphyTbi *it, EphyWindow *w)
-{
- if (it->window)
- {
- g_object_remove_weak_pointer (G_OBJECT (it->window),
- (gpointer *) &it->window);
- }
-
- it->window = w;
-
- if (it->window)
- {
- g_object_add_weak_pointer (G_OBJECT (it->window),
- (gpointer *) &it->window);
- }
-}
-
-EphyWindow *
-ephy_tbi_get_window (EphyTbi *tbi)
-{
- return tbi->window;
-}
-
diff --git a/src/ephy-tbi.h b/src/ephy-tbi.h
deleted file mode 100644
index 2296a144f..000000000
--- a/src/ephy-tbi.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2002 Ricardo Fernández Pascual
- *
- * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef EPHY_TBI_H
-#define EPHY_TBI_H
-
-#include "ephy-toolbar-item.h"
-#include "ephy-window.h"
-
-G_BEGIN_DECLS
-
-/* object forward declarations */
-
-typedef struct _EphyTbi EphyTbi;
-typedef struct _EphyTbiClass EphyTbiClass;
-typedef struct _EphyTbiPrivate EphyTbiPrivate;
-
-/**
- * Tbi object
- */
-
-#define EPHY_TYPE_TBI (ephy_tbi_get_type())
-#define EPHY_TBI(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EPHY_TYPE_TBI,\
- EphyTbi))
-#define EPHY_TBI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EPHY_TYPE_TBI,\
- EphyTbiClass))
-#define EPHY_IS_TBI_(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EPHY_TYPE_TBI))
-#define EPHY_IS_TBI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EPHY_TYPE_TBI))
-#define EPHY_TBI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_TBI,\
- EphyTbiClass))
-
-struct _EphyTbiClass
-{
- EphyTbItemClass parent_class;
-
-};
-
-/* Remember: fields are public read-only */
-struct _EphyTbi
-{
- EphyTbItem parent_object;
-
- EphyWindow *window;
-};
-
-/* this class is abstract */
-
-GType ephy_tbi_get_type (void);
-EphyTbi * ephy_tbi_new (void);
-void ephy_tbi_set_window (EphyTbi *tbi, EphyWindow *w);
-EphyWindow * ephy_tbi_get_window (EphyTbi *tbi);
-
-G_END_DECLS
-
-#endif
diff --git a/src/ephy-window.c b/src/ephy-window.c
index 455602244..8cca7ba26 100644
--- a/src/ephy-window.c
+++ b/src/ephy-window.c
@@ -24,123 +24,250 @@
#include "ephy-favorites-menu.h"
#include "ephy-state.h"
#include "ephy-gobject-misc.h"
-#include "statusbar.h"
-#include "toolbar.h"
#include "ppview-toolbar.h"
#include "window-commands.h"
#include "find-dialog.h"
#include "history-dialog.h"
-#include "popup-commands.h"
#include "ephy-shell.h"
-#include "ephy-bonobo-extensions.h"
#include "eel-gconf-extensions.h"
#include "ephy-prefs.h"
#include "ephy-embed-utils.h"
#include "ephy-debug.h"
+#include "ephy-file-helpers.h"
+#include "statusbar.h"
+#include "toolbar.h"
+#include "popup-commands.h"
#include <string.h>
-#include <bonobo/bonobo-window.h>
-#include <bonobo/bonobo-i18n.h>
-#include <bonobo/bonobo-ui-util.h>
-#include <bonobo/bonobo-ui-component.h>
+#include <libgnome/gnome-i18n.h>
#include <libgnomevfs/gnome-vfs-uri.h>
#include <gtk/gtk.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>
+#include "egg-action-group.h"
+#include "egg-menu-merge.h"
#define CHARSET_MENU_PATH "/menu/View/EncodingMenuPlaceholder"
#define GO_FAVORITES_PATH "/menu/Go/Favorites"
-#define GO_BACK_CMD_PATH "/commands/GoBack"
-#define GO_FORWARD_CMD_PATH "/commands/GoForward"
-#define GO_UP_CMD_PATH "/commands/GoUp"
-#define EDIT_FIND_NEXT_CMD_PATH "/commands/EditFindNext"
-#define EDIT_FIND_PREV_CMD_PATH "/commands/EditFindPrev"
-#define VIEW_MENUBAR_PATH "/commands/View Menubar"
-#define VIEW_STATUSBAR_PATH "/commands/View Statusbar"
-#define VIEW_TOOLBAR_PATH "/commands/View Toolbar"
-#define VIEW_BOOKMARKSBAR_PATH "/commands/View BookmarksBar"
-#define VIEW_FULLSCREEN_PATH "/commands/View Fullscreen"
-
-#define ID_VIEW_MENUBAR "View Menubar"
-#define ID_VIEW_STATUSBAR "View Statusbar"
-#define ID_VIEW_TOOLBAR "View Toolbar"
-#define ID_VIEW_BOOKMARKSBAR "View BookmarksBar"
-#define ID_VIEW_FULLSCREEN "View Fullscreen"
-
-static BonoboUIVerb ephy_verbs [] = {
- BONOBO_UI_VERB ("EditFind", (BonoboUIVerbFn)window_cmd_edit_find),
- BONOBO_UI_VERB ("FilePrint", (BonoboUIVerbFn)window_cmd_file_print),
- BONOBO_UI_VERB ("GoStop", (BonoboUIVerbFn)window_cmd_go_stop),
- BONOBO_UI_VERB ("GoReload", (BonoboUIVerbFn)window_cmd_go_reload),
- BONOBO_UI_VERB ("GoBack", (BonoboUIVerbFn)window_cmd_go_back),
- BONOBO_UI_VERB ("GoForward", (BonoboUIVerbFn)window_cmd_go_forward),
- BONOBO_UI_VERB ("GoGo", (BonoboUIVerbFn)window_cmd_go_go),
- BONOBO_UI_VERB ("GoUp", (BonoboUIVerbFn)window_cmd_go_up),
- BONOBO_UI_VERB ("GoHome", (BonoboUIVerbFn)window_cmd_go_home),
- BONOBO_UI_VERB ("GoMyportal", (BonoboUIVerbFn)window_cmd_go_myportal),
- BONOBO_UI_VERB ("GoLocation", (BonoboUIVerbFn)window_cmd_go_location),
- BONOBO_UI_VERB ("FileNew", (BonoboUIVerbFn)window_cmd_new),
- BONOBO_UI_VERB ("FileNewWindow", (BonoboUIVerbFn)window_cmd_new_window),
- BONOBO_UI_VERB ("FileNewTab", (BonoboUIVerbFn)window_cmd_new_tab),
- BONOBO_UI_VERB ("FileOpen", (BonoboUIVerbFn)window_cmd_file_open),
- BONOBO_UI_VERB ("FileSaveAs", (BonoboUIVerbFn)window_cmd_file_save_as),
- BONOBO_UI_VERB ("FileCloseTab", (BonoboUIVerbFn)window_cmd_file_close_tab),
- BONOBO_UI_VERB ("FileCloseWindow", (BonoboUIVerbFn)window_cmd_file_close_window),
- BONOBO_UI_VERB ("FileSendTo", (BonoboUIVerbFn)window_cmd_file_send_to),
- BONOBO_UI_VERB ("EditCut", (BonoboUIVerbFn)window_cmd_edit_cut),
- BONOBO_UI_VERB ("EditCopy", (BonoboUIVerbFn)window_cmd_edit_copy),
- BONOBO_UI_VERB ("EditPaste", (BonoboUIVerbFn)window_cmd_edit_paste),
- BONOBO_UI_VERB ("EditSelectAll", (BonoboUIVerbFn)window_cmd_edit_select_all),
- BONOBO_UI_VERB ("EditPrefs", (BonoboUIVerbFn)window_cmd_edit_prefs),
- BONOBO_UI_VERB ("SettingsToolbarEditor", (BonoboUIVerbFn)window_cmd_settings_toolbar_editor),
- BONOBO_UI_VERB ("Zoom In", (BonoboUIVerbFn)window_cmd_view_zoom_in),
- BONOBO_UI_VERB ("EditFindNext", (BonoboUIVerbFn)window_cmd_edit_find_next),
- BONOBO_UI_VERB ("EditFindPrev", (BonoboUIVerbFn)window_cmd_edit_find_prev),
- BONOBO_UI_VERB ("Zoom Out", (BonoboUIVerbFn)window_cmd_view_zoom_out),
- BONOBO_UI_VERB ("Zoom Normal", (BonoboUIVerbFn)window_cmd_view_zoom_normal),
- BONOBO_UI_VERB ("ViewPageSource", (BonoboUIVerbFn)window_cmd_view_page_source),
- BONOBO_UI_VERB ("BookmarksAddDefault", (BonoboUIVerbFn)window_cmd_bookmarks_add_default),
- BONOBO_UI_VERB ("BookmarksEdit", (BonoboUIVerbFn)window_cmd_bookmarks_edit),
- BONOBO_UI_VERB ("ToolsHistory", (BonoboUIVerbFn)window_cmd_tools_history),
- BONOBO_UI_VERB ("ToolsPDM", (BonoboUIVerbFn)window_cmd_tools_pdm),
- BONOBO_UI_VERB ("TabsNext", (BonoboUIVerbFn)window_cmd_tabs_next),
- BONOBO_UI_VERB ("TabsPrevious", (BonoboUIVerbFn)window_cmd_tabs_previous),
- BONOBO_UI_VERB ("TabsMoveLeft", (BonoboUIVerbFn)window_cmd_tabs_move_left),
- BONOBO_UI_VERB ("TabsMoveRight", (BonoboUIVerbFn)window_cmd_tabs_move_right),
- BONOBO_UI_VERB ("TabsDetach", (BonoboUIVerbFn)window_cmd_tabs_detach),
- BONOBO_UI_VERB ("HelpContents", (BonoboUIVerbFn)window_cmd_help_manual),
- BONOBO_UI_VERB ("About", (BonoboUIVerbFn)window_cmd_help_about),
-
- BONOBO_UI_VERB_END
+#define GO_BACK_ACTION "GoBack"
+#define GO_FORWARD_ACTION "GoForward"
+#define GO_UP_ACTION "GoUp"
+#define EDIT_FIND_NEXT_ACTION "EditFindNext"
+#define EDIT_FIND_PREV_ACTION "EditFindPrev"
+#define VIEW_STATUSBAR_ACTION "ViewStatusbar"
+#define VIEW_TOOLBAR_ACTION "ViewToolbar"
+#define VIEW_FULLSCREEN_ACTION "ViewFullscreen"
+
+static EggActionGroupEntry ephy_menu_entries [] = {
+
+ /* Toplevel */
+ { "File", N_("_File"), NULL, NULL, NULL, NULL, NULL },
+ { "Edit", N_("_Edit"), NULL, NULL, NULL, NULL, NULL },
+ { "View", N_("_View"), NULL, NULL, NULL, NULL, NULL },
+ { "Go", N_("_Go"), NULL, NULL, NULL, NULL, NULL },
+ { "Tabs", N_("_Tabs"), NULL, NULL, NULL, NULL, NULL },
+ { "Help", N_("_Help"), NULL, NULL, NULL, NULL, NULL },
+
+ /* File menu */
+ { "FileNewWindow", N_("_New Window"), GTK_STOCK_NEW, "<control>N",
+ N_("Create a new window"),
+ G_CALLBACK (window_cmd_file_new_window), NULL },
+ { "FileNewTab", N_("New _Tab"), NULL, "<shift><control>N",
+ N_("Create a new tab"),
+ G_CALLBACK (window_cmd_file_new_tab), NULL },
+ { "FileOpen", N_("_Open..."), GTK_STOCK_OPEN, "<control>O",
+ N_("Open a file"),
+ G_CALLBACK (window_cmd_file_open), NULL },
+ { "FileSaveAs", N_("Save _As..."), GTK_STOCK_SAVE, "<shift><control>S",
+ N_("Save the current page"),
+ G_CALLBACK (window_cmd_file_save_as), NULL },
+ { "FilePrint", N_("_Print..."), GTK_STOCK_PRINT, "<control>P",
+ N_("Print the current page"),
+ G_CALLBACK (window_cmd_file_print), NULL },
+ { "FileSendTo", N_("S_end To..."), NULL, NULL,
+ N_("Send a link of the current page"),
+ G_CALLBACK (window_cmd_file_send_to), NULL },
+ { "FileAddBookmark", N_("_Add Bookmark..."), GTK_STOCK_ADD, "<control>D",
+ N_("Add a bookmark for the current page"),
+ G_CALLBACK (window_cmd_file_add_bookmark), NULL },
+ { "FileCloseTab", N_("_Close Tab"), GTK_STOCK_CLOSE, "<control>W",
+ N_("Send a link of the current page"),
+ G_CALLBACK (window_cmd_file_close_tab), NULL },
+ { "FileCloseWindow", N_("Close _Window"), NULL, "<shift><control>W",
+ N_("Send a link of the current page"),
+ G_CALLBACK (window_cmd_file_close_window), NULL },
+
+ /* Edit menu */
+ { "EditCut", N_("Cu_t"), GTK_STOCK_CUT, "<control>X",
+ N_("Cut the selection"),
+ G_CALLBACK (window_cmd_edit_cut), NULL },
+ { "EditCopy", N_("_Copy"), GTK_STOCK_COPY, "<control>C",
+ N_("Copy the selection"),
+ G_CALLBACK (window_cmd_edit_copy), NULL },
+ { "EditPaste", N_("_Paste"), GTK_STOCK_PASTE, "<control>V",
+ N_("Paste clipboard"),
+ G_CALLBACK (window_cmd_edit_paste), NULL },
+ { "EditSelectAll", N_("Select _All"), NULL, "<control>A",
+ N_("Select the entire page"),
+ G_CALLBACK (window_cmd_edit_select_all), NULL },
+ { "EditFind", N_("_Find"), GTK_STOCK_FIND, "<control>F",
+ N_("Find a string"),
+ G_CALLBACK (window_cmd_edit_find), NULL },
+ { "EditFindNext", N_("Find Ne_xt"), NULL, "<control>G",
+ N_("Find next occurence of the string"),
+ G_CALLBACK (window_cmd_edit_find_next), NULL },
+ { "EditFindPrev", N_("Find Pre_vious"), NULL, "<shift><control>G",
+ N_("Find previous occurence of the string"),
+ G_CALLBACK (window_cmd_edit_find_prev), NULL },
+ { "EditPersonalData", N_("P_ersonal Data"), NULL, "<control>F",
+ N_("View and remove cookies and passwords"),
+ G_CALLBACK (window_cmd_edit_personal_data), NULL },
+ { "EditToolbar", N_("T_oolbars"), NULL, NULL,
+ N_("Costumize toolbars"),
+ G_CALLBACK (window_cmd_edit_toolbar), NULL },
+ { "EditPrefs", N_("P_references"), GTK_STOCK_PREFERENCES, NULL,
+ N_("Configure the web browser"),
+ G_CALLBACK (window_cmd_edit_prefs), NULL },
+
+ /* View menu */
+ { "ViewStop", N_("_Stop"), GTK_STOCK_STOP, "Escape",
+ N_("Stop current data transfer"),
+ G_CALLBACK (window_cmd_view_stop), NULL },
+ { "ViewReload", N_("_Reload"), GTK_STOCK_REFRESH, "<control>R",
+ N_("Display the latest content of the current page"),
+ G_CALLBACK (window_cmd_view_reload), NULL },
+ { "ViewStatusbar", N_("St_atusbar"), NULL, NULL,
+ N_("Show or hide statusbar"),
+ G_CALLBACK (window_cmd_view_statusbar), NULL, TOGGLE_ACTION },
+ { "ViewFullscreen", N_("_Fullscreen"), NULL, NULL,
+ N_("Browse at full screen"),
+ G_CALLBACK (window_cmd_view_fullscreen), NULL, TOGGLE_ACTION},
+ { "ViewZoomIn", N_("Zoom _In"), GTK_STOCK_ZOOM_IN, "<control>plus",
+ N_("Show the contents in more detail"),
+ G_CALLBACK (window_cmd_view_zoom_in), NULL },
+ { "ViewZoomOut", N_("Zoom _Out"), GTK_STOCK_ZOOM_OUT, "<control>minus",
+ N_("Show the contents in less detail"),
+ G_CALLBACK (window_cmd_view_zoom_out), NULL },
+ { "ViewZoomNormal", N_("_Normal Size"), GTK_STOCK_ZOOM_100, NULL,
+ N_("Show the contents at the normal size"),
+ G_CALLBACK (window_cmd_view_zoom_normal), NULL },
+ { "ViewPageSource", N_("_Page Source"), NULL, NULL,
+ N_("View the source code of the page"),
+ G_CALLBACK (window_cmd_view_page_source), NULL },
+
+ /* Go menu */
+ { "GoBack", N_("_Back"), GTK_STOCK_GO_BACK, "<alt>left",
+ N_("Go to the previous visited page"),
+ G_CALLBACK (window_cmd_go_back), NULL },
+ { "GoForward", N_("_Forward"), GTK_STOCK_GO_FORWARD, "<alt>right",
+ N_("Go to the next visited page"),
+ G_CALLBACK (window_cmd_go_forward), NULL },
+ { "GoUp", N_("_Up"), GTK_STOCK_GO_UP, "<alt>up",
+ N_("Go up one level"),
+ G_CALLBACK (window_cmd_go_up), NULL },
+ { "GoHome", N_("_Home"), GTK_STOCK_HOME, "<alt>home",
+ N_("Go to the home page"),
+ G_CALLBACK (window_cmd_go_home), NULL },
+ { "GoLocation", N_("_Location..."), NULL, "<control>L",
+ N_("Go to a specified location"),
+ G_CALLBACK (window_cmd_go_location), NULL },
+ { "GoHistory", N_("_History"), NULL, "<control>H",
+ N_("Go to an already visited page"),
+ G_CALLBACK (window_cmd_go_history), NULL },
+ { "GoBookmarks", N_("_Bookmarks"), NULL, "<control>B",
+ N_("Go to a bookmark"),
+ G_CALLBACK (window_cmd_go_bookmarks), NULL },
+
+ /* Tabs menu */
+ { "TabsPrevious", N_("_Previous Tab"), NULL, "<control>page_up",
+ N_("Activate previous tab"),
+ G_CALLBACK (window_cmd_tabs_previous), NULL },
+ { "TabsNext", N_("_Next Tab"), NULL, "<control>page_down",
+ N_("Activate next tab"),
+ G_CALLBACK (window_cmd_tabs_next), NULL },
+ { "TabsMoveLeft", N_("Move Tab _Left"), NULL, "<shift><control>page_up",
+ N_("Move current tab to left"),
+ G_CALLBACK (window_cmd_tabs_move_left), NULL },
+ { "TabsMoveRight", N_("Move Tab _Right"), NULL, "<shift><control>page_up",
+ N_("Move current tab to right"),
+ G_CALLBACK (window_cmd_tabs_move_right), NULL },
+ { "TabsDetach", N_("_Detach Tab"), NULL, "<shift><control>M",
+ N_("Detach current tab"),
+ G_CALLBACK (window_cmd_tabs_detach), NULL },
+
+ /* Help menu */
+ { "HelpAbout", N_("_About"), NULL, NULL,
+ N_("Display credits for the web browser creators"),
+ G_CALLBACK (window_cmd_help_about), NULL },
};
-
-static BonoboUIVerb ephy_popup_verbs [] = {
- BONOBO_UI_VERB ("EPOpenInNewWindow", (BonoboUIVerbFn)popup_cmd_new_window),
- BONOBO_UI_VERB ("EPOpenInNewTab", (BonoboUIVerbFn)popup_cmd_new_tab),
- BONOBO_UI_VERB ("EPAddBookmark", (BonoboUIVerbFn)popup_cmd_add_bookmark),
- BONOBO_UI_VERB ("EPOpenImageInNewWindow", (BonoboUIVerbFn)popup_cmd_image_in_new_window),
- BONOBO_UI_VERB ("EPOpenImageInNewTab", (BonoboUIVerbFn)popup_cmd_image_in_new_tab),
- BONOBO_UI_VERB ("DPOpenFrameInNewWindow", (BonoboUIVerbFn)popup_cmd_frame_in_new_window),
- BONOBO_UI_VERB ("DPOpenFrameInNewTab", (BonoboUIVerbFn)popup_cmd_frame_in_new_tab),
- BONOBO_UI_VERB ("DPAddFrameBookmark", (BonoboUIVerbFn)popup_cmd_add_frame_bookmark),
- BONOBO_UI_VERB ("DPViewSource", (BonoboUIVerbFn)popup_cmd_view_source),
-
- BONOBO_UI_VERB_END
+static guint ephy_menu_n_entries = G_N_ELEMENTS (ephy_menu_entries);
+
+static EggActionGroupEntry ephy_popups_entries [] = {
+ /* Toplevel */
+ { "FakeToplevel", (""), NULL, NULL, NULL, NULL, NULL },
+
+ /* Document */
+ { "SaveBackgroundAs", N_("Save Background As..."), NULL, NULL,
+ NULL, G_CALLBACK (popup_cmd_save_background_as), NULL },
+ { "CopyPageLocation", N_("Copy Page Location"), GTK_STOCK_COPY, NULL,
+ NULL, G_CALLBACK (popup_cmd_copy_page_location), NULL },
+
+ /* Framed document */
+ { "OpenFrame", N_("Open Frame"), NULL, NULL,
+ NULL, G_CALLBACK (popup_cmd_open_frame), NULL },
+ { "OpenFrameInNewWindow", N_("Open Frame in New Window"), NULL, NULL,
+ NULL, G_CALLBACK (popup_cmd_frame_in_new_window), NULL },
+ { "OpenFrameInNewTab", N_("Open Frame in New Tab"), NULL, NULL,
+ NULL, G_CALLBACK (popup_cmd_frame_in_new_tab), NULL },
+
+ /* Links */
+ { "OpenLink", N_("Open Link"), GTK_STOCK_OPEN, NULL,
+ NULL, G_CALLBACK (popup_cmd_open_link), NULL },
+ { "OpenLinkInNewWindow", N_("Open Link in New Window"), NULL, NULL,
+ NULL, G_CALLBACK (popup_cmd_link_in_new_window), NULL },
+ { "OpenLinkInNewTab", N_("Open Link in New Tab"), NULL, NULL,
+ NULL, G_CALLBACK (popup_cmd_link_in_new_tab), NULL },
+ { "DownloadLink", N_("Download Link"), GTK_STOCK_SAVE, NULL,
+ NULL, G_CALLBACK (popup_cmd_download_link), NULL },
+ { "AddLinkBookmark", N_("Add Bookmark"), GTK_STOCK_ADD, NULL,
+ NULL, G_CALLBACK (popup_cmd_add_link_bookmark), NULL },
+ { "CopyLinkLocation", N_("Copy Link Location"), NULL, NULL,
+ NULL, G_CALLBACK (popup_cmd_copy_link_location), NULL },
+ { "CopyEmail", N_("Copy Email"), NULL, NULL,
+ NULL, G_CALLBACK (popup_cmd_copy_email), NULL },
+
+ /* Images */
+ { "OpenImage", N_("Open Image"), GTK_STOCK_OPEN, NULL,
+ NULL, G_CALLBACK (popup_cmd_open_image), NULL },
+ { "OpenImageInNewWindow", N_("Open Image in New Window"), NULL, NULL,
+ NULL, G_CALLBACK (popup_cmd_image_in_new_window), NULL },
+ { "OpenImageInNewTab", N_("Open Image in New Tab"), NULL, NULL,
+ NULL, G_CALLBACK (popup_cmd_image_in_new_tab), NULL },
+ { "SaveImageAs", N_("Save Image As..."), GTK_STOCK_SAVE_AS, NULL,
+ NULL, G_CALLBACK (popup_cmd_save_image_as), NULL },
+ { "SetImageAsBackground", N_("Use Image as Background"), NULL, NULL,
+ NULL, G_CALLBACK (popup_cmd_set_image_as_background), NULL },
+ { "CopyImageLocation", N_("Copy Image Location"), GTK_STOCK_COPY, NULL,
+ NULL, G_CALLBACK (popup_cmd_copy_image_location), NULL },
};
+static guint ephy_popups_n_entries = G_N_ELEMENTS (ephy_popups_entries);
struct EphyWindowPrivate
{
+ GtkWidget *main_vbox;
+ GtkWidget *menubar;
+ Toolbar *toolbar;
+ GtkWidget *statusbar;
+ EggActionGroup *action_group;
+ EggActionGroup *popups_action_group;
EphyFavoritesMenu *fav_menu;
PPViewToolbar *ppview_toolbar;
- Toolbar *toolbar;
- Statusbar *statusbar;
GtkNotebook *notebook;
EphyTab *active_tab;
GtkWidget *sidebar;
- EphyEmbedPopupBW *embed_popup;
EphyDialog *find_dialog;
EphyDialog *history_dialog;
EphyDialog *history_sidebar;
@@ -191,7 +318,7 @@ ephy_window_get_type (void)
(GInstanceInitFunc) ephy_window_init
};
- ephy_window_type = g_type_register_static (BONOBO_TYPE_WINDOW,
+ ephy_window_type = g_type_register_static (GTK_TYPE_WINDOW,
"EphyWindow",
&our_info, 0);
}
@@ -212,8 +339,7 @@ ephy_window_class_init (EphyWindowClass *klass)
widget_class->show = ephy_window_show;
}
-static
-gboolean
+static gboolean
ephy_window_key_press_event_cb (GtkWidget *widget,
GdkEventKey *event,
EphyWindow *window)
@@ -287,63 +413,75 @@ ephy_window_state_event_cb (GtkWidget *widget,
}
static void
-setup_bonobo_window (EphyWindow *window,
- BonoboUIComponent **ui_component)
+add_widget (EggMenuMerge *merge, GtkWidget *widget, EphyWindow *window)
+{
+ if (GTK_IS_MENU_SHELL (widget))
+ {
+ window->priv->menubar = widget;
+ }
+
+ gtk_box_pack_start (GTK_BOX (window->priv->main_vbox),
+ widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+}
+
+static void
+setup_window (EphyWindow *window)
{
- BonoboWindow *win = BONOBO_WINDOW(window);
- BonoboUIContainer *container;
- Bonobo_UIContainer corba_container;
+ EggActionGroup *action_group;
+ EggMenuMerge *merge;
+ int i;
+
+ window->priv->main_vbox = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (window->priv->main_vbox);
+ gtk_container_add (GTK_CONTAINER (window),
+ window->priv->main_vbox);
+
+ for (i = 0; i < ephy_menu_n_entries; i++)
+ {
+ ephy_menu_entries[i].user_data = window;
+ }
- container = bonobo_window_get_ui_container (win);
+ for (i = 0; i < ephy_popups_n_entries; i++)
+ {
+ ephy_popups_entries[i].user_data = window;
+ }
- bonobo_ui_engine_config_set_path (bonobo_window_get_ui_engine (win),
- "/apps/ephy/UIConfig/kvps");
+ merge = egg_menu_merge_new ();
- corba_container = BONOBO_OBJREF (container);
+ action_group = egg_action_group_new ("WindowActions");
+ egg_action_group_add_actions (action_group, ephy_menu_entries,
+ ephy_menu_n_entries);
+ egg_menu_merge_insert_action_group (merge, action_group, 0);
+ window->priv->action_group = action_group;
- *ui_component = bonobo_ui_component_new_default ();
+ action_group = egg_action_group_new ("PopupsActions");
+ egg_action_group_add_actions (action_group, ephy_popups_entries,
+ ephy_popups_n_entries);
+ egg_menu_merge_insert_action_group (merge, action_group, 0);
+ window->priv->popups_action_group = action_group;
- bonobo_ui_component_set_container (*ui_component,
- corba_container,
- NULL);
+ window->ui_merge = G_OBJECT (merge);
+ g_signal_connect (merge, "add_widget", G_CALLBACK (add_widget), window);
+ egg_menu_merge_add_ui_from_file (merge, ephy_file ("epiphany-ui.xml"), NULL);
+ gtk_window_add_accel_group (GTK_WINDOW (window), merge->accel_group);
- bonobo_ui_util_set_ui (*ui_component,
- DATADIR,
- "epiphany-ui.xml",
- "ephy", NULL);
+ window->priv->toolbar = toolbar_new (window);
- /* Key handling */
- g_signal_connect(G_OBJECT(win),
+ g_signal_connect(window,
"key-press-event",
G_CALLBACK(ephy_window_key_press_event_cb),
window);
-
- g_signal_connect (G_OBJECT(win), "configure_event",
+ g_signal_connect (window, "configure_event",
G_CALLBACK (ephy_window_configure_event_cb), NULL);
- g_signal_connect (G_OBJECT(win), "window_state_event",
+ g_signal_connect (window, "window_state_event",
G_CALLBACK (ephy_window_state_event_cb), NULL);
-
- g_signal_connect (G_OBJECT(win),
+ g_signal_connect (window,
"selection-received",
G_CALLBACK (ephy_window_selection_received_cb),
window);
}
-static EphyEmbedPopupBW *
-setup_popup_factory (EphyWindow *window,
- BonoboUIComponent *ui_component)
-{
- EphyEmbedPopupBW *popup;
-
- popup = ephy_window_get_popup_factory (window);
- g_object_set_data (G_OBJECT(popup), "EphyWindow", window);
- bonobo_ui_component_add_verb_list_with_data (ui_component,
- ephy_popup_verbs,
- popup);
-
- return popup;
-}
-
static GtkNotebook *
setup_notebook (EphyWindow *window)
{
@@ -369,89 +507,6 @@ setup_notebook (EphyWindow *window)
}
static void
-view_toolbar_changed_cb (BonoboUIComponent *component,
- const char *path,
- Bonobo_UIComponent_EventType type,
- const char *state,
- EphyWindow *window)
-{
- EmbedChromeMask mask;
-
- if (window->priv->ignore_layout_toggles) return;
-
- mask = ephy_window_get_chrome (window);
- mask ^= EMBED_CHROME_TOOLBARON;
- ephy_window_set_chrome (window, mask);
-}
-
-static void
-view_statusbar_changed_cb (BonoboUIComponent *component,
- const char *path,
- Bonobo_UIComponent_EventType type,
- const char *state,
- EphyWindow *window)
-{
- EmbedChromeMask mask;
-
- if (window->priv->ignore_layout_toggles) return;
-
- mask = ephy_window_get_chrome (window);
- mask ^= EMBED_CHROME_STATUSBARON;
- ephy_window_set_chrome (window, mask);
-}
-
-static void
-view_fullscreen_changed_cb (BonoboUIComponent *component,
- const char *path,
- Bonobo_UIComponent_EventType type,
- const char *state,
- EphyWindow *window)
-{
- EmbedChromeMask mask;
-
- if (window->priv->ignore_layout_toggles) return;
-
- mask = ephy_window_get_chrome (window);
- mask ^= EMBED_CHROME_OPENASFULLSCREEN;
- mask |= EMBED_CHROME_DEFAULT;
- ephy_window_set_chrome (window, mask);
-}
-
-static void
-update_layout_toggles (EphyWindow *window)
-{
- BonoboUIComponent *ui_component = BONOBO_UI_COMPONENT (window->ui_component);
- EmbedChromeMask mask = window->priv->chrome_mask;
-
- window->priv->ignore_layout_toggles = TRUE;
-
- ephy_bonobo_set_toggle_state (ui_component, VIEW_TOOLBAR_PATH,
- mask & EMBED_CHROME_TOOLBARON);
- ephy_bonobo_set_toggle_state (ui_component, VIEW_STATUSBAR_PATH,
- mask & EMBED_CHROME_STATUSBARON);
- ephy_bonobo_set_toggle_state (ui_component, VIEW_FULLSCREEN_PATH,
- mask & EMBED_CHROME_OPENASFULLSCREEN);
-
- window->priv->ignore_layout_toggles = FALSE;
-}
-
-static void
-setup_layout_menus (EphyWindow *window)
-{
- BonoboUIComponent *ui_component = BONOBO_UI_COMPONENT (window->ui_component);
-
- bonobo_ui_component_add_listener (ui_component, ID_VIEW_TOOLBAR,
- (BonoboUIListenerFn)view_toolbar_changed_cb,
- window);
- bonobo_ui_component_add_listener (ui_component, ID_VIEW_STATUSBAR,
- (BonoboUIListenerFn)view_statusbar_changed_cb,
- window);
- bonobo_ui_component_add_listener (ui_component, ID_VIEW_FULLSCREEN,
- (BonoboUIListenerFn)view_fullscreen_changed_cb,
- window);
-}
-
-static void
favicon_cache_changed_cb (EphyFaviconCache *cache, char *url, EphyWindow *window)
{
ephy_window_update_control (window, FaviconControl);
@@ -460,14 +515,12 @@ favicon_cache_changed_cb (EphyFaviconCache *cache, char *url, EphyWindow *window
static void
ephy_window_init (EphyWindow *window)
{
- BonoboUIComponent *ui_component;
Session *session;
EphyFaviconCache *cache;
session = ephy_shell_get_session (ephy_shell);
window->priv = g_new0 (EphyWindowPrivate, 1);
- window->priv->embed_popup = NULL;
window->priv->active_tab = NULL;
window->priv->chrome_mask = 0;
window->priv->ignore_layout_toggles = FALSE;
@@ -482,42 +535,25 @@ ephy_window_init (EphyWindow *window)
0);
/* Setup the window and connect verbs */
- setup_bonobo_window (window, &ui_component);
- window->ui_component = G_OBJECT (ui_component);
- bonobo_ui_component_add_verb_list_with_data (ui_component,
- ephy_verbs,
- window);
- setup_layout_menus (window);
-
- /* Setup the embed popups factory */
- window->priv->embed_popup = setup_popup_factory (window,
- ui_component);
-
- bonobo_ui_component_freeze (ui_component, NULL);
-
- /* Setup menubar */
- ephy_embed_utils_build_charsets_submenu (ui_component,
- CHARSET_MENU_PATH,
- (BonoboUIVerbFn)window_cmd_set_charset,
- window);
- window->priv->fav_menu = ephy_favorites_menu_new (window);
- ephy_favorites_menu_set_path (window->priv->fav_menu, GO_FAVORITES_PATH);
+ setup_window (window);
- /* Setup toolbar and statusbar */
- window->priv->toolbar = toolbar_new (window);
- window->priv->statusbar = statusbar_new (window);
- window->priv->ppview_toolbar = ppview_toolbar_new (window);
+ window->priv->fav_menu = ephy_favorites_menu_new (window);
/* Setup window contents */
window->priv->notebook = setup_notebook (window);
- bonobo_window_set_contents (BONOBO_WINDOW (window),
- GTK_WIDGET (window->priv->notebook));
+ gtk_box_pack_start (GTK_BOX (window->priv->main_vbox),
+ GTK_WIDGET (window->priv->notebook),
+ TRUE, TRUE, 0);
- bonobo_ui_component_thaw (ui_component, NULL);
+ window->priv->statusbar = statusbar_new ();
+ gtk_widget_show (window->priv->statusbar);
+ gtk_box_pack_start (GTK_BOX (window->priv->main_vbox),
+ GTK_WIDGET (window->priv->statusbar),
+ FALSE, TRUE, 0);
g_object_ref (ephy_shell);
- /*Once window is fully created, add it to the session list*/
+ /* Once window is fully created, add it to the session list*/
session_add_window (session, window);
}
@@ -572,14 +608,6 @@ ephy_window_finalize (GObject *object)
remove_from_session (window);
- if (window->priv->embed_popup)
- {
- g_object_unref (G_OBJECT (window->priv->embed_popup));
- }
-
- g_object_unref (G_OBJECT (window->priv->toolbar));
- g_object_unref (G_OBJECT (window->priv->statusbar));
-
if (window->priv->find_dialog)
{
g_object_unref (G_OBJECT (window->priv->find_dialog));
@@ -592,7 +620,14 @@ ephy_window_finalize (GObject *object)
(gpointer *)&window->priv->history_dialog);
}
- g_free (window->priv);
+ g_object_unref (window->priv->fav_menu);
+
+ if (window->priv->ppview_toolbar)
+ {
+ g_object_unref (window->priv->ppview_toolbar);
+ }
+
+ g_free (window->priv);
G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -607,16 +642,6 @@ ephy_window_new (void)
return EPHY_WINDOW (g_object_new (EPHY_WINDOW_TYPE, NULL));
}
-static void
-dock_item_set_visibility (EphyWindow *window,
- const char *path,
- gboolean visibility)
-{
- ephy_bonobo_set_hidden (BONOBO_UI_COMPONENT(window->ui_component),
- path,
- !visibility);
-}
-
EmbedChromeMask
ephy_window_get_chrome (EphyWindow *window)
{
@@ -718,29 +743,46 @@ void
ephy_window_set_chrome (EphyWindow *window,
EmbedChromeMask flags)
{
- gboolean toolbar, ppvtoolbar, statusbar;
-
if (flags & EMBED_CHROME_DEFAULT)
{
translate_default_chrome (&flags);
}
- dock_item_set_visibility (window, "/menu",
- flags & EMBED_CHROME_MENUBARON);
+ if (flags & EMBED_CHROME_MENUBARON)
+ {
+ gtk_widget_show (window->priv->menubar);
+ }
+ else
+ {
+ gtk_widget_hide (window->priv->menubar);
+ }
- toolbar = (flags & EMBED_CHROME_TOOLBARON) != FALSE;
toolbar_set_visibility (window->priv->toolbar,
- toolbar);
+ flags & EMBED_CHROME_TOOLBARON);
- statusbar = (flags & EMBED_CHROME_STATUSBARON) != FALSE;
- statusbar_set_visibility (window->priv->statusbar,
- statusbar);
+ if (flags & EMBED_CHROME_STATUSBARON)
+ {
+ gtk_widget_show (window->priv->statusbar);
+ }
+ else
+ {
+ gtk_widget_hide (window->priv->statusbar);
+ }
- ppvtoolbar = (flags & EMBED_CHROME_PPVIEWTOOLBARON) != FALSE;
- ppview_toolbar_set_old_chrome (window->priv->ppview_toolbar,
- window->priv->chrome_mask);
- ppview_toolbar_set_visibility (window->priv->ppview_toolbar,
- ppvtoolbar);
+ if ((flags & EMBED_CHROME_PPVIEWTOOLBARON) != FALSE)
+ {
+ if (!window->priv->ppview_toolbar)
+ {
+ window->priv->ppview_toolbar = ppview_toolbar_new (window);
+ }
+ }
+ else
+ {
+ if (window->priv->ppview_toolbar)
+ {
+ g_object_unref (window->priv->ppview_toolbar);
+ }
+ }
/* set fullscreen only when it's really changed */
if ((window->priv->chrome_mask & EMBED_CHROME_OPENASFULLSCREEN) !=
@@ -753,8 +795,6 @@ ephy_window_set_chrome (EphyWindow *window,
window->priv->chrome_mask = flags;
- update_layout_toggles (window);
-
save_window_chrome (window);
}
@@ -988,14 +1028,11 @@ update_security (EphyWindow *window)
static void
update_nav_control (EphyWindow *window)
{
- /* the zoom control is updated at the same time than the navigation
- controls. This keeps it synched most of the time, but not always,
- because we don't get a notification when zoom changes */
-
gresult back, forward, up, stop;
EphyEmbed *embed;
EphyTab *tab;
- gint zoom;
+ EggActionGroup *action_group;
+ EggAction *action;
g_return_if_fail (window != NULL);
@@ -1010,29 +1047,16 @@ update_nav_control (EphyWindow *window)
up = ephy_embed_can_go_up (embed);
stop = ephy_tab_get_load_status (tab) & TAB_LOAD_STARTED;
- toolbar_button_set_sensitive (window->priv->toolbar,
- TOOLBAR_BACK_BUTTON,
- back == G_OK ? TRUE : FALSE);
- toolbar_button_set_sensitive (window->priv->toolbar,
- TOOLBAR_FORWARD_BUTTON,
- forward == G_OK ? TRUE : FALSE);
- toolbar_button_set_sensitive (window->priv->toolbar,
- TOOLBAR_UP_BUTTON,
- up == G_OK ? TRUE : FALSE);
- toolbar_button_set_sensitive (window->priv->toolbar,
- TOOLBAR_STOP_BUTTON,
- stop);
- if (ephy_embed_zoom_get (embed, &zoom) == G_OK)
- {
- toolbar_set_zoom (window->priv->toolbar, zoom);
- }
+ action_group = window->priv->action_group;
+ action = egg_action_group_get_action (action_group, "GoBack");
+ g_object_set (action, "sensitive", !back, NULL);
+ action = egg_action_group_get_action (action_group, "GoForward");
+ g_object_set (action, "sensitive", !forward, NULL);
+ action = egg_action_group_get_action (action_group, "GoUp");
+ g_object_set (action, "sensitive", !up, NULL);
- ephy_bonobo_set_sensitive (BONOBO_UI_COMPONENT(window->ui_component),
- GO_BACK_CMD_PATH, !back);
- ephy_bonobo_set_sensitive (BONOBO_UI_COMPONENT(window->ui_component),
- GO_FORWARD_CMD_PATH, !forward);
- ephy_bonobo_set_sensitive (BONOBO_UI_COMPONENT(window->ui_component),
- GO_UP_CMD_PATH, !up);
+ toolbar_update_navigation_actions (window->priv->toolbar,
+ back, forward, up);
}
static void
@@ -1066,8 +1090,7 @@ update_location_control (EphyWindow *window)
if (!location) location = "";
- toolbar_set_location (window->priv->toolbar,
- location);
+ toolbar_set_location (window->priv->toolbar, location);
}
static void
@@ -1108,11 +1131,11 @@ update_find_control (EphyWindow *window)
(FIND_DIALOG(window->priv->find_dialog));
can_go_prev = find_dialog_can_go_prev
(FIND_DIALOG(window->priv->find_dialog));
-
+/*
ephy_bonobo_set_sensitive (BONOBO_UI_COMPONENT(window->ui_component),
EDIT_FIND_NEXT_CMD_PATH, can_go_next);
ephy_bonobo_set_sensitive (BONOBO_UI_COMPONENT(window->ui_component),
- EDIT_FIND_PREV_CMD_PATH, can_go_prev);
+ EDIT_FIND_PREV_CMD_PATH, can_go_prev);*/
}
}
@@ -1218,7 +1241,7 @@ void
ephy_window_update_all_controls (EphyWindow *window)
{
g_return_if_fail (IS_EPHY_WINDOW (window));
-
+
if (ephy_window_get_active_tab (window) != NULL)
{
update_nav_control (window);
@@ -1257,21 +1280,6 @@ ephy_window_get_active_embed (EphyWindow *window)
else return NULL;
}
-EphyEmbedPopupBW *
-ephy_window_get_popup_factory (EphyWindow *window)
-{
- if (!window->priv->embed_popup)
- {
- window->priv->embed_popup = ephy_embed_popup_bw_new
- (BONOBO_WINDOW(window));
- ephy_embed_popup_connect_verbs
- (EPHY_EMBED_POPUP (window->priv->embed_popup),
- BONOBO_UI_COMPONENT (window->ui_component));
- }
-
- return window->priv->embed_popup;
-}
-
GList *
ephy_window_get_tabs (EphyWindow *window)
{
@@ -1296,8 +1304,11 @@ ephy_window_get_tabs (EphyWindow *window)
static void
save_old_embed_status (EphyTab *tab, EphyWindow *window)
{
- /* save old tab location status */
- ephy_tab_set_location (tab, toolbar_get_location (window->priv->toolbar));
+ char *location;
+
+ location = toolbar_get_location (window->priv->toolbar);
+ ephy_tab_set_location (tab, location);
+ g_free (location);
}
static void
@@ -1335,9 +1346,9 @@ update_embed_dialogs (EphyWindow *window,
static void
ephy_window_notebook_switch_page_cb (GtkNotebook *notebook,
- GtkNotebookPage *page,
- guint page_num,
- EphyWindow *window)
+ GtkNotebookPage *page,
+ guint page_num,
+ EphyWindow *window)
{
EphyTab *tab, *old_tab;
diff --git a/src/ephy-window.h b/src/ephy-window.h
index 315cd8cca..10712e3ff 100644
--- a/src/ephy-window.h
+++ b/src/ephy-window.h
@@ -20,13 +20,11 @@
#define EPHY_WINDOW_H
#include "ephy-embed.h"
-#include "ephy-embed-persist.h"
-#include "ephy-embed-popup-bw.h"
#include "ephy-dialog.h"
#include "ephy-notebook.h"
#include <glib-object.h>
#include <glib.h>
-#include <bonobo/bonobo-window.h>
+#include <gtk/gtkwindow.h>
G_BEGIN_DECLS
@@ -44,16 +42,16 @@ typedef struct Toolbar Toolbar;
struct EphyWindow
{
- BonoboWindow parent;
+ GtkWindow parent;
EphyWindowPrivate *priv;
/* Public to toolbar and statusbar, dont use outside */
- GObject *ui_component;
+ GObject *ui_merge;
};
struct EphyWindowClass
{
- BonoboWindowClass parent_class;
+ GtkWindowClass parent_class;
};
typedef enum
@@ -123,8 +121,6 @@ EphyTab *ephy_window_get_active_tab (EphyWindow *window);
EphyEmbed *ephy_window_get_active_embed (EphyWindow *window);
-EphyEmbedPopupBW *ephy_window_get_popup_factory (EphyWindow *window);
-
GList *ephy_window_get_tabs (EphyWindow *window);
Toolbar *ephy_window_get_toolbar (EphyWindow *window);
diff --git a/src/popup-commands.c b/src/popup-commands.c
index f1ec8ae74..84ce259c8 100644
--- a/src/popup-commands.c
+++ b/src/popup-commands.c
@@ -18,47 +18,60 @@
#include "popup-commands.h"
#include "ephy-shell.h"
+#include "ephy-new-bookmark.h"
+#include "ephy-embed-persist.h"
+#include "ephy-prefs.h"
+#include "ephy-embed-utils.h"
+#include "eel-gconf-extensions.h"
+#include "ephy-file-helpers.h"
-static EphyWindow *
-get_window_from_popup (EphyEmbedPopup *popup)
+#include <string.h>
+
+static EphyEmbedEvent *
+get_event_info (EphyWindow *window)
{
- return EPHY_WINDOW (g_object_get_data(G_OBJECT(popup), "EphyWindow"));
+ EphyEmbedEvent *info;
+ EphyTab *tab;
+
+ tab = ephy_window_get_active_tab (window);
+ g_return_val_if_fail (tab != NULL, NULL);
+
+ info = ephy_tab_get_event (tab);
+ g_return_val_if_fail (info != NULL, NULL);
+
+ return info;
}
-void popup_cmd_new_window (BonoboUIComponent *uic,
- EphyEmbedPopup *popup,
- const char* verbname)
+void
+popup_cmd_link_in_new_window (EggAction *action,
+ EphyWindow *window)
{
EphyEmbedEvent *info;
EphyTab *tab;
const GValue *value;
- tab = ephy_window_get_active_tab (get_window_from_popup (popup));
+ tab = ephy_window_get_active_tab (window);
- info = ephy_embed_popup_get_event (popup);
+ info = get_event_info (window);
ephy_embed_event_get_property (info, "link", &value);
ephy_shell_new_tab (ephy_shell, NULL, tab,
- g_value_get_string (value),
- EPHY_NEW_TAB_IN_NEW_WINDOW);
+ g_value_get_string (value),
+ EPHY_NEW_TAB_IN_NEW_WINDOW);
}
-void popup_cmd_new_tab (BonoboUIComponent *uic,
- EphyEmbedPopup *popup,
- const char* verbname)
+void
+popup_cmd_link_in_new_tab (EggAction *action,
+ EphyWindow *window)
{
EphyEmbedEvent *info;
EphyTab *tab;
- EphyWindow *window;
const GValue *value;
- window = get_window_from_popup (popup);
- g_return_if_fail (window != NULL);
-
tab = ephy_window_get_active_tab (window);
- info = ephy_embed_popup_get_event (popup);
+ info = get_event_info (window);
ephy_embed_event_get_property (info, "link", &value);
@@ -67,21 +80,17 @@ void popup_cmd_new_tab (BonoboUIComponent *uic,
EPHY_NEW_TAB_IN_EXISTING_WINDOW);
}
-void popup_cmd_image_in_new_tab (BonoboUIComponent *uic,
- EphyEmbedPopup *popup,
- const char* verbname)
+void
+popup_cmd_image_in_new_tab (EggAction *action,
+ EphyWindow *window)
{
EphyEmbedEvent *info;
EphyTab *tab;
- EphyWindow *window;
const GValue *value;
- window = get_window_from_popup (popup);
- g_return_if_fail (window != NULL);
-
tab = ephy_window_get_active_tab (window);
- info = ephy_embed_popup_get_event (popup);
+ info = get_event_info (window);
ephy_embed_event_get_property (info, "image", &value);
@@ -90,17 +99,17 @@ void popup_cmd_image_in_new_tab (BonoboUIComponent *uic,
EPHY_NEW_TAB_IN_EXISTING_WINDOW);
}
-void popup_cmd_image_in_new_window (BonoboUIComponent *uic,
- EphyEmbedPopup *popup,
- const char* verbname)
+void
+popup_cmd_image_in_new_window (EggAction *action,
+ EphyWindow *window)
{
EphyEmbedEvent *info;
EphyTab *tab;
const GValue *value;
- tab = ephy_window_get_active_tab (get_window_from_popup (popup));
+ tab = ephy_window_get_active_tab (window);
- info = ephy_embed_popup_get_event (popup);
+ info = get_event_info (window);
ephy_embed_event_get_property (info, "image", &value);
@@ -109,15 +118,14 @@ void popup_cmd_image_in_new_window (BonoboUIComponent *uic,
EPHY_NEW_TAB_IN_NEW_WINDOW);
}
-void popup_cmd_add_bookmark (BonoboUIComponent *uic,
- EphyEmbedPopup *popup,
- const char* verbname)
+void
+popup_cmd_add_link_bookmark (EggAction *action,
+ EphyWindow *window)
{
GtkWidget *new_bookmark;
EphyBookmarks *bookmarks;
- EphyEmbedEvent *info = ephy_embed_popup_get_event (popup);
+ EphyEmbedEvent *info;
EphyEmbed *embed;
- GtkWidget *window;
const GValue *link_title;
const GValue *link_rel;
const GValue *link;
@@ -127,8 +135,8 @@ void popup_cmd_add_bookmark (BonoboUIComponent *uic,
const char *rel;
gboolean is_smart;
- embed = ephy_embed_popup_get_embed (popup);
- window = gtk_widget_get_toplevel (GTK_WIDGET (embed));
+ info = get_event_info (window);
+ embed = ephy_window_get_active_embed (window);
ephy_embed_event_get_property (info, "link_is_smart", &link_is_smart);
ephy_embed_event_get_property (info, "link", &link);
@@ -157,18 +165,14 @@ void popup_cmd_add_bookmark (BonoboUIComponent *uic,
gtk_widget_show (new_bookmark);
}
-void popup_cmd_frame_in_new_tab (BonoboUIComponent *uic,
- EphyEmbedPopup *popup,
- const char* verbname)
+void
+popup_cmd_frame_in_new_tab (EggAction *action,
+ EphyWindow *window)
{
EphyTab *tab;
- EphyWindow *window;
EphyEmbed *embed;
char *location;
- window = get_window_from_popup (popup);
- g_return_if_fail (window != NULL);
-
tab = ephy_window_get_active_tab (window);
embed = ephy_window_get_active_embed (window);
@@ -182,18 +186,14 @@ void popup_cmd_frame_in_new_tab (BonoboUIComponent *uic,
g_free (location);
}
-void popup_cmd_frame_in_new_window (BonoboUIComponent *uic,
- EphyEmbedPopup *popup,
- const char* verbname)
+void
+popup_cmd_frame_in_new_window (EggAction *action,
+ EphyWindow *window)
{
EphyTab *tab;
EphyEmbed *embed;
- EphyWindow *window;
char *location;
- window = get_window_from_popup (popup);
- g_return_if_fail (window != NULL);
-
tab = ephy_window_get_active_tab (window);
embed = ephy_window_get_active_embed (window);
@@ -207,16 +207,260 @@ void popup_cmd_frame_in_new_window (BonoboUIComponent *uic,
g_free (location);
}
-void popup_cmd_add_frame_bookmark (BonoboUIComponent *uic,
- EphyEmbedPopup *popup,
- const char* verbname)
+static void
+popup_cmd_copy_to_clipboard (EphyWindow *window, const char *text)
+{
+ gtk_clipboard_set_text (gtk_clipboard_get (GDK_NONE),
+ text, -1);
+ gtk_clipboard_set_text (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
+ text, -1);
+}
+
+void
+popup_cmd_copy_page_location (EggAction *action,
+ EphyWindow *window)
+{
+ char *location;
+ EphyEmbed *embed;
+
+ embed = ephy_window_get_active_embed (window);
+ g_return_if_fail (embed != NULL);
+
+ ephy_embed_get_location (embed, FALSE, &location);
+ popup_cmd_copy_to_clipboard (window, location);
+ g_free (location);
+}
+
+void
+popup_cmd_copy_email (EggAction *action,
+ EphyWindow *window)
+{
+ EphyEmbedEvent *info;
+ const char *location;
+ const GValue *value;
+ EphyEmbed *embed;
+
+ embed = ephy_window_get_active_embed (window);
+ g_return_if_fail (embed != NULL);
+
+ info = get_event_info (window);
+ ephy_embed_event_get_property (info, "email", &value);
+ location = g_value_get_string (value);
+ popup_cmd_copy_to_clipboard (window, location);
+}
+
+void
+popup_cmd_copy_link_location (EggAction *action,
+ EphyWindow *window)
+{
+ EphyEmbedEvent *info;
+ const char *location;
+ const GValue *value;
+ EphyEmbed *embed;
+
+ embed = ephy_window_get_active_embed (window);
+ g_return_if_fail (embed != NULL);
+
+ info = get_event_info (window);
+ ephy_embed_event_get_property (info, "link", &value);
+ location = g_value_get_string (value);
+ popup_cmd_copy_to_clipboard (window, location);
+}
+
+static void
+save_property_url (EggAction *action,
+ EphyWindow *window,
+ gboolean ask_dest,
+ gboolean show_progress,
+ const char *property)
+{
+ EphyEmbedEvent *info;
+ const char *location;
+ const GValue *value;
+ GtkWidget *widget;
+ EphyEmbedPersist *persist;
+ EphyEmbed *embed;
+
+ embed = ephy_window_get_active_embed (window);
+ g_return_if_fail (embed != NULL);
+
+ info = get_event_info (window);
+ ephy_embed_event_get_property (info, property, &value);
+ location = g_value_get_string (value);
+
+ widget = GTK_WIDGET (embed);
+
+ persist = ephy_embed_persist_new (embed);
+
+ ephy_embed_persist_set_source (persist, location);
+
+ if (show_progress)
+ {
+ ephy_embed_persist_set_flags (persist,
+ EMBED_PERSIST_SHOW_PROGRESS);
+ }
+
+ ephy_embed_utils_save (GTK_WIDGET (window),
+ CONF_STATE_DOWNLOADING_DIR,
+ ask_dest,
+ FALSE,
+ persist);
+}
+
+void
+popup_cmd_open_link (EggAction *action,
+ EphyWindow *window)
+{
+ EphyEmbedEvent *info;
+ const char *location;
+ const GValue *value;
+ EphyEmbed *embed;
+
+ embed = ephy_window_get_active_embed (window);
+ g_return_if_fail (embed != NULL);
+
+ info = get_event_info (window);
+ ephy_embed_event_get_property (info, "link", &value);
+ location = g_value_get_string (value);
+
+ ephy_embed_load_url (embed, location);
+}
+
+void
+popup_cmd_download_link (EggAction *action,
+ EphyWindow *window)
+{
+ save_property_url (action, window,
+ eel_gconf_get_boolean
+ (CONF_STATE_DOWNLOADING_DIR),
+ TRUE, "link");
+}
+
+void
+popup_cmd_save_image_as (EggAction *action,
+ EphyWindow *window)
+{
+ save_property_url (action, window, TRUE, FALSE, "image");
+}
+
+#define CONF_DESKTOP_BG_PICTURE "/desktop/gnome/background/picture_filename"
+#define CONF_DESKTOP_BG_TYPE "/desktop/gnome/background/picture_options"
+
+static void
+background_download_completed (EphyEmbedPersist *persist,
+ gpointer data)
+{
+ const char *bg;
+ char *type;
+
+ ephy_embed_persist_get_dest (persist, &bg);
+ eel_gconf_set_string (CONF_DESKTOP_BG_PICTURE, bg);
+
+ type = eel_gconf_get_string (CONF_DESKTOP_BG_TYPE);
+ if (type || strcmp (type, "none") == 0)
+ {
+ eel_gconf_set_string (CONF_DESKTOP_BG_TYPE,
+ "wallpaper");
+ }
+
+ g_free (type);
+
+ g_object_unref (persist);
+}
+
+void
+popup_cmd_set_image_as_background (EggAction *action,
+ EphyWindow *window)
+{
+ EphyEmbedEvent *info;
+ const char *location;
+ char *dest, *base;
+ const GValue *value;
+ EphyEmbedPersist *persist;
+ EphyEmbed *embed;
+
+ embed = ephy_window_get_active_embed (window);
+ g_return_if_fail (embed != NULL);
+
+ info = get_event_info (window);
+ ephy_embed_event_get_property (info, "image", &value);
+ location = g_value_get_string (value);
+
+ persist = ephy_embed_persist_new (embed);
+
+ base = g_path_get_basename (location);
+ dest = g_build_filename (ephy_dot_dir (),
+ base, NULL);
+
+ ephy_embed_persist_set_source (persist, location);
+ ephy_embed_persist_set_dest (persist, dest);
+
+ ephy_embed_persist_save (persist);
+
+ g_signal_connect (persist, "completed",
+ G_CALLBACK (background_download_completed),
+ NULL);
+
+ g_free (dest);
+ g_free (base);
+}
+
+void
+popup_cmd_copy_image_location (EggAction *action,
+ EphyWindow *window)
+{
+ EphyEmbedEvent *info;
+ const char *location;
+ const GValue *value;
+ EphyEmbed *embed;
+
+ embed = ephy_window_get_active_embed (window);
+ g_return_if_fail (embed != NULL);
+
+ info = get_event_info (window);
+ ephy_embed_event_get_property (info, "image", &value);
+ location = g_value_get_string (value);
+ popup_cmd_copy_to_clipboard (window, location);
+}
+
+void
+popup_cmd_save_background_as (EggAction *action,
+ EphyWindow *window)
+{
+ save_property_url (action, window, TRUE, FALSE, "background_image");
+}
+
+void
+popup_cmd_open_frame (EggAction *action,
+ EphyWindow *window)
{
- /* FIXME implement */
+ char *location;
+ EphyEmbed *embed;
+
+ embed = ephy_window_get_active_embed (window);
+ g_return_if_fail (embed != NULL);
+
+ ephy_embed_get_location (embed, FALSE, &location);
+
+ ephy_embed_load_url (embed, location);
}
-void popup_cmd_view_source (BonoboUIComponent *uic,
- EphyEmbedPopup *popup,
- const char* verbname)
+void
+popup_cmd_open_image (EggAction *action,
+ EphyWindow *window)
{
- /* FIXME implement */
+ EphyEmbedEvent *info;
+ const char *location;
+ const GValue *value;
+ EphyEmbed *embed;
+
+ embed = ephy_window_get_active_embed (window);
+ g_return_if_fail (embed != NULL);
+
+ info = get_event_info (window);
+ ephy_embed_event_get_property (info, "image", &value);
+ location = g_value_get_string (value);
+
+ ephy_embed_load_url (embed, location);
}
+
diff --git a/src/popup-commands.h b/src/popup-commands.h
index e5b369c76..c2ac4fb36 100644
--- a/src/popup-commands.h
+++ b/src/popup-commands.h
@@ -16,43 +16,69 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "ephy-embed-popup.h"
-#include "ephy-new-bookmark.h"
+#include "egg-action.h"
+#include "ephy-window.h"
-#include <bonobo/bonobo-ui-component.h>
+void popup_cmd_link_in_new_window (EggAction *action,
+ EphyWindow *window);
-void popup_cmd_new_window (BonoboUIComponent *uic,
- EphyEmbedPopup *popup,
- const char* verbname);
+void popup_cmd_link_in_new_tab (EggAction *action,
+ EphyWindow *window);
-void popup_cmd_new_tab (BonoboUIComponent *uic,
- EphyEmbedPopup *popup,
- const char* verbname);
+void popup_cmd_image_in_new_tab (EggAction *action,
+ EphyWindow *window);
-void popup_cmd_image_in_new_tab (BonoboUIComponent *uic,
- EphyEmbedPopup *popup,
- const char* verbname);
+void popup_cmd_image_in_new_window (EggAction *action,
+ EphyWindow *window);
-void popup_cmd_image_in_new_window (BonoboUIComponent *uic,
- EphyEmbedPopup *popup,
- const char* verbname);
+void popup_cmd_add_link_bookmark (EggAction *action,
+ EphyWindow *window);
-void popup_cmd_add_bookmark (BonoboUIComponent *uic,
- EphyEmbedPopup *popup,
- const char* verbname);
+void popup_cmd_frame_in_new_tab (EggAction *action,
+ EphyWindow *window);
-void popup_cmd_frame_in_new_tab (BonoboUIComponent *uic,
- EphyEmbedPopup *popup,
- const char* verbname);
+void popup_cmd_frame_in_new_window (EggAction *action,
+ EphyWindow *window);
-void popup_cmd_frame_in_new_window (BonoboUIComponent *uic,
- EphyEmbedPopup *popup,
- const char* verbname);
+void popup_cmd_add_frame_bookmark (EggAction *action,
+ EphyWindow *window);
-void popup_cmd_add_frame_bookmark (BonoboUIComponent *uic,
- EphyEmbedPopup *popup,
- const char* verbname);
+void popup_cmd_view_source (EggAction *action,
+ EphyWindow *window);
+
+void popup_cmd_copy_page_location (EggAction *action,
+ EphyWindow *window);
+
+void popup_cmd_copy_email (EggAction *action,
+ EphyWindow *window);
+
+void popup_cmd_copy_link_location (EggAction *action,
+ EphyWindow *window);
+
+void popup_cmd_open_link (EggAction *action,
+ EphyWindow *window);
+
+void popup_cmd_download_link (EggAction *action,
+ EphyWindow *window);
+
+void popup_cmd_set_image_as_background (EggAction *action,
+ EphyWindow *window);
+
+void popup_cmd_copy_image_location (EggAction *action,
+ EphyWindow *window);
+
+void popup_cmd_save_background_as (EggAction *action,
+ EphyWindow *window);
+
+void popup_cmd_open_frame (EggAction *action,
+ EphyWindow *window);
+
+void popup_cmd_open_image (EggAction *action,
+ EphyWindow *window);
+
+void popup_cmd_download_link (EggAction *action,
+ EphyWindow *window);
+
+void popup_cmd_save_image_as (EggAction *action,
+ EphyWindow *window);
-void popup_cmd_view_source (BonoboUIComponent *uic,
- EphyEmbedPopup *popup,
- const char* verbname);
diff --git a/src/ppview-toolbar.c b/src/ppview-toolbar.c
index 06b2cbb6e..fea06c2d7 100755
--- a/src/ppview-toolbar.c
+++ b/src/ppview-toolbar.c
@@ -22,6 +22,7 @@
#include "ephy-bonobo-extensions.h"
#include "ephy-string.h"
#include "ephy-gui.h"
+#include "egg-menu-merge.h"
#include <string.h>
#include <bonobo/bonobo-i18n.h>
@@ -63,48 +64,68 @@ static GObjectClass *parent_class = NULL;
struct PPViewToolbarPrivate
{
EphyWindow *window;
- BonoboUIComponent *ui_component;
- gboolean visibility;
- EmbedChromeMask old_chrome;
+ EggMenuMerge *ui_merge;
+ EggActionGroup *action_group;
+ guint ui_id;
int current_page;
};
static void
-toolbar_cmd_ppv_goto_first (BonoboUIComponent *uic,
- PPViewToolbar *t,
- const char* verbname);
+toolbar_cmd_ppv_goto_first (EggMenuMerge *merge,
+ PPViewToolbar *t);
static void
-toolbar_cmd_ppv_goto_last (BonoboUIComponent *uic,
- PPViewToolbar *t,
- const char* verbname);
+toolbar_cmd_ppv_goto_last (EggMenuMerge *merge,
+ PPViewToolbar *t);
static void
-toolbar_cmd_ppv_go_back (BonoboUIComponent *uic,
- PPViewToolbar *t,
- const char* verbname);
+toolbar_cmd_ppv_go_back (EggMenuMerge *merge,
+ PPViewToolbar *t);
static void
-toolbar_cmd_ppv_go_forward (BonoboUIComponent *uic,
- PPViewToolbar *t,
- const char* verbname);
+toolbar_cmd_ppv_go_forward (EggMenuMerge *merge,
+ PPViewToolbar *t);
static void
-toolbar_cmd_ppv_close (BonoboUIComponent *uic,
- PPViewToolbar *t,
- const char* verbname);
-
-BonoboUIVerb ppview_toolbar_verbs [] = {
- BONOBO_UI_VERB ("PPVGotoFirst", (BonoboUIVerbFn)toolbar_cmd_ppv_goto_first),
- BONOBO_UI_VERB ("PPVGotoLast", (BonoboUIVerbFn)toolbar_cmd_ppv_goto_last),
- BONOBO_UI_VERB ("PPVGoBack", (BonoboUIVerbFn)toolbar_cmd_ppv_go_back),
- BONOBO_UI_VERB ("PPVGoForward", (BonoboUIVerbFn)toolbar_cmd_ppv_go_forward),
- BONOBO_UI_VERB ("PPVClose", (BonoboUIVerbFn)toolbar_cmd_ppv_close),
-
- BONOBO_UI_VERB_END
+toolbar_cmd_ppv_close (EggMenuMerge *merge,
+ PPViewToolbar *t);
+
+static EggActionGroupEntry entries [] = {
+ { "PPVGotoFirst", N_("First"),
+ GTK_STOCK_GOTO_FIRST, NULL,
+ N_("Go to the first page"),
+ (GCallback)toolbar_cmd_ppv_goto_first, NULL },
+ { "PPVGotoLast", N_("Last"),
+ GTK_STOCK_GOTO_LAST, NULL,
+ N_("Go to the last page"),
+ (GCallback)toolbar_cmd_ppv_goto_last, NULL },
+ { "PPVGoBack", N_("Previous"),
+ GTK_STOCK_GO_BACK, NULL,
+ N_("Go to the previous page"),
+ (GCallback)toolbar_cmd_ppv_go_back, NULL },
+ { "PPVGoForward", N_("Next"),
+ GTK_STOCK_GO_FORWARD, NULL,
+ N_("Go to next page"),
+ (GCallback)toolbar_cmd_ppv_go_forward, NULL },
+ { "PPVClose", N_("Close"),
+ GTK_STOCK_CLOSE, NULL,
+ N_("Close print preview"),
+ (GCallback)toolbar_cmd_ppv_close, NULL },
};
-
-GType
+static guint n_entries = G_N_ELEMENTS (entries);
+
+static const gchar *ui_info =
+"<Root>\n"
+" <dockitem name=\"PPViewToolbar\">\n"
+" <toolitem name=\"PPVGotoFirstItem\" verb=\"PPVGotoFirst\" />\n"
+" <toolitem name=\"PPVGotoLastItem\" verb=\"PPVGotoLast\" />\n"
+" <toolitem name=\"PPVGoBackItem\"verb=\"PPVGoBack\" />\n"
+" <toolitem name=\"PPVGoForwardItem\" verb=\"PPVGoForward\" />\n"
+" <toolitem name=\"PPVClose\" verb=\"PPVClose\" />\n"
+" </dockitem>\n"
+"</Root>\n";
+
+GType
ppview_toolbar_get_type (void)
{
static GType ppview_toolbar_type = 0;
@@ -192,22 +213,30 @@ ppview_toolbar_set_window (PPViewToolbar *t, EphyWindow *window)
g_return_if_fail (t->priv->window == NULL);
t->priv->window = window;
- t->priv->ui_component = BONOBO_UI_COMPONENT
- (t->priv->window->ui_component);
-
- bonobo_ui_component_add_verb_list_with_data (t->priv->ui_component,
- ppview_toolbar_verbs,
- t);
+ t->priv->ui_merge = EGG_MENU_MERGE (t->priv->window->ui_merge);
+
+ t->priv->action_group = egg_action_group_new ("PPViewActions");
+ egg_action_group_add_actions (t->priv->action_group, entries, n_entries);
+ egg_menu_merge_insert_action_group (t->priv->ui_merge,
+ t->priv->action_group, 0);
+ t->priv->ui_id = egg_menu_merge_add_ui_from_string
+ (t->priv->ui_merge, ui_info, -1, NULL);
}
static void
ppview_toolbar_init (PPViewToolbar *t)
{
+ int i;
+
t->priv = g_new0 (PPViewToolbarPrivate, 1);
t->priv->window = NULL;
- t->priv->ui_component = NULL;
- t->priv->visibility = TRUE;
+ t->priv->ui_merge = NULL;
+
+ for (i = 0; i < n_entries; i++)
+ {
+ entries[i].user_data = t;
+ }
}
static void
@@ -221,6 +250,8 @@ ppview_toolbar_finalize (GObject *object)
t = PPVIEW_TOOLBAR (object);
g_return_if_fail (t->priv != NULL);
+ egg_menu_merge_remove_ui (t->priv->ui_merge, t->priv->ui_id);
+ g_object_unref (t->priv->action_group);
g_free (t->priv);
@@ -241,13 +272,6 @@ ppview_toolbar_new (EphyWindow *window)
return t;
}
-void
-ppview_toolbar_set_old_chrome (PPViewToolbar *t,
- EmbedChromeMask chrome)
-{
- t->priv->old_chrome = chrome;
-}
-
static void
toolbar_update_sensitivity (PPViewToolbar *t)
{
@@ -260,7 +284,7 @@ toolbar_update_sensitivity (PPViewToolbar *t)
ephy_embed_print_preview_num_pages (embed, &pages);
c_page = t->priv->current_page;
-
+/*
ephy_bonobo_set_sensitive (t->priv->ui_component,
PPV_GO_BACK_PATH, c_page > 1);
ephy_bonobo_set_sensitive (t->priv->ui_component,
@@ -269,30 +293,12 @@ toolbar_update_sensitivity (PPViewToolbar *t)
PPV_GO_FORWARD_PATH, c_page < pages);
ephy_bonobo_set_sensitive (t->priv->ui_component,
PPV_GOTO_LAST_PATH, c_page < pages);
-}
-
-void
-ppview_toolbar_set_visibility (PPViewToolbar *t, gboolean visibility)
-{
- if (visibility == t->priv->visibility) return;
-
- t->priv->visibility = visibility;
-
- if (visibility)
- {
- t->priv->current_page = 1;
- toolbar_update_sensitivity (t);
- }
-
- ephy_bonobo_set_hidden (BONOBO_UI_COMPONENT(t->priv->ui_component),
- "/PrintPreview",
- !visibility);
+ */
}
static void
-toolbar_cmd_ppv_goto_first (BonoboUIComponent *uic,
- PPViewToolbar *t,
- const char* verbname)
+toolbar_cmd_ppv_goto_first (EggMenuMerge *merge,
+ PPViewToolbar *t)
{
EphyWindow *window = t->priv->window;
EphyEmbed *embed;
@@ -308,9 +314,8 @@ toolbar_cmd_ppv_goto_first (BonoboUIComponent *uic,
}
static void
-toolbar_cmd_ppv_goto_last (BonoboUIComponent *uic,
- PPViewToolbar *t,
- const char* verbname)
+toolbar_cmd_ppv_goto_last (EggMenuMerge *merge,
+ PPViewToolbar *t)
{
EphyWindow *window = t->priv->window;
EphyEmbed *embed;
@@ -329,9 +334,8 @@ toolbar_cmd_ppv_goto_last (BonoboUIComponent *uic,
}
static void
-toolbar_cmd_ppv_go_back (BonoboUIComponent *uic,
- PPViewToolbar *t,
- const char* verbname)
+toolbar_cmd_ppv_go_back (EggMenuMerge *merge,
+ PPViewToolbar *t)
{
EphyWindow *window = t->priv->window;
EphyEmbed *embed;
@@ -349,9 +353,8 @@ toolbar_cmd_ppv_go_back (BonoboUIComponent *uic,
}
static void
-toolbar_cmd_ppv_go_forward (BonoboUIComponent *uic,
- PPViewToolbar *t,
- const char* verbname)
+toolbar_cmd_ppv_go_forward (EggMenuMerge *merge,
+ PPViewToolbar *t)
{
EphyWindow *window = t->priv->window;
EphyEmbed *embed;
@@ -369,20 +372,8 @@ toolbar_cmd_ppv_go_forward (BonoboUIComponent *uic,
}
static void
-toolbar_cmd_ppv_close (BonoboUIComponent *uic,
- PPViewToolbar *t,
- const char* verbname)
+toolbar_cmd_ppv_close (EggMenuMerge *merge,
+ PPViewToolbar *t)
{
- EphyWindow *window = t->priv->window;
- EphyEmbed *embed;
-
- embed = ephy_window_get_active_embed (window);
- g_return_if_fail (embed != NULL);
-
- ephy_window_set_chrome (window, t->priv->old_chrome);
-
- ephy_embed_print_preview_close (embed);
-
- toolbar_update_sensitivity (t);
}
diff --git a/src/ppview-toolbar.h b/src/ppview-toolbar.h
index 3e6a4b504..35356a0e5 100644
--- a/src/ppview-toolbar.h
+++ b/src/ppview-toolbar.h
@@ -52,12 +52,6 @@ GType ppview_toolbar_get_type (void);
PPViewToolbar *ppview_toolbar_new (EphyWindow *window);
-void ppview_toolbar_set_visibility (PPViewToolbar *t,
- gboolean visibility);
-
-void ppview_toolbar_set_old_chrome (PPViewToolbar *t,
- EmbedChromeMask chrome);
-
G_END_DECLS
#endif
diff --git a/src/statusbar.c b/src/statusbar.c
index 8ac84cfb9..8ff6b4402 100755
--- a/src/statusbar.c
+++ b/src/statusbar.c
@@ -18,7 +18,6 @@
#include "statusbar.h"
#include "ephy-stock-icons.h"
-#include "ephy-bonobo-extensions.h"
#include <string.h>
#include <time.h>
@@ -27,45 +26,22 @@
#include <gtk/gtkimage.h>
#include <gtk/gtkframe.h>
#include <gtk/gtktooltips.h>
-#include <bonobo/bonobo-window.h>
-#include <bonobo/bonobo-control.h>
static void statusbar_class_init (StatusbarClass *klass);
static void statusbar_init (Statusbar *t);
static void statusbar_finalize (GObject *object);
-static void
-statusbar_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void
-statusbar_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-static void
-statusbar_set_window (Statusbar *t, EphyWindow *window);
-
-enum
-{
- PROP_0,
- PROP_EPHY_WINDOW
-};
static GObjectClass *parent_class = NULL;
struct StatusbarPrivate
{
- EphyWindow *window;
- BonoboUIComponent *ui_component;
GtkWidget *security_icon;
GtkWidget *progress;
GtkTooltips *tooltips;
GtkWidget *security_evbox;
- gboolean visibility;
};
-GType
+GType
statusbar_get_type (void)
{
static GType statusbar_type = 0;
@@ -85,7 +61,7 @@ statusbar_get_type (void)
(GInstanceInitFunc) statusbar_init
};
- statusbar_type = g_type_register_static (G_TYPE_OBJECT,
+ statusbar_type = g_type_register_static (GTK_TYPE_STATUSBAR,
"Statusbar",
&our_info, 0);
}
@@ -102,55 +78,12 @@ statusbar_class_init (StatusbarClass *klass)
parent_class = g_type_class_peek_parent (klass);
object_class->finalize = statusbar_finalize;
- object_class->set_property = statusbar_set_property;
- object_class->get_property = statusbar_get_property;
-
- g_object_class_install_property (object_class,
- PROP_EPHY_WINDOW,
- g_param_spec_object ("EphyWindow",
- "EphyWindow",
- "Parent window",
- EPHY_WINDOW_TYPE,
- G_PARAM_READWRITE));
-}
-
-static void
-statusbar_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- Statusbar *s = STATUSBAR (object);
-
- switch (prop_id)
- {
- case PROP_EPHY_WINDOW:
- statusbar_set_window (s, g_value_get_object (value));
- break;
- }
-}
-
-static void
-statusbar_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- Statusbar *s = STATUSBAR (object);
-
- switch (prop_id)
- {
- case PROP_EPHY_WINDOW:
- g_value_set_object (value, s->priv->window);
- break;
- }
}
static void
create_statusbar_security_icon (Statusbar *s)
{
GtkWidget *security_frame;
- BonoboControl *control;
security_frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (security_frame),
@@ -162,61 +95,38 @@ create_statusbar_security_icon (Statusbar *s)
GTK_WIDGET (s->priv->security_evbox));
gtk_container_add (GTK_CONTAINER (s->priv->security_evbox),
GTK_WIDGET (s->priv->security_icon));
- /*
- g_signal_connect (G_OBJECT (security_eventbox),
- "button_release_event",
- GTK_SIGNAL_FUNC
- (security_icon_button_release_cb), t);
- */
-
- control = bonobo_control_new (security_frame);
- bonobo_ui_component_object_set (s->priv->ui_component,
- "/status/SecurityIconWrapper",
- BONOBO_OBJREF (control),
- NULL);
- bonobo_object_unref (control);
statusbar_set_security_state (s, FALSE, NULL);
gtk_widget_show_all (security_frame);
+
+ gtk_box_pack_start (GTK_BOX (s),
+ GTK_WIDGET (security_frame),
+ FALSE, TRUE, 0);
}
static void
create_statusbar_progress (Statusbar *s)
{
- BonoboControl *control;
-
s->priv->progress = gtk_progress_bar_new ();
-
- control = bonobo_control_new (s->priv->progress);
- bonobo_ui_component_object_set (s->priv->ui_component,
- "/status/ProgressWrapper",
- BONOBO_OBJREF (control),
- NULL);
-
gtk_widget_show_all (s->priv->progress);
-}
-
-static void
-statusbar_set_window (Statusbar *s, EphyWindow *window)
-{
- g_return_if_fail (s->priv->window == NULL);
- s->priv->window = window;
- s->priv->ui_component = BONOBO_UI_COMPONENT
- (s->priv->window->ui_component);
-
- create_statusbar_progress (s);
- create_statusbar_security_icon (s);
+ gtk_box_pack_start (GTK_BOX (s),
+ GTK_WIDGET (s->priv->progress),
+ FALSE, TRUE, 0);
}
static void
statusbar_init (Statusbar *t)
{
t->priv = g_new0 (StatusbarPrivate, 1);
- t->priv->visibility = TRUE;
t->priv->tooltips = gtk_tooltips_new ();
+
+ gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (t), FALSE);
+
+ create_statusbar_progress (t);
+ create_statusbar_security_icon (t);
}
static void
@@ -238,34 +148,18 @@ statusbar_finalize (GObject *object)
G_OBJECT_CLASS (parent_class)->finalize (object);
}
-Statusbar *
-statusbar_new (EphyWindow *window)
+GtkWidget *
+statusbar_new (void)
{
- Statusbar *t;
-
- t = STATUSBAR (g_object_new (STATUSBAR_TYPE,
- "EphyWindow", window,
- NULL));
+ GtkWidget *t;
- g_return_val_if_fail (t->priv != NULL, NULL);
+ t = GTK_WIDGET (g_object_new (STATUSBAR_TYPE,
+ NULL));
return t;
}
void
-statusbar_set_visibility (Statusbar *t,
- gboolean visibility)
-{
- if (visibility == t->priv->visibility) return;
-
- t->priv->visibility = visibility;
-
- ephy_bonobo_set_hidden (BONOBO_UI_COMPONENT(t->priv->ui_component),
- "/status",
- !visibility);
-}
-
-void
statusbar_set_security_state (Statusbar *t,
gboolean state,
const char *tooltip)
@@ -302,20 +196,9 @@ void
statusbar_set_message (Statusbar *s,
const char *message)
{
- g_return_if_fail (BONOBO_IS_UI_COMPONENT(s->priv->ui_component));
g_return_if_fail (message != NULL);
- /* Bonobo doesnt like 0 length messages */
- if (g_utf8_strlen (message, -1) == 0)
- {
- message = " ";
- }
-
- if (bonobo_ui_component_get_container (s->priv->ui_component)) /* should not do this here... */
- {
- bonobo_ui_component_set_status (s->priv->ui_component,
- message,
- NULL);
- }
+ gtk_statusbar_pop (GTK_STATUSBAR (s), 0);
+ gtk_statusbar_push (GTK_STATUSBAR (s), 0, message);
}
diff --git a/src/statusbar.h b/src/statusbar.h
index 590b89394..27af4b315 100644
--- a/src/statusbar.h
+++ b/src/statusbar.h
@@ -19,13 +19,10 @@
#ifndef STATUSBAR_H
#define STATUSBAR_H
-#include "ephy-window.h"
+#include <gtk/gtkstatusbar.h>
G_BEGIN_DECLS
-#include <glib-object.h>
-#include <glib.h>
-
typedef struct Statusbar Statusbar;
typedef struct StatusbarClass StatusbarClass;
@@ -39,21 +36,18 @@ typedef struct StatusbarPrivate StatusbarPrivate;
struct Statusbar
{
- GObject parent;
+ GtkStatusbar parent;
StatusbarPrivate *priv;
};
struct StatusbarClass
{
- GObjectClass parent_class;
+ GtkStatusbarClass parent_class;
};
GType statusbar_get_type (void);
-Statusbar *statusbar_new (EphyWindow *window);
-
-void statusbar_set_visibility (Statusbar *s,
- gboolean visibility);
+GtkWidget *statusbar_new (void);
void statusbar_set_security_state (Statusbar *s,
gboolean state,
diff --git a/src/toolbar.c b/src/toolbar.c
index 27c2606f2..51cf64b5f 100755
--- a/src/toolbar.c
+++ b/src/toolbar.c
@@ -18,48 +18,22 @@
*/
#include "toolbar.h"
-#include "ephy-spinner.h"
-#include "ephy-window.h"
-#include "ephy-bonobo-extensions.h"
-#include "ephy-string.h"
-#include "ephy-gui.h"
-#include "ephy-location-entry.h"
+#include "egg-menu-merge.h"
+#include "ephy-file-helpers.h"
#include "ephy-shell.h"
+#include "ephy-location-entry.h"
#include "ephy-dnd.h"
-#include "ephy-toolbar-bonobo-view.h"
-#include "ephy-toolbar-item-factory.h"
-#include "ephy-prefs.h"
-#include "eel-gconf-extensions.h"
-#include "ephy-navigation-button.h"
-#include "ephy-debug.h"
-
-#include <string.h>
-#include <bonobo/bonobo-i18n.h>
-#include <bonobo/bonobo-window.h>
-#include <bonobo/bonobo-control.h>
-#include <bonobo/bonobo-ui-toolbar-button-item.h>
-#include <bonobo/bonobo-property-bag.h>
-#include <gtk/gtkentry.h>
-#include <gtk/gtkmenu.h>
-
-#define DEFAULT_TOOLBAR_SETUP \
- "back_menu=navigation_button(direction=back,arrow=TRUE);" \
- "forward_menu=navigation_button(direction=forward,arrow=TRUE);" \
- "stop=std_toolitem(item=stop);" \
- "reload=std_toolitem(item=reload);" \
- "home=std_toolitem(item=home);" \
- "favicon=favicon;" \
- "location=location;" \
- "spinner=spinner;"
-
-#define ZOOM_DELAY 50
+#include "ephy-spinner.h"
+#include "ephy-spinner-action.h"
+#include "ephy-location-action.h"
+#include "ephy-favicon-action.h"
+#include "ephy-navigation-action.h"
+#include "window-commands.h"
static void toolbar_class_init (ToolbarClass *klass);
static void toolbar_init (Toolbar *t);
static void toolbar_finalize (GObject *object);
static void toolbar_set_window (Toolbar *t, EphyWindow *window);
-static void toolbar_get_widgets (Toolbar *t);
-static void toolbar_changed_cb (EphyToolbar *gt, Toolbar *t);
static void
toolbar_set_property (GObject *object,
guint prop_id,
@@ -78,31 +52,17 @@ enum
PROP_EPHY_WINDOW
};
-enum
-{
- TOOLBAR_ITEM_STYLE_PROP,
- TOOLBAR_ITEM_ORIENTATION_PROP,
- TOOLBAR_ITEM_PRIORITY_PROP
-};
-
static GObjectClass *parent_class = NULL;
struct ToolbarPrivate
{
EphyWindow *window;
- BonoboUIComponent *ui_component;
- EphyTbBonoboView *bview;
-
- GtkWidget *spinner;
+ EggMenuMerge *ui_merge;
+ EggActionGroup *action_group;
gboolean visibility;
GtkWidget *location_entry;
- GSList *navigation_buttons;
- GtkTooltips *tooltips;
+ GtkWidget *spinner;
GtkWidget *favicon;
- GtkWidget *favicon_ebox;
- GtkWidget *zoom_spinbutton;
- guint zoom_timeout_id;
- gboolean zoom_lock;
};
GType
@@ -125,7 +85,7 @@ toolbar_get_type (void)
(GInstanceInitFunc) toolbar_init
};
- toolbar_type = g_type_register_static (EPHY_TYPE_TOOLBAR,
+ toolbar_type = g_type_register_static (G_TYPE_OBJECT,
"Toolbar",
&our_info, 0);
}
@@ -153,8 +113,6 @@ toolbar_class_init (ToolbarClass *klass)
"Parent window",
EPHY_WINDOW_TYPE,
G_PARAM_READWRITE));
- ephy_toolbar_item_register_type
- ("navigation_button", (EphyTbItemConstructor) ephy_navigation_button_new);
}
static void
@@ -190,287 +148,108 @@ toolbar_get_property (GObject *object,
}
static void
-toolbar_location_url_activate_cb (EphyLocationEntry *entry,
- const char *content,
- const char *target,
- EphyWindow *window)
+toolbar_setup_widgets (Toolbar *t)
{
- EphyBookmarks *bookmarks;
-
- bookmarks = ephy_shell_get_bookmarks (ephy_shell);
-
- if (!content)
- {
- ephy_window_load_url (window, target);
- }
- else
- {
- char *url;
-
- url = ephy_bookmarks_solve_smart_url
- (bookmarks, target, content);
- g_return_if_fail (url != NULL);
- ephy_window_load_url (window, url);
- g_free (url);
- }
+ egg_menu_merge_add_ui_from_file (t->priv->ui_merge,
+ ephy_file ("epiphany-toolbar.xml"), NULL);
+ egg_menu_merge_ensure_update (t->priv->ui_merge);
}
static void
-each_url_get_data_binder (EphyDragEachSelectedItemDataGet iteratee,
- gpointer iterator_context, gpointer data)
+add_widget (EggMenuMerge *merge, GtkWidget *widget, EphyWindow *window)
{
- const char *location;
- EphyTab *tab;
- EphyWindow *window = EPHY_WINDOW(iterator_context);
-
- tab = ephy_window_get_active_tab (window);
- location = ephy_tab_get_location (tab);
-
- iteratee (location, -1, -1, -1, -1, data);
}
static void
-favicon_drag_data_get_cb (GtkWidget *widget,
- GdkDragContext *context,
- GtkSelectionData *selection_data,
- guint info,
- guint32 time,
- EphyWindow *window)
+go_location_cb (EggAction *action, char *location, EphyWindow *window)
{
- g_assert (widget != NULL);
- g_return_if_fail (context != NULL);
-
- ephy_dnd_drag_data_get (widget, context, selection_data,
- info, time, window, each_url_get_data_binder);
-}
+ EphyEmbed *embed;
-static void
-toolbar_setup_favicon_ebox (Toolbar *t, GtkWidget *w)
-{
- ToolbarPrivate *p = t->priv;
+ embed = ephy_window_get_active_embed (window);
+ g_return_if_fail (embed != NULL);
- g_return_if_fail (w == p->favicon_ebox);
-
- p->favicon = g_object_ref (gtk_image_new ());
- gtk_container_add (GTK_CONTAINER (p->favicon_ebox), p->favicon);
- gtk_container_set_border_width (GTK_CONTAINER (p->favicon_ebox), 2);
-
- ephy_dnd_url_drag_source_set (p->favicon_ebox);
-
- g_signal_connect (G_OBJECT (p->favicon_ebox),
- "drag_data_get",
- G_CALLBACK (favicon_drag_data_get_cb),
- p->window);
- gtk_widget_show_all (p->favicon_ebox);
-}
-
-static gboolean
-toolbar_zoom_timeout_cb (gpointer data)
-{
- Toolbar *t = data;
- gint zoom = toolbar_get_zoom (t);
-
- g_return_val_if_fail (IS_EPHY_WINDOW (t->priv->window), FALSE);
-
- ephy_window_set_zoom (t->priv->window, zoom);
-
- return FALSE;
-}
-
-static void
-toolbar_zoom_spinbutton_value_changed_cb (GtkSpinButton *sb, Toolbar *t)
-{
- ToolbarPrivate *p = t->priv;
- if (p->zoom_timeout_id != 0)
- {
- g_source_remove (p->zoom_timeout_id);
- }
- if (!p->zoom_lock)
- {
- p->zoom_timeout_id = g_timeout_add (ZOOM_DELAY, toolbar_zoom_timeout_cb, t);
- }
-}
-
-static void
-toolbar_setup_zoom_spinbutton (Toolbar *t, GtkWidget *w)
-{
- g_signal_connect (w, "value_changed",
- G_CALLBACK (toolbar_zoom_spinbutton_value_changed_cb), t);
- gtk_tooltips_set_tip (t->priv->tooltips, w, _("Zoom"), NULL);
+ ephy_embed_load_url (embed, location);
}
static void
-toolbar_setup_location_entry (Toolbar *t, GtkWidget *w)
-{
- EphyAutocompletion *ac = ephy_shell_get_autocompletion (ephy_shell);
- EphyLocationEntry *e;
-
- g_return_if_fail (w == t->priv->location_entry);
- g_return_if_fail (EPHY_IS_LOCATION_ENTRY (w));
-
- e = EPHY_LOCATION_ENTRY (w);
- ephy_location_entry_set_autocompletion (e, ac);
-
- g_signal_connect (e, "activated",
- GTK_SIGNAL_FUNC(toolbar_location_url_activate_cb),
- t->priv->window);
+toolbar_setup_actions (Toolbar *t)
+{
+ EggAction *action;
+
+ t->priv->action_group = egg_action_group_new ("SpecialToolbarActions");
+
+ action = g_object_new (EPHY_TYPE_NAVIGATION_ACTION,
+ "name", "NavigationBack",
+ "label", _("Back"),
+ "stock_id", GTK_STOCK_GO_BACK,
+ "window", t->priv->window,
+ "direction", EPHY_NAVIGATION_DIRECTION_BACK,
+ NULL);
+ g_signal_connect (action, "activate",
+ G_CALLBACK (window_cmd_go_back), t->priv->window);
+ egg_action_group_add_action (t->priv->action_group, action);
+ g_object_unref (action);
+
+ action = g_object_new (EPHY_TYPE_NAVIGATION_ACTION,
+ "name", "NavigationForward",
+ "label", _("Forward"),
+ "stock_id", GTK_STOCK_GO_FORWARD,
+ "window", t->priv->window,
+ "direction", EPHY_NAVIGATION_DIRECTION_FORWARD,
+ NULL);
+ g_signal_connect (action, "activate",
+ G_CALLBACK (window_cmd_go_forward), t->priv->window);
+ egg_action_group_add_action (t->priv->action_group, action);
+ g_object_unref (action);
+
+ action = g_object_new (EPHY_TYPE_NAVIGATION_ACTION,
+ "name", "NavigationUp",
+ "label", _("Up"),
+ "window", t->priv->window,
+ "direction", EPHY_NAVIGATION_DIRECTION_UP,
+ "stock_id", GTK_STOCK_GO_UP,
+ NULL);
+ g_signal_connect (action, "activate",
+ G_CALLBACK (window_cmd_go_up), t->priv->window);
+ egg_action_group_add_action (t->priv->action_group, action);
+ g_object_unref (action);
+
+ action = g_object_new (EPHY_TYPE_SPINNER_ACTION,
+ "name", "Spinner",
+ NULL);
+ egg_action_group_add_action (t->priv->action_group, action);
+ g_object_unref (action);
+
+ action = g_object_new (EPHY_TYPE_LOCATION_ACTION,
+ "name", "Location",
+ NULL);
+ g_signal_connect (action, "go_location",
+ G_CALLBACK (go_location_cb), t->priv->window);
+ egg_action_group_add_action (t->priv->action_group, action);
+ g_object_unref (action);
+
+ action = g_object_new (EPHY_TYPE_FAVICON_ACTION,
+ "name", "Favicon",
+ "window", t->priv->window,
+ NULL);
+ egg_action_group_add_action (t->priv->action_group, action);
+ g_object_unref (action);
}
static void
-toolbar_setup_spinner (Toolbar *t, GtkWidget *w)
-{
- ToolbarPrivate *p = t->priv;
- GtkWidget *spinner;
-
- g_return_if_fail (w == p->spinner);
-
- /* build the spinner and insert it into the box */
- spinner = ephy_spinner_new ();
- ephy_spinner_set_small_mode (EPHY_SPINNER (spinner), TRUE);
- gtk_container_add (GTK_CONTAINER (p->spinner), spinner);
- gtk_widget_show (spinner);
-
- /* don't care about the box anymore */
- g_object_unref (p->spinner);
- p->spinner = g_object_ref (spinner);
-}
-
-
-static void
toolbar_set_window (Toolbar *t, EphyWindow *window)
{
g_return_if_fail (t->priv->window == NULL);
t->priv->window = window;
- t->priv->ui_component = g_object_ref (t->priv->window->ui_component);
-
- ephy_tb_bonobo_view_set_path (t->priv->bview, t->priv->ui_component, "/Toolbar");
-
- toolbar_get_widgets (t);
-}
-
-static void
-toolbar_get_widgets (Toolbar *t)
-{
- ToolbarPrivate *p;
- EphyToolbar *gt;
- EphyTbItem *it;
- GSList *li;
- const gchar *nav_buttons_ids[] = {"back", "back_menu", "up", "up_menu", "forward", "forward_menu" };
- guint i;
-
- LOG ("in toolbar_get_widgets");
-
- g_return_if_fail (IS_TOOLBAR (t));
- p = t->priv;
- g_return_if_fail (IS_EPHY_WINDOW (p->window));
- g_return_if_fail (BONOBO_IS_UI_COMPONENT (p->ui_component));
-
- /* release all the widgets */
-
- for (li = p->navigation_buttons; li; li = li->next)
- {
- g_object_unref (li->data);
- }
- g_slist_free (p->navigation_buttons);
- p->navigation_buttons = NULL;
-
- if (p->favicon_ebox)
- {
- g_object_unref (p->favicon_ebox);
- p->favicon_ebox = NULL;
- }
-
- if (p->favicon)
- {
- g_object_unref (p->favicon);
- p->favicon = NULL;
- }
-
- if (p->location_entry)
- {
- g_object_unref (p->location_entry);
- p->location_entry = NULL;
- }
-
- if (p->spinner)
- {
- g_object_unref (p->spinner);
- p->spinner = NULL;
- }
-
- if (p->zoom_spinbutton)
- {
- g_object_unref (p->zoom_spinbutton);
- p->zoom_spinbutton = NULL;
- }
-
- gt = EPHY_TOOLBAR (t);
-
- for (i = 0; i < G_N_ELEMENTS (nav_buttons_ids); ++i)
- {
- it = ephy_toolbar_get_item_by_id (gt, nav_buttons_ids[i]);
- if (it)
- {
- if (EPHY_IS_NAVIGATION_BUTTON (it))
- {
- LOG ("got a navigation button")
- p->navigation_buttons = g_slist_prepend (p->navigation_buttons, g_object_ref (it));
- if (p->window)
- {
- ephy_tbi_set_window (EPHY_TBI (it), p->window);
- }
- }
- else
- {
- g_warning ("An unexpected button has been found in your toolbar. "
- "Maybe your setup is too old.");
- }
- }
- }
-
- it = ephy_toolbar_get_item_by_id (gt, "location");
- if (it)
- {
- p->location_entry = ephy_tb_item_get_widget (it);
- g_object_ref (p->location_entry);
- toolbar_setup_location_entry (t, p->location_entry);
-
- LOG ("got a location entry")
- }
-
- it = ephy_toolbar_get_item_by_id (gt, "favicon");
- if (it)
- {
- p->favicon_ebox = ephy_tb_item_get_widget (it);
- g_object_ref (p->favicon_ebox);
- toolbar_setup_favicon_ebox (t, p->favicon_ebox);
-
- LOG ("got a favicon ebox")
- }
-
- it = ephy_toolbar_get_item_by_id (gt, "spinner");
- if (it)
- {
- p->spinner = ephy_tb_item_get_widget (it);
- g_object_ref (p->spinner);
- toolbar_setup_spinner (t, p->spinner);
-
- LOG ("got a spinner")
- }
-
- it = ephy_toolbar_get_item_by_id (gt, "zoom");
- if (it)
- {
- p->zoom_spinbutton = ephy_tb_item_get_widget (it);
- g_object_ref (p->zoom_spinbutton);
- toolbar_setup_zoom_spinbutton (t, p->zoom_spinbutton);
-
- LOG ("got a zoom control")
- }
-
- /* update the controls */
- ephy_window_update_all_controls (p->window);
+ t->priv->ui_merge = EGG_MENU_MERGE (window->ui_merge);
+ g_signal_connect (t->priv->ui_merge, "add_widget",
+ G_CALLBACK (add_widget), t);
+
+ toolbar_setup_actions (t);
+ egg_menu_merge_insert_action_group (t->priv->ui_merge,
+ t->priv->action_group, 1);
+ toolbar_setup_widgets (t);
}
static void
@@ -479,38 +258,8 @@ toolbar_init (Toolbar *t)
t->priv = g_new0 (ToolbarPrivate, 1);
t->priv->window = NULL;
- t->priv->ui_component = NULL;
- t->priv->navigation_buttons = NULL;
+ t->priv->ui_merge = NULL;
t->priv->visibility = TRUE;
- t->priv->tooltips = gtk_tooltips_new ();
- g_object_ref (t->priv->tooltips);
- gtk_object_sink (GTK_OBJECT (t->priv->tooltips));
-
- if (!ephy_toolbar_listen_to_gconf (EPHY_TOOLBAR (t), CONF_TOOLBAR_SETUP))
- {
- /* FIXME: make this a dialog? */
- g_warning ("An incorrect toolbar configuration has been found, resetting to the default");
-
- /* this is to make sure we get a toolbar, even if the
- setup is wrong or there is no schema */
- eel_gconf_set_string (CONF_TOOLBAR_SETUP, DEFAULT_TOOLBAR_SETUP);
- }
-
- g_signal_connect (t, "changed", G_CALLBACK (toolbar_changed_cb), t);
-
- t->priv->bview = ephy_tb_bonobo_view_new ();
- ephy_tb_bonobo_view_set_toolbar (t->priv->bview, EPHY_TOOLBAR (t));
-}
-
-static void
-toolbar_changed_cb (EphyToolbar *gt, Toolbar *t)
-{
- g_return_if_fail (gt == EPHY_TOOLBAR (t));
-
- if (t->priv->window)
- {
- toolbar_get_widgets (t);
- }
}
static void
@@ -518,7 +267,6 @@ toolbar_finalize (GObject *object)
{
Toolbar *t;
ToolbarPrivate *p;
- GSList *li;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_TOOLBAR (object));
@@ -528,24 +276,7 @@ toolbar_finalize (GObject *object)
g_return_if_fail (p != NULL);
- if (p->location_entry) g_object_unref (p->location_entry);
- if (p->favicon_ebox) g_object_unref (p->favicon_ebox);
- if (p->favicon) g_object_unref (p->favicon);
- if (p->spinner) g_object_unref (p->spinner);
- if (p->tooltips) g_object_unref (p->tooltips);
- if (p->zoom_spinbutton) g_object_unref (p->zoom_spinbutton);
- if (p->zoom_timeout_id != 0)
- {
- g_source_remove (p->zoom_timeout_id);
- }
-
- for (li = t->priv->navigation_buttons; li; li = li->next)
- {
- g_object_unref (li->data);
- }
- g_slist_free (t->priv->navigation_buttons);
-
- g_object_unref (t->priv->bview);
+ g_object_unref (t->priv->action_group);
g_free (t->priv);
@@ -569,165 +300,106 @@ toolbar_new (EphyWindow *window)
void
toolbar_set_visibility (Toolbar *t, gboolean visibility)
{
- if (visibility == t->priv->visibility) return;
-
- t->priv->visibility = visibility;
-
- ephy_bonobo_set_hidden (BONOBO_UI_COMPONENT(t->priv->ui_component),
- "/Toolbar",
- !visibility);
}
void
toolbar_activate_location (Toolbar *t)
{
- if (t->priv->location_entry)
- {
- ephy_location_entry_activate
- (EPHY_LOCATION_ENTRY(t->priv->location_entry));
- }
+ EggAction *action;
+ GtkWidget *location;
+
+ action = egg_action_group_get_action
+ (t->priv->action_group, "Location");
+ location = ephy_location_action_get_widget
+ (EPHY_LOCATION_ACTION (action));
+ g_return_if_fail (location != NULL);
+
+ ephy_location_entry_activate
+ (EPHY_LOCATION_ENTRY(location));
}
void
toolbar_spinner_start (Toolbar *t)
{
- if (t->priv->spinner)
- {
- ephy_spinner_start (EPHY_SPINNER(t->priv->spinner));
- }
+ EggActionGroup *action_group;
+ EggAction *action;
+
+ action_group = t->priv->action_group;
+ action = egg_action_group_get_action (action_group, "Spinner");
+ g_object_set (action, "throbbing", TRUE, NULL);
}
void
toolbar_spinner_stop (Toolbar *t)
{
- if (t->priv->spinner)
- {
- ephy_spinner_stop (EPHY_SPINNER(t->priv->spinner));
- }
-}
+ EggActionGroup *action_group;
+ EggAction *action;
-static void
-toolbar_navigation_button_set_sensitive (Toolbar *t, EphyNavigationDirection d, gboolean sensitivity)
-{
- GSList *li;
- ToolbarPrivate *p = t->priv;
-
- for (li = p->navigation_buttons; li; li = li->next)
- {
- EphyNavigationButton *b = EPHY_NAVIGATION_BUTTON (li->data);
- if (ephy_navigation_button_get_direction (b) == d)
- {
- ephy_navigation_button_set_sensitive (b, sensitivity);
- }
- }
-}
-
-void
-toolbar_button_set_sensitive (Toolbar *t,
- ToolbarButtonID id,
- gboolean sensitivity)
-{
- switch (id)
- {
- case TOOLBAR_BACK_BUTTON:
- toolbar_navigation_button_set_sensitive (t, EPHY_NAVIGATION_DIRECTION_BACK, sensitivity);
- break;
- case TOOLBAR_FORWARD_BUTTON:
- toolbar_navigation_button_set_sensitive (t, EPHY_NAVIGATION_DIRECTION_FORWARD, sensitivity);
- break;
- case TOOLBAR_UP_BUTTON:
- toolbar_navigation_button_set_sensitive (t, EPHY_NAVIGATION_DIRECTION_UP, sensitivity);
- break;
- case TOOLBAR_STOP_BUTTON:
- ephy_bonobo_set_sensitive (t->priv->ui_component,
- "/commands/GoStop",
- sensitivity);
- break;
- }
+ action_group = t->priv->action_group;
+ action = egg_action_group_get_action (action_group, "Spinner");
+ g_object_set (action, "throbbing", FALSE, NULL);
}
void
toolbar_set_location (Toolbar *t,
- const char *location)
+ const char *alocation)
{
+ EggAction *action;
+ GtkWidget *location;
+
+ action = egg_action_group_get_action
+ (t->priv->action_group, "Location");
+ location = ephy_location_action_get_widget
+ (EPHY_LOCATION_ACTION (action));
g_return_if_fail (location != NULL);
- if (t->priv->location_entry)
- {
- ephy_location_entry_set_location
- (EPHY_LOCATION_ENTRY (t->priv->location_entry), location);
- }
+ ephy_location_entry_set_location
+ (EPHY_LOCATION_ENTRY (location), alocation);
}
void
toolbar_update_favicon (Toolbar *t)
{
- GdkPixbuf *pixbuf = NULL;
- EphyFaviconCache *cache;
EphyTab *tab;
const char *url;
+ EggActionGroup *action_group;
+ EggAction *action;
- cache = ephy_embed_shell_get_favicon_cache (EPHY_EMBED_SHELL (ephy_shell));
tab = ephy_window_get_active_tab (t->priv->window);
url = ephy_tab_get_favicon_url (tab);
-
- if (url)
- {
- pixbuf = ephy_favicon_cache_get (cache, url);
- }
-
- if (pixbuf)
- {
- gtk_image_set_from_pixbuf (GTK_IMAGE (t->priv->favicon), pixbuf);
- }
- else
- {
- gtk_image_set_from_stock (GTK_IMAGE (t->priv->favicon),
- GTK_STOCK_JUMP_TO,
- GTK_ICON_SIZE_MENU);
- }
+ action_group = t->priv->action_group;
+ action = egg_action_group_get_action (action_group, "Favicon");
+ g_object_set (action, "icon", url, NULL);
}
char *
toolbar_get_location (Toolbar *t)
{
- gchar *location;
- if (t->priv->location_entry)
- {
- location = ephy_location_entry_get_location
- (EPHY_LOCATION_ENTRY (t->priv->location_entry));
- }
- else
- {
- location = g_strdup ("");
- }
- return location;
-}
+ EggAction *action;
+ GtkWidget *location;
-gint
-toolbar_get_zoom (Toolbar *t)
-{
- gint zoom;
- if (t->priv->zoom_spinbutton)
- {
- zoom = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (t->priv->zoom_spinbutton));
- }
- else
- {
- zoom = 100;
- }
- return zoom;
+ action = egg_action_group_get_action
+ (t->priv->action_group, "Location");
+ location = ephy_location_action_get_widget
+ (EPHY_LOCATION_ACTION (action));
+ g_return_val_if_fail (location != NULL, NULL);
+
+ return ephy_location_entry_get_location
+ (EPHY_LOCATION_ENTRY (location));
}
void
-toolbar_set_zoom (Toolbar *t, gint zoom)
-{
- ToolbarPrivate *p = t->priv;
- if (p->zoom_spinbutton)
- {
- p->zoom_lock = TRUE;
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (p->zoom_spinbutton), zoom);
- p->zoom_lock = FALSE;
- }
+toolbar_update_navigation_actions (Toolbar *t, gboolean back, gboolean forward, gboolean up)
+{
+ EggActionGroup *action_group;
+ EggAction *action;
+
+ action_group = t->priv->action_group;
+ action = egg_action_group_get_action (action_group, "NavigationBack");
+ g_object_set (action, "sensitive", !back, NULL);
+ action = egg_action_group_get_action (action_group, "NavigationForward");
+ g_object_set (action, "sensitive", !forward, NULL);
+ action = egg_action_group_get_action (action_group, "NavigationUp");
+ g_object_set (action, "sensitive", !up, NULL);
}
diff --git a/src/toolbar.h b/src/toolbar.h
index 5764c14e1..63ebff824 100644
--- a/src/toolbar.h
+++ b/src/toolbar.h
@@ -22,7 +22,6 @@
#include "ephy-window.h"
#include <glib-object.h>
#include <glib.h>
-#include "ephy-toolbar.h"
G_BEGIN_DECLS
@@ -36,23 +35,15 @@ typedef struct ToolbarClass ToolbarClass;
typedef struct ToolbarPrivate ToolbarPrivate;
-typedef enum
-{
- TOOLBAR_BACK_BUTTON,
- TOOLBAR_FORWARD_BUTTON,
- TOOLBAR_STOP_BUTTON,
- TOOLBAR_UP_BUTTON
-} ToolbarButtonID;
-
struct Toolbar
{
- EphyToolbar parent_object;
+ GObject parent_object;
ToolbarPrivate *priv;
};
struct ToolbarClass
{
- EphyToolbarClass parent_class;
+ GObjectClass parent_class;
};
GType toolbar_get_type (void);
@@ -62,10 +53,6 @@ Toolbar *toolbar_new (EphyWindow *window);
void toolbar_set_visibility (Toolbar *t,
gboolean visibility);
-void toolbar_button_set_sensitive (Toolbar *t,
- ToolbarButtonID id,
- gboolean sensitivity);
-
void toolbar_spinner_start (Toolbar *t);
void toolbar_spinner_stop (Toolbar *t);
@@ -75,14 +62,15 @@ char *toolbar_get_location (Toolbar *t);
void toolbar_set_location (Toolbar *t,
const char *location);
-gint toolbar_get_zoom (Toolbar *t);
-
-void toolbar_set_zoom (Toolbar *t, gint zoom);
-
void toolbar_activate_location (Toolbar *t);
void toolbar_update_favicon (Toolbar *t);
+void toolbar_update_navigation_actions (Toolbar *t,
+ gboolean back,
+ gboolean forward,
+ gboolean up);
+
G_END_DECLS
#endif
diff --git a/src/window-commands.c b/src/window-commands.c
index 0364a7d60..ece083b35 100644
--- a/src/window-commands.c
+++ b/src/window-commands.c
@@ -26,8 +26,6 @@
#include "ephy-prefs.h"
#include "ephy-embed-utils.h"
#include "pdm-dialog.h"
-#include "toolbar.h"
-#include "ephy-toolbar-editor.h"
#include "ephy-bookmarks-editor.h"
#include "ephy-new-bookmark.h"
@@ -58,9 +56,8 @@
"separator;"
void
-window_cmd_edit_find (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_edit_find (EggAction *action,
+ EphyWindow *window)
{
EphyDialog *dialog;
dialog = ephy_window_get_find_dialog (window);
@@ -78,9 +75,8 @@ print_dialog_preview_cb (PrintDialog *dialog,
}
void
-window_cmd_file_print (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_file_print (EggAction *action,
+ EphyWindow *window)
{
EphyDialog *dialog;
EphyEmbed *embed;
@@ -99,9 +95,8 @@ window_cmd_file_print (BonoboUIComponent *uic,
}
void
-window_cmd_go_back (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_go_back (EggAction *action,
+ EphyWindow *window)
{
EphyEmbed *embed;
@@ -112,9 +107,8 @@ window_cmd_go_back (BonoboUIComponent *uic,
}
void
-window_cmd_go_up (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_go_up (EggAction *action,
+ EphyWindow *window)
{
EphyEmbed *embed;
@@ -125,9 +119,8 @@ window_cmd_go_up (BonoboUIComponent *uic,
}
void
-window_cmd_file_send_to (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_file_send_to (EggAction *action,
+ EphyWindow *window)
{
char *url;
EphyTab *tab;
@@ -165,9 +158,8 @@ window_cmd_file_send_to (BonoboUIComponent *uic,
}
void
-window_cmd_go_forward (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_go_forward (EggAction *action,
+ EphyWindow *window)
{
EphyEmbed *embed;
@@ -178,28 +170,8 @@ window_cmd_go_forward (BonoboUIComponent *uic,
}
void
-window_cmd_go_go (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
-{
- Toolbar *tb;
-
- g_return_if_fail (IS_EPHY_WINDOW (window));
-
- tb = ephy_window_get_toolbar (window);
-
- if (tb)
- {
- char *location = toolbar_get_location (tb);
- ephy_window_load_url (window, location);
- g_free (location);
- }
-}
-
-void
-window_cmd_go_home (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_go_home (EggAction *action,
+ EphyWindow *window)
{
EphyEmbed *embed;
char *location;
@@ -216,30 +188,15 @@ window_cmd_go_home (BonoboUIComponent *uic,
}
void
-window_cmd_go_myportal (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
-{
- EphyEmbed *embed;
-
- embed = ephy_window_get_active_embed (window);
- g_return_if_fail (embed != NULL);
-
- ephy_embed_load_url (embed, "myportal:");
-}
-
-void
-window_cmd_go_location (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_go_location (EggAction *action,
+ EphyWindow *window)
{
ephy_window_activate_location (window);
}
void
-window_cmd_go_stop (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_view_stop (EggAction *action,
+ EphyWindow *window)
{
EphyEmbed *embed;
@@ -250,9 +207,8 @@ window_cmd_go_stop (BonoboUIComponent *uic,
}
void
-window_cmd_go_reload (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_view_reload (EggAction *action,
+ EphyWindow *window)
{
EphyEmbed *embed;
@@ -263,23 +219,8 @@ window_cmd_go_reload (BonoboUIComponent *uic,
}
void
-window_cmd_new (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
-{
- EphyTab *tab;
-
- tab = ephy_window_get_active_tab (window);
-
- ephy_shell_new_tab (ephy_shell, window, tab, NULL,
- EPHY_NEW_TAB_HOMEPAGE |
- EPHY_NEW_TAB_JUMP);
-}
-
-void
-window_cmd_new_window (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_file_new_window (EggAction *action,
+ EphyWindow *window)
{
EphyTab *tab;
@@ -292,9 +233,8 @@ window_cmd_new_window (BonoboUIComponent *uic,
}
void
-window_cmd_new_tab (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_file_new_tab (EggAction *action,
+ EphyWindow *window)
{
EphyTab *tab;
@@ -307,9 +247,8 @@ window_cmd_new_tab (BonoboUIComponent *uic,
}
void
-window_cmd_bookmarks_edit (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_go_bookmarks (EggAction *action,
+ EphyWindow *window)
{
GtkWidget *dialog;
EphyBookmarks *bookmarks;
@@ -321,9 +260,8 @@ window_cmd_bookmarks_edit (BonoboUIComponent *uic,
}
void
-window_cmd_bookmarks_add_default (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_file_add_bookmark (EggAction *action,
+ EphyWindow *window)
{
EphyTab *tab;
EphyEmbed *embed;
@@ -358,9 +296,8 @@ window_cmd_bookmarks_add_default (BonoboUIComponent *uic,
}
void
-window_cmd_file_open (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_file_open (EggAction *action,
+ EphyWindow *window)
{
gchar *dir, *retDir;
gchar *file = NULL;
@@ -406,9 +343,8 @@ window_cmd_file_open (BonoboUIComponent *uic,
}
void
-window_cmd_file_save_as (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_file_save_as (EggAction *action,
+ EphyWindow *window)
{
EphyEmbed *embed;
EphyEmbedPersist *persist;
@@ -430,9 +366,8 @@ window_cmd_file_save_as (BonoboUIComponent *uic,
}
void
-window_cmd_file_close_tab (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_file_close_tab (EggAction *action,
+ EphyWindow *window)
{
EphyTab *tab;
@@ -443,17 +378,15 @@ window_cmd_file_close_tab (BonoboUIComponent *uic,
}
void
-window_cmd_file_close_window (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_file_close_window (EggAction *action,
+ EphyWindow *window)
{
gtk_widget_destroy (GTK_WIDGET(window));
}
void
-window_cmd_edit_cut (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_edit_cut (EggAction *action,
+ EphyWindow *window)
{
GtkWidget *widget = gtk_window_get_focus (GTK_WINDOW (window));
@@ -472,9 +405,8 @@ window_cmd_edit_cut (BonoboUIComponent *uic,
}
void
-window_cmd_edit_copy (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_edit_copy (EggAction *action,
+ EphyWindow *window)
{
GtkWidget *widget = gtk_window_get_focus (GTK_WINDOW (window));
@@ -494,9 +426,8 @@ window_cmd_edit_copy (BonoboUIComponent *uic,
}
void
-window_cmd_edit_paste (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_edit_paste (EggAction *action,
+ EphyWindow *window)
{
GtkWidget *widget = gtk_window_get_focus (GTK_WINDOW (window));
@@ -516,9 +447,8 @@ window_cmd_edit_paste (BonoboUIComponent *uic,
}
void
-window_cmd_edit_select_all (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_edit_select_all (EggAction *action,
+ EphyWindow *window)
{
GtkWidget *widget = gtk_window_get_focus (GTK_WINDOW (window));
@@ -538,9 +468,8 @@ window_cmd_edit_select_all (BonoboUIComponent *uic,
}
void
-window_cmd_edit_find_next (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_edit_find_next (EggAction *action,
+ EphyWindow *window)
{
EphyDialog *dialog;
@@ -552,9 +481,8 @@ window_cmd_edit_find_next (BonoboUIComponent *uic,
}
void
-window_cmd_edit_find_prev (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_edit_find_prev (EggAction *action,
+ EphyWindow *window)
{
EphyDialog *dialog;
@@ -566,9 +494,20 @@ window_cmd_edit_find_prev (BonoboUIComponent *uic,
}
void
-window_cmd_view_zoom_in (BonoboUIComponent *uic,
- EphyWindow *window,
- const char *verbname)
+window_cmd_view_statusbar (EggAction *action,
+ EphyWindow *window)
+{
+}
+
+void
+window_cmd_view_fullscreen (EggAction *action,
+ EphyWindow *window)
+{
+}
+
+void
+window_cmd_view_zoom_in (EggAction *action,
+ EphyWindow *window)
{
EphyEmbed *embed;
int zoom;
@@ -581,9 +520,8 @@ window_cmd_view_zoom_in (BonoboUIComponent *uic,
}
void
-window_cmd_view_zoom_out (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_view_zoom_out (EggAction *action,
+ EphyWindow *window)
{
EphyEmbed *embed;
int zoom;
@@ -599,17 +537,15 @@ window_cmd_view_zoom_out (BonoboUIComponent *uic,
}
void
-window_cmd_view_zoom_normal (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_view_zoom_normal (EggAction *action,
+ EphyWindow *window)
{
ephy_window_set_zoom (window, 100);
}
void
-window_cmd_view_page_source (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_view_page_source (EggAction *action,
+ EphyWindow *window)
{
EphyTab *tab;
@@ -621,17 +557,15 @@ window_cmd_view_page_source (BonoboUIComponent *uic,
}
void
-window_cmd_tools_history (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_go_history (EggAction *action,
+ EphyWindow *window)
{
ephy_window_show_history (window);
}
void
-window_cmd_tools_pdm (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_edit_personal_data (EggAction *action,
+ EphyWindow *window)
{
EphyDialog *dialog;
@@ -641,9 +575,8 @@ window_cmd_tools_pdm (BonoboUIComponent *uic,
}
void
-window_cmd_edit_prefs (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_edit_prefs (EggAction *action,
+ EphyWindow *window)
{
GtkDialog *dialog;
@@ -655,101 +588,15 @@ window_cmd_edit_prefs (BonoboUIComponent *uic,
gtk_widget_show (GTK_WIDGET(dialog));
}
-static void
-window_cmd_settings_toolbar_editor_revert_clicked_cb (GtkButton *b, EphyTbEditor *tbe)
-{
- gchar *def;
-
- g_return_if_fail (EPHY_IS_TB_EDITOR (tbe));
-
- eel_gconf_unset (CONF_TOOLBAR_SETUP);
- def = eel_gconf_get_string (CONF_TOOLBAR_SETUP);
- if (def)
- {
- EphyToolbar *current;
- EphyToolbar *avail;
- current = ephy_tb_editor_get_toolbar (tbe);
- ephy_toolbar_parse (current, def);
- g_free (def);
-
- avail = ephy_tb_editor_get_available (tbe);
- g_object_ref (avail);
- ephy_toolbar_parse (avail, AVAILABLE_TOOLBAR_ITEMS);
- ephy_tb_editor_set_available (tbe, avail);
- g_object_unref (avail);
- }
-
-}
-
-static void
-window_cmd_settings_toolbar_editor_current_changed_cb (EphyToolbar *tb, gpointer data)
-{
- gchar *current_str;
-
- g_return_if_fail (EPHY_IS_TOOLBAR (tb));
-
- current_str = ephy_toolbar_to_string (tb);
- eel_gconf_set_string (CONF_TOOLBAR_SETUP, current_str);
- g_free (current_str);
-}
-
void
-window_cmd_settings_toolbar_editor (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_edit_toolbar (EggAction *action,
+ EphyWindow *window)
{
- static EphyTbEditor *tbe = NULL;
- EphyToolbar *avail;
- EphyToolbar *current;
- gchar *current_str;
- GtkButton *revert_button;
-
- avail = ephy_toolbar_new ();
- ephy_toolbar_parse (avail, AVAILABLE_TOOLBAR_ITEMS);
-
- current_str = eel_gconf_get_string (CONF_TOOLBAR_SETUP);
- current = ephy_toolbar_new ();
- if (current_str)
- {
- ephy_toolbar_parse (current, current_str);
- g_free (current_str);
- }
-
- if (!tbe)
- {
- tbe = ephy_tb_editor_new ();
- g_object_add_weak_pointer (G_OBJECT (tbe),
- (void **)&tbe);
- ephy_tb_editor_set_parent (tbe,
- GTK_WIDGET(window));
- }
- else
- {
- ephy_tb_editor_show (tbe);
- return;
- }
-
- ephy_tb_editor_set_toolbar (tbe, current);
- ephy_tb_editor_set_available (tbe, avail);
- g_object_unref (avail);
- g_object_unref (current);
-
- g_signal_connect (current, "changed",
- G_CALLBACK (window_cmd_settings_toolbar_editor_current_changed_cb), NULL);
-
- revert_button = ephy_tb_editor_get_revert_button (tbe);
- gtk_widget_show (GTK_WIDGET (revert_button));
-
- g_signal_connect (revert_button, "clicked",
- G_CALLBACK (window_cmd_settings_toolbar_editor_revert_clicked_cb), tbe);
-
- ephy_tb_editor_show (tbe);
}
void
-window_cmd_help_about (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_help_about (EggAction *action,
+ EphyWindow *window)
{
static GtkWidget *about = NULL;
@@ -792,23 +639,8 @@ window_cmd_help_about (BonoboUIComponent *uic,
}
void
-window_cmd_set_charset (BonoboUIComponent *uic,
- EncodingMenuData *data,
- const char* verbname)
-{
- EphyWindow *window = data->data;
- EphyEmbed *embed;
-
- embed = ephy_window_get_active_embed (window);
- g_return_if_fail (embed != NULL);
-
- ephy_embed_set_charset (embed, data->encoding);
-}
-
-void
-window_cmd_tabs_next (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_tabs_next (EggAction *action,
+ EphyWindow *window)
{
GList *tabs;
EphyTab *tab;
@@ -829,9 +661,8 @@ window_cmd_tabs_next (BonoboUIComponent *uic,
}
void
-window_cmd_tabs_previous (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_tabs_previous (EggAction *action,
+ EphyWindow *window)
{
GList *tabs;
EphyTab *tab;
@@ -852,22 +683,19 @@ window_cmd_tabs_previous (BonoboUIComponent *uic,
}
void
-window_cmd_tabs_move_left (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_tabs_move_left (EggAction *action,
+ EphyWindow *window)
{
}
-void window_cmd_tabs_move_right (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+void window_cmd_tabs_move_right (EggAction *action,
+ EphyWindow *window)
{
}
void
-window_cmd_tabs_detach (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname)
+window_cmd_tabs_detach (EggAction *action,
+ EphyWindow *window)
{
EphyTab *tab;
GtkWidget *src_page;
@@ -886,32 +714,3 @@ window_cmd_tabs_detach (BonoboUIComponent *uic,
ephy_tab_set_window (tab, new_win);
gtk_widget_show (GTK_WIDGET (new_win));
}
-
-void
-window_cmd_help_manual (BonoboUIComponent *uic,
- char *filename,
- const char* verbname)
-{
- GError *error;
- GtkWidget *dialog;
-
- error = NULL;
- gnome_help_display ("Ephy.xml", NULL, &error);
-
- if (error)
- {
- dialog = gtk_message_dialog_new (NULL,
- GTK_DIALOG_MODAL,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
- _("There was an error displaying help: \n%s"),
- error->message);
- g_signal_connect (G_OBJECT (dialog), "response",
- G_CALLBACK (gtk_widget_destroy),
- NULL);
-
- gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
- gtk_widget_show (dialog);
- g_error_free (error);
- }
-}
diff --git a/src/window-commands.h b/src/window-commands.h
index df05a4d50..bf733897c 100644
--- a/src/window-commands.h
+++ b/src/window-commands.h
@@ -16,181 +16,136 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#include "egg-action.h"
#include "ephy-window.h"
#include "ephy-embed-utils.h"
-#include <bonobo/bonobo-ui-component.h>
+void window_cmd_edit_find (EggAction *action,
+ EphyWindow *window);
-void window_cmd_edit_find (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_file_print (EggAction *action,
+ EphyWindow *window);
-void window_cmd_file_print (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_view_stop (EggAction *action,
+ EphyWindow *window);
-void window_cmd_go_stop (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_go_back (EggAction *action,
+ EphyWindow *window);
-void window_cmd_go_back (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_go_forward (EggAction *action,
+ EphyWindow *window);
-void window_cmd_go_forward (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_go_location (EggAction *action,
+ EphyWindow *window);
-void window_cmd_go_go (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_go_up (EggAction *action,
+ EphyWindow *window);
-void window_cmd_go_up (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_go_home (EggAction *action,
+ EphyWindow *window);
-void window_cmd_go_home (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_go_myportal (EggAction *action,
+ EphyWindow *window);
-void window_cmd_go_myportal (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_go_location (EggAction *action,
+ EphyWindow *window);
-void window_cmd_go_location (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_view_reload (EggAction *action,
+ EphyWindow *window);
-void window_cmd_go_reload (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_new (EggAction *action,
+ EphyWindow *window);
-void window_cmd_new (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_file_new_window (EggAction *action,
+ EphyWindow *window);
-void window_cmd_new_window (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_file_new_tab (EggAction *action,
+ EphyWindow *window);
-void window_cmd_new_tab (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_file_add_bookmark(EggAction *action,
+ EphyWindow *window);
-void window_cmd_bookmarks_add_default (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_go_bookmarks (EggAction *action,
+ EphyWindow *window);
-void window_cmd_bookmarks_edit (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_file_open (EggAction *action,
+ EphyWindow *window);
-void window_cmd_file_open (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_file_save_as (EggAction *action,
+ EphyWindow *window);
-void window_cmd_file_save_as (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_file_send_to (EggAction *action,
+ EphyWindow *window);
-void window_cmd_file_send_to (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_file_close_tab (EggAction *action,
+ EphyWindow *window);
-void window_cmd_file_close_tab (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_file_close_window (EggAction *action,
+ EphyWindow *window);
-void window_cmd_file_close_window (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_edit_cut (EggAction *action,
+ EphyWindow *window);
-void window_cmd_edit_cut (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_edit_copy (EggAction *action,
+ EphyWindow *window);
-void window_cmd_edit_copy (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_edit_paste (EggAction *action,
+ EphyWindow *window);
-void window_cmd_edit_paste (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_edit_select_all (EggAction *action,
+ EphyWindow *window);
-void window_cmd_edit_select_all (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_edit_find_next (EggAction *action,
+ EphyWindow *window);
-void window_cmd_edit_find_next (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_edit_find_prev (EggAction *action,
+ EphyWindow *window);
-void window_cmd_edit_find_prev (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_view_statusbar (EggAction *action,
+ EphyWindow *window);
-void window_cmd_view_zoom_in (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_view_fullscreen (EggAction *action,
+ EphyWindow *window);
-void window_cmd_view_zoom_out (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_view_zoom_in (EggAction *action,
+ EphyWindow *window);
-void window_cmd_view_zoom_normal(BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_view_zoom_out (EggAction *action,
+ EphyWindow *window);
-void window_cmd_view_page_source(BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_view_zoom_normal(EggAction *action,
+ EphyWindow *window);
-void window_cmd_tools_history (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_view_page_source(EggAction *action,
+ EphyWindow *window);
-void window_cmd_tools_pdm (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_go_history (EggAction *action,
+ EphyWindow *window);
-void window_cmd_edit_prefs (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
+void window_cmd_edit_personal_data (EggAction *action,
+ EphyWindow *window);
-void
-window_cmd_settings_toolbar_editor (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
-
-void window_cmd_help_about (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
-
-void window_cmd_set_charset (BonoboUIComponent *uic,
- EncodingMenuData *data,
- const char* verbname);
-
-void window_cmd_tabs_next (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
-
-void window_cmd_tabs_previous (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
-
-void window_cmd_tabs_move_left (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
-
-void window_cmd_tabs_move_right (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
-
-void window_cmd_tabs_detach (BonoboUIComponent *uic,
- EphyWindow *window,
- const char* verbname);
-
-void window_cmd_help_manual (BonoboUIComponent *uic,
- char *filename,
- const char* verbname);
+void window_cmd_edit_prefs (EggAction *action,
+ EphyWindow *window);
+
+void window_cmd_edit_toolbar (EggAction *action,
+ EphyWindow *window);
+
+void window_cmd_help_about (EggAction *action,
+ EphyWindow *window);
+
+void window_cmd_tabs_next (EggAction *action,
+ EphyWindow *window);
+
+void window_cmd_tabs_previous (EggAction *action,
+ EphyWindow *window);
+
+void window_cmd_tabs_move_left (EggAction *action,
+ EphyWindow *window);
+
+void window_cmd_tabs_move_right (EggAction *action,
+ EphyWindow *window);
+
+void window_cmd_tabs_detach (EggAction *action,
+ EphyWindow *window);