2006-12-10 05:33:38 +08:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
2001-04-07 22:44:12 +08:00
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
|
|
|
* gimpdockable.c
|
2003-10-11 05:24:12 +08:00
|
|
|
* Copyright (C) 2001-2003 Michael Natterer <mitch@gimp.org>
|
2001-04-07 22:44:12 +08:00
|
|
|
*
|
2009-01-18 06:28:01 +08:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
2001-04-07 22:44:12 +08:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2009-01-18 06:28:01 +08:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
2001-04-07 22:44:12 +08:00
|
|
|
* (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
|
2009-01-18 06:28:01 +08:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2001-04-07 22:44:12 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2009-10-18 02:20:39 +08:00
|
|
|
#undef GSEAL_ENABLE
|
|
|
|
|
2008-05-20 05:11:03 +08:00
|
|
|
#include <string.h>
|
|
|
|
|
2001-04-07 22:44:12 +08:00
|
|
|
#include <gtk/gtk.h>
|
|
|
|
|
2003-08-26 09:30:05 +08:00
|
|
|
#include "libgimpwidgets/gimpwidgets.h"
|
|
|
|
|
2001-05-08 11:48:54 +08:00
|
|
|
#include "widgets-types.h"
|
2001-04-07 22:44:12 +08:00
|
|
|
|
2009-12-11 02:26:23 +08:00
|
|
|
#include "menus/menus.h"
|
|
|
|
|
|
|
|
#include "dialogs/dialogs.h"
|
|
|
|
|
2001-05-09 10:32:03 +08:00
|
|
|
#include "core/gimpcontext.h"
|
|
|
|
|
2003-10-07 20:24:01 +08:00
|
|
|
#include "gimpdialogfactory.h"
|
2003-10-06 01:26:21 +08:00
|
|
|
#include "gimpdnd.h"
|
2003-10-08 23:44:35 +08:00
|
|
|
#include "gimpdock.h"
|
2001-04-07 22:44:12 +08:00
|
|
|
#include "gimpdockable.h"
|
2001-04-16 00:16:13 +08:00
|
|
|
#include "gimpdockbook.h"
|
2003-10-11 05:24:12 +08:00
|
|
|
#include "gimpdocked.h"
|
2009-09-26 22:21:10 +08:00
|
|
|
#include "gimpdockwindow.h"
|
2004-08-18 17:53:38 +08:00
|
|
|
#include "gimphelp-ids.h"
|
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 "gimppanedbox.h"
|
2008-05-20 05:11:03 +08:00
|
|
|
#include "gimpsessioninfo-aux.h"
|
2004-04-23 01:14:22 +08:00
|
|
|
#include "gimpuimanager.h"
|
2003-10-01 02:50:55 +08:00
|
|
|
#include "gimpwidgets-utils.h"
|
2001-04-07 22:44:12 +08:00
|
|
|
|
2003-10-19 06:12:32 +08:00
|
|
|
#include "gimp-intl.h"
|
|
|
|
|
2001-04-07 22:44:12 +08:00
|
|
|
|
2008-05-20 05:11:03 +08:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_0,
|
|
|
|
PROP_LOCKED
|
|
|
|
};
|
|
|
|
|
|
|
|
static void gimp_dockable_set_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec);
|
|
|
|
static void gimp_dockable_get_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec);
|
2003-10-11 05:24:12 +08:00
|
|
|
static void gimp_dockable_destroy (GtkObject *object);
|
|
|
|
static void gimp_dockable_size_request (GtkWidget *widget,
|
|
|
|
GtkRequisition *requisition);
|
|
|
|
static void gimp_dockable_size_allocate (GtkWidget *widget,
|
|
|
|
GtkAllocation *allocation);
|
|
|
|
static void gimp_dockable_realize (GtkWidget *widget);
|
|
|
|
static void gimp_dockable_unrealize (GtkWidget *widget);
|
|
|
|
static void gimp_dockable_map (GtkWidget *widget);
|
|
|
|
static void gimp_dockable_unmap (GtkWidget *widget);
|
|
|
|
|
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 void gimp_dockable_drag_leave (GtkWidget *widget,
|
|
|
|
GdkDragContext *context,
|
|
|
|
guint time);
|
|
|
|
static gboolean gimp_dockable_drag_motion (GtkWidget *widget,
|
|
|
|
GdkDragContext *context,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
guint time);
|
2003-10-11 05:24:12 +08:00
|
|
|
static gboolean gimp_dockable_drag_drop (GtkWidget *widget,
|
|
|
|
GdkDragContext *context,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
guint time);
|
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
|
|
|
|
2003-10-11 05:24:12 +08:00
|
|
|
static void gimp_dockable_style_set (GtkWidget *widget,
|
|
|
|
GtkStyle *prev_style);
|
|
|
|
static gboolean gimp_dockable_expose_event (GtkWidget *widget,
|
|
|
|
GdkEventExpose *event);
|
2005-12-29 11:12:26 +08:00
|
|
|
static gboolean gimp_dockable_button_press (GtkWidget *widget,
|
|
|
|
GdkEventButton *event);
|
2005-12-29 12:28:41 +08:00
|
|
|
static gboolean gimp_dockable_button_release (GtkWidget *widget);
|
2003-10-11 05:24:12 +08:00
|
|
|
static gboolean gimp_dockable_popup_menu (GtkWidget *widget);
|
|
|
|
|
2003-10-21 22:49:12 +08:00
|
|
|
static void gimp_dockable_add (GtkContainer *container,
|
|
|
|
GtkWidget *widget);
|
|
|
|
static void gimp_dockable_remove (GtkContainer *container,
|
|
|
|
GtkWidget *widget);
|
2003-10-11 05:24:12 +08:00
|
|
|
static GType gimp_dockable_child_type (GtkContainer *container);
|
|
|
|
static void gimp_dockable_forall (GtkContainer *container,
|
2008-09-17 19:44:17 +08:00
|
|
|
gboolean include_internals,
|
2003-10-11 05:24:12 +08:00
|
|
|
GtkCallback callback,
|
|
|
|
gpointer callback_data);
|
|
|
|
|
2008-05-20 05:11:03 +08:00
|
|
|
static void gimp_dockable_cursor_setup (GimpDockable *dockable);
|
|
|
|
|
2003-10-11 05:24:12 +08:00
|
|
|
static void gimp_dockable_get_title_area (GimpDockable *dockable,
|
|
|
|
GdkRectangle *area);
|
2005-12-29 07:43:53 +08:00
|
|
|
static void gimp_dockable_clear_title_area (GimpDockable *dockable);
|
2003-10-11 05:24:12 +08:00
|
|
|
|
|
|
|
static gboolean gimp_dockable_menu_button_press (GtkWidget *button,
|
|
|
|
GdkEventButton *bevent,
|
|
|
|
GimpDockable *dockable);
|
|
|
|
static gboolean gimp_dockable_show_menu (GimpDockable *dockable);
|
2005-01-18 23:18:35 +08:00
|
|
|
static gboolean gimp_dockable_blink_timeout (GimpDockable *dockable);
|
2001-04-07 22:44:12 +08:00
|
|
|
|
2003-10-21 22:49:12 +08:00
|
|
|
static void gimp_dockable_title_changed (GimpDocked *docked,
|
|
|
|
GimpDockable *dockable);
|
|
|
|
|
2001-08-04 03:43:19 +08:00
|
|
|
|
2006-05-15 17:46:31 +08:00
|
|
|
G_DEFINE_TYPE (GimpDockable, gimp_dockable, GTK_TYPE_BIN)
|
2001-04-07 22:44:12 +08:00
|
|
|
|
2005-12-20 06:37:49 +08:00
|
|
|
#define parent_class gimp_dockable_parent_class
|
2003-10-06 01:26:21 +08:00
|
|
|
|
2006-04-06 20:43:58 +08:00
|
|
|
static const GtkTargetEntry dialog_target_table[] = { GIMP_TARGET_DIALOG };
|
2001-04-07 22:44:12 +08:00
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_dockable_class_init (GimpDockableClass *klass)
|
|
|
|
{
|
2008-05-20 05:11:03 +08:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass);
|
|
|
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
|
|
|
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
|
2001-04-07 22:44:12 +08:00
|
|
|
|
2008-05-20 05:11:03 +08:00
|
|
|
object_class->set_property = gimp_dockable_set_property;
|
|
|
|
object_class->get_property = gimp_dockable_get_property;
|
|
|
|
|
|
|
|
gtk_object_class->destroy = gimp_dockable_destroy;
|
2001-08-04 03:43:19 +08:00
|
|
|
|
2003-04-12 00:51:49 +08:00
|
|
|
widget_class->size_request = gimp_dockable_size_request;
|
|
|
|
widget_class->size_allocate = gimp_dockable_size_allocate;
|
2003-10-06 01:26:21 +08:00
|
|
|
widget_class->realize = gimp_dockable_realize;
|
|
|
|
widget_class->unrealize = gimp_dockable_unrealize;
|
|
|
|
widget_class->map = gimp_dockable_map;
|
|
|
|
widget_class->unmap = gimp_dockable_unmap;
|
2003-04-12 00:51:49 +08:00
|
|
|
widget_class->style_set = gimp_dockable_style_set;
|
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
|
|
|
widget_class->drag_leave = gimp_dockable_drag_leave;
|
|
|
|
widget_class->drag_motion = gimp_dockable_drag_motion;
|
2003-10-06 01:26:21 +08:00
|
|
|
widget_class->drag_drop = gimp_dockable_drag_drop;
|
2003-09-22 03:35:54 +08:00
|
|
|
widget_class->expose_event = gimp_dockable_expose_event;
|
2003-09-24 00:17:25 +08:00
|
|
|
widget_class->popup_menu = gimp_dockable_popup_menu;
|
2003-09-22 03:35:54 +08:00
|
|
|
|
2003-10-21 22:49:12 +08:00
|
|
|
container_class->add = gimp_dockable_add;
|
|
|
|
container_class->remove = gimp_dockable_remove;
|
2003-10-11 05:24:12 +08:00
|
|
|
container_class->child_type = gimp_dockable_child_type;
|
2003-09-22 03:35:54 +08:00
|
|
|
container_class->forall = gimp_dockable_forall;
|
2001-08-04 03:43:19 +08:00
|
|
|
|
2008-05-20 05:11:03 +08:00
|
|
|
g_object_class_install_property (object_class, PROP_LOCKED,
|
|
|
|
g_param_spec_boolean ("locked", NULL, NULL,
|
|
|
|
FALSE,
|
|
|
|
GIMP_PARAM_READWRITE));
|
|
|
|
|
2001-08-04 03:43:19 +08:00
|
|
|
gtk_widget_class_install_style_property (widget_class,
|
2005-05-28 00:51:39 +08:00
|
|
|
g_param_spec_int ("content-border",
|
2001-08-04 03:43:19 +08:00
|
|
|
NULL, NULL,
|
|
|
|
0,
|
|
|
|
G_MAXINT,
|
|
|
|
0,
|
2006-01-19 04:29:40 +08:00
|
|
|
GIMP_PARAM_READABLE));
|
2001-04-07 22:44:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_dockable_init (GimpDockable *dockable)
|
|
|
|
{
|
2003-09-22 03:35:54 +08:00
|
|
|
GtkWidget *image;
|
|
|
|
|
2003-10-11 05:24:12 +08:00
|
|
|
dockable->name = NULL;
|
|
|
|
dockable->blurb = NULL;
|
|
|
|
dockable->stock_id = NULL;
|
|
|
|
dockable->help_id = NULL;
|
|
|
|
dockable->tab_style = GIMP_TAB_STYLE_PREVIEW;
|
|
|
|
dockable->dockbook = NULL;
|
|
|
|
dockable->context = NULL;
|
2003-09-22 03:35:54 +08:00
|
|
|
|
2003-10-11 05:24:12 +08:00
|
|
|
dockable->title_layout = NULL;
|
|
|
|
dockable->title_window = NULL;
|
2003-09-24 02:11:09 +08:00
|
|
|
|
2005-12-30 09:37:35 +08:00
|
|
|
dockable->drag_x = GIMP_DOCKABLE_DRAG_OFFSET;
|
|
|
|
dockable->drag_y = GIMP_DOCKABLE_DRAG_OFFSET;
|
2005-12-29 11:12:26 +08:00
|
|
|
|
2003-09-22 03:35:54 +08:00
|
|
|
gtk_widget_push_composite_child ();
|
|
|
|
dockable->menu_button = gtk_button_new ();
|
|
|
|
gtk_widget_pop_composite_child ();
|
|
|
|
|
2009-10-18 02:20:39 +08:00
|
|
|
gtk_widget_set_can_focus (dockable->menu_button, FALSE);
|
2003-09-22 03:35:54 +08:00
|
|
|
gtk_widget_set_parent (dockable->menu_button, GTK_WIDGET (dockable));
|
|
|
|
gtk_button_set_relief (GTK_BUTTON (dockable->menu_button), GTK_RELIEF_NONE);
|
2003-09-24 00:17:25 +08:00
|
|
|
gtk_widget_show (dockable->menu_button);
|
2003-09-22 03:35:54 +08:00
|
|
|
|
2003-09-23 20:30:53 +08:00
|
|
|
image = gtk_image_new_from_stock (GIMP_STOCK_MENU_LEFT, GTK_ICON_SIZE_MENU);
|
2003-09-22 03:35:54 +08:00
|
|
|
gtk_container_add (GTK_CONTAINER (dockable->menu_button), image);
|
|
|
|
gtk_widget_show (image);
|
|
|
|
|
2005-02-19 10:13:33 +08:00
|
|
|
gimp_help_set_help_data (dockable->menu_button, _("Configure this tab"),
|
|
|
|
GIMP_HELP_DOCK_TAB_MENU);
|
|
|
|
|
2005-05-28 00:51:39 +08:00
|
|
|
g_signal_connect (dockable->menu_button, "button-press-event",
|
2003-09-22 03:35:54 +08:00
|
|
|
G_CALLBACK (gimp_dockable_menu_button_press),
|
|
|
|
dockable);
|
|
|
|
|
2003-10-06 01:26:21 +08:00
|
|
|
gtk_drag_dest_set (GTK_WIDGET (dockable),
|
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
|
|
|
0,
|
2003-10-06 01:26:21 +08:00
|
|
|
dialog_target_table, G_N_ELEMENTS (dialog_target_table),
|
|
|
|
GDK_ACTION_MOVE);
|
2003-12-12 03:34:37 +08:00
|
|
|
|
2008-05-20 05:11:03 +08:00
|
|
|
/* Filter out all button-press events not coming from the event window
|
2003-12-12 03:34:37 +08:00
|
|
|
over the title area. This keeps events that originate from widgets
|
|
|
|
in the dockable to start a drag.
|
|
|
|
*/
|
2005-05-28 00:51:39 +08:00
|
|
|
g_signal_connect (dockable, "button-press-event",
|
2005-12-29 11:12:26 +08:00
|
|
|
G_CALLBACK (gimp_dockable_button_press),
|
2003-12-12 03:34:37 +08:00
|
|
|
NULL);
|
2005-12-29 12:28:41 +08:00
|
|
|
g_signal_connect (dockable, "button-release-event",
|
|
|
|
G_CALLBACK (gimp_dockable_button_release),
|
|
|
|
NULL);
|
2001-04-07 22:44:12 +08:00
|
|
|
}
|
|
|
|
|
2008-05-20 05:11:03 +08:00
|
|
|
static void
|
|
|
|
gimp_dockable_set_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
GimpDockable *dockable = GIMP_DOCKABLE (object);
|
|
|
|
|
|
|
|
switch (property_id)
|
|
|
|
{
|
|
|
|
case PROP_LOCKED:
|
|
|
|
gimp_dockable_set_locked (dockable, g_value_get_boolean (value));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_dockable_get_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
GimpDockable *dockable = GIMP_DOCKABLE (object);
|
|
|
|
|
|
|
|
switch (property_id)
|
|
|
|
{
|
|
|
|
case PROP_LOCKED:
|
|
|
|
g_value_set_boolean (value, dockable->locked);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-04-07 22:44:12 +08:00
|
|
|
static void
|
|
|
|
gimp_dockable_destroy (GtkObject *object)
|
|
|
|
{
|
2003-09-22 03:35:54 +08:00
|
|
|
GimpDockable *dockable = GIMP_DOCKABLE (object);
|
2001-04-07 22:44:12 +08:00
|
|
|
|
2005-12-29 07:43:53 +08:00
|
|
|
gimp_dockable_blink_cancel (dockable);
|
|
|
|
|
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
|
|
|
if (dockable->context)
|
|
|
|
gimp_dockable_set_context (dockable, NULL);
|
|
|
|
|
2006-03-31 18:08:02 +08:00
|
|
|
if (dockable->blurb)
|
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
|
|
|
{
|
2006-03-31 18:08:02 +08:00
|
|
|
if (dockable->blurb != dockable->name)
|
|
|
|
g_free (dockable->blurb);
|
|
|
|
|
2003-10-01 02:50:55 +08:00
|
|
|
dockable->blurb = 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
|
|
|
}
|
|
|
|
|
2003-10-01 02:50:55 +08:00
|
|
|
if (dockable->name)
|
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
|
|
|
{
|
2003-10-01 02:50:55 +08:00
|
|
|
g_free (dockable->name);
|
|
|
|
dockable->name = 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
|
|
|
}
|
2001-04-07 22:44:12 +08:00
|
|
|
|
2002-05-10 22:50:27 +08:00
|
|
|
if (dockable->stock_id)
|
|
|
|
{
|
|
|
|
g_free (dockable->stock_id);
|
|
|
|
dockable->stock_id = NULL;
|
|
|
|
}
|
|
|
|
|
2003-08-25 22:18:33 +08:00
|
|
|
if (dockable->help_id)
|
|
|
|
{
|
|
|
|
g_free (dockable->help_id);
|
|
|
|
dockable->help_id = NULL;
|
|
|
|
}
|
|
|
|
|
2003-09-24 02:11:09 +08:00
|
|
|
if (dockable->title_layout)
|
|
|
|
{
|
|
|
|
g_object_unref (dockable->title_layout);
|
|
|
|
dockable->title_layout = NULL;
|
|
|
|
}
|
|
|
|
|
2003-09-22 03:35:54 +08:00
|
|
|
if (dockable->menu_button)
|
|
|
|
{
|
|
|
|
gtk_widget_unparent (dockable->menu_button);
|
|
|
|
dockable->menu_button = NULL;
|
|
|
|
}
|
|
|
|
|
2003-04-09 03:54:22 +08:00
|
|
|
GTK_OBJECT_CLASS (parent_class)->destroy (object);
|
2001-04-07 22:44:12 +08:00
|
|
|
}
|
|
|
|
|
2003-04-12 00:51:49 +08:00
|
|
|
static void
|
|
|
|
gimp_dockable_size_request (GtkWidget *widget,
|
|
|
|
GtkRequisition *requisition)
|
|
|
|
{
|
2004-09-01 05:29:30 +08:00
|
|
|
GtkContainer *container = GTK_CONTAINER (widget);
|
|
|
|
GimpDockable *dockable = GIMP_DOCKABLE (widget);
|
2008-03-13 00:58:28 +08:00
|
|
|
GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
|
2004-09-01 05:29:30 +08:00
|
|
|
GtkRequisition child_requisition;
|
2008-06-28 23:50:27 +08:00
|
|
|
gint border_width;
|
2003-04-12 00:51:49 +08:00
|
|
|
|
2008-06-28 23:50:27 +08:00
|
|
|
border_width = gtk_container_get_border_width (container);
|
|
|
|
|
|
|
|
requisition->width = border_width * 2;
|
|
|
|
requisition->height = border_width * 2;
|
2003-09-22 03:35:54 +08:00
|
|
|
|
2009-10-18 02:20:39 +08:00
|
|
|
if (dockable->menu_button && gtk_widget_get_visible (dockable->menu_button))
|
2003-04-12 00:51:49 +08:00
|
|
|
{
|
2005-04-22 07:30:38 +08:00
|
|
|
gtk_widget_size_request (dockable->menu_button, &child_requisition);
|
2003-09-22 03:35:54 +08:00
|
|
|
|
2008-03-13 00:58:28 +08:00
|
|
|
if (! child)
|
2003-09-22 03:35:54 +08:00
|
|
|
requisition->width += child_requisition.width;
|
2003-08-26 09:30:05 +08:00
|
|
|
|
2003-09-22 03:35:54 +08:00
|
|
|
requisition->height += child_requisition.height;
|
|
|
|
}
|
|
|
|
|
2009-10-18 02:20:39 +08:00
|
|
|
if (child && gtk_widget_get_visible (child))
|
2003-09-22 03:35:54 +08:00
|
|
|
{
|
2008-03-13 00:58:28 +08:00
|
|
|
gtk_widget_size_request (child, &child_requisition);
|
2003-04-12 00:51:49 +08:00
|
|
|
|
|
|
|
requisition->width += child_requisition.width;
|
|
|
|
requisition->height += child_requisition.height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_dockable_size_allocate (GtkWidget *widget,
|
|
|
|
GtkAllocation *allocation)
|
|
|
|
{
|
2004-09-01 05:29:30 +08:00
|
|
|
GtkContainer *container = GTK_CONTAINER (widget);
|
|
|
|
GimpDockable *dockable = GIMP_DOCKABLE (widget);
|
2008-03-13 00:58:28 +08:00
|
|
|
GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
|
2004-09-01 05:29:30 +08:00
|
|
|
|
2003-09-22 03:35:54 +08:00
|
|
|
GtkRequisition button_requisition = { 0, };
|
|
|
|
GtkAllocation child_allocation;
|
2008-06-28 23:50:27 +08:00
|
|
|
gint border_width;
|
2003-09-22 03:35:54 +08:00
|
|
|
|
2003-04-12 00:51:49 +08:00
|
|
|
widget->allocation = *allocation;
|
|
|
|
|
2008-06-28 23:50:27 +08:00
|
|
|
border_width = gtk_container_get_border_width (container);
|
|
|
|
|
2009-10-18 02:20:39 +08:00
|
|
|
if (dockable->menu_button && gtk_widget_get_visible (dockable->menu_button))
|
2003-04-12 00:51:49 +08:00
|
|
|
{
|
2005-04-22 07:30:38 +08:00
|
|
|
gtk_widget_size_request (dockable->menu_button, &button_requisition);
|
2003-09-22 03:35:54 +08:00
|
|
|
|
2003-09-24 02:11:09 +08:00
|
|
|
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
|
|
|
|
child_allocation.x = (allocation->x +
|
2003-09-22 03:35:54 +08:00
|
|
|
allocation->width -
|
2008-06-28 23:50:27 +08:00
|
|
|
border_width -
|
2003-09-22 03:35:54 +08:00
|
|
|
button_requisition.width);
|
2003-09-24 02:11:09 +08:00
|
|
|
else
|
2008-06-28 23:50:27 +08:00
|
|
|
child_allocation.x = allocation->x + border_width;
|
2003-09-24 02:11:09 +08:00
|
|
|
|
2008-06-28 23:50:27 +08:00
|
|
|
child_allocation.y = allocation->y + border_width;
|
2003-09-22 03:35:54 +08:00
|
|
|
child_allocation.width = button_requisition.width;
|
|
|
|
child_allocation.height = button_requisition.height;
|
|
|
|
|
|
|
|
gtk_widget_size_allocate (dockable->menu_button, &child_allocation);
|
|
|
|
}
|
2003-04-12 00:51:49 +08:00
|
|
|
|
2009-10-18 02:20:39 +08:00
|
|
|
if (child && gtk_widget_get_visible (child))
|
2003-09-22 03:35:54 +08:00
|
|
|
{
|
2008-06-28 23:50:27 +08:00
|
|
|
child_allocation.x = allocation->x + border_width;
|
|
|
|
child_allocation.y = allocation->y + border_width;
|
2003-04-12 00:51:49 +08:00
|
|
|
child_allocation.width = MAX (allocation->width -
|
2008-06-28 23:50:27 +08:00
|
|
|
border_width * 2,
|
2003-04-12 00:51:49 +08:00
|
|
|
0);
|
|
|
|
child_allocation.height = MAX (allocation->height -
|
2008-06-28 23:50:27 +08:00
|
|
|
border_width * 2 -
|
2003-09-22 03:35:54 +08:00
|
|
|
button_requisition.height,
|
2003-04-12 00:51:49 +08:00
|
|
|
0);
|
|
|
|
|
2003-09-22 03:35:54 +08:00
|
|
|
child_allocation.y += button_requisition.height;
|
|
|
|
|
2008-03-13 00:58:28 +08:00
|
|
|
gtk_widget_size_allocate (child, &child_allocation);
|
2003-04-12 00:51:49 +08:00
|
|
|
}
|
2003-10-06 01:26:21 +08:00
|
|
|
|
|
|
|
if (dockable->title_window)
|
|
|
|
{
|
|
|
|
GdkRectangle area;
|
|
|
|
|
|
|
|
gimp_dockable_get_title_area (dockable, &area);
|
|
|
|
|
|
|
|
gdk_window_move_resize (dockable->title_window,
|
|
|
|
area.x, area.y, area.width, area.height);
|
2005-05-25 17:45:06 +08:00
|
|
|
|
|
|
|
if (dockable->title_layout)
|
|
|
|
pango_layout_set_width (dockable->title_layout,
|
|
|
|
PANGO_SCALE * area.width);
|
2003-10-06 01:26:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_dockable_realize (GtkWidget *widget)
|
|
|
|
{
|
|
|
|
GimpDockable *dockable = GIMP_DOCKABLE (widget);
|
|
|
|
|
|
|
|
GTK_WIDGET_CLASS (parent_class)->realize (widget);
|
|
|
|
|
|
|
|
if (! dockable->title_window)
|
|
|
|
{
|
2003-11-02 08:50:57 +08:00
|
|
|
GdkWindowAttr attributes;
|
|
|
|
GdkRectangle area;
|
2003-10-06 01:26:21 +08:00
|
|
|
|
|
|
|
gimp_dockable_get_title_area (dockable, &area);
|
|
|
|
|
|
|
|
attributes.x = area.x;
|
|
|
|
attributes.y = area.y;
|
|
|
|
attributes.width = area.width;
|
|
|
|
attributes.height = area.height;
|
2005-10-24 16:50:14 +08:00
|
|
|
attributes.window_type = GDK_WINDOW_CHILD;
|
2003-10-06 01:26:21 +08:00
|
|
|
attributes.wclass = GDK_INPUT_ONLY;
|
|
|
|
attributes.override_redirect = TRUE;
|
|
|
|
attributes.event_mask = (GDK_BUTTON_PRESS_MASK |
|
|
|
|
GDK_BUTTON_RELEASE_MASK |
|
|
|
|
GDK_BUTTON_MOTION_MASK |
|
|
|
|
gtk_widget_get_events (widget));
|
|
|
|
|
2009-03-23 00:35:53 +08:00
|
|
|
dockable->title_window = gdk_window_new (gtk_widget_get_window (widget),
|
2003-10-06 01:26:21 +08:00
|
|
|
&attributes,
|
|
|
|
(GDK_WA_X |
|
|
|
|
GDK_WA_Y |
|
|
|
|
GDK_WA_NOREDIR));
|
|
|
|
|
|
|
|
gdk_window_set_user_data (dockable->title_window, widget);
|
|
|
|
}
|
2008-05-20 05:11:03 +08:00
|
|
|
|
|
|
|
gimp_dockable_cursor_setup (dockable);
|
2003-10-06 01:26:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_dockable_unrealize (GtkWidget *widget)
|
|
|
|
{
|
|
|
|
GimpDockable *dockable = GIMP_DOCKABLE (widget);
|
|
|
|
|
|
|
|
if (dockable->title_window)
|
|
|
|
{
|
|
|
|
gdk_window_set_user_data (dockable->title_window, NULL);
|
|
|
|
gdk_window_destroy (dockable->title_window);
|
|
|
|
dockable->title_window = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_dockable_map (GtkWidget *widget)
|
|
|
|
{
|
|
|
|
GimpDockable *dockable = GIMP_DOCKABLE (widget);
|
|
|
|
|
|
|
|
GTK_WIDGET_CLASS (parent_class)->map (widget);
|
|
|
|
|
|
|
|
if (dockable->title_window)
|
|
|
|
gdk_window_show (dockable->title_window);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_dockable_unmap (GtkWidget *widget)
|
|
|
|
{
|
|
|
|
GimpDockable *dockable = GIMP_DOCKABLE (widget);
|
|
|
|
|
|
|
|
if (dockable->title_window)
|
|
|
|
gdk_window_hide (dockable->title_window);
|
|
|
|
|
|
|
|
GTK_WIDGET_CLASS (parent_class)->unmap (widget);
|
|
|
|
}
|
|
|
|
|
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 void
|
|
|
|
gimp_dockable_drag_leave (GtkWidget *widget,
|
|
|
|
GdkDragContext *context,
|
|
|
|
guint time)
|
|
|
|
{
|
|
|
|
gimp_highlight_widget (widget, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gimp_dockable_drag_motion (GtkWidget *widget,
|
|
|
|
GdkDragContext *context,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
guint time)
|
|
|
|
{
|
|
|
|
GimpDockable *dockable = GIMP_DOCKABLE (widget);
|
|
|
|
gboolean other_will_handle = FALSE;
|
|
|
|
|
|
|
|
other_will_handle = gimp_paned_box_will_handle_drag (dockable->drag_handler,
|
|
|
|
widget,
|
|
|
|
context,
|
|
|
|
x, y,
|
|
|
|
time);
|
|
|
|
|
|
|
|
gdk_drag_status (context, other_will_handle ? 0 : GDK_ACTION_MOVE, time);
|
|
|
|
gimp_highlight_widget (widget, ! other_will_handle);
|
|
|
|
return other_will_handle ? FALSE : TRUE;
|
|
|
|
}
|
|
|
|
|
2003-10-06 01:26:21 +08:00
|
|
|
static gboolean
|
|
|
|
gimp_dockable_drag_drop (GtkWidget *widget,
|
|
|
|
GdkDragContext *context,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
guint time)
|
|
|
|
{
|
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
|
|
|
GimpDockable *dockable = GIMP_DOCKABLE (widget);
|
|
|
|
gboolean handled = FALSE;
|
|
|
|
|
|
|
|
if (gimp_paned_box_will_handle_drag (dockable->drag_handler,
|
|
|
|
widget,
|
|
|
|
context,
|
|
|
|
x, y,
|
|
|
|
time))
|
|
|
|
{
|
|
|
|
/* Make event fall through to the drag handler */
|
|
|
|
handled = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
handled =
|
|
|
|
gimp_dockbook_drop_dockable (GIMP_DOCKABLE (widget)->dockbook,
|
|
|
|
gtk_drag_get_source_widget (context));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We must call gtk_drag_finish() ourselves */
|
|
|
|
if (handled)
|
|
|
|
gtk_drag_finish (context, TRUE, TRUE, time);
|
|
|
|
|
|
|
|
return handled;
|
2003-04-12 00:51:49 +08:00
|
|
|
}
|
|
|
|
|
2001-08-04 03:43:19 +08:00
|
|
|
static void
|
|
|
|
gimp_dockable_style_set (GtkWidget *widget,
|
2004-09-01 05:29:30 +08:00
|
|
|
GtkStyle *prev_style)
|
2001-08-04 03:43:19 +08:00
|
|
|
{
|
2007-05-17 22:09:50 +08:00
|
|
|
GimpDockable *dockable = GIMP_DOCKABLE (widget);
|
2003-09-24 02:11:09 +08:00
|
|
|
gint content_border;
|
2001-08-04 03:43:19 +08:00
|
|
|
|
2008-03-30 07:43:39 +08:00
|
|
|
GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style);
|
2007-11-14 22:42:05 +08:00
|
|
|
|
2001-08-04 03:43:19 +08:00
|
|
|
gtk_widget_style_get (widget,
|
2005-05-28 00:51:39 +08:00
|
|
|
"content-border", &content_border,
|
2004-09-01 05:29:30 +08:00
|
|
|
NULL);
|
2001-08-04 03:43:19 +08:00
|
|
|
|
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (widget), content_border);
|
|
|
|
|
2003-09-24 02:11:09 +08:00
|
|
|
if (dockable->title_layout)
|
|
|
|
{
|
|
|
|
g_object_unref (dockable->title_layout);
|
|
|
|
dockable->title_layout = NULL;
|
|
|
|
}
|
2001-08-04 03:43:19 +08:00
|
|
|
}
|
|
|
|
|
2005-12-30 00:00:28 +08:00
|
|
|
static PangoLayout *
|
|
|
|
gimp_dockable_create_title_layout (GimpDockable *dockable,
|
|
|
|
GtkWidget *widget,
|
|
|
|
gint width)
|
|
|
|
{
|
2008-03-13 00:58:28 +08:00
|
|
|
GtkWidget *child = gtk_bin_get_child (GTK_BIN (dockable));
|
|
|
|
PangoLayout *layout;
|
|
|
|
gchar *title = NULL;
|
2005-12-30 00:00:28 +08:00
|
|
|
|
2008-03-13 00:58:28 +08:00
|
|
|
if (child)
|
|
|
|
title = gimp_docked_get_title (GIMP_DOCKED (child));
|
2005-12-30 00:00:28 +08:00
|
|
|
|
|
|
|
layout = gtk_widget_create_pango_layout (widget,
|
|
|
|
title ? title : dockable->blurb);
|
|
|
|
g_free (title);
|
|
|
|
|
2008-03-19 17:29:30 +08:00
|
|
|
gimp_pango_layout_set_weight (layout, PANGO_WEIGHT_SEMIBOLD);
|
2008-03-08 22:33:16 +08:00
|
|
|
|
2005-12-30 00:00:28 +08:00
|
|
|
if (width > 0)
|
|
|
|
{
|
|
|
|
pango_layout_set_width (layout, PANGO_SCALE * width);
|
|
|
|
pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
|
|
|
|
}
|
|
|
|
|
|
|
|
return layout;
|
|
|
|
}
|
|
|
|
|
2003-09-22 03:35:54 +08:00
|
|
|
static gboolean
|
|
|
|
gimp_dockable_expose_event (GtkWidget *widget,
|
|
|
|
GdkEventExpose *event)
|
|
|
|
{
|
2009-10-18 02:20:39 +08:00
|
|
|
if (gtk_widget_is_drawable (widget))
|
2003-09-22 03:35:54 +08:00
|
|
|
{
|
2007-05-17 22:09:50 +08:00
|
|
|
GimpDockable *dockable = GIMP_DOCKABLE (widget);
|
2008-06-28 23:50:27 +08:00
|
|
|
GtkStyle *style = gtk_widget_get_style (widget);
|
2003-09-22 03:35:54 +08:00
|
|
|
GdkRectangle title_area;
|
|
|
|
GdkRectangle expose_area;
|
|
|
|
|
2003-10-06 01:26:21 +08:00
|
|
|
gimp_dockable_get_title_area (dockable, &title_area);
|
2003-09-24 02:11:09 +08:00
|
|
|
|
2003-09-22 03:35:54 +08:00
|
|
|
if (gdk_rectangle_intersect (&title_area, &event->area, &expose_area))
|
|
|
|
{
|
2003-09-24 02:11:09 +08:00
|
|
|
gint layout_width;
|
|
|
|
gint layout_height;
|
|
|
|
gint text_x;
|
|
|
|
gint text_y;
|
2003-09-22 03:35:54 +08:00
|
|
|
|
2005-01-18 23:18:35 +08:00
|
|
|
if (dockable->blink_counter & 1)
|
|
|
|
{
|
2009-03-23 00:35:53 +08:00
|
|
|
gtk_paint_box (style, gtk_widget_get_window (widget),
|
2005-01-18 23:18:35 +08:00
|
|
|
GTK_STATE_SELECTED, GTK_SHADOW_NONE,
|
|
|
|
&expose_area, widget, "",
|
|
|
|
title_area.x, title_area.y,
|
|
|
|
title_area.width, title_area.height);
|
|
|
|
}
|
|
|
|
|
2003-10-21 22:49:12 +08:00
|
|
|
if (! dockable->title_layout)
|
2003-09-24 02:11:09 +08:00
|
|
|
{
|
2005-12-29 10:27:32 +08:00
|
|
|
dockable->title_layout =
|
2005-12-30 00:00:28 +08:00
|
|
|
gimp_dockable_create_title_layout (dockable, widget,
|
|
|
|
title_area.width);
|
2003-09-24 02:11:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
pango_layout_get_pixel_size (dockable->title_layout,
|
|
|
|
&layout_width, &layout_height);
|
2003-09-22 03:35:54 +08:00
|
|
|
|
|
|
|
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
|
|
|
|
{
|
|
|
|
text_x = title_area.x;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
text_x = title_area.x + title_area.width - layout_width;
|
|
|
|
}
|
|
|
|
|
|
|
|
text_y = title_area.y + (title_area.height - layout_height) / 2;
|
|
|
|
|
2009-03-23 00:35:53 +08:00
|
|
|
gtk_paint_layout (style, gtk_widget_get_window (widget),
|
2005-01-19 04:03:11 +08:00
|
|
|
(dockable->blink_counter & 1) ?
|
2009-10-18 02:20:39 +08:00
|
|
|
GTK_STATE_SELECTED : gtk_widget_get_state (widget),
|
|
|
|
TRUE,
|
2003-09-22 03:35:54 +08:00
|
|
|
&expose_area, widget, NULL,
|
2003-09-24 02:11:09 +08:00
|
|
|
text_x, text_y, dockable->title_layout);
|
2003-09-22 03:35:54 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
|
|
|
|
}
|
|
|
|
|
2003-12-12 03:34:37 +08:00
|
|
|
static gboolean
|
2005-12-29 11:12:26 +08:00
|
|
|
gimp_dockable_button_press (GtkWidget *widget,
|
|
|
|
GdkEventButton *event)
|
2003-12-12 03:34:37 +08:00
|
|
|
{
|
2005-12-29 11:12:26 +08:00
|
|
|
GimpDockable *dockable = GIMP_DOCKABLE (widget);
|
|
|
|
|
2005-12-29 12:28:41 +08:00
|
|
|
/* stop processing of events not coming from the title event window */
|
|
|
|
if (event->window != dockable->title_window)
|
|
|
|
return TRUE;
|
|
|
|
|
2005-12-29 12:45:41 +08:00
|
|
|
dockable->drag_x = event->x;
|
2005-12-29 11:12:26 +08:00
|
|
|
|
2005-12-29 12:28:41 +08:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gimp_dockable_button_release (GtkWidget *widget)
|
|
|
|
{
|
|
|
|
GimpDockable *dockable = GIMP_DOCKABLE (widget);
|
|
|
|
|
2005-12-30 09:37:35 +08:00
|
|
|
dockable->drag_x = GIMP_DOCKABLE_DRAG_OFFSET;
|
2005-12-29 12:28:41 +08:00
|
|
|
|
|
|
|
return FALSE;
|
2003-12-12 03:34:37 +08:00
|
|
|
}
|
|
|
|
|
2003-09-24 00:17:25 +08:00
|
|
|
static gboolean
|
|
|
|
gimp_dockable_popup_menu (GtkWidget *widget)
|
|
|
|
{
|
|
|
|
return gimp_dockable_show_menu (GIMP_DOCKABLE (widget));
|
|
|
|
}
|
|
|
|
|
2003-10-21 22:49:12 +08:00
|
|
|
static void
|
|
|
|
gimp_dockable_add (GtkContainer *container,
|
|
|
|
GtkWidget *widget)
|
|
|
|
{
|
2005-03-26 05:58:48 +08:00
|
|
|
GimpDockable *dockable;
|
|
|
|
|
2008-03-13 00:58:28 +08:00
|
|
|
g_return_if_fail (gtk_bin_get_child (GTK_BIN (container)) == NULL);
|
2003-10-21 22:49:12 +08:00
|
|
|
|
|
|
|
GTK_CONTAINER_CLASS (parent_class)->add (container, widget);
|
|
|
|
|
2005-05-28 00:51:39 +08:00
|
|
|
g_signal_connect (widget, "title-changed",
|
2003-10-21 22:49:12 +08:00
|
|
|
G_CALLBACK (gimp_dockable_title_changed),
|
|
|
|
container);
|
2005-03-26 05:58:48 +08:00
|
|
|
|
|
|
|
/* not all tab styles are supported by all children */
|
|
|
|
dockable = GIMP_DOCKABLE (container);
|
|
|
|
gimp_dockable_set_tab_style (dockable, dockable->tab_style);
|
2003-10-21 22:49:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_dockable_remove (GtkContainer *container,
|
|
|
|
GtkWidget *widget)
|
|
|
|
{
|
2008-03-13 00:58:28 +08:00
|
|
|
g_return_if_fail (gtk_bin_get_child (GTK_BIN (container)) == widget);
|
2003-10-21 22:49:12 +08:00
|
|
|
|
|
|
|
g_signal_handlers_disconnect_by_func (widget,
|
|
|
|
gimp_dockable_title_changed,
|
|
|
|
container);
|
|
|
|
|
|
|
|
GTK_CONTAINER_CLASS (parent_class)->remove (container, widget);
|
|
|
|
}
|
|
|
|
|
2003-10-11 05:24:12 +08:00
|
|
|
static GType
|
|
|
|
gimp_dockable_child_type (GtkContainer *container)
|
|
|
|
{
|
2008-03-13 00:58:28 +08:00
|
|
|
if (gtk_bin_get_child (GTK_BIN (container)))
|
2003-10-11 05:24:12 +08:00
|
|
|
return G_TYPE_NONE;
|
|
|
|
|
|
|
|
return GIMP_TYPE_DOCKED;
|
|
|
|
}
|
|
|
|
|
2003-09-22 03:35:54 +08:00
|
|
|
static void
|
|
|
|
gimp_dockable_forall (GtkContainer *container,
|
|
|
|
gboolean include_internals,
|
|
|
|
GtkCallback callback,
|
|
|
|
gpointer callback_data)
|
|
|
|
{
|
|
|
|
GimpDockable *dockable = GIMP_DOCKABLE (container);
|
|
|
|
|
|
|
|
if (include_internals)
|
|
|
|
{
|
|
|
|
if (dockable->menu_button)
|
|
|
|
(* callback) (dockable->menu_button, callback_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
GTK_CONTAINER_CLASS (parent_class)->forall (container, include_internals,
|
|
|
|
callback, callback_data);
|
|
|
|
}
|
|
|
|
|
2008-08-22 16:57:11 +08:00
|
|
|
static GtkWidget *
|
|
|
|
gimp_dockable_get_icon (GimpDockable *dockable,
|
|
|
|
GtkIconSize size)
|
|
|
|
{
|
|
|
|
GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (dockable));
|
|
|
|
GtkIconTheme *theme = gtk_icon_theme_get_for_screen (screen);
|
|
|
|
|
|
|
|
if (gtk_icon_theme_has_icon (theme, dockable->stock_id))
|
|
|
|
{
|
|
|
|
return gtk_image_new_from_icon_name (dockable->stock_id, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
return gtk_image_new_from_stock (dockable->stock_id, size);
|
|
|
|
}
|
|
|
|
|
2008-03-11 00:01:48 +08:00
|
|
|
static GtkWidget *
|
|
|
|
gimp_dockable_get_tab_widget_internal (GimpDockable *dockable,
|
|
|
|
GimpContext *context,
|
|
|
|
GimpTabStyle tab_style,
|
|
|
|
GtkIconSize size,
|
|
|
|
gboolean dnd)
|
|
|
|
{
|
|
|
|
GtkWidget *tab_widget = NULL;
|
|
|
|
GtkWidget *label = NULL;
|
|
|
|
GtkWidget *icon = NULL;
|
|
|
|
|
|
|
|
switch (tab_style)
|
|
|
|
{
|
|
|
|
case GIMP_TAB_STYLE_NAME:
|
|
|
|
case GIMP_TAB_STYLE_ICON_NAME:
|
|
|
|
case GIMP_TAB_STYLE_PREVIEW_NAME:
|
|
|
|
label = gtk_label_new (dockable->name);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_TAB_STYLE_BLURB:
|
|
|
|
case GIMP_TAB_STYLE_ICON_BLURB:
|
|
|
|
case GIMP_TAB_STYLE_PREVIEW_BLURB:
|
|
|
|
label = gtk_label_new (dockable->blurb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (tab_style)
|
|
|
|
{
|
|
|
|
case GIMP_TAB_STYLE_ICON:
|
|
|
|
case GIMP_TAB_STYLE_ICON_NAME:
|
|
|
|
case GIMP_TAB_STYLE_ICON_BLURB:
|
2008-08-22 16:57:11 +08:00
|
|
|
icon = gimp_dockable_get_icon (dockable, size);
|
2008-03-11 00:01:48 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_TAB_STYLE_PREVIEW:
|
|
|
|
case GIMP_TAB_STYLE_PREVIEW_NAME:
|
|
|
|
case GIMP_TAB_STYLE_PREVIEW_BLURB:
|
2008-03-13 00:58:28 +08:00
|
|
|
{
|
|
|
|
GtkWidget *child = gtk_bin_get_child (GTK_BIN (dockable));
|
2008-03-11 00:01:48 +08:00
|
|
|
|
2008-03-13 00:58:28 +08:00
|
|
|
if (child)
|
|
|
|
icon = gimp_docked_get_preview (GIMP_DOCKED (child),
|
|
|
|
context, size);
|
|
|
|
|
|
|
|
if (! icon)
|
2008-08-22 16:57:11 +08:00
|
|
|
icon = gimp_dockable_get_icon (dockable, size);
|
2008-03-13 00:58:28 +08:00
|
|
|
}
|
2008-03-11 00:01:48 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (label && dnd)
|
|
|
|
gimp_label_set_attributes (GTK_LABEL (label),
|
|
|
|
PANGO_ATTR_WEIGHT, PANGO_WEIGHT_SEMIBOLD,
|
|
|
|
-1);
|
|
|
|
|
|
|
|
switch (tab_style)
|
|
|
|
{
|
|
|
|
case GIMP_TAB_STYLE_ICON:
|
|
|
|
case GIMP_TAB_STYLE_PREVIEW:
|
|
|
|
tab_widget = icon;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_TAB_STYLE_NAME:
|
|
|
|
case GIMP_TAB_STYLE_BLURB:
|
|
|
|
tab_widget = label;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_TAB_STYLE_ICON_NAME:
|
|
|
|
case GIMP_TAB_STYLE_ICON_BLURB:
|
|
|
|
case GIMP_TAB_STYLE_PREVIEW_NAME:
|
|
|
|
case GIMP_TAB_STYLE_PREVIEW_BLURB:
|
|
|
|
tab_widget = gtk_hbox_new (FALSE, dnd ? 6 : 2);
|
|
|
|
|
|
|
|
gtk_box_pack_start (GTK_BOX (tab_widget), icon, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (icon);
|
|
|
|
|
|
|
|
gtk_box_pack_start (GTK_BOX (tab_widget), label, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (label);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return tab_widget;
|
|
|
|
}
|
2005-01-18 23:18:35 +08:00
|
|
|
|
|
|
|
/* public functions */
|
|
|
|
|
2001-04-07 22:44:12 +08:00
|
|
|
GtkWidget *
|
2003-10-11 05:24:12 +08:00
|
|
|
gimp_dockable_new (const gchar *name,
|
2004-09-01 05:29:30 +08:00
|
|
|
const gchar *blurb,
|
2003-10-11 05:24:12 +08:00
|
|
|
const gchar *stock_id,
|
|
|
|
const gchar *help_id)
|
2001-04-07 22:44:12 +08:00
|
|
|
{
|
2001-04-11 00:03:40 +08:00
|
|
|
GimpDockable *dockable;
|
|
|
|
|
2001-04-07 22:44:12 +08:00
|
|
|
g_return_val_if_fail (name != NULL, NULL);
|
2003-07-08 23:07:56 +08:00
|
|
|
g_return_val_if_fail (stock_id != NULL, NULL);
|
2003-08-25 22:18:33 +08:00
|
|
|
g_return_val_if_fail (help_id != NULL, NULL);
|
2001-04-11 00:03:40 +08:00
|
|
|
|
2001-08-10 22:41:39 +08:00
|
|
|
dockable = g_object_new (GIMP_TYPE_DOCKABLE, NULL);
|
2001-04-11 00:03:40 +08:00
|
|
|
|
2003-07-08 23:07:56 +08:00
|
|
|
dockable->name = g_strdup (name);
|
|
|
|
dockable->stock_id = g_strdup (stock_id);
|
2003-08-25 22:18:33 +08:00
|
|
|
dockable->help_id = g_strdup (help_id);
|
2001-04-11 00:03:40 +08:00
|
|
|
|
2003-10-01 02:50:55 +08:00
|
|
|
if (blurb)
|
|
|
|
dockable->blurb = g_strdup (blurb);
|
|
|
|
else
|
|
|
|
dockable->blurb = dockable->name;
|
|
|
|
|
2003-08-26 09:30:05 +08:00
|
|
|
gimp_help_set_help_data (GTK_WIDGET (dockable), NULL, help_id);
|
|
|
|
|
2001-04-11 00:03:40 +08:00
|
|
|
return GTK_WIDGET (dockable);
|
|
|
|
}
|
|
|
|
|
2008-05-20 05:11:03 +08:00
|
|
|
|
2003-10-10 23:59:12 +08:00
|
|
|
void
|
|
|
|
gimp_dockable_set_aux_info (GimpDockable *dockable,
|
|
|
|
GList *aux_info)
|
|
|
|
{
|
2008-03-13 00:58:28 +08:00
|
|
|
GtkWidget *child;
|
|
|
|
|
2003-10-10 23:59:12 +08:00
|
|
|
g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
|
|
|
|
|
2008-03-13 00:58:28 +08:00
|
|
|
child = gtk_bin_get_child (GTK_BIN (dockable));
|
|
|
|
|
|
|
|
if (child)
|
|
|
|
gimp_docked_set_aux_info (GIMP_DOCKED (child), aux_info);
|
2003-10-10 23:59:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
GList *
|
|
|
|
gimp_dockable_get_aux_info (GimpDockable *dockable)
|
|
|
|
{
|
2008-03-13 00:58:28 +08:00
|
|
|
GtkWidget *child;
|
|
|
|
|
2003-10-10 23:59:12 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), NULL);
|
|
|
|
|
2008-03-13 00:58:28 +08:00
|
|
|
child = gtk_bin_get_child (GTK_BIN (dockable));
|
2003-10-11 05:24:12 +08:00
|
|
|
|
2008-03-13 00:58:28 +08:00
|
|
|
if (child)
|
|
|
|
return gimp_docked_get_aux_info (GIMP_DOCKED (child));
|
2003-10-11 05:24:12 +08:00
|
|
|
|
|
|
|
return NULL;
|
2003-10-10 23:59:12 +08:00
|
|
|
}
|
|
|
|
|
2008-05-20 05:11:03 +08:00
|
|
|
|
|
|
|
void
|
|
|
|
gimp_dockable_set_locked (GimpDockable *dockable,
|
|
|
|
gboolean lock)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
|
|
|
|
|
|
|
|
if (dockable->locked != lock)
|
|
|
|
{
|
|
|
|
dockable->locked = lock ? TRUE : FALSE;
|
|
|
|
|
|
|
|
gimp_dockable_cursor_setup (dockable);
|
|
|
|
|
|
|
|
g_object_notify (G_OBJECT (dockable), "locked");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
gimp_dockable_is_locked (GimpDockable *dockable)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), FALSE);
|
|
|
|
|
|
|
|
return dockable->locked;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-06-01 20:31:44 +08:00
|
|
|
void
|
|
|
|
gimp_dockable_set_tab_style (GimpDockable *dockable,
|
|
|
|
GimpTabStyle tab_style)
|
|
|
|
{
|
2008-03-13 00:58:28 +08:00
|
|
|
GtkWidget *child;
|
|
|
|
|
2004-06-01 20:31:44 +08:00
|
|
|
g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
|
|
|
|
|
2008-03-13 00:58:28 +08:00
|
|
|
child = gtk_bin_get_child (GTK_BIN (dockable));
|
|
|
|
|
|
|
|
if (child && ! GIMP_DOCKED_GET_INTERFACE (child)->get_preview)
|
2004-06-01 20:31:44 +08:00
|
|
|
{
|
|
|
|
switch (tab_style)
|
|
|
|
{
|
|
|
|
case GIMP_TAB_STYLE_PREVIEW:
|
|
|
|
tab_style = GIMP_TAB_STYLE_ICON;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_TAB_STYLE_PREVIEW_NAME:
|
|
|
|
tab_style = GIMP_TAB_STYLE_ICON_BLURB;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_TAB_STYLE_PREVIEW_BLURB:
|
|
|
|
tab_style = GIMP_TAB_STYLE_ICON_BLURB;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dockable->tab_style = tab_style;
|
|
|
|
}
|
|
|
|
|
2001-04-11 00:03:40 +08:00
|
|
|
GtkWidget *
|
|
|
|
gimp_dockable_get_tab_widget (GimpDockable *dockable,
|
2003-07-08 23:07:56 +08:00
|
|
|
GimpContext *context,
|
|
|
|
GimpTabStyle tab_style,
|
|
|
|
GtkIconSize size)
|
2001-08-04 03:43:19 +08:00
|
|
|
{
|
2003-10-11 05:24:12 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), NULL);
|
|
|
|
g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
|
|
|
|
|
2008-03-11 00:01:48 +08:00
|
|
|
return gimp_dockable_get_tab_widget_internal (dockable, context,
|
|
|
|
tab_style, size, FALSE);
|
|
|
|
}
|
2003-07-08 23:07:56 +08:00
|
|
|
|
2008-03-11 00:01:48 +08:00
|
|
|
GtkWidget *
|
|
|
|
gimp_dockable_get_drag_widget (GimpDockable *dockable)
|
|
|
|
{
|
|
|
|
GtkWidget *frame;
|
|
|
|
GtkWidget *widget;
|
2003-07-08 23:07:56 +08:00
|
|
|
|
2008-03-11 00:01:48 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), NULL);
|
2003-07-08 23:07:56 +08:00
|
|
|
|
2008-03-11 00:01:48 +08:00
|
|
|
frame = gtk_frame_new (NULL);
|
|
|
|
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
|
2003-07-08 23:07:56 +08:00
|
|
|
|
2008-03-11 00:01:48 +08:00
|
|
|
widget = gimp_dockable_get_tab_widget_internal (dockable,
|
|
|
|
dockable->context,
|
|
|
|
GIMP_TAB_STYLE_ICON_BLURB,
|
|
|
|
GTK_ICON_SIZE_DND,
|
|
|
|
TRUE);
|
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (widget), 6);
|
|
|
|
gtk_container_add (GTK_CONTAINER (frame), widget);
|
|
|
|
gtk_widget_show (widget);
|
2002-05-10 22:50:27 +08:00
|
|
|
|
2008-03-11 00:01:48 +08:00
|
|
|
return frame;
|
2001-04-07 22:44:12 +08:00
|
|
|
}
|
2001-04-24 00:58:18 +08:00
|
|
|
|
2003-10-11 05:24:12 +08:00
|
|
|
void
|
|
|
|
gimp_dockable_set_context (GimpDockable *dockable,
|
|
|
|
GimpContext *context)
|
2001-04-24 00:58:18 +08:00
|
|
|
{
|
2003-10-11 05:24:12 +08:00
|
|
|
g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
|
|
|
|
g_return_if_fail (context == NULL || GIMP_IS_CONTEXT (context));
|
|
|
|
|
2004-05-23 18:04:41 +08:00
|
|
|
if (context != dockable->context)
|
2003-10-11 05:24:12 +08:00
|
|
|
{
|
2008-03-13 00:58:28 +08:00
|
|
|
GtkWidget *child = gtk_bin_get_child (GTK_BIN (dockable));
|
|
|
|
|
|
|
|
if (child)
|
|
|
|
gimp_docked_set_context (GIMP_DOCKED (child), context);
|
2001-08-04 03:43:19 +08:00
|
|
|
|
2004-05-23 18:04:41 +08:00
|
|
|
dockable->context = context;
|
|
|
|
}
|
2001-04-24 00:58:18 +08:00
|
|
|
}
|
2003-09-22 03:35:54 +08:00
|
|
|
|
2004-04-29 20:52:29 +08:00
|
|
|
GimpUIManager *
|
|
|
|
gimp_dockable_get_menu (GimpDockable *dockable,
|
|
|
|
const gchar **ui_path,
|
|
|
|
gpointer *popup_data)
|
2003-09-22 03:35:54 +08:00
|
|
|
{
|
2008-03-13 00:58:28 +08:00
|
|
|
GtkWidget *child;
|
|
|
|
|
2003-10-11 05:24:12 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), NULL);
|
2004-04-29 20:52:29 +08:00
|
|
|
g_return_val_if_fail (ui_path != NULL, NULL);
|
2004-04-23 01:14:22 +08:00
|
|
|
g_return_val_if_fail (popup_data != NULL, NULL);
|
2003-10-11 05:24:12 +08:00
|
|
|
|
2008-03-13 00:58:28 +08:00
|
|
|
child = gtk_bin_get_child (GTK_BIN (dockable));
|
|
|
|
|
|
|
|
if (child)
|
|
|
|
return gimp_docked_get_menu (GIMP_DOCKED (child), ui_path, popup_data);
|
2003-09-22 03:35:54 +08:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
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_dockable_set_drag_handler:
|
|
|
|
* @dockable:
|
|
|
|
* @handler:
|
|
|
|
*
|
|
|
|
* Set a drag handler that will be asked if it will handle drag events
|
|
|
|
* before the dockable handles the event itself.
|
|
|
|
**/
|
|
|
|
void
|
|
|
|
gimp_dockable_set_drag_handler (GimpDockable *dockable,
|
|
|
|
GimpPanedBox *handler)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
|
|
|
|
|
|
|
|
dockable->drag_handler = handler;
|
|
|
|
}
|
|
|
|
|
2003-10-11 05:24:12 +08:00
|
|
|
void
|
|
|
|
gimp_dockable_detach (GimpDockable *dockable)
|
|
|
|
{
|
2009-12-06 04:20:18 +08:00
|
|
|
GimpDockWindow *src_dock_window = NULL;
|
|
|
|
GimpDock *src_dock = NULL;
|
|
|
|
GtkWidget *dock = NULL;
|
|
|
|
GimpDockWindow *dock_window = NULL;
|
|
|
|
GtkWidget *dockbook = NULL;
|
2003-10-11 05:24:12 +08:00
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
|
|
|
|
g_return_if_fail (GIMP_IS_DOCKBOOK (dockable->dockbook));
|
|
|
|
|
2009-09-13 22:30:09 +08:00
|
|
|
src_dock = gimp_dockbook_get_dock (dockable->dockbook);
|
2009-12-06 04:20:18 +08:00
|
|
|
src_dock_window = gimp_dock_window_from_dock (src_dock);
|
2003-10-11 05:24:12 +08:00
|
|
|
|
2009-12-20 21:41:02 +08:00
|
|
|
dock = gimp_dialog_factory_dock_with_window_new (global_dock_window_factory,
|
2009-12-02 04:42:24 +08:00
|
|
|
gtk_widget_get_screen (GTK_WIDGET (dockable)));
|
2009-09-26 22:21:10 +08:00
|
|
|
dock_window = gimp_dock_window_from_dock (GIMP_DOCK (dock));
|
|
|
|
gtk_window_set_position (GTK_WINDOW (dock_window), GTK_WIN_POS_MOUSE);
|
2009-12-11 02:26:23 +08:00
|
|
|
if (src_dock_window)
|
|
|
|
gimp_dock_window_setup (dock_window, src_dock_window);
|
2003-10-11 05:24:12 +08:00
|
|
|
|
2009-12-11 02:26:23 +08:00
|
|
|
dockbook = gimp_dockbook_new (global_menu_factory);
|
2003-10-11 05:24:12 +08:00
|
|
|
|
|
|
|
gimp_dock_add_book (GIMP_DOCK (dock), GIMP_DOCKBOOK (dockbook), 0);
|
|
|
|
|
|
|
|
g_object_ref (dockable);
|
|
|
|
|
|
|
|
gimp_dockbook_remove (dockable->dockbook, dockable);
|
|
|
|
gimp_dockbook_add (GIMP_DOCKBOOK (dockbook), dockable, 0);
|
|
|
|
|
|
|
|
g_object_unref (dockable);
|
|
|
|
|
2009-09-26 22:21:10 +08:00
|
|
|
gtk_widget_show (GTK_WIDGET (dock_window));
|
2003-10-11 05:24:12 +08:00
|
|
|
gtk_widget_show (dock);
|
|
|
|
}
|
|
|
|
|
2005-01-18 23:18:35 +08:00
|
|
|
void
|
|
|
|
gimp_dockable_blink (GimpDockable *dockable)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
|
|
|
|
|
|
|
|
if (dockable->blink_timeout_id)
|
|
|
|
g_source_remove (dockable->blink_timeout_id);
|
|
|
|
|
|
|
|
dockable->blink_timeout_id =
|
2005-12-29 07:43:53 +08:00
|
|
|
g_timeout_add (150, (GSourceFunc) gimp_dockable_blink_timeout, dockable);
|
2005-01-18 23:18:35 +08:00
|
|
|
|
|
|
|
gimp_dockable_blink_timeout (dockable);
|
|
|
|
}
|
|
|
|
|
2005-07-14 01:03:44 +08:00
|
|
|
void
|
|
|
|
gimp_dockable_blink_cancel (GimpDockable *dockable)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
|
|
|
|
|
|
|
|
if (dockable->blink_timeout_id)
|
|
|
|
{
|
|
|
|
g_source_remove (dockable->blink_timeout_id);
|
2005-12-29 07:43:53 +08:00
|
|
|
|
2005-07-14 01:03:44 +08:00
|
|
|
dockable->blink_timeout_id = 0;
|
|
|
|
dockable->blink_counter = 0;
|
2005-12-29 07:43:53 +08:00
|
|
|
|
|
|
|
gimp_dockable_clear_title_area (dockable);
|
2005-07-14 01:03:44 +08:00
|
|
|
}
|
|
|
|
}
|
2005-01-18 23:18:35 +08:00
|
|
|
|
2008-05-20 05:11:03 +08:00
|
|
|
|
2005-01-18 23:18:35 +08:00
|
|
|
/* private functions */
|
|
|
|
|
2008-05-20 05:11:03 +08:00
|
|
|
static void
|
|
|
|
gimp_dockable_cursor_setup (GimpDockable *dockable)
|
|
|
|
{
|
2009-10-18 02:20:39 +08:00
|
|
|
if (! GTK_WIDGET_REALIZED (GTK_WIDGET (dockable)))
|
2008-05-20 05:11:03 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (! dockable->title_window)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* only show a hand cursor for unlocked dockables */
|
|
|
|
|
|
|
|
if (gimp_dockable_is_locked (dockable))
|
|
|
|
{
|
|
|
|
gdk_window_set_cursor (dockable->title_window, NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (dockable));
|
|
|
|
GdkCursor *cursor;
|
|
|
|
|
|
|
|
cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
|
|
|
|
gdk_window_set_cursor (dockable->title_window, cursor);
|
|
|
|
gdk_cursor_unref (cursor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-10-11 05:24:12 +08:00
|
|
|
static void
|
|
|
|
gimp_dockable_get_title_area (GimpDockable *dockable,
|
|
|
|
GdkRectangle *area)
|
|
|
|
{
|
|
|
|
GtkWidget *widget = GTK_WIDGET (dockable);
|
2008-06-28 23:50:27 +08:00
|
|
|
gint border = gtk_container_get_border_width (GTK_CONTAINER (dockable));
|
2003-10-11 05:24:12 +08:00
|
|
|
|
|
|
|
area->x = widget->allocation.x + border;
|
|
|
|
area->y = widget->allocation.y + border;
|
|
|
|
area->width = (widget->allocation.width -
|
2005-04-22 07:30:38 +08:00
|
|
|
2 * border - dockable->menu_button->allocation.width);
|
|
|
|
area->height = dockable->menu_button->allocation.height;
|
2003-10-11 05:24:12 +08:00
|
|
|
|
|
|
|
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
|
2005-04-22 07:30:38 +08:00
|
|
|
area->x += dockable->menu_button->allocation.width;
|
2003-10-11 05:24:12 +08:00
|
|
|
}
|
|
|
|
|
2005-12-29 07:43:53 +08:00
|
|
|
static void
|
|
|
|
gimp_dockable_clear_title_area (GimpDockable *dockable)
|
|
|
|
{
|
2009-10-18 02:20:39 +08:00
|
|
|
if (gtk_widget_is_drawable (GTK_WIDGET (dockable)))
|
2005-12-29 07:43:53 +08:00
|
|
|
{
|
|
|
|
GdkRectangle area;
|
|
|
|
|
|
|
|
gimp_dockable_get_title_area (dockable, &area);
|
2005-12-30 00:00:28 +08:00
|
|
|
|
2005-12-29 07:43:53 +08:00
|
|
|
gtk_widget_queue_draw_area (GTK_WIDGET (dockable),
|
|
|
|
area.x, area.y, area.width, area.height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-09-24 00:17:25 +08:00
|
|
|
static gboolean
|
|
|
|
gimp_dockable_menu_button_press (GtkWidget *button,
|
|
|
|
GdkEventButton *bevent,
|
|
|
|
GimpDockable *dockable)
|
|
|
|
{
|
|
|
|
if (bevent->button == 1 && bevent->type == GDK_BUTTON_PRESS)
|
|
|
|
{
|
|
|
|
return gimp_dockable_show_menu (dockable);
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2003-09-22 03:35:54 +08:00
|
|
|
static void
|
|
|
|
gimp_dockable_menu_position (GtkMenu *menu,
|
|
|
|
gint *x,
|
|
|
|
gint *y,
|
|
|
|
gpointer data)
|
|
|
|
{
|
2003-09-24 04:27:12 +08:00
|
|
|
GimpDockable *dockable = GIMP_DOCKABLE (data);
|
2003-09-22 03:35:54 +08:00
|
|
|
|
2003-09-24 04:27:12 +08:00
|
|
|
gimp_button_menu_position (dockable->menu_button, menu, GTK_POS_LEFT, x, y);
|
2003-09-22 03:35:54 +08:00
|
|
|
}
|
|
|
|
|
2003-10-07 20:24:01 +08:00
|
|
|
#define GIMP_DOCKABLE_DETACH_REF_KEY "gimp-dockable-detach-ref"
|
|
|
|
|
2003-09-24 00:17:25 +08:00
|
|
|
static void
|
|
|
|
gimp_dockable_menu_end (GimpDockable *dockable)
|
2003-09-22 03:35:54 +08:00
|
|
|
{
|
2004-04-23 01:14:22 +08:00
|
|
|
GimpUIManager *dialog_ui_manager;
|
2004-04-29 20:52:29 +08:00
|
|
|
const gchar *dialog_ui_path;
|
|
|
|
gpointer dialog_popup_data;
|
2003-09-22 03:35:54 +08:00
|
|
|
|
2004-04-29 20:52:29 +08:00
|
|
|
dialog_ui_manager = gimp_dockable_get_menu (dockable,
|
|
|
|
&dialog_ui_path,
|
|
|
|
&dialog_popup_data);
|
2003-09-22 03:35:54 +08:00
|
|
|
|
2004-05-13 02:36:33 +08:00
|
|
|
if (dialog_ui_manager && dialog_ui_path)
|
2004-04-23 01:14:22 +08:00
|
|
|
{
|
2005-02-09 04:55:00 +08:00
|
|
|
GtkWidget *child_menu_widget =
|
|
|
|
gtk_ui_manager_get_widget (GTK_UI_MANAGER (dialog_ui_manager),
|
|
|
|
dialog_ui_path);
|
2004-12-01 08:13:48 +08:00
|
|
|
|
|
|
|
if (child_menu_widget)
|
|
|
|
gtk_menu_detach (GTK_MENU (child_menu_widget));
|
2004-04-23 01:14:22 +08:00
|
|
|
}
|
2003-09-22 03:35:54 +08:00
|
|
|
|
2003-10-07 20:24:01 +08:00
|
|
|
/* release gimp_dockable_show_menu()'s references */
|
|
|
|
g_object_set_data (G_OBJECT (dockable), GIMP_DOCKABLE_DETACH_REF_KEY, NULL);
|
2003-09-24 00:17:25 +08:00
|
|
|
g_object_unref (dockable);
|
2003-09-22 03:35:54 +08:00
|
|
|
}
|
|
|
|
|
2003-09-24 00:17:25 +08:00
|
|
|
static gboolean
|
|
|
|
gimp_dockable_show_menu (GimpDockable *dockable)
|
2003-09-22 03:35:54 +08:00
|
|
|
{
|
2009-09-13 22:30:09 +08:00
|
|
|
GimpUIManager *dockbook_ui_manager = gimp_dockbook_get_ui_manager (dockable->dockbook);
|
2004-05-23 18:04:41 +08:00
|
|
|
GimpUIManager *dialog_ui_manager;
|
|
|
|
const gchar *dialog_ui_path;
|
|
|
|
gpointer dialog_popup_data;
|
|
|
|
GtkWidget *parent_menu_widget;
|
|
|
|
GtkAction *parent_menu_action;
|
2003-09-24 00:17:25 +08:00
|
|
|
|
2004-04-29 20:52:29 +08:00
|
|
|
if (! dockbook_ui_manager)
|
2003-09-24 00:17:25 +08:00
|
|
|
return FALSE;
|
|
|
|
|
2004-05-23 18:04:41 +08:00
|
|
|
parent_menu_widget =
|
2005-02-09 04:55:00 +08:00
|
|
|
gtk_ui_manager_get_widget (GTK_UI_MANAGER (dockbook_ui_manager),
|
|
|
|
"/dockable-popup/dockable-menu");
|
2004-05-23 18:04:41 +08:00
|
|
|
|
|
|
|
parent_menu_action =
|
|
|
|
gtk_ui_manager_get_action (GTK_UI_MANAGER (dockbook_ui_manager),
|
|
|
|
"/dockable-popup/dockable-menu");
|
|
|
|
|
2004-12-01 08:13:48 +08:00
|
|
|
if (! parent_menu_widget || ! parent_menu_action)
|
|
|
|
return FALSE;
|
|
|
|
|
2004-04-29 20:52:29 +08:00
|
|
|
dialog_ui_manager = gimp_dockable_get_menu (dockable,
|
|
|
|
&dialog_ui_path,
|
|
|
|
&dialog_popup_data);
|
2004-04-23 01:14:22 +08:00
|
|
|
|
2004-05-13 02:36:33 +08:00
|
|
|
if (dialog_ui_manager && dialog_ui_path)
|
2004-04-23 01:14:22 +08:00
|
|
|
{
|
2004-04-30 23:29:11 +08:00
|
|
|
GtkWidget *child_menu_widget;
|
2004-04-23 01:14:22 +08:00
|
|
|
GtkAction *child_menu_action;
|
|
|
|
const gchar *label;
|
|
|
|
|
2004-04-30 23:29:11 +08:00
|
|
|
child_menu_widget =
|
2005-02-09 04:55:00 +08:00
|
|
|
gtk_ui_manager_get_widget (GTK_UI_MANAGER (dialog_ui_manager),
|
|
|
|
dialog_ui_path);
|
2004-04-23 01:14:22 +08:00
|
|
|
|
2007-07-08 20:23:44 +08:00
|
|
|
if (! child_menu_widget)
|
|
|
|
{
|
|
|
|
g_warning ("%s: UI manager '%s' has now widget at path '%s'",
|
|
|
|
G_STRFUNC, dialog_ui_manager->name, dialog_ui_path);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2004-04-23 01:14:22 +08:00
|
|
|
child_menu_action =
|
|
|
|
gtk_ui_manager_get_action (GTK_UI_MANAGER (dialog_ui_manager),
|
2004-04-29 20:52:29 +08:00
|
|
|
dialog_ui_path);
|
2004-04-23 01:14:22 +08:00
|
|
|
|
2007-07-08 20:23:44 +08:00
|
|
|
if (! child_menu_action)
|
|
|
|
{
|
|
|
|
g_warning ("%s: UI manager '%s' has no action at path '%s'",
|
|
|
|
G_STRFUNC, dialog_ui_manager->name, dialog_ui_path);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-12-01 08:13:48 +08:00
|
|
|
|
2004-04-23 01:14:22 +08:00
|
|
|
g_object_get (child_menu_action,
|
|
|
|
"label", &label,
|
|
|
|
NULL);
|
2003-09-24 00:17:25 +08:00
|
|
|
|
2004-04-23 01:14:22 +08:00
|
|
|
g_object_set (parent_menu_action,
|
|
|
|
"label", label,
|
|
|
|
"stock-id", dockable->stock_id,
|
|
|
|
"visible", TRUE,
|
|
|
|
NULL);
|
|
|
|
|
2008-08-22 16:57:11 +08:00
|
|
|
if (dockable->stock_id)
|
|
|
|
{
|
|
|
|
if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default (),
|
|
|
|
dockable->stock_id))
|
|
|
|
{
|
2009-05-25 04:29:18 +08:00
|
|
|
gtk_action_set_icon_name (parent_menu_action, dockable->stock_id);
|
2008-08-22 16:57:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-04-23 01:14:22 +08:00
|
|
|
if (! GTK_IS_MENU (child_menu_widget))
|
|
|
|
{
|
|
|
|
g_warning ("%s: child_menu_widget (%p) is not a GtkMenu",
|
|
|
|
G_STRFUNC, child_menu_widget);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2004-04-29 20:52:29 +08:00
|
|
|
/* FIXME */
|
|
|
|
{
|
2008-08-22 16:57:11 +08:00
|
|
|
GtkWidget *image = gimp_dockable_get_icon (dockable,
|
|
|
|
GTK_ICON_SIZE_MENU);
|
2004-04-29 20:52:29 +08:00
|
|
|
|
|
|
|
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (parent_menu_widget),
|
|
|
|
image);
|
|
|
|
gtk_widget_show (image);
|
|
|
|
}
|
|
|
|
|
2004-04-23 01:14:22 +08:00
|
|
|
gtk_menu_item_set_submenu (GTK_MENU_ITEM (parent_menu_widget),
|
|
|
|
child_menu_widget);
|
|
|
|
|
|
|
|
gimp_ui_manager_update (dialog_ui_manager, dialog_popup_data);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_object_set (parent_menu_action, "visible", FALSE, NULL);
|
|
|
|
}
|
2003-09-24 00:17:25 +08:00
|
|
|
|
2004-04-29 20:52:29 +08:00
|
|
|
/* an action callback may destroy both dockable and dockbook, so
|
|
|
|
* reference them for gimp_dockable_menu_end()
|
2003-09-24 00:17:25 +08:00
|
|
|
*/
|
|
|
|
g_object_ref (dockable);
|
2003-10-07 20:24:01 +08:00
|
|
|
g_object_set_data_full (G_OBJECT (dockable), GIMP_DOCKABLE_DETACH_REF_KEY,
|
|
|
|
g_object_ref (dockable->dockbook),
|
|
|
|
g_object_unref);
|
2003-09-24 00:17:25 +08:00
|
|
|
|
2004-04-23 01:14:22 +08:00
|
|
|
gimp_ui_manager_update (dockbook_ui_manager, dockable);
|
|
|
|
gimp_ui_manager_ui_popup (dockbook_ui_manager, "/dockable-popup",
|
|
|
|
GTK_WIDGET (dockable),
|
|
|
|
gimp_dockable_menu_position, dockable,
|
2008-06-20 19:08:42 +08:00
|
|
|
(GDestroyNotify) gimp_dockable_menu_end, dockable);
|
2004-04-23 01:14:22 +08:00
|
|
|
|
2003-09-24 00:17:25 +08:00
|
|
|
return TRUE;
|
2003-09-22 03:35:54 +08:00
|
|
|
}
|
2003-10-21 22:49:12 +08:00
|
|
|
|
2005-01-18 23:18:35 +08:00
|
|
|
static gboolean
|
|
|
|
gimp_dockable_blink_timeout (GimpDockable *dockable)
|
|
|
|
{
|
2005-12-29 07:43:53 +08:00
|
|
|
gimp_dockable_clear_title_area (dockable);
|
2005-01-18 23:18:35 +08:00
|
|
|
|
|
|
|
if (dockable->blink_counter++ > 3)
|
|
|
|
{
|
|
|
|
dockable->blink_timeout_id = 0;
|
|
|
|
dockable->blink_counter = 0;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2003-10-21 22:49:12 +08:00
|
|
|
static void
|
|
|
|
gimp_dockable_title_changed (GimpDocked *docked,
|
|
|
|
GimpDockable *dockable)
|
|
|
|
{
|
|
|
|
if (dockable->title_layout)
|
|
|
|
{
|
|
|
|
g_object_unref (dockable->title_layout);
|
|
|
|
dockable->title_layout = NULL;
|
|
|
|
}
|
|
|
|
|
2009-10-18 02:20:39 +08:00
|
|
|
if (gtk_widget_is_drawable (GTK_WIDGET (dockable)))
|
2003-10-21 22:49:12 +08:00
|
|
|
{
|
2005-12-29 07:51:39 +08:00
|
|
|
GdkRectangle area;
|
2003-10-21 22:49:12 +08:00
|
|
|
|
2005-12-29 07:51:39 +08:00
|
|
|
gimp_dockable_get_title_area (dockable, &area);
|
2003-10-21 22:49:12 +08:00
|
|
|
|
2009-03-23 00:35:53 +08:00
|
|
|
gdk_window_invalidate_rect (gtk_widget_get_window (GTK_WIDGET (dockable)),
|
|
|
|
&area, FALSE);
|
2003-10-21 22:49:12 +08:00
|
|
|
}
|
|
|
|
}
|