aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarco Pesenti Gritti <marco@it.gnome.org>2002-12-31 21:52:44 +0800
committerMarco Pesenti Gritti <mpeseng@src.gnome.org>2002-12-31 21:52:44 +0800
commit6afec98b2cc4c33cd4128d045035a0ec7d43629c (patch)
treefbca72a16cc232b59b16adbe365f29f8bba1b010
parentbeec33b028bdeb5f0da6ed51305f32e3b8041f6e (diff)
downloadgsoc2013-epiphany-6afec98b2cc4c33cd4128d045035a0ec7d43629c.tar
gsoc2013-epiphany-6afec98b2cc4c33cd4128d045035a0ec7d43629c.tar.gz
gsoc2013-epiphany-6afec98b2cc4c33cd4128d045035a0ec7d43629c.tar.bz2
gsoc2013-epiphany-6afec98b2cc4c33cd4128d045035a0ec7d43629c.tar.lz
gsoc2013-epiphany-6afec98b2cc4c33cd4128d045035a0ec7d43629c.tar.xz
gsoc2013-epiphany-6afec98b2cc4c33cd4128d045035a0ec7d43629c.tar.zst
gsoc2013-epiphany-6afec98b2cc4c33cd4128d045035a0ec7d43629c.zip
Resync with galeon.
2002-12-31 Marco Pesenti Gritti <marco@it.gnome.org> * embed/mozilla/FilePicker.cpp: * embed/mozilla/FilePicker.h: * embed/mozilla/mozilla-embed-shell.cpp: Resync with galeon. * data/epiphany.schemas.in: * lib/ephy-bonobo-extensions.c: (ephy_bonobo_add_numbered_widget): * lib/ephy-bonobo-extensions.h: * lib/toolbar/Makefile.am: * lib/toolbar/ephy-tbi-std-toolitem.c: (ephy_tbi_std_toolitem_init), (ephy_tbi_std_toolitem_get_icon_impl), (ephy_tbi_std_toolitem_get_name_human_impl), (ephy_tbi_std_toolitem_to_string_impl), (ephy_tbi_std_toolitem_add_to_bonobo_tb_impl), (ephy_tbi_std_toolitem_parse_properties_impl), (ephy_tbi_std_toolitem_set_item): * lib/toolbar/ephy-tbi-std-toolitem.h: * lib/toolbar/ephy-toolbar-item-factory.c: (ephy_tb_item_factory_init), (ephy_toolbar_item_create_from_string), (ephy_toolbar_item_register_type): * lib/toolbar/ephy-toolbar-item-factory.h: * src/Makefile.am: * src/toolbar.c: (toolbar_class_init), (toolbar_set_property), (toolbar_get_widgets), (toolbar_init), (toolbar_finalize), (toolbar_navigation_button_set_sensitive), (toolbar_button_set_sensitive): * src/window-commands.c: Resync with galeon. Now we use a widget for navigation buttons.
-rw-r--r--ChangeLog36
-rw-r--r--data/epiphany.schemas.in2
-rw-r--r--embed/mozilla/FilePicker.cpp67
-rw-r--r--embed/mozilla/FilePicker.h17
-rw-r--r--embed/mozilla/mozilla-embed-shell.cpp8
-rw-r--r--lib/ephy-bonobo-extensions.c16
-rw-r--r--lib/ephy-bonobo-extensions.h2
-rw-r--r--lib/toolbar/Makefile.am4
-rw-r--r--lib/toolbar/ephy-tb-button.c746
-rw-r--r--lib/toolbar/ephy-tb-button.h79
-rw-r--r--lib/toolbar/ephy-tbi-std-toolitem.c112
-rw-r--r--lib/toolbar/ephy-tbi-std-toolitem.h6
-rw-r--r--lib/toolbar/ephy-toolbar-item-factory.c80
-rw-r--r--lib/toolbar/ephy-toolbar-item-factory.h4
-rw-r--r--src/Makefile.am6
-rw-r--r--src/ephy-navigation-button.c614
-rw-r--r--src/ephy-navigation-button.h79
-rw-r--r--src/ephy-tbi.c193
-rw-r--r--src/ephy-tbi.h70
-rwxr-xr-xsrc/toolbar.c393
-rw-r--r--src/window-commands.c15
21 files changed, 2037 insertions, 512 deletions
diff --git a/ChangeLog b/ChangeLog
index d5e481d10..de4a0f1e1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,41 @@
2002-12-31 Marco Pesenti Gritti <marco@it.gnome.org>
+ * embed/mozilla/FilePicker.cpp:
+ * embed/mozilla/FilePicker.h:
+ * embed/mozilla/mozilla-embed-shell.cpp:
+
+ Resync with galeon.
+
+ * data/epiphany.schemas.in:
+ * lib/ephy-bonobo-extensions.c: (ephy_bonobo_add_numbered_widget):
+ * lib/ephy-bonobo-extensions.h:
+ * lib/toolbar/Makefile.am:
+ * lib/toolbar/ephy-tbi-std-toolitem.c:
+ (ephy_tbi_std_toolitem_init),
+ (ephy_tbi_std_toolitem_get_icon_impl),
+ (ephy_tbi_std_toolitem_get_name_human_impl),
+ (ephy_tbi_std_toolitem_to_string_impl),
+ (ephy_tbi_std_toolitem_add_to_bonobo_tb_impl),
+ (ephy_tbi_std_toolitem_parse_properties_impl),
+ (ephy_tbi_std_toolitem_set_item):
+ * lib/toolbar/ephy-tbi-std-toolitem.h:
+ * lib/toolbar/ephy-toolbar-item-factory.c:
+ (ephy_tb_item_factory_init),
+ (ephy_toolbar_item_create_from_string),
+ (ephy_toolbar_item_register_type):
+ * lib/toolbar/ephy-toolbar-item-factory.h:
+ * src/Makefile.am:
+ * src/toolbar.c: (toolbar_class_init), (toolbar_set_property),
+ (toolbar_get_widgets), (toolbar_init), (toolbar_finalize),
+ (toolbar_navigation_button_set_sensitive),
+ (toolbar_button_set_sensitive):
+ * src/window-commands.c:
+
+ Resync with galeon. Now we use a widget for navigation
+ buttons.
+
+2002-12-31 Marco Pesenti Gritti <marco@it.gnome.org>
+
* data/glade/prefs-dialog.glade:
Remove hidden filtering page.
diff --git a/data/epiphany.schemas.in b/data/epiphany.schemas.in
index 7450fefc7..f45104907 100644
--- a/data/epiphany.schemas.in
+++ b/data/epiphany.schemas.in
@@ -322,7 +322,7 @@
<applyto>/apps/epiphany/interface/toolbar_setup</applyto>
<owner>epiphany</owner>
<type>string</type>
- <default>back=std_toolitem(item=back);back_history=navigation_history(direction=back);forward=std_toolitem(item=forward);forward_history=navigation_history(direction=forward);stop=std_toolitem(item=stop);reload=std_toolitem(item=reload);home_separator=separator;home=std_toolitem(item=home);favicons_separator=separator;favicon=favicon;location=location;spinner=spinner;</default>
+ <default>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_separator=separator;home=std_toolitem(item=home);favicons_separator=separator;favicon=favicon;location=location;spinner=spinner;</default>
<locale name="C">
<short>Toolbar setup</short>
<long>The list of controls that will be present in the toolbar. You should edit
diff --git a/embed/mozilla/FilePicker.cpp b/embed/mozilla/FilePicker.cpp
index baae069ef..6ef57d503 100644
--- a/embed/mozilla/FilePicker.cpp
+++ b/embed/mozilla/FilePicker.cpp
@@ -36,6 +36,7 @@
#include "ephy-gui.h"
#include "eel-gconf-extensions.h"
+#include <glib/gconvert.h>
#include <gtk/gtkmain.h>
#include <gtk/gtksignal.h>
#include <gtk/gtkmenu.h>
@@ -74,20 +75,17 @@
#include "FilePicker.h"
#include "MozillaPrivate.h"
-void filePicker_save_content_cb(GtkToggleButton *aButton,
- GFilePicker *aFilePicker);
-
/* Implementation file */
NS_IMPL_ISUPPORTS1(GFilePicker, nsIFilePicker)
-GFilePicker::GFilePicker(PRBool showContentCheck, FileFormat *fileFormats) :
- mSaveContent(PR_FALSE)
+GFilePicker::GFilePicker(PRBool aShowContentCheck, FileFormat *aFileFormats) :
+ mShowContentCheck(aShowContentCheck),
+ mSaveContentCheck(NULL),
+ mFileFormats(aFileFormats)
{
NS_INIT_ISUPPORTS();
- /* member initializers and constructor code */
- mShowContentCheck = showContentCheck;
- mFileFormats = fileFormats;
+ /* member initializers and constructor code */
mFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID);
mDisplayDirectory = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID);
mDisplayDirectory->InitWithNativePath(nsDependentCString(g_get_home_dir()));
@@ -147,13 +145,28 @@ NS_IMETHODIMP GFilePicker::SetFilterIndex(PRInt32 aFilterIndex)
/* attribute wstring defaultString; */
NS_IMETHODIMP GFilePicker::GetDefaultString(PRUnichar * *aDefaultString)
{
- *aDefaultString = ToNewUnicode(NS_ConvertUTF8toUCS2(mDefaultString));
+ guint bytesRead(0), bytesWritten(0);
+ gchar *utf8DefaultString = g_filename_to_utf8(mDefaultString.get(), -1,
+ &bytesRead,
+ &bytesWritten, NULL);
+
+ *aDefaultString = ToNewUnicode(NS_ConvertUTF8toUCS2(utf8DefaultString));
+ g_free(utf8DefaultString);
+
return NS_OK;
}
NS_IMETHODIMP GFilePicker::SetDefaultString(const PRUnichar *aDefaultString)
{
if (aDefaultString)
- mDefaultString = NS_ConvertUCS2toUTF8(aDefaultString);
+ {
+ guint bytesRead(0), bytesWritten(0);
+ gchar *localeDefaultString =
+ g_filename_from_utf8(NS_ConvertUCS2toUTF8(aDefaultString).get(),
+ -1, &bytesRead,
+ &bytesWritten, NULL);
+ mDefaultString = localeDefaultString;
+ g_free(localeDefaultString);
+ }
else
mDefaultString = "";
return NS_OK;
@@ -244,14 +257,10 @@ NS_IMETHODIMP GFilePicker::Show(PRInt16 *_retval)
gtk_box_pack_end(GTK_BOX(GTK_FILE_SELECTION(mFileSelector)->action_area),
bbox, TRUE, TRUE, 0);
- GtkWidget *saveContent =
+ mSaveContentCheck =
gtk_check_button_new_with_label(_("Save with content"));
- g_signal_connect(G_OBJECT(saveContent),
- "clicked",
- G_CALLBACK(filePicker_save_content_cb),
- (gpointer)this);
- gtk_box_pack_start(GTK_BOX(bbox), saveContent,
+ gtk_box_pack_start(GTK_BOX(bbox), mSaveContentCheck,
FALSE, FALSE, 0);
gtk_widget_show_all(bbox);
@@ -447,25 +456,28 @@ NS_METHOD GFilePicker::HandleFilePickerResult(PRInt16 *retval)
if (mFormatChooser)
{
- gint i = 0;
GtkWidget *menu = gtk_option_menu_get_menu
(GTK_OPTION_MENU(mFormatChooser));
- GList *iterator = GTK_MENU_SHELL(menu)->children;
GtkWidget *selected = gtk_menu_get_active (GTK_MENU(menu));
- while (iterator)
+ gint i(0);
+ for (GList *iterator = GTK_MENU_SHELL(menu)->children ;
+ iterator ; iterator = iterator->next, i++)
{
if (iterator->data == selected)
{
mSelectedFileFormat = i;
break;
}
- iterator = iterator->next;
- i++;
}
}
- *retval = mSaveContent ? returnOKSaveContent : returnOK;
+ if (GTK_IS_TOGGLE_BUTTON(mSaveContentCheck))
+ *retval = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(mSaveContentCheck)) ?
+ returnOKSaveContent : returnOK;
+ else
+ *retval = returnOK;
+
return NS_OK;
}
@@ -492,14 +504,3 @@ nsresult NS_NewFilePickerFactory(nsIFactory** aFactory)
return NS_OK;
}
-
-////////////////////////////////////////////////////////////////////////////////
-// begin FileSelector callbacks.
-////////////////////////////////////////////////////////////////////////////////
-
-void filePicker_save_content_cb(GtkToggleButton *aButton,
- GFilePicker *aFilePicker)
-{
- aFilePicker->mSaveContent = gtk_toggle_button_get_active (aButton) ?
- PR_TRUE : PR_FALSE;
-}
diff --git a/embed/mozilla/FilePicker.h b/embed/mozilla/FilePicker.h
index 93c025637..7433b8b2d 100644
--- a/embed/mozilla/FilePicker.h
+++ b/embed/mozilla/FilePicker.h
@@ -16,8 +16,8 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#ifndef FILE_PICKER_H
-#define FILE_PICKER_H
+#ifndef __FilePicker_h
+#define __FilePicker_h
#include "nsIFilePicker.h"
#include "nsError.h"
@@ -47,21 +47,20 @@ extern nsresult NS_NewFilePickerFactory(nsIFactory** aFactory);
/* Header file */
class GFilePicker : public nsIFilePicker
{
- friend void filePicker_save_content_cb(GtkToggleButton *aButton,
- GFilePicker *aFilePicker);
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIFILEPICKER
- enum { returnOK = nsIFilePicker::returnOK,
+ enum { returnOK = nsIFilePicker::returnOK,
returnCancel = nsIFilePicker::returnCancel,
returnReplace = nsIFilePicker::returnReplace,
returnOKSaveContent = 256 };
- GFilePicker(PRBool aShowContentCheck = PR_FALSE, FileFormat *aFileFormats = NULL);
+ GFilePicker(PRBool aShowContentCheck = PR_FALSE,
+ FileFormat *aFileFormats = nsnull);
virtual ~GFilePicker();
/* additional members */
- NS_METHOD InitWithGtkWidget(GtkWidget *aParentWidget,
+ NS_METHOD InitWithGtkWidget(GtkWidget *aParentWidget,
const char *aTitle, PRInt16 aMode);
NS_METHOD SanityCheck(PRBool *retIsSane);
@@ -82,11 +81,11 @@ class GFilePicker : public nsIFilePicker
PRInt16 mMode;
PRBool mShowContentCheck;
- PRBool mSaveContent;
- GtkWidget *mParentWidget;
+ GtkWidget *mParentWidget;
GtkWidget *mFileSelector;
GtkWidget *mFormatChooser;
+ GtkWidget *mSaveContentCheck;
FileFormat *mFileFormats;
};
diff --git a/embed/mozilla/mozilla-embed-shell.cpp b/embed/mozilla/mozilla-embed-shell.cpp
index 00b3c390d..717985d45 100644
--- a/embed/mozilla/mozilla-embed-shell.cpp
+++ b/embed/mozilla/mozilla-embed-shell.cpp
@@ -1064,7 +1064,7 @@ impl_show_file_picker (EphyEmbedShell *shell,
nsCOMPtr<nsILocalFile> dir =
do_CreateInstance (NS_LOCAL_FILE_CONTRACTID);
- dir->InitWithPath (NS_ConvertUTF8toUCS2(expanded_directory));
+ dir->InitWithNativePath (nsDependentCString(expanded_directory));
g_free (expanded_directory);
filePicker->InitWithGtkWidget (parentWidget, title, mode);
@@ -1097,9 +1097,9 @@ impl_show_file_picker (EphyEmbedShell *shell,
g_free (*ret_fullpath);
nsCOMPtr<nsILocalFile> file;
filePicker->GetFile (getter_AddRefs(file));
- nsAutoString tempFullPathStr;
- file->GetPath (tempFullPathStr);
- *ret_fullpath = g_strdup (NS_ConvertUCS2toUTF8(tempFullPathStr).get());
+ nsCAutoString tempFullPathStr;
+ file->GetNativePath (tempFullPathStr);
+ *ret_fullpath = g_strdup (tempFullPathStr.get());
delete filePicker;
return G_OK;
}
diff --git a/lib/ephy-bonobo-extensions.c b/lib/ephy-bonobo-extensions.c
index e40b377cd..efc43ed60 100644
--- a/lib/ephy-bonobo-extensions.c
+++ b/lib/ephy-bonobo-extensions.c
@@ -677,3 +677,19 @@ ephy_bonobo_clear_path (BonoboUIComponent *uic,
g_free (remove_wildcard);
}
}
+
+void
+ephy_bonobo_add_numbered_widget (BonoboUIComponent *uic, GtkWidget *w,
+ guint index, const char *container_path)
+{
+ gchar *path = ephy_bonobo_get_numbered_menu_item_path (uic, container_path, index);
+ gchar *item_name = get_numbered_menu_item_name (index);
+ gchar *xml_string = g_strdup_printf ("<control name=\"%s\"/>", item_name);
+
+ bonobo_ui_component_set (uic, container_path, xml_string, NULL);
+ bonobo_ui_component_widget_set (uic, path, w, NULL);
+
+ g_free (path);
+ g_free (item_name);
+ g_free (xml_string);
+}
diff --git a/lib/ephy-bonobo-extensions.h b/lib/ephy-bonobo-extensions.h
index 86bb977f9..be090711d 100644
--- a/lib/ephy-bonobo-extensions.h
+++ b/lib/ephy-bonobo-extensions.h
@@ -117,5 +117,7 @@ void ephy_bonobo_clear_path (BonoboUIComponent *uic,
void ephy_bonobo_replace_path (BonoboUIComponent *uic,
const gchar *path_src,
const char *path_dst);
+void ephy_bonobo_add_numbered_widget (BonoboUIComponent *uic, GtkWidget *w,
+ guint index, const char *container_path);
#endif /* EPHY_BONOBO_EXTENSIONS_H */
diff --git a/lib/toolbar/Makefile.am b/lib/toolbar/Makefile.am
index a6affaa04..eb2bcf687 100644
--- a/lib/toolbar/Makefile.am
+++ b/lib/toolbar/Makefile.am
@@ -38,4 +38,6 @@ libephytoolbar_la_SOURCES = \
ephy-toolbar-tree-model.h \
ephy-toolbar-tree-model.c \
ephy-toolbar-editor.h \
- ephy-toolbar-editor.c
+ ephy-toolbar-editor.c \
+ ephy-tb-button.c \
+ ephy-tb-button.h
diff --git a/lib/toolbar/ephy-tb-button.c b/lib/toolbar/ephy-tb-button.c
new file mode 100644
index 000000000..4b251a094
--- /dev/null
+++ b/lib/toolbar/ephy-tb-button.c
@@ -0,0 +1,746 @@
+/*
+ * 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-tb-button.h"
+#include "ephy-gobject-misc.h"
+#include "ephy-gui.h"
+#include "ephy-marshal.h"
+#include "eel-gconf-extensions.h"
+
+#include <libgnome/gnome-i18n.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkalignment.h>
+#include <gtk/gtktoolbar.h>
+#include <bonobo/bonobo-ui-toolbar.h>
+#include <string.h>
+
+#define NOT_IMPLEMENTED g_warning ("not implemented: " G_STRLOC);
+//#define DEBUG_MSG(x) g_print x
+#define DEBUG_MSG(x)
+
+/**
+ * Private data
+ */
+struct _EphyTbButtonPrivate
+{
+ gchar *label;
+ GtkWidget *image;
+ gboolean use_stock;
+ gchar *tooltip_text;
+ GtkMenu *menu;
+ GtkWidget *arrow_widget;
+ gboolean sensitive;
+
+ GtkWidget *button;
+ GtkBox *button_box;
+ GtkLabel *label_wid;
+ gboolean priority;
+
+ gboolean in_bonobo_toobar;
+
+ GtkReliefStyle button_relief;
+ GtkOrientation orientation;
+ GtkToolbarStyle style_gtk;
+ BonoboUIToolbarStyle style_bonobo;
+ GtkIconSize icon_size; // TODO
+ gboolean show_tooltips;
+ GtkTooltips *tooltips;
+};
+
+/**
+ * Private functions, only availble from this file
+ */
+static void ephy_tb_button_class_init (EphyTbButtonClass *klass);
+static void ephy_tb_button_init (EphyTbButton *b);
+static void ephy_tb_button_finalize_impl (GObject *o);
+static void ephy_tb_button_build (EphyTbButton *b);
+static void ephy_tb_button_empty (EphyTbButton *b);
+static void ephy_tb_button_parent_set_cb (GtkWidget *widget, GtkObject *old_parent,
+ EphyTbButton *tb);
+static void ephy_tb_button_gtk_orientation_changed_cb (GtkToolbar *toolbar, GtkOrientation orientation,
+ EphyTbButton *b);
+static void ephy_tb_button_gtk_style_changed_cb (GtkToolbar *toolbar, GtkToolbarStyle style,
+ EphyTbButton *b);
+static void ephy_tb_button_bonobo_set_orientation_cb (BonoboUIToolbar *toolbar, GtkOrientation orientation,
+ EphyTbButton *b);
+static void ephy_tb_button_bonobo_set_style_cb (BonoboUIToolbar *toolbar, EphyTbButton *b);
+static gboolean ephy_tb_button_arrow_key_press_event_cb (GtkWidget *widget, GdkEventKey *event,
+ EphyTbButton *b);
+static gboolean ephy_tb_button_arrow_button_press_event_cb (GtkWidget *widget, GdkEventButton *event,
+ EphyTbButton *b);
+static gboolean ephy_tb_button_button_button_press_event_cb (GtkWidget *widget, GdkEventButton *event,
+ EphyTbButton *b);
+static void ephy_tb_button_button_popup_menu_cb (GtkWidget *w, EphyTbButton *b);
+static void ephy_tb_button_menu_deactivated_cb (GtkMenuShell *ms, EphyTbButton *b);
+
+
+static gpointer gtk_hbox_class;
+
+enum EphyTbButtonSignalsEnum {
+ EPHY_TB_BUTTON_MENU_ACTIVATED,
+ EPHY_TB_BUTTON_LAST_SIGNAL
+};
+static gint EphyTbButtonSignals[EPHY_TB_BUTTON_LAST_SIGNAL];
+
+/**
+ * TbButton object
+ */
+
+MAKE_GET_TYPE (ephy_tb_button, "EphyTbButton", EphyTbButton, ephy_tb_button_class_init,
+ ephy_tb_button_init, GTK_TYPE_HBOX);
+
+static void
+ephy_tb_button_class_init (EphyTbButtonClass *klass)
+{
+ G_OBJECT_CLASS (klass)->finalize = ephy_tb_button_finalize_impl;
+ gtk_hbox_class = g_type_class_peek_parent (klass);
+
+ EphyTbButtonSignals[EPHY_TB_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 (EphyTbButtonClass, menu_activated),
+ NULL, NULL,
+ ephy_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+ephy_tb_button_init (EphyTbButton *tb)
+{
+ EphyTbButtonPrivate *p = g_new0 (EphyTbButtonPrivate, 1);
+ tb->priv = p;
+ p->label = g_strdup ("");
+ p->tooltip_text = g_strdup ("");
+
+ p->button_relief = GTK_RELIEF_NORMAL;
+ p->orientation = GTK_ORIENTATION_HORIZONTAL;
+ p->style_gtk = GTK_TOOLBAR_BOTH_HORIZ;
+ p->style_bonobo = BONOBO_UI_TOOLBAR_STYLE_PRIORITY_TEXT;
+ p->icon_size = GTK_ICON_SIZE_LARGE_TOOLBAR;
+ p->show_tooltips = TRUE;
+
+ g_signal_connect (tb, "parent-set",
+ G_CALLBACK (ephy_tb_button_parent_set_cb), tb);
+}
+
+EphyTbButton *
+ephy_tb_button_new (void)
+{
+ EphyTbButton *ret = g_object_new (EPHY_TYPE_TB_BUTTON, NULL);
+ return ret;
+}
+
+static void
+ephy_tb_button_finalize_impl (GObject *o)
+{
+ EphyTbButton *it = EPHY_TB_BUTTON (o);
+ EphyTbButtonPrivate *p = it->priv;
+
+ ephy_tb_button_empty (it);
+
+ if (p->image)
+ {
+ g_object_unref (p->image);
+ }
+
+ if (p->tooltips)
+ {
+ g_object_unref (p->tooltips);
+ }
+
+ if (p->menu)
+ {
+ g_object_unref (p->menu);
+ }
+
+ if (p->arrow_widget)
+ {
+ g_object_unref (p->arrow_widget);
+ }
+
+ g_free (p);
+
+ DEBUG_MSG (("EphyTbButton finalized\n"));
+
+ G_OBJECT_CLASS (gtk_hbox_class)->finalize (o);
+}
+
+void
+ephy_tb_button_set_label (EphyTbButton *b, const gchar *text)
+{
+ EphyTbButtonPrivate *p = b->priv;
+ g_free (p->label);
+ p->label = g_strdup (text);
+ DEBUG_MSG (("EphyTbButton label set to '%s'\n", p->label));
+ if (!p->label_wid || p->use_stock)
+ {
+ ephy_tb_button_build (b);
+ }
+ else
+ {
+ gtk_label_set_text (p->label_wid, p->label);
+ }
+}
+
+void
+ephy_tb_button_set_tooltip_text (EphyTbButton *b, const gchar *text)
+{
+ EphyTbButtonPrivate *p = b->priv;
+ g_free (p->tooltip_text);
+ p->tooltip_text = g_strdup (text);
+
+ if (!p->tooltips || !p->button)
+ {
+ ephy_tb_button_build (b);
+ }
+ else
+ {
+ gtk_tooltips_set_tip (p->tooltips, p->button,
+ p->tooltip_text, p->tooltip_text);
+ }
+}
+
+/* this function comes directly from gtktoolbar.c */
+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
+ephy_tb_button_build (EphyTbButton *b)
+{
+ EphyTbButtonPrivate *p = b->priv;
+ GtkWidget *align;
+ GtkWidget *image;
+ GtkStockItem stock_item;
+ gboolean really_use_stock = p->use_stock && gtk_stock_lookup (p->label, &stock_item);
+ gboolean show_image = p->label[0] == '\0'
+ || (p->in_bonobo_toobar && p->style_bonobo != BONOBO_UI_TOOLBAR_STYLE_TEXT_ONLY)
+ || (!p->in_bonobo_toobar && p->style_gtk != GTK_TOOLBAR_TEXT);
+ gboolean show_label = !show_image
+ || (p->priority && ((p->in_bonobo_toobar && p->style_bonobo == BONOBO_UI_TOOLBAR_STYLE_PRIORITY_TEXT)
+ || (!p->in_bonobo_toobar && p->style_gtk == GTK_TOOLBAR_BOTH_HORIZ)))
+ || (!p->in_bonobo_toobar
+ && (p->style_gtk == GTK_TOOLBAR_BOTH
+ || p->style_gtk == GTK_TOOLBAR_TEXT
+ /* CHECK: what about GTK_TOOLBAR_BOTH_HORIZ? */ ))
+ || (p->in_bonobo_toobar
+ && (p->style_bonobo == BONOBO_UI_TOOLBAR_STYLE_ICONS_AND_TEXT
+ || p->style_bonobo == BONOBO_UI_TOOLBAR_STYLE_TEXT_ONLY));
+
+ ephy_tb_button_empty (b);
+
+ if (!p->button)
+ {
+ p->button = gtk_button_new ();
+ g_object_ref (p->button);
+ gtk_widget_show (p->button);
+ gtk_box_pack_start_defaults (GTK_BOX (b), p->button);
+ }
+
+ gtk_button_set_relief (GTK_BUTTON (p->button), p->button_relief);
+ gtk_widget_set_sensitive (p->button, p->sensitive);
+ if (p->tooltips)
+ {
+ gtk_tooltips_set_tip (p->tooltips, p->button,
+ p->tooltip_text, p->tooltip_text);
+ }
+ g_signal_connect (p->button, "button_press_event",
+ G_CALLBACK (ephy_tb_button_button_button_press_event_cb), b);
+ g_signal_connect (p->button, "popup_menu",
+ G_CALLBACK (ephy_tb_button_button_popup_menu_cb), b);
+
+ align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
+ gtk_widget_show (align);
+ gtk_container_add (GTK_CONTAINER (p->button), align);
+
+ if ((p->in_bonobo_toobar && p->style_bonobo == BONOBO_UI_TOOLBAR_STYLE_ICONS_AND_TEXT)
+ || (!p->in_bonobo_toobar && p->style_gtk == GTK_TOOLBAR_BOTH)
+ || p->orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ p->button_box = GTK_BOX (gtk_vbox_new (FALSE, 2));
+ }
+ else
+ {
+ p->button_box = GTK_BOX (gtk_hbox_new (FALSE, 2));
+ }
+ g_object_ref (p->button_box);
+ gtk_widget_show (GTK_WIDGET (p->button_box));
+ gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET (p->button_box));
+
+ if (!p->image && really_use_stock && show_image)
+ {
+ image = gtk_image_new_from_stock (p->label, p->icon_size);
+ }
+ else
+ {
+ image = p->image;
+ }
+
+ if (image)
+ {
+ if (show_image)
+ {
+ gtk_box_pack_start_defaults (p->button_box, GTK_WIDGET (image));
+ gtk_widget_show (image);
+ }
+ }
+ else
+ {
+ show_label = TRUE;
+ }
+
+ if (show_label)
+ {
+ p->label_wid = GTK_LABEL (gtk_label_new (p->label));
+ g_object_ref (p->label_wid);
+
+ if (really_use_stock)
+ {
+ gchar *l = elide_underscores (stock_item.label);
+ gtk_label_set_text (p->label_wid, l);
+ g_free (l);
+ }
+
+ gtk_widget_show (GTK_WIDGET (p->label_wid));
+ gtk_box_pack_end_defaults (p->button_box, GTK_WIDGET (p->label_wid));
+ }
+
+ DEBUG_MSG (("EphyTbButton built, label='%s'\n", p->label));
+}
+
+void
+ephy_tb_button_set_priority (EphyTbButton *b, gboolean priority)
+{
+ EphyTbButtonPrivate *p = b->priv;
+ if (p->priority != priority)
+ {
+ p->priority = priority;
+ ephy_tb_button_build (b);
+ }
+}
+
+void
+ephy_tb_button_set_image (EphyTbButton *b, GtkWidget *image)
+{
+ EphyTbButtonPrivate *p = b->priv;
+ if (p->image)
+ {
+ g_object_unref (p->image);
+ }
+ p->image = image ? g_object_ref (image) : NULL;
+ ephy_tb_button_build (b);
+}
+
+void
+ephy_tb_button_set_show_arrow (EphyTbButton *b, gboolean value)
+{
+ EphyTbButtonPrivate *p = b->priv;
+
+ if (p->arrow_widget && !value)
+ {
+ if (p->arrow_widget->parent == GTK_WIDGET (b))
+ {
+ gtk_container_remove (GTK_CONTAINER (b), p->arrow_widget);
+ }
+ g_object_unref (p->arrow_widget);
+ p->arrow_widget = NULL;
+ }
+ else if (!p->arrow_widget && value)
+ {
+ p->arrow_widget = gtk_toggle_button_new ();
+ gtk_button_set_relief (GTK_BUTTON (p->arrow_widget), GTK_RELIEF_NONE);
+
+ gtk_container_add (GTK_CONTAINER (p->arrow_widget),
+ gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT));
+
+ g_object_ref (p->arrow_widget);
+ gtk_object_sink (GTK_OBJECT (p->arrow_widget));
+
+ g_signal_connect (p->arrow_widget, "key_press_event",
+ G_CALLBACK (ephy_tb_button_arrow_key_press_event_cb),
+ b);
+
+ g_signal_connect (p->arrow_widget, "button_press_event",
+ G_CALLBACK (ephy_tb_button_arrow_button_press_event_cb),
+ b);
+
+ gtk_widget_show_all (p->arrow_widget);
+ gtk_box_pack_end_defaults (GTK_BOX (b), p->arrow_widget);
+ gtk_widget_set_sensitive (p->arrow_widget, value);
+ }
+}
+
+void
+ephy_tb_button_set_enable_menu (EphyTbButton *b, gboolean value)
+{
+ EphyTbButtonPrivate *p = b->priv;
+ if (value && !p->menu)
+ {
+ p->menu = GTK_MENU (gtk_menu_new ());
+ g_signal_connect (p->menu, "deactivate",
+ G_CALLBACK (ephy_tb_button_menu_deactivated_cb), b);
+ }
+ else if (!value && p->menu)
+ {
+ g_object_unref (p->menu);
+ p->menu = FALSE;
+ }
+
+}
+
+GtkMenuShell *
+ephy_tb_button_get_menu (EphyTbButton *b)
+{
+ EphyTbButtonPrivate *p = b->priv;
+ return p->menu ? GTK_MENU_SHELL (p->menu) : NULL;
+}
+
+GtkButton *
+ephy_tb_button_get_button (EphyTbButton *b)
+{
+ EphyTbButtonPrivate *p = b->priv;
+ if (!p->button)
+ {
+ ephy_tb_button_build (b);
+ }
+ return GTK_BUTTON (p->button);
+}
+
+void
+ephy_tb_button_set_use_stock (EphyTbButton *b, gboolean value)
+{
+ EphyTbButtonPrivate *p = b->priv;
+ if (value != p->use_stock)
+ {
+ p->use_stock = value;
+ ephy_tb_button_build (b);
+ }
+}
+
+static void
+ephy_tb_button_empty (EphyTbButton *b)
+{
+ EphyTbButtonPrivate *p = b->priv;
+
+ if (p->button)
+ {
+ if (GTK_BIN (p->button)->child)
+ {
+ gtk_container_remove (GTK_CONTAINER (p->button), GTK_BIN (p->button)->child);
+ }
+ }
+
+ if (p->button_box)
+ {
+ g_object_unref (p->button_box);
+ p->button_box = NULL;
+ }
+
+ if (p->label_wid)
+ {
+ g_object_unref (p->label_wid);
+ p->label_wid = NULL;
+ }
+}
+
+static void
+ephy_tb_button_parent_set_cb (GtkWidget *widget, GtkObject *old_parent, EphyTbButton *tb)
+{
+ EphyTbButtonPrivate *p = tb->priv;
+ GtkWidget *new_parent = widget->parent;
+
+ DEBUG_MSG (("EphyTbButton parent changed (widget=%p, button=%p, old=%p, new=%p)\n",
+ widget, tb, old_parent, new_parent));
+
+ if (new_parent)
+ {
+ GtkToolbar *gtktb = NULL;
+ BonoboUIToolbar *btb = NULL;
+ while (new_parent && !gtktb && !btb)
+ {
+ DEBUG_MSG (("new_parent ia a %s\n", g_type_name_from_instance ((void *) new_parent)));
+
+ if (GTK_IS_TOOLBAR (new_parent))
+ {
+ gtktb = GTK_TOOLBAR (new_parent);
+ }
+ else if (BONOBO_IS_UI_TOOLBAR (new_parent))
+ {
+ btb = BONOBO_UI_TOOLBAR (new_parent);
+ }
+ else
+ {
+ g_signal_connect (new_parent, "parent_set",
+ G_CALLBACK (ephy_tb_button_parent_set_cb), tb);
+ }
+ new_parent = new_parent->parent;
+ }
+
+ if (gtktb)
+ {
+ DEBUG_MSG (("EphyTbButton getting style from a GtkToolbar (%p)\n", gtktb));
+ p->in_bonobo_toobar = FALSE;
+
+ gtk_widget_ensure_style (GTK_WIDGET (gtktb));
+ gtk_widget_style_get (GTK_WIDGET (gtktb), "button_relief", &p->button_relief, NULL);
+
+ p->orientation = gtk_toolbar_get_orientation (gtktb);
+ p->style_gtk = gtk_toolbar_get_style (gtktb);
+ p->icon_size = gtk_toolbar_get_icon_size (gtktb);
+ p->show_tooltips = gtk_toolbar_get_tooltips (gtktb);
+
+ if (p->tooltips)
+ {
+ g_object_unref (p->tooltips);
+ }
+ p->tooltips = gtk_tooltips_new ();
+ if (p->show_tooltips)
+ {
+ gtk_tooltips_enable (p->tooltips);
+ }
+ else
+ {
+ gtk_tooltips_disable (p->tooltips);
+ }
+ g_object_ref (p->tooltips);
+ gtk_object_sink (GTK_OBJECT (p->tooltips));
+
+ g_signal_connect (gtktb, "orientation-changed",
+ G_CALLBACK (ephy_tb_button_gtk_orientation_changed_cb), tb);
+ g_signal_connect (gtktb, "style-changed",
+ G_CALLBACK (ephy_tb_button_gtk_style_changed_cb), tb);
+
+ ephy_tb_button_build (tb);
+ }
+
+ if (btb)
+ {
+ DEBUG_MSG (("EphyTbButton getting style from a BonoboUIToolbar (%p)\n", btb));
+ p->in_bonobo_toobar = TRUE;
+
+ p->button_relief = GTK_RELIEF_NONE;
+
+ p->orientation = bonobo_ui_toolbar_get_orientation (btb);
+ p->style_bonobo = bonobo_ui_toolbar_get_style (btb);
+ //p->icon_size = ???;
+ p->show_tooltips = TRUE;
+
+ if (p->tooltips)
+ {
+ g_object_unref (p->tooltips);
+ }
+ p->tooltips = bonobo_ui_toolbar_get_tooltips (btb);
+ g_object_ref (p->tooltips);
+
+ g_signal_connect (btb, "set-orientation",
+ G_CALLBACK (ephy_tb_button_bonobo_set_orientation_cb), tb);
+ g_signal_connect (btb, "set-style",
+ G_CALLBACK (ephy_tb_button_bonobo_set_style_cb), tb);
+
+ ephy_tb_button_build (tb);
+ }
+ }
+ else
+ {
+ while (old_parent)
+ {
+ g_signal_handlers_disconnect_matched (old_parent, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, tb);
+ if (GTK_IS_WIDGET (old_parent))
+ {
+ old_parent = GTK_WIDGET (old_parent)->parent
+ ? GTK_OBJECT (GTK_WIDGET (old_parent)->parent)
+ : NULL;
+ }
+ else
+ {
+ old_parent = NULL;
+ }
+ }
+ }
+}
+
+static void
+ephy_tb_button_gtk_orientation_changed_cb (GtkToolbar *toolbar, GtkOrientation orientation, EphyTbButton *b)
+{
+ EphyTbButtonPrivate *p = b->priv;
+ if (p->orientation != orientation)
+ {
+ p->orientation = orientation;
+ ephy_tb_button_build (b);
+ }
+}
+
+static void
+ephy_tb_button_gtk_style_changed_cb (GtkToolbar *toolbar, GtkToolbarStyle style, EphyTbButton *b)
+{
+ EphyTbButtonPrivate *p = b->priv;
+ if (p->style_gtk != style)
+ {
+ p->style_gtk = style;
+ ephy_tb_button_build (b);
+ }
+}
+
+static void
+ephy_tb_button_bonobo_set_orientation_cb (BonoboUIToolbar *toolbar, GtkOrientation orientation, EphyTbButton *b)
+{
+ EphyTbButtonPrivate *p = b->priv;
+ if (p->orientation != orientation)
+ {
+ p->orientation = orientation;
+ ephy_tb_button_build (b);
+ }
+}
+
+static void
+ephy_tb_button_bonobo_set_style_cb (BonoboUIToolbar *toolbar, EphyTbButton *b)
+{
+ EphyTbButtonPrivate *p = b->priv;
+ BonoboUIToolbarStyle style = bonobo_ui_toolbar_get_style (toolbar);
+ if (style != p->style_bonobo)
+ {
+ p->style_bonobo = style;
+ ephy_tb_button_build (b);
+ }
+}
+
+static void
+ephy_tb_button_popup_menu_under_arrow (EphyTbButton *b, GdkEventButton *event)
+{
+ EphyTbButtonPrivate *p = b->priv;
+
+ if (p->menu)
+ {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (p->arrow_widget), TRUE);
+ g_signal_emit (b, EphyTbButtonSignals[EPHY_TB_BUTTON_MENU_ACTIVATED], 0);
+ gtk_menu_popup (p->menu, NULL, NULL, ephy_gui_menu_position_under_widget, p->arrow_widget,
+ event ? event->button : 0,
+ event ? event->time : gtk_get_current_event_time ());
+ }
+}
+
+static void
+ephy_tb_button_menu_deactivated_cb (GtkMenuShell *ms, EphyTbButton *b)
+{
+ EphyTbButtonPrivate *p = b->priv;
+ if (p->arrow_widget)
+ {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (p->arrow_widget), FALSE);
+ }
+}
+
+static gboolean
+ephy_tb_button_arrow_button_press_event_cb (GtkWidget *widget, GdkEventButton *event, EphyTbButton *b)
+{
+ ephy_tb_button_popup_menu_under_arrow (b, event);
+ return TRUE;
+}
+
+static gboolean
+ephy_tb_button_arrow_key_press_event_cb (GtkWidget *widget, GdkEventKey *event, EphyTbButton *b)
+{
+ if (event->keyval == GDK_space
+ || event->keyval == GDK_KP_Space
+ || event->keyval == GDK_Return
+ || event->keyval == GDK_KP_Enter
+ || event->keyval == GDK_Menu)
+ {
+ ephy_tb_button_popup_menu_under_arrow (b, NULL);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+ephy_tb_button_button_button_press_event_cb (GtkWidget *widget, GdkEventButton *event,
+ EphyTbButton *b)
+{
+ EphyTbButtonPrivate *p = b->priv;
+
+ if (event->button == 3 && p->menu)
+ {
+ g_signal_emit (b, EphyTbButtonSignals[EPHY_TB_BUTTON_MENU_ACTIVATED], 0);
+ gtk_menu_popup (p->menu, NULL, NULL, NULL, b,
+ event ? event->button : 0,
+ event ? event->time : gtk_get_current_event_time ());
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+ephy_tb_button_button_popup_menu_cb (GtkWidget *w, EphyTbButton *b)
+{
+ EphyTbButtonPrivate *p = b->priv;
+
+ g_signal_emit (b, EphyTbButtonSignals[EPHY_TB_BUTTON_MENU_ACTIVATED], 0);
+ gtk_menu_popup (p->menu, NULL, NULL,
+ ephy_gui_menu_position_under_widget, b, 0, gtk_get_current_event_time ());
+}
+
+void
+ephy_tb_button_set_sensitivity (EphyTbButton *b, gboolean value)
+{
+ EphyTbButtonPrivate *p = b->priv;
+
+ p->sensitive = value;
+
+ if (!p->button)
+ {
+ ephy_tb_button_build (b);
+ }
+ else
+ {
+ gtk_widget_set_sensitive (p->button, value);
+ if (p->arrow_widget)
+ {
+ gtk_widget_set_sensitive (p->arrow_widget, value);
+ }
+ }
+}
+
diff --git a/lib/toolbar/ephy-tb-button.h b/lib/toolbar/ephy-tb-button.h
new file mode 100644
index 000000000..5d3d9616a
--- /dev/null
+++ b/lib/toolbar/ephy-tb-button.h
@@ -0,0 +1,79 @@
+/*
+ * 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_TB_BUTTON_H
+#define EPHY_TB_BUTTON_H
+
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkmenushell.h>
+#include <gtk/gtkbutton.h>
+
+G_BEGIN_DECLS
+
+/* object forward declarations */
+
+typedef struct _EphyTbButton EphyTbButton;
+typedef struct _EphyTbButtonClass EphyTbButtonClass;
+typedef struct _EphyTbButtonPrivate EphyTbButtonPrivate;
+
+/**
+ * TbButton object
+ */
+
+#define EPHY_TYPE_TB_BUTTON (ephy_tb_button_get_type())
+#define EPHY_TB_BUTTON(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EPHY_TYPE_TB_BUTTON,\
+ EphyTbButton))
+#define EPHY_TB_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EPHY_TYPE_TB_BUTTON,\
+ EphyTbButtonClass))
+#define EPHY_IS_TB_BUTTON(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EPHY_TYPE_TB_BUTTON))
+#define EPHY_IS_TB_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EPHY_TYPE_TB_BUTTON))
+#define EPHY_TB_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_TB_BUTTON,\
+ EphyTbButtonClass))
+
+struct _EphyTbButtonClass
+{
+ GtkHBoxClass parent_class;
+
+ void (*menu_activated) (EphyTbButton *b);
+};
+
+/* Remember: fields are public read-only */
+struct _EphyTbButton
+{
+ GtkHBox parent_object;
+ EphyTbButtonPrivate *priv;
+};
+
+/* this class is abstract */
+
+GType ephy_tb_button_get_type (void);
+EphyTbButton * ephy_tb_button_new (void);
+void ephy_tb_button_set_label (EphyTbButton *b, const gchar *text);
+void ephy_tb_button_set_use_stock (EphyTbButton *b, gboolean value);
+void ephy_tb_button_set_priority (EphyTbButton *b, gboolean priority);
+void ephy_tb_button_set_image (EphyTbButton *b, GtkWidget *image);
+void ephy_tb_button_set_tooltip_text (EphyTbButton *b, const gchar *text);
+void ephy_tb_button_set_show_arrow (EphyTbButton *b, gboolean value);
+void ephy_tb_button_set_enable_menu (EphyTbButton *b, gboolean value);
+GtkMenuShell * ephy_tb_button_get_menu (EphyTbButton *b);
+GtkButton * ephy_tb_button_get_button (EphyTbButton *b);
+void ephy_tb_button_set_sensitivity (EphyTbButton *b, gboolean value);
+
+G_END_DECLS
+
+#endif
diff --git a/lib/toolbar/ephy-tbi-std-toolitem.c b/lib/toolbar/ephy-tbi-std-toolitem.c
index deb468ecb..4b7f3864c 100644
--- a/lib/toolbar/ephy-tbi-std-toolitem.c
+++ b/lib/toolbar/ephy-tbi-std-toolitem.c
@@ -97,7 +97,7 @@ ephy_tbi_std_toolitem_init (EphyTbiStdToolitem *tb)
EphyTbiStdToolitemPrivate *p = g_new0 (EphyTbiStdToolitemPrivate, 1);
tb->priv = p;
- p->item = EPHY_TBI_STD_TOOLITEM_BACK;
+ p->item = EPHY_TBI_STD_TOOLITEM_STOP;
}
EphyTbiStdToolitem *
@@ -137,31 +137,16 @@ ephy_tbi_std_toolitem_get_icon_impl (EphyTbItem *i)
{
EphyTbiStdToolitemPrivate *p = EPHY_TBI_STD_TOOLITEM (i)->priv;
- static GdkPixbuf *pb_up = NULL;
- static GdkPixbuf *pb_back = NULL;
- static GdkPixbuf *pb_forward = NULL;
static GdkPixbuf *pb_stop = NULL;
static GdkPixbuf *pb_reload = NULL;
static GdkPixbuf *pb_home = NULL;
static GdkPixbuf *pb_go = NULL;
static GdkPixbuf *pb_new = NULL;
-
- if (!pb_up)
+
+ if (!pb_stop)
{
/* what's the easier way? */
GtkWidget *b = gtk_spin_button_new_with_range (0, 1, 0.5);
- 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);
pb_stop = gtk_widget_render_icon (b,
GTK_STOCK_STOP,
GTK_ICON_SIZE_SMALL_TOOLBAR,
@@ -187,15 +172,6 @@ ephy_tbi_std_toolitem_get_icon_impl (EphyTbItem *i)
switch (p->item)
{
- case EPHY_TBI_STD_TOOLITEM_BACK:
- return g_object_ref (pb_back);
- break;
- case EPHY_TBI_STD_TOOLITEM_FORWARD:
- return g_object_ref (pb_forward);
- break;
- case EPHY_TBI_STD_TOOLITEM_UP:
- return g_object_ref (pb_up);
- break;
case EPHY_TBI_STD_TOOLITEM_STOP:
return g_object_ref (pb_stop);
break;
@@ -211,6 +187,9 @@ ephy_tbi_std_toolitem_get_icon_impl (EphyTbItem *i)
case EPHY_TBI_STD_TOOLITEM_NEW:
return g_object_ref (pb_new);
break;
+ case EPHY_TBI_STD_TOOLITEM_ERROR:
+ return NULL;
+ break;
default:
g_assert_not_reached ();
return NULL;
@@ -225,15 +204,6 @@ ephy_tbi_std_toolitem_get_name_human_impl (EphyTbItem *i)
switch (p->item)
{
- case EPHY_TBI_STD_TOOLITEM_BACK:
- ret = _("Back");
- break;
- case EPHY_TBI_STD_TOOLITEM_FORWARD:
- ret = _("Forward");
- break;
- case EPHY_TBI_STD_TOOLITEM_UP:
- ret = _("Up");
- break;
case EPHY_TBI_STD_TOOLITEM_STOP:
ret = _("Stop");
break;
@@ -249,6 +219,9 @@ ephy_tbi_std_toolitem_get_name_human_impl (EphyTbItem *i)
case EPHY_TBI_STD_TOOLITEM_NEW:
ret = _("New");
break;
+ case EPHY_TBI_STD_TOOLITEM_ERROR:
+ ret = "Erroneous button";
+ break;
default:
g_assert_not_reached ();
ret = "unknown";
@@ -267,15 +240,6 @@ ephy_tbi_std_toolitem_to_string_impl (EphyTbItem *i)
switch (p->item)
{
- case EPHY_TBI_STD_TOOLITEM_BACK:
- sitem = "back";
- break;
- case EPHY_TBI_STD_TOOLITEM_FORWARD:
- sitem = "forward";
- break;
- case EPHY_TBI_STD_TOOLITEM_UP:
- sitem = "up";
- break;
case EPHY_TBI_STD_TOOLITEM_STOP:
sitem = "stop";
break;
@@ -291,6 +255,9 @@ ephy_tbi_std_toolitem_to_string_impl (EphyTbItem *i)
case EPHY_TBI_STD_TOOLITEM_NEW:
sitem = "new";
break;
+ case EPHY_TBI_STD_TOOLITEM_ERROR:
+ sitem = "error";
+ break;
default:
g_assert_not_reached ();
sitem = "unknown";
@@ -330,28 +297,6 @@ ephy_tbi_std_toolitem_add_to_bonobo_tb_impl (EphyTbItem *i, BonoboUIComponent *u
switch (p->item)
{
- case EPHY_TBI_STD_TOOLITEM_BACK:
- xml_item = g_strdup_printf
- ("<toolitem name=\"Back\" "
- "label=\"%s\" "
- "pixtype=\"stock\" pixname=\"gtk-go-back\" "
- "priority=\"1\" "
- "verb=\"GoBack\"/>", _("Back"));;
- break;
- case EPHY_TBI_STD_TOOLITEM_FORWARD:
- xml_item = g_strdup_printf
- ("<toolitem name=\"Forward\" "
- "label=\"%s\" "
- "pixtype=\"stock\" pixname=\"gtk-go-forward\" "
- "verb=\"GoForward\"/>", _("Forward"));
- break;
- case EPHY_TBI_STD_TOOLITEM_UP:
- xml_item = g_strdup_printf
- ("<toolitem name=\"Up\" "
- "label=\"%s\" "
- "pixtype=\"stock\" pixname=\"gtk-go-up\" "
- "verb=\"GoUp\"/>", _("Up"));;
- break;
case EPHY_TBI_STD_TOOLITEM_STOP:
xml_item = g_strdup_printf
("<toolitem name=\"Stop\" "
@@ -388,7 +333,14 @@ ephy_tbi_std_toolitem_add_to_bonobo_tb_impl (EphyTbItem *i, BonoboUIComponent *u
"pixtype=\"stock\" pixname=\"gtk-new\" "
"verb=\"FileNew\"/>", _("New"));;
break;
-
+ case EPHY_TBI_STD_TOOLITEM_ERROR:
+ xml_item = g_strdup_printf
+ ("<toolitem name=\"Error\" "
+ "label=\"%s\" "
+ "pixtype=\"stock\" pixname=\"gtk-cancel\" "
+ "priority=\"1\" "
+ "verb=\"ErrorVerb\"/>", "Erroneous button");
+ break;
default:
g_assert_not_reached ();
xml_item = g_strdup ("");
@@ -412,19 +364,7 @@ ephy_tbi_std_toolitem_parse_properties_impl (EphyTbItem *it, const gchar *props)
if (item_prop)
{
item_prop += strlen ("item=");
- if (!strncmp (item_prop, "back", 4))
- {
- ephy_tbi_std_toolitem_set_item (a, EPHY_TBI_STD_TOOLITEM_BACK);
- }
- else if (!strncmp (item_prop, "forward", 4))
- {
- ephy_tbi_std_toolitem_set_item (a, EPHY_TBI_STD_TOOLITEM_FORWARD);
- }
- else if (!strncmp (item_prop, "up", 2))
- {
- ephy_tbi_std_toolitem_set_item (a, EPHY_TBI_STD_TOOLITEM_UP);
- }
- else if (!strncmp (item_prop, "stop", 4))
+ if (!strncmp (item_prop, "stop", 4))
{
ephy_tbi_std_toolitem_set_item (a, EPHY_TBI_STD_TOOLITEM_STOP);
}
@@ -444,7 +384,10 @@ ephy_tbi_std_toolitem_parse_properties_impl (EphyTbItem *it, const gchar *props)
{
ephy_tbi_std_toolitem_set_item (a, EPHY_TBI_STD_TOOLITEM_NEW);
}
-
+ else
+ {
+ ephy_tbi_std_toolitem_set_item (a, EPHY_TBI_STD_TOOLITEM_ERROR);
+ }
}
}
@@ -453,10 +396,7 @@ ephy_tbi_std_toolitem_set_item (EphyTbiStdToolitem *a, EphyTbiStdToolitemItem i)
{
EphyTbiStdToolitemPrivate *p = a->priv;
- g_return_if_fail (i == EPHY_TBI_STD_TOOLITEM_UP
- || i == EPHY_TBI_STD_TOOLITEM_BACK
- || i == EPHY_TBI_STD_TOOLITEM_FORWARD
- || i == EPHY_TBI_STD_TOOLITEM_STOP
+ g_return_if_fail (i == EPHY_TBI_STD_TOOLITEM_STOP
|| i == EPHY_TBI_STD_TOOLITEM_RELOAD
|| i == EPHY_TBI_STD_TOOLITEM_GO
|| i == EPHY_TBI_STD_TOOLITEM_HOME
diff --git a/lib/toolbar/ephy-tbi-std-toolitem.h b/lib/toolbar/ephy-tbi-std-toolitem.h
index 67073041f..c47d5d7ea 100644
--- a/lib/toolbar/ephy-tbi-std-toolitem.h
+++ b/lib/toolbar/ephy-tbi-std-toolitem.h
@@ -49,14 +49,12 @@ typedef struct _EphyTbiStdToolitemPrivate EphyTbiStdToolitemPrivate;
EphyTbiStdToolitemClass))
typedef enum
{
- EPHY_TBI_STD_TOOLITEM_BACK,
- EPHY_TBI_STD_TOOLITEM_FORWARD,
- EPHY_TBI_STD_TOOLITEM_UP,
EPHY_TBI_STD_TOOLITEM_STOP,
EPHY_TBI_STD_TOOLITEM_RELOAD,
EPHY_TBI_STD_TOOLITEM_HOME,
EPHY_TBI_STD_TOOLITEM_GO,
- EPHY_TBI_STD_TOOLITEM_NEW
+ EPHY_TBI_STD_TOOLITEM_NEW,
+ EPHY_TBI_STD_TOOLITEM_ERROR
} EphyTbiStdToolitemItem;
diff --git a/lib/toolbar/ephy-toolbar-item-factory.c b/lib/toolbar/ephy-toolbar-item-factory.c
index 1637100ae..60cfbbc41 100644
--- a/lib/toolbar/ephy-toolbar-item-factory.c
+++ b/lib/toolbar/ephy-toolbar-item-factory.c
@@ -35,26 +35,42 @@
//#define DEBUG_MSG(x) g_print x
#define DEBUG_MSG(x)
-typedef EphyTbItem *(EphyTbItemConstructor) (void);
-
typedef struct
{
const char *type_name;
- EphyTbItemConstructor *constructor;
+ EphyTbItemConstructor constructor;
} EphyTbItemTypeInfo;
-static EphyTbItemTypeInfo ephy_tb_item_known_types[] =
+static EphyTbItemTypeInfo ephy_tb_item_default_types[] =
{
- { "std_toolitem", (EphyTbItemConstructor *) ephy_tbi_std_toolitem_new },
- { "navigation_history", (EphyTbItemConstructor *) ephy_tbi_navigation_history_new },
- { "zoom", (EphyTbItemConstructor *) ephy_tbi_zoom_new },
- { "location", (EphyTbItemConstructor *) ephy_tbi_location_new },
- { "spinner", (EphyTbItemConstructor *) ephy_tbi_spinner_new },
- { "favicon", (EphyTbItemConstructor *) ephy_tbi_favicon_new },
- { "separator", (EphyTbItemConstructor *) ephy_tbi_separator_new },
+ { "std_toolitem", (EphyTbItemConstructor) ephy_tbi_std_toolitem_new },
+ { "navigation_history", (EphyTbItemConstructor) ephy_tbi_navigation_history_new },
+ { "zoom", (EphyTbItemConstructor) ephy_tbi_zoom_new },
+ { "location", (EphyTbItemConstructor) ephy_tbi_location_new },
+ { "spinner", (EphyTbItemConstructor) ephy_tbi_spinner_new },
+ { "favicon", (EphyTbItemConstructor) ephy_tbi_favicon_new },
+ { "separator", (EphyTbItemConstructor) ephy_tbi_separator_new },
{ NULL, NULL }
};
+static GHashTable *ephy_tb_item_known_types = NULL;
+
+static void
+ephy_tb_item_factory_init (void)
+{
+ if (ephy_tb_item_known_types == NULL)
+ {
+ int i;
+ ephy_tb_item_known_types = g_hash_table_new (g_str_hash, g_str_equal);
+
+ for (i = 0; ephy_tb_item_default_types[i].type_name; ++i)
+ {
+ ephy_toolbar_item_register_type (ephy_tb_item_default_types[i].type_name,
+ ephy_tb_item_default_types[i].constructor);
+ }
+ }
+}
+
EphyTbItem *
ephy_toolbar_item_create_from_string (const gchar *str)
{
@@ -66,7 +82,9 @@ ephy_toolbar_item_create_from_string (const gchar *str)
const gchar *lpar;
const gchar *rpar;
const gchar *eq;
- int i;
+ EphyTbItemConstructor constructor;
+
+ ephy_tb_item_factory_init ();
rest = str;
@@ -104,21 +122,20 @@ ephy_toolbar_item_create_from_string (const gchar *str)
props = NULL;
}
- DEBUG_MSG (("ephytoolbar_item_create_from_string id=%s type=%s props=%s\n", id, type, props));
+ DEBUG_MSG (("ephy_toolbar_item_create_from_string id=%s type=%s props=%s\n", id, type, props));
+
+ constructor = g_hash_table_lookup (ephy_tb_item_known_types, type);
- for (i = 0; ephy_tb_item_known_types[i].type_name; ++i)
+ if (constructor)
{
- if (!strcmp (type, ephy_tb_item_known_types[i].type_name))
+ ret = constructor ();
+ if (id)
+ {
+ ephy_tb_item_set_id (ret, id);
+ }
+ if (props)
{
- ret = ephy_tb_item_known_types[i].constructor ();
- if (id)
- {
- ephy_tb_item_set_id (ret, id);
- }
- if (props)
- {
- ephy_tb_item_parse_properties (ret, props);
- }
+ ephy_tb_item_parse_properties (ret, props);
}
}
@@ -143,16 +160,9 @@ ephy_toolbar_item_create_from_string (const gchar *str)
return ret;
}
-GSList *
-ephy_toolbar_list_item_types (void)
+void
+ephy_toolbar_item_register_type (const gchar *type, EphyTbItemConstructor constructor)
{
- int i;
- GSList *ret = NULL;
- for (i = 0; ephy_tb_item_known_types[i].type_name; ++i)
- {
- ret = g_slist_prepend (ret,
- (gchar *) ephy_tb_item_known_types[i].type_name);
- }
- return ret;
+ ephy_tb_item_factory_init ();
+ g_hash_table_insert (ephy_tb_item_known_types, g_strdup (type), constructor);
}
-
diff --git a/lib/toolbar/ephy-toolbar-item-factory.h b/lib/toolbar/ephy-toolbar-item-factory.h
index e86179399..d613abeeb 100644
--- a/lib/toolbar/ephy-toolbar-item-factory.h
+++ b/lib/toolbar/ephy-toolbar-item-factory.h
@@ -23,8 +23,10 @@
G_BEGIN_DECLS
+typedef EphyTbItem *(*EphyTbItemConstructor) (void);
+
EphyTbItem * ephy_toolbar_item_create_from_string (const gchar *str);
-GSList * ephy_toolbar_list_item_types (void);
+void ephy_toolbar_item_register_type (const gchar *type, EphyTbItemConstructor constructor);
G_END_DECLS
diff --git a/src/Makefile.am b/src/Makefile.am
index 5ec49453d..cad9cd290 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -79,7 +79,11 @@ epiphany_SOURCES = \
ephy-favorites-menu.c \
ephy-favorites-menu.h \
ephy-history-model.c \
- ephy-history-model.h
+ ephy-history-model.h \
+ ephy-tbi.c \
+ ephy-tbi.h \
+ ephy-navigation-button.c \
+ ephy-navigation-button.h
epiphany_LDADD = \
$(top_builddir)/embed/libephyembed.la \
diff --git a/src/ephy-navigation-button.c b/src/ephy-navigation-button.c
new file mode 100644
index 000000000..f57de2690
--- /dev/null
+++ b/src/ephy-navigation-button.c
@@ -0,0 +1,614 @@
+/*
+ * 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 <libgnome/gnome-i18n.h>
+#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 <gtk/gtkstock.h>
+#include <string.h>
+
+#define NOT_IMPLEMENTED g_warning ("not implemented: " G_STRLOC);
+//#define DEBUG_MSG(x) g_print x
+#define DEBUG_MSG(x)
+
+/**
+ * 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);
+
+ DEBUG_MSG (("EphyNavigationButton finalized\n"));
+
+ 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 (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
new file mode 100644
index 000000000..036ec6d7e
--- /dev/null
+++ b/src/ephy-navigation-button.h
@@ -0,0 +1,79 @@
+/*
+ * 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-tbi.c b/src/ephy-tbi.c
new file mode 100644
index 000000000..0c6e04f9b
--- /dev/null
+++ b/src/ephy-tbi.c
@@ -0,0 +1,193 @@
+/*
+ * 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 <libgnome/gnome-i18n.h>
+#include "ephy-gobject-misc.h"
+#include "ephy-marshal.h"
+#include "ephy-bonobo-extensions.h"
+#include "ephy-tbi.h"
+#include <string.h>
+
+#define NOT_IMPLEMENTED g_warning ("not implemented: " G_STRLOC);
+//#define DEBUG_MSG(x) g_print x
+#define DEBUG_MSG(x)
+
+/**
+ * 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);
+ }
+
+ DEBUG_MSG (("EphyTbi finalized\n"));
+
+ 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
new file mode 100644
index 000000000..2296a144f
--- /dev/null
+++ b/src/ephy-tbi.h
@@ -0,0 +1,70 @@
+/*
+ * 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/toolbar.c b/src/toolbar.c
index 4bff4615e..059f1277d 100755
--- a/src/toolbar.c
+++ b/src/toolbar.c
@@ -32,8 +32,10 @@
#include "ephy-embed-favicon.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 <string.h>
#include <bonobo/bonobo-i18n.h>
@@ -45,18 +47,13 @@
#include <gtk/gtkmenu.h>
#define DEFAULT_TOOLBAR_SETUP \
- "back=std_toolitem(item=back);" \
- "back_history=navigation_history(direction=back);" \
- "up=std_toolitem(item=up);" \
- "up_history=navigation_history(direction=up);" \
- "forward=std_toolitem(item=forward);" \
- "forward_history=navigation_history(direction=forward);" \
+ "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;" \
- "zoom=zoom;" \
"spinner=spinner;"
#define ZOOM_DELAY 50
@@ -102,13 +99,8 @@ struct ToolbarPrivate
GtkWidget *spinner;
gboolean visibility;
- /* This field is unused... what is it?
- GdkPixbufAnimation *animation;
- */
- GtkWidget *back_button;
- GtkWidget *forward_button;
- GtkWidget *up_button;
GtkWidget *location_entry;
+ GSList *navigation_buttons;
GtkTooltips *tooltips;
GtkWidget *favicon;
GtkWidget *favicon_ebox;
@@ -165,6 +157,8 @@ 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
@@ -177,9 +171,9 @@ toolbar_set_property (GObject *object,
switch (prop_id)
{
- case PROP_EPHY_WINDOW:
- toolbar_set_window (t, g_value_get_object (value));
- break;
+ case PROP_EPHY_WINDOW:
+ toolbar_set_window (t, g_value_get_object (value));
+ break;
}
}
@@ -199,247 +193,6 @@ toolbar_get_property (GObject *object,
}
}
-static GtkWidget *
-new_history_menu_item (gint num, gchar *origtext, gboolean lettersok,
- GtkWidget *menu, 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 gboolean
-back_or_forward_button_pressed_callback (GtkWidget *widget,
- GdkEventButton *event,
- gpointer *user_data)
-{
- Toolbar *t;
- GtkWidget *menu;
- int pos, count;
- EphyEmbed *embed;
- int start, end, accell_count = 0;
-
- g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
-
- t = TOOLBAR (user_data);
-
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
-
- embed = ephy_window_get_active_embed (t->priv->window);
- g_return_val_if_fail (embed != NULL, FALSE);
-
- ephy_embed_shistory_get_pos (embed, &pos);
- ephy_embed_shistory_count (embed, &count);
-
- if (count == 0) return FALSE;
-
- if (widget == t->priv->back_button)
- {
- start = pos - 1;
- end = -1;
- }
- else
- {
- start = pos + 1;
- end = count;
- }
-
- menu = gtk_menu_new ();
-
- while (start != end)
- {
- char *title, *url;
- GtkWidget *item;
- ephy_embed_shistory_get_nth (embed, start, FALSE,
- &url, &title);
- item = new_history_menu_item (accell_count, url, TRUE,
- menu, NULL);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), 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),
- t->priv->window);
- gtk_widget_show_all (item);
-
- g_free (url);
- g_free (title);
-
- accell_count++;
- if (start < end) start++;
- else start--;
- }
-
-
- gnome_popup_menu_do_popup_modal (menu,
- ephy_gui_menu_position_under_widget, widget, event, widget, widget);
-
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
-
- return TRUE;
-}
-
-static gboolean
-up_button_pressed_callback (GtkWidget *widget,
- GdkEventButton *event,
- gpointer *user_data)
-{
- Toolbar *t;
- GtkWidget *menu;
- EphyEmbed *embed;
- int accell_count = 0;
- GSList *l;
- GSList *li;
-
- g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
-
- t = TOOLBAR (user_data);
-
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
-
- embed = ephy_window_get_active_embed (t->priv->window);
- g_return_val_if_fail (embed != NULL, FALSE);
-
- ephy_embed_get_go_up_list (embed, &l);
-
- if (l == NULL) return FALSE;
-
- menu = gtk_menu_new ();
-
- for (li = l; li; li = li->next)
- {
- char *url = li->data;
- GtkWidget *item;
- item = new_history_menu_item (accell_count, url, TRUE,
- menu, NULL);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
- g_object_set_data (G_OBJECT(item), "go_nth", GINT_TO_POINTER (accell_count));
- g_signal_connect (item, "activate",
- G_CALLBACK (activate_up_menu_item_cb),
- t->priv->window);
- gtk_widget_show_all (item);
-
- accell_count++;
- }
-
- g_slist_foreach (l, (GFunc) g_free, NULL);
- g_slist_free (l);
-
- gnome_popup_menu_do_popup_modal (menu,
- ephy_gui_menu_position_under_widget, widget, event, widget, widget);
-
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
-
- return TRUE;
-}
-
-static gboolean
-back_or_forward_key_pressed_callback (GtkWidget *widget,
- GdkEventKey *event,
- gpointer *user_data)
-{
- if (event->keyval == GDK_space ||
- event->keyval == GDK_KP_Space ||
- event->keyval == GDK_Return ||
- event->keyval == GDK_KP_Enter)
- {
- back_or_forward_button_pressed_callback (widget, NULL, user_data);
- }
-
- return FALSE;
-}
-
-static gboolean
-up_key_pressed_callback (GtkWidget *widget,
- GdkEventKey *event,
- gpointer *user_data)
-{
- if (event->keyval == GDK_space ||
- event->keyval == GDK_KP_Space ||
- event->keyval == GDK_Return ||
- event->keyval == GDK_KP_Enter)
- {
- up_button_pressed_callback (widget, NULL, user_data);
- }
-
- return FALSE;
-}
-
-static void
-toolbar_setup_navigation_button (Toolbar *t, GtkWidget *w, const char *tooltip)
-{
- g_signal_connect_object (w, "key_press_event",
- G_CALLBACK (back_or_forward_key_pressed_callback),
- t, 0);
- g_signal_connect_object (w, "button_press_event",
- G_CALLBACK (back_or_forward_button_pressed_callback),
- t, 0);
-
- gtk_tooltips_set_tip (t->priv->tooltips, w, tooltip, NULL);
-}
-
-static void
-toolbar_setup_up_button (Toolbar *t, GtkWidget *w, const char *tooltip)
-{
- g_signal_connect_object (w, "key_press_event",
- G_CALLBACK (up_key_pressed_callback),
- t, 0);
- g_signal_connect_object (w, "button_press_event",
- G_CALLBACK (up_button_pressed_callback),
- t, 0);
-
- gtk_tooltips_set_tip (t->priv->tooltips, w, tooltip, NULL);
-}
-
-
static void
toolbar_location_url_activate_cb (EphyLocationEntry *entry,
const char *content,
@@ -607,6 +360,9 @@ 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;
DEBUG_MSG (("in toolbar_get_widgets\n"));
@@ -617,23 +373,12 @@ toolbar_get_widgets (Toolbar *t)
/* release all the widgets */
- if (p->back_button)
+ for (li = p->navigation_buttons; li; li = li->next)
{
- g_object_unref (p->back_button);
- p->back_button = NULL;
- }
-
- if (p->forward_button)
- {
- g_object_unref (p->forward_button);
- p->forward_button = NULL;
- }
-
- if (p->up_button)
- {
- g_object_unref (p->up_button);
- p->up_button = NULL;
+ g_object_unref (li->data);
}
+ g_slist_free (p->navigation_buttons);
+ p->navigation_buttons = NULL;
if (p->favicon_ebox)
{
@@ -667,34 +412,26 @@ toolbar_get_widgets (Toolbar *t)
gt = EPHY_TOOLBAR (t);
- it = ephy_toolbar_get_item_by_id (gt, "back_history");
- if (it)
- {
- p->back_button = ephy_tb_item_get_widget (it);
- g_object_ref (p->back_button);
- toolbar_setup_navigation_button (t, p->back_button, _("Go back a number of pages"));
-
- DEBUG_MSG ((" got a back_history button\n"));
- }
-
- it = ephy_toolbar_get_item_by_id (gt, "forward_history");
- if (it)
- {
- p->forward_button = ephy_tb_item_get_widget (it);
- g_object_ref (p->forward_button);
- toolbar_setup_navigation_button (t, p->forward_button, _("Go forward a number of pages"));
-
- DEBUG_MSG ((" got a forward_history button\n"));
- }
-
- it = ephy_toolbar_get_item_by_id (gt, "up_history");
- if (it)
+ for (i = 0; i < G_N_ELEMENTS (nav_buttons_ids); ++i)
{
- p->up_button = ephy_tb_item_get_widget (it);
- g_object_ref (p->up_button);
- toolbar_setup_up_button (t, p->up_button, _("Go up a number of levels"));
-
- DEBUG_MSG ((" got a up_history button\n"));
+ it = ephy_toolbar_get_item_by_id (gt, nav_buttons_ids[i]);
+ if (it)
+ {
+ if (EPHY_IS_NAVIGATION_BUTTON (it))
+ {
+ DEBUG_MSG ((" got a navigation button\n"));
+ 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");
@@ -748,6 +485,7 @@ toolbar_init (Toolbar *t)
t->priv->window = NULL;
t->priv->ui_component = NULL;
+ t->priv->navigation_buttons = NULL;
t->priv->visibility = TRUE;
t->priv->tooltips = gtk_tooltips_new ();
g_object_ref (t->priv->tooltips);
@@ -785,6 +523,7 @@ toolbar_finalize (GObject *object)
{
Toolbar *t;
ToolbarPrivate *p;
+ GSList *li;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_TOOLBAR (object));
@@ -795,9 +534,6 @@ toolbar_finalize (GObject *object)
g_return_if_fail (p != NULL);
if (p->location_entry) g_object_unref (p->location_entry);
- if (p->back_button) g_object_unref (p->back_button);
- if (p->forward_button) g_object_unref (p->forward_button);
- if (p->up_button) g_object_unref (p->up_button);
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);
@@ -808,6 +544,12 @@ toolbar_finalize (GObject *object)
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_free (t->priv);
@@ -869,6 +611,22 @@ toolbar_spinner_stop (Toolbar *t)
}
}
+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,
@@ -877,40 +635,19 @@ toolbar_button_set_sensitive (Toolbar *t,
switch (id)
{
case TOOLBAR_BACK_BUTTON:
- ephy_bonobo_set_sensitive (t->priv->ui_component,
- "/commands/GoBack",
- sensitivity);
- if (t->priv->back_button)
- {
- gtk_widget_set_sensitive (t->priv->back_button,
- sensitivity);
- }
+ toolbar_navigation_button_set_sensitive (t, EPHY_NAVIGATION_DIRECTION_BACK, sensitivity);
break;
case TOOLBAR_FORWARD_BUTTON:
- ephy_bonobo_set_sensitive (t->priv->ui_component,
- "/commands/GoForward",
- sensitivity);
- if (t->priv->forward_button)
- {
- gtk_widget_set_sensitive (t->priv->forward_button,
- sensitivity);
- }
+ 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;
- case TOOLBAR_UP_BUTTON:
- ephy_bonobo_set_sensitive (t->priv->ui_component,
- "/commands/GoUp",
- sensitivity);
- if (t->priv->up_button)
- {
- gtk_widget_set_sensitive (t->priv->up_button,
- sensitivity);
- }
- break;
}
}
diff --git a/src/window-commands.c b/src/window-commands.c
index cef1d675c..c7d5ec16c 100644
--- a/src/window-commands.c
+++ b/src/window-commands.c
@@ -41,13 +41,12 @@
#include <gtk/gtkeditable.h>
#define AVAILABLE_TOOLBAR_ITEMS \
- "new=std_toolitem(item=new);" \
- "back=std_toolitem(item=back);" \
- "back_history=navigation_history(direction=back);" \
- "up=std_toolitem(item=up);" \
- "up_history=navigation_history(direction=up);" \
- "forward=std_toolitem(item=forward);" \
- "forward_history=navigation_history(direction=forward);" \
+ "back=navigation_button(direction=back,arrow=FALSE);" \
+ "back_menu=navigation_button(direction=back,arrow=TRUE);" \
+ "forward=navigation_button(direction=forward,arrow=FALSE);" \
+ "forward_menu=navigation_button(direction=forward,arrow=TRUE);" \
+ "up=navigation_button(direction=up,arrow=FALSE);" \
+ "up_menu=navigation_button(direction=up,arrow=TRUE);" \
"stop=std_toolitem(item=stop);" \
"reload=std_toolitem(item=reload);" \
"home=std_toolitem(item=home);" \
@@ -58,8 +57,6 @@
"spinner=spinner;" \
"separator;"
-
-
void
window_cmd_edit_find (BonoboUIComponent *uic,
EphyWindow *window,