aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/misc
diff options
context:
space:
mode:
Diffstat (limited to 'widgets/misc')
-rw-r--r--widgets/misc/e-canvas.c117
-rw-r--r--widgets/misc/e-canvas.h9
-rw-r--r--widgets/misc/e-reflow.c102
3 files changed, 157 insertions, 71 deletions
diff --git a/widgets/misc/e-canvas.c b/widgets/misc/e-canvas.c
index 850e438386..68f1b0f9f3 100644
--- a/widgets/misc/e-canvas.c
+++ b/widgets/misc/e-canvas.c
@@ -36,6 +36,13 @@ static int emit_event (GnomeCanvas *canvas, GdkEvent *event);
static GnomeCanvasClass *parent_class = NULL;
+enum {
+ REFLOW,
+ LAST_SIGNAL
+};
+
+static guint e_canvas_signals [LAST_SIGNAL] = { 0, };
+
GtkType
e_canvas_get_type (void)
{
@@ -78,6 +85,18 @@ e_canvas_class_init (ECanvasClass *klass)
widget_class->key_release_event = e_canvas_key;
widget_class->focus_in_event = e_canvas_focus_in;
widget_class->focus_out_event = e_canvas_focus_out;
+
+ klass->reflow = NULL;
+
+ e_canvas_signals [REFLOW] =
+ gtk_signal_new ("reflow",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (ECanvasClass, reflow),
+ gtk_marshal_NONE__INT_INT,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, e_canvas_signals, LAST_SIGNAL);
}
static void
@@ -299,3 +318,101 @@ e_canvas_focus_out (GtkWidget *widget, GdkEventFocus *event)
else
return FALSE;
}
+
+
+static void
+e_canvas_item_invoke_update (GnomeCanvasItem *item, int flags)
+{
+ GnomeCanvasGroup *group;
+ GList *list;
+ GnomeCanvasItem *child;
+ if ( ! gtk_object_get_data(GTK_OBJECT(item), "ECanvasItem::descendent_needs_reflow") )
+ return;
+
+ if ( GNOME_IS_CANVAS_GROUP( item ) ) {
+ group = GNOME_CANVAS_GROUP( item );
+ for ( list = group->item_list; list; list = list->next ) {
+ child = GNOME_CANVAS_ITEM(list->data);
+ e_canvas_item_invoke_update(child, flags);
+ }
+ }
+
+ if ( gtk_object_get_data(GTK_OBJECT(item), "ECanvasItem::needs_reflow") ) {
+ ECanvasItemReflowFunc func = gtk_object_get_data(GTK_OBJECT(item), "ECanvasItem::reflow_callback");
+ if ( func )
+ func(item, flags);
+ }
+
+ gtk_object_set_data(GTK_OBJECT(item), "ECanvasItem::needs_reflow", (gpointer) 0);
+ gtk_object_set_data(GTK_OBJECT(item), "ECanvasItem::descendent_needs_reflow", (gpointer) 0);
+}
+
+static void
+do_update (ECanvas *canvas)
+{
+ e_canvas_item_invoke_update (GNOME_CANVAS(canvas)->root, 0);
+}
+
+/* Idle handler for the canvas. It deals with pending updates and redraws. */
+static gint
+idle_handler (gpointer data)
+{
+ ECanvas *canvas;
+
+ GDK_THREADS_ENTER ();
+
+ canvas = E_CANVAS (data);
+ do_update (canvas);
+
+ /* Reset idle id */
+ canvas->idle_id = 0;
+
+ gtk_signal_emit (GTK_OBJECT (canvas),
+ e_canvas_signals [REFLOW]);
+
+ GDK_THREADS_LEAVE ();
+
+ return FALSE;
+}
+
+/* Convenience function to add an idle handler to a canvas */
+static void
+add_idle (ECanvas *canvas)
+{
+ if (canvas->idle_id != 0)
+ return;
+
+ canvas->idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE, idle_handler, (gpointer) canvas, NULL);
+}
+
+static void
+e_canvas_item_descendent_needs_reflow (GnomeCanvasItem *item)
+{
+ if ( gtk_object_get_data(GTK_OBJECT(item), "ECanvasItem::descendent_needs_reflow") )
+ return;
+ gtk_object_set_data(GTK_OBJECT(item), "ECanvasItem::descendent_needs_reflow", (gpointer) 1);
+ if ( item->parent )
+ e_canvas_item_descendent_needs_reflow(item->parent);
+}
+
+void
+e_canvas_item_request_reflow (GnomeCanvasItem *item)
+{
+ gtk_object_set_data(GTK_OBJECT(item), "ECanvasItem::needs_reflow", (gpointer) 1);
+ e_canvas_item_descendent_needs_reflow(item);
+ add_idle(E_CANVAS(item->canvas));
+}
+
+void
+e_canvas_item_request_parent_reflow (GnomeCanvasItem *item)
+{
+ g_return_if_fail(item != NULL);
+ g_return_if_fail(GNOME_IS_CANVAS_ITEM(item));
+ e_canvas_item_request_reflow(item->parent);
+}
+
+void
+e_canvas_item_set_reflow_callback (GnomeCanvasItem *item, ECanvasItemReflowFunc func)
+{
+ gtk_object_set_data(GTK_OBJECT(item), "ECanvasItem::reflow_callback", (gpointer) func);
+}
diff --git a/widgets/misc/e-canvas.h b/widgets/misc/e-canvas.h
index 0ece5ae3b4..e70957b6d7 100644
--- a/widgets/misc/e-canvas.h
+++ b/widgets/misc/e-canvas.h
@@ -38,6 +38,8 @@ extern "C" {
#define E_IS_CANVAS(obj) (GTK_CHECK_TYPE ((obj), E_CANVAS_TYPE))
#define E_IS_CANVAS_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_CANVAS_TYPE))
+typedef void (*ECanvasItemReflowFunc) (GnomeCanvasItem *item,
+ gint flags);
typedef struct _ECanvas ECanvas;
typedef struct _ECanvasClass ECanvasClass;
@@ -46,12 +48,13 @@ struct _ECanvas
{
GnomeCanvas parent;
- /* item specific fields */
+ int idle_id;
};
struct _ECanvasClass
{
GnomeCanvasClass parent_class;
+ void (* reflow) (ECanvas *canvas);
};
@@ -63,6 +66,10 @@ GtkWidget *e_canvas_new (void);
*/
void e_canvas_item_grab_focus (GnomeCanvasItem *item);
+void e_canvas_item_request_reflow (GnomeCanvasItem *item);
+void e_canvas_item_request_parent_reflow (GnomeCanvasItem *item);
+void e_canvas_item_set_reflow_callback (GnomeCanvasItem *item, ECanvasItemReflowFunc func);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/widgets/misc/e-reflow.c b/widgets/misc/e-reflow.c
index 984e972f0c..4af46bd4a4 100644
--- a/widgets/misc/e-reflow.c
+++ b/widgets/misc/e-reflow.c
@@ -24,6 +24,7 @@
#include <math.h>
#include "e-reflow.h"
#include "e-canvas-utils.h"
+#include "e-canvas.h"
#include "e-util.h"
static void e_reflow_init (EReflow *card);
static void e_reflow_class_init (EReflowClass *klass);
@@ -36,10 +37,9 @@ static void e_reflow_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
int x, int y, int width, int height);
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 _update_reflow ( EReflow *reflow );
-static void _resize( GtkObject *object, gpointer data );
-static void _queue_reflow(EReflow *e_reflow);
+static void e_reflow_resize_children (GnomeCanvasItem *item);
#define E_REFLOW_DIVIDER_WIDTH 2
#define E_REFLOW_BORDER_WIDTH 7
@@ -47,13 +47,6 @@ static void _queue_reflow(EReflow *e_reflow);
static GnomeCanvasGroupClass *parent_class = NULL;
-enum {
- E_REFLOW_RESIZE,
- E_REFLOW_LAST_SIGNAL
-};
-
-static guint e_reflow_signals[E_REFLOW_LAST_SIGNAL] = { 0 };
-
/* The arguments we take */
enum {
ARG_0,
@@ -98,16 +91,6 @@ e_reflow_class_init (EReflowClass *klass)
parent_class = gtk_type_class (gnome_canvas_group_get_type ());
- e_reflow_signals[E_REFLOW_RESIZE] =
- gtk_signal_new ("resize",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (EReflowClass, resize),
- gtk_marshal_NONE__NONE,
- GTK_TYPE_NONE, 0);
-
- gtk_object_class_add_signals (object_class, e_reflow_signals, E_REFLOW_LAST_SIGNAL);
-
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,
@@ -149,6 +132,8 @@ e_reflow_init (EReflow *reflow)
reflow->default_cursor_shown = TRUE;
reflow->arrow_cursor = NULL;
reflow->default_cursor = NULL;
+
+ e_canvas_item_set_reflow_callback(GNOME_CANVAS_ITEM(reflow), e_reflow_reflow);
}
static void
@@ -163,11 +148,11 @@ e_reflow_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
switch (arg_id){
case ARG_HEIGHT:
e_reflow->height = GTK_VALUE_DOUBLE (*arg);
- _queue_reflow(e_reflow);
+ e_canvas_item_request_reflow(item);
break;
case ARG_MINIMUM_WIDTH:
e_reflow->minimum_width = GTK_VALUE_DOUBLE (*arg);
- _queue_reflow(e_reflow);
+ e_canvas_item_request_reflow(item);
break;
}
}
@@ -214,17 +199,13 @@ e_reflow_realize (GnomeCanvasItem *item)
for(list = e_reflow->items; list; list = g_list_next(list)) {
GnomeCanvasItem *item = GNOME_CANVAS_ITEM(list->data);
- gtk_signal_connect(GTK_OBJECT(item),
- "resize",
- GTK_SIGNAL_FUNC(_resize),
- (gpointer) e_reflow);
gnome_canvas_item_set(item,
"width", (double) e_reflow->column_width,
NULL);
}
- _queue_reflow( e_reflow );
-
+ 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;
adjustment->page_increment = adjustment->page_size - adjustment->step_increment;
@@ -365,11 +346,11 @@ e_reflow_event (GnomeCanvasItem *item, GdkEvent *event)
adjustment->step_increment = (e_reflow->column_width + E_REFLOW_FULL_GUTTER) / 2;
adjustment->page_increment = adjustment->page_size - adjustment->step_increment;
gtk_adjustment_changed(adjustment);
- _queue_reflow(e_reflow);
- } else {
- e_reflow->need_column_resize = TRUE;
- gnome_canvas_item_request_update(item);
+ e_reflow_resize_children(item);
+ e_canvas_item_request_reflow(item);
}
+ e_reflow->need_column_resize = TRUE;
+ gnome_canvas_item_request_update(item);
gnome_canvas_item_ungrab (item, button->time);
return TRUE;
}
@@ -452,14 +433,10 @@ e_reflow_add_item(EReflow *e_reflow, GnomeCanvasItem *item)
{
e_reflow->items = g_list_append(e_reflow->items, item);
if ( GTK_OBJECT_FLAGS( e_reflow ) & GNOME_CANVAS_ITEM_REALIZED ) {
- gtk_signal_connect(GTK_OBJECT(item),
- "resize",
- GTK_SIGNAL_FUNC(_resize),
- (gpointer) e_reflow);
gnome_canvas_item_set(item,
"width", (double) e_reflow->column_width,
NULL);
- _queue_reflow(e_reflow);
+ e_canvas_item_request_reflow(item);
}
}
@@ -621,6 +598,21 @@ e_reflow_update (GnomeCanvasItem *item, double affine[6], ArtSVP *clip_path, gin
}
}
+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);
+ }
+}
+
static double
e_reflow_point (GnomeCanvasItem *item,
double x, double y, int cx, int cy,
@@ -696,8 +688,9 @@ _reflow( EReflow *e_reflow )
}
static void
-_update_reflow( EReflow *e_reflow )
+e_reflow_reflow( GnomeCanvasItem *item, int flags )
{
+ EReflow *e_reflow = E_REFLOW(item);
if ( GTK_OBJECT_FLAGS( e_reflow ) & GNOME_CANVAS_ITEM_REALIZED ) {
gdouble old_width;
@@ -719,9 +712,6 @@ _update_reflow( EReflow *e_reflow )
running_height = E_REFLOW_BORDER_WIDTH;
list = e_reflow->items;
- gtk_object_set (GTK_OBJECT(list->data),
- "width", e_reflow->column_width,
- NULL);
gtk_object_get (GTK_OBJECT(list->data),
"height", &item_height,
NULL);
@@ -733,9 +723,6 @@ _update_reflow( EReflow *e_reflow )
list = g_list_next(list);
for( ; list; list = g_list_next(list)) {
- gtk_object_set (GTK_OBJECT(list->data),
- "width", e_reflow->column_width,
- NULL);
gtk_object_get (GTK_OBJECT(list->data),
"height", &item_height,
NULL);
@@ -757,31 +744,6 @@ _update_reflow( EReflow *e_reflow )
if ( e_reflow->width < e_reflow->minimum_width )
e_reflow->width = e_reflow->minimum_width;
if (old_width != e_reflow->width)
- gtk_signal_emit_by_name (GTK_OBJECT (e_reflow), "resize");
+ e_canvas_item_request_parent_reflow(item);
}
}
-
-
-static gboolean
-_idle_reflow(gpointer data)
-{
- EReflow *e_reflow = E_REFLOW(data);
- _update_reflow(e_reflow);
- e_reflow->need_height_update = TRUE;
- gnome_canvas_item_request_update(GNOME_CANVAS_ITEM(e_reflow));
- e_reflow->idle = 0;
- return FALSE;
-}
-
-static void
-_queue_reflow(EReflow *e_reflow)
-{
- if (e_reflow->idle == 0)
- e_reflow->idle = g_idle_add(_idle_reflow, e_reflow);
-}
-
-static void
-_resize( GtkObject *object, gpointer data )
-{
- _queue_reflow(E_REFLOW(data));
-}