diff options
Diffstat (limited to 'widgets/misc')
-rw-r--r-- | widgets/misc/e-canvas.c | 117 | ||||
-rw-r--r-- | widgets/misc/e-canvas.h | 9 | ||||
-rw-r--r-- | widgets/misc/e-reflow.c | 102 |
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)); -} |