aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher James Lahey <clahey@ximian.com>2001-05-08 12:56:03 +0800
committerChris Lahey <clahey@src.gnome.org>2001-05-08 12:56:03 +0800
commit5d4895eb431adfbf2c7895d4257fa20a28f474f9 (patch)
treeb9ffd215f0444ecd0349f459fa77aa1069f0a524
parentc1a0dc0e04b739acc5c35aa3ea761dae11632f9d (diff)
downloadgsoc2013-evolution-5d4895eb431adfbf2c7895d4257fa20a28f474f9.tar.gz
gsoc2013-evolution-5d4895eb431adfbf2c7895d4257fa20a28f474f9.tar.zst
gsoc2013-evolution-5d4895eb431adfbf2c7895d4257fa20a28f474f9.zip
Added util/e-sorter-array.lo and widgets/e-reflow-model.lo. Removed
2001-05-07 Christopher James Lahey <clahey@ximian.com> * gal/Makefile.am (libgal_la_LIBADD): Added util/e-sorter-array.lo and widgets/e-reflow-model.lo. Removed widgets/e-reflow-sorted.lo. * gal/util/Makefile.am (libutil_la_SOURCES): Added e-sorter-array.c. (libgalinclude_HEADERS): Added e-sorter-array.h. * gal/util/e-sorter-array.c, gal/util/e-sorter-array.h: A sorter for use with a single compare function to do sorting. * gal/util/e-util.c, gal/util/e-util.h (e_marshal_INT__OBJECT_POINTER): Added this marshaller. * gal/widgets/Makefile.am (libwidgets_la_SOURCES): Added e-reflow-model.c. Removed e-reflow-sorted.c. (libwidgetsinclude_HEADERS): Added e-reflow-sorted.h. Removed e-reflow-model.h. * gal/widgets/e-reflow-model.c, gal/widgets/e-reflow-model.h: Model for EReflow. Has a number of items and generates canvas items on the fly. * gal/widgets/e-reflow.c, gal/widgets/e-reflow.h: Major rewrite. This now uses a model to generate its canvas items instead of having canvas items added to it. It doesn't create the canvas items now until they will be shown on screen. svn path=/trunk/; revision=9710
-rw-r--r--e-util/e-sorter-array.c278
-rw-r--r--e-util/e-sorter-array.h56
-rw-r--r--e-util/e-util.c21
-rw-r--r--e-util/e-util.h21
-rw-r--r--widgets/misc/e-reflow-model.c288
-rw-r--r--widgets/misc/e-reflow-model.h83
-rw-r--r--widgets/misc/e-reflow.c1190
-rw-r--r--widgets/misc/e-reflow.h48
8 files changed, 1564 insertions, 421 deletions
diff --git a/e-util/e-sorter-array.c b/e-util/e-sorter-array.c
new file mode 100644
index 0000000000..44cf7b0f67
--- /dev/null
+++ b/e-util/e-sorter-array.c
@@ -0,0 +1,278 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * e-sorter-array.c:
+ *
+ * Author:
+ * Christopher James Lahey <clahey@ximian.com>
+ *
+ * (C) 2001 Ximian, Inc.
+ */
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gtk/gtksignal.h>
+#include "gal/util/e-util.h"
+#include "e-sorter-array.h"
+
+#define d(x)
+
+/* The arguments we take */
+enum {
+ ARG_0,
+};
+
+#define PARENT_TYPE e_sorter_get_type()
+
+#define INCREMENT_AMOUNT 100
+
+static ESorterClass *parent_class;
+
+static void esa_sort (ESorterArray *esa);
+static void esa_backsort (ESorterArray *esa);
+
+static gint esa_model_to_sorted (ESorter *sorter, int row);
+static gint esa_sorted_to_model (ESorter *sorter, int row);
+static void esa_get_model_to_sorted_array (ESorter *sorter, int **array, int *count);
+static void esa_get_sorted_to_model_array (ESorter *sorter, int **array, int *count);
+static gboolean esa_needs_sorting (ESorter *esa);
+
+#define ESA_NEEDS_SORTING(esa) (((ESorterArray *) (esa))->compare != NULL)
+
+static int
+esort_callback(const void *data1, const void *data2, gpointer user_data)
+{
+ ESorterArray *esa = user_data;
+ int ret_val;
+ int int1, int2;
+
+ int1 = *(int *)data1;
+ int2 = *(int *)data2;
+
+ ret_val = esa->compare (int1, int2, esa->closure);
+ if (ret_val != 0)
+ return ret_val;
+
+ if (int1 < int2)
+ return -1;
+ if (int1 > int2)
+ return 1;
+ return 0;
+}
+
+static void
+esa_sort(ESorterArray *esa)
+{
+ int rows;
+ int i;
+
+ if (esa->sorted)
+ return;
+
+ rows = esa->rows;
+
+ esa->sorted = g_new(int, rows);
+ for (i = 0; i < rows; i++)
+ esa->sorted[i] = i;
+
+ if (esa->compare)
+ e_sort (esa->sorted, rows, sizeof(int), esort_callback, esa);
+}
+
+static void
+esa_backsort(ESorterArray *esa)
+{
+ int i, rows;
+
+ if (esa->backsorted)
+ return;
+
+ esa_sort(esa);
+
+ rows = esa->rows;
+
+ esa->backsorted = g_new0(int, rows);
+
+ for (i = 0; i < rows; i++) {
+ esa->backsorted[esa->sorted[i]] = i;
+ }
+}
+
+
+static gint
+esa_model_to_sorted (ESorter *es, int row)
+{
+ ESorterArray *esa = E_SORTER_ARRAY(es);
+
+ g_return_val_if_fail(row >= 0, -1);
+ g_return_val_if_fail(row < esa->rows, -1);
+
+ if (ESA_NEEDS_SORTING(es))
+ esa_backsort(esa);
+
+ if (esa->backsorted)
+ return esa->backsorted[row];
+ else
+ return row;
+}
+
+static gint
+esa_sorted_to_model (ESorter *es, int row)
+{
+ ESorterArray *esa = (ESorterArray *) es;
+
+ g_return_val_if_fail(row >= 0, -1);
+ g_return_val_if_fail(row < esa->rows, -1);
+
+ if (ESA_NEEDS_SORTING(es))
+ esa_sort(esa);
+
+ if (esa->sorted)
+ return esa->sorted[row];
+ else
+ return row;
+}
+
+static void
+esa_get_model_to_sorted_array (ESorter *es, int **array, int *count)
+{
+ ESorterArray *esa = E_SORTER_ARRAY(es);
+ if (array || count) {
+ esa_backsort(esa);
+
+ if (array)
+ *array = esa->backsorted;
+ if (count)
+ *count = esa->rows;
+ }
+}
+
+static void
+esa_get_sorted_to_model_array (ESorter *es, int **array, int *count)
+{
+ ESorterArray *esa = E_SORTER_ARRAY(es);
+ if (array || count) {
+ esa_sort(esa);
+
+ if (array)
+ *array = esa->sorted;
+ if (count)
+ *count = esa->rows;
+ }
+}
+
+static gboolean
+esa_needs_sorting(ESorter *es)
+{
+ ESorterArray *esa = E_SORTER_ARRAY(es);
+ return esa->compare != NULL;
+}
+
+void
+e_sorter_array_clean(ESorterArray *esa)
+{
+ g_free(esa->sorted);
+ esa->sorted = NULL;
+
+ g_free(esa->backsorted);
+ esa->backsorted = NULL;
+}
+
+void
+e_sorter_array_set_count (ESorterArray *esa, int count)
+{
+ e_sorter_array_clean (esa);
+ esa->rows = count;
+}
+
+void
+e_sorter_array_append (ESorterArray *esa, int count)
+{
+ int i;
+ g_free(esa->backsorted);
+ esa->backsorted = NULL;
+
+ if (esa->sorted) {
+ esa->sorted = g_renew(int, esa->sorted, esa->rows + count);
+ for (i = 0; i < count; i++) {
+ int value = esa->rows;
+ int pos;
+ e_bsearch (&value, esa->sorted, esa->rows, sizeof (int), esort_callback, esa, &pos, NULL);
+ memmove (esa->sorted + pos + 1, esa->sorted + pos, sizeof (int) * (esa->rows - pos));
+ esa->sorted[pos] = value;
+ esa->rows ++;
+ }
+ } else {
+ esa->rows = count;
+ }
+}
+
+ESorterArray *
+e_sorter_array_construct (ESorterArray *esa,
+ ECompareRowsFunc compare,
+ gpointer closure)
+{
+ esa->compare = compare;
+ esa->closure = closure;
+ return esa;
+}
+
+ESorterArray *
+e_sorter_array_new (ECompareRowsFunc compare, gpointer closure)
+{
+ ESorterArray *esa = gtk_type_new (E_SORTER_ARRAY_TYPE);
+
+ return e_sorter_array_construct (esa, compare, closure);
+}
+
+static void
+esa_destroy (GtkObject *object)
+{
+ GTK_OBJECT_CLASS (parent_class)->destroy (object);
+}
+
+static void
+esa_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ switch (arg_id) {
+ default:
+ break;
+ }
+}
+
+static void
+esa_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ switch (arg_id) {
+ }
+}
+
+static void
+esa_class_init (ESorterArrayClass *klass)
+{
+ GtkObjectClass *object_class = GTK_OBJECT_CLASS(klass);
+ ESorterClass *sorter_class = E_SORTER_CLASS(klass);
+
+ parent_class = gtk_type_class (PARENT_TYPE);
+
+ object_class->destroy = esa_destroy;
+ object_class->set_arg = esa_set_arg;
+ object_class->get_arg = esa_get_arg;
+
+ sorter_class->model_to_sorted = esa_model_to_sorted ;
+ sorter_class->sorted_to_model = esa_sorted_to_model ;
+ sorter_class->get_model_to_sorted_array = esa_get_model_to_sorted_array ;
+ sorter_class->get_sorted_to_model_array = esa_get_sorted_to_model_array ;
+ sorter_class->needs_sorting = esa_needs_sorting ;
+}
+
+static void
+esa_init (ESorterArray *esa)
+{
+ esa->rows = 0;
+ esa->compare = NULL;
+ esa->closure = NULL;
+ esa->sorted = NULL;
+ esa->backsorted = NULL;
+}
+
+E_MAKE_TYPE(e_sorter_array, "ESorterArray", ESorterArray, esa_class_init, esa_init, PARENT_TYPE);
diff --git a/e-util/e-sorter-array.h b/e-util/e-sorter-array.h
new file mode 100644
index 0000000000..7f876e4148
--- /dev/null
+++ b/e-util/e-sorter-array.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#ifndef _E_SORTER_ARRAY_H_
+#define _E_SORTER_ARRAY_H_
+
+#include <gtk/gtkobject.h>
+#include <gal/util/e-sorter.h>
+#include <glib.h>
+#include <libgnome/gnome-defs.h>
+
+BEGIN_GNOME_DECLS
+
+#define E_SORTER_ARRAY_TYPE (e_sorter_array_get_type ())
+#define E_SORTER_ARRAY(o) (GTK_CHECK_CAST ((o), E_SORTER_ARRAY_TYPE, ESorterArray))
+#define E_SORTER_ARRAY_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_SORTER_ARRAY_TYPE, ESorterArrayClass))
+#define E_IS_SORTER_ARRAY(o) (GTK_CHECK_TYPE ((o), E_SORTER_ARRAY_TYPE))
+#define E_IS_SORTER_ARRAY_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_SORTER_ARRAY_TYPE))
+
+#ifndef _E_COMPARE_ROWS_FUNC_H_
+#define _E_COMPARE_ROWS_FUNC_H_
+typedef int (*ECompareRowsFunc) (int row1,
+ int row2,
+ gpointer closure);
+#endif
+
+typedef struct {
+ ESorter base;
+
+ ECompareRowsFunc compare;
+ gpointer closure;
+
+ /* If needs_sorting is 0, then model_to_sorted and sorted_to_model are no-ops. */
+ int *sorted;
+ int *backsorted;
+
+ int rows;
+} ESorterArray;
+
+typedef struct {
+ ESorterClass parent_class;
+} ESorterArrayClass;
+
+GtkType e_sorter_array_get_type (void);
+ESorterArray *e_sorter_array_construct (ESorterArray *sorter,
+ ECompareRowsFunc compare,
+ gpointer closure);
+ESorterArray *e_sorter_array_new (ECompareRowsFunc compare,
+ gpointer closure);
+void e_sorter_array_clean (ESorterArray *esa);
+void e_sorter_array_set_count (ESorterArray *esa,
+ int count);
+void e_sorter_array_append (ESorterArray *esa,
+ int count);
+
+END_GNOME_DECLS
+
+#endif /* _E_SORTER_ARRAY_H_ */
diff --git a/e-util/e-util.c b/e-util/e-util.c
index 5bbb9522b4..d7770ac3fa 100644
--- a/e-util/e-util.c
+++ b/e-util/e-util.c
@@ -678,6 +678,27 @@ e_marshal_NONE__POINTER_INT_INT_INT (GtkObject *object,
func_data);
}
+typedef int (*GtkSignal_INT__OBJECT_POINTER) (GtkObject *,
+ GtkObject *, gpointer,
+ gpointer user_data);
+void
+e_marshal_INT__OBJECT_POINTER (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ GtkSignal_INT__OBJECT_POINTER rfunc;
+ int *return_val;
+
+ rfunc = (GtkSignal_INT__OBJECT_POINTER) func;
+ return_val = GTK_RETLOC_INT (args[2]);
+
+ *return_val = (*rfunc) (object,
+ GTK_VALUE_OBJECT (args[0]),
+ GTK_VALUE_POINTER (args[1]),
+ func_data);
+}
+
gchar**
e_strsplit (const gchar *string,
const gchar *delimiter,
diff --git a/e-util/e-util.h b/e-util/e-util.h
index bf89b27aa1..c131676fc6 100644
--- a/e-util/e-util.h
+++ b/e-util/e-util.h
@@ -80,14 +80,12 @@ gchar *e_strstrcase (cons
void e_filename_make_safe (gchar *string);
gchar *e_format_number (gint number);
gchar *e_format_number_float (gfloat number);
-
gboolean e_create_directory (gchar *directory);
typedef int (*ESortCompareFunc) (const void *first,
const void *second,
gpointer closure);
-
void e_sort (void *base,
size_t nmemb,
size_t size,
@@ -99,11 +97,8 @@ void e_bsearch (cons
size_t size,
ESortCompareFunc compare,
gpointer closure,
- size_t *start,
- size_t *end);
-
-
-
+ size_t *start,
+ size_t *end);
void e_marshal_INT__INT_INT_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
@@ -192,11 +187,15 @@ void e_marshal_INT__POINTER_POINTER_POINTER_POINTER (GtkO
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
+void e_marshal_NONE__POINTER_INT_INT_INT (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+void e_marshal_INT__OBJECT_POINTER (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
-void e_marshal_NONE__POINTER_INT_INT_INT (GtkObject *object,
- GtkSignalFunc func,
- gpointer func_data,
- GtkArg *args);
#ifdef __cplusplus
}
diff --git a/widgets/misc/e-reflow-model.c b/widgets/misc/e-reflow-model.c
new file mode 100644
index 0000000000..74e7b1726c
--- /dev/null
+++ b/widgets/misc/e-reflow-model.c
@@ -0,0 +1,288 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * e-reflow-model.c: a Reflow Model
+ *
+ * Authors:
+ * Chris Lahey <clahey@ximian.com>
+ *
+ * (C) 2001 Ximian, Inc.
+ */
+#include <config.h>
+#include "e-reflow-model.h"
+#include <gtk/gtksignal.h>
+
+#define ERM_CLASS(e) ((EReflowModelClass *)((GtkObject *)e)->klass)
+
+#define PARENT_TYPE gtk_object_get_type ()
+
+#define d(x)
+
+d(static gint depth = 0);
+
+
+static GtkObjectClass *e_reflow_model_parent_class;
+
+enum {
+ MODEL_CHANGED,
+ MODEL_ITEMS_INSERTED,
+ MODEL_ITEM_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint e_reflow_model_signals [LAST_SIGNAL] = { 0, };
+
+/**
+ * e_reflow_model_set_width:
+ * @e_reflow_model: The e-reflow-model to operate on
+ * @width: The new value for the width of each item.
+ */
+void
+e_reflow_model_set_width (EReflowModel *e_reflow_model, int width)
+{
+ g_return_if_fail (e_reflow_model != NULL);
+ g_return_if_fail (E_IS_REFLOW_MODEL (e_reflow_model));
+
+ ERM_CLASS (e_reflow_model)->set_width (e_reflow_model, width);
+}
+
+/**
+ * e_reflow_model_count:
+ * @e_reflow_model: The e-reflow-model to operate on
+ *
+ * Returns: the number of items in the reflow model.
+ */
+int
+e_reflow_model_count (EReflowModel *e_reflow_model)
+{
+ g_return_val_if_fail (e_reflow_model != NULL, 0);
+ g_return_val_if_fail (E_IS_REFLOW_MODEL (e_reflow_model), 0);
+
+ return ERM_CLASS (e_reflow_model)->count (e_reflow_model);
+}
+
+/**
+ * e_reflow_model_height:
+ * @e_reflow_model: The e-reflow-model to operate on
+ * @n: The item number to get the height of.
+ * @parent: The parent GnomeCanvasItem.
+ *
+ * Returns: the height of the nth item.
+ */
+int
+e_reflow_model_height (EReflowModel *e_reflow_model, int n, GnomeCanvasGroup *parent)
+{
+ g_return_val_if_fail (e_reflow_model != NULL, 0);
+ g_return_val_if_fail (E_IS_REFLOW_MODEL (e_reflow_model), 0);
+
+ return ERM_CLASS (e_reflow_model)->height (e_reflow_model, n, parent);
+}
+
+/**
+ * e_reflow_model_incarnate:
+ * @e_reflow_model: The e-reflow-model to operate on
+ * @n: The item to create.
+ * @parent: The parent GnomeCanvasItem to create a child of.
+ *
+ * Create a GnomeCanvasItem to represent the nth piece of data.
+ *
+ * Returns: the new GnomeCanvasItem.
+ */
+GnomeCanvasItem *
+e_reflow_model_incarnate (EReflowModel *e_reflow_model, int n, GnomeCanvasGroup *parent)
+{
+ g_return_val_if_fail (e_reflow_model != NULL, NULL);
+ g_return_val_if_fail (E_IS_REFLOW_MODEL (e_reflow_model), NULL);
+
+ return ERM_CLASS (e_reflow_model)->incarnate (e_reflow_model, n, parent);
+}
+
+/**
+ * e_reflow_model_compare:
+ * @e_reflow_model: The e-reflow-model to operate on
+ * @n1: The first item to compare
+ * @n2: The second item to compare
+ *
+ * Compares item n1 and item n2 to see which should come first.
+ *
+ * Returns: strcmp like semantics for the comparison value.
+ */
+int
+e_reflow_model_compare (EReflowModel *e_reflow_model, int n1, int n2)
+{
+#if 0
+ g_return_val_if_fail (e_reflow_model != NULL, 0);
+ g_return_val_if_fail (E_IS_REFLOW_MODEL (e_reflow_model), 0);
+#endif
+
+ return ERM_CLASS (e_reflow_model)->compare (e_reflow_model, n1, n2);
+}
+
+/**
+ * e_reflow_model_reincarnate:
+ * @e_reflow_model: The e-reflow-model to operate on
+ * @n: The item to create.
+ * @item: The item to reuse.
+ *
+ * Update item to represent the nth piece of data.
+ */
+void
+e_reflow_model_reincarnate (EReflowModel *e_reflow_model, int n, GnomeCanvasItem *item)
+{
+ g_return_if_fail (e_reflow_model != NULL);
+ g_return_if_fail (E_IS_REFLOW_MODEL (e_reflow_model));
+
+ ERM_CLASS (e_reflow_model)->reincarnate (e_reflow_model, n, item);
+}
+
+static void
+e_reflow_model_class_init (GtkObjectClass *object_class)
+{
+ EReflowModelClass *klass = E_REFLOW_MODEL_CLASS(object_class);
+ e_reflow_model_parent_class = gtk_type_class (PARENT_TYPE);
+
+ e_reflow_model_signals [MODEL_CHANGED] =
+ gtk_signal_new ("model_changed",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EReflowModelClass, model_changed),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ e_reflow_model_signals [MODEL_ITEMS_INSERTED] =
+ gtk_signal_new ("model_items_inserted",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EReflowModelClass, model_items_inserted),
+ gtk_marshal_NONE__INT_INT,
+ GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
+
+ e_reflow_model_signals [MODEL_ITEM_CHANGED] =
+ gtk_signal_new ("model_item_changed",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EReflowModelClass, model_item_changed),
+ gtk_marshal_NONE__INT,
+ GTK_TYPE_NONE, 1, GTK_TYPE_INT);
+
+ gtk_object_class_add_signals (object_class, e_reflow_model_signals, LAST_SIGNAL);
+
+ klass->set_width = NULL;
+ klass->count = NULL;
+ klass->height = NULL;
+ klass->incarnate = NULL;
+ klass->reincarnate = NULL;
+
+ klass->model_changed = NULL;
+ klass->model_items_inserted = NULL;
+ klass->model_item_changed = NULL;
+}
+
+
+guint
+e_reflow_model_get_type (void)
+{
+ static guint type = 0;
+
+ if (!type)
+ {
+ GtkTypeInfo info =
+ {
+ "EReflowModel",
+ sizeof (EReflowModel),
+ sizeof (EReflowModelClass),
+ (GtkClassInitFunc) e_reflow_model_class_init,
+ NULL,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ type = gtk_type_unique (PARENT_TYPE, &info);
+ }
+
+ return type;
+}
+
+#if d(!)0
+static void
+print_tabs (void)
+{
+ int i;
+ for (i = 0; i < depth; i++)
+ g_print("\t");
+}
+#endif
+
+/**
+ * e_reflow_model_changed:
+ * @e_reflow_model: the reflow model to notify of the change
+ *
+ * Use this function to notify any views of this reflow model that
+ * the contents of the reflow model have changed. This will emit
+ * the signal "model_changed" on the @e_reflow_model object.
+ *
+ * It is preferable to use the e_reflow_model_item_changed() signal to
+ * notify of smaller changes than to invalidate the entire model, as
+ * the views might have ways of caching the information they render
+ * from the model.
+ */
+void
+e_reflow_model_changed (EReflowModel *e_reflow_model)
+{
+ g_return_if_fail (e_reflow_model != NULL);
+ g_return_if_fail (E_IS_REFLOW_MODEL (e_reflow_model));
+
+ d(print_tabs());
+ d(g_print("Emitting model_changed on model 0x%p.\n", e_reflow_model));
+ d(depth++);
+ gtk_signal_emit (GTK_OBJECT (e_reflow_model),
+ e_reflow_model_signals [MODEL_CHANGED]);
+ d(depth--);
+}
+
+/**
+ * e_reflow_model_items_inserted:
+ * @e_reflow_model: The model changed.
+ * @position: The position the items were insert in.
+ * @count: The number of items inserted.
+ *
+ * Use this function to notify any views of the reflow model that a number of items have been inserted.
+ **/
+void
+e_reflow_model_items_inserted (EReflowModel *e_reflow_model, int position, int count)
+{
+ g_return_if_fail (e_reflow_model != NULL);
+ g_return_if_fail (E_IS_REFLOW_MODEL (e_reflow_model));
+
+ d(print_tabs());
+ d(g_print("Emitting items_inserted on model 0x%p, position=%d, count=%d.\n", e_reflow_model, position, count));
+ d(depth++);
+ gtk_signal_emit (GTK_OBJECT (e_reflow_model),
+ e_reflow_model_signals [MODEL_ITEMS_INSERTED], position, count);
+ d(depth--);
+}
+
+/**
+ * e_reflow_model_item_changed:
+ * @e_reflow_model: the reflow model to notify of the change
+ * @item: the item that was changed in the model.
+ *
+ * Use this function to notify any views of the reflow model that the
+ * contents of item @item have changed in model such that the height
+ * has changed or the item needs to be reincarnated. This function
+ * will emit the "model_item_changed" signal on the @e_reflow_model
+ * object
+ */
+void
+e_reflow_model_item_changed (EReflowModel *e_reflow_model, int n)
+{
+ g_return_if_fail (e_reflow_model != NULL);
+ g_return_if_fail (E_IS_REFLOW_MODEL (e_reflow_model));
+
+ d(print_tabs());
+ d(g_print("Emitting item_changed on model 0x%p, n=%d.\n", e_reflow_model, n));
+ d(depth++);
+ gtk_signal_emit (GTK_OBJECT (e_reflow_model),
+ e_reflow_model_signals [MODEL_ITEM_CHANGED], n);
+ d(depth--);
+}
diff --git a/widgets/misc/e-reflow-model.h b/widgets/misc/e-reflow-model.h
new file mode 100644
index 0000000000..db26335a35
--- /dev/null
+++ b/widgets/misc/e-reflow-model.h
@@ -0,0 +1,83 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#ifndef _E_REFLOW_MODEL_H_
+#define _E_REFLOW_MODEL_H_
+
+#include <gtk/gtkobject.h>
+#include <libgnomeui/gnome-canvas.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define E_REFLOW_MODEL_TYPE (e_reflow_model_get_type ())
+#define E_REFLOW_MODEL(o) (GTK_CHECK_CAST ((o), E_REFLOW_MODEL_TYPE, EReflowModel))
+#define E_REFLOW_MODEL_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_REFLOW_MODEL_TYPE, EReflowModelClass))
+#define E_IS_REFLOW_MODEL(o) (GTK_CHECK_TYPE ((o), E_REFLOW_MODEL_TYPE))
+#define E_IS_REFLOW_MODEL_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_REFLOW_MODEL_TYPE))
+
+typedef struct {
+ GtkObject base;
+} EReflowModel;
+
+typedef struct {
+ GtkObjectClass parent_class;
+
+ /*
+ * Virtual methods
+ */
+ void (*set_width) (EReflowModel *etm, int width);
+
+ int (*count) (EReflowModel *etm);
+ int (*height) (EReflowModel *etm, int n, GnomeCanvasGroup *parent);
+ GnomeCanvasItem *(*incarnate) (EReflowModel *etm, int n, GnomeCanvasGroup *parent);
+ int (*compare) (EReflowModel *etm, int n1, int n2);
+ void (*reincarnate) (EReflowModel *etm, int n, GnomeCanvasItem *item);
+
+ /*
+ * Signals
+ */
+
+ /*
+ * These all come after the change has been made.
+ * Major structural changes: model_changed
+ * Changes only in an item: item_changed
+ */
+ void (*model_changed) (EReflowModel *etm);
+ void (*model_items_inserted) (EReflowModel *etm, int position, int count);
+ void (*model_item_changed) (EReflowModel *etm, int n);
+} EReflowModelClass;
+
+GtkType e_reflow_model_get_type (void);
+
+/**/
+void e_reflow_model_set_width (EReflowModel *e_reflow_model,
+ int width);
+int e_reflow_model_count (EReflowModel *e_reflow_model);
+int e_reflow_model_height (EReflowModel *e_reflow_model,
+ int n,
+ GnomeCanvasGroup *parent);
+GnomeCanvasItem *e_reflow_model_incarnate (EReflowModel *e_reflow_model,
+ int n,
+ GnomeCanvasGroup *parent);
+int e_reflow_model_compare (EReflowModel *e_reflow_model,
+ int n1,
+ int n2);
+void e_reflow_model_reincarnate (EReflowModel *e_reflow_model,
+ int n,
+ GnomeCanvasItem *item);
+
+/*
+ * Routines for emitting signals on the e_reflow
+ */
+void e_reflow_model_changed (EReflowModel *e_reflow_model);
+void e_reflow_model_items_inserted (EReflowModel *e_reflow_model,
+ int position,
+ int count);
+void e_reflow_model_item_changed (EReflowModel *e_reflow_model,
+ int n);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _E_REFLOW_MODEL_H_ */
diff --git a/widgets/misc/e-reflow.c b/widgets/misc/e-reflow.c
index d67d501019..65fb2f91a6 100644
--- a/widgets/misc/e-reflow.c
+++ b/widgets/misc/e-reflow.c
@@ -1,7 +1,7 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* e-reflow.c
- * Copyright (C) 2000 Helix Code, Inc.
+ * Copyright (C) 2000, 2001 Ximian, Inc.
* Author: Chris Lahey <clahey@helixcode.com>
*
* This library is free software; you can redistribute it and/or
@@ -21,19 +21,20 @@
*/
#include <config.h>
+
+#include "e-reflow.h"
+
#include <math.h>
#include <gdk/gdkkeysyms.h>
-#include "e-reflow.h"
#include "e-canvas-utils.h"
#include "e-canvas.h"
#include "gal/e-text/e-text.h"
#include "gal/util/e-util.h"
+#include <gtk/gtksignal.h>
+#include "e-selection-model-simple.h"
+
+#include <string.h>
-static void e_reflow_init (EReflow *reflow);
-static void e_reflow_class_init (EReflowClass *klass);
-static void e_reflow_set_arg (GtkObject *o, GtkArg *arg, guint arg_id);
-static void e_reflow_get_arg (GtkObject *object, GtkArg *arg, guint arg_id);
-static void e_reflow_destroy (GtkObject *object);
static gboolean e_reflow_event (GnomeCanvasItem *item, GdkEvent *event);
static void e_reflow_realize (GnomeCanvasItem *item);
static void e_reflow_unrealize (GnomeCanvasItem *item);
@@ -42,8 +43,7 @@ static void e_reflow_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
static void e_reflow_update (GnomeCanvasItem *item, double affine[6], ArtSVP *clip_path, gint flags);
static double e_reflow_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item);
static void e_reflow_reflow (GnomeCanvasItem *item, int flags);
-static void e_reflow_real_add_item(EReflow *e_reflow, GnomeCanvasItem *item, gint *position);
-static void set_empty(EReflow *e_reflow);
+static void set_empty(EReflow *reflow);
static void e_reflow_resize_children (GnomeCanvasItem *item);
@@ -60,142 +60,511 @@ enum {
ARG_WIDTH,
ARG_HEIGHT,
ARG_EMPTY_MESSAGE,
+ ARG_MODEL,
};
-GtkType
-e_reflow_get_type (void)
+enum {
+ SELECTION_EVENT,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = {0, };
+
+static gint
+er_compare (int i1, int i2, gpointer user_data)
{
- static GtkType reflow_type = 0;
+ EReflow *reflow = user_data;
+ return e_reflow_model_compare (reflow->model, i1, i2);
+}
- if (!reflow_type)
- {
- static const GtkTypeInfo reflow_info =
- {
- "EReflow",
- sizeof (EReflow),
- sizeof (EReflowClass),
- (GtkClassInitFunc) e_reflow_class_init,
- (GtkObjectInitFunc) e_reflow_init,
- /* reserved_1 */ NULL,
- /* reserved_2 */ NULL,
- (GtkClassInitFunc) NULL,
- };
+static gint
+e_reflow_pick_line (EReflow *reflow, double x)
+{
+ x += E_REFLOW_BORDER_WIDTH + E_REFLOW_DIVIDER_WIDTH;
+ x /= reflow->column_width + E_REFLOW_FULL_GUTTER;
+ return x;
+}
- reflow_type = gtk_type_unique (gnome_canvas_group_get_type (), &reflow_info);
- }
+static int
+er_find_item (EReflow *reflow, GnomeCanvasItem *item)
+{
+ int i;
+ for (i = 0; i < reflow->count; i++) {
+ if (reflow->items[i] == item)
+ return i;
+ }
+ return -1;
+}
+
+static void
+e_reflow_resize_children (GnomeCanvasItem *item)
+{
+ EReflow *reflow;
+ int i;
+ int count;
+
+ reflow = E_REFLOW (item);
- return reflow_type;
+ count = reflow->count;
+ for (i = 0; i < count; i++) {
+ if (reflow->items[i])
+ gnome_canvas_item_set(reflow->items[i],
+ "width", (double) reflow->column_width,
+ NULL);
+ }
}
static void
-e_reflow_class_init (EReflowClass *klass)
+e_reflow_update_selection (EReflow *reflow)
{
- GtkObjectClass *object_class;
- GnomeCanvasItemClass *item_class;
+ int i;
+ int count;
+
+ count = reflow->count;
+ for (i = 0; i < count; i++) {
+ if (reflow->items[i]) {
+ gtk_object_set(GTK_OBJECT(reflow->items[i]),
+ "selected", e_selection_model_is_row_selected(E_SELECTION_MODEL(reflow->selection), i),
+ NULL);
+ } else if (e_selection_model_is_row_selected (E_SELECTION_MODEL (reflow->selection), i)) {
+ reflow->items[i] = e_reflow_model_incarnate (reflow->model, i, GNOME_CANVAS_GROUP (reflow));
+ gtk_object_set (GTK_OBJECT (reflow->items[i]),
+ "selected", e_selection_model_is_row_selected(E_SELECTION_MODEL(reflow->selection), i),
+ "width", (double) reflow->column_width,
+ NULL);
+ }
+ }
+}
- object_class = (GtkObjectClass*) klass;
- item_class = (GnomeCanvasItemClass *) klass;
+static void
+selection_changed (ESelectionModel *selection, EReflow *reflow)
+{
+ e_reflow_update_selection (reflow);
+}
- parent_class = gtk_type_class (gnome_canvas_group_get_type ());
-
- gtk_object_add_arg_type ("EReflow::minimum_width", GTK_TYPE_DOUBLE,
- GTK_ARG_READWRITE, ARG_MINIMUM_WIDTH);
- gtk_object_add_arg_type ("EReflow::width", GTK_TYPE_DOUBLE,
- GTK_ARG_READABLE, ARG_WIDTH);
- gtk_object_add_arg_type ("EReflow::height", GTK_TYPE_DOUBLE,
- GTK_ARG_READWRITE, ARG_HEIGHT);
- gtk_object_add_arg_type ("EReflow::empty_message", GTK_TYPE_STRING,
- GTK_ARG_READWRITE, ARG_EMPTY_MESSAGE);
+static void
+incarnate (EReflow *reflow)
+{
+ int column_width;
+ int first_column;
+ int last_column;
+ int first_cell;
+ int last_cell;
+ int i;
+ GtkAdjustment *adjustment = gtk_layout_get_hadjustment (GTK_LAYOUT (GNOME_CANVAS_ITEM (reflow)->canvas));
- klass->add_item = e_reflow_real_add_item;
-
- object_class->set_arg = e_reflow_set_arg;
- object_class->get_arg = e_reflow_get_arg;
- object_class->destroy = e_reflow_destroy;
-
- /* GnomeCanvasItem method overrides */
- item_class->event = e_reflow_event;
- item_class->realize = e_reflow_realize;
- item_class->unrealize = e_reflow_unrealize;
- item_class->draw = e_reflow_draw;
- item_class->update = e_reflow_update;
- item_class->point = e_reflow_point;
+ column_width = reflow->column_width;
+
+ first_column = adjustment->value - 1 + E_REFLOW_BORDER_WIDTH;
+ first_column /= column_width + E_REFLOW_FULL_GUTTER;
+
+ last_column = adjustment->value + adjustment->page_size + 1 - E_REFLOW_BORDER_WIDTH - E_REFLOW_DIVIDER_WIDTH;
+ last_column /= column_width + E_REFLOW_FULL_GUTTER;
+ last_column ++;
+
+ if (first_column >= 0 && first_column < reflow->column_count)
+ first_cell = reflow->columns[first_column];
+ else
+ first_cell = 0;
+
+ if (last_column >= 0 && last_column < reflow->column_count)
+ last_cell = reflow->columns[last_column];
+ else
+ last_cell = reflow->count;
+
+ for (i = first_cell; i < last_cell; i++) {
+ int unsorted = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), i);
+ if (reflow->items[unsorted] == NULL) {
+ if (reflow->model) {
+ reflow->items[unsorted] = e_reflow_model_incarnate (reflow->model, unsorted, GNOME_CANVAS_GROUP (reflow));
+ gtk_object_set (GTK_OBJECT (reflow->items[unsorted]),
+ "selected", e_selection_model_is_row_selected(E_SELECTION_MODEL(reflow->selection), unsorted),
+ "width", (double) reflow->column_width,
+ NULL);
+ }
+ }
+ }
+ reflow->incarnate_idle_id = 0;
+}
+
+static gboolean
+invoke_incarnate (gpointer user_data)
+{
+ EReflow *reflow = user_data;
+ incarnate (reflow);
+ return FALSE;
}
static void
-e_reflow_init (EReflow *reflow)
+queue_incarnate (EReflow *reflow)
{
- reflow->items = NULL;
- reflow->columns = NULL;
- reflow->column_width = 150;
+ if (reflow->incarnate_idle_id == 0)
+ reflow->incarnate_idle_id =
+ g_idle_add_full (25, invoke_incarnate, reflow, NULL);
+}
- reflow->minimum_width = 10;
- reflow->width = 10;
- reflow->height = 10;
- reflow->idle = 0;
+static void
+reflow_columns (EReflow *reflow)
+{
+ GSList *list;
+ int count;
+ int i;
+ int column_count;
+ double running_height;
+
+ g_free (reflow->columns);
+ reflow->column_count = 0;
+ reflow->columns = NULL;
+
+ list = NULL;
+
+ running_height = E_REFLOW_BORDER_WIDTH;
+ column_count = 1;
+
+ count = reflow->count;
+ for (i = 0; i < count; i++) {
+ int unsorted = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), i);
+ if (reflow->heights[unsorted] == -1) {
+ if (reflow->model)
+ reflow->heights[unsorted] = e_reflow_model_height (reflow->model, unsorted, GNOME_CANVAS_GROUP (reflow));
+ else
+ reflow->heights[unsorted] = 0;
+ }
+ if (i != 0 && running_height + reflow->heights[unsorted] + E_REFLOW_BORDER_WIDTH > reflow->height) {
+ list = g_slist_prepend (list, GINT_TO_POINTER(i));
+ column_count ++;
+ running_height = E_REFLOW_BORDER_WIDTH * 2 + reflow->heights[2];
+ } else
+ running_height += reflow->heights[unsorted] + E_REFLOW_BORDER_WIDTH;
+ }
- reflow->empty_message = NULL;
- reflow->empty_text = NULL;
+ reflow->column_count = column_count;
+ reflow->columns = g_new (int, column_count);
+ column_count --;
+ for (; column_count > 0; column_count--) {
+ GSList *to_free;
+ reflow->columns[column_count] = GPOINTER_TO_INT(list->data);
+ to_free = list;
+ list = list->next;
+ g_slist_free_1 (to_free);
+ }
+ reflow->columns[0] = 0;
- reflow->column_drag = FALSE;
+ queue_incarnate (reflow);
- reflow->need_height_update = FALSE;
- reflow->need_column_resize = FALSE;
+ reflow->need_reflow_columns = FALSE;
+}
- reflow->default_cursor_shown = TRUE;
- reflow->arrow_cursor = NULL;
- reflow->default_cursor = NULL;
+static void
+item_changed (EReflowModel *model, int i, EReflow *reflow)
+{
+ if (i < 0 || i >= reflow->count)
+ return;
- e_canvas_item_set_reflow_callback(GNOME_CANVAS_ITEM(reflow), e_reflow_reflow);
+ reflow->heights[i] = -1;
+ if (reflow->items[i] != NULL)
+ e_reflow_model_reincarnate (model, i, reflow->items[i]);
+ e_sorter_array_clean (reflow->sorter);
+ reflow->need_reflow_columns = TRUE;
+ e_canvas_item_request_reflow(GNOME_CANVAS_ITEM (reflow));
+}
+
+static void
+items_inserted (EReflowModel *model, int position, int count, EReflow *reflow)
+{
+ int i;
+ int oldcount;
+ if (position < 0 || position > reflow->count)
+ return;
+
+ oldcount = reflow->count;
+
+ reflow->count += count;
+
+ if (reflow->count > reflow->allocated_count) {
+ while (reflow->count > reflow->allocated_count)
+ reflow->allocated_count += 256;
+ reflow->heights = g_renew (int, reflow->heights, reflow->allocated_count);
+ reflow->items = g_renew (GnomeCanvasItem *, reflow->items, reflow->allocated_count);
+ }
+ memmove (reflow->heights + position + count, reflow->heights + position, (reflow->count - position - count) * sizeof (int));
+ memmove (reflow->items + position + count, reflow->items + position, (reflow->count - position - count) * sizeof (GnomeCanvasItem *));
+ for (i = position; i < position + count; i++) {
+ reflow->items[i] = 0;
+ reflow->heights[i] = -1;
+ }
+
+ e_selection_model_simple_set_row_count (E_SELECTION_MODEL_SIMPLE (reflow->selection), reflow->count);
+ if (position == oldcount)
+ e_sorter_array_append (reflow->sorter, count);
+ else
+ e_sorter_array_set_count (reflow->sorter, reflow->count);
+ reflow->need_reflow_columns = TRUE;
+ e_canvas_item_request_reflow(GNOME_CANVAS_ITEM (reflow));
+
+ g_print ("New count = %d\n", reflow->count);
+}
+
+static void
+model_changed (EReflowModel *model, EReflow *reflow)
+{
+ int i;
+ int count;
+ int oldcount;
+
+ count = reflow->count;
+ oldcount = count;
+
+ for (i = 0; i < count; i++) {
+ gtk_object_destroy (GTK_OBJECT (reflow->items[i]));
+ }
+ g_free (reflow->items);
+ g_free (reflow->heights);
+ reflow->count = e_reflow_model_count (model);
+ reflow->allocated_count = reflow->count;
+ reflow->items = g_new (GnomeCanvasItem *, reflow->count);
+ reflow->heights = g_new (int, reflow->count);
+
+ count = reflow->count;
+ for (i = 0; i < count; i++) {
+ reflow->items[i] = 0;
+ reflow->heights[i] = -1;
+ }
+
+ e_selection_model_simple_set_row_count (E_SELECTION_MODEL_SIMPLE (reflow->selection), count);
+ e_sorter_array_set_count (reflow->sorter, reflow->count);
+
+ reflow->need_reflow_columns = TRUE;
+ if (oldcount > reflow->count)
+ reflow_columns (reflow);
+ e_canvas_item_request_reflow(GNOME_CANVAS_ITEM (reflow));
+}
+
+static void
+set_empty(EReflow *reflow)
+{
+ if (reflow->count == 0) {
+ if (reflow->empty_text) {
+ if (reflow->empty_message) {
+ gnome_canvas_item_set(reflow->empty_text,
+ "width", reflow->minimum_width,
+ "text", reflow->empty_message,
+ NULL);
+ e_canvas_item_move_absolute(reflow->empty_text,
+ reflow->minimum_width / 2,
+ 0);
+ } else {
+ gtk_object_destroy(GTK_OBJECT(reflow->empty_text));
+ reflow->empty_text = NULL;
+ }
+ } else {
+ if (reflow->empty_message)
+ reflow->empty_text =
+ gnome_canvas_item_new(GNOME_CANVAS_GROUP(reflow),
+ e_text_get_type(),
+ "anchor", GTK_ANCHOR_N,
+ "width", reflow->minimum_width,
+ "clip", TRUE,
+ "use_ellipsis", TRUE,
+ "font_gdk", GTK_WIDGET(GNOME_CANVAS_ITEM(reflow)->canvas)->style->font,
+ "fill_color", "black",
+ "justification", GTK_JUSTIFY_CENTER,
+ "text", reflow->empty_message,
+ "draw_background", FALSE,
+ NULL);
+ e_canvas_item_move_absolute(reflow->empty_text,
+ reflow->minimum_width / 2,
+ 0);
+ }
+ } else {
+ if (reflow->empty_text) {
+ gtk_object_destroy(GTK_OBJECT(reflow->empty_text));
+ reflow->empty_text = NULL;
+ }
+ }
+}
+
+static void
+disconnect_model (EReflow *reflow)
+{
+ if (reflow->model == NULL)
+ return;
+
+ gtk_signal_disconnect (GTK_OBJECT (reflow->model),
+ reflow->model_changed_id);
+ gtk_signal_disconnect (GTK_OBJECT (reflow->model),
+ reflow->model_items_inserted_id);
+ gtk_signal_disconnect (GTK_OBJECT (reflow->model),
+ reflow->model_item_changed_id);
+ gtk_object_unref (GTK_OBJECT (reflow->model));
+
+ reflow->model_changed_id = 0;
+ reflow->model_items_inserted_id = 0;
+ reflow->model_item_changed_id = 0;
+ reflow->model = NULL;
}
static void
+disconnect_selection (EReflow *reflow)
+{
+ if (reflow->selection == NULL)
+ return;
+
+ gtk_signal_disconnect (GTK_OBJECT (reflow->selection),
+ reflow->selection_changed_id);
+ gtk_object_unref (GTK_OBJECT (reflow->selection));
+
+ reflow->selection_changed_id = 0;
+ reflow->selection = NULL;
+}
+
+static void
+connect_model (EReflow *reflow, EReflowModel *model)
+{
+ if (reflow->model != NULL)
+ disconnect_model (reflow);
+
+ if (model == NULL)
+ return;
+
+ reflow->model = model;
+ gtk_object_ref (GTK_OBJECT (reflow->model));
+ reflow->model_changed_id =
+ gtk_signal_connect (GTK_OBJECT (reflow->model), "model_changed",
+ GTK_SIGNAL_FUNC (model_changed), reflow);
+ reflow->model_items_inserted_id =
+ gtk_signal_connect (GTK_OBJECT (reflow->model), "model_items_inserted",
+ GTK_SIGNAL_FUNC (items_inserted), reflow);
+ reflow->model_item_changed_id =
+ gtk_signal_connect (GTK_OBJECT (reflow->model), "model_item_changed",
+ GTK_SIGNAL_FUNC (item_changed), reflow);
+}
+
+static void
+adjustment_changed (GtkAdjustment *adjustment, EReflow *reflow)
+{
+ incarnate (reflow);
+}
+
+static void
+disconnect_adjustment (EReflow *reflow)
+{
+ if (reflow->adjustment == NULL)
+ return;
+
+ gtk_signal_disconnect (GTK_OBJECT (reflow->adjustment),
+ reflow->adjustment_changed_id);
+ gtk_signal_disconnect (GTK_OBJECT (reflow->adjustment),
+ reflow->adjustment_value_changed_id);
+
+ gtk_object_unref (GTK_OBJECT (reflow->adjustment));
+
+ reflow->adjustment_changed_id = 0;
+ reflow->adjustment_value_changed_id = 0;
+ reflow->adjustment = NULL;
+}
+
+static void
+connect_adjustment (EReflow *reflow, GtkAdjustment *adjustment)
+{
+ if (reflow->adjustment != NULL)
+ disconnect_adjustment (reflow);
+
+ if (adjustment == NULL)
+ return;
+
+ reflow->adjustment = adjustment;
+ reflow->adjustment_changed_id =
+ gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
+ adjustment_changed, reflow);
+ reflow->adjustment_value_changed_id =
+ gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+ adjustment_changed, reflow);
+ gtk_object_ref (GTK_OBJECT (adjustment));
+}
+
+static void
+set_scroll_adjustments (GtkLayout *layout, GtkAdjustment *hadj, GtkAdjustment *vadj, EReflow *reflow)
+{
+ connect_adjustment (reflow, hadj);
+}
+
+static void
+disconnect_set_adjustment (EReflow *reflow)
+{
+ gtk_signal_disconnect (GTK_OBJECT (GNOME_CANVAS_ITEM (reflow)->canvas),
+ reflow->set_scroll_adjustments_id);
+ reflow->set_scroll_adjustments_id = 0;
+}
+
+static void
+connect_set_adjustment (EReflow *reflow)
+{
+ reflow->set_scroll_adjustments_id =
+ gtk_signal_connect (GTK_OBJECT (GNOME_CANVAS_ITEM (reflow)->canvas),
+ "set_scroll_adjustments",
+ GTK_SIGNAL_FUNC (set_scroll_adjustments), reflow);
+}
+
+
+
+
+/* Virtual functions */
+static void
e_reflow_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
{
GnomeCanvasItem *item;
- EReflow *e_reflow;
+ EReflow *reflow;
item = GNOME_CANVAS_ITEM (o);
- e_reflow = E_REFLOW (o);
+ reflow = E_REFLOW (o);
switch (arg_id){
case ARG_HEIGHT:
- e_reflow->height = GTK_VALUE_DOUBLE (*arg);
+ reflow->height = GTK_VALUE_DOUBLE (*arg);
+ reflow->need_reflow_columns = TRUE;
e_canvas_item_request_reflow(item);
break;
case ARG_MINIMUM_WIDTH:
- e_reflow->minimum_width = GTK_VALUE_DOUBLE (*arg);
+ reflow->minimum_width = GTK_VALUE_DOUBLE (*arg);
if (GNOME_CANVAS_ITEM_REALIZED & GTK_OBJECT_FLAGS(o))
- set_empty(e_reflow);
+ set_empty(reflow);
e_canvas_item_request_reflow(item);
break;
case ARG_EMPTY_MESSAGE:
- g_free(e_reflow->empty_message);
- e_reflow->empty_message = g_strdup(GTK_VALUE_STRING (*arg));
+ g_free(reflow->empty_message);
+ reflow->empty_message = g_strdup(GTK_VALUE_STRING (*arg));
if (GNOME_CANVAS_ITEM_REALIZED & GTK_OBJECT_FLAGS(o))
- set_empty(e_reflow);
+ set_empty(reflow);
+ break;
+ case ARG_MODEL:
+ connect_model (reflow, (EReflowModel *) GTK_VALUE_OBJECT (*arg));
+ break;
}
}
static void
e_reflow_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
- EReflow *e_reflow;
+ EReflow *reflow;
- e_reflow = E_REFLOW (object);
+ reflow = E_REFLOW (object);
switch (arg_id) {
case ARG_MINIMUM_WIDTH:
- GTK_VALUE_DOUBLE (*arg) = e_reflow->minimum_width;
+ GTK_VALUE_DOUBLE (*arg) = reflow->minimum_width;
break;
case ARG_WIDTH:
- GTK_VALUE_DOUBLE (*arg) = e_reflow->width;
+ GTK_VALUE_DOUBLE (*arg) = reflow->width;
break;
case ARG_HEIGHT:
- GTK_VALUE_DOUBLE (*arg) = e_reflow->height;
+ GTK_VALUE_DOUBLE (*arg) = reflow->height;
break;
case ARG_EMPTY_MESSAGE:
- GTK_VALUE_STRING (*arg) = g_strdup(e_reflow->empty_message);
+ GTK_VALUE_STRING (*arg) = g_strdup(reflow->empty_message);
+ break;
+ case ARG_MODEL:
+ GTK_VALUE_OBJECT (*arg) = (GtkObject *) reflow->model;
break;
default:
arg->type = GTK_TYPE_INVALID;
@@ -207,10 +576,25 @@ static void
e_reflow_destroy (GtkObject *object)
{
EReflow *reflow = E_REFLOW(object);
+ int count;
- g_list_foreach(reflow->items, (GFunc) gtk_object_unref, NULL);
- g_list_free(reflow->items);
- reflow->items = NULL;
+ count = reflow->count;
+
+ g_free (reflow->items);
+ g_free (reflow->heights);
+ g_free (reflow->columns);
+
+ reflow->items = NULL;
+ reflow->heights = NULL;
+ reflow->columns = NULL;
+ reflow->count = 0;
+ reflow->allocated_count = 0;
+
+ if (reflow->incarnate_idle_id != 0)
+ g_source_remove (reflow->incarnate_idle_id);
+
+ disconnect_model (reflow);
+ disconnect_selection (reflow);
g_free(reflow->empty_message);
@@ -220,33 +604,40 @@ e_reflow_destroy (GtkObject *object)
static void
e_reflow_realize (GnomeCanvasItem *item)
{
- EReflow *e_reflow;
+ EReflow *reflow;
GnomeCanvasGroup *group;
- GList *list;
GtkAdjustment *adjustment;
+ int count;
+ int i;
- e_reflow = E_REFLOW (item);
- group = GNOME_CANVAS_GROUP( item );
+ reflow = E_REFLOW (item);
+ group = GNOME_CANVAS_GROUP (item);
if (GNOME_CANVAS_ITEM_CLASS(parent_class)->realize)
(* GNOME_CANVAS_ITEM_CLASS(parent_class)->realize) (item);
- e_reflow->arrow_cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
- e_reflow->default_cursor = gdk_cursor_new (GDK_LEFT_PTR);
-
- for(list = e_reflow->items; list; list = g_list_next(list)) {
- GnomeCanvasItem *item = GNOME_CANVAS_ITEM(list->data);
- gnome_canvas_item_set(item,
- "width", (double) e_reflow->column_width,
- NULL);
+ reflow->arrow_cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
+ reflow->default_cursor = gdk_cursor_new (GDK_LEFT_PTR);
+
+ count = reflow->count;
+ for(i = 0; i < count; i++) {
+ if (reflow->items[i])
+ gnome_canvas_item_set(reflow->items[i],
+ "width", (double) reflow->column_width,
+ NULL);
}
- set_empty(e_reflow);
+ set_empty(reflow);
+ reflow->need_reflow_columns = TRUE;
e_canvas_item_request_reflow(item);
-
+
adjustment = gtk_layout_get_hadjustment(GTK_LAYOUT(item->canvas));
- adjustment->step_increment = (e_reflow->column_width + E_REFLOW_FULL_GUTTER) / 2;
+
+ connect_set_adjustment (reflow);
+ connect_adjustment (reflow, adjustment);
+
+ adjustment->step_increment = (reflow->column_width + E_REFLOW_FULL_GUTTER) / 2;
adjustment->page_increment = adjustment->page_size - adjustment->step_increment;
gtk_adjustment_changed(adjustment);
@@ -257,71 +648,82 @@ e_reflow_realize (GnomeCanvasItem *item)
static void
e_reflow_unrealize (GnomeCanvasItem *item)
{
- EReflow *e_reflow;
+ EReflow *reflow;
- e_reflow = E_REFLOW (item);
+ reflow = E_REFLOW (item);
- if (!item->canvas->aa)
- {
- }
+ if (!item->canvas->aa) {
+ }
- gdk_cursor_destroy (e_reflow->arrow_cursor);
- gdk_cursor_destroy (e_reflow->default_cursor);
- e_reflow->arrow_cursor = NULL;
- e_reflow->default_cursor = NULL;
+ gdk_cursor_destroy (reflow->arrow_cursor);
+ gdk_cursor_destroy (reflow->default_cursor);
+ reflow->arrow_cursor = NULL;
+ reflow->default_cursor = NULL;
- g_list_free (e_reflow->columns);
- e_reflow->columns = NULL;
+ g_free (reflow->columns);
+ reflow->columns = NULL;
- if (GNOME_CANVAS_ITEM_CLASS(parent_class)->unrealize)
- (* GNOME_CANVAS_ITEM_CLASS(parent_class)->unrealize) (item);
-}
+ disconnect_set_adjustment (reflow);
+ disconnect_adjustment (reflow);
-static gint
-e_reflow_pick_line (EReflow *e_reflow, double x)
-{
- x += E_REFLOW_BORDER_WIDTH + E_REFLOW_DIVIDER_WIDTH;
- x /= e_reflow->column_width + E_REFLOW_FULL_GUTTER;
- return x;
+ if (GNOME_CANVAS_ITEM_CLASS(parent_class)->unrealize)
+ (* GNOME_CANVAS_ITEM_CLASS(parent_class)->unrealize) (item);
}
static gboolean
e_reflow_event (GnomeCanvasItem *item, GdkEvent *event)
{
- EReflow *e_reflow;
+ EReflow *reflow;
+ int return_val = FALSE;
- e_reflow = E_REFLOW (item);
+ reflow = E_REFLOW (item);
switch( event->type )
{
case GDK_KEY_PRESS:
+ return_val = e_selection_model_key_press(reflow->selection, (GdkEventKey *) event);
+ break;
+#if 0
if (event->key.keyval == GDK_Tab ||
event->key.keyval == GDK_KP_Tab ||
event->key.keyval == GDK_ISO_Left_Tab) {
- GList *list;
- for (list = e_reflow->items; list; list = list->next) {
- GnomeCanvasItem *item = GNOME_CANVAS_ITEM (list->data);
+ int i;
+ int count;
+ count = reflow->count;
+ for (i = 0; i < count; i++) {
+ int unsorted = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), i);
+ GnomeCanvasItem *item = reflow->items[unsorted];
EFocus has_focus;
- gtk_object_get(GTK_OBJECT(item),
- "has_focus", &has_focus,
- NULL);
- if (has_focus) {
- if (event->key.state & GDK_SHIFT_MASK)
- list = list->prev;
- else
- list = list->next;
- if (list) {
- item = GNOME_CANVAS_ITEM(list->data);
+ if (item) {
+ gtk_object_get(GTK_OBJECT(item),
+ "has_focus", &has_focus,
+ NULL);
+ if (has_focus) {
+ if (event->key.state & GDK_SHIFT_MASK) {
+ if (i == 0)
+ return 0;
+ i--;
+ } else {
+ if (i == count - 1)
+ return 0;
+ i++;
+ }
+
+ unsorted = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), i);
+ if (reflow->items[unsorted] == NULL) {
+ reflow->items[unsorted] = e_reflow_model_incarnate (reflow->model, unsorted, GNOME_CANVAS_GROUP (reflow));
+ }
+
+ item = reflow->items[unsorted];
gnome_canvas_item_set(item,
"has_focus", (event->key.state & GDK_SHIFT_MASK) ? E_FOCUS_END : E_FOCUS_START,
NULL);
return 1;
- } else {
- return 0;
}
}
}
}
+#endif
break;
case GDK_BUTTON_PRESS:
switch(event->button.button)
@@ -332,23 +734,23 @@ e_reflow_event (GnomeCanvasItem *item, GdkEvent *event)
double n_x, max_x;
n_x = button->x;
n_x += E_REFLOW_BORDER_WIDTH + E_REFLOW_DIVIDER_WIDTH;
- n_x = fmod(n_x,(e_reflow->column_width + E_REFLOW_FULL_GUTTER));
+ n_x = fmod(n_x,(reflow->column_width + E_REFLOW_FULL_GUTTER));
max_x = E_REFLOW_BORDER_WIDTH;
- max_x += (e_reflow->column_width + E_REFLOW_FULL_GUTTER) * e_reflow->column_count;
- if ( button->y >= E_REFLOW_BORDER_WIDTH && button->y <= e_reflow->height - E_REFLOW_BORDER_WIDTH && n_x < E_REFLOW_FULL_GUTTER && max_x > button->x ) {
- e_reflow->which_column_dragged = e_reflow_pick_line(e_reflow, button->x);
- e_reflow->start_x = e_reflow->which_column_dragged * (e_reflow->column_width + E_REFLOW_FULL_GUTTER) - E_REFLOW_DIVIDER_WIDTH / 2;
- e_reflow->temp_column_width = e_reflow->column_width;
- e_reflow->column_drag = TRUE;
+ max_x += (reflow->column_width + E_REFLOW_FULL_GUTTER) * reflow->column_count;
+ if ( button->y >= E_REFLOW_BORDER_WIDTH && button->y <= reflow->height - E_REFLOW_BORDER_WIDTH && n_x < E_REFLOW_FULL_GUTTER && max_x > button->x ) {
+ reflow->which_column_dragged = e_reflow_pick_line(reflow, button->x);
+ reflow->start_x = reflow->which_column_dragged * (reflow->column_width + E_REFLOW_FULL_GUTTER) - E_REFLOW_DIVIDER_WIDTH / 2;
+ reflow->temp_column_width = reflow->column_width;
+ reflow->column_drag = TRUE;
gnome_canvas_item_grab (item,
GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
- e_reflow->arrow_cursor,
+ reflow->arrow_cursor,
button->time);
- e_reflow->previous_temp_column_width = -1;
- e_reflow->need_column_resize = TRUE;
+ reflow->previous_temp_column_width = -1;
+ reflow->need_column_resize = TRUE;
gnome_canvas_item_request_update(item);
return TRUE;
}
@@ -375,41 +777,41 @@ e_reflow_event (GnomeCanvasItem *item, GdkEvent *event)
}
break;
case GDK_BUTTON_RELEASE:
- if (e_reflow->column_drag) {
- gdouble old_width = e_reflow->column_width;
+ if (reflow->column_drag) {
+ gdouble old_width = reflow->column_width;
GdkEventButton *button = (GdkEventButton *) event;
GtkAdjustment *adjustment = gtk_layout_get_hadjustment(GTK_LAYOUT(item->canvas));
- e_reflow->temp_column_width = e_reflow->column_width +
- (button->x - e_reflow->start_x)/(e_reflow->which_column_dragged - e_reflow_pick_line(e_reflow, adjustment->value));
- if ( e_reflow->temp_column_width < 50 )
- e_reflow->temp_column_width = 50;
- e_reflow->column_drag = FALSE;
- if ( old_width != e_reflow->temp_column_width ) {
- gtk_adjustment_set_value(adjustment, adjustment->value + e_reflow_pick_line(e_reflow, adjustment->value) * (e_reflow->temp_column_width - e_reflow->column_width));
- e_reflow->column_width = e_reflow->temp_column_width;
- adjustment->step_increment = (e_reflow->column_width + E_REFLOW_FULL_GUTTER) / 2;
+ reflow->temp_column_width = reflow->column_width +
+ (button->x - reflow->start_x)/(reflow->which_column_dragged - e_reflow_pick_line(reflow, adjustment->value));
+ if ( reflow->temp_column_width < 50 )
+ reflow->temp_column_width = 50;
+ reflow->column_drag = FALSE;
+ if ( old_width != reflow->temp_column_width ) {
+ gtk_adjustment_set_value(adjustment, adjustment->value + e_reflow_pick_line(reflow, adjustment->value) * (reflow->temp_column_width - reflow->column_width));
+ reflow->column_width = reflow->temp_column_width;
+ adjustment->step_increment = (reflow->column_width + E_REFLOW_FULL_GUTTER) / 2;
adjustment->page_increment = adjustment->page_size - adjustment->step_increment;
gtk_adjustment_changed(adjustment);
e_reflow_resize_children(item);
e_canvas_item_request_reflow(item);
}
- e_reflow->need_column_resize = TRUE;
+ reflow->need_column_resize = TRUE;
gnome_canvas_item_request_update(item);
gnome_canvas_item_ungrab (item, button->time);
return TRUE;
}
break;
case GDK_MOTION_NOTIFY:
- if (e_reflow->column_drag) {
- double old_width = e_reflow->temp_column_width;
+ if (reflow->column_drag) {
+ double old_width = reflow->temp_column_width;
GdkEventMotion *motion = (GdkEventMotion *) event;
GtkAdjustment *adjustment = gtk_layout_get_hadjustment(GTK_LAYOUT(item->canvas));
- e_reflow->temp_column_width = e_reflow->column_width +
- (motion->x - e_reflow->start_x)/(e_reflow->which_column_dragged - e_reflow_pick_line(e_reflow, adjustment->value));
- if (e_reflow->temp_column_width < 50)
- e_reflow->temp_column_width = 50;
- if (old_width != e_reflow->temp_column_width) {
- e_reflow->need_column_resize = TRUE;
+ reflow->temp_column_width = reflow->column_width +
+ (motion->x - reflow->start_x)/(reflow->which_column_dragged - e_reflow_pick_line(reflow, adjustment->value));
+ if (reflow->temp_column_width < 50)
+ reflow->temp_column_width = 50;
+ if (old_width != reflow->temp_column_width) {
+ reflow->need_column_resize = TRUE;
gnome_canvas_item_request_update(item);
}
return TRUE;
@@ -419,53 +821,53 @@ e_reflow_event (GnomeCanvasItem *item, GdkEvent *event)
n_x = motion->x;
n_x += E_REFLOW_BORDER_WIDTH + E_REFLOW_DIVIDER_WIDTH;
- n_x = fmod(n_x,(e_reflow->column_width + E_REFLOW_FULL_GUTTER));
+ n_x = fmod(n_x,(reflow->column_width + E_REFLOW_FULL_GUTTER));
max_x = E_REFLOW_BORDER_WIDTH;
- max_x += (e_reflow->column_width + E_REFLOW_FULL_GUTTER) * e_reflow->column_count;
+ max_x += (reflow->column_width + E_REFLOW_FULL_GUTTER) * reflow->column_count;
- if ( motion->y >= E_REFLOW_BORDER_WIDTH && motion->y <= e_reflow->height - E_REFLOW_BORDER_WIDTH && n_x < E_REFLOW_FULL_GUTTER && max_x > motion->x) {
- if ( e_reflow->default_cursor_shown ) {
- gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, e_reflow->arrow_cursor);
- e_reflow->default_cursor_shown = FALSE;
+ if ( motion->y >= E_REFLOW_BORDER_WIDTH && motion->y <= reflow->height - E_REFLOW_BORDER_WIDTH && n_x < E_REFLOW_FULL_GUTTER && max_x > motion->x) {
+ if ( reflow->default_cursor_shown ) {
+ gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, reflow->arrow_cursor);
+ reflow->default_cursor_shown = FALSE;
}
} else
- if ( ! e_reflow->default_cursor_shown ) {
- gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, e_reflow->default_cursor);
- e_reflow->default_cursor_shown = TRUE;
+ if ( ! reflow->default_cursor_shown ) {
+ gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, reflow->default_cursor);
+ reflow->default_cursor_shown = TRUE;
}
}
break;
case GDK_ENTER_NOTIFY:
- if (!e_reflow->column_drag) {
+ if (!reflow->column_drag) {
GdkEventCrossing *crossing = (GdkEventCrossing *) event;
double n_x, max_x;
n_x = crossing->x;
n_x += E_REFLOW_BORDER_WIDTH + E_REFLOW_DIVIDER_WIDTH;
- n_x = fmod(n_x,(e_reflow->column_width + E_REFLOW_FULL_GUTTER));
+ n_x = fmod(n_x,(reflow->column_width + E_REFLOW_FULL_GUTTER));
max_x = E_REFLOW_BORDER_WIDTH;
- max_x += (e_reflow->column_width + E_REFLOW_FULL_GUTTER) * e_reflow->column_count;
- if ( crossing->y >= E_REFLOW_BORDER_WIDTH && crossing->y <= e_reflow->height - E_REFLOW_BORDER_WIDTH && n_x < E_REFLOW_FULL_GUTTER && max_x > crossing->x) {
- if ( e_reflow->default_cursor_shown ) {
- gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, e_reflow->arrow_cursor);
- e_reflow->default_cursor_shown = FALSE;
+ max_x += (reflow->column_width + E_REFLOW_FULL_GUTTER) * reflow->column_count;
+ if ( crossing->y >= E_REFLOW_BORDER_WIDTH && crossing->y <= reflow->height - E_REFLOW_BORDER_WIDTH && n_x < E_REFLOW_FULL_GUTTER && max_x > crossing->x) {
+ if ( reflow->default_cursor_shown ) {
+ gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, reflow->arrow_cursor);
+ reflow->default_cursor_shown = FALSE;
}
}
}
break;
case GDK_LEAVE_NOTIFY:
- if (!e_reflow->column_drag) {
+ if (!reflow->column_drag) {
GdkEventCrossing *crossing = (GdkEventCrossing *) event;
double n_x;
n_x = crossing->x;
n_x += E_REFLOW_BORDER_WIDTH + E_REFLOW_DIVIDER_WIDTH;
- n_x = fmod(n_x,(e_reflow->column_width + E_REFLOW_FULL_GUTTER));
- if ( !( crossing->y >= E_REFLOW_BORDER_WIDTH && crossing->y <= e_reflow->height - E_REFLOW_BORDER_WIDTH && n_x < E_REFLOW_FULL_GUTTER ) ) {
- if ( ! e_reflow->default_cursor_shown ) {
- gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, e_reflow->default_cursor);
- e_reflow->default_cursor_shown = TRUE;
+ n_x = fmod(n_x,(reflow->column_width + E_REFLOW_FULL_GUTTER));
+ if ( !( crossing->y >= E_REFLOW_BORDER_WIDTH && crossing->y <= reflow->height - E_REFLOW_BORDER_WIDTH && n_x < E_REFLOW_FULL_GUTTER ) ) {
+ if ( ! reflow->default_cursor_shown ) {
+ gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, reflow->default_cursor);
+ reflow->default_cursor_shown = TRUE;
}
}
}
@@ -473,27 +875,12 @@ e_reflow_event (GnomeCanvasItem *item, GdkEvent *event)
default:
break;
}
-
- if (GNOME_CANVAS_ITEM_CLASS( parent_class )->event)
+ if (return_val)
+ return return_val;
+ else if (GNOME_CANVAS_ITEM_CLASS( parent_class )->event)
return (* GNOME_CANVAS_ITEM_CLASS( parent_class )->event) (item, event);
else
- return 0;
-}
-
-static void
-e_reflow_real_add_item(EReflow *e_reflow, GnomeCanvasItem *item, gint *position)
-{
- e_reflow->items = g_list_append(e_reflow->items, item);
- gtk_object_ref(GTK_OBJECT(item));
- if (GTK_OBJECT_FLAGS (e_reflow) & GNOME_CANVAS_ITEM_REALIZED) {
- gnome_canvas_item_set(item,
- "width", (double) e_reflow->column_width,
- NULL);
- e_reflow_post_add_item(e_reflow, item);
- e_canvas_item_request_reflow(item);
- }
- if (position)
- *position = g_list_index(e_reflow->items, item);
+ return FALSE;
}
static void e_reflow_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
@@ -501,25 +888,25 @@ static void e_reflow_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
{
int x_rect, y_rect, width_rect, height_rect;
gdouble running_width;
- EReflow *e_reflow = E_REFLOW(item);
+ EReflow *reflow = E_REFLOW(item);
int i;
double column_width;
if (GNOME_CANVAS_ITEM_CLASS(parent_class)->draw)
GNOME_CANVAS_ITEM_CLASS(parent_class)->draw (item, drawable, x, y, width, height);
- column_width = e_reflow->column_width;
+ column_width = reflow->column_width;
running_width = E_REFLOW_BORDER_WIDTH + column_width + E_REFLOW_BORDER_WIDTH;
x_rect = running_width;
y_rect = E_REFLOW_BORDER_WIDTH;
width_rect = E_REFLOW_DIVIDER_WIDTH;
- height_rect = e_reflow->height - (E_REFLOW_BORDER_WIDTH * 2);
+ height_rect = reflow->height - (E_REFLOW_BORDER_WIDTH * 2);
/* Compute first column to draw. */
i = x;
i /= column_width + E_REFLOW_FULL_GUTTER;
running_width += i * (column_width + E_REFLOW_FULL_GUTTER);
- for ( ; i < e_reflow->column_count; i++) {
+ for ( ; i < reflow->column_count; i++) {
if ( running_width > x + width )
break;
x_rect = running_width;
@@ -536,25 +923,25 @@ static void e_reflow_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
height_rect);
running_width += E_REFLOW_DIVIDER_WIDTH + E_REFLOW_BORDER_WIDTH + column_width + E_REFLOW_BORDER_WIDTH;
}
- if (e_reflow->column_drag) {
- int start_line = e_reflow_pick_line(e_reflow,
+ if (reflow->column_drag) {
+ int start_line = e_reflow_pick_line(reflow,
gtk_layout_get_hadjustment(GTK_LAYOUT(item->canvas))->value);
i = x - start_line * (column_width + E_REFLOW_FULL_GUTTER);
running_width = start_line * (column_width + E_REFLOW_FULL_GUTTER);
- column_width = e_reflow->temp_column_width;
+ column_width = reflow->temp_column_width;
running_width -= start_line * (column_width + E_REFLOW_FULL_GUTTER);
i += start_line * (column_width + E_REFLOW_FULL_GUTTER);
running_width += E_REFLOW_BORDER_WIDTH + column_width + E_REFLOW_BORDER_WIDTH;
x_rect = running_width;
y_rect = E_REFLOW_BORDER_WIDTH;
width_rect = E_REFLOW_DIVIDER_WIDTH;
- height_rect = e_reflow->height - (E_REFLOW_BORDER_WIDTH * 2);
+ height_rect = reflow->height - (E_REFLOW_BORDER_WIDTH * 2);
/* Compute first column to draw. */
i /= column_width + E_REFLOW_FULL_GUTTER;
running_width += i * (column_width + E_REFLOW_FULL_GUTTER);
- for ( ; i < e_reflow->column_count; i++) {
+ for ( ; i < reflow->column_count; i++) {
if ( running_width > x + width )
break;
x_rect = running_width;
@@ -573,10 +960,10 @@ static void e_reflow_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
static void
e_reflow_update (GnomeCanvasItem *item, double affine[6], ArtSVP *clip_path, gint flags)
{
- EReflow *e_reflow;
+ EReflow *reflow;
double x0, x1, y0, y1;
- e_reflow = E_REFLOW (item);
+ reflow = E_REFLOW (item);
if (GNOME_CANVAS_ITEM_CLASS(parent_class)->update)
GNOME_CANVAS_ITEM_CLASS(parent_class)->update (item, affine, clip_path, flags);
@@ -585,14 +972,14 @@ e_reflow_update (GnomeCanvasItem *item, double affine[6], ArtSVP *clip_path, gin
y0 = item->y1;
x1 = item->x2;
y1 = item->y2;
- if ( x1 < x0 + e_reflow->width )
- x1 = x0 + e_reflow->width;
- if ( y1 < y0 + e_reflow->height )
- y1 = y0 + e_reflow->height;
+ if ( x1 < x0 + reflow->width )
+ x1 = x0 + reflow->width;
+ if ( y1 < y0 + reflow->height )
+ y1 = y0 + reflow->height;
item->x2 = x1;
item->y2 = y1;
- if (e_reflow->need_height_update) {
+ if (reflow->need_height_update) {
x0 = item->x1;
y0 = item->y1;
x1 = item->x2;
@@ -607,64 +994,49 @@ e_reflow_update (GnomeCanvasItem *item, double affine[6], ArtSVP *clip_path, gin
x1 = E_REFLOW(item)->height;
gnome_canvas_request_redraw(item->canvas, x0, y0, x1, y1);
- e_reflow->need_height_update = FALSE;
- } else if (e_reflow->need_column_resize) {
+ reflow->need_height_update = FALSE;
+ } else if (reflow->need_column_resize) {
int x_rect, y_rect, width_rect, height_rect;
- int start_line = e_reflow_pick_line(e_reflow,
+ int start_line = e_reflow_pick_line(reflow,
gtk_layout_get_hadjustment(GTK_LAYOUT(item->canvas))->value);
gdouble running_width;
int i;
double column_width;
- if ( e_reflow->previous_temp_column_width != -1 ) {
- running_width = start_line * (e_reflow->column_width + E_REFLOW_FULL_GUTTER);
- column_width = e_reflow->previous_temp_column_width;
+ if ( reflow->previous_temp_column_width != -1 ) {
+ running_width = start_line * (reflow->column_width + E_REFLOW_FULL_GUTTER);
+ column_width = reflow->previous_temp_column_width;
running_width -= start_line * (column_width + E_REFLOW_FULL_GUTTER);
running_width += E_REFLOW_BORDER_WIDTH + column_width + E_REFLOW_BORDER_WIDTH;
y_rect = E_REFLOW_BORDER_WIDTH;
width_rect = E_REFLOW_DIVIDER_WIDTH;
- height_rect = e_reflow->height - (E_REFLOW_BORDER_WIDTH * 2);
+ height_rect = reflow->height - (E_REFLOW_BORDER_WIDTH * 2);
- for ( i = 0; i < e_reflow->column_count; i++) {
+ for ( i = 0; i < reflow->column_count; i++) {
x_rect = running_width;
gnome_canvas_request_redraw(item->canvas, x_rect, y_rect, x_rect + width_rect, y_rect + height_rect);
running_width += E_REFLOW_DIVIDER_WIDTH + E_REFLOW_BORDER_WIDTH + column_width + E_REFLOW_BORDER_WIDTH;
}
}
- if ( e_reflow->temp_column_width != -1 ) {
- running_width = start_line * (e_reflow->column_width + E_REFLOW_FULL_GUTTER);
- column_width = e_reflow->temp_column_width;
+ if ( reflow->temp_column_width != -1 ) {
+ running_width = start_line * (reflow->column_width + E_REFLOW_FULL_GUTTER);
+ column_width = reflow->temp_column_width;
running_width -= start_line * (column_width + E_REFLOW_FULL_GUTTER);
running_width += E_REFLOW_BORDER_WIDTH + column_width + E_REFLOW_BORDER_WIDTH;
y_rect = E_REFLOW_BORDER_WIDTH;
width_rect = E_REFLOW_DIVIDER_WIDTH;
- height_rect = e_reflow->height - (E_REFLOW_BORDER_WIDTH * 2);
+ height_rect = reflow->height - (E_REFLOW_BORDER_WIDTH * 2);
- for ( i = 0; i < e_reflow->column_count; i++) {
+ for ( i = 0; i < reflow->column_count; i++) {
x_rect = running_width;
gnome_canvas_request_redraw(item->canvas, x_rect, y_rect, x_rect + width_rect, y_rect + height_rect);
running_width += E_REFLOW_DIVIDER_WIDTH + E_REFLOW_BORDER_WIDTH + column_width + E_REFLOW_BORDER_WIDTH;
}
}
- e_reflow->previous_temp_column_width = e_reflow->temp_column_width;
- e_reflow->need_column_resize = FALSE;
- }
-}
-
-static void
-e_reflow_resize_children (GnomeCanvasItem *item)
-{
- GList *list;
- EReflow *e_reflow;
-
- e_reflow = E_REFLOW (item);
- for ( list = e_reflow->items; list; list = list->next ) {
- GnomeCanvasItem *child = GNOME_CANVAS_ITEM(list->data);
- gnome_canvas_item_set(child,
- "width", (double) e_reflow->column_width,
- NULL);
+ reflow->previous_temp_column_width = reflow->temp_column_width;
+ reflow->need_column_resize = FALSE;
}
}
@@ -685,11 +1057,11 @@ e_reflow_point (GnomeCanvasItem *item,
*actual_item = item;
return 0;
#if 0
- if (y >= E_REFLOW_BORDER_WIDTH && y <= e_reflow->height - E_REFLOW_BORDER_WIDTH) {
+ if (y >= E_REFLOW_BORDER_WIDTH && y <= reflow->height - E_REFLOW_BORDER_WIDTH) {
float n_x;
n_x = x;
n_x += E_REFLOW_BORDER_WIDTH + E_REFLOW_DIVIDER_WIDTH;
- n_x = fmod(n_x, (e_reflow->column_width + E_REFLOW_FULL_GUTTER));
+ n_x = fmod(n_x, (reflow->column_width + E_REFLOW_FULL_GUTTER));
if (n_x < E_REFLOW_FULL_GUTTER) {
*actual_item = item;
return 0;
@@ -700,164 +1072,194 @@ e_reflow_point (GnomeCanvasItem *item,
}
static void
-_reflow( EReflow *e_reflow )
+e_reflow_reflow( GnomeCanvasItem *item, int flags )
{
+ EReflow *reflow = E_REFLOW(item);
+ gdouble old_width;
+ gdouble running_width;
gdouble running_height;
- GList *list;
- double item_height;
+ int next_column;
+ int i;
- if (e_reflow->columns) {
- g_list_free (e_reflow->columns);
- e_reflow->columns = NULL;
+ if (! (GTK_OBJECT_FLAGS (reflow) & GNOME_CANVAS_ITEM_REALIZED))
+ return;
+
+ if (reflow->need_reflow_columns) {
+ reflow_columns (reflow);
}
+
+ old_width = reflow->width;
- e_reflow->column_count = 0;
+ running_width = E_REFLOW_BORDER_WIDTH;
+ running_height = E_REFLOW_BORDER_WIDTH;
- if (e_reflow->items == NULL) {
- e_reflow->columns = NULL;
- e_reflow->column_count = 0;
- return;
- }
+ next_column = 1;
- list = e_reflow->items;
-
- gtk_object_get (GTK_OBJECT(list->data),
- "height", &item_height,
- NULL);
- running_height = E_REFLOW_BORDER_WIDTH + item_height + E_REFLOW_BORDER_WIDTH;
- e_reflow->columns = g_list_append (e_reflow->columns, list);
- e_reflow->column_count = 1;
-
- list = g_list_next(list);
-
- for ( ; list; list = g_list_next(list)) {
- gtk_object_get (GTK_OBJECT(list->data),
- "height", &item_height,
- NULL);
- if (running_height + item_height + E_REFLOW_BORDER_WIDTH > e_reflow->height) {
- running_height = E_REFLOW_BORDER_WIDTH + item_height + E_REFLOW_BORDER_WIDTH;
- e_reflow->columns = g_list_append (e_reflow->columns, list);
- e_reflow->column_count ++;
- } else {
- running_height += item_height + E_REFLOW_BORDER_WIDTH;
+ for (i = 0; i < reflow->count; i++) {
+ int unsorted = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), i);
+ if (next_column < reflow->column_count && i == reflow->columns[next_column]) {
+ running_height = E_REFLOW_BORDER_WIDTH;
+ running_width += reflow->column_width + E_REFLOW_FULL_GUTTER;
+ next_column ++;
}
+
+ if (reflow->items[unsorted])
+ e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(reflow->items[unsorted]),
+ (double) running_width,
+ (double) running_height);
+ running_height += reflow->heights[unsorted] + E_REFLOW_BORDER_WIDTH;
}
+ reflow->width = running_width + reflow->column_width + E_REFLOW_BORDER_WIDTH;
+ if ( reflow->width < reflow->minimum_width )
+ reflow->width = reflow->minimum_width;
+ if (old_width != reflow->width)
+ e_canvas_item_request_parent_reflow(item);
}
-static void
-set_empty(EReflow *e_reflow)
-{
- if (e_reflow->items == NULL) {
- if (e_reflow->empty_text) {
- if (e_reflow->empty_message) {
- gnome_canvas_item_set(e_reflow->empty_text,
- "width", e_reflow->minimum_width,
- "text", e_reflow->empty_message,
- NULL);
- e_canvas_item_move_absolute(e_reflow->empty_text,
- e_reflow->minimum_width / 2,
- 0);
- } else {
- gtk_object_destroy(GTK_OBJECT(e_reflow->empty_text));
- e_reflow->empty_text = NULL;
- }
- } else {
- if (e_reflow->empty_message)
- e_reflow->empty_text =
- gnome_canvas_item_new(GNOME_CANVAS_GROUP(e_reflow),
- e_text_get_type(),
- "anchor", GTK_ANCHOR_N,
- "width", e_reflow->minimum_width,
- "clip", TRUE,
- "use_ellipsis", TRUE,
- "font_gdk", GTK_WIDGET(GNOME_CANVAS_ITEM(e_reflow)->canvas)->style->font,
- "fill_color", "black",
- "justification", GTK_JUSTIFY_CENTER,
- "text", e_reflow->empty_message,
- "draw_background", FALSE,
- NULL);
- e_canvas_item_move_absolute(e_reflow->empty_text,
- e_reflow->minimum_width / 2,
- 0);
- }
- } else {
- if (e_reflow->empty_text) {
- gtk_object_destroy(GTK_OBJECT(e_reflow->empty_text));
- e_reflow->empty_text = NULL;
+static int
+e_reflow_selection_event_real (EReflow *reflow, GnomeCanvasItem *item, GdkEvent *event)
+{
+ int row;
+ int return_val = TRUE;
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ switch (event->button.button) {
+ case 1: /* Fall through. */
+ case 2:
+ row = er_find_item (reflow, item);
+ e_selection_model_do_something(reflow->selection, row, 0, event->button.state);
+ break;
+ case 3:
+ row = er_find_item (reflow, item);
+ e_selection_model_maybe_do_something(reflow->selection, row, 0, event->button.state);
+ break;
+ default:
+ return_val = FALSE;
+ break;
}
+ break;
+ case GDK_KEY_PRESS:
+ return_val = e_selection_model_key_press(reflow->selection, (GdkEventKey *) event);
+ break;
+ default:
+ return_val = FALSE;
+ break;
}
+
+ return return_val;
}
static void
-e_reflow_reflow( GnomeCanvasItem *item, int flags )
+e_reflow_class_init (EReflowClass *klass)
{
- EReflow *e_reflow = E_REFLOW(item);
- if ( GTK_OBJECT_FLAGS( e_reflow ) & GNOME_CANVAS_ITEM_REALIZED ) {
+ GtkObjectClass *object_class;
+ GnomeCanvasItemClass *item_class;
- gdouble old_width;
- gdouble running_width;
+ object_class = (GtkObjectClass*) klass;
+ item_class = (GnomeCanvasItemClass *) klass;
- _reflow (e_reflow);
-
- old_width = e_reflow->width;
-
- running_width = E_REFLOW_BORDER_WIDTH;
+ parent_class = gtk_type_class (gnome_canvas_group_get_type ());
+
+ gtk_object_add_arg_type ("EReflow::minimum_width", GTK_TYPE_DOUBLE,
+ GTK_ARG_READWRITE, ARG_MINIMUM_WIDTH);
+ gtk_object_add_arg_type ("EReflow::width", GTK_TYPE_DOUBLE,
+ GTK_ARG_READABLE, ARG_WIDTH);
+ gtk_object_add_arg_type ("EReflow::height", GTK_TYPE_DOUBLE,
+ GTK_ARG_READWRITE, ARG_HEIGHT);
+ gtk_object_add_arg_type ("EReflow::empty_message", GTK_TYPE_STRING,
+ GTK_ARG_READWRITE, ARG_EMPTY_MESSAGE);
+ gtk_object_add_arg_type ("EReflow::model", E_REFLOW_MODEL_TYPE,
+ GTK_ARG_READWRITE, ARG_MODEL);
+
+ signals [SELECTION_EVENT] =
+ gtk_signal_new ("selection_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EReflowClass, selection_event),
+ e_marshal_INT__OBJECT_POINTER,
+ GTK_TYPE_INT, 2, GTK_TYPE_OBJECT, GTK_TYPE_GDK_EVENT);
+
+ gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
+
+ object_class->set_arg = e_reflow_set_arg;
+ object_class->get_arg = e_reflow_get_arg;
+ object_class->destroy = e_reflow_destroy;
+
+ /* GnomeCanvasItem method overrides */
+ item_class->event = e_reflow_event;
+ item_class->realize = e_reflow_realize;
+ item_class->unrealize = e_reflow_unrealize;
+ item_class->draw = e_reflow_draw;
+ item_class->update = e_reflow_update;
+ item_class->point = e_reflow_point;
+
+ klass->selection_event = e_reflow_selection_event_real;
+}
- if (e_reflow->items == NULL) {
- } else {
- GList *list;
- GList *next_column;
- gdouble item_height;
- gdouble running_height;
+static void
+e_reflow_init (EReflow *reflow)
+{
+ reflow->model = NULL;
+ reflow->items = NULL;
+ reflow->heights = NULL;
+ reflow->count = 0;
- running_height = E_REFLOW_BORDER_WIDTH;
-
- list = e_reflow->items;
- gtk_object_get (GTK_OBJECT(list->data),
- "height", &item_height,
- NULL);
- e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(list->data),
- (double) running_width,
- (double) running_height);
- running_height += item_height + E_REFLOW_BORDER_WIDTH;
- next_column = g_list_next(e_reflow->columns);
- list = g_list_next(list);
-
- for( ; list; list = g_list_next(list)) {
- gtk_object_get (GTK_OBJECT(list->data),
- "height", &item_height,
- NULL);
+ reflow->columns = NULL;
+ reflow->column_count = 0;
- if (next_column && (next_column->data == list)) {
- next_column = g_list_next (next_column);
- running_height = E_REFLOW_BORDER_WIDTH;
- running_width += e_reflow->column_width + E_REFLOW_BORDER_WIDTH + E_REFLOW_DIVIDER_WIDTH + E_REFLOW_BORDER_WIDTH;
- }
- e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(list->data),
- (double) running_width,
- (double) running_height);
+ reflow->empty_text = NULL;
+ reflow->empty_message = NULL;
- running_height += item_height + E_REFLOW_BORDER_WIDTH;
- }
-
- }
- e_reflow->width = running_width + e_reflow->column_width + E_REFLOW_BORDER_WIDTH;
- if ( e_reflow->width < e_reflow->minimum_width )
- e_reflow->width = e_reflow->minimum_width;
- if (old_width != e_reflow->width)
- e_canvas_item_request_parent_reflow(item);
- }
-}
+ reflow->minimum_width = 10;
+ reflow->width = 10;
+ reflow->height = 10;
-void
-e_reflow_add_item(EReflow *e_reflow, GnomeCanvasItem *item, gint *position)
-{
- if (E_REFLOW_CLASS(GTK_OBJECT(e_reflow)->klass)->add_item)
- (E_REFLOW_CLASS(GTK_OBJECT(e_reflow)->klass)->add_item) (e_reflow, item, position);
+ reflow->column_width = 150;
+
+ reflow->column_drag = FALSE;
+
+ reflow->need_height_update = FALSE;
+ reflow->need_column_resize = FALSE;
+
+ reflow->default_cursor_shown = TRUE;
+ reflow->arrow_cursor = NULL;
+ reflow->default_cursor = NULL;
+
+ reflow->incarnate_idle_id = 0;
+
+ reflow->selection = E_SELECTION_MODEL (e_selection_model_simple_new());
+ reflow->sorter = e_sorter_array_new (er_compare, reflow);
+
+ gtk_object_set (GTK_OBJECT (reflow->selection),
+ "sorter", reflow->sorter,
+ NULL);
+
+ reflow->selection_changed_id =
+ gtk_signal_connect(GTK_OBJECT(reflow->selection), "selection_changed",
+ GTK_SIGNAL_FUNC(selection_changed), reflow);
+
+ e_canvas_item_set_reflow_callback(GNOME_CANVAS_ITEM(reflow), e_reflow_reflow);
}
-void
-e_reflow_post_add_item(EReflow *e_reflow, GnomeCanvasItem *item)
+GtkType
+e_reflow_get_type (void)
{
- set_empty(e_reflow);
+ static GtkType type = 0;
+
+ if (!type) {
+ static const GtkTypeInfo info = {
+ "EReflow",
+ sizeof (EReflow),
+ sizeof (EReflowClass),
+ (GtkClassInitFunc) e_reflow_class_init,
+ (GtkObjectInitFunc) e_reflow_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ type = gtk_type_unique (gnome_canvas_group_get_type (), &info);
+ }
+
+ return type;
}
diff --git a/widgets/misc/e-reflow.h b/widgets/misc/e-reflow.h
index 641a4af0e5..9ecbb5c529 100644
--- a/widgets/misc/e-reflow.h
+++ b/widgets/misc/e-reflow.h
@@ -22,6 +22,9 @@
#define __E_REFLOW_H__
#include <libgnomeui/gnome-canvas.h>
+#include <gal/widgets/e-reflow-model.h>
+#include <gal/widgets/e-selection-model.h>
+#include <gal/util/e-sorter-array.h>
#ifdef __cplusplus
extern "C" {
@@ -46,6 +49,8 @@ extern "C" {
#define E_IS_REFLOW_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_REFLOW_TYPE))
+typedef struct EReflowPriv EReflowPriv;
+
typedef struct _EReflow EReflow;
typedef struct _EReflowClass EReflowClass;
@@ -54,30 +59,50 @@ struct _EReflow
GnomeCanvasGroup parent;
/* item specific fields */
- GList *items; /* Of type GnomeCanvasItem */
- GList *columns; /* Of type GList of type GnomeCanvasItem (points into items) */
+ EReflowModel *model;
+ guint model_changed_id;
+ guint model_items_inserted_id;
+ guint model_item_changed_id;
+
+ ESelectionModel *selection;
+ guint selection_changed_id;
+ ESorterArray *sorter;
+
+ GtkAdjustment *adjustment;
+ guint adjustment_changed_id;
+ guint adjustment_value_changed_id;
+ guint set_scroll_adjustments_id;
+
+ int *heights;
+ GnomeCanvasItem **items;
+ int count;
+ int allocated_count;
+
+ int *columns;
gint column_count; /* Number of columnns */
GnomeCanvasItem *empty_text;
gchar *empty_message;
-
+
double minimum_width;
double width;
double height;
-
+
double column_width;
- int idle;
+ int incarnate_idle_id;
/* These are all for when the column is being dragged. */
- gboolean column_drag;
gdouble start_x;
gint which_column_dragged;
double temp_column_width;
double previous_temp_column_width;
+ guint column_drag : 1;
+
guint need_height_update : 1;
guint need_column_resize : 1;
+ guint need_reflow_columns : 1;
guint default_cursor_shown : 1;
GdkCursor *arrow_cursor;
@@ -88,8 +113,7 @@ struct _EReflowClass
{
GnomeCanvasGroupClass parent_class;
- /* Virtual methods. */
- void (* add_item) (EReflow *reflow, GnomeCanvasItem *item, gint *position);
+ int (*selection_event) (EReflow *reflow, GnomeCanvasItem *item, GdkEvent *event);
};
/*
@@ -98,18 +122,10 @@ struct _EReflowClass
* should also do an ECanvas parent reflow request if its size
* changes.
*/
-void e_reflow_add_item (EReflow *e_reflow,
- GnomeCanvasItem *item,
- gint *position);
GtkType e_reflow_get_type (void);
-/* Internal usage only: */
-void e_reflow_post_add_item (EReflow *e_reflow,
- GnomeCanvasItem *item);
-
#ifdef __cplusplus
}
#endif /* __cplusplus */
-
#endif /* __E_REFLOW_H__ */