gimp/app/widgets/gimpdock.c

637 lines
18 KiB
C
Raw Normal View History

/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpdock.c
* Copyright (C) 2001-2005 Michael Natterer <mitch@gimp.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 <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gtk/gtk.h>
#include "libgimpwidgets/gimpwidgets.h"
#include "widgets-types.h"
#include "core/gimp.h"
g_strdup() the stock_id passed to gimp_tool_info_new() because the 2002-03-14 Michael Natterer <mitch@gimp.org> * app/core/gimptoolinfo.c: g_strdup() the stock_id passed to gimp_tool_info_new() because the caller's memory may disappear after registering the tool (tool modules). Made a GimpDock out of the toolbox: * app/gui/Makefile.am * app/gui/color-area.[ch] * app/gui/indicator-area.[ch] * app/gui/toolbox.[ch]: removed... * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimptoolbox-color-area.[ch] * app/widgets/gimptoolbox-indicator-area.[ch] * app/widgets/gimptoolbox.[ch]: ...and added here. * app/widgets/gimpdock.[ch]: don't set a minimal width. Added a "destroy_if_empty" boolean so we can prevent destruction of the toolbox if it's last dockable is removed. Added gimp_dock_construct() which is called from GimpImageDock and GimpToolbox. * app/widgets/gimpimagedock.[ch]: Default to not showing the image menu, set a minimal width here, misc. minor cleanup. * app/widgets/gimpdockbook.c: some more GIMP_IS_IMAGE_DOCK() checks, fixed dnd widget creation. * app/widgets/gimpdialogfactory.[ch]: changed gimp_dialog_factories_toggle() to take just the toolbox_factory as parameter. When restoring the session use the created dock's dialog factory to create dockables, not the the factory we created the dock from (for the toolbox). * app/display/gimpdisplayshell-callbacks.c: changed accordingly. * app/gui/dialogs.[ch]: create an own dialog factory for the toolbox and set dialogs_toolbox_new() as it's new_dock_func. * app/gui/dialogs-constructors.[ch]: changed dialogs_toolbox_get() accordingly. * app/gui/dialogs-commands.[ch]: added dialogs_show_toolbox(), ckeck if a dock is really a GimpImageDock before casting. * app/gui/gui.c * app/gui/menus.c * app/widgets/gimppaletteeditor.c: changed accordingly. * app/gui/color-notebook.c * app/gui/color-select.c * app/gui/colormap-dialog.c * app/gui/palette-editor-commands.c: removed useless inclusion of "gui/color-area.h". * themes/Default/gtkrc: set "gimp-dock-style" for GimpToolbox widgets.
2002-03-15 01:07:02 +08:00
#include "core/gimpcontext.h"
#include "core/gimpmarshal.h"
g_strdup() the stock_id passed to gimp_tool_info_new() because the 2002-03-14 Michael Natterer <mitch@gimp.org> * app/core/gimptoolinfo.c: g_strdup() the stock_id passed to gimp_tool_info_new() because the caller's memory may disappear after registering the tool (tool modules). Made a GimpDock out of the toolbox: * app/gui/Makefile.am * app/gui/color-area.[ch] * app/gui/indicator-area.[ch] * app/gui/toolbox.[ch]: removed... * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimptoolbox-color-area.[ch] * app/widgets/gimptoolbox-indicator-area.[ch] * app/widgets/gimptoolbox.[ch]: ...and added here. * app/widgets/gimpdock.[ch]: don't set a minimal width. Added a "destroy_if_empty" boolean so we can prevent destruction of the toolbox if it's last dockable is removed. Added gimp_dock_construct() which is called from GimpImageDock and GimpToolbox. * app/widgets/gimpimagedock.[ch]: Default to not showing the image menu, set a minimal width here, misc. minor cleanup. * app/widgets/gimpdockbook.c: some more GIMP_IS_IMAGE_DOCK() checks, fixed dnd widget creation. * app/widgets/gimpdialogfactory.[ch]: changed gimp_dialog_factories_toggle() to take just the toolbox_factory as parameter. When restoring the session use the created dock's dialog factory to create dockables, not the the factory we created the dock from (for the toolbox). * app/display/gimpdisplayshell-callbacks.c: changed accordingly. * app/gui/dialogs.[ch]: create an own dialog factory for the toolbox and set dialogs_toolbox_new() as it's new_dock_func. * app/gui/dialogs-constructors.[ch]: changed dialogs_toolbox_get() accordingly. * app/gui/dialogs-commands.[ch]: added dialogs_show_toolbox(), ckeck if a dock is really a GimpImageDock before casting. * app/gui/gui.c * app/gui/menus.c * app/widgets/gimppaletteeditor.c: changed accordingly. * app/gui/color-notebook.c * app/gui/color-select.c * app/gui/colormap-dialog.c * app/gui/palette-editor-commands.c: removed useless inclusion of "gui/color-area.h". * themes/Default/gtkrc: set "gimp-dock-style" for GimpToolbox widgets.
2002-03-15 01:07:02 +08:00
#include "gimpdialogfactory.h"
#include "gimpdock.h"
#include "gimpdockable.h"
#include "gimpdockbook.h"
#include "gimppanedbox.h"
#include "gimpuimanager.h"
#include "gimpwidgets-utils.h"
#include "gimp-intl.h"
#define DEFAULT_DOCK_FONT_SCALE PANGO_SCALE_SMALL
enum
{
PROP_0,
PROP_CONTEXT,
PROP_DIALOG_FACTORY,
PROP_UI_MANAGER
};
enum
{
BOOK_ADDED,
BOOK_REMOVED,
TITLE_INVALIDATED,
GEOMETRY_INVALIDATED,
LAST_SIGNAL
};
struct _GimpDockPrivate
{
GimpDialogFactory *dialog_factory;
GimpContext *context;
GimpUIManager *ui_manager;
GtkWidget *main_vbox;
GtkWidget *paned_vbox;
GList *dockbooks;
gint ID;
};
static void gimp_dock_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_dock_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_dock_style_set (GtkWidget *widget,
GtkStyle *prev_style);
static void gimp_dock_destroy (GtkObject *object);
static void gimp_dock_real_book_added (GimpDock *dock,
GimpDockbook *dockbook);
static void gimp_dock_real_book_removed (GimpDock *dock,
GimpDockbook *dockbook);
app: Use a GdkWindow instead of GimpDockSeparators for dockable DND Make drag-and-drop rearrangement of dockables happen directly in the existing widget hierarchy so we don't have to use special, ugly widgets (read GimpDockSeparator:s) for that. More specifically, make edges of dockables and dockbooks have the same semantics as the GimpDockSeparators had. We put a highlight colored GdkWindow on top of the widget in question to highlight these special drop areas. This GdkWindow is not taken into consideration in the GTK+ drag-and-drop code, so it does not interupt the DND interaction. To achive this, there is a problem we must solve: Drag events in GTK+ are propagated inwards and out, but we sometimes want ancenstor widgets to take care of drop events. We solve this by introducing the concept of "drag handlers". A drag handler is asked if it will handle a given drag event, and if it will, a client will let the drag event be propagated upwards in the widget hierarchy. Right now, the GimpPanedBox is the only "drag handler". The code could be generalized more but it doesn't feel worth it at this point. The size of the special drop area is 5px, the same size as the default GtkPaned handles. This is because the plan is to later use these handles as drop areas too. Other changes of interest are: * We need to take care of "drag-motion", "drag-drop" and widget highlightning ourselves. We can not use the GtkDestDefaults conveniences with gtk_drag_dest_set() any longer since we need more control. * Make the drop callback pass the insert index directly instead of a GimpDockSeparator * Add some GIMP_LOG() debug output for DND * Disable the GimpDockSeparator code in GimpToolbox
2009-11-30 01:22:12 +08:00
static gboolean gimp_dock_dropped_cb (GtkWidget *source,
gint insert_index,
gpointer data);
G_DEFINE_TYPE (GimpDock, gimp_dock, GTK_TYPE_VBOX)
#define parent_class gimp_dock_parent_class
static guint dock_signals[LAST_SIGNAL] = { 0 };
static void
gimp_dock_class_init (GimpDockClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
dock_signals[BOOK_ADDED] =
g_signal_new ("book-added",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpDockClass, book_added),
NULL, NULL,
gimp_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
GIMP_TYPE_DOCKBOOK);
dock_signals[BOOK_REMOVED] =
g_signal_new ("book-removed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpDockClass, book_removed),
NULL, NULL,
gimp_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
GIMP_TYPE_DOCKBOOK);
dock_signals[TITLE_INVALIDATED] =
g_signal_new ("title-invalidated",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpDockClass, title_invalidated),
NULL, NULL,
gimp_marshal_VOID__VOID,
G_TYPE_NONE, 0);
dock_signals[GEOMETRY_INVALIDATED] =
g_signal_new ("geometry-invalidated",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpDockClass, geometry_invalidated),
NULL, NULL,
gimp_marshal_VOID__VOID,
G_TYPE_NONE, 0);
object_class->set_property = gimp_dock_set_property;
object_class->get_property = gimp_dock_get_property;
gtk_object_class->destroy = gimp_dock_destroy;
widget_class->style_set = gimp_dock_style_set;
klass->setup = NULL;
klass->set_host_geometry_hints = NULL;
klass->book_added = gimp_dock_real_book_added;
klass->book_removed = gimp_dock_real_book_removed;
klass->title_invalidated = NULL;
klass->geometry_invalidated = NULL;
g_object_class_install_property (object_class, PROP_CONTEXT,
g_param_spec_object ("context", NULL, NULL,
GIMP_TYPE_CONTEXT,
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class, PROP_DIALOG_FACTORY,
g_param_spec_object ("dialog-factory",
NULL, NULL,
GIMP_TYPE_DIALOG_FACTORY,
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class, PROP_UI_MANAGER,
g_param_spec_object ("ui-manager",
NULL, NULL,
GIMP_TYPE_UI_MANAGER,
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
gtk_widget_class_install_style_property (widget_class,
g_param_spec_double ("font-scale",
NULL, NULL,
0.0,
G_MAXDOUBLE,
DEFAULT_DOCK_FONT_SCALE,
GIMP_PARAM_READABLE));
g_type_class_add_private (klass, sizeof (GimpDockPrivate));
}
static void
gimp_dock_init (GimpDock *dock)
{
static gint dock_ID = 1;
gchar *name = NULL;
dock->p = G_TYPE_INSTANCE_GET_PRIVATE (dock,
GIMP_TYPE_DOCK,
GimpDockPrivate);
dock->p->context = NULL;
dock->p->dialog_factory = NULL;
dock->p->ID = dock_ID++;
name = g_strdup_printf ("gimp-internal-dock-%d", dock->p->ID);
gtk_widget_set_name (GTK_WIDGET (dock), name);
g_free (name);
dock->p->main_vbox = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (dock), dock->p->main_vbox);
gtk_widget_show (dock->p->main_vbox);
cleanup. 2001-04-22 Michael Natterer <mitch@gimp.org> * app/Makefile.am: cleanup. * app/interface.c: #include "gimpui.h" * app/gui/dialogs-constructors.[ch] * app/gui/dialogs.c * app/gui/menus.c * app/gui/test-commands.[ch]: changes for the image menu below. * app/apptypes.h * app/widgets/Makefile.am * app/widgets/gimpcontainermenu.[ch] * app/widgets/gimpcontainermenuimpl.[ch]: new widgets. The actual implemtation lives in a separate file because gimpcontainermenu.c's code is identical to gimpcontainerview.c's except for the base class. This will become an interface with Gtk 2.0. * app/widgets/gimpimagedock.[ch]: a dock with an image menu. The pages still don't follow the context correctly. * app/widgets/gimpmenuitem.[ch]: a menu item with a preview. * app/widgets/gimpdialogfactory.[ch]: pass a dock constructor to the constructor and provide a method to create a new dock within this factory's context. * app/widgets/gimpdock.[ch]: removed the constructor because we create only image docks now. Put the vbox into a main_vbox (which also contains the image menu). * app/widgets/gimpdockbook.[ch]: create new docks with the dialog factory. * app/gimpcontainer.[ch] * app/gimpdata.[ch] * app/gimpdatafactory.[ch] * app/gimpdatalist.[ch] * app/gimplist.[ch] * app/gimpviewable.[ch] * app/widgets/gimpbrushpreview.[ch] * app/widgets/gimpcontainergridview.[ch] * app/widgets/gimpcontainerlistview.[ch] * app/widgets/gimpcontainerview.[ch] * app/widgets/gimpdatafactoryview.[ch] * app/widgets/gimpdockable.[ch] * app/widgets/gimpdrawablelistitem.[ch] * app/widgets/gimpdrawablelistview.[ch] * app/widgets/gimpdrawablepreview.[ch] * app/widgets/gimplayerlistitem.[ch] * app/widgets/gimplayerlistview.[ch] * app/widgets/gimplistitem.[ch] * app/widgets/gimppalettepreview.[ch] * app/widgets/gimppatternpreview.[ch] * app/widgets/gimppreview.[ch]: ass-sign some copyrights.
2001-04-22 08:38:56 +08:00
dock->p->paned_vbox = gimp_paned_box_new (FALSE, 0, GTK_ORIENTATION_VERTICAL);
gimp_paned_box_set_dropped_cb (GIMP_PANED_BOX (dock->p->paned_vbox),
gimp_dock_dropped_cb,
dock);
gtk_container_add (GTK_CONTAINER (dock->p->main_vbox), dock->p->paned_vbox);
gtk_widget_show (dock->p->paned_vbox);
}
static void
gimp_dock_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GimpDock *dock = GIMP_DOCK (object);
switch (property_id)
{
case PROP_CONTEXT:
dock->p->context = g_value_dup_object (value);
break;
case PROP_DIALOG_FACTORY:
dock->p->dialog_factory = g_value_get_object (value);
break;
case PROP_UI_MANAGER:
dock->p->ui_manager = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_dock_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpDock *dock = GIMP_DOCK (object);
switch (property_id)
{
case PROP_CONTEXT:
g_value_set_object (value, dock->p->context);
break;
case PROP_DIALOG_FACTORY:
g_value_set_object (value, dock->p->dialog_factory);
break;
case PROP_UI_MANAGER:
g_value_set_object (value, dock->p->ui_manager);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_dock_style_set (GtkWidget *widget,
GtkStyle *prev_style)
{
GimpDock *dock = GIMP_DOCK (widget);
gdouble font_scale = 1.0;
GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style);
gtk_widget_style_get (widget,
"font-scale", &font_scale,
NULL);
if (font_scale != 1.0)
{
PangoContext *context;
PangoFontDescription *font_desc;
gint font_size;
gchar *font_str;
gchar *rc_string;
context = gtk_widget_get_pango_context (widget);
font_desc = pango_context_get_font_description (context);
font_desc = pango_font_description_copy (font_desc);
font_size = pango_font_description_get_size (font_desc);
font_size = font_scale * font_size;
pango_font_description_set_size (font_desc, font_size);
font_str = pango_font_description_to_string (font_desc);
pango_font_description_free (font_desc);
rc_string =
g_strdup_printf ("style \"gimp-dock-style\""
"{"
" font_name = \"%s\""
"}"
"widget \"*.gimp-internal-dock-%d.*\" style \"gimp-dock-style\"",
font_str,
dock->p->ID);
g_free (font_str);
gtk_rc_parse_string (rc_string);
g_free (rc_string);
gtk_widget_reset_rc_styles (widget);
}
}
static void
gimp_dock_destroy (GtkObject *object)
{
GimpDock *dock = GIMP_DOCK (object);
while (dock->p->dockbooks)
gimp_dock_remove_book (dock, GIMP_DOCKBOOK (dock->p->dockbooks->data));
if (dock->p->ui_manager)
{
g_object_unref (dock->p->ui_manager);
dock->p->ui_manager = NULL;
}
if (dock->p->context)
Port to glib/gtk+ 2.0 episode I (every segfault has it's beginning) 2001-07-24 Michael Natterer <mitch@gimp.org> Port to glib/gtk+ 2.0 episode I (every segfault has it's beginning) * configure.in: require glib/gtk+ >= 1.3.7, commented out the gtkxmhtml stuff. From now on, you will need glib, pango, atk and gtk+ HEAD from CVS to hack or use GIMP HEAD. Beware, it crashes randomly :) * app/core/Makefile.am * app/core/gimpmarshal.list: new file plus rules to generate gimpmarshal.[ch] from it. * app/core/* * app/tools/* * app/widgets/* * libgimpwidgets/*: started to use the glib object system. All core/ objects are still gtk objects however. All signals are created using g_signal_new(). There are many gtk+ artefacts left. Finally, we will _not_ use the gtk_signal_foo() wrappers and friends any more. * app/colormaps.c * app/devices.[ch] * app/disp_callbacks.c * app/errorconsole.c * app/file-save.[ch] * app/interface.c * app/module_db.c * app/nav_window.c * app/ops_buttons.c * app/scroll.c * app/user_install.c * app/gui/about-dialog.c * app/gui/brush-editor.c * app/gui/brushes-commands.c * app/gui/color-notebook.c * app/gui/colormap-dialog.c * app/gui/dialogs-commands.c * app/gui/dialogs-constructors.c * app/gui/file-commands.c * app/gui/file-dialog-utils.c * app/gui/file-new-dialog.c * app/gui/file-open-dialog.[ch] * app/gui/file-save-dialog.c * app/gui/gradient-editor.c * app/gui/gradients-commands.c * app/gui/image-commands.c * app/gui/info-dialog.[ch] * app/gui/layer-select.c * app/gui/layers-commands.c * app/gui/menus.c * app/gui/offset-dialog.c * app/gui/palette-editor.c * app/gui/palettes-commands.c * app/gui/patterns-commands.c * app/gui/preferences-dialog.c * app/gui/resize-dialog.[ch] * app/gui/splash.c * app/gui/tips-dialog.c * app/gui/tool-options-dialog.c * app/gui/toolbox.c * app/gui/tools-commands.c * libgimp/gimpbrushmenu.c * libgimp/gimpmenu.c * libgimp/gimppatternmenu.c * libgimp/gimpui.c * libgimpbase/gimpenv.c: tons and tons of changes like "const gchar*", switch from GdkDeviceInfo to GdkDevice (very incomplete and currently disables), lots of s/gtk_signal/g_signal/, removal/replacement of deprecated stuff, s/GtkSignalFunc/GCallback/ and lots of small changes and fixes while I was on it, zillions of warnings left... * modules/Makefile.am: disabled the water color selector temporarily (XInput issues). * plug-ins/Makefile.am * plug-ins/common/.cvsignore * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl: simply excluded all plug-ins which did not build (including Script-Fu). They are trivial to fix.
2001-07-25 05:27:11 +08:00
{
g_object_unref (dock->p->context);
dock->p->context = NULL;
Port to glib/gtk+ 2.0 episode I (every segfault has it's beginning) 2001-07-24 Michael Natterer <mitch@gimp.org> Port to glib/gtk+ 2.0 episode I (every segfault has it's beginning) * configure.in: require glib/gtk+ >= 1.3.7, commented out the gtkxmhtml stuff. From now on, you will need glib, pango, atk and gtk+ HEAD from CVS to hack or use GIMP HEAD. Beware, it crashes randomly :) * app/core/Makefile.am * app/core/gimpmarshal.list: new file plus rules to generate gimpmarshal.[ch] from it. * app/core/* * app/tools/* * app/widgets/* * libgimpwidgets/*: started to use the glib object system. All core/ objects are still gtk objects however. All signals are created using g_signal_new(). There are many gtk+ artefacts left. Finally, we will _not_ use the gtk_signal_foo() wrappers and friends any more. * app/colormaps.c * app/devices.[ch] * app/disp_callbacks.c * app/errorconsole.c * app/file-save.[ch] * app/interface.c * app/module_db.c * app/nav_window.c * app/ops_buttons.c * app/scroll.c * app/user_install.c * app/gui/about-dialog.c * app/gui/brush-editor.c * app/gui/brushes-commands.c * app/gui/color-notebook.c * app/gui/colormap-dialog.c * app/gui/dialogs-commands.c * app/gui/dialogs-constructors.c * app/gui/file-commands.c * app/gui/file-dialog-utils.c * app/gui/file-new-dialog.c * app/gui/file-open-dialog.[ch] * app/gui/file-save-dialog.c * app/gui/gradient-editor.c * app/gui/gradients-commands.c * app/gui/image-commands.c * app/gui/info-dialog.[ch] * app/gui/layer-select.c * app/gui/layers-commands.c * app/gui/menus.c * app/gui/offset-dialog.c * app/gui/palette-editor.c * app/gui/palettes-commands.c * app/gui/patterns-commands.c * app/gui/preferences-dialog.c * app/gui/resize-dialog.[ch] * app/gui/splash.c * app/gui/tips-dialog.c * app/gui/tool-options-dialog.c * app/gui/toolbox.c * app/gui/tools-commands.c * libgimp/gimpbrushmenu.c * libgimp/gimpmenu.c * libgimp/gimppatternmenu.c * libgimp/gimpui.c * libgimpbase/gimpenv.c: tons and tons of changes like "const gchar*", switch from GdkDeviceInfo to GdkDevice (very incomplete and currently disables), lots of s/gtk_signal/g_signal/, removal/replacement of deprecated stuff, s/GtkSignalFunc/GCallback/ and lots of small changes and fixes while I was on it, zillions of warnings left... * modules/Makefile.am: disabled the water color selector temporarily (XInput issues). * plug-ins/Makefile.am * plug-ins/common/.cvsignore * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl: simply excluded all plug-ins which did not build (including Script-Fu). They are trivial to fix.
2001-07-25 05:27:11 +08:00
}
GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
static void
gimp_dock_real_book_added (GimpDock *dock,
GimpDockbook *dockbook)
{
}
static void
gimp_dock_real_book_removed (GimpDock *dock,
GimpDockbook *dockbook)
{
}
static gboolean
app: Use a GdkWindow instead of GimpDockSeparators for dockable DND Make drag-and-drop rearrangement of dockables happen directly in the existing widget hierarchy so we don't have to use special, ugly widgets (read GimpDockSeparator:s) for that. More specifically, make edges of dockables and dockbooks have the same semantics as the GimpDockSeparators had. We put a highlight colored GdkWindow on top of the widget in question to highlight these special drop areas. This GdkWindow is not taken into consideration in the GTK+ drag-and-drop code, so it does not interupt the DND interaction. To achive this, there is a problem we must solve: Drag events in GTK+ are propagated inwards and out, but we sometimes want ancenstor widgets to take care of drop events. We solve this by introducing the concept of "drag handlers". A drag handler is asked if it will handle a given drag event, and if it will, a client will let the drag event be propagated upwards in the widget hierarchy. Right now, the GimpPanedBox is the only "drag handler". The code could be generalized more but it doesn't feel worth it at this point. The size of the special drop area is 5px, the same size as the default GtkPaned handles. This is because the plan is to later use these handles as drop areas too. Other changes of interest are: * We need to take care of "drag-motion", "drag-drop" and widget highlightning ourselves. We can not use the GtkDestDefaults conveniences with gtk_drag_dest_set() any longer since we need more control. * Make the drop callback pass the insert index directly instead of a GimpDockSeparator * Add some GIMP_LOG() debug output for DND * Disable the GimpDockSeparator code in GimpToolbox
2009-11-30 01:22:12 +08:00
gimp_dock_dropped_cb (GtkWidget *source,
gint insert_index,
gpointer data)
{
GimpDock *dock = GIMP_DOCK (data);
GimpDockable *dockable = gimp_dockbook_drag_source_to_dockable (source);
GtkWidget *dockbook = NULL;
if (!dockable )
return FALSE;
/* if dropping to the same dock, take care that we don't try
* to reorder the *only* dockable in the dock
*/
if (gimp_dockbook_get_dock (dockable->dockbook) == dock)
{
GList *children;
gint n_books;
gint n_dockables;
n_books = g_list_length (gimp_dock_get_dockbooks (dock));
children = gtk_container_get_children (GTK_CONTAINER (dockable->dockbook));
n_dockables = g_list_length (children);
g_list_free (children);
if (n_books == 1 && n_dockables == 1)
return TRUE; /* successfully do nothing */
}
/* Detach the dockable from the old dockbook */
g_object_ref (dockable);
gimp_dockbook_remove (dockable->dockbook, dockable);
/* Create a new dockbook */
dockbook = gimp_dockbook_new (gimp_dock_get_dialog_factory (dock)->menu_factory);
app: Use a GdkWindow instead of GimpDockSeparators for dockable DND Make drag-and-drop rearrangement of dockables happen directly in the existing widget hierarchy so we don't have to use special, ugly widgets (read GimpDockSeparator:s) for that. More specifically, make edges of dockables and dockbooks have the same semantics as the GimpDockSeparators had. We put a highlight colored GdkWindow on top of the widget in question to highlight these special drop areas. This GdkWindow is not taken into consideration in the GTK+ drag-and-drop code, so it does not interupt the DND interaction. To achive this, there is a problem we must solve: Drag events in GTK+ are propagated inwards and out, but we sometimes want ancenstor widgets to take care of drop events. We solve this by introducing the concept of "drag handlers". A drag handler is asked if it will handle a given drag event, and if it will, a client will let the drag event be propagated upwards in the widget hierarchy. Right now, the GimpPanedBox is the only "drag handler". The code could be generalized more but it doesn't feel worth it at this point. The size of the special drop area is 5px, the same size as the default GtkPaned handles. This is because the plan is to later use these handles as drop areas too. Other changes of interest are: * We need to take care of "drag-motion", "drag-drop" and widget highlightning ourselves. We can not use the GtkDestDefaults conveniences with gtk_drag_dest_set() any longer since we need more control. * Make the drop callback pass the insert index directly instead of a GimpDockSeparator * Add some GIMP_LOG() debug output for DND * Disable the GimpDockSeparator code in GimpToolbox
2009-11-30 01:22:12 +08:00
gimp_dock_add_book (dock, GIMP_DOCKBOOK (dockbook), insert_index);
/* Add the dockable to new new dockbook */
gimp_dockbook_add (GIMP_DOCKBOOK (dockbook), dockable, -1);
g_object_unref (dockable);
return TRUE;
}
/* public functions */
void
gimp_dock_setup (GimpDock *dock,
const GimpDock *template)
{
g_return_if_fail (GIMP_IS_DOCK (dock));
g_return_if_fail (GIMP_IS_DOCK (template));
if (GIMP_DOCK_GET_CLASS (dock)->setup)
GIMP_DOCK_GET_CLASS (dock)->setup (dock, template);
}
void
gimp_dock_set_aux_info (GimpDock *dock,
GList *aux_info)
{
g_return_if_fail (GIMP_IS_DOCK (dock));
if (GIMP_DOCK_GET_CLASS (dock)->set_aux_info)
GIMP_DOCK_GET_CLASS (dock)->set_aux_info (dock, aux_info);
}
GList *
gimp_dock_get_aux_info (GimpDock *dock)
{
g_return_val_if_fail (GIMP_IS_DOCK (dock), NULL);
if (GIMP_DOCK_GET_CLASS (dock)->get_aux_info)
return GIMP_DOCK_GET_CLASS (dock)->get_aux_info (dock);
return NULL;
}
gchar *
gimp_dock_get_title (GimpDock *dock)
{
g_return_val_if_fail (GIMP_IS_DOCK (dock), NULL);
if (GIMP_DOCK_GET_CLASS (dock)->get_title)
return GIMP_DOCK_GET_CLASS (dock)->get_title (dock);
return NULL;
}
void
gimp_dock_invalidate_title (GimpDock *dock)
{
g_return_if_fail (GIMP_IS_DOCK (dock));
g_signal_emit (dock, dock_signals[TITLE_INVALIDATED], 0);
}
/**
* gimp_dock_set_host_geometry_hints:
* @dock: The dock
* @window: The #GtkWindow to adapt to hosting the dock
*
* Some docks have some specific needs on the #GtkWindow they are
* in. This function allows such docks to perform any such setup on
* the #GtkWindow they are in/will be put in.
**/
void
gimp_dock_set_host_geometry_hints (GimpDock *dock,
GtkWindow *window)
{
g_return_if_fail (GIMP_IS_DOCK (dock));
g_return_if_fail (GTK_IS_WINDOW (window));
if (GIMP_DOCK_GET_CLASS (dock)->set_host_geometry_hints)
GIMP_DOCK_GET_CLASS (dock)->set_host_geometry_hints (dock, window);
}
/**
* gimp_dock_invalidate_geometry:
* @dock:
*
* Call when the dock needs to setup its host #GtkWindow with
* GtkDock::set_host_geometry_hints().
**/
void
gimp_dock_invalidate_geometry (GimpDock *dock)
{
g_return_if_fail (GIMP_IS_DOCK (dock));
g_signal_emit (dock, dock_signals[GEOMETRY_INVALIDATED], 0);
}
GimpContext *
gimp_dock_get_context (GimpDock *dock)
{
g_return_val_if_fail (GIMP_IS_DOCK (dock), NULL);
return dock->p->context;
}
GimpDialogFactory *
gimp_dock_get_dialog_factory (GimpDock *dock)
{
g_return_val_if_fail (GIMP_IS_DOCK (dock), NULL);
return dock->p->dialog_factory;
}
GimpUIManager *
gimp_dock_get_ui_manager (GimpDock *dock)
{
g_return_val_if_fail (GIMP_IS_DOCK (dock), NULL);
return dock->p->ui_manager;
}
GList *
gimp_dock_get_dockbooks (GimpDock *dock)
{
g_return_val_if_fail (GIMP_IS_DOCK (dock), NULL);
return dock->p->dockbooks;
}
gint
gimp_dock_get_n_dockables (GimpDock *dock)
{
GList *list = NULL;
gint n = 0;
g_return_val_if_fail (GIMP_IS_DOCK (dock), 0);
for (list = dock->p->dockbooks; list; list = list->next)
n += gtk_notebook_get_n_pages (GTK_NOTEBOOK (list->data));
return n;
}
GtkWidget *
gimp_dock_get_main_vbox (GimpDock *dock)
{
g_return_val_if_fail (GIMP_IS_DOCK (dock), NULL);
return dock->p->main_vbox;
}
GtkWidget *
gimp_dock_get_vbox (GimpDock *dock)
{
g_return_val_if_fail (GIMP_IS_DOCK (dock), NULL);
return dock->p->paned_vbox;
}
void
gimp_dock_add (GimpDock *dock,
GimpDockable *dockable,
gint section,
gint position)
{
GimpDockbook *dockbook;
g_return_if_fail (GIMP_IS_DOCK (dock));
g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
g_return_if_fail (dockable->dockbook == NULL);
dockbook = GIMP_DOCKBOOK (dock->p->dockbooks->data);
gimp_dockbook_add (dockbook, dockable, position);
}
void
gimp_dock_remove (GimpDock *dock,
GimpDockable *dockable)
{
g_return_if_fail (GIMP_IS_DOCK (dock));
g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
g_return_if_fail (dockable->dockbook != NULL);
g_return_if_fail (gimp_dockbook_get_dock (dockable->dockbook) == dock);
gimp_dockbook_remove (dockable->dockbook, dockable);
}
void
gimp_dock_add_book (GimpDock *dock,
GimpDockbook *dockbook,
gint index)
{
g_return_if_fail (GIMP_IS_DOCK (dock));
g_return_if_fail (GIMP_IS_DOCKBOOK (dockbook));
g_return_if_fail (gimp_dockbook_get_dock (dockbook) == NULL);
gimp_dockbook_set_dock (dockbook, dock);
dock->p->dockbooks = g_list_insert (dock->p->dockbooks, dockbook, index);
gimp_paned_box_add_widget (GIMP_PANED_BOX (dock->p->paned_vbox),
GTK_WIDGET (dockbook),
index);
gtk_widget_show (GTK_WIDGET (dockbook));
g_signal_emit (dock, dock_signals[BOOK_ADDED], 0, dockbook);
}
void
gimp_dock_remove_book (GimpDock *dock,
GimpDockbook *dockbook)
{
g_return_if_fail (GIMP_IS_DOCK (dock));
g_return_if_fail (GIMP_IS_DOCKBOOK (dockbook));
g_return_if_fail (gimp_dockbook_get_dock (dockbook) == dock);
gimp_dockbook_set_dock (dockbook, NULL);
/* Ref the dockbook so we can emit the "book-removed" signal and
* pass it as a parameter before it's destroyed
*/
g_object_ref (dockbook);
dock->p->dockbooks = g_list_remove (dock->p->dockbooks, dockbook);
gimp_paned_box_remove_widget (GIMP_PANED_BOX (dock->p->paned_vbox),
GTK_WIDGET (dockbook));
g_signal_emit (dock, dock_signals[BOOK_REMOVED], 0, dockbook);
g_object_unref (dockbook);
}