2009-09-26 22:48:39 +08:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
|
|
|
* gimpdockcolumns.c
|
|
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2012-03-30 01:19:01 +08:00
|
|
|
#include <gegl.h>
|
2009-09-26 22:48:39 +08:00
|
|
|
#include <gtk/gtk.h>
|
|
|
|
|
|
|
|
#include "widgets-types.h"
|
|
|
|
|
2009-10-26 06:34:43 +08:00
|
|
|
#include "core/gimp.h"
|
|
|
|
#include "core/gimpcontext.h"
|
2009-11-14 01:24:20 +08:00
|
|
|
#include "core/gimpmarshal.h"
|
2009-10-26 06:34:43 +08:00
|
|
|
|
|
|
|
#include "gimpdialogfactory.h"
|
2009-10-04 08:05:22 +08:00
|
|
|
#include "gimpdock.h"
|
2009-10-26 06:34:43 +08:00
|
|
|
#include "gimpdockable.h"
|
|
|
|
#include "gimpdockbook.h"
|
2009-09-26 22:48:39 +08:00
|
|
|
#include "gimpdockcolumns.h"
|
2009-10-26 06:34:43 +08:00
|
|
|
#include "gimpmenudock.h"
|
2009-10-25 02:08:58 +08:00
|
|
|
#include "gimppanedbox.h"
|
2010-01-06 22:10:32 +08:00
|
|
|
#include "gimptoolbox.h"
|
2010-01-08 02:18:03 +08:00
|
|
|
#include "gimpuimanager.h"
|
2009-09-26 22:48:39 +08:00
|
|
|
|
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
|
|
|
#include "gimp-log.h"
|
2009-09-26 22:48:39 +08:00
|
|
|
|
2010-01-08 02:13:13 +08:00
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_0,
|
2010-01-08 02:18:03 +08:00
|
|
|
PROP_CONTEXT,
|
|
|
|
PROP_DIALOG_FACTORY,
|
|
|
|
PROP_UI_MANAGER
|
2010-01-08 02:13:13 +08:00
|
|
|
};
|
|
|
|
|
2009-11-14 01:24:20 +08:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
DOCK_ADDED,
|
|
|
|
DOCK_REMOVED,
|
|
|
|
LAST_SIGNAL
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2009-09-26 22:48:39 +08:00
|
|
|
struct _GimpDockColumnsPrivate
|
|
|
|
{
|
2010-01-08 02:18:03 +08:00
|
|
|
GimpContext *context;
|
|
|
|
GimpDialogFactory *dialog_factory;
|
|
|
|
GimpUIManager *ui_manager;
|
2009-10-25 02:08:58 +08:00
|
|
|
|
2010-01-08 02:18:03 +08:00
|
|
|
GList *docks;
|
2010-01-05 18:08:10 +08:00
|
|
|
|
2010-01-08 02:18:03 +08:00
|
|
|
GtkWidget *paned_hbox;
|
2009-09-26 22:48:39 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2010-06-27 05:27:17 +08:00
|
|
|
static void gimp_dock_columns_dispose (GObject *object);
|
2010-01-08 02:13:13 +08:00
|
|
|
static void gimp_dock_columns_set_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec);
|
|
|
|
static void gimp_dock_columns_get_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec);
|
|
|
|
static gboolean gimp_dock_columns_dropped_cb (GtkWidget *source,
|
|
|
|
gint insert_index,
|
|
|
|
gpointer data);
|
|
|
|
static void gimp_dock_columns_real_dock_added (GimpDockColumns *dock_columns,
|
|
|
|
GimpDock *dock);
|
|
|
|
static void gimp_dock_columns_real_dock_removed (GimpDockColumns *dock_columns,
|
|
|
|
GimpDock *dock);
|
|
|
|
static void gimp_dock_columns_dock_book_removed (GimpDockColumns *dock_columns,
|
|
|
|
GimpDockbook *dockbook,
|
|
|
|
GimpDock *dock);
|
2009-10-25 02:08:58 +08:00
|
|
|
|
|
|
|
|
2010-10-30 21:44:46 +08:00
|
|
|
G_DEFINE_TYPE (GimpDockColumns, gimp_dock_columns, GTK_TYPE_BOX)
|
2009-09-26 22:48:39 +08:00
|
|
|
|
|
|
|
#define parent_class gimp_dock_columns_parent_class
|
|
|
|
|
2009-11-14 01:24:20 +08:00
|
|
|
static guint dock_columns_signals[LAST_SIGNAL] = { 0 };
|
|
|
|
|
2009-09-26 22:48:39 +08:00
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_dock_columns_class_init (GimpDockColumnsClass *klass)
|
|
|
|
{
|
2010-01-08 02:13:13 +08:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
2010-06-27 05:27:17 +08:00
|
|
|
object_class->dispose = gimp_dock_columns_dispose;
|
2010-01-08 02:13:13 +08:00
|
|
|
object_class->set_property = gimp_dock_columns_set_property;
|
|
|
|
object_class->get_property = gimp_dock_columns_get_property;
|
|
|
|
|
2009-11-14 01:24:20 +08:00
|
|
|
klass->dock_added = gimp_dock_columns_real_dock_added;
|
|
|
|
klass->dock_removed = gimp_dock_columns_real_dock_removed;
|
|
|
|
|
2010-01-08 02:13:13 +08:00
|
|
|
g_object_class_install_property (object_class, PROP_CONTEXT,
|
|
|
|
g_param_spec_object ("context",
|
|
|
|
NULL, NULL,
|
|
|
|
GIMP_TYPE_CONTEXT,
|
|
|
|
GIMP_PARAM_WRITABLE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY));
|
2016-11-24 02:16:36 +08:00
|
|
|
|
2010-01-08 02:18:03 +08:00
|
|
|
g_object_class_install_property (object_class, PROP_DIALOG_FACTORY,
|
|
|
|
g_param_spec_object ("dialog-factory",
|
|
|
|
NULL, NULL,
|
|
|
|
GIMP_TYPE_DIALOG_FACTORY,
|
|
|
|
GIMP_PARAM_WRITABLE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY));
|
2016-11-24 02:16:36 +08:00
|
|
|
|
2010-01-08 02:18:03 +08:00
|
|
|
g_object_class_install_property (object_class, PROP_UI_MANAGER,
|
|
|
|
g_param_spec_object ("ui-manager",
|
|
|
|
NULL, NULL,
|
|
|
|
GIMP_TYPE_UI_MANAGER,
|
|
|
|
GIMP_PARAM_WRITABLE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY));
|
2010-01-08 02:13:13 +08:00
|
|
|
|
2009-11-14 01:24:20 +08:00
|
|
|
dock_columns_signals[DOCK_ADDED] =
|
|
|
|
g_signal_new ("dock-added",
|
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
G_STRUCT_OFFSET (GimpDockColumnsClass, dock_added),
|
|
|
|
NULL, NULL,
|
|
|
|
gimp_marshal_VOID__OBJECT,
|
|
|
|
G_TYPE_NONE, 1,
|
|
|
|
GIMP_TYPE_DOCK);
|
|
|
|
|
|
|
|
dock_columns_signals[DOCK_REMOVED] =
|
|
|
|
g_signal_new ("dock-removed",
|
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
G_STRUCT_OFFSET (GimpDockColumnsClass, dock_removed),
|
|
|
|
NULL, NULL,
|
|
|
|
gimp_marshal_VOID__OBJECT,
|
|
|
|
G_TYPE_NONE, 1,
|
|
|
|
GIMP_TYPE_DOCK);
|
|
|
|
|
2009-09-26 22:48:39 +08:00
|
|
|
g_type_class_add_private (klass, sizeof (GimpDockColumnsPrivate));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_dock_columns_init (GimpDockColumns *dock_columns)
|
|
|
|
{
|
2010-10-30 21:44:46 +08:00
|
|
|
gtk_orientable_set_orientation (GTK_ORIENTABLE (dock_columns),
|
|
|
|
GTK_ORIENTATION_HORIZONTAL);
|
|
|
|
|
2009-09-26 22:48:39 +08:00
|
|
|
dock_columns->p = G_TYPE_INSTANCE_GET_PRIVATE (dock_columns,
|
2009-10-25 02:08:58 +08:00
|
|
|
GIMP_TYPE_DOCK_COLUMNS,
|
|
|
|
GimpDockColumnsPrivate);
|
|
|
|
|
|
|
|
dock_columns->p->paned_hbox = gimp_paned_box_new (FALSE, 0,
|
|
|
|
GTK_ORIENTATION_HORIZONTAL);
|
|
|
|
gimp_paned_box_set_dropped_cb (GIMP_PANED_BOX (dock_columns->p->paned_hbox),
|
|
|
|
gimp_dock_columns_dropped_cb,
|
|
|
|
dock_columns);
|
2010-10-30 21:44:46 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (dock_columns), dock_columns->p->paned_hbox,
|
|
|
|
TRUE, TRUE, 0);
|
2009-10-25 02:08:58 +08:00
|
|
|
gtk_widget_show (dock_columns->p->paned_hbox);
|
2009-09-26 22:48:39 +08:00
|
|
|
}
|
|
|
|
|
2010-06-27 05:27:17 +08:00
|
|
|
static void
|
|
|
|
gimp_dock_columns_dispose (GObject *object)
|
|
|
|
{
|
|
|
|
GimpDockColumns *dock_columns = GIMP_DOCK_COLUMNS (object);
|
|
|
|
|
|
|
|
while (dock_columns->p->docks)
|
2012-02-21 07:36:18 +08:00
|
|
|
{
|
|
|
|
GimpDock *dock = dock_columns->p->docks->data;
|
|
|
|
|
|
|
|
g_object_ref (dock);
|
|
|
|
gimp_dock_columns_remove_dock (dock_columns, dock);
|
|
|
|
gtk_widget_destroy (GTK_WIDGET (dock));
|
|
|
|
g_object_unref (dock);
|
|
|
|
}
|
2010-06-27 05:27:17 +08:00
|
|
|
|
2016-08-04 05:44:14 +08:00
|
|
|
if (dock_columns->p->context)
|
|
|
|
{
|
|
|
|
g_object_remove_weak_pointer (G_OBJECT (dock_columns->p->context),
|
|
|
|
(gpointer) &dock_columns->p->context);
|
|
|
|
dock_columns->p->context = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dock_columns->p->dialog_factory)
|
|
|
|
{
|
|
|
|
g_object_remove_weak_pointer (G_OBJECT (dock_columns->p->dialog_factory),
|
|
|
|
(gpointer) &dock_columns->p->dialog_factory);
|
|
|
|
dock_columns->p->dialog_factory = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dock_columns->p->ui_manager)
|
|
|
|
{
|
|
|
|
g_object_remove_weak_pointer (G_OBJECT (dock_columns->p->ui_manager),
|
|
|
|
(gpointer)&dock_columns->p->ui_manager);
|
|
|
|
dock_columns->p->ui_manager = NULL;
|
|
|
|
}
|
|
|
|
|
2010-06-27 05:27:17 +08:00
|
|
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
|
|
|
}
|
|
|
|
|
2010-01-08 02:13:13 +08:00
|
|
|
static void
|
|
|
|
gimp_dock_columns_set_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
GimpDockColumns *dock_columns = GIMP_DOCK_COLUMNS (object);
|
|
|
|
|
|
|
|
switch (property_id)
|
|
|
|
{
|
|
|
|
case PROP_CONTEXT:
|
2016-08-04 05:44:14 +08:00
|
|
|
if (dock_columns->p->context)
|
|
|
|
g_object_remove_weak_pointer (G_OBJECT (dock_columns->p->context),
|
|
|
|
(gpointer) &dock_columns->p->context);
|
2010-01-08 02:13:13 +08:00
|
|
|
dock_columns->p->context = g_value_get_object (value);
|
2016-08-04 05:44:14 +08:00
|
|
|
if (dock_columns->p->context)
|
|
|
|
g_object_add_weak_pointer (G_OBJECT (dock_columns->p->context),
|
|
|
|
(gpointer) &dock_columns->p->context);
|
2010-01-08 02:13:13 +08:00
|
|
|
break;
|
2016-08-04 05:44:14 +08:00
|
|
|
|
2010-01-08 02:18:03 +08:00
|
|
|
case PROP_DIALOG_FACTORY:
|
2016-08-04 05:44:14 +08:00
|
|
|
if (dock_columns->p->dialog_factory)
|
|
|
|
g_object_remove_weak_pointer (G_OBJECT (dock_columns->p->dialog_factory),
|
|
|
|
(gpointer) &dock_columns->p->dialog_factory);
|
2010-01-08 02:18:03 +08:00
|
|
|
dock_columns->p->dialog_factory = g_value_get_object (value);
|
2016-08-04 05:44:14 +08:00
|
|
|
if (dock_columns->p->dialog_factory)
|
|
|
|
g_object_add_weak_pointer (G_OBJECT (dock_columns->p->dialog_factory),
|
|
|
|
(gpointer) &dock_columns->p->dialog_factory);
|
2010-01-08 02:18:03 +08:00
|
|
|
break;
|
2016-08-04 05:44:14 +08:00
|
|
|
|
2010-01-08 02:18:03 +08:00
|
|
|
case PROP_UI_MANAGER:
|
2016-08-04 05:44:14 +08:00
|
|
|
if (dock_columns->p->ui_manager)
|
|
|
|
g_object_remove_weak_pointer (G_OBJECT (dock_columns->p->ui_manager),
|
|
|
|
(gpointer) &dock_columns->p->ui_manager);
|
2010-01-08 02:18:03 +08:00
|
|
|
dock_columns->p->ui_manager = g_value_get_object (value);
|
2016-08-04 05:44:14 +08:00
|
|
|
if (dock_columns->p->ui_manager)
|
|
|
|
g_object_add_weak_pointer (G_OBJECT (dock_columns->p->ui_manager),
|
|
|
|
(gpointer) &dock_columns->p->ui_manager);
|
2010-01-08 02:18:03 +08:00
|
|
|
break;
|
2010-01-08 02:13:13 +08:00
|
|
|
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_dock_columns_get_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
GimpDockColumns *dock_columns = GIMP_DOCK_COLUMNS (object);
|
|
|
|
|
|
|
|
switch (property_id)
|
|
|
|
{
|
|
|
|
case PROP_CONTEXT:
|
|
|
|
g_value_set_object (value, dock_columns->p->context);
|
|
|
|
break;
|
2010-01-08 02:18:03 +08:00
|
|
|
case PROP_DIALOG_FACTORY:
|
|
|
|
g_value_set_object (value, dock_columns->p->dialog_factory);
|
|
|
|
break;
|
|
|
|
case PROP_UI_MANAGER:
|
|
|
|
g_value_set_object (value, dock_columns->p->ui_manager);
|
|
|
|
break;
|
2010-01-08 02:13:13 +08:00
|
|
|
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-25 02:08:58 +08:00
|
|
|
static gboolean
|
2011-07-04 02:34:42 +08:00
|
|
|
gimp_dock_columns_dropped_cb (GtkWidget *source,
|
|
|
|
gint insert_index,
|
|
|
|
gpointer data)
|
2009-10-25 02:08:58 +08:00
|
|
|
{
|
2009-10-26 06:34:43 +08:00
|
|
|
GimpDockColumns *dock_columns = GIMP_DOCK_COLUMNS (data);
|
|
|
|
GimpDockable *dockable = gimp_dockbook_drag_source_to_dockable (source);
|
|
|
|
GtkWidget *dockbook = NULL;
|
|
|
|
|
2011-07-04 02:34:42 +08:00
|
|
|
if (! dockable)
|
2009-10-26 06:34:43 +08:00
|
|
|
return FALSE;
|
|
|
|
|
2011-07-04 02:34:42 +08:00
|
|
|
/* Create a new dock (including a new dockbook) */
|
|
|
|
gimp_dock_columns_prepare_dockbook (dock_columns,
|
|
|
|
insert_index,
|
|
|
|
&dockbook);
|
2009-10-26 06:34:43 +08:00
|
|
|
|
|
|
|
/* Move the dockable to the new dockbook */
|
2011-07-04 02:34:42 +08:00
|
|
|
g_object_ref (dockbook);
|
2009-10-26 06:34:43 +08:00
|
|
|
g_object_ref (dockable);
|
2010-01-05 07:30:10 +08:00
|
|
|
gimp_dockbook_remove (gimp_dockable_get_dockbook (dockable), dockable);
|
2009-10-26 06:34:43 +08:00
|
|
|
gimp_dockbook_add (GIMP_DOCKBOOK (dockbook), dockable, -1);
|
|
|
|
g_object_unref (dockable);
|
|
|
|
g_object_unref (dockbook);
|
|
|
|
|
|
|
|
return TRUE;
|
2009-10-25 02:08:58 +08:00
|
|
|
}
|
|
|
|
|
2009-11-14 01:24:20 +08:00
|
|
|
static void
|
|
|
|
gimp_dock_columns_real_dock_added (GimpDockColumns *dock_columns,
|
|
|
|
GimpDock *dock)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_dock_columns_real_dock_removed (GimpDockColumns *dock_columns,
|
|
|
|
GimpDock *dock)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2009-11-15 22:54:20 +08:00
|
|
|
static void
|
2009-11-16 02:51:15 +08:00
|
|
|
gimp_dock_columns_dock_book_removed (GimpDockColumns *dock_columns,
|
|
|
|
GimpDockbook *dockbook,
|
|
|
|
GimpDock *dock)
|
2009-11-15 22:54:20 +08:00
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DOCK (dock));
|
|
|
|
|
2010-01-06 22:10:32 +08:00
|
|
|
if (gimp_dock_get_dockbooks (dock) == NULL &&
|
2010-03-07 16:33:33 +08:00
|
|
|
! GIMP_IS_TOOLBOX (dock) &&
|
2010-03-07 19:59:21 +08:00
|
|
|
gtk_widget_get_parent (GTK_WIDGET (dock)) != NULL)
|
2009-11-15 22:54:20 +08:00
|
|
|
gimp_dock_columns_remove_dock (dock_columns, dock);
|
|
|
|
}
|
|
|
|
|
2009-11-14 01:24:20 +08:00
|
|
|
|
2010-01-08 02:13:13 +08:00
|
|
|
/**
|
|
|
|
* gimp_dock_columns_new:
|
|
|
|
* @context:
|
|
|
|
*
|
|
|
|
* Returns: A new #GimpDockColumns.
|
|
|
|
**/
|
|
|
|
GtkWidget *
|
2010-01-08 02:18:03 +08:00
|
|
|
gimp_dock_columns_new (GimpContext *context,
|
|
|
|
GimpDialogFactory *dialog_factory,
|
|
|
|
GimpUIManager *ui_manager)
|
2010-01-08 02:13:13 +08:00
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
|
2010-01-08 02:18:03 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_DIALOG_FACTORY (dialog_factory), NULL);
|
|
|
|
g_return_val_if_fail (GIMP_IS_UI_MANAGER (ui_manager), NULL);
|
2010-01-08 02:13:13 +08:00
|
|
|
|
|
|
|
return g_object_new (GIMP_TYPE_DOCK_COLUMNS,
|
2010-01-08 02:18:03 +08:00
|
|
|
"context", context,
|
|
|
|
"dialog-factory", dialog_factory,
|
|
|
|
"ui-manager", ui_manager,
|
2010-01-08 02:13:13 +08:00
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
2009-10-25 02:08:58 +08:00
|
|
|
/**
|
|
|
|
* gimp_dock_columns_add_dock:
|
|
|
|
* @dock_columns:
|
|
|
|
* @dock:
|
|
|
|
*
|
|
|
|
* Add a dock, added to a horizontal GimpPanedBox.
|
|
|
|
**/
|
2009-10-04 08:05:22 +08:00
|
|
|
void
|
|
|
|
gimp_dock_columns_add_dock (GimpDockColumns *dock_columns,
|
2009-10-25 02:08:58 +08:00
|
|
|
GimpDock *dock,
|
|
|
|
gint index)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DOCK_COLUMNS (dock_columns));
|
|
|
|
g_return_if_fail (GIMP_IS_DOCK (dock));
|
|
|
|
|
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_LOG (DND, "Adding GimpDock %p to GimpDockColumns %p", dock, dock_columns);
|
|
|
|
|
2016-06-11 22:51:21 +08:00
|
|
|
dock_columns->p->docks = g_list_insert (dock_columns->p->docks, dock, index);
|
2009-10-25 02:08:58 +08:00
|
|
|
|
2010-01-06 20:33:47 +08:00
|
|
|
gimp_dock_update_with_context (dock, dock_columns->p->context);
|
|
|
|
|
2009-10-25 02:08:58 +08:00
|
|
|
gimp_paned_box_add_widget (GIMP_PANED_BOX (dock_columns->p->paned_hbox),
|
|
|
|
GTK_WIDGET (dock),
|
|
|
|
index);
|
2009-11-14 01:24:20 +08:00
|
|
|
|
2009-11-15 22:54:20 +08:00
|
|
|
g_signal_connect_object (dock, "book-removed",
|
2009-11-16 02:51:15 +08:00
|
|
|
G_CALLBACK (gimp_dock_columns_dock_book_removed),
|
2009-11-15 22:54:20 +08:00
|
|
|
dock_columns,
|
|
|
|
G_CONNECT_SWAPPED);
|
|
|
|
|
2009-11-14 01:24:20 +08:00
|
|
|
g_signal_emit (dock_columns, dock_columns_signals[DOCK_ADDED], 0, dock);
|
2009-10-25 02:08:58 +08:00
|
|
|
}
|
|
|
|
|
2011-07-04 02:34:42 +08:00
|
|
|
/**
|
|
|
|
* gimp_dock_columns_prepare_dockbook:
|
|
|
|
* @dock_columns:
|
|
|
|
* @dock_index:
|
|
|
|
* @dockbook_p:
|
|
|
|
*
|
|
|
|
* Create a new dock and add it to the dock columns with the given
|
|
|
|
* dock_index insert index, then create and add a dockbook and put it
|
|
|
|
* in the dock.
|
|
|
|
**/
|
|
|
|
void
|
|
|
|
gimp_dock_columns_prepare_dockbook (GimpDockColumns *dock_columns,
|
|
|
|
gint dock_index,
|
|
|
|
GtkWidget **dockbook_p)
|
|
|
|
{
|
2016-11-24 02:16:36 +08:00
|
|
|
GimpMenuFactory *menu_factory;
|
|
|
|
GtkWidget *dock;
|
|
|
|
GtkWidget *dockbook;
|
2011-07-04 02:34:42 +08:00
|
|
|
|
|
|
|
dock = gimp_menu_dock_new ();
|
|
|
|
gimp_dock_columns_add_dock (dock_columns, GIMP_DOCK (dock), dock_index);
|
|
|
|
|
2016-11-24 02:16:36 +08:00
|
|
|
menu_factory = gimp_dialog_factory_get_menu_factory (dock_columns->p->dialog_factory);
|
|
|
|
dockbook = gimp_dockbook_new (menu_factory);
|
2011-07-04 02:34:42 +08:00
|
|
|
gimp_dock_add_book (GIMP_DOCK (dock), GIMP_DOCKBOOK (dockbook), -1);
|
|
|
|
|
|
|
|
gtk_widget_show (GTK_WIDGET (dock));
|
|
|
|
|
|
|
|
if (dockbook_p)
|
|
|
|
*dockbook_p = dockbook;
|
|
|
|
}
|
|
|
|
|
2009-10-25 02:08:58 +08:00
|
|
|
|
|
|
|
void
|
|
|
|
gimp_dock_columns_remove_dock (GimpDockColumns *dock_columns,
|
|
|
|
GimpDock *dock)
|
2009-10-04 08:05:22 +08:00
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DOCK_COLUMNS (dock_columns));
|
|
|
|
g_return_if_fail (GIMP_IS_DOCK (dock));
|
|
|
|
|
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_LOG (DND, "Removing GimpDock %p from GimpDockColumns %p", dock, dock_columns);
|
|
|
|
|
2009-10-25 02:08:58 +08:00
|
|
|
dock_columns->p->docks = g_list_remove (dock_columns->p->docks, dock);
|
|
|
|
|
2010-01-06 20:33:47 +08:00
|
|
|
gimp_dock_update_with_context (dock, NULL);
|
|
|
|
|
2009-11-15 22:54:20 +08:00
|
|
|
g_signal_handlers_disconnect_by_func (dock,
|
2009-11-16 02:51:15 +08:00
|
|
|
gimp_dock_columns_dock_book_removed,
|
2009-11-15 22:54:20 +08:00
|
|
|
dock_columns);
|
|
|
|
|
2009-11-14 01:24:20 +08:00
|
|
|
g_object_ref (dock);
|
2009-10-25 02:08:58 +08:00
|
|
|
gimp_paned_box_remove_widget (GIMP_PANED_BOX (dock_columns->p->paned_hbox),
|
|
|
|
GTK_WIDGET (dock));
|
2009-11-14 01:24:20 +08:00
|
|
|
|
|
|
|
g_signal_emit (dock_columns, dock_columns_signals[DOCK_REMOVED], 0, dock);
|
|
|
|
g_object_unref (dock);
|
2009-10-25 02:08:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
GList *
|
|
|
|
gimp_dock_columns_get_docks (GimpDockColumns *dock_columns)
|
|
|
|
{
|
2010-01-05 17:37:03 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_DOCK_COLUMNS (dock_columns), NULL);
|
|
|
|
|
2009-11-16 02:21:57 +08:00
|
|
|
return dock_columns->p->docks;
|
2009-10-04 08:05:22 +08:00
|
|
|
}
|
2010-01-05 18:08:10 +08:00
|
|
|
|
|
|
|
GimpContext *
|
|
|
|
gimp_dock_columns_get_context (GimpDockColumns *dock_columns)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DOCK_COLUMNS (dock_columns), NULL);
|
|
|
|
|
|
|
|
return dock_columns->p->context;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_dock_columns_set_context (GimpDockColumns *dock_columns,
|
|
|
|
GimpContext *context)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DOCK_COLUMNS (dock_columns));
|
|
|
|
|
|
|
|
dock_columns->p->context = context;
|
|
|
|
}
|
2010-01-08 02:18:03 +08:00
|
|
|
|
|
|
|
GimpDialogFactory *
|
|
|
|
gimp_dock_columns_get_dialog_factory (GimpDockColumns *dock_columns)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DOCK_COLUMNS (dock_columns), NULL);
|
|
|
|
|
|
|
|
return dock_columns->p->dialog_factory;
|
|
|
|
}
|
|
|
|
|
|
|
|
GimpUIManager *
|
|
|
|
gimp_dock_columns_get_ui_manager (GimpDockColumns *dock_columns)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DOCK_COLUMNS (dock_columns), NULL);
|
|
|
|
|
|
|
|
return dock_columns->p->ui_manager;
|
|
|
|
}
|