/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * GnomeApp widget (C) 1998 Red Hat Software, The Free Software Foundation, * Miguel de Icaza, Federico Menu, Chris Toshok, Ettore Perazzoli. * * Originally by Elliot Lee, * * improvements and rearrangement by Miguel, * and I don't know what you other people did :) * * Even more changes by Federico Mena. * * Toolbar separators and configurable relief by Andrew Veliath. * * Modified by Ettore Perazzoli to support GnomeDock. * */ #include "config.h" #include #include #include "libgnome/gnome-defs.h" #include "libgnome/gnome-i18nP.h" #include "libgnome/gnome-util.h" #include "libgnome/gnome-config.h" #include "libgnomeui/gnome-uidefs.h" #include "libgnomeui/gnome-preferences.h" #include "libgnomeui/gnome-dock.h" #include "gnome-app.h" #define LAYOUT_CONFIG_PATH "Placement/Dock" static void gnome_app_class_init (GnomeAppClass *class); static void gnome_app_init (GnomeApp *app); static void gnome_app_destroy (GtkObject *object); static void gnome_app_show (GtkWidget *widget); static gchar *read_layout_config (GnomeApp *app); static void write_layout_config (GnomeApp *app, GnomeDockLayout *layout); static void layout_changed (GtkWidget *widget, gpointer data); static GtkWindowClass *parent_class; static gchar * read_layout_config (GnomeApp *app) { gchar *s; gnome_config_push_prefix (app->prefix); s = gnome_config_get_string (LAYOUT_CONFIG_PATH); gnome_config_pop_prefix (); return s; } static void write_layout_config (GnomeApp *app, GnomeDockLayout *layout) { gchar *s; s = gnome_dock_layout_create_string (layout); gnome_config_push_prefix (app->prefix); gnome_config_set_string (LAYOUT_CONFIG_PATH, s); gnome_config_pop_prefix (); gnome_config_sync (); g_free (s); } GtkType gnome_app_get_type (void) { static GtkType gnomeapp_type = 0; if (!gnomeapp_type) { GtkTypeInfo gnomeapp_info = { "GnomeApp", sizeof (GnomeApp), sizeof (GnomeAppClass), (GtkClassInitFunc) gnome_app_class_init, (GtkObjectInitFunc) gnome_app_init, NULL, /* reserved_1 */ NULL, /* reserved_2 */ (GtkClassInitFunc) NULL }; gnomeapp_type = gtk_type_unique (gtk_window_get_type (), &gnomeapp_info); } return gnomeapp_type; } static void gnome_app_class_init (GnomeAppClass *class) { GtkObjectClass *object_class; GtkWidgetClass *widget_class; object_class = (GtkObjectClass *) class; widget_class = (GtkWidgetClass *) class; parent_class = gtk_type_class (gtk_window_get_type ()); object_class->destroy = gnome_app_destroy; widget_class->show = gnome_app_show; } static void gnome_app_init (GnomeApp *app) { app->accel_group = gtk_accel_group_new (); gtk_window_add_accel_group (GTK_WINDOW (app), app->accel_group); app->vbox = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (app), app->vbox); app->dock = gnome_dock_new (); gtk_box_pack_start (GTK_BOX (app->vbox), app->dock, TRUE, TRUE, 0); gtk_signal_connect (GTK_OBJECT (app->dock), "layout_changed", GTK_SIGNAL_FUNC (layout_changed), (gpointer) app); app->layout = gnome_dock_layout_new (); app->enable_layout_config = TRUE; } static void gnome_app_show (GtkWidget *widget) { GnomeApp *app; app = GNOME_APP (widget); if (app->layout != NULL) { if (app->enable_layout_config) { gchar *s; /* Override the layout with the user's saved configuration. */ s = read_layout_config (app); gnome_dock_layout_parse_string (app->layout, s); g_free (s); } gnome_dock_add_from_layout (GNOME_DOCK (app->dock), app->layout); if (app->enable_layout_config) write_layout_config (app, app->layout); gtk_object_unref (GTK_OBJECT (app->layout)); app->layout = NULL; } gtk_widget_show (app->vbox); gtk_widget_show (app->dock); if (GTK_WIDGET_CLASS (parent_class)->show != NULL) (*GTK_WIDGET_CLASS (parent_class)->show) (widget); } static void layout_changed (GtkWidget *w, gpointer data) { GnomeApp *app; g_return_if_fail (GNOME_IS_APP (data)); g_return_if_fail (GNOME_IS_DOCK (w)); app = GNOME_APP (data); if (app->enable_layout_config) { GnomeDockLayout *layout; layout = gnome_dock_get_layout (GNOME_DOCK (app->dock)); write_layout_config (app, layout); gtk_object_unref (GTK_OBJECT (layout)); } } /** * gnome_app_new * @appname: Name of program, using in file names and paths. * @title: Window title for application. * * Description: * Create a new (empty) application window. You must specify the * application's name (used internally as an identifier). * @title can be left as NULL, in which case the window's title will * not be set. * * Returns: Pointer to new GNOME app object. **/ GtkWidget * gnome_app_new(gchar *appname, char *title) { GnomeApp *app; g_return_val_if_fail (appname != NULL, NULL); app = GNOME_APP (gtk_type_new (gnome_app_get_type ())); gnome_app_construct (app, appname, title); return GTK_WIDGET (app); } /** * gnome_app_construct * @app: Pointer to newly-created GNOME app object. * @appname: Name of program, using in file names and paths. * @title: Window title for application. * * Description: * Constructor for language bindings; you don't normally need this. **/ void gnome_app_construct (GnomeApp *app, gchar *appname, char *title) { g_return_if_fail (appname != NULL); app->name = g_strdup (appname); app->prefix = g_strconcat ("/", appname, "/", NULL); if (title) gtk_window_set_title (GTK_WINDOW (app), title); } static void gnome_app_destroy (GtkObject *object) { GnomeApp *app; g_return_if_fail (object != NULL); g_return_if_fail (GNOME_IS_APP (object)); app = GNOME_APP (object); g_free (app->name); app->name = NULL; g_free (app->prefix); app->prefix = NULL; gtk_accel_group_unref (app->accel_group); app->accel_group = NULL; if (GTK_OBJECT_CLASS (parent_class)->destroy) (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); } /** * gnome_app_set_contents * @app: Pointer to GNOME app object. * @contents: Widget to be application content area. * * Description: * Sets the content area of the GNOME app's main window. **/ void gnome_app_set_contents (GnomeApp *app, GtkWidget *contents) { g_return_if_fail (app != NULL); g_return_if_fail (GNOME_IS_APP(app)); g_return_if_fail (app->dock != NULL); g_return_if_fail (app->contents == NULL); gnome_dock_set_client_area (GNOME_DOCK (app->dock), contents); gtk_widget_show (contents); app->contents = contents; } /** * gnome_app_set_menus * @app: Pointer to GNOME app object. * @menubar: Menu bar widget for main app window. * * Description: * Sets the menu bar of the application window. **/ void gnome_app_set_menus (GnomeApp *app, GtkMenuBar *menubar) { GtkWidget *dock_item; GtkAccelGroup *ag; GnomeDockItemBehavior behavior; g_return_if_fail(app != NULL); g_return_if_fail(GNOME_IS_APP(app)); g_return_if_fail(app->menubar == NULL); g_return_if_fail(menubar != NULL); g_return_if_fail(GTK_IS_MENU_BAR(menubar)); behavior = (GNOME_DOCK_ITEM_BEH_EXCLUSIVE | GNOME_DOCK_ITEM_BEH_NEVER_VERTICAL); if (!gnome_preferences_get_menubar_detachable()) behavior |= GNOME_DOCK_ITEM_BEH_LOCKED; dock_item = gnome_dock_item_new (GNOME_APP_MENUBAR_NAME, behavior); gtk_container_add (GTK_CONTAINER (dock_item), GTK_WIDGET (menubar)); app->menubar = GTK_WIDGET (menubar); /* To have menubar relief agree with the toolbar (and have the relief outside of * smaller handles), substitute the dock item's relief for the menubar's relief, * but don't change the size of the menubar in the process. */ gtk_menu_bar_set_shadow_type (GTK_MENU_BAR (app->menubar), GTK_SHADOW_NONE); if (gnome_preferences_get_menubar_relief ()) { guint border_width; gtk_container_set_border_width (GTK_CONTAINER (dock_item), 2); border_width = GTK_CONTAINER (app->menubar)->border_width; if (border_width >= 2) border_width -= 2; gtk_container_set_border_width (GTK_CONTAINER (app->menubar), border_width); } else gnome_dock_item_set_shadow_type (GNOME_DOCK_ITEM (dock_item), GTK_SHADOW_NONE); if (app->layout != NULL) gnome_dock_layout_add_item (app->layout, GNOME_DOCK_ITEM (dock_item), GNOME_DOCK_TOP, 0, 0, 0); else gnome_dock_add_item(GNOME_DOCK(app->dock), GNOME_DOCK_ITEM (dock_item), GNOME_DOCK_TOP, 0, 0, 0, TRUE); gtk_widget_show (GTK_WIDGET (menubar)); gtk_widget_show (GTK_WIDGET (dock_item)); ag = gtk_object_get_data(GTK_OBJECT(app), "GtkAccelGroup"); if (ag && !g_slist_find(gtk_accel_groups_from_object (GTK_OBJECT (app)), ag)) gtk_window_add_accel_group(GTK_WINDOW(app), ag); } /** * gnome_app_set_statusbar * @app: Pointer to GNOME app object * @statusbar: Statusbar widget for main app window * * Description: * Sets the status bar of the application window. **/ void gnome_app_set_statusbar (GnomeApp *app, GtkWidget *statusbar) { GtkWidget *hbox; g_return_if_fail(app != NULL); g_return_if_fail(GNOME_IS_APP(app)); g_return_if_fail(statusbar != NULL); g_return_if_fail(app->statusbar == NULL); app->statusbar = GTK_WIDGET(statusbar); gtk_widget_show(app->statusbar); hbox = gtk_hbox_new(FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(hbox), 0); gtk_box_pack_start(GTK_BOX(hbox), statusbar, TRUE, TRUE, 0); gtk_widget_show(hbox); gtk_box_pack_start (GTK_BOX (app->vbox), hbox, FALSE, FALSE, 0); } /** * gnome_app_set_statusbar_custom * @app: Pointer to GNOME app object * @container: container widget containing the statusbar * @statusbar: Statusbar widget for main app window * * Description: * Sets the status bar of the application window, but use @container * as its container. * **/ void gnome_app_set_statusbar_custom (GnomeApp *app, GtkWidget *container, GtkWidget *statusbar) { g_return_if_fail(app != NULL); g_return_if_fail(GNOME_IS_APP(app)); g_return_if_fail(container != NULL); g_return_if_fail(GTK_IS_CONTAINER(container)); g_return_if_fail(statusbar != NULL); g_return_if_fail(app->statusbar == NULL); app->statusbar = GTK_WIDGET(statusbar); gtk_box_pack_start (GTK_BOX (app->vbox), container, FALSE, FALSE, 0); } /** * gnome_app_add_toolbar: * @app: A &GnomeApp widget * @toolbar: Toolbar to be added to @app's dock * @name: Name for the dock item that will contain @toolbar * @behavior: Behavior for the new dock item * @placement: Placement for the new dock item * @band_num: Number of the band where the dock item should be placed * @band_position: Position of the new dock item in band @band_num * @offset: Offset from the previous dock item in the band; if there is * no previous item, offset from the beginning of the band. * * Create a new &GnomeDockItem widget containing @toolbar, and add it * to @app's dock with the specified layout information. Notice that, * if automatic layout configuration is enabled, the layout is * overridden by the saved configuration, if any. **/ void gnome_app_add_toolbar (GnomeApp *app, GtkToolbar *toolbar, const gchar *name, GnomeDockItemBehavior behavior, GnomeDockPlacement placement, gint band_num, gint band_position, gint offset) { GtkWidget *dock_item; GtkAccelGroup *ag; g_return_if_fail(app != NULL); g_return_if_fail(GNOME_IS_APP(app)); g_return_if_fail(toolbar != NULL); dock_item = gnome_dock_item_new (name, behavior); gtk_container_set_border_width (GTK_CONTAINER (toolbar), 1); gtk_container_add (GTK_CONTAINER (dock_item), GTK_WIDGET (toolbar)); if(app->layout) gnome_dock_layout_add_item (app->layout, GNOME_DOCK_ITEM (dock_item), placement, band_num, band_position, offset); else gnome_dock_add_item (GNOME_DOCK(app->dock), GNOME_DOCK_ITEM (dock_item), placement, band_num, band_position, offset, TRUE); if (gnome_preferences_get_toolbar_relief ()) { gtk_container_set_border_width (GTK_CONTAINER (dock_item), 1); } else { gnome_dock_item_set_shadow_type (GNOME_DOCK_ITEM (dock_item), GTK_SHADOW_NONE); } /* Configure toolbar to gnome preferences, if possible. (Sync to gnome_app_helper.c:gnome_app_toolbar_custom.) */ if (gnome_preferences_get_toolbar_lines ()) { gtk_toolbar_set_space_style (toolbar, GTK_TOOLBAR_SPACE_LINE); gtk_toolbar_set_space_size (toolbar, GNOME_PAD * 2); } else { gtk_toolbar_set_space_size (toolbar, GNOME_PAD); } if (!gnome_preferences_get_toolbar_relief_btn ()) gtk_toolbar_set_button_relief(toolbar, GTK_RELIEF_NONE); if (!gnome_preferences_get_toolbar_labels ()) gtk_toolbar_set_style (toolbar, GTK_TOOLBAR_ICONS); gtk_widget_show (GTK_WIDGET (toolbar)); gtk_widget_show (GTK_WIDGET (dock_item)); ag = gtk_object_get_data(GTK_OBJECT(app), "GtkAccelGroup"); if (ag && !g_slist_find(gtk_accel_groups_from_object (GTK_OBJECT (app)), ag)) gtk_window_add_accel_group(GTK_WINDOW(app), ag); } /** * gnome_app_set_toolbar * @app: Pointer to GNOME app object. * @toolbar: Toolbar widget for main app window. * * Description: * Sets the main toolbar of the application window. **/ void gnome_app_set_toolbar (GnomeApp *app, GtkToolbar *toolbar) { GnomeDockItemBehavior behavior; /* Making dock items containing toolbars use `GNOME_DOCK_ITEM_BEH_EXCLUSIVE' is not really a requirement. We only do this for backwards compatibility. */ behavior = GNOME_DOCK_ITEM_BEH_EXCLUSIVE; if (!gnome_preferences_get_toolbar_detachable()) behavior |= GNOME_DOCK_ITEM_BEH_LOCKED; gnome_app_add_toolbar (app, toolbar, GNOME_APP_TOOLBAR_NAME, behavior, GNOME_DOCK_TOP, 1, 0, 0); } /** * gnome_app_add_docked: * @app: A &GnomeApp widget * @item: Dock item to be added to @app's dock. * @placement: Placement for the dock item * @band_num: Number of the band where the dock item should be placed * @band_position: Position of the dock item in band @band_num * @offset: Offset from the previous dock item in the band; if there is * no previous item, offset from the beginning of the band. * * Add @item according to the specified layout information. Notice * that, if automatic layout configuration is enabled, the layout is * overridden by the saved configuration, if any. **/ void gnome_app_add_dock_item (GnomeApp *app, GnomeDockItem *item, GnomeDockPlacement placement, gint band_num, gint band_position, gint offset) { if (app->layout) gnome_dock_layout_add_item (app->layout, GNOME_DOCK_ITEM (item), placement, band_num, band_position, offset); else { gnome_dock_add_item (GNOME_DOCK(app->dock), GNOME_DOCK_ITEM( item), placement, band_num, band_position, offset, FALSE); gtk_signal_emit_by_name (GTK_OBJECT (app->dock), "layout_changed", (gpointer) app); } } /** * gnome_app_add_docked: * @app: A &GnomeApp widget * @widget: Widget to be added to the &GnomeApp * @name: Name for the new dock item * @behavior: Behavior for the new dock item * @placement: Placement for the new dock item * @band_num: Number of the band where the dock item should be placed * @band_position: Position of the new dock item in band @band_num * @offset: Offset from the previous dock item in the band; if there is * no previous item, offset from the beginning of the band. * * Add @widget as a dock item according to the specified layout * information. Notice that, if automatic layout configuration is * enabled, the layout is overridden by the saved configuration, if * any. **/ void gnome_app_add_docked (GnomeApp *app, GtkWidget *widget, const gchar *name, GnomeDockItemBehavior behavior, GnomeDockPlacement placement, gint band_num, gint band_position, gint offset) { GtkWidget *item; item = gnome_dock_item_new (name, behavior); gtk_container_add (GTK_CONTAINER (item), widget); gnome_app_add_dock_item (app, GNOME_DOCK_ITEM (item), placement, band_num, band_position, offset); } /** * gnome_app_enable_layout_config: * @app: A &GnomeApp widget * @enable: Boolean specifying whether automatic configuration saving * is enabled * * Specify whether @app should automatically save the dock's * layout configuration via gnome-config whenever it changes or not. **/ void gnome_app_enable_layout_config (GnomeApp *app, gboolean enable) { app->enable_layout_config = enable; } /** * gnome_app_get_dock_item_by_name: * @app: A &GnomeApp widget * @name: Name of the dock item to retrieve * * Retrieve the dock item whose name matches @name. * * Return value: The retrieved dock item. **/ GnomeDockItem * gnome_app_get_dock_item_by_name (GnomeApp *app, const gchar *name) { GnomeDockItem *item; item = gnome_dock_get_item_by_name (GNOME_DOCK (app->dock), name, NULL, NULL, NULL, NULL); if (item == NULL && app->layout != NULL) { GnomeDockLayoutItem *i; i = gnome_dock_layout_get_item_by_name (app->layout, name); if (i == NULL) return NULL; return i->item; } else { return item; } } /** * gnome_app_get_dock: * @app: A &GnomeApp widget * * Retrieves the &GnomeDock widget contained in the &GnomeApp. * * Returns: The &GnomeDock widget. **/ GnomeDock * gnome_app_get_dock (GnomeApp *app) { return GNOME_DOCK (app->dock); }