app: "You can drop dockable dialogs here" no more!
This commit removes the empty-dock-pane message, and instead highlights all empty dockable drop-target areas once a drag operation begins. Add new gimp_dockbook_{add,remove}_callback() global functions, which can be used to register a callback function to be called when a dockable drag operation begins and ends. Register such a callback in GimpPanedBox, and use it to highlight all drop areas the widget handles. Furthermore, when the widget is contained in a GtkPaned, make sure that it has a minimal size for the duration of the drag operation, so that the drop area is visible even if the widget is normally hidden.
This commit is contained in:
@ -82,6 +82,13 @@ static const GimpTabStyle gimp_tab_style_candidates[] =
|
||||
GIMP_TAB_STYLE_PREVIEW
|
||||
};
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GimpDockbookDragCallback callback;
|
||||
gpointer data;
|
||||
} GimpDockbookDragCallbackData;
|
||||
|
||||
struct _GimpDockbookPrivate
|
||||
{
|
||||
GimpDock *dock;
|
||||
@ -144,6 +151,9 @@ static void gimp_dockbook_tab_drag_source_setup (GtkWidget *w
|
||||
static void gimp_dockbook_tab_drag_begin (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GimpDockable *dockable);
|
||||
static void gimp_dockbook_tab_drag_end (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GimpDockable *dockable);
|
||||
static gboolean gimp_dockbook_tab_drag_failed (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkDragResult result,
|
||||
@ -196,6 +206,8 @@ static guint dockbook_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static const GtkTargetEntry dialog_target_table[] = { GIMP_TARGET_DIALOG };
|
||||
|
||||
static GList *drag_callbacks = NULL;
|
||||
|
||||
|
||||
static void
|
||||
gimp_dockbook_class_init (GimpDockbookClass *klass)
|
||||
@ -1173,6 +1185,9 @@ gimp_dockbook_create_tab_widget (GimpDockbook *dockbook,
|
||||
g_signal_connect_object (tab_widget, "drag-begin",
|
||||
G_CALLBACK (gimp_dockbook_tab_drag_begin),
|
||||
dockable, 0);
|
||||
g_signal_connect_object (tab_widget, "drag-end",
|
||||
G_CALLBACK (gimp_dockbook_tab_drag_end),
|
||||
dockable, 0);
|
||||
g_signal_connect_object (tab_widget, "drag-failed",
|
||||
G_CALLBACK (gimp_dockbook_tab_drag_failed),
|
||||
dockable, 0);
|
||||
@ -1180,6 +1195,9 @@ gimp_dockbook_create_tab_widget (GimpDockbook *dockbook,
|
||||
g_signal_connect_object (dockable, "drag-begin",
|
||||
G_CALLBACK (gimp_dockbook_tab_drag_begin),
|
||||
dockable, 0);
|
||||
g_signal_connect_object (dockable, "drag-end",
|
||||
G_CALLBACK (gimp_dockbook_tab_drag_end),
|
||||
dockable, 0);
|
||||
g_signal_connect_object (dockable, "drag-failed",
|
||||
G_CALLBACK (gimp_dockbook_tab_drag_failed),
|
||||
dockable, 0);
|
||||
@ -1296,6 +1314,45 @@ gimp_dockbook_drag_source_to_dockable (GtkWidget *drag_source)
|
||||
return dockable;
|
||||
}
|
||||
|
||||
void
|
||||
gimp_dockbook_add_drag_callback (GimpDockbookDragCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
GimpDockbookDragCallbackData *callback_data;
|
||||
|
||||
callback_data = g_slice_new (GimpDockbookDragCallbackData);
|
||||
|
||||
callback_data->callback = callback;
|
||||
callback_data->data = data;
|
||||
|
||||
drag_callbacks = g_list_prepend (drag_callbacks, callback_data);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_dockbook_remove_drag_callback (GimpDockbookDragCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
GList *iter;
|
||||
|
||||
iter = drag_callbacks;
|
||||
|
||||
while (iter)
|
||||
{
|
||||
GimpDockbookDragCallbackData *callback_data = iter->data;
|
||||
GList *next = g_list_next (iter);
|
||||
|
||||
if (callback_data->callback == callback &&
|
||||
callback_data->data == data)
|
||||
{
|
||||
g_slice_free (GimpDockbookDragCallbackData, callback_data);
|
||||
|
||||
drag_callbacks = g_list_delete_link (drag_callbacks, iter);
|
||||
}
|
||||
|
||||
iter = next;
|
||||
}
|
||||
}
|
||||
|
||||
/* tab DND source side */
|
||||
|
||||
static void
|
||||
@ -1364,6 +1421,7 @@ gimp_dockbook_tab_drag_begin (GtkWidget *widget,
|
||||
GtkAllocation allocation;
|
||||
GtkWidget *window;
|
||||
GtkWidget *view;
|
||||
GList *iter;
|
||||
GtkRequisition requisition;
|
||||
gint drag_x;
|
||||
gint drag_y;
|
||||
@ -1391,6 +1449,36 @@ gimp_dockbook_tab_drag_begin (GtkWidget *widget,
|
||||
|
||||
gimp_dockable_get_drag_pos (dockable, &drag_x, &drag_y);
|
||||
gtk_drag_set_icon_widget (context, window, drag_x, drag_y);
|
||||
|
||||
iter = drag_callbacks;
|
||||
|
||||
while (iter)
|
||||
{
|
||||
GimpDockbookDragCallbackData *callback_data = iter->data;
|
||||
|
||||
iter = g_list_next (iter);
|
||||
|
||||
callback_data->callback (context, TRUE, callback_data->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_dockbook_tab_drag_end (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GimpDockable *dockable)
|
||||
{
|
||||
GList *iter;
|
||||
|
||||
iter = drag_callbacks;
|
||||
|
||||
while (iter)
|
||||
{
|
||||
GimpDockbookDragCallbackData *callback_data = iter->data;
|
||||
|
||||
iter = g_list_next (iter);
|
||||
|
||||
callback_data->callback (context, FALSE, callback_data->data);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -30,6 +30,11 @@
|
||||
#define GIMP_DOCKBOOK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_DOCKBOOK, GimpDockbookClass))
|
||||
|
||||
|
||||
typedef void (* GimpDockbookDragCallback) (GdkDragContext *context,
|
||||
gboolean begin,
|
||||
gpointer data);
|
||||
|
||||
|
||||
typedef struct _GimpDockbookClass GimpDockbookClass;
|
||||
typedef struct _GimpDockbookPrivate GimpDockbookPrivate;
|
||||
|
||||
@ -59,30 +64,35 @@ struct _GimpDockbookClass
|
||||
};
|
||||
|
||||
|
||||
GType gimp_dockbook_get_type (void) G_GNUC_CONST;
|
||||
GtkWidget * gimp_dockbook_new (GimpMenuFactory *menu_factory);
|
||||
GimpDock * gimp_dockbook_get_dock (GimpDockbook *dockbook);
|
||||
void gimp_dockbook_set_dock (GimpDockbook *dockbook,
|
||||
GimpDock *dock);
|
||||
GimpUIManager * gimp_dockbook_get_ui_manager (GimpDockbook *dockbook);
|
||||
void gimp_dockbook_add (GimpDockbook *dockbook,
|
||||
GimpDockable *dockable,
|
||||
gint position);
|
||||
GtkWidget * gimp_dockbook_add_from_dialog_factory (GimpDockbook *dockbook,
|
||||
const gchar *identifiers,
|
||||
gint position);
|
||||
void gimp_dockbook_remove (GimpDockbook *dockbook,
|
||||
GimpDockable *dockable);
|
||||
void gimp_dockbook_update_with_context (GimpDockbook *dockbook,
|
||||
GimpContext *context);
|
||||
GtkWidget * gimp_dockbook_create_tab_widget (GimpDockbook *dockbook,
|
||||
GimpDockable *dockable);
|
||||
void gimp_dockbook_update_auto_tab_style (GimpDockbook *dockbook);
|
||||
gboolean gimp_dockbook_drop_dockable (GimpDockbook *dockbook,
|
||||
GtkWidget *drag_source);
|
||||
void gimp_dockbook_set_drag_handler (GimpDockbook *dockbook,
|
||||
GimpPanedBox *drag_handler);
|
||||
GimpDockable * gimp_dockbook_drag_source_to_dockable (GtkWidget *drag_source);
|
||||
GType gimp_dockbook_get_type (void) G_GNUC_CONST;
|
||||
GtkWidget * gimp_dockbook_new (GimpMenuFactory *menu_factory);
|
||||
GimpDock * gimp_dockbook_get_dock (GimpDockbook *dockbook);
|
||||
void gimp_dockbook_set_dock (GimpDockbook *dockbook,
|
||||
GimpDock *dock);
|
||||
GimpUIManager * gimp_dockbook_get_ui_manager (GimpDockbook *dockbook);
|
||||
void gimp_dockbook_add (GimpDockbook *dockbook,
|
||||
GimpDockable *dockable,
|
||||
gint position);
|
||||
GtkWidget * gimp_dockbook_add_from_dialog_factory (GimpDockbook *dockbook,
|
||||
const gchar *identifiers,
|
||||
gint position);
|
||||
void gimp_dockbook_remove (GimpDockbook *dockbook,
|
||||
GimpDockable *dockable);
|
||||
void gimp_dockbook_update_with_context (GimpDockbook *dockbook,
|
||||
GimpContext *context);
|
||||
GtkWidget * gimp_dockbook_create_tab_widget (GimpDockbook *dockbook,
|
||||
GimpDockable *dockable);
|
||||
void gimp_dockbook_update_auto_tab_style (GimpDockbook *dockbook);
|
||||
gboolean gimp_dockbook_drop_dockable (GimpDockbook *dockbook,
|
||||
GtkWidget *drag_source);
|
||||
void gimp_dockbook_set_drag_handler (GimpDockbook *dockbook,
|
||||
GimpPanedBox *drag_handler);
|
||||
GimpDockable * gimp_dockbook_drag_source_to_dockable (GtkWidget *drag_source);
|
||||
|
||||
void gimp_dockbook_add_drag_callback (GimpDockbookDragCallback callback,
|
||||
gpointer data);
|
||||
void gimp_dockbook_remove_drag_callback (GimpDockbookDragCallback callback,
|
||||
gpointer data);
|
||||
|
||||
|
||||
#endif /* __GIMP_DOCKBOOK_H__ */
|
||||
|
@ -22,8 +22,12 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#ifdef GDK_DISABLE_DEPRECATED
|
||||
#undef GDK_DISABLE_DEPRECATED
|
||||
#endif
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libgimpcolor/gimpcolor.h"
|
||||
#include "libgimpwidgets/gimpwidgets.h"
|
||||
|
||||
#include "widgets-types.h"
|
||||
@ -51,12 +55,14 @@
|
||||
* order to be inserted and get space on their own (rather than
|
||||
* inserted among others and sharing space)
|
||||
*/
|
||||
#define DROP_AREA_SIZE 6
|
||||
#define DROP_AREA_SIZE 6
|
||||
|
||||
#define INSERT_INDEX_UNUSED G_MININT
|
||||
#define DROP_HIGHLIGHT_MIN_SIZE 32
|
||||
#define DROP_HIGHLIGHT_COLOR "#215d9c"
|
||||
#define DROP_HIGHLIGHT_OPACITY_ACTIVE 1.0
|
||||
#define DROP_HIGHLIGHT_OPACITY_INACTIVE 0.5
|
||||
|
||||
#define INSTRUCTIONS_TEXT_PADDING 6
|
||||
#define INSTRUCTIONS_TEXT _("You can drop dockable dialogs here")
|
||||
#define INSERT_INDEX_UNUSED G_MININT
|
||||
|
||||
|
||||
struct _GimpPanedBoxPrivate
|
||||
@ -64,11 +70,11 @@ struct _GimpPanedBoxPrivate
|
||||
/* Widgets that are separated by panes */
|
||||
GList *widgets;
|
||||
|
||||
/* Displays INSTRUCTIONS_TEXT when there are no dockables */
|
||||
GtkWidget *instructions;
|
||||
|
||||
/* Window used for drag-and-drop output */
|
||||
GdkWindow *dnd_window;
|
||||
/* Windows used for drag-and-drop output */
|
||||
GdkWindow *dnd_windows[3];
|
||||
GdkDragContext *dnd_context;
|
||||
gint dnd_paned_position;
|
||||
gint dnd_idle_id;
|
||||
|
||||
/* The insert index to use on drop */
|
||||
gint insert_index;
|
||||
@ -103,6 +109,10 @@ static void gimp_paned_box_set_widget_drag_handler (GtkWidget *widget,
|
||||
GimpPanedBox *handler);
|
||||
static gint gimp_paned_box_get_drop_area_size (GimpPanedBox *paned_box);
|
||||
|
||||
static void gimp_paned_box_drag_callback (GdkDragContext *context,
|
||||
gboolean begin,
|
||||
GimpPanedBox *paned_box);
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GimpPanedBox, gimp_paned_box, GTK_TYPE_BOX)
|
||||
|
||||
@ -131,32 +141,15 @@ gimp_paned_box_init (GimpPanedBox *paned_box)
|
||||
{
|
||||
paned_box->p = gimp_paned_box_get_instance_private (paned_box);
|
||||
|
||||
/* Instructions label
|
||||
*
|
||||
* Size a small size request so it don't mess up dock window layouts
|
||||
* during startup; in particular, set its height request to 0 so it
|
||||
* doesn't contribute to the minimum height of the toolbox.
|
||||
*/
|
||||
paned_box->p->instructions = gtk_label_new (INSTRUCTIONS_TEXT);
|
||||
gtk_misc_set_padding (GTK_MISC (paned_box->p->instructions),
|
||||
INSTRUCTIONS_TEXT_PADDING, INSTRUCTIONS_TEXT_PADDING);
|
||||
gtk_label_set_line_wrap (GTK_LABEL (paned_box->p->instructions), TRUE);
|
||||
gtk_label_set_justify (GTK_LABEL (paned_box->p->instructions),
|
||||
GTK_JUSTIFY_CENTER);
|
||||
gtk_widget_set_size_request (paned_box->p->instructions, 1, DROP_AREA_SIZE);
|
||||
gimp_label_set_attributes (GTK_LABEL (paned_box->p->instructions),
|
||||
PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC,
|
||||
-1);
|
||||
gtk_box_pack_start (GTK_BOX (paned_box), paned_box->p->instructions,
|
||||
TRUE, TRUE, 0);
|
||||
gtk_widget_show (paned_box->p->instructions);
|
||||
|
||||
|
||||
/* Setup DND */
|
||||
gtk_drag_dest_set (GTK_WIDGET (paned_box),
|
||||
0,
|
||||
dialog_target_table, G_N_ELEMENTS (dialog_target_table),
|
||||
GDK_ACTION_MOVE);
|
||||
|
||||
gimp_dockbook_add_drag_callback (
|
||||
(GimpDockbookDragCallback) gimp_paned_box_drag_callback,
|
||||
paned_box);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -164,6 +157,13 @@ gimp_paned_box_dispose (GObject *object)
|
||||
{
|
||||
GimpPanedBox *paned_box = GIMP_PANED_BOX (object);
|
||||
|
||||
if (paned_box->p->dnd_idle_id)
|
||||
{
|
||||
g_source_remove (paned_box->p->dnd_idle_id);
|
||||
|
||||
paned_box->p->dnd_idle_id = 0;
|
||||
}
|
||||
|
||||
while (paned_box->p->widgets)
|
||||
{
|
||||
GtkWidget *widget = paned_box->p->widgets->data;
|
||||
@ -174,6 +174,10 @@ gimp_paned_box_dispose (GObject *object)
|
||||
g_object_unref (widget);
|
||||
}
|
||||
|
||||
gimp_dockbook_remove_drag_callback (
|
||||
(GimpDockbookDragCallback) gimp_paned_box_drag_callback,
|
||||
paned_box);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
@ -191,12 +195,19 @@ static void
|
||||
gimp_paned_box_unrealize (GtkWidget *widget)
|
||||
{
|
||||
GimpPanedBox *paned_box = GIMP_PANED_BOX (widget);
|
||||
gint i;
|
||||
|
||||
if (paned_box->p->dnd_window)
|
||||
for (i = 0; i < G_N_ELEMENTS (paned_box->p->dnd_windows); i++)
|
||||
{
|
||||
gdk_window_set_user_data (paned_box->p->dnd_window, NULL);
|
||||
gdk_window_destroy (paned_box->p->dnd_window);
|
||||
paned_box->p->dnd_window = NULL;
|
||||
GdkWindow *window = paned_box->p->dnd_windows[i];
|
||||
|
||||
if (window)
|
||||
{
|
||||
gdk_window_set_user_data (window, NULL);
|
||||
gdk_window_destroy (window);
|
||||
|
||||
paned_box->p->dnd_windows[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
|
||||
@ -261,24 +272,127 @@ gimp_paned_box_get_drop_area_size (GimpPanedBox *paned_box)
|
||||
return drop_area_size;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_paned_box_get_handle_drag (GimpPanedBox *paned_box,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time,
|
||||
gint *insert_index,
|
||||
GeglRectangle *area)
|
||||
{
|
||||
gint index = INSERT_INDEX_UNUSED;
|
||||
GtkAllocation allocation = { 0, };
|
||||
gint area_x = 0;
|
||||
gint area_y = 0;
|
||||
gint area_w = 0;
|
||||
gint area_h = 0;
|
||||
GtkOrientation orientation = 0;
|
||||
gint drop_area_size = gimp_paned_box_get_drop_area_size (paned_box);
|
||||
|
||||
if (gimp_paned_box_will_handle_drag (paned_box->p->drag_handler,
|
||||
GTK_WIDGET (paned_box),
|
||||
context,
|
||||
x, y,
|
||||
time))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (paned_box), &allocation);
|
||||
|
||||
/* See if we're at the edge of the dock If there are no dockables,
|
||||
* the entire paned box is a drop area
|
||||
*/
|
||||
orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (paned_box));
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
area_y = 0;
|
||||
area_h = allocation.height;
|
||||
|
||||
/* If there are no widgets, the drop area is as big as the paned
|
||||
* box
|
||||
*/
|
||||
if (! paned_box->p->widgets)
|
||||
area_w = allocation.width;
|
||||
else
|
||||
area_w = drop_area_size;
|
||||
|
||||
if (x < drop_area_size)
|
||||
{
|
||||
index = 0;
|
||||
area_x = 0;
|
||||
}
|
||||
if (x > allocation.width - drop_area_size)
|
||||
{
|
||||
index = -1;
|
||||
area_x = allocation.width - drop_area_size;
|
||||
}
|
||||
}
|
||||
else /* if (orientation = GTK_ORIENTATION_VERTICAL) */
|
||||
{
|
||||
area_x = 0;
|
||||
area_w = allocation.width;
|
||||
|
||||
/* If there are no widgets, the drop area is as big as the paned
|
||||
* box
|
||||
*/
|
||||
if (! paned_box->p->widgets)
|
||||
area_h = allocation.height;
|
||||
else
|
||||
area_h = drop_area_size;
|
||||
|
||||
if (y < drop_area_size)
|
||||
{
|
||||
index = 0;
|
||||
area_y = 0;
|
||||
}
|
||||
if (y > allocation.height - drop_area_size)
|
||||
{
|
||||
index = -1;
|
||||
area_y = allocation.height - drop_area_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (area)
|
||||
{
|
||||
area->x = allocation.x + area_x;
|
||||
area->y = allocation.y + area_y;
|
||||
area->width = area_w;
|
||||
area->height = area_h;
|
||||
}
|
||||
|
||||
if (insert_index)
|
||||
*insert_index = index;
|
||||
|
||||
return index != INSERT_INDEX_UNUSED;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_paned_box_position_drop_indicator (GimpPanedBox *paned_box,
|
||||
gint index,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height)
|
||||
gint height,
|
||||
gdouble opacity)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (paned_box);
|
||||
GtkWidget *widget = GTK_WIDGET (paned_box);
|
||||
GdkWindow *window = paned_box->p->dnd_windows[index];
|
||||
GtkStyle *style = gtk_widget_get_style (widget);
|
||||
GtkStateType state = gtk_widget_get_state (widget);
|
||||
GimpRGB bg;
|
||||
GimpRGB fg;
|
||||
GdkColor color;
|
||||
|
||||
if (! gtk_widget_is_drawable (widget))
|
||||
return;
|
||||
|
||||
/* Create or move the GdkWindow in place */
|
||||
if (! paned_box->p->dnd_window)
|
||||
if (! window)
|
||||
{
|
||||
GtkStyle *style = gtk_widget_get_style (widget);
|
||||
GtkAllocation allocation;
|
||||
GdkWindowAttr attributes;
|
||||
GtkAllocation allocation;
|
||||
GdkWindowAttr attributes;
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
@ -290,31 +404,50 @@ gimp_paned_box_position_drop_indicator (GimpPanedBox *paned_box,
|
||||
attributes.wclass = GDK_INPUT_OUTPUT;
|
||||
attributes.event_mask = gtk_widget_get_events (widget);
|
||||
|
||||
paned_box->p->dnd_window = gdk_window_new (gtk_widget_get_window (widget),
|
||||
&attributes,
|
||||
GDK_WA_X | GDK_WA_Y);
|
||||
gdk_window_set_user_data (paned_box->p->dnd_window, widget);
|
||||
window = gdk_window_new (gtk_widget_get_window (widget),
|
||||
&attributes,
|
||||
GDK_WA_X | GDK_WA_Y);
|
||||
gdk_window_set_user_data (window, widget);
|
||||
|
||||
gdk_window_set_background (paned_box->p->dnd_window,
|
||||
&style->bg[GTK_STATE_SELECTED]);
|
||||
paned_box->p->dnd_windows[index] = window;
|
||||
}
|
||||
else
|
||||
{
|
||||
gdk_window_move_resize (paned_box->p->dnd_window,
|
||||
gdk_window_move_resize (window,
|
||||
x, y,
|
||||
width, height);
|
||||
}
|
||||
|
||||
gdk_window_show (paned_box->p->dnd_window);
|
||||
gimp_rgb_set_uchar (&bg,
|
||||
style->bg[state].red >> 8,
|
||||
style->bg[state].green >> 8,
|
||||
style->bg[state].blue >> 8);
|
||||
bg.a = 1.0;
|
||||
|
||||
gimp_rgb_parse_hex (&fg, DROP_HIGHLIGHT_COLOR, -1);
|
||||
fg.a = opacity;
|
||||
|
||||
gimp_rgb_composite (&bg, &fg, GIMP_RGB_COMPOSITE_NORMAL);
|
||||
|
||||
color.red = bg.r * 0xffff;
|
||||
color.green = bg.g * 0xffff;
|
||||
color.blue = bg.b * 0xffff;
|
||||
|
||||
gdk_rgb_find_color (gtk_widget_get_colormap (widget), &color);
|
||||
|
||||
gdk_window_set_background (window, &color);
|
||||
|
||||
gdk_window_show (window);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_paned_box_hide_drop_indicator (GimpPanedBox *paned_box)
|
||||
gimp_paned_box_hide_drop_indicator (GimpPanedBox *paned_box,
|
||||
gint index)
|
||||
{
|
||||
if (! paned_box->p->dnd_window)
|
||||
if (! paned_box->p->dnd_windows[index])
|
||||
return;
|
||||
|
||||
gdk_window_hide (paned_box->p->dnd_window);
|
||||
gdk_window_hide (paned_box->p->dnd_windows[index]);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -322,7 +455,9 @@ gimp_paned_box_drag_leave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time)
|
||||
{
|
||||
gimp_paned_box_hide_drop_indicator (GIMP_PANED_BOX (widget));
|
||||
GimpPanedBox *paned_box = GIMP_PANED_BOX (widget);
|
||||
|
||||
gimp_paned_box_hide_drop_indicator (paned_box, 0);
|
||||
gimp_highlight_widget (widget, FALSE);
|
||||
}
|
||||
|
||||
@ -333,99 +468,30 @@ gimp_paned_box_drag_motion (GtkWidget *widget,
|
||||
gint y,
|
||||
guint time)
|
||||
{
|
||||
GimpPanedBox *paned_box = GIMP_PANED_BOX (widget);
|
||||
gint insert_index = INSERT_INDEX_UNUSED;
|
||||
gint dnd_window_x = 0;
|
||||
gint dnd_window_y = 0;
|
||||
gint dnd_window_w = 0;
|
||||
gint dnd_window_h = 0;
|
||||
GtkAllocation allocation = { 0, };
|
||||
GtkOrientation orientation = 0;
|
||||
gboolean handle = FALSE;
|
||||
gint drop_area_size = gimp_paned_box_get_drop_area_size (paned_box);
|
||||
GimpPanedBox *paned_box = GIMP_PANED_BOX (widget);
|
||||
gint insert_index;
|
||||
GeglRectangle area;
|
||||
gboolean handle;
|
||||
|
||||
if (gimp_paned_box_will_handle_drag (paned_box->p->drag_handler,
|
||||
widget,
|
||||
context,
|
||||
x, y,
|
||||
time))
|
||||
{
|
||||
gdk_drag_status (context, 0, time);
|
||||
gimp_highlight_widget (widget, FALSE);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
/* See if we're at the edge of the dock If there are no dockables,
|
||||
* the entire paned box is a drop area
|
||||
*/
|
||||
orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (paned_box));
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
dnd_window_y = 0;
|
||||
dnd_window_h = allocation.height;
|
||||
|
||||
/* If there are no widgets, the drop area is as big as the paned
|
||||
* box
|
||||
*/
|
||||
if (! paned_box->p->widgets)
|
||||
dnd_window_w = allocation.width;
|
||||
else
|
||||
dnd_window_w = drop_area_size;
|
||||
|
||||
if (x < drop_area_size)
|
||||
{
|
||||
insert_index = 0;
|
||||
dnd_window_x = 0;
|
||||
}
|
||||
if (x > allocation.width - drop_area_size)
|
||||
{
|
||||
insert_index = -1;
|
||||
dnd_window_x = allocation.width - drop_area_size;
|
||||
}
|
||||
}
|
||||
else /* if (orientation = GTK_ORIENTATION_VERTICAL) */
|
||||
{
|
||||
dnd_window_x = 0;
|
||||
dnd_window_w = allocation.width;
|
||||
|
||||
/* If there are no widgets, the drop area is as big as the paned
|
||||
* box
|
||||
*/
|
||||
if (! paned_box->p->widgets)
|
||||
dnd_window_h = allocation.height;
|
||||
else
|
||||
dnd_window_h = drop_area_size;
|
||||
|
||||
if (y < drop_area_size)
|
||||
{
|
||||
insert_index = 0;
|
||||
dnd_window_y = 0;
|
||||
}
|
||||
if (y > allocation.height - drop_area_size)
|
||||
{
|
||||
insert_index = -1;
|
||||
dnd_window_y = allocation.height - drop_area_size;
|
||||
}
|
||||
}
|
||||
handle = gimp_paned_box_get_handle_drag (paned_box, context, x, y, time,
|
||||
&insert_index, &area);
|
||||
|
||||
/* If we are at the edge, show a GdkWindow to communicate that a
|
||||
* drop will create a new dock column
|
||||
*/
|
||||
handle = (insert_index != INSERT_INDEX_UNUSED);
|
||||
if (handle)
|
||||
{
|
||||
gimp_paned_box_position_drop_indicator (paned_box,
|
||||
allocation.x + dnd_window_x,
|
||||
allocation.y + dnd_window_y,
|
||||
dnd_window_w,
|
||||
dnd_window_h);
|
||||
0,
|
||||
area.x,
|
||||
area.y,
|
||||
area.width,
|
||||
area.height,
|
||||
DROP_HIGHLIGHT_OPACITY_ACTIVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_paned_box_hide_drop_indicator (paned_box);
|
||||
gimp_paned_box_hide_drop_indicator (paned_box, 0);
|
||||
}
|
||||
|
||||
/* Save the insert index for drag-drop */
|
||||
@ -435,7 +501,7 @@ gimp_paned_box_drag_motion (GtkWidget *widget,
|
||||
gimp_highlight_widget (widget, handle);
|
||||
|
||||
/* Return TRUE so drag_leave() is called */
|
||||
return TRUE;
|
||||
return handle;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -472,6 +538,133 @@ gimp_paned_box_drag_drop (GtkWidget *widget,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_paned_box_drag_callback_idle (GimpPanedBox *paned_box)
|
||||
{
|
||||
GtkAllocation allocation;
|
||||
GtkOrientation orientation;
|
||||
GeglRectangle area;
|
||||
|
||||
paned_box->p->dnd_idle_id = 0;
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (paned_box), &allocation);
|
||||
orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (paned_box));
|
||||
|
||||
#define ADD_AREA(index, left, top) \
|
||||
if (gimp_paned_box_get_handle_drag ( \
|
||||
paned_box, \
|
||||
paned_box->p->dnd_context, \
|
||||
(left), (top), \
|
||||
0, \
|
||||
NULL, &area)) \
|
||||
{ \
|
||||
gimp_paned_box_position_drop_indicator ( \
|
||||
paned_box, \
|
||||
index, \
|
||||
area.x, area.y, area.width, area.height, \
|
||||
DROP_HIGHLIGHT_OPACITY_INACTIVE); \
|
||||
}
|
||||
|
||||
if (! paned_box->p->widgets)
|
||||
{
|
||||
ADD_AREA (1, allocation.width / 2, allocation.height / 2)
|
||||
}
|
||||
else if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
ADD_AREA (1, 0, allocation.height / 2)
|
||||
ADD_AREA (2, allocation.width - 1, allocation.height / 2)
|
||||
}
|
||||
else
|
||||
{
|
||||
ADD_AREA (1, allocation.width / 2, 0)
|
||||
ADD_AREA (2, allocation.width / 2, allocation.height - 1)
|
||||
}
|
||||
|
||||
#undef ADD_AREA
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_paned_box_drag_callback (GdkDragContext *context,
|
||||
gboolean begin,
|
||||
GimpPanedBox *paned_box)
|
||||
{
|
||||
GtkWidget *paned;
|
||||
gint position;
|
||||
|
||||
if (! gtk_widget_get_sensitive (GTK_WIDGET (paned_box)))
|
||||
return;
|
||||
|
||||
paned = gtk_widget_get_ancestor (GTK_WIDGET (paned_box),
|
||||
GTK_TYPE_PANED);
|
||||
|
||||
if (begin)
|
||||
{
|
||||
paned_box->p->dnd_context = context;
|
||||
|
||||
if (paned)
|
||||
{
|
||||
GtkAllocation allocation;
|
||||
|
||||
gtk_widget_get_allocation (paned, &allocation);
|
||||
|
||||
position = gtk_paned_get_position (GTK_PANED (paned));
|
||||
|
||||
paned_box->p->dnd_paned_position = position;
|
||||
|
||||
if (position < 0)
|
||||
{
|
||||
position = 0;
|
||||
}
|
||||
else if (gtk_widget_is_ancestor (
|
||||
GTK_WIDGET (paned_box),
|
||||
gtk_paned_get_child2 (GTK_PANED (paned))))
|
||||
{
|
||||
position = allocation.width - position;
|
||||
}
|
||||
|
||||
if (position < DROP_HIGHLIGHT_MIN_SIZE)
|
||||
{
|
||||
position = DROP_HIGHLIGHT_MIN_SIZE;
|
||||
|
||||
if (gtk_widget_is_ancestor (
|
||||
GTK_WIDGET (paned_box),
|
||||
gtk_paned_get_child2 (GTK_PANED (paned))))
|
||||
{
|
||||
position = allocation.width - position;
|
||||
}
|
||||
|
||||
gtk_paned_set_position (GTK_PANED (paned), position);
|
||||
}
|
||||
}
|
||||
|
||||
paned_box->p->dnd_idle_id = g_idle_add (
|
||||
(GSourceFunc) gimp_paned_box_drag_callback_idle,
|
||||
paned_box);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (paned_box->p->dnd_idle_id)
|
||||
{
|
||||
g_source_remove (paned_box->p->dnd_idle_id);
|
||||
|
||||
paned_box->p->dnd_idle_id = 0;
|
||||
}
|
||||
|
||||
paned_box->p->dnd_context = NULL;
|
||||
|
||||
gimp_paned_box_hide_drop_indicator (paned_box, 1);
|
||||
gimp_paned_box_hide_drop_indicator (paned_box, 2);
|
||||
|
||||
if (paned)
|
||||
{
|
||||
gtk_paned_set_position (GTK_PANED (paned),
|
||||
paned_box->p->dnd_paned_position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GtkWidget *
|
||||
gimp_paned_box_new (gboolean homogeneous,
|
||||
@ -537,9 +730,6 @@ gimp_paned_box_add_widget (GimpPanedBox *paned_box,
|
||||
/* Insert into the GtkPaned hierarchy */
|
||||
if (old_length == 0)
|
||||
{
|
||||
/* A widget is added, hide the instructions */
|
||||
gtk_widget_hide (paned_box->p->instructions);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (paned_box), widget, TRUE, TRUE, 0);
|
||||
}
|
||||
else
|
||||
@ -647,9 +837,6 @@ gimp_paned_box_remove_widget (GimpPanedBox *paned_box,
|
||||
*/
|
||||
if (gtk_widget_get_parent (widget) != NULL)
|
||||
gtk_container_remove (GTK_CONTAINER (paned_box), widget);
|
||||
|
||||
/* The last widget is removed, show the instructions */
|
||||
gtk_widget_show (paned_box->p->instructions);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Reference in New Issue
Block a user