[glom] Use EggSpreadTableDnd.
- From: Murray Cumming <murrayc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glom] Use EggSpreadTableDnd.
- Date: Mon, 18 Apr 2011 09:15:14 +0000 (UTC)
commit 03e556e5605e23796e5d371c6d31a8c48bd03649
Author: Murray Cumming <murrayc murrayc com>
Date: Mon Apr 18 11:15:07 2011 +0200
Use EggSpreadTableDnd.
* glom/utility_widgets/eggspreadtable/eggmarshalers.[h|c}
* glom/utility_widgets/eggspreadtable/eggplaceholder.[h|c]
* glom/utility_widgets/eggspreadtable/eggspreadtablednd.[h|c]:
Added these files, copied from libegg.
* glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.[h|cc]:
* glom/utility_widgets/eggspreadtablemm/private/eggspreadtabledndmm
_p.h:
Created a hand-written C++ wrapper for EggSpreadTableDnd.
* glom/Makefile_glom.am: Mention the new files.
* glom/utility_widgets/flowtable.h: Use SpreadTableDnd instead of
SpreadTable, though we do not use the drag-and-drop functionality yet.
ChangeLog | 16 +
Makefile_glom.am | 9 +
.../utility_widgets/eggspreadtable/eggmarshalers.c | 104 ++
.../utility_widgets/eggspreadtable/eggmarshalers.h | 20 +
.../eggspreadtable/eggplaceholder.c | 211 ++++
.../eggspreadtable/eggplaceholder.h | 53 +
.../eggspreadtable/eggspreadtablednd.c | 1251 ++++++++++++++++++++
.../eggspreadtable/eggspreadtablednd.h | 67 ++
.../eggspreadtable/testspreadtable.c | 393 ------
.../eggspreadtablemm/eggspreadtabledndmm.cc | 134 +++
.../eggspreadtablemm/eggspreadtabledndmm.h | 113 ++
.../private/eggspreadtabledndmm_p.h | 45 +
glom/utility_widgets/flowtable.h | 4 +-
13 files changed, 2025 insertions(+), 395 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index eb3c136..7e136b9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2011-04-18 Murray Cumming <murrayc murrayc com>
+
+ Use EggSpreadTableDnd.
+
+ * glom/utility_widgets/eggspreadtable/eggmarshalers.[h|c}
+ * glom/utility_widgets/eggspreadtable/eggplaceholder.[h|c]
+ * glom/utility_widgets/eggspreadtable/eggspreadtablednd.[h|c]:
+ Added these files, copied from libegg.
+ * glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.[h|cc]:
+ * glom/utility_widgets/eggspreadtablemm/private/eggspreadtabledndmm
+ _p.h:
+ Created a hand-written C++ wrapper for EggSpreadTableDnd.
+ * glom/Makefile_glom.am: Mention the new files.
+ * glom/utility_widgets/flowtable.h: Use SpreadTableDnd instead of
+ SpreadTable, though we do not use the drag-and-drop functionality yet.
+
2011-04-12 Murray Cumming <murrayc murrayc com>
Correct the sizing of the ... date button.
diff --git a/Makefile_glom.am b/Makefile_glom.am
index 9b3517f..47b23c0 100644
--- a/Makefile_glom.am
+++ b/Makefile_glom.am
@@ -178,11 +178,20 @@ glom_source_files = \
glom/utility_widgets/dialog_properties.h \
glom/utility_widgets/flowtable.cc \
glom/utility_widgets/flowtable.h \
+ glom/utility_widgets/eggspreadtable/eggmarshalers.c \
+ glom/utility_widgets/eggspreadtable/eggmarshalers.h \
glom/utility_widgets/eggspreadtable/eggspreadtable.c \
glom/utility_widgets/eggspreadtable/eggspreadtable.h \
+ glom/utility_widgets/eggspreadtable/eggspreadtablednd.c \
+ glom/utility_widgets/eggspreadtable/eggspreadtablednd.h \
+ glom/utility_widgets/eggspreadtable/eggplaceholder.c \
+ glom/utility_widgets/eggspreadtable/eggplaceholder.h \
glom/utility_widgets/eggspreadtablemm/eggspreadtablemm.cc \
glom/utility_widgets/eggspreadtablemm/eggspreadtablemm.h \
+ glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc \
+ glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h \
glom/utility_widgets/eggspreadtablemm/private/eggspreadtablemm_p.h \
+ glom/utility_widgets/eggspreadtablemm/private/eggspreadtabledndmm_p.h \
glom/utility_widgets/gimpruler/gimpruler.c \
glom/utility_widgets/gimpruler/gimpruler.h \
glom/utility_widgets/gimpruler/libgimpbase/gimpbase.h \
diff --git a/glom/utility_widgets/eggspreadtable/eggmarshalers.c b/glom/utility_widgets/eggspreadtable/eggmarshalers.c
new file mode 100644
index 0000000..80af893
--- /dev/null
+++ b/glom/utility_widgets/eggspreadtable/eggmarshalers.c
@@ -0,0 +1,104 @@
+
+#ifndef ___egg_marshal_MARSHAL_H__
+#define ___egg_marshal_MARSHAL_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v) g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v) g_value_get_int (v)
+#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
+#define g_marshal_value_peek_long(v) g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
+#define g_marshal_value_peek_float(v) g_value_get_float (v)
+#define g_marshal_value_peek_double(v) g_value_get_double (v)
+#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v) g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v) g_value_get_object (v)
+#define g_marshal_value_peek_variant(v) g_value_get_variant (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ * Do not access GValues directly in your code. Instead, use the
+ * g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
+#define g_marshal_value_peek_char(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v) (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v) (v)->data[0].v_float
+#define g_marshal_value_peek_double(v) (v)->data[0].v_double
+#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* BOOLEAN:OBJECT (./eggmarshalers.list:1) */
+extern void _egg_marshal_BOOLEAN__OBJECT (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+void
+_egg_marshal_BOOLEAN__OBJECT (GClosure *closure,
+ GValue *return_value G_GNUC_UNUSED,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint G_GNUC_UNUSED,
+ gpointer marshal_data)
+{
+ typedef gboolean (*GMarshalFunc_BOOLEAN__OBJECT) (gpointer data1,
+ gpointer arg_1,
+ gpointer data2);
+ register GMarshalFunc_BOOLEAN__OBJECT callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+ gboolean v_return;
+
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 2);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_BOOLEAN__OBJECT) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ g_marshal_value_peek_object (param_values + 1),
+ data2);
+
+ g_value_set_boolean (return_value, v_return);
+}
+
+G_END_DECLS
+
+#endif /* ___egg_marshal_MARSHAL_H__ */
+
diff --git a/glom/utility_widgets/eggspreadtable/eggmarshalers.h b/glom/utility_widgets/eggspreadtable/eggmarshalers.h
new file mode 100644
index 0000000..7307150
--- /dev/null
+++ b/glom/utility_widgets/eggspreadtable/eggmarshalers.h
@@ -0,0 +1,20 @@
+
+#ifndef ___egg_marshal_MARSHAL_H__
+#define ___egg_marshal_MARSHAL_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* BOOLEAN:OBJECT (./eggmarshalers.list:1) */
+extern void _egg_marshal_BOOLEAN__OBJECT (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+G_END_DECLS
+
+#endif /* ___egg_marshal_MARSHAL_H__ */
+
diff --git a/glom/utility_widgets/eggspreadtable/eggplaceholder.c b/glom/utility_widgets/eggspreadtable/eggplaceholder.c
new file mode 100644
index 0000000..d0913e8
--- /dev/null
+++ b/glom/utility_widgets/eggspreadtable/eggplaceholder.c
@@ -0,0 +1,211 @@
+
+#include "eggplaceholder.h"
+
+/* GObjectClass */
+static void egg_placeholder_finalize (GObject *object);
+
+/* GtkWidgetClass */
+static void egg_placeholder_get_preferred_width (GtkWidget *widget,
+ gint *min_width,
+ gint *nat_width);
+static void egg_placeholder_get_preferred_height (GtkWidget *widget,
+ gint *min_height,
+ gint *nat_height);
+
+#define ANIMATION_STEP 0.12F /* How much percentage of the size to animate per iteration */
+#define ANIMATION_FREQ 20 /* At what frequency in millisecs to animate */
+
+enum {
+ SIGNAL_ANIMATION_DONE,
+ NUM_SIGNALS
+};
+
+static guint placeholder_signals[NUM_SIGNALS] = { 0, };
+
+struct _EggPlaceholderPrivate
+{
+ gint width;
+ gint height;
+
+ GtkOrientation animation_orientation; /* Whether we are animating in/out horizontally or vertically */
+ gdouble animation_percent; /* A multiplier between 0 and 1 representing the current progress */
+ guint animation_id; /* The GSource id for the animation timeout */
+ EggPlaceholderAnimDirection animation_direction; /* Whether the placeholder is animating in or out */
+};
+
+G_DEFINE_TYPE (EggPlaceholder, egg_placeholder, GTK_TYPE_DRAWING_AREA)
+
+static void egg_placeholder_class_init (EggPlaceholderClass * klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = egg_placeholder_finalize;
+
+ widget_class->get_preferred_width = egg_placeholder_get_preferred_width;
+ widget_class->get_preferred_height = egg_placeholder_get_preferred_height;
+
+ placeholder_signals[SIGNAL_ANIMATION_DONE] =
+ g_signal_new ("animation-done",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_FIRST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_type_class_add_private (klass, sizeof (EggPlaceholderPrivate));
+}
+
+static void
+egg_placeholder_init (EggPlaceholder * placeholder)
+{
+ placeholder->priv =
+ G_TYPE_INSTANCE_GET_PRIVATE (placeholder,
+ EGG_TYPE_PLACEHOLDER,
+ EggPlaceholderPrivate);
+
+ placeholder->priv->animation_percent = 1.0F;
+
+ /* Default visible, avoid cluttering code in eggspreadtablednd.c */
+ gtk_widget_show (GTK_WIDGET (placeholder));
+}
+
+static void
+egg_placeholder_finalize (GObject * object)
+{
+ EggPlaceholder *placeholder = EGG_PLACEHOLDER (object);
+
+ if (placeholder->priv->animation_id > 0)
+ {
+ g_source_remove (placeholder->priv->animation_id);
+ placeholder->priv->animation_id = 0;
+ }
+
+ G_OBJECT_CLASS (egg_placeholder_parent_class)->finalize (object);
+}
+
+static void
+egg_placeholder_get_preferred_width (GtkWidget *widget,
+ gint *min_width,
+ gint *nat_width)
+{
+ EggPlaceholder *placeholder = EGG_PLACEHOLDER (widget);
+ gint width;
+
+ if (placeholder->priv->animation_orientation == GTK_ORIENTATION_HORIZONTAL)
+ width = placeholder->priv->width * placeholder->priv->animation_percent;
+ else
+ width = placeholder->priv->width;
+
+ *min_width = *nat_width = width;
+}
+
+static void
+egg_placeholder_get_preferred_height (GtkWidget *widget,
+ gint *min_height,
+ gint *nat_height)
+{
+ EggPlaceholder *placeholder = EGG_PLACEHOLDER (widget);
+ gint height;
+
+ if (placeholder->priv->animation_orientation == GTK_ORIENTATION_VERTICAL)
+ height = placeholder->priv->height * placeholder->priv->animation_percent;
+ else
+ height = placeholder->priv->height;
+
+ *min_height = *nat_height = height;
+}
+
+static gboolean
+placeholder_animate (EggPlaceholder *placeholder)
+{
+ if (placeholder->priv->animation_direction == EGG_PLACEHOLDER_ANIM_IN)
+ placeholder->priv->animation_percent += ANIMATION_STEP;
+ else if (placeholder->priv->animation_direction == EGG_PLACEHOLDER_ANIM_OUT)
+ placeholder->priv->animation_percent -= ANIMATION_STEP;
+ else
+ g_error ("Placeholder animation called while not animating");
+
+ placeholder->priv->animation_percent =
+ CLAMP (placeholder->priv->animation_percent, 0.0, 1.0);
+
+ gtk_widget_queue_resize (GTK_WIDGET (placeholder));
+
+ if (placeholder->priv->animation_percent >= 1.0 ||
+ placeholder->priv->animation_percent <= 0.0)
+ {
+ placeholder->priv->animation_id = 0;
+ placeholder->priv->animation_direction = EGG_PLACEHOLDER_ANIM_NONE;
+
+ g_signal_emit (placeholder, placeholder_signals[SIGNAL_ANIMATION_DONE], 0);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+egg_placeholder_animate_in (EggPlaceholder *placeholder,
+ GtkOrientation orientation)
+{
+ g_return_if_fail (EGG_IS_PLACEHOLDER (placeholder));
+
+ placeholder->priv->animation_orientation = orientation;
+ placeholder->priv->animation_direction = EGG_PLACEHOLDER_ANIM_IN;
+
+ if (placeholder->priv->animation_id == 0)
+ {
+ placeholder->priv->animation_percent = 0.0F;
+ placeholder->priv->animation_id =
+ gdk_threads_add_timeout (ANIMATION_FREQ,
+ (GSourceFunc)placeholder_animate,
+ placeholder);
+ }
+
+ gtk_widget_queue_resize (GTK_WIDGET (placeholder));
+}
+
+void
+egg_placeholder_animate_out (EggPlaceholder *placeholder,
+ GtkOrientation orientation)
+{
+ g_return_if_fail (EGG_IS_PLACEHOLDER (placeholder));
+
+ placeholder->priv->animation_orientation = orientation;
+ placeholder->priv->animation_direction = EGG_PLACEHOLDER_ANIM_OUT;
+
+ if (placeholder->priv->animation_id == 0)
+ {
+ placeholder->priv->animation_percent = 1.0F;
+ placeholder->priv->animation_id =
+ gdk_threads_add_timeout (ANIMATION_FREQ,
+ (GSourceFunc)placeholder_animate,
+ placeholder);
+ }
+
+ gtk_widget_queue_resize (GTK_WIDGET (placeholder));
+}
+
+
+EggPlaceholderAnimDirection
+egg_placeholder_get_animating (EggPlaceholder *placeholder)
+{
+ g_return_val_if_fail (EGG_IS_PLACEHOLDER (placeholder),
+ EGG_PLACEHOLDER_ANIM_NONE);
+
+ return placeholder->priv->animation_direction;
+}
+
+
+GtkWidget *
+egg_placeholder_new (gint width,
+ gint height)
+{
+ EggPlaceholder *placeholder = g_object_new (EGG_TYPE_PLACEHOLDER, NULL);
+
+ placeholder->priv->width = width;
+ placeholder->priv->height = height;
+
+ return GTK_WIDGET (placeholder);
+}
diff --git a/glom/utility_widgets/eggspreadtable/eggplaceholder.h b/glom/utility_widgets/eggspreadtable/eggplaceholder.h
new file mode 100644
index 0000000..496cdff
--- /dev/null
+++ b/glom/utility_widgets/eggspreadtable/eggplaceholder.h
@@ -0,0 +1,53 @@
+
+#ifndef __EGG_PLACEHOLDER_H__
+#define __EGG_PLACEHOLDER_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_PLACEHOLDER (egg_placeholder_get_type ())
+#define EGG_PLACEHOLDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_PLACEHOLDER, EggPlaceholder))
+#define EGG_PLACEHOLDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_PLACEHOLDER, EggPlaceholderClass))
+#define EGG_IS_PLACEHOLDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_PLACEHOLDER))
+#define EGG_IS_PLACEHOLDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_PLACEHOLDER))
+#define EGG_PLACEHOLDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_PLACEHOLDER, EggPlaceholderClass))
+
+typedef struct _EggPlaceholder EggPlaceholder;
+typedef struct _EggPlaceholderClass EggPlaceholderClass;
+typedef struct _EggPlaceholderPrivate EggPlaceholderPrivate;
+
+
+typedef enum {
+ EGG_PLACEHOLDER_ANIM_NONE,
+ EGG_PLACEHOLDER_ANIM_IN,
+ EGG_PLACEHOLDER_ANIM_OUT
+} EggPlaceholderAnimDirection;
+
+
+struct _EggPlaceholder
+{
+ GtkDrawingArea drawing_area;
+
+ EggPlaceholderPrivate *priv;
+};
+
+struct _EggPlaceholderClass
+{
+ GtkDrawingAreaClass parent_class;
+};
+
+GType egg_placeholder_get_type (void) G_GNUC_CONST;
+
+GtkWidget *egg_placeholder_new (gint width,
+ gint height);
+void egg_placeholder_animate_in (EggPlaceholder *placeholder,
+ GtkOrientation orientation);
+void egg_placeholder_animate_out (EggPlaceholder *placeholder,
+ GtkOrientation orientation);
+
+EggPlaceholderAnimDirection egg_placeholder_get_animating (EggPlaceholder *placeholder);
+
+G_END_DECLS
+
+#endif /* __EGG_PLACEHOLDER_H__ */
diff --git a/glom/utility_widgets/eggspreadtable/eggspreadtablednd.c b/glom/utility_widgets/eggspreadtable/eggspreadtablednd.c
new file mode 100644
index 0000000..6fad48e
--- /dev/null
+++ b/glom/utility_widgets/eggspreadtable/eggspreadtablednd.c
@@ -0,0 +1,1251 @@
+/* gtkspreadtablednd.c
+ * Copyright (C) 2011 Openismus GmbH
+ *
+ * Authors:
+ * Tristan Van Berkom <tristanvb openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include <gtk/gtk.h>
+#include <string.h>
+#include "eggspreadtablednd.h"
+#include "eggplaceholder.h"
+#include "eggmarshalers.h"
+
+#define DEFAULT_LINES 2
+#define P_(msgid) (msgid)
+
+/* GtkWidgetClass */
+static void egg_spread_table_dnd_realize (GtkWidget *widget);
+static gboolean egg_spread_table_dnd_motion (GtkWidget *widget,
+ GdkEventMotion *event);
+static gboolean egg_spread_table_dnd_leave (GtkWidget *widget,
+ GdkEventCrossing *event);
+static gboolean egg_spread_table_dnd_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gboolean egg_spread_table_dnd_button_release (GtkWidget *widget,
+ GdkEventButton *event);
+static void egg_spread_table_dnd_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+
+/* GtkWidgetClass drag-source */
+static void egg_spread_table_dnd_drag_data_get (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time_);
+
+/* GtkWidgetClass drag-dest */
+static void egg_spread_table_dnd_drag_leave (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time_);
+static gboolean egg_spread_table_dnd_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time_);
+static gboolean egg_spread_table_dnd_drag_drop (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time_);
+static void egg_spread_table_dnd_drag_data_received (GtkWidget *widget,
+ GdkDragContext *drag_context,
+ gint x,
+ gint y,
+ GtkSelectionData *data,
+ guint info,
+ guint time);
+
+/* GtkContainerClass */
+static void egg_spread_table_dnd_remove (GtkContainer *container,
+ GtkWidget *child);
+
+/* EggSpreadTableClass */
+static void egg_spread_table_dnd_insert_child (EggSpreadTable *spread_table,
+ GtkWidget *child,
+ gint index);
+static gint egg_spread_table_dnd_build_segments (EggSpreadTable *table,
+ gint for_size,
+ gint **segments);
+
+/* EggSpreadTableDndClass */
+static gboolean egg_spread_table_dnd_drop_possible(EggSpreadTableDnd *table,
+ GtkWidget *widget);
+
+/* Drag and Drop callbacks & other utilities */
+static void drag_begin (GtkWidget *widget,
+ GdkDragContext *context,
+ EggSpreadTableDnd *spread_table);
+static void drag_end (GtkWidget *widget,
+ GdkDragContext *context,
+ EggSpreadTableDnd *spread_table);
+static void drag_data_get (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection,
+ guint info,
+ guint time,
+ EggSpreadTableDnd *spread_table);
+static gboolean drag_failed (GtkWidget *widget,
+ GdkDragContext *drag_context,
+ GtkDragResult result,
+ EggSpreadTableDnd *spread_table);
+
+static GtkWidget *get_child_at_position (EggSpreadTableDnd *spread_table,
+ gint x,
+ gint y);
+static gint get_index_at_position (EggSpreadTableDnd *spread_table,
+ gint x,
+ gint y,
+ gint *line_ret);
+static gboolean boolean_handled_accumulator (GSignalInvocationHint *ihint,
+ GValue *return_accu,
+ const GValue *handler_return,
+ gpointer dummy);
+
+static gboolean drop_possible (EggSpreadTableDnd *spread_table,
+ GtkWidget *widget);
+static void adjust_line_segment (EggSpreadTableDnd *table,
+ gint segment,
+ gint offset);
+static void lock_table (EggSpreadTableDnd *spread_table);
+static void unlock_table (EggSpreadTableDnd *spread_table);
+static void animate_out_drop_target (EggSpreadTableDnd *table,
+ gboolean end);
+
+typedef struct {
+ EggSpreadTableDnd *table;
+ GtkWidget *child;
+} EggSpreadTableDndDragData;
+
+struct _EggSpreadTableDndPrivate {
+
+ /* State of drop target while drag-motion is happening over this spread table */
+ GtkWidget *drop_target; /* Remember which child widget is the active placeholder */
+
+ /* After successfully calling gtk_drag_get_data(), the drag data ends up in this struct */
+ EggSpreadTableDndDragData drag_data;
+
+ GtkWidget *drag_child; /* If the drag started on a widget with no window, then the spread table
+ * keeps a hold on which child is being dragged */
+
+ guint dragging : 1; /* Whether the drag'n'drop operation is currently active over this table */
+
+ gint disappearing; /* Count of placeholders that are currently disappearing */
+
+ /* These states are used to trigger a drag operation on a child widget with no window */
+ gint pressed_button;
+ gint press_start_x;
+ gint press_start_y;
+
+ /* Caching and locking the child configuration */
+ gint *locked_config;
+
+};
+
+
+enum {
+ SIGNAL_DROP_POSSIBLE,
+ LAST_SIGNAL
+};
+
+static guint dnd_table_signals [LAST_SIGNAL] = { 0 };
+static GdkAtom dnd_target_atom_child = GDK_NONE;
+static const GtkTargetEntry dnd_targets[] = {
+ { "application/x-egg-spread-table-dnd-child", GTK_TARGET_SAME_APP, 0 }
+};
+
+
+
+G_DEFINE_TYPE (EggSpreadTableDnd, egg_spread_table_dnd, EGG_TYPE_SPREAD_TABLE)
+
+static void
+egg_spread_table_dnd_class_init (EggSpreadTableDndClass *class)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
+ EggSpreadTableClass *spread_class = EGG_SPREAD_TABLE_CLASS (class);
+
+ widget_class->realize = egg_spread_table_dnd_realize;
+ widget_class->button_press_event = egg_spread_table_dnd_button_press;
+ widget_class->button_release_event = egg_spread_table_dnd_button_release;
+ widget_class->motion_notify_event = egg_spread_table_dnd_motion;
+ widget_class->leave_notify_event = egg_spread_table_dnd_leave;
+
+ widget_class->size_allocate = egg_spread_table_dnd_size_allocate;
+
+ /* Drag source */
+ widget_class->drag_data_get = egg_spread_table_dnd_drag_data_get;
+
+ /* Drag dest */
+ widget_class->drag_leave = egg_spread_table_dnd_drag_leave;
+ widget_class->drag_motion = egg_spread_table_dnd_drag_motion;
+ widget_class->drag_drop = egg_spread_table_dnd_drag_drop;
+ widget_class->drag_data_received = egg_spread_table_dnd_drag_data_received;
+
+ container_class->remove = egg_spread_table_dnd_remove;
+
+ spread_class->insert_child = egg_spread_table_dnd_insert_child;
+ spread_class->build_segments_for_size = egg_spread_table_dnd_build_segments;
+
+ class->widget_drop_possible = egg_spread_table_dnd_drop_possible;
+
+ /**
+ * EggSpreadTableDnd::widget-drop-possible
+ *
+ * Emitted to check if a widget can be dropped into this spread table.
+ *
+ * The first connected signal to return TRUE decides that the widget
+ * can be dropped.
+ *
+ * By default EggSpreadTableDnd accepts drops from the same table
+ * (the only way to dissallow drops from the same spread table is
+ * to implement a subclass which overrides the
+ * EggSpreadTableDndClass.widget_drop_possible() virtual method).
+ */
+ dnd_table_signals[SIGNAL_DROP_POSSIBLE] =
+ g_signal_new ("widget-drop-possible",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggSpreadTableDndClass, widget_drop_possible),
+ boolean_handled_accumulator, NULL,
+ _egg_marshal_BOOLEAN__OBJECT,
+ G_TYPE_BOOLEAN, 1, GTK_TYPE_WIDGET);
+
+
+ dnd_target_atom_child = gdk_atom_intern_static_string (dnd_targets[0].target);
+
+ g_type_class_add_private (class, sizeof (EggSpreadTableDndPrivate));
+}
+
+static void
+egg_spread_table_dnd_init (EggSpreadTableDnd *spread_table)
+{
+ EggSpreadTableDndPrivate *priv;
+
+ spread_table->priv = priv =
+ G_TYPE_INSTANCE_GET_PRIVATE (spread_table, EGG_TYPE_SPREAD_TABLE_DND, EggSpreadTableDndPrivate);
+
+ priv->pressed_button = -1;
+
+ /* Setup the spread table as a drag target for our target type */
+ gtk_drag_dest_set (GTK_WIDGET (spread_table),
+ 0,
+ dnd_targets, G_N_ELEMENTS (dnd_targets),
+ GDK_ACTION_MOVE);
+
+ /* Setup the spread table as a drag source for our target type also
+ * (to handle no-window widget children) */
+ gtk_drag_source_set (GTK_WIDGET (spread_table),
+ 0, dnd_targets, G_N_ELEMENTS (dnd_targets),
+ GDK_ACTION_MOVE);
+
+ gtk_widget_set_has_window (GTK_WIDGET (spread_table), TRUE);
+}
+
+/*****************************************************
+ * GtkWidgetClass *
+ *****************************************************/
+static void
+egg_spread_table_dnd_realize (GtkWidget *widget)
+{
+ GtkAllocation allocation;
+ GdkWindow *window;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ gtk_widget_set_realized (widget, TRUE);
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = allocation.x;
+ attributes.y = allocation.y;
+ attributes.width = allocation.width;
+ attributes.height = allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.event_mask = gtk_widget_get_events (widget)
+ | GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK
+ | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
+ | GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK;
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
+
+ window = gdk_window_new (gtk_widget_get_parent_window (widget),
+ &attributes, attributes_mask);
+ gtk_widget_set_window (widget, window);
+ gdk_window_set_user_data (window, widget);
+
+ gtk_style_context_set_background (gtk_widget_get_style_context (widget), window);
+}
+
+static gboolean
+egg_spread_table_dnd_motion (GtkWidget *widget,
+ GdkEventMotion *event)
+{
+ EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
+
+ if (spread_table->priv->pressed_button >= 0 &&
+ gtk_drag_check_threshold (widget,
+ spread_table->priv->press_start_x,
+ spread_table->priv->press_start_y,
+ event->x, event->y))
+ {
+ spread_table->priv->drag_child =
+ get_child_at_position (spread_table,
+ spread_table->priv->press_start_x,
+ spread_table->priv->press_start_y);
+
+ if (spread_table->priv->drag_child)
+ {
+ gtk_drag_begin (spread_table->priv->drag_child,
+ gtk_drag_source_get_target_list (widget),
+ GDK_ACTION_MOVE,
+ spread_table->priv->pressed_button,
+ (GdkEvent*)event);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static gboolean
+egg_spread_table_dnd_leave (GtkWidget *widget,
+ G_GNUC_UNUSED GdkEventCrossing *event)
+{
+ EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
+
+ spread_table->priv->pressed_button = -1;
+
+ return TRUE;
+}
+
+static gboolean
+egg_spread_table_dnd_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
+ gboolean handled = FALSE;
+
+ if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
+ {
+ /* Save press to possibly begin a drag */
+ if (get_child_at_position (spread_table, event->x, event->y) &&
+ spread_table->priv->pressed_button < 0)
+ {
+ spread_table->priv->pressed_button = event->button;
+ spread_table->priv->press_start_x = event->x;
+ spread_table->priv->press_start_y = event->y;
+
+ handled = TRUE;
+ }
+ }
+
+ return handled;
+}
+
+static gboolean
+egg_spread_table_dnd_button_release (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
+
+ if (spread_table->priv->pressed_button == (gint)event->button)
+ spread_table->priv->pressed_button = -1;
+
+ return TRUE;
+}
+
+static void
+get_widget_size (GtkWidget *widget,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *min_size,
+ gint *nat_size)
+{
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ if (for_size < 0)
+ gtk_widget_get_preferred_width (widget, min_size, nat_size);
+ else
+ gtk_widget_get_preferred_width_for_height (widget, for_size, min_size, nat_size);
+ }
+ else
+ {
+ if (for_size < 0)
+ gtk_widget_get_preferred_height (widget, min_size, nat_size);
+ else
+ gtk_widget_get_preferred_height_for_width (widget, for_size, min_size, nat_size);
+ }
+}
+
+static void
+allocate_child (EggSpreadTableDnd *table,
+ GtkWidget *child,
+ gint item_offset,
+ gint line_offset,
+ gint item_size,
+ gint line_size)
+{
+ GtkAllocation widget_allocation;
+ GtkAllocation child_allocation;
+ GtkOrientation orientation;
+
+ gtk_widget_get_allocation (GTK_WIDGET (table), &widget_allocation);
+ orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (table));
+
+ if (gtk_widget_get_has_window (GTK_WIDGET (table)))
+ {
+ widget_allocation.x = 0;
+ widget_allocation.y = 0;
+ }
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ child_allocation.x = widget_allocation.x + item_offset;
+ child_allocation.y = widget_allocation.y + line_offset;
+ child_allocation.width = item_size;
+ child_allocation.height = line_size;
+ }
+ else /* GTK_ORIENTATION_VERTICAL */
+ {
+ child_allocation.x = widget_allocation.x + line_offset;
+ child_allocation.y = widget_allocation.y + item_offset;
+ child_allocation.width = line_size;
+ child_allocation.height = item_size;
+ }
+
+ gtk_widget_size_allocate (child, &child_allocation);
+}
+
+static void
+get_spread_table_dimentions (EggSpreadTableDnd *spread_table,
+ gint for_size,
+ gint *line_spacing,
+ gint *item_spacing,
+ gint *full_size,
+ gint *line_width)
+{
+ EggSpreadTable *table = EGG_SPREAD_TABLE (spread_table);
+ gint local_full_size, local_item_spacing, local_spacing;
+ gint lines = egg_spread_table_get_lines (table);
+ GtkAllocation allocation;
+
+ gtk_widget_get_allocation (GTK_WIDGET (table), &allocation);
+
+ if (gtk_orientable_get_orientation (GTK_ORIENTABLE (table)) == GTK_ORIENTATION_VERTICAL)
+ {
+ local_full_size = for_size < 0 ? allocation.width : for_size;
+ local_spacing = egg_spread_table_get_horizontal_spacing (table);
+ local_item_spacing = egg_spread_table_get_vertical_spacing (table);
+ }
+ else
+ {
+ local_full_size = for_size < 0 ? allocation.height : for_size;
+ local_spacing = egg_spread_table_get_vertical_spacing (table);
+ local_item_spacing = egg_spread_table_get_horizontal_spacing (table);
+ }
+
+ if (full_size)
+ *full_size = local_full_size;
+ if (line_spacing)
+ *line_spacing = local_spacing;
+ if (item_spacing)
+ *item_spacing = local_item_spacing;
+
+ if (line_width)
+ *line_width = (local_full_size - (local_spacing * (lines -1))) / lines;
+}
+
+static void
+egg_spread_table_dnd_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ EggSpreadTableDnd *table = EGG_SPREAD_TABLE_DND (widget);
+ GList *list, *children;
+ gint *segments = NULL;
+ gint full_thickness;
+ gint i, j;
+ gint line_offset, item_offset;
+ gint line_thickness;
+ gint line_spacing;
+ gint item_spacing;
+ gint placeholder_cnt = 0;
+ gint lines;
+ GtkWidgetClass *parent_parent_class;
+ GtkOrientation orientation;
+
+ /* Skip the EggSpreadTableClass allocator, chain up to it's parent to resize
+ * the GdkWindow properly */
+ parent_parent_class = g_type_class_peek_parent (egg_spread_table_dnd_parent_class);
+ parent_parent_class->size_allocate (widget, allocation);
+
+ get_spread_table_dimentions (table, -1, &line_spacing, &item_spacing, &full_thickness, &line_thickness);
+ lines = egg_spread_table_get_lines (EGG_SPREAD_TABLE (table));
+ orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (table));
+
+ egg_spread_table_build_segments_for_size (EGG_SPREAD_TABLE (table), full_thickness, &segments);
+
+ children = gtk_container_get_children (GTK_CONTAINER (table));
+
+ for (list = children, line_offset = 0, i = 0; i < lines;
+ line_offset += line_thickness + line_spacing, i++)
+ {
+ /* Count the placeholders on each line */
+ placeholder_cnt = 0;
+
+ for (j = 0, item_offset = 0; list && j < segments[i]; list = list->next, j++)
+ {
+ GtkWidget *child = list->data;
+ gint child_size;
+
+ if (!gtk_widget_get_visible (child))
+ continue;
+
+ get_widget_size (child, orientation, line_thickness, NULL, &child_size);
+
+ /* Stop allocating children on this line after 2 placeholders
+ * this avoids annoying flicker when moving a widget inside a single column */
+ if (placeholder_cnt >= 2)
+ continue;
+
+ if (placeholder_cnt < 2 && EGG_IS_PLACEHOLDER (child))
+ placeholder_cnt++;
+
+ allocate_child (table, child, item_offset, line_offset, child_size, line_thickness);
+
+ item_offset += child_size + item_spacing;
+ }
+ }
+
+ g_list_free (children);
+ g_free (segments);
+}
+
+
+/*****************************************************
+ * GtkWidgetClass drag source *
+ *****************************************************/
+
+static void
+egg_spread_table_dnd_drag_data_get (GtkWidget *widget,
+ G_GNUC_UNUSED GdkDragContext *context,
+ GtkSelectionData *selection,
+ G_GNUC_UNUSED guint info,
+ G_GNUC_UNUSED guint time_)
+{
+ EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
+ EggSpreadTableDndDragData drag_data = { spread_table, NULL };
+ GdkAtom target;
+
+ target = gtk_selection_data_get_target (selection);
+
+ if (spread_table->priv->drag_child &&
+ target == dnd_target_atom_child)
+ {
+ drag_data.child = spread_table->priv->drag_child;
+
+ gtk_selection_data_set (selection, target, 8,
+ (guchar*) &drag_data, sizeof (drag_data));
+ }
+}
+
+/*****************************************************
+ * GtkWidgetClass drag dest *
+ *****************************************************/
+static gint
+get_child_line (EggSpreadTableDnd *table,
+ GtkWidget *child)
+{
+ gint size;
+
+ if (gtk_orientable_get_orientation (GTK_ORIENTABLE (table)) == GTK_ORIENTATION_VERTICAL)
+ size = gtk_widget_get_allocated_width (GTK_WIDGET (table));
+ else
+ size = gtk_widget_get_allocated_height (GTK_WIDGET (table));
+
+ return egg_spread_table_get_child_line (EGG_SPREAD_TABLE (table), child, size);
+}
+
+static void
+placeholder_animated_out (GtkWidget *placeholder,
+ EggSpreadTableDnd *spread_table)
+{
+ gint line = -1;
+ gboolean last_target = FALSE;
+
+ if (spread_table->priv->drop_target == placeholder)
+ {
+ spread_table->priv->drop_target = NULL;
+ last_target = TRUE;
+ }
+
+ if (spread_table->priv->dragging)
+ line = get_child_line (spread_table, placeholder);
+
+ gtk_container_remove (GTK_CONTAINER (spread_table), placeholder);
+
+ /* Adjust line segment here manually since table may be locked */
+ if (spread_table->priv->dragging)
+ adjust_line_segment (spread_table, line, -1);
+ else if (last_target)
+ /* Unlock the table after the drag is finished */
+ unlock_table (spread_table);
+
+ spread_table->priv->disappearing--;
+}
+
+static void
+egg_spread_table_dnd_drag_leave (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time_)
+{
+ EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
+
+ gtk_drag_get_data (widget, context, dnd_target_atom_child, time_);
+
+ /* Animate-out drop target for drop-zone spread table */
+ animate_out_drop_target (spread_table, TRUE);
+
+ /* Animate-out drop target for drag-source spread table
+ * (sometimes when drag'n'drop happens very fast no drag-leave gets
+ * emitted on the source spread table so we take care of it here)
+ */
+ if (spread_table->priv->drag_data.table != spread_table)
+ animate_out_drop_target (spread_table->priv->drag_data.table, TRUE);
+}
+
+static void
+get_placeholder_size (EggSpreadTableDnd *spread_table,
+ gint *width,
+ gint *height)
+{
+ GtkOrientation orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (spread_table));
+ gint line_width;
+
+ /* Calculate the size of the required placeholder based on the dimentions of the drag widget */
+ get_spread_table_dimentions (spread_table, -1, NULL, NULL, NULL, &line_width);
+
+ if (orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ gint min_width;
+
+ gtk_widget_get_preferred_width (spread_table->priv->drag_data.child, &min_width, NULL);
+
+ *width = MAX (line_width, min_width);
+
+ gtk_widget_get_preferred_height_for_width (spread_table->priv->drag_data.child,
+ *width, height, NULL);
+ }
+ else
+ {
+ gint min_height;
+
+ gtk_widget_get_preferred_width (spread_table->priv->drag_data.child, &min_height, NULL);
+
+ *height = MAX (line_width, min_height);
+
+ gtk_widget_get_preferred_width_for_height (spread_table->priv->drag_data.child,
+ *height, width, NULL);
+ }
+}
+
+static gboolean
+egg_spread_table_dnd_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time_)
+{
+ EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
+ gint index, line, drop_index;
+
+ /* Could be comming from another spread table, lock it now incase
+ * its not already locked. */
+
+ gtk_drag_get_data (widget, context, dnd_target_atom_child, time_);
+
+ if (!drop_possible (spread_table, spread_table->priv->drag_data.child))
+ return FALSE;
+
+ lock_table (spread_table);
+ spread_table->priv->dragging = TRUE;
+
+ /* Dont do anything until the currently drop target placeholder finishes animating in */
+ if ((spread_table->priv->drop_target &&
+ egg_placeholder_get_animating
+ (EGG_PLACEHOLDER (spread_table->priv->drop_target)) != EGG_PLACEHOLDER_ANIM_NONE) ||
+ spread_table->priv->disappearing)
+ return TRUE;
+
+ if (spread_table->priv->drop_target)
+ gtk_container_child_get (GTK_CONTAINER (spread_table),
+ spread_table->priv->drop_target,
+ "position", &drop_index,
+ NULL);
+ else
+ drop_index = -1;
+
+ index = get_index_at_position (spread_table, x, y, &line);
+
+ if (index != drop_index)
+ {
+
+ animate_out_drop_target (spread_table, FALSE);
+
+ if (index >= 0)
+ {
+ gint width, height;
+
+ /* Import the drag data, get the drag widget and query it's size for this spread table */
+ get_placeholder_size (spread_table, &width, &height);
+
+ spread_table->priv->drop_target = egg_placeholder_new (width, height);
+ egg_spread_table_insert_child (EGG_SPREAD_TABLE (spread_table),
+ spread_table->priv->drop_target, index);
+ adjust_line_segment (spread_table, line, 1);
+
+ egg_placeholder_animate_in (EGG_PLACEHOLDER (spread_table->priv->drop_target),
+ gtk_orientable_get_orientation (GTK_ORIENTABLE (spread_table)));
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+egg_spread_table_dnd_drag_drop (GtkWidget *widget,
+ GdkDragContext *context,
+ G_GNUC_UNUSED gint x,
+ G_GNUC_UNUSED gint y,
+ guint time_)
+{
+ EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
+
+ gtk_drag_get_data (widget, context, dnd_target_atom_child, time_);
+
+ if (spread_table->priv->drop_target &&
+ spread_table->priv->drag_data.child)
+ {
+ gint drop_index;
+
+ /* Carry the widget over */
+ g_object_ref (spread_table->priv->drag_data.child);
+
+ gtk_container_remove (GTK_CONTAINER (spread_table->priv->drag_data.table),
+ spread_table->priv->drag_data.child);
+
+ /* Get the appropriate target index */
+ gtk_container_child_get (GTK_CONTAINER (spread_table),
+ spread_table->priv->drop_target,
+ "position", &drop_index,
+ NULL);
+
+ /* Insert drag child at the index */
+ egg_spread_table_insert_child (EGG_SPREAD_TABLE (spread_table),
+ spread_table->priv->drag_data.child,
+ drop_index);
+ g_object_unref (spread_table->priv->drag_data.child);
+
+ /* Ensure visibility */
+ gtk_widget_show (spread_table->priv->drag_data.child);
+
+ /* Hide the drop target placeholder in the target spread table,
+ * it will be removed and the spread table unlocked after animating out
+ * (the placeholder started animating out at "drag-leave" time).
+ */
+ gtk_widget_hide (spread_table->priv->drop_target);
+
+ gtk_drag_finish (context, TRUE, TRUE, time_);
+ return TRUE;
+ }
+ else
+ {
+ gtk_drag_finish (context, FALSE, TRUE, time_);
+ return FALSE;
+ }
+
+}
+
+static void
+egg_spread_table_dnd_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ G_GNUC_UNUSED gint x,
+ G_GNUC_UNUSED gint y,
+ GtkSelectionData *data,
+ G_GNUC_UNUSED guint info,
+ guint time_)
+{
+ EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
+ EggSpreadTableDndDragData *drag_data;
+
+ memset (&spread_table->priv->drag_data, 0x0, sizeof (EggSpreadTableDndDragData));
+
+ g_return_if_fail (gtk_selection_data_get_format (data) == 8);
+ g_return_if_fail (gtk_selection_data_get_length (data) == sizeof (EggSpreadTableDndDragData));
+ g_return_if_fail (gtk_selection_data_get_target (data) == dnd_target_atom_child);
+
+ drag_data = (EggSpreadTableDndDragData*) gtk_selection_data_get_data (data);
+ memcpy (&spread_table->priv->drag_data, drag_data, sizeof (EggSpreadTableDndDragData));
+
+ gdk_drag_status (context, GDK_ACTION_MOVE, time_);
+}
+
+/*****************************************************
+ * GtkContainerClass *
+ *****************************************************/
+static void
+egg_spread_table_dnd_remove (GtkContainer *container,
+ GtkWidget *child)
+{
+ /* Disconnect dnd */
+ if (!EGG_IS_PLACEHOLDER (child))
+ {
+ g_signal_handlers_disconnect_by_func (child, G_CALLBACK (drag_data_get), container);
+ g_signal_handlers_disconnect_by_func (child, G_CALLBACK (drag_failed), container);
+ g_signal_handlers_disconnect_by_func (child, G_CALLBACK (drag_begin), container);
+ g_signal_handlers_disconnect_by_func (child, G_CALLBACK (drag_end), container);
+ gtk_drag_source_unset (child);
+ }
+
+ GTK_CONTAINER_CLASS (egg_spread_table_dnd_parent_class)->remove (container, child);
+}
+
+
+/*****************************************************
+ * EggSpreadTableClass *
+ *****************************************************/
+static void
+egg_spread_table_dnd_insert_child (EggSpreadTable *spread_table,
+ GtkWidget *child,
+ gint index)
+{
+ EGG_SPREAD_TABLE_CLASS (egg_spread_table_dnd_parent_class)->insert_child (spread_table, child, index);
+
+ /* Connect dnd */
+ if (!EGG_IS_PLACEHOLDER (child))
+ {
+ gtk_drag_source_set (child, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
+ dnd_targets, G_N_ELEMENTS (dnd_targets),
+ GDK_ACTION_MOVE);
+
+ g_signal_connect (child, "drag-data-get",
+ G_CALLBACK (drag_data_get), spread_table);
+ g_signal_connect (child, "drag-failed",
+ G_CALLBACK (drag_failed), spread_table);
+ g_signal_connect (child, "drag-begin",
+ G_CALLBACK (drag_begin), spread_table);
+ g_signal_connect (child, "drag-end",
+ G_CALLBACK (drag_end), spread_table);
+ }
+}
+
+static gint
+egg_spread_table_dnd_build_segments (EggSpreadTable *table,
+ gint for_size,
+ gint **segments)
+{
+ EggSpreadTableDnd *dnd_table = EGG_SPREAD_TABLE_DND (table);
+ EggSpreadTableDndPrivate *priv = dnd_table->priv;
+ GList *list, *children;
+ gint i, j, lines;
+ gint largest_line = 0, line_size = 0;
+ gint line_thickness;
+ gint spacing;
+ GtkOrientation orientation;
+ gboolean first_widget = TRUE;
+
+ if (!priv->locked_config)
+ return EGG_SPREAD_TABLE_CLASS
+ (egg_spread_table_dnd_parent_class)->build_segments_for_size (table, for_size, segments);
+
+ get_spread_table_dimentions (dnd_table, for_size, NULL, &spacing, NULL, &line_thickness);
+
+ children = gtk_container_get_children (GTK_CONTAINER (table));
+ orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (table));
+ lines = egg_spread_table_get_lines (table);
+
+ for (list = children, i = 0; i < lines; i++)
+ {
+ for (j = 0; list && j < priv->locked_config[i]; list = list->next, j++)
+ {
+ GtkWidget *child = list->data;
+ gint child_size;
+
+ if (!gtk_widget_get_visible (child))
+ continue;
+
+ get_widget_size (child, orientation, line_thickness, NULL, &child_size);
+
+ line_size += child_size;
+ if (!first_widget)
+ line_size += spacing;
+ else
+ first_widget = FALSE;
+ }
+
+ largest_line = MAX (largest_line, line_size);
+ line_size = 0;
+ first_widget = TRUE;
+ }
+
+ if (segments)
+ *segments = g_memdup (priv->locked_config, lines * sizeof (gint));
+
+ g_list_free (children);
+
+ return largest_line;
+}
+
+
+/*****************************************************
+ * EggSpreadTableDndClass *
+ *****************************************************/
+static gboolean
+egg_spread_table_dnd_drop_possible (EggSpreadTableDnd *table,
+ GtkWidget *widget)
+{
+ return (GTK_WIDGET (table) == gtk_widget_get_parent (widget));
+}
+
+/*****************************************************
+ * Drag'n'Drop signals & other functions *
+ *****************************************************/
+
+static void
+drag_begin (GtkWidget *widget,
+ G_GNUC_UNUSED GdkDragContext *context,
+ EggSpreadTableDnd *spread_table)
+{
+ GtkAllocation allocation;
+ gint drop_index;
+
+ /* Mark the spread table for an active drag */
+ lock_table (spread_table);
+ spread_table->priv->dragging = TRUE;
+
+ /* Just assign a drag child, this is only important for
+ * child widgets that dont have a GdkWindow though really */
+ spread_table->priv->drag_child = widget;
+
+ /* Save the drag origin in case of failed drags and insert a placeholder as the first
+ * default drop target */
+ gtk_container_child_get (GTK_CONTAINER (spread_table),
+ spread_table->priv->drag_child,
+ "position", &drop_index,
+ NULL);
+
+ /* Create a placeholder of the correct dimentions and insert it at the drag origin */
+ gtk_widget_get_allocation (widget, &allocation);
+ spread_table->priv->drop_target = egg_placeholder_new (allocation.width, allocation.height);
+
+ egg_spread_table_insert_child (EGG_SPREAD_TABLE (spread_table),
+ spread_table->priv->drop_target,
+ drop_index);
+
+ /* Add one index for the new placeholder */
+ adjust_line_segment (spread_table,
+ get_child_line (spread_table, spread_table->priv->drop_target), 1);
+
+ /* Hide the drag child (we cant remove it because it needs a GdkWindow in the mean time) */
+ gtk_widget_hide (spread_table->priv->drag_child);
+}
+
+static void
+drag_end (G_GNUC_UNUSED GtkWidget *widget,
+ G_GNUC_UNUSED GdkDragContext *context,
+ EggSpreadTableDnd *spread_table)
+{
+ /* Sometimes when drag'n'drop happens very fast, drag-leave,
+ * drag-failed and drag-drop dont happen, so we cancel it out here
+ */
+ animate_out_drop_target (spread_table, TRUE);
+}
+
+static void
+drag_data_get (GtkWidget *widget,
+ G_GNUC_UNUSED GdkDragContext *context,
+ GtkSelectionData *selection,
+ G_GNUC_UNUSED guint info,
+ G_GNUC_UNUSED guint time,
+ EggSpreadTableDnd *spread_table)
+{
+ EggSpreadTableDndDragData drag_data = { spread_table, NULL };
+ GdkAtom target;
+
+ target = gtk_selection_data_get_target (selection);
+
+ if (target == dnd_target_atom_child)
+ {
+ drag_data.child = widget;
+
+ gtk_selection_data_set (selection, target, 8,
+ (guchar*) &drag_data, sizeof (drag_data));
+ }
+}
+
+static gboolean
+drag_failed (GtkWidget *widget,
+ G_GNUC_UNUSED GdkDragContext *drag_context,
+ G_GNUC_UNUSED GtkDragResult result,
+ G_GNUC_UNUSED EggSpreadTableDnd *spread_table)
+{
+ gtk_widget_show (widget);
+
+ return FALSE;
+}
+
+static gint
+get_index_at_position (EggSpreadTableDnd *spread_table,
+ gint x,
+ gint y,
+ gint *line_ret)
+{
+ EggSpreadTable *table;
+ GtkWidget *widget, *child;
+ GList *children, *l;
+ GtkAllocation allocation;
+ gint placeholder_cnt = 0;
+ GtkOrientation orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (spread_table));
+ gint *segments, lines, line = -1, i, full_size, spacing, position, line_width, first_child;
+ gint index = -1;
+
+ widget = GTK_WIDGET (spread_table);
+ table = EGG_SPREAD_TABLE (spread_table);
+
+ /* First find the "line" in question */
+ lines = egg_spread_table_get_lines (table);
+ segments = egg_spread_table_get_segments (table);
+
+ get_spread_table_dimentions (spread_table, -1, &spacing, NULL, &full_size, &line_width);
+
+ if (orientation == GTK_ORIENTATION_VERTICAL)
+ position = x;
+ else
+ position = y;
+
+ for (i = 0; i < lines; i++)
+ {
+ gint start, end;
+
+ start = line_width * i + (spacing / 2) * i;
+ end = start + line_width + (spacing / 2) * i;
+
+ if (i == lines - 1)
+ end = full_size;
+
+ if (position >= start && position <= end)
+ {
+ line = i;
+ break;
+ }
+ }
+ g_assert (line >= 0);
+
+ /* Get the first child on this line */
+ for (i = 0, first_child = 0; i < line; i++)
+ first_child += segments[i];
+
+ children = gtk_container_get_children (GTK_CONTAINER (spread_table));
+
+ for (l = g_list_nth (children, first_child), i = 0;
+ l != NULL && index < 0 && i < segments[line];
+ l = l->next, i++)
+ {
+ child = l->data;
+
+ if (!gtk_widget_get_visible (child))
+ continue;
+
+ gtk_widget_get_allocation (child, &allocation);
+
+ if (child == spread_table->priv->drop_target)
+ {
+ if (orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ if (y < allocation.y + allocation.height)
+ index = first_child + i;
+ }
+ else
+ {
+ if (x < allocation.x + allocation.width)
+ index = first_child + i;
+ }
+
+ placeholder_cnt++;
+ }
+ else
+ {
+ if (orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ if (y < allocation.y + allocation.height / 2)
+ index = first_child + i + placeholder_cnt;
+ }
+ else
+ {
+ if (x < allocation.x + allocation.width / 2)
+ index = first_child + i + placeholder_cnt;
+ }
+ }
+ }
+
+ if (index < 0)
+ index = first_child + segments[line];
+
+ g_list_free (children);
+
+ g_free (segments);
+
+ if (line_ret)
+ *line_ret = line;
+
+ g_assert (index >= 0);
+
+ return index;
+}
+
+static GtkWidget *
+get_child_at_position (EggSpreadTableDnd *spread_table,
+ gint x,
+ gint y)
+{
+ GtkWidget *child, *ret_child = NULL;
+ GList *children, *l;
+ GtkAllocation allocation;
+
+ children = gtk_container_get_children (GTK_CONTAINER (spread_table));
+
+ for (l = children; ret_child == NULL && l != NULL; l = l->next)
+ {
+ child = l->data;
+
+ if (!gtk_widget_get_visible (child))
+ continue;
+
+ gtk_widget_get_allocation (child, &allocation);
+
+ if (x >= allocation.x && x <= allocation.x + allocation.width &&
+ y >= allocation.y && y <= allocation.y + allocation.height)
+ {
+ ret_child = child;
+ }
+ }
+
+ g_list_free (children);
+
+ return ret_child;
+}
+
+static gboolean
+drop_possible (EggSpreadTableDnd *spread_table,
+ GtkWidget *widget)
+{
+ gboolean possible = FALSE;
+
+ g_signal_emit (spread_table, dnd_table_signals[SIGNAL_DROP_POSSIBLE], 0, widget, &possible);
+
+ return possible;
+}
+
+/* Copy of _gtk_boolean_handled_accumulator */
+static gboolean
+boolean_handled_accumulator (G_GNUC_UNUSED GSignalInvocationHint *ihint,
+ GValue *return_accu,
+ const GValue *handler_return,
+ G_GNUC_UNUSED gpointer dummy)
+{
+ gboolean continue_emission;
+ gboolean signal_handled;
+
+ signal_handled = g_value_get_boolean (handler_return);
+ g_value_set_boolean (return_accu, signal_handled);
+ continue_emission = !signal_handled;
+
+ return continue_emission;
+}
+
+static void
+adjust_line_segment (EggSpreadTableDnd *table,
+ gint segment,
+ gint offset)
+{
+ if (table->priv->locked_config)
+ table->priv->locked_config[segment] += offset;
+}
+
+static void
+animate_out_drop_target (EggSpreadTableDnd *table,
+ gboolean end)
+{
+ if (table->priv->drop_target &&
+ egg_placeholder_get_animating
+ (EGG_PLACEHOLDER (table->priv->drop_target)) != EGG_PLACEHOLDER_ANIM_OUT)
+ {
+ egg_placeholder_animate_out (EGG_PLACEHOLDER (table->priv->drop_target),
+ gtk_orientable_get_orientation (GTK_ORIENTABLE (table)));
+
+ g_signal_connect (table->priv->drop_target, "animation-done",
+ G_CALLBACK (placeholder_animated_out), table);
+
+ table->priv->disappearing++;
+ }
+
+ if (end)
+ table->priv->dragging = FALSE;
+}
+
+static void
+lock_table (EggSpreadTableDnd *table)
+
+{
+ if (table->priv->locked_config == NULL)
+ table->priv->locked_config = egg_spread_table_get_segments (EGG_SPREAD_TABLE (table));
+}
+
+static void
+unlock_table (EggSpreadTableDnd *table)
+{
+
+ g_free (table->priv->locked_config);
+ table->priv->locked_config = NULL;
+
+ gtk_widget_queue_resize (GTK_WIDGET (table));
+}
+
+/*****************************************************
+ * API *
+ *****************************************************/
+
+/**
+ * egg_spread_table_dnd_new:
+ * @orientation: The #GtkOrientation for the #EggSpreadTableDnd
+ * @lines: The fixed amount of lines to distribute children to.
+ *
+ * Creates a #EggSpreadTableDnd.
+ *
+ * Returns: A new #EggSpreadTableDnd container
+ */
+GtkWidget *
+egg_spread_table_dnd_new (GtkOrientation orientation,
+ guint lines)
+{
+ return (GtkWidget *)g_object_new (EGG_TYPE_SPREAD_TABLE_DND,
+ "orientation", orientation,
+ "lines", lines,
+ NULL);
+}
diff --git a/glom/utility_widgets/eggspreadtable/eggspreadtablednd.h b/glom/utility_widgets/eggspreadtable/eggspreadtablednd.h
new file mode 100644
index 0000000..36c323b
--- /dev/null
+++ b/glom/utility_widgets/eggspreadtable/eggspreadtablednd.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 Openismus GmbH
+ *
+ * Authors:
+ * Tristan Van Berkom <tristanvb openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_SPREAD_TABLE_DND_H__
+#define __EGG_SPREAD_TABLE_DND_H__
+
+#include <gtk/gtk.h>
+#include "eggspreadtable.h"
+
+G_BEGIN_DECLS
+
+
+#define EGG_TYPE_SPREAD_TABLE_DND (egg_spread_table_dnd_get_type ())
+#define EGG_SPREAD_TABLE_DND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SPREAD_TABLE_DND, EggSpreadTableDnd))
+#define EGG_SPREAD_TABLE_DND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SPREAD_TABLE_DND, EggSpreadTableDndClass))
+#define EGG_IS_SPREAD_TABLE_DND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SPREAD_TABLE_DND))
+#define EGG_IS_SPREAD_TABLE_DND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SPREAD_TABLE_DND))
+#define EGG_SPREAD_TABLE_DND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SPREAD_TABLE_DND, EggSpreadTableDndClass))
+
+typedef struct _EggSpreadTableDnd EggSpreadTableDnd;
+typedef struct _EggSpreadTableDndPrivate EggSpreadTableDndPrivate;
+typedef struct _EggSpreadTableDndClass EggSpreadTableDndClass;
+
+
+struct _EggSpreadTableDnd
+{
+ EggSpreadTable parent_instance;
+
+ /*< private >*/
+ EggSpreadTableDndPrivate *priv;
+};
+
+struct _EggSpreadTableDndClass
+{
+ EggSpreadTableClass parent_class;
+
+ gboolean (* widget_drop_possible) (EggSpreadTableDnd *table, GtkWidget *widget);
+};
+
+GType egg_spread_table_dnd_get_type (void) G_GNUC_CONST;
+GtkWidget *egg_spread_table_dnd_new (GtkOrientation orientation,
+ guint lines);
+
+
+G_END_DECLS
+
+
+#endif /* __EGG_SPREAD_TABLE_H__ */
diff --git a/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc
new file mode 100644
index 0000000..873700b
--- /dev/null
+++ b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc
@@ -0,0 +1,134 @@
+/*
+ *
+ * Copyright 2011 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h>
+#include <glom/utility_widgets/eggspreadtablemm/private/eggspreadtabledndmm_p.h>
+
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <glom/utility_widgets/eggspreadtable/eggspreadtablednd.h>
+
+namespace Glib
+{
+
+Egg::SpreadTableDnd* wrap(EggSpreadTableDnd* object, bool take_copy)
+{
+ return dynamic_cast<Egg::SpreadTableDnd *> (Glib::wrap_auto ((GObject*)(object), take_copy));
+}
+
+} /* namespace Glib */
+
+namespace Egg
+{
+
+
+/* The *_Class implementation: */
+
+const Glib::Class& SpreadTableDnd_Class::init()
+{
+ if(!gtype_) // create the GType if necessary
+ {
+ // Glib::Class has to know the class init function to clone custom types.
+ class_init_func_ = &SpreadTableDnd_Class::class_init_function;
+
+ // This is actually just optimized away, apparently with no harm.
+ // Make sure that the parent type has been created.
+ //CppClassParent::CppObjectType::get_type();
+
+ // Create the wrapper type, with the same class/instance size as the base type.
+ register_derived_type(egg_spread_table_get_type());
+
+ // Add derived versions of interfaces, if the C type implements any interfaces:
+ Gtk::Orientable::add_interface(get_type());
+
+ }
+
+ return *this;
+}
+
+
+void SpreadTableDnd_Class::class_init_function(void* g_class, void* class_data)
+{
+ BaseClassType *const klass = static_cast<BaseClassType*>(g_class);
+ CppClassParent::class_init_function(klass, class_data);
+
+
+}
+
+
+Glib::ObjectBase* SpreadTableDnd_Class::wrap_new(GObject* o)
+{
+ return manage(new SpreadTableDnd((EggSpreadTableDnd*)(o)));
+
+}
+
+
+/* The implementation: */
+
+SpreadTableDnd::SpreadTableDnd(const Glib::ConstructParams& construct_params)
+:
+ SpreadTable(construct_params)
+{
+ }
+
+SpreadTableDnd::SpreadTableDnd(EggSpreadTableDnd* castitem)
+:
+ SpreadTable((EggSpreadTable*)(castitem))
+{
+ }
+
+SpreadTableDnd::~SpreadTableDnd()
+{
+ destroy_();
+}
+
+SpreadTableDnd::CppClassType SpreadTableDnd::spreadtable_class_; // initialize static member
+
+GType SpreadTableDnd::get_type()
+{
+ return spreadtable_class_.init().get_type();
+}
+
+
+GType SpreadTableDnd::get_base_type()
+{
+ return egg_spread_table_get_type();
+}
+
+
+SpreadTableDnd::SpreadTableDnd()
+:
+ // Mark this class as non-derived to allow C++ vfuncs to be skipped.
+ Glib::ObjectBase(0),
+ SpreadTable(Glib::ConstructParams(spreadtable_class_.init()))
+{
+
+
+}
+
+SpreadTableDnd::SpreadTableDnd(Gtk::Orientation orientation, guint lines)
+:
+ // Mark this class as non-derived to allow C++ vfuncs to be skipped.
+ Glib::ObjectBase(0),
+ SpreadTable(Glib::ConstructParams(spreadtable_class_.init(), "orientation", ((GtkOrientation)(orientation)), "lines", lines, static_cast<char*>(0)))
+{
+}
+
+} // namespace Egg
diff --git a/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h
new file mode 100644
index 0000000..069a65b
--- /dev/null
+++ b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h
@@ -0,0 +1,113 @@
+/* Copyright (C) 2011 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _EGG_SPREADTABLE_DND_H
+#define _EGG_SPREADTABLE_DND_H
+
+#include <glom/utility_widgets/eggspreadtablemm/eggspreadtablemm.h>
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+typedef struct _EggSpreadTableDnd EggSpreadTableDnd;
+typedef struct _EggSpreadTableDndClass EggSpreadTableDndClass;
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+
+namespace Egg
+{ class SpreadTableDnd_Class; } // namespace Egg
+namespace Egg
+{
+
+class SpreadTableDnd
+: public SpreadTable
+{
+ public:
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ typedef SpreadTableDnd CppObjectType;
+ typedef SpreadTableDnd_Class CppClassType;
+ typedef EggSpreadTableDnd BaseObjectType;
+ typedef EggSpreadTableDndClass BaseClassType;
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+ virtual ~SpreadTableDnd();
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+private:
+ friend class SpreadTableDnd_Class;
+ static CppClassType spreadtable_class_;
+
+ // noncopyable
+ SpreadTableDnd(const SpreadTableDnd&);
+ SpreadTableDnd& operator=(const SpreadTableDnd&);
+
+protected:
+ explicit SpreadTableDnd(const Glib::ConstructParams& construct_params);
+ explicit SpreadTableDnd(EggSpreadTableDnd* castitem);
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+public:
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ static GType get_type() G_GNUC_CONST;
+
+
+ static GType get_base_type() G_GNUC_CONST;
+#endif
+
+ ///Provides access to the underlying C GtkObject.
+ EggSpreadTableDnd* gobj() { return reinterpret_cast<EggSpreadTableDnd*>(gobject_); }
+
+ ///Provides access to the underlying C GtkObject.
+ const EggSpreadTableDnd* gobj() const { return reinterpret_cast<EggSpreadTableDnd*>(gobject_); }
+
+
+public:
+ //C++ methods used to invoke GTK+ virtual functions:
+
+protected:
+ //GTK+ Virtual Functions (override these to change behaviour):
+
+ //Default Signal Handlers::
+
+
+private:
+
+
+public:
+ SpreadTableDnd();
+ explicit SpreadTableDnd(Gtk::Orientation orientation, guint lines);
+};
+
+} // namespace Egg
+
+
+namespace Glib
+{
+ /** A Glib::wrap() method for this object.
+ *
+ * @param object The C instance.
+ * @param take_copy False if the result should take ownership of the C instance. True if it should take a new copy or ref.
+ * @result A C++ instance that wraps this C instance.
+ *
+ * @relates Egg::SpreadTableDnd
+ */
+ Egg::SpreadTableDnd* wrap(EggSpreadTableDnd* object, bool take_copy = false);
+} //namespace Glib
+
+
+#endif /* _EGG_SPREADTABLE_H */
diff --git a/glom/utility_widgets/eggspreadtablemm/private/eggspreadtabledndmm_p.h b/glom/utility_widgets/eggspreadtablemm/private/eggspreadtabledndmm_p.h
new file mode 100644
index 0000000..7acf0f9
--- /dev/null
+++ b/glom/utility_widgets/eggspreadtablemm/private/eggspreadtabledndmm_p.h
@@ -0,0 +1,45 @@
+#ifndef _EGG_SPREADTABLE_DND_P_H
+#define _EGG_SPREADTABLE_DND_P_H
+
+
+#include <glom/utility_widgets/eggspreadtablemm/private/eggspreadtablemm_p.h>
+
+#include <glibmm/class.h>
+
+namespace Egg
+{
+
+class SpreadTableDnd_Class : public Glib::Class
+{
+public:
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ typedef SpreadTableDnd CppObjectType;
+ typedef EggSpreadTableDnd BaseObjectType;
+ typedef EggSpreadTableDndClass BaseClassType;
+ typedef SpreadTable_Class CppClassParent;
+ typedef EggSpreadTableClass BaseClassParent;
+
+ friend class SpreadTableDnd;
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+ const Glib::Class& init();
+
+
+ static void class_init_function(void* g_class, void* class_data);
+
+ static Glib::ObjectBase* wrap_new(GObject*);
+
+protected:
+
+ //Callbacks (default signal handlers):
+ //These will call the *_impl member methods, which will then call the existing default signal callbacks, if any.
+ //You could prevent the original default signal handlers being called by overriding the *_impl method.
+
+ //Callbacks (virtual functions):
+};
+
+
+} // namespace Egg
+
+
+#endif /* _EGG_SPREADTABLE_P_H */
diff --git a/glom/utility_widgets/flowtable.h b/glom/utility_widgets/flowtable.h
index 8a426e3..df1c95c 100644
--- a/glom/utility_widgets/flowtable.h
+++ b/glom/utility_widgets/flowtable.h
@@ -22,13 +22,13 @@
#define GLOM_UTILITYWIDGETS_FLOWTABLE_H
#include <gtkmm.h>
-#include <glom/utility_widgets/eggspreadtablemm/eggspreadtablemm.h>
+#include <glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h>
#include "layoutwidgetbase.h"
namespace Glom
{
-class FlowTable : public Egg::SpreadTable
+class FlowTable : public Egg::SpreadTableDnd
{
public:
FlowTable();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]