1263 lines
46 KiB
C
1263 lines
46 KiB
C
/* PIKA - Photo and Image Kooker Application
|
|
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
|
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
|
*
|
|
* Original copyright, applying to most contents (license remains unchanged):
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* pikadockwindow.c
|
|
* Copyright (C) 2001-2005 Michael Natterer <mitch@gimp.org>
|
|
* Copyright (C) 2009 Martin Nordholts <martinn@src.gnome.org>
|
|
*
|
|
* 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 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <gegl.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "libpikabase/pikabase.h"
|
|
#include "libpikawidgets/pikawidgets.h"
|
|
|
|
#include "widgets-types.h"
|
|
|
|
#include "dialogs/dialogs.h" /* FIXME, we are in the widget layer */
|
|
|
|
#include "config/pikaguiconfig.h"
|
|
|
|
#include "core/pika.h"
|
|
#include "core/pikacontext.h"
|
|
#include "core/pikacontainer.h"
|
|
#include "core/pikacontainer.h"
|
|
#include "core/pikalist.h"
|
|
#include "core/pikaimage.h"
|
|
|
|
#include "menus/menus.h"
|
|
|
|
#include "pikacontainercombobox.h"
|
|
#include "pikacontainerview.h"
|
|
#include "pikadialogfactory.h"
|
|
#include "pikadock.h"
|
|
#include "pikadockbook.h"
|
|
#include "pikadockcolumns.h"
|
|
#include "pikadockcontainer.h"
|
|
#include "pikadockwindow.h"
|
|
#include "pikahelp-ids.h"
|
|
#include "pikamenufactory.h"
|
|
#include "pikasessioninfo-aux.h"
|
|
#include "pikasessioninfo.h"
|
|
#include "pikasessionmanaged.h"
|
|
#include "pikatoolbox.h"
|
|
#include "pikauimanager.h"
|
|
#include "pikawidgets-utils.h"
|
|
#include "pikawindow.h"
|
|
|
|
#include "pika-intl.h"
|
|
|
|
|
|
#define DEFAULT_DOCK_HEIGHT 300
|
|
#define DEFAULT_MENU_VIEW_SIZE GTK_ICON_SIZE_SMALL_TOOLBAR
|
|
#define AUX_INFO_SHOW_IMAGE_MENU "show-image-menu"
|
|
#define AUX_INFO_FOLLOW_ACTIVE_IMAGE "follow-active-image"
|
|
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
PROP_CONTEXT,
|
|
PROP_DIALOG_FACTORY,
|
|
PROP_UI_MANAGER_NAME,
|
|
PROP_IMAGE_CONTAINER,
|
|
PROP_DISPLAY_CONTAINER,
|
|
PROP_ALLOW_DOCKBOOK_ABSENCE
|
|
};
|
|
|
|
|
|
struct _PikaDockWindowPrivate
|
|
{
|
|
PikaContext *context;
|
|
|
|
PikaDialogFactory *dialog_factory;
|
|
|
|
gchar *ui_manager_name;
|
|
PikaUIManager *ui_manager;
|
|
GQuark image_flush_handler_id;
|
|
|
|
PikaDockColumns *dock_columns;
|
|
|
|
gboolean allow_dockbook_absence;
|
|
|
|
guint update_title_idle_id;
|
|
|
|
gint ID;
|
|
|
|
PikaContainer *image_container;
|
|
PikaContainer *display_container;
|
|
|
|
gboolean show_image_menu;
|
|
gboolean auto_follow_active;
|
|
|
|
GtkWidget *image_combo;
|
|
GtkWidget *auto_button;
|
|
};
|
|
|
|
|
|
static void pika_dock_window_dock_container_iface_init (PikaDockContainerInterface *iface);
|
|
static void pika_dock_window_session_managed_iface_init(PikaSessionManagedInterface*iface);
|
|
static void pika_dock_window_constructed (GObject *object);
|
|
static void pika_dock_window_dispose (GObject *object);
|
|
static void pika_dock_window_finalize (GObject *object);
|
|
static void pika_dock_window_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec);
|
|
static void pika_dock_window_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec);
|
|
static void pika_dock_window_style_updated (GtkWidget *widget);
|
|
static gboolean pika_dock_window_delete_event (GtkWidget *widget,
|
|
GdkEventAny *event);
|
|
static GList * pika_dock_window_get_docks (PikaDockContainer *dock_container);
|
|
static PikaDialogFactory * pika_dock_window_get_dialog_factory (PikaDockContainer *dock_container);
|
|
static PikaUIManager * pika_dock_window_get_ui_manager (PikaDockContainer *dock_container);
|
|
static void pika_dock_window_add_dock_from_session (PikaDockContainer *dock_container,
|
|
PikaDock *dock,
|
|
PikaSessionInfoDock *dock_info);
|
|
static GList * pika_dock_window_get_aux_info (PikaSessionManaged *session_managed);
|
|
static void pika_dock_window_set_aux_info (PikaSessionManaged *session_managed,
|
|
GList *aux_info);
|
|
static PikaAlignmentType
|
|
pika_dock_window_get_dock_side (PikaDockContainer *dock_container,
|
|
PikaDock *dock);
|
|
static gboolean pika_dock_window_should_add_to_recent (PikaDockWindow *dock_window);
|
|
static void pika_dock_window_display_changed (PikaDockWindow *dock_window,
|
|
PikaDisplay *display,
|
|
PikaContext *context);
|
|
static void pika_dock_window_image_changed (PikaDockWindow *dock_window,
|
|
PikaImage *image,
|
|
PikaContext *context);
|
|
static void pika_dock_window_image_flush (PikaImage *image,
|
|
gboolean invalidate_preview,
|
|
PikaDockWindow *dock_window);
|
|
static void pika_dock_window_update_title (PikaDockWindow *dock_window);
|
|
static gboolean pika_dock_window_update_title_idle (PikaDockWindow *dock_window);
|
|
static gchar * pika_dock_window_get_description (PikaDockWindow *dock_window,
|
|
gboolean complete);
|
|
static void pika_dock_window_dock_removed (PikaDockWindow *dock_window,
|
|
PikaDock *dock,
|
|
PikaDockColumns *dock_columns);
|
|
static void pika_dock_window_factory_display_changed (PikaContext *context,
|
|
PikaDisplay *display,
|
|
PikaDock *dock);
|
|
static void pika_dock_window_factory_image_changed (PikaContext *context,
|
|
PikaImage *image,
|
|
PikaDock *dock);
|
|
static void pika_dock_window_auto_clicked (GtkWidget *widget,
|
|
PikaDock *dock);
|
|
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (PikaDockWindow, pika_dock_window, PIKA_TYPE_WINDOW,
|
|
G_ADD_PRIVATE (PikaDockWindow)
|
|
G_IMPLEMENT_INTERFACE (PIKA_TYPE_DOCK_CONTAINER,
|
|
pika_dock_window_dock_container_iface_init)
|
|
G_IMPLEMENT_INTERFACE (PIKA_TYPE_SESSION_MANAGED,
|
|
pika_dock_window_session_managed_iface_init))
|
|
|
|
#define parent_class pika_dock_window_parent_class
|
|
|
|
|
|
static void
|
|
pika_dock_window_class_init (PikaDockWindowClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
|
|
|
object_class->constructed = pika_dock_window_constructed;
|
|
object_class->dispose = pika_dock_window_dispose;
|
|
object_class->finalize = pika_dock_window_finalize;
|
|
object_class->set_property = pika_dock_window_set_property;
|
|
object_class->get_property = pika_dock_window_get_property;
|
|
|
|
widget_class->style_updated = pika_dock_window_style_updated;
|
|
widget_class->delete_event = pika_dock_window_delete_event;
|
|
|
|
g_object_class_install_property (object_class, PROP_CONTEXT,
|
|
g_param_spec_object ("context", NULL, NULL,
|
|
PIKA_TYPE_CONTEXT,
|
|
PIKA_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
|
|
g_object_class_install_property (object_class, PROP_DIALOG_FACTORY,
|
|
g_param_spec_object ("dialog-factory",
|
|
NULL, NULL,
|
|
PIKA_TYPE_DIALOG_FACTORY,
|
|
PIKA_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
|
|
g_object_class_install_property (object_class, PROP_UI_MANAGER_NAME,
|
|
g_param_spec_string ("ui-manager-name",
|
|
NULL, NULL,
|
|
NULL,
|
|
PIKA_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
|
|
g_object_class_install_property (object_class, PROP_IMAGE_CONTAINER,
|
|
g_param_spec_object ("image-container",
|
|
NULL, NULL,
|
|
PIKA_TYPE_CONTAINER,
|
|
PIKA_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
|
|
g_object_class_install_property (object_class, PROP_DISPLAY_CONTAINER,
|
|
g_param_spec_object ("display-container",
|
|
NULL, NULL,
|
|
PIKA_TYPE_CONTAINER,
|
|
PIKA_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
|
|
g_object_class_install_property (object_class, PROP_ALLOW_DOCKBOOK_ABSENCE,
|
|
g_param_spec_boolean ("allow-dockbook-absence",
|
|
NULL, NULL,
|
|
FALSE,
|
|
PIKA_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
|
|
|
|
gtk_widget_class_install_style_property (widget_class,
|
|
g_param_spec_int ("default-height",
|
|
NULL, NULL,
|
|
-1, G_MAXINT,
|
|
DEFAULT_DOCK_HEIGHT,
|
|
PIKA_PARAM_READABLE));
|
|
|
|
gtk_widget_class_install_style_property (widget_class,
|
|
g_param_spec_enum ("menu-preview-size",
|
|
NULL, NULL,
|
|
GTK_TYPE_ICON_SIZE,
|
|
DEFAULT_MENU_VIEW_SIZE,
|
|
PIKA_PARAM_READABLE));
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_init (PikaDockWindow *dock_window)
|
|
{
|
|
static gint dock_window_ID = 1;
|
|
gchar *name = NULL;
|
|
|
|
dock_window->p = pika_dock_window_get_instance_private (dock_window);
|
|
dock_window->p->ID = dock_window_ID++;
|
|
dock_window->p->auto_follow_active = TRUE;
|
|
|
|
name = g_strdup_printf ("pika-dock-%d", dock_window->p->ID);
|
|
gtk_widget_set_name (GTK_WIDGET (dock_window), name);
|
|
g_free (name);
|
|
|
|
gtk_window_set_resizable (GTK_WINDOW (dock_window), TRUE);
|
|
gtk_window_set_focus_on_map (GTK_WINDOW (dock_window), FALSE);
|
|
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dock_window), FALSE);
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_dock_container_iface_init (PikaDockContainerInterface *iface)
|
|
{
|
|
iface->get_docks = pika_dock_window_get_docks;
|
|
iface->get_dialog_factory = pika_dock_window_get_dialog_factory;
|
|
iface->get_ui_manager = pika_dock_window_get_ui_manager;
|
|
iface->add_dock = pika_dock_window_add_dock_from_session;
|
|
iface->get_dock_side = pika_dock_window_get_dock_side;
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_session_managed_iface_init (PikaSessionManagedInterface *iface)
|
|
{
|
|
iface->get_aux_info = pika_dock_window_get_aux_info;
|
|
iface->set_aux_info = pika_dock_window_set_aux_info;
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_constructed (GObject *object)
|
|
{
|
|
PikaDockWindow *dock_window = PIKA_DOCK_WINDOW (object);
|
|
PikaGuiConfig *config;
|
|
PikaContext *factory_context;
|
|
PikaMenuFactory *menu_factory;
|
|
Pika *pika;
|
|
gint menu_view_width = -1;
|
|
gint menu_view_height = -1;
|
|
|
|
G_OBJECT_CLASS (parent_class)->constructed (object);
|
|
|
|
pika = PIKA (dock_window->p->context->pika);
|
|
config = PIKA_GUI_CONFIG (pika->config);
|
|
|
|
/* Create a separate context per dock so that docks can be bound to
|
|
* a specific image and does not necessarily have to follow the
|
|
* active image in the user context
|
|
*/
|
|
g_object_unref (dock_window->p->context);
|
|
dock_window->p->context = pika_context_new (pika, "Dock Context", NULL);
|
|
dock_window->p->image_container = pika->images;
|
|
dock_window->p->display_container = pika->displays;
|
|
|
|
factory_context =
|
|
pika_dialog_factory_get_context (dock_window->p->dialog_factory);
|
|
|
|
/* Setup hints */
|
|
pika_window_set_hint (GTK_WINDOW (dock_window), config->dock_window_hint);
|
|
|
|
menu_factory = menus_get_global_menu_factory (pika);
|
|
|
|
/* Make image window related keyboard shortcuts work also when a
|
|
* dock window is the focused window
|
|
*/
|
|
dock_window->p->ui_manager =
|
|
pika_menu_factory_get_manager (menu_factory,
|
|
dock_window->p->ui_manager_name,
|
|
dock_window);
|
|
|
|
g_signal_connect_object (dock_window->p->context, "display-changed",
|
|
G_CALLBACK (pika_dock_window_display_changed),
|
|
dock_window,
|
|
G_CONNECT_SWAPPED);
|
|
g_signal_connect_object (dock_window->p->context, "image-changed",
|
|
G_CALLBACK (pika_dock_window_image_changed),
|
|
dock_window,
|
|
G_CONNECT_SWAPPED);
|
|
|
|
dock_window->p->image_flush_handler_id =
|
|
pika_container_add_handler (pika->images, "flush",
|
|
G_CALLBACK (pika_dock_window_image_flush),
|
|
dock_window);
|
|
|
|
pika_context_define_properties (dock_window->p->context,
|
|
PIKA_CONTEXT_PROP_MASK_ALL &
|
|
~(PIKA_CONTEXT_PROP_MASK_IMAGE |
|
|
PIKA_CONTEXT_PROP_MASK_DISPLAY),
|
|
FALSE);
|
|
pika_context_set_parent (dock_window->p->context,
|
|
factory_context);
|
|
|
|
/* Setup widget hierarchy */
|
|
{
|
|
GtkWidget *vbox = NULL;
|
|
|
|
/* Top-level GtkVBox */
|
|
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
|
gtk_container_add (GTK_CONTAINER (dock_window), vbox);
|
|
gtk_widget_show (vbox);
|
|
|
|
/* Image selection menu */
|
|
{
|
|
GtkWidget *hbox = NULL;
|
|
|
|
/* GtkHBox */
|
|
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
|
|
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
|
if (dock_window->p->show_image_menu)
|
|
gtk_widget_show (hbox);
|
|
|
|
/* Image combo */
|
|
dock_window->p->image_combo = pika_container_combo_box_new (NULL, NULL, 16, 1);
|
|
gtk_box_pack_start (GTK_BOX (hbox), dock_window->p->image_combo, TRUE, TRUE, 0);
|
|
g_signal_connect (dock_window->p->image_combo, "destroy",
|
|
G_CALLBACK (gtk_widget_destroyed),
|
|
&dock_window->p->image_combo);
|
|
pika_help_set_help_data (dock_window->p->image_combo,
|
|
NULL, PIKA_HELP_DOCK_IMAGE_MENU);
|
|
gtk_widget_show (dock_window->p->image_combo);
|
|
|
|
/* Auto button */
|
|
dock_window->p->auto_button = gtk_toggle_button_new_with_label (_("Auto"));
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dock_window->p->auto_button),
|
|
dock_window->p->auto_follow_active);
|
|
gtk_box_pack_start (GTK_BOX (hbox), dock_window->p->auto_button, FALSE, FALSE, 0);
|
|
gtk_widget_show (dock_window->p->auto_button);
|
|
|
|
g_signal_connect (dock_window->p->auto_button, "clicked",
|
|
G_CALLBACK (pika_dock_window_auto_clicked),
|
|
dock_window);
|
|
|
|
pika_help_set_help_data (dock_window->p->auto_button,
|
|
_("When enabled, the dialog automatically "
|
|
"follows the image you are working on."),
|
|
PIKA_HELP_DOCK_AUTO_BUTTON);
|
|
}
|
|
|
|
/* PikaDockColumns */
|
|
/* Let the PikaDockColumns mirror the context so that a PikaDock can
|
|
* get it when inside a dock window. We do the same thing in the
|
|
* PikaImageWindow so docks can get the PikaContext there as well
|
|
*/
|
|
dock_window->p->dock_columns =
|
|
PIKA_DOCK_COLUMNS (pika_dock_columns_new (dock_window->p->context,
|
|
dock_window->p->dialog_factory,
|
|
dock_window->p->ui_manager));
|
|
gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (dock_window->p->dock_columns),
|
|
TRUE, TRUE, 0);
|
|
gtk_widget_show (GTK_WIDGET (dock_window->p->dock_columns));
|
|
g_signal_connect_object (dock_window->p->dock_columns, "dock-removed",
|
|
G_CALLBACK (pika_dock_window_dock_removed),
|
|
dock_window,
|
|
G_CONNECT_SWAPPED);
|
|
|
|
g_signal_connect_object (dock_window->p->dock_columns, "dock-added",
|
|
G_CALLBACK (pika_dock_window_update_title),
|
|
dock_window,
|
|
G_CONNECT_SWAPPED);
|
|
g_signal_connect_object (dock_window->p->dock_columns, "dock-removed",
|
|
G_CALLBACK (pika_dock_window_update_title),
|
|
dock_window,
|
|
G_CONNECT_SWAPPED);
|
|
}
|
|
|
|
if (dock_window->p->auto_follow_active)
|
|
{
|
|
if (pika_context_get_display (factory_context))
|
|
pika_context_copy_property (factory_context,
|
|
dock_window->p->context,
|
|
PIKA_CONTEXT_PROP_DISPLAY);
|
|
else
|
|
pika_context_copy_property (factory_context,
|
|
dock_window->p->context,
|
|
PIKA_CONTEXT_PROP_IMAGE);
|
|
}
|
|
|
|
g_signal_connect_object (factory_context, "display-changed",
|
|
G_CALLBACK (pika_dock_window_factory_display_changed),
|
|
dock_window,
|
|
0);
|
|
g_signal_connect_object (factory_context, "image-changed",
|
|
G_CALLBACK (pika_dock_window_factory_image_changed),
|
|
dock_window,
|
|
0);
|
|
|
|
gtk_icon_size_lookup (DEFAULT_MENU_VIEW_SIZE,
|
|
&menu_view_width,
|
|
&menu_view_height);
|
|
|
|
g_object_set (dock_window->p->image_combo,
|
|
"container", dock_window->p->image_container,
|
|
"context", dock_window->p->context,
|
|
NULL);
|
|
|
|
pika_help_connect (GTK_WIDGET (dock_window), pika_standard_help_func,
|
|
PIKA_HELP_DOCK, NULL, NULL);
|
|
|
|
if (dock_window->p->auto_follow_active)
|
|
{
|
|
if (pika_context_get_display (factory_context))
|
|
pika_context_copy_property (factory_context,
|
|
dock_window->p->context,
|
|
PIKA_CONTEXT_PROP_DISPLAY);
|
|
else
|
|
pika_context_copy_property (factory_context,
|
|
dock_window->p->context,
|
|
PIKA_CONTEXT_PROP_IMAGE);
|
|
}
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_dispose (GObject *object)
|
|
{
|
|
PikaDockWindow *dock_window = PIKA_DOCK_WINDOW (object);
|
|
|
|
if (dock_window->p->update_title_idle_id)
|
|
{
|
|
g_source_remove (dock_window->p->update_title_idle_id);
|
|
dock_window->p->update_title_idle_id = 0;
|
|
}
|
|
|
|
if (dock_window->p->image_flush_handler_id)
|
|
{
|
|
pika_container_remove_handler (dock_window->p->context->pika->images,
|
|
dock_window->p->image_flush_handler_id);
|
|
dock_window->p->image_flush_handler_id = 0;
|
|
}
|
|
|
|
g_clear_object (&dock_window->p->dialog_factory);
|
|
|
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_finalize (GObject *object)
|
|
{
|
|
PikaDockWindow *dock_window = PIKA_DOCK_WINDOW (object);
|
|
PikaMenuFactory *menu_factory;
|
|
Pika *pika;
|
|
|
|
pika = PIKA (dock_window->p->context->pika);
|
|
menu_factory = menus_get_global_menu_factory (pika);
|
|
|
|
/* If the whole GUI is in destruction, global menu factory might already not
|
|
* exist anymore.
|
|
*/
|
|
if (menu_factory != NULL)
|
|
pika_menu_factory_delete_manager (menu_factory,
|
|
dock_window->p->ui_manager_name,
|
|
dock_window);
|
|
g_clear_pointer (&dock_window->p->ui_manager_name, g_free);
|
|
g_clear_object (&dock_window->p->context);
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
PikaDockWindow *dock_window = PIKA_DOCK_WINDOW (object);
|
|
|
|
switch (property_id)
|
|
{
|
|
case PROP_CONTEXT:
|
|
dock_window->p->context = g_value_dup_object (value);
|
|
break;
|
|
|
|
case PROP_DIALOG_FACTORY:
|
|
dock_window->p->dialog_factory = g_value_dup_object (value);
|
|
break;
|
|
|
|
case PROP_UI_MANAGER_NAME:
|
|
g_free (dock_window->p->ui_manager_name);
|
|
dock_window->p->ui_manager_name = g_value_dup_string (value);
|
|
break;
|
|
|
|
case PROP_IMAGE_CONTAINER:
|
|
dock_window->p->image_container = g_value_dup_object (value);
|
|
break;
|
|
|
|
case PROP_DISPLAY_CONTAINER:
|
|
dock_window->p->display_container = g_value_dup_object (value);
|
|
break;
|
|
|
|
case PROP_ALLOW_DOCKBOOK_ABSENCE:
|
|
dock_window->p->allow_dockbook_absence = g_value_get_boolean (value);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
PikaDockWindow *dock_window = PIKA_DOCK_WINDOW (object);
|
|
|
|
switch (property_id)
|
|
{
|
|
case PROP_CONTEXT:
|
|
g_value_set_object (value, dock_window->p->context);
|
|
break;
|
|
|
|
case PROP_DIALOG_FACTORY:
|
|
g_value_set_object (value, dock_window->p->dialog_factory);
|
|
break;
|
|
|
|
case PROP_UI_MANAGER_NAME:
|
|
g_value_set_string (value, dock_window->p->ui_manager_name);
|
|
break;
|
|
|
|
case PROP_IMAGE_CONTAINER:
|
|
g_value_set_object (value, dock_window->p->image_container);
|
|
break;
|
|
|
|
case PROP_DISPLAY_CONTAINER:
|
|
g_value_set_object (value, dock_window->p->display_container);
|
|
break;
|
|
|
|
case PROP_ALLOW_DOCKBOOK_ABSENCE:
|
|
g_value_set_boolean (value, dock_window->p->allow_dockbook_absence);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_style_updated (GtkWidget *widget)
|
|
{
|
|
PikaDockWindow *dock_window = PIKA_DOCK_WINDOW (widget);
|
|
GtkStyleContext *button_style;
|
|
GtkIconSize menu_view_size;
|
|
gint default_height = DEFAULT_DOCK_HEIGHT;
|
|
|
|
GTK_WIDGET_CLASS (parent_class)->style_updated (widget);
|
|
|
|
gtk_widget_style_get (widget,
|
|
"default-height", &default_height,
|
|
"menu-preview-size", &menu_view_size,
|
|
NULL);
|
|
|
|
gtk_window_set_default_size (GTK_WINDOW (widget), -1, default_height);
|
|
|
|
if (dock_window->p->image_combo)
|
|
{
|
|
GtkBorder border;
|
|
gint menu_view_width = 18;
|
|
gint menu_view_height = 18;
|
|
gint focus_line_width;
|
|
gint focus_padding;
|
|
|
|
gtk_icon_size_lookup (menu_view_size,
|
|
&menu_view_width,
|
|
&menu_view_height);
|
|
|
|
gtk_widget_style_get (dock_window->p->auto_button,
|
|
"focus-line-width", &focus_line_width,
|
|
"focus-padding", &focus_padding,
|
|
NULL);
|
|
|
|
button_style = gtk_widget_get_style_context (widget);
|
|
gtk_style_context_get_border (button_style,
|
|
gtk_widget_get_state_flags (widget),
|
|
&border);
|
|
|
|
pika_container_view_set_view_size (PIKA_CONTAINER_VIEW (dock_window->p->image_combo),
|
|
menu_view_height, 1);
|
|
|
|
gtk_widget_set_size_request (dock_window->p->auto_button, -1,
|
|
menu_view_height +
|
|
2 * (1 /* CHILD_SPACING */ +
|
|
border.top +
|
|
border.bottom +
|
|
focus_padding +
|
|
focus_line_width));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* pika_dock_window_delete_event:
|
|
* @widget:
|
|
* @event:
|
|
*
|
|
* Makes sure that when dock windows are closed they are added to the
|
|
* list of recently closed docks so that they are easy to bring back.
|
|
**/
|
|
static gboolean
|
|
pika_dock_window_delete_event (GtkWidget *widget,
|
|
GdkEventAny *event)
|
|
{
|
|
PikaDockWindow *dock_window = PIKA_DOCK_WINDOW (widget);
|
|
PikaSessionInfo *info = NULL;
|
|
const gchar *entry_name = NULL;
|
|
PikaDialogFactoryEntry *entry = NULL;
|
|
gchar *name = NULL;
|
|
|
|
/* Don't add docks with just a single dockable to the list of
|
|
* recently closed dock since those can be brought back through the
|
|
* normal Windows->Dockable Dialogs menu
|
|
*/
|
|
if (! pika_dock_window_should_add_to_recent (dock_window))
|
|
return FALSE;
|
|
|
|
info = pika_session_info_new ();
|
|
|
|
name = pika_dock_window_get_description (dock_window, TRUE /*complete*/);
|
|
pika_object_set_name (PIKA_OBJECT (info), name);
|
|
g_free (name);
|
|
|
|
pika_session_info_get_info_with_widget (info, GTK_WIDGET (dock_window));
|
|
|
|
entry_name = (pika_dock_window_has_toolbox (dock_window) ?
|
|
"pika-toolbox-window" :
|
|
"pika-dock-window");
|
|
entry = pika_dialog_factory_find_entry (dock_window->p->dialog_factory,
|
|
entry_name);
|
|
pika_session_info_set_factory_entry (info, entry);
|
|
|
|
pika_container_add (global_recent_docks, PIKA_OBJECT (info));
|
|
g_object_unref (info);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static GList *
|
|
pika_dock_window_get_docks (PikaDockContainer *dock_container)
|
|
{
|
|
PikaDockWindow *dock_window = PIKA_DOCK_WINDOW (dock_container);
|
|
|
|
return g_list_copy (pika_dock_columns_get_docks (dock_window->p->dock_columns));
|
|
}
|
|
|
|
static PikaDialogFactory *
|
|
pika_dock_window_get_dialog_factory (PikaDockContainer *dock_container)
|
|
{
|
|
PikaDockWindow *dock_window = PIKA_DOCK_WINDOW (dock_container);
|
|
|
|
return dock_window->p->dialog_factory;
|
|
}
|
|
|
|
static PikaUIManager *
|
|
pika_dock_window_get_ui_manager (PikaDockContainer *dock_container)
|
|
{
|
|
PikaDockWindow *dock_window = PIKA_DOCK_WINDOW (dock_container);
|
|
|
|
return dock_window->p->ui_manager;
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_add_dock_from_session (PikaDockContainer *dock_container,
|
|
PikaDock *dock,
|
|
PikaSessionInfoDock *dock_info)
|
|
{
|
|
PikaDockWindow *dock_window = PIKA_DOCK_WINDOW (dock_container);
|
|
|
|
pika_dock_window_add_dock (dock_window,
|
|
dock,
|
|
-1 /*index*/);
|
|
}
|
|
|
|
static GList *
|
|
pika_dock_window_get_aux_info (PikaSessionManaged *session_managed)
|
|
{
|
|
PikaDockWindow *dock_window = PIKA_DOCK_WINDOW (session_managed);
|
|
GList *aux_info = NULL;
|
|
PikaSessionInfoAux *aux;
|
|
|
|
if (dock_window->p->allow_dockbook_absence)
|
|
{
|
|
/* Assume it is the toolbox; it does not have aux info */
|
|
return NULL;
|
|
}
|
|
|
|
g_return_val_if_fail (PIKA_IS_DOCK_WINDOW (dock_window), NULL);
|
|
|
|
aux = pika_session_info_aux_new (AUX_INFO_SHOW_IMAGE_MENU,
|
|
dock_window->p->show_image_menu ?
|
|
"true" : "false");
|
|
aux_info = g_list_append (aux_info, aux);
|
|
|
|
aux = pika_session_info_aux_new (AUX_INFO_FOLLOW_ACTIVE_IMAGE,
|
|
dock_window->p->auto_follow_active ?
|
|
"true" : "false");
|
|
aux_info = g_list_append (aux_info, aux);
|
|
|
|
return aux_info;
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_set_aux_info (PikaSessionManaged *session_managed,
|
|
GList *aux_info)
|
|
{
|
|
PikaDockWindow *dock_window;
|
|
GList *list;
|
|
gboolean menu_shown;
|
|
gboolean auto_follow;
|
|
|
|
g_return_if_fail (PIKA_IS_DOCK_WINDOW (session_managed));
|
|
|
|
dock_window = PIKA_DOCK_WINDOW (session_managed);
|
|
menu_shown = dock_window->p->show_image_menu;
|
|
auto_follow = dock_window->p->auto_follow_active;
|
|
|
|
for (list = aux_info; list; list = g_list_next (list))
|
|
{
|
|
PikaSessionInfoAux *aux = list->data;
|
|
|
|
if (! strcmp (aux->name, AUX_INFO_SHOW_IMAGE_MENU))
|
|
{
|
|
menu_shown = ! g_ascii_strcasecmp (aux->value, "true");
|
|
}
|
|
else if (! strcmp (aux->name, AUX_INFO_FOLLOW_ACTIVE_IMAGE))
|
|
{
|
|
auto_follow = ! g_ascii_strcasecmp (aux->value, "true");
|
|
}
|
|
}
|
|
|
|
if (menu_shown != dock_window->p->show_image_menu)
|
|
pika_dock_window_set_show_image_menu (dock_window, menu_shown);
|
|
|
|
if (auto_follow != dock_window->p->auto_follow_active)
|
|
pika_dock_window_set_auto_follow_active (dock_window, auto_follow);
|
|
}
|
|
|
|
static PikaAlignmentType
|
|
pika_dock_window_get_dock_side (PikaDockContainer *dock_container,
|
|
PikaDock *dock)
|
|
{
|
|
g_return_val_if_fail (PIKA_IS_DOCK_WINDOW (dock_container), -1);
|
|
g_return_val_if_fail (PIKA_IS_DOCK (dock), -1);
|
|
|
|
/* A PikaDockWindow don't have docks on different sides, it's just
|
|
* one set of columns
|
|
*/
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* pika_dock_window_should_add_to_recent:
|
|
* @dock_window:
|
|
*
|
|
* Returns: %FALSE if the dock window can be recreated with one
|
|
* Windows menu item such as Windows->Toolbox or
|
|
* Windows->Dockable Dialogs->Layers, %TRUE if not. It should
|
|
* then be added to the list of recently closed docks.
|
|
**/
|
|
static gboolean
|
|
pika_dock_window_should_add_to_recent (PikaDockWindow *dock_window)
|
|
{
|
|
GList *docks;
|
|
gboolean should_add = TRUE;
|
|
|
|
docks = pika_dock_container_get_docks (PIKA_DOCK_CONTAINER (dock_window));
|
|
|
|
if (! docks)
|
|
{
|
|
should_add = FALSE;
|
|
}
|
|
else if (g_list_length (docks) == 1)
|
|
{
|
|
PikaDock *dock = PIKA_DOCK (g_list_nth_data (docks, 0));
|
|
|
|
if (PIKA_IS_TOOLBOX (dock) &&
|
|
pika_dock_get_n_dockables (dock) == 0)
|
|
{
|
|
should_add = FALSE;
|
|
}
|
|
else if (! PIKA_IS_TOOLBOX (dock) &&
|
|
pika_dock_get_n_dockables (dock) == 1)
|
|
{
|
|
should_add = FALSE;
|
|
}
|
|
}
|
|
|
|
g_list_free (docks);
|
|
|
|
return should_add;
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_image_flush (PikaImage *image,
|
|
gboolean invalidate_preview,
|
|
PikaDockWindow *dock_window)
|
|
{
|
|
if (image == pika_context_get_image (dock_window->p->context))
|
|
{
|
|
PikaDisplay *display = pika_context_get_display (dock_window->p->context);
|
|
|
|
if (display)
|
|
pika_ui_manager_update (dock_window->p->ui_manager, display);
|
|
}
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_update_title (PikaDockWindow *dock_window)
|
|
{
|
|
if (dock_window->p->update_title_idle_id)
|
|
g_source_remove (dock_window->p->update_title_idle_id);
|
|
|
|
dock_window->p->update_title_idle_id =
|
|
g_idle_add ((GSourceFunc) pika_dock_window_update_title_idle,
|
|
dock_window);
|
|
}
|
|
|
|
static gboolean
|
|
pika_dock_window_update_title_idle (PikaDockWindow *dock_window)
|
|
{
|
|
gchar *desc = pika_dock_window_get_description (dock_window,
|
|
FALSE /*complete*/);
|
|
if (desc)
|
|
{
|
|
gtk_window_set_title (GTK_WINDOW (dock_window), desc);
|
|
g_free (desc);
|
|
}
|
|
|
|
dock_window->p->update_title_idle_id = 0;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gchar *
|
|
pika_dock_window_get_description (PikaDockWindow *dock_window,
|
|
gboolean complete)
|
|
{
|
|
GString *complete_desc = g_string_new (NULL);
|
|
GList *docks = NULL;
|
|
GList *iter = NULL;
|
|
|
|
docks = pika_dock_container_get_docks (PIKA_DOCK_CONTAINER (dock_window));
|
|
|
|
for (iter = docks;
|
|
iter;
|
|
iter = g_list_next (iter))
|
|
{
|
|
gchar *desc = pika_dock_get_description (PIKA_DOCK (iter->data), complete);
|
|
g_string_append (complete_desc, desc);
|
|
g_free (desc);
|
|
|
|
if (g_list_next (iter))
|
|
g_string_append (complete_desc, PIKA_DOCK_COLUMN_SEPARATOR);
|
|
}
|
|
|
|
g_list_free (docks);
|
|
|
|
return g_string_free (complete_desc, FALSE /*free_segment*/);
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_dock_removed (PikaDockWindow *dock_window,
|
|
PikaDock *dock,
|
|
PikaDockColumns *dock_columns)
|
|
{
|
|
g_return_if_fail (PIKA_IS_DOCK (dock));
|
|
|
|
if (pika_dock_columns_get_docks (dock_columns) == NULL &&
|
|
! dock_window->p->allow_dockbook_absence)
|
|
gtk_widget_destroy (GTK_WIDGET (dock_window));
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_factory_display_changed (PikaContext *context,
|
|
PikaDisplay *display,
|
|
PikaDock *dock)
|
|
{
|
|
PikaDockWindow *dock_window = PIKA_DOCK_WINDOW (dock);
|
|
|
|
if (display && dock_window->p->auto_follow_active)
|
|
pika_context_set_display (dock_window->p->context, display);
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_factory_image_changed (PikaContext *context,
|
|
PikaImage *image,
|
|
PikaDock *dock)
|
|
{
|
|
PikaDockWindow *dock_window = PIKA_DOCK_WINDOW (dock);
|
|
|
|
/* won't do anything if we already set the display above */
|
|
if (image && dock_window->p->auto_follow_active)
|
|
pika_context_set_image (dock_window->p->context, image);
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_display_changed (PikaDockWindow *dock_window,
|
|
PikaDisplay *display,
|
|
PikaContext *context)
|
|
{
|
|
/* make sure auto-follow-active works both ways */
|
|
if (display && dock_window->p->auto_follow_active)
|
|
{
|
|
PikaContext *factory_context =
|
|
pika_dialog_factory_get_context (dock_window->p->dialog_factory);
|
|
|
|
pika_context_set_display (factory_context, display);
|
|
}
|
|
|
|
pika_ui_manager_update (dock_window->p->ui_manager,
|
|
display);
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_image_changed (PikaDockWindow *dock_window,
|
|
PikaImage *image,
|
|
PikaContext *context)
|
|
{
|
|
PikaContainer *image_container = dock_window->p->image_container;
|
|
PikaContainer *display_container = dock_window->p->display_container;
|
|
|
|
/* make sure auto-follow-active works both ways */
|
|
if (image && dock_window->p->auto_follow_active)
|
|
{
|
|
PikaContext *factory_context =
|
|
pika_dialog_factory_get_context (dock_window->p->dialog_factory);
|
|
|
|
pika_context_set_image (factory_context, image);
|
|
}
|
|
|
|
if (image == NULL && ! pika_container_is_empty (image_container))
|
|
{
|
|
image = PIKA_IMAGE (pika_container_get_first_child (image_container));
|
|
|
|
/* this invokes this function recursively but we don't enter
|
|
* the if() branch the second time
|
|
*/
|
|
pika_context_set_image (context, image);
|
|
|
|
/* stop the emission of the original signal (the emission of
|
|
* the recursive signal is finished)
|
|
*/
|
|
g_signal_stop_emission_by_name (context, "image-changed");
|
|
}
|
|
else if (image != NULL && ! pika_container_is_empty (display_container))
|
|
{
|
|
PikaDisplay *display;
|
|
PikaImage *display_image;
|
|
gboolean find_display = TRUE;
|
|
|
|
display = pika_context_get_display (context);
|
|
|
|
if (display)
|
|
{
|
|
g_object_get (display, "image", &display_image, NULL);
|
|
|
|
if (display_image)
|
|
{
|
|
g_object_unref (display_image);
|
|
|
|
if (display_image == image)
|
|
find_display = FALSE;
|
|
}
|
|
}
|
|
|
|
if (find_display)
|
|
{
|
|
GList *list;
|
|
|
|
for (list = PIKA_LIST (display_container)->queue->head;
|
|
list;
|
|
list = g_list_next (list))
|
|
{
|
|
display = list->data;
|
|
|
|
g_object_get (display, "image", &display_image, NULL);
|
|
|
|
if (display_image)
|
|
{
|
|
g_object_unref (display_image);
|
|
|
|
if (display_image == image)
|
|
{
|
|
/* this invokes this function recursively but we
|
|
* don't enter the if(find_display) branch the
|
|
* second time
|
|
*/
|
|
pika_context_set_display (context, display);
|
|
|
|
/* don't stop signal emission here because the
|
|
* context's image was not changed by the
|
|
* recursive call
|
|
*/
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pika_ui_manager_update (dock_window->p->ui_manager,
|
|
pika_context_get_display (context));
|
|
}
|
|
|
|
static void
|
|
pika_dock_window_auto_clicked (GtkWidget *widget,
|
|
PikaDock *dock)
|
|
{
|
|
PikaDockWindow *dock_window = PIKA_DOCK_WINDOW (dock);
|
|
|
|
pika_toggle_button_update (widget, &dock_window->p->auto_follow_active);
|
|
|
|
if (dock_window->p->auto_follow_active)
|
|
{
|
|
PikaContext *context;
|
|
|
|
context = pika_dialog_factory_get_context (dock_window->p->dialog_factory);
|
|
|
|
pika_context_copy_properties (context,
|
|
dock_window->p->context,
|
|
PIKA_CONTEXT_PROP_MASK_DISPLAY |
|
|
PIKA_CONTEXT_PROP_MASK_IMAGE);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
pika_dock_window_add_dock (PikaDockWindow *dock_window,
|
|
PikaDock *dock,
|
|
gint index)
|
|
{
|
|
g_return_if_fail (PIKA_IS_DOCK_WINDOW (dock_window));
|
|
g_return_if_fail (PIKA_IS_DOCK (dock));
|
|
|
|
pika_dock_columns_add_dock (dock_window->p->dock_columns,
|
|
PIKA_DOCK (dock),
|
|
index);
|
|
|
|
g_signal_connect_object (dock, "description-invalidated",
|
|
G_CALLBACK (pika_dock_window_update_title),
|
|
dock_window,
|
|
G_CONNECT_SWAPPED);
|
|
|
|
/* Some docks like the toolbox dock needs to maintain special hints
|
|
* on its container GtkWindow, allow those to do so
|
|
*/
|
|
pika_dock_set_host_geometry_hints (dock, GTK_WINDOW (dock_window));
|
|
g_signal_connect_object (dock, "geometry-invalidated",
|
|
G_CALLBACK (pika_dock_set_host_geometry_hints),
|
|
dock_window, 0);
|
|
}
|
|
|
|
void
|
|
pika_dock_window_remove_dock (PikaDockWindow *dock_window,
|
|
PikaDock *dock)
|
|
{
|
|
pika_dock_columns_remove_dock (dock_window->p->dock_columns,
|
|
PIKA_DOCK (dock));
|
|
|
|
g_signal_handlers_disconnect_by_func (dock,
|
|
pika_dock_window_update_title,
|
|
dock_window);
|
|
g_signal_handlers_disconnect_by_func (dock,
|
|
pika_dock_set_host_geometry_hints,
|
|
dock_window);
|
|
}
|
|
|
|
GtkWidget *
|
|
pika_dock_window_new (const gchar *role,
|
|
const gchar *ui_manager_name,
|
|
gboolean allow_dockbook_absence,
|
|
PikaDialogFactory *dialog_factory,
|
|
PikaContext *context)
|
|
{
|
|
g_return_val_if_fail (PIKA_IS_DIALOG_FACTORY (dialog_factory), NULL);
|
|
g_return_val_if_fail (PIKA_IS_CONTEXT (context), NULL);
|
|
|
|
return g_object_new (PIKA_TYPE_DOCK_WINDOW,
|
|
"role", role,
|
|
"ui-manager-name", ui_manager_name,
|
|
"allow-dockbook-absence", allow_dockbook_absence,
|
|
"dialog-factory", dialog_factory,
|
|
"context", context,
|
|
NULL);
|
|
}
|
|
|
|
gint
|
|
pika_dock_window_get_id (PikaDockWindow *dock_window)
|
|
{
|
|
g_return_val_if_fail (PIKA_IS_DOCK_WINDOW (dock_window), 0);
|
|
|
|
return dock_window->p->ID;
|
|
}
|
|
|
|
PikaContext *
|
|
pika_dock_window_get_context (PikaDockWindow *dock_window)
|
|
{
|
|
g_return_val_if_fail (PIKA_IS_DOCK_WINDOW (dock_window), NULL);
|
|
|
|
return dock_window->p->context;
|
|
}
|
|
|
|
gboolean
|
|
pika_dock_window_get_auto_follow_active (PikaDockWindow *dock_window)
|
|
{
|
|
g_return_val_if_fail (PIKA_IS_DOCK_WINDOW (dock_window), FALSE);
|
|
|
|
return dock_window->p->auto_follow_active;
|
|
}
|
|
|
|
void
|
|
pika_dock_window_set_auto_follow_active (PikaDockWindow *dock_window,
|
|
gboolean auto_follow_active)
|
|
{
|
|
g_return_if_fail (PIKA_IS_DOCK_WINDOW (dock_window));
|
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dock_window->p->auto_button),
|
|
auto_follow_active ? TRUE : FALSE);
|
|
}
|
|
|
|
gboolean
|
|
pika_dock_window_get_show_image_menu (PikaDockWindow *dock_window)
|
|
{
|
|
g_return_val_if_fail (PIKA_IS_DOCK_WINDOW (dock_window), FALSE);
|
|
|
|
return dock_window->p->show_image_menu;
|
|
}
|
|
|
|
void
|
|
pika_dock_window_set_show_image_menu (PikaDockWindow *dock_window,
|
|
gboolean show)
|
|
{
|
|
GtkWidget *parent;
|
|
|
|
g_return_if_fail (PIKA_IS_DOCK_WINDOW (dock_window));
|
|
|
|
parent = gtk_widget_get_parent (dock_window->p->image_combo);
|
|
|
|
gtk_widget_set_visible (parent, show);
|
|
|
|
dock_window->p->show_image_menu = show ? TRUE : FALSE;
|
|
}
|
|
|
|
void
|
|
pika_dock_window_setup (PikaDockWindow *dock_window,
|
|
PikaDockWindow *template)
|
|
{
|
|
pika_dock_window_set_auto_follow_active (PIKA_DOCK_WINDOW (dock_window),
|
|
template->p->auto_follow_active);
|
|
pika_dock_window_set_show_image_menu (PIKA_DOCK_WINDOW (dock_window),
|
|
template->p->show_image_menu);
|
|
}
|
|
|
|
/**
|
|
* pika_dock_window_has_toolbox:
|
|
* @dock_window:
|
|
*
|
|
* Returns: %TRUE if the dock window has a PikaToolbox dock, %FALSE
|
|
* otherwise.
|
|
**/
|
|
gboolean
|
|
pika_dock_window_has_toolbox (PikaDockWindow *dock_window)
|
|
{
|
|
GList *iter = NULL;
|
|
|
|
g_return_val_if_fail (PIKA_IS_DOCK_WINDOW (dock_window), FALSE);
|
|
|
|
for (iter = pika_dock_columns_get_docks (dock_window->p->dock_columns);
|
|
iter;
|
|
iter = g_list_next (iter))
|
|
{
|
|
if (PIKA_IS_TOOLBOX (iter->data))
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/**
|
|
* pika_dock_window_from_dock:
|
|
* @dock:
|
|
*
|
|
* For convenience.
|
|
*
|
|
* Returns: If the toplevel widget for the dock is a PikaDockWindow,
|
|
* return that. Otherwise return %NULL.
|
|
**/
|
|
PikaDockWindow *
|
|
pika_dock_window_from_dock (PikaDock *dock)
|
|
{
|
|
GtkWidget *toplevel = NULL;
|
|
|
|
g_return_val_if_fail (PIKA_IS_DOCK (dock), NULL);
|
|
|
|
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (dock));
|
|
|
|
if (PIKA_IS_DOCK_WINDOW (toplevel))
|
|
return PIKA_DOCK_WINDOW (toplevel);
|
|
else
|
|
return NULL;
|
|
}
|