diff options
author | Christopher James Lahey <clahey@helixcode.com> | 2000-03-11 08:32:15 +0800 |
---|---|---|
committer | Chris Lahey <clahey@src.gnome.org> | 2000-03-11 08:32:15 +0800 |
commit | 0a908b7fe481dd3bf216021fd8e04489f5f2aa66 (patch) | |
tree | cd22b484c729a21684ef46b6c99483847c43dae2 /widgets | |
parent | 8c65f8861bd16321eeafac1d827d1fb4a557247c (diff) | |
download | gsoc2013-evolution-0a908b7fe481dd3bf216021fd8e04489f5f2aa66.tar.gz gsoc2013-evolution-0a908b7fe481dd3bf216021fd8e04489f5f2aa66.tar.zst gsoc2013-evolution-0a908b7fe481dd3bf216021fd8e04489f5f2aa66.zip |
Designed a new system for doing hierarchical displays in the canvas. Adds
2000-03-10 Christopher James Lahey <clahey@helixcode.com>
* e-util/e-canvas.c, e-util/e-canvas.h: Designed a new system for
doing hierarchical displays in the canvas. Adds an extra idle
loop to the canvas system.
* widgets/e-minicard/e-minicard.c,
widgets/e-minicard/e-minicard-label.c,
widgets/e-minicard/e-minicard-label.h,
widgets/e-minicard/e-reflow.c, widgets/e-minicard/test-reflow.c,
widgets/e-text/e-text.c, widgets/e-text/e-text.h: Adapted to use
the new e-canvas reflow system.
svn path=/trunk/; revision=2096
Diffstat (limited to 'widgets')
-rw-r--r-- | widgets/e-minicard/e-minicard-label.c | 86 | ||||
-rw-r--r-- | widgets/e-minicard/e-minicard-label.h | 2 | ||||
-rw-r--r-- | widgets/e-minicard/e-minicard.c | 93 | ||||
-rw-r--r-- | widgets/e-minicard/e-reflow.c | 102 | ||||
-rw-r--r-- | widgets/e-minicard/test-reflow.c | 8 | ||||
-rw-r--r-- | widgets/e-reflow/e-reflow.c | 102 | ||||
-rw-r--r-- | widgets/e-text/e-text.c | 211 | ||||
-rw-r--r-- | widgets/e-text/e-text.h | 6 | ||||
-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 | ||||
-rw-r--r-- | widgets/text/e-text.c | 211 | ||||
-rw-r--r-- | widgets/text/e-text.h | 6 |
13 files changed, 608 insertions, 447 deletions
diff --git a/widgets/e-minicard/e-minicard-label.c b/widgets/e-minicard/e-minicard-label.c index 3f6a80a890..25f7f939fc 100644 --- a/widgets/e-minicard/e-minicard-label.c +++ b/widgets/e-minicard/e-minicard-label.c @@ -33,19 +33,12 @@ static void e_minicard_label_get_arg (GtkObject *object, GtkArg *arg, guint arg_ static gboolean e_minicard_label_event (GnomeCanvasItem *item, GdkEvent *event); static void e_minicard_label_realize (GnomeCanvasItem *item); static void e_minicard_label_unrealize (GnomeCanvasItem *item); +static void e_minicard_label_reflow(GnomeCanvasItem *item, int flags); -static void update_label( EMinicardLabel *minicard_label ); -static void resize( GtkObject *object, gpointer data ); +static void e_minicard_label_resize_children( EMinicardLabel *e_minicard_label ); static GnomeCanvasGroupClass *parent_class = NULL; -enum { - E_MINICARD_LABEL_RESIZE, - E_MINICARD_LABEL_LAST_SIGNAL -}; - -static guint e_minicard_label_signals[E_MINICARD_LABEL_LAST_SIGNAL] = { 0 }; - /* The arguments we take */ enum { ARG_0, @@ -92,17 +85,6 @@ e_minicard_label_class_init (EMinicardLabelClass *klass) parent_class = gtk_type_class (gnome_canvas_group_get_type ()); - e_minicard_label_signals[E_MINICARD_LABEL_RESIZE] = - gtk_signal_new ("resize", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EMinicardLabelClass, resize), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - - gtk_object_class_add_signals (object_class, e_minicard_label_signals, E_MINICARD_LABEL_LAST_SIGNAL); - gtk_object_add_arg_type ("EMinicardLabel::width", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_WIDTH); gtk_object_add_arg_type ("EMinicardLabel::height", GTK_TYPE_DOUBLE, @@ -113,8 +95,6 @@ e_minicard_label_class_init (EMinicardLabelClass *klass) GTK_ARG_READWRITE, ARG_FIELD); gtk_object_add_arg_type ("EMinicardLabel::fieldname", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_FIELDNAME); - - klass->resize = NULL; object_class->set_arg = e_minicard_label_set_arg; object_class->get_arg = e_minicard_label_get_arg; @@ -136,6 +116,8 @@ e_minicard_label_init (EMinicardLabel *minicard_label) minicard_label->field = NULL; minicard_label->fieldname_text = NULL; minicard_label->field_text = NULL; + + e_canvas_item_set_reflow_callback(GNOME_CANVAS_ITEM(minicard_label), e_minicard_label_reflow); } static void @@ -150,8 +132,8 @@ e_minicard_label_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) switch (arg_id){ case ARG_WIDTH: e_minicard_label->width = GTK_VALUE_DOUBLE (*arg); - update_label( e_minicard_label ); - gnome_canvas_item_request_update (item); + e_minicard_label_resize_children(e_minicard_label); + e_canvas_item_request_reflow (item); break; case ARG_HAS_FOCUS: if (e_minicard_label->field && (GTK_VALUE_ENUM(*arg) != E_FOCUS_NONE)) @@ -241,7 +223,6 @@ e_minicard_label_realize (GnomeCanvasItem *item) e_text_get_type(), "anchor", GTK_ANCHOR_NW, "clip_width", (double) ( e_minicard_label->width / 2 - 4 ), - "clip_height", (double) 1, "clip", TRUE, "use_ellipsis", TRUE, "font_gdk", font, @@ -255,17 +236,12 @@ e_minicard_label_realize (GnomeCanvasItem *item) NULL ); g_free( e_minicard_label->fieldname_text ); } - gtk_signal_connect(GTK_OBJECT(e_minicard_label->fieldname), - "resize", - GTK_SIGNAL_FUNC(resize), - (gpointer) e_minicard_label); e_minicard_label->field = gnome_canvas_item_new( group, e_text_get_type(), "anchor", GTK_ANCHOR_NW, "clip_width", (double) ( ( e_minicard_label->width + 1 ) / 2 - 4 ), - "clip_height", (double) 1, "clip", TRUE, "use_ellipsis", TRUE, "font_gdk", font, @@ -281,12 +257,7 @@ e_minicard_label_realize (GnomeCanvasItem *item) g_free( e_minicard_label->field_text ); } - gtk_signal_connect(GTK_OBJECT(e_minicard_label->field), - "resize", - GTK_SIGNAL_FUNC(resize), - (gpointer) e_minicard_label); - - update_label (e_minicard_label); + e_canvas_item_request_reflow(item); if (!item->canvas->aa) { @@ -344,10 +315,11 @@ e_minicard_label_event (GnomeCanvasItem *item, GdkEvent *event) case GDK_MOTION_NOTIFY: case GDK_ENTER_NOTIFY: case GDK_LEAVE_NOTIFY: { + gboolean return_val; +#if 0 GnomeCanvasItem *field; ArtPoint p; double inv[6], affine[6]; - gboolean return_val; field = e_minicard_label->field; art_affine_identity (affine); @@ -389,7 +361,7 @@ e_minicard_label_event (GnomeCanvasItem *item, GdkEvent *event) default: break; } - +#endif gtk_signal_emit_by_name(GTK_OBJECT(e_minicard_label->field), "event", event, &return_val); return return_val; break; @@ -405,8 +377,22 @@ e_minicard_label_event (GnomeCanvasItem *item, GdkEvent *event) } static void -update_label( EMinicardLabel *e_minicard_label ) +e_minicard_label_resize_children(EMinicardLabel *e_minicard_label) { + if ( GTK_OBJECT_FLAGS( e_minicard_label ) & GNOME_CANVAS_ITEM_REALIZED ) { + gnome_canvas_item_set( e_minicard_label->fieldname, + "clip_width", (double) ( e_minicard_label->width / 2 - 4 ), + NULL ); + gnome_canvas_item_set( e_minicard_label->field, + "clip_width", (double) ( ( e_minicard_label->width + 1 ) / 2 - 4 ), + NULL ); + } +} + +static void +e_minicard_label_reflow(GnomeCanvasItem *item, int flags) +{ + EMinicardLabel *e_minicard_label = E_MINICARD_LABEL(item); if ( GTK_OBJECT_FLAGS( e_minicard_label ) & GNOME_CANVAS_ITEM_REALIZED ) { gint old_height; @@ -416,9 +402,6 @@ update_label( EMinicardLabel *e_minicard_label ) gtk_object_get(GTK_OBJECT(e_minicard_label->fieldname), "text_height", &text_height, NULL); - gnome_canvas_item_set(e_minicard_label->fieldname, - "clip_height", (double) text_height, - NULL); e_minicard_label->height = text_height; @@ -426,9 +409,6 @@ update_label( EMinicardLabel *e_minicard_label ) gtk_object_get(GTK_OBJECT(e_minicard_label->field), "text_height", &text_height, NULL); - gnome_canvas_item_set(e_minicard_label->field, - "clip_height", (double) text_height, - NULL); if (e_minicard_label->height < text_height) e_minicard_label->height = text_height; @@ -438,24 +418,10 @@ update_label( EMinicardLabel *e_minicard_label ) "x2", (double) e_minicard_label->width - 1, "y2", (double) e_minicard_label->height - 1, NULL ); - gnome_canvas_item_set( e_minicard_label->fieldname, - "clip_width", (double) ( e_minicard_label->width / 2 - 4 ), - NULL ); - gnome_canvas_item_set( e_minicard_label->field, - "clip_width", (double) ( ( e_minicard_label->width + 1 ) / 2 - 4 ), - NULL ); e_canvas_item_move_absolute(e_minicard_label->field, ( e_minicard_label->width / 2 + 2), 1); if (old_height != e_minicard_label->height) - gtk_signal_emit_by_name (GTK_OBJECT (e_minicard_label), "resize"); + e_canvas_item_request_parent_reflow(item); } } - - -static void -resize( GtkObject *object, gpointer data ) -{ - update_label(E_MINICARD_LABEL(data)); -} - diff --git a/widgets/e-minicard/e-minicard-label.h b/widgets/e-minicard/e-minicard-label.h index 3311e3c9af..b439c53f9d 100644 --- a/widgets/e-minicard/e-minicard-label.h +++ b/widgets/e-minicard/e-minicard-label.h @@ -69,8 +69,6 @@ struct _EMinicardLabel struct _EMinicardLabelClass { GnomeCanvasGroupClass parent_class; - - void (* resize) (EMinicardLabel *text); }; diff --git a/widgets/e-minicard/e-minicard.c b/widgets/e-minicard/e-minicard.c index b8d25f5dc6..79668b6507 100644 --- a/widgets/e-minicard/e-minicard.c +++ b/widgets/e-minicard/e-minicard.c @@ -34,19 +34,12 @@ static void e_minicard_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); static gboolean e_minicard_event (GnomeCanvasItem *item, GdkEvent *event); static void e_minicard_realize (GnomeCanvasItem *item); static void e_minicard_unrealize (GnomeCanvasItem *item); +static void e_minicard_reflow ( GnomeCanvasItem *item, int flags ); -static void _update_card ( EMinicard *minicard ); -static void _resize( GtkObject *object, gpointer data ); +static void e_minicard_resize_children( EMinicard *e_minicard ); static GnomeCanvasGroupClass *parent_class = NULL; -enum { - E_MINICARD_RESIZE, - E_MINICARD_LAST_SIGNAL -}; - -static guint e_minicard_signals[E_MINICARD_LAST_SIGNAL] = { 0 }; - /* The arguments we take */ enum { ARG_0, @@ -92,17 +85,6 @@ e_minicard_class_init (EMinicardClass *klass) parent_class = gtk_type_class (gnome_canvas_group_get_type ()); - e_minicard_signals[E_MINICARD_RESIZE] = - gtk_signal_new ("resize", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EMinicardClass, resize), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - - gtk_object_class_add_signals (object_class, e_minicard_signals, E_MINICARD_LAST_SIGNAL); - gtk_object_add_arg_type ("EMinicard::width", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_WIDTH); gtk_object_add_arg_type ("EMinicard::height", GTK_TYPE_DOUBLE, @@ -131,6 +113,8 @@ e_minicard_init (EMinicard *minicard) minicard->width = 10; minicard->height = 10; minicard->has_focus = FALSE; + + e_canvas_item_set_reflow_callback(GNOME_CANVAS_ITEM(minicard), e_minicard_reflow); } static void @@ -146,8 +130,8 @@ e_minicard_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) case ARG_WIDTH: if (e_minicard->width != GTK_VALUE_DOUBLE (*arg)) { e_minicard->width = GTK_VALUE_DOUBLE (*arg); - _update_card(e_minicard); - gnome_canvas_item_request_update (item); + e_minicard_resize_children(e_minicard); + e_canvas_item_request_reflow(item); } break; case ARG_HAS_FOCUS: @@ -237,7 +221,7 @@ e_minicard_realize (GnomeCanvasItem *item) gnome_canvas_item_new( group, e_text_get_type(), "anchor", GTK_ANCHOR_NW, - "clip_width", (double) ( e_minicard->width - 12 ), + "width", (double) ( e_minicard->width - 12 ), "clip", TRUE, "use_ellipsis", TRUE, "font", "lucidasans-bold-10", @@ -246,10 +230,6 @@ e_minicard_realize (GnomeCanvasItem *item) NULL ); e_canvas_item_move_absolute(e_minicard->header_text, 6, 6); - gtk_signal_connect(GTK_OBJECT(e_minicard->header_text), - "resize", - GTK_SIGNAL_FUNC(_resize), - (gpointer) e_minicard); if ( rand() % 2 ) { new_item = gnome_canvas_item_new( group, e_minicard_label_get_type(), @@ -259,11 +239,6 @@ e_minicard_realize (GnomeCanvasItem *item) NULL ); e_minicard->fields = g_list_append( e_minicard->fields, new_item); e_canvas_item_move_absolute(new_item, 2, e_minicard->height); - - gtk_signal_connect(GTK_OBJECT(new_item), - "resize", - GTK_SIGNAL_FUNC(_resize), - (gpointer) e_minicard); } if (rand() % 2) { @@ -275,11 +250,6 @@ e_minicard_realize (GnomeCanvasItem *item) NULL ); e_minicard->fields = g_list_append( e_minicard->fields, new_item); e_canvas_item_move_absolute(new_item, 2, e_minicard->height); - - gtk_signal_connect(GTK_OBJECT(new_item), - "resize", - GTK_SIGNAL_FUNC(_resize), - (gpointer) e_minicard); } if (rand() % 2) { @@ -291,13 +261,8 @@ e_minicard_realize (GnomeCanvasItem *item) NULL ); e_minicard->fields = g_list_append( e_minicard->fields, new_item); e_canvas_item_move_absolute(new_item, 2, e_minicard->height); - - gtk_signal_connect(GTK_OBJECT(new_item), - "resize", - GTK_SIGNAL_FUNC(_resize), - (gpointer) e_minicard); } - _update_card( e_minicard ); + e_canvas_item_request_reflow(item); if (!item->canvas->aa) { } @@ -402,8 +367,26 @@ e_minicard_event (GnomeCanvasItem *item, GdkEvent *event) } static void -_update_card( EMinicard *e_minicard ) +e_minicard_resize_children( EMinicard *e_minicard ) +{ + if ( GTK_OBJECT_FLAGS( e_minicard ) & GNOME_CANVAS_ITEM_REALIZED ) { + GList *list; + + gnome_canvas_item_set( e_minicard->header_text, + "width", (double) e_minicard->width - 12, + NULL ); + for ( list = e_minicard->fields; list; list = g_list_next( list ) ) { + gnome_canvas_item_set( GNOME_CANVAS_ITEM( list->data ), + "width", (double) e_minicard->width - 4.0, + NULL ); + } + } +} + +static void +e_minicard_reflow( GnomeCanvasItem *item, int flags ) { + EMinicard *e_minicard = E_MINICARD(item); if ( GTK_OBJECT_FLAGS( e_minicard ) & GNOME_CANVAS_ITEM_REALIZED ) { GList *list; gdouble text_height; @@ -421,10 +404,6 @@ _update_card( EMinicard *e_minicard ) "y2", text_height + 9.0, NULL ); - gnome_canvas_item_set( e_minicard->header_text, - "clip_height", (double)text_height, - NULL ); - for(list = e_minicard->fields; list; list = g_list_next(list)) { gtk_object_get (GTK_OBJECT(list->data), "height", &text_height, @@ -445,22 +424,8 @@ _update_card( EMinicard *e_minicard ) gnome_canvas_item_set( e_minicard->header_rect, "x2", (double) e_minicard->width - 3.0, NULL ); - gnome_canvas_item_set( e_minicard->header_text, - "clip_width", (double) e_minicard->width - 12, - NULL ); - for ( list = e_minicard->fields; list; list = g_list_next( list ) ) { - gnome_canvas_item_set( GNOME_CANVAS_ITEM( list->data ), - "width", (double) e_minicard->width - 4.0, - NULL ); if (old_height != e_minicard->height) - gtk_signal_emit_by_name (GTK_OBJECT (e_minicard), "resize"); - } - } -} - -static void -_resize( GtkObject *object, gpointer data ) -{ - _update_card(E_MINICARD(data)); + e_canvas_item_request_parent_reflow(item); + } } diff --git a/widgets/e-minicard/e-reflow.c b/widgets/e-minicard/e-reflow.c index 984e972f0c..4af46bd4a4 100644 --- a/widgets/e-minicard/e-reflow.c +++ b/widgets/e-minicard/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)); -} diff --git a/widgets/e-minicard/test-reflow.c b/widgets/e-minicard/test-reflow.c index 319a3f5626..8cedbaac28 100644 --- a/widgets/e-minicard/test-reflow.c +++ b/widgets/e-minicard/test-reflow.c @@ -55,14 +55,14 @@ static void allocate_callback(GtkWidget *canvas, GtkAllocation *allocation, gpoi NULL ); } -static void resize(GnomeCanvasItem *item, gpointer data) +static void resize(GnomeCanvas *canvas, gpointer data) { double width; gtk_object_get(GTK_OBJECT(reflow), - "width", &width, + "width", &width, NULL); width = MAX(width, last_alloc.width); - gnome_canvas_set_scroll_region(item->canvas , 0, 0, width, last_alloc.height ); + gnome_canvas_set_scroll_region(canvas , 0, 0, width, last_alloc.height ); gnome_canvas_item_set( rect, "x2", (double) width, "y2", (double) last_alloc.height, @@ -121,7 +121,7 @@ int main( int argc, char *argv[] ) "height", (double) 100, "minimum_width", (double) 100, NULL ); - gtk_signal_connect( GTK_OBJECT( reflow ), "resize", + gtk_signal_connect( GTK_OBJECT( canvas ), "reflow", GTK_SIGNAL_FUNC( resize ), ( gpointer ) app); for ( i = 0; i < 200; i++ ) diff --git a/widgets/e-reflow/e-reflow.c b/widgets/e-reflow/e-reflow.c index 984e972f0c..4af46bd4a4 100644 --- a/widgets/e-reflow/e-reflow.c +++ b/widgets/e-reflow/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)); -} diff --git a/widgets/e-text/e-text.c b/widgets/e-text/e-text.c index d9448fe783..ca41dc1d96 100644 --- a/widgets/e-text/e-text.c +++ b/widgets/e-text/e-text.c @@ -25,6 +25,7 @@ #include <libart_lgpl/art_rgb.h> #include <libart_lgpl/art_rgb_bitmap_affine.h> #include <gtk/gtkinvisible.h> +#include "e-util/e-canvas.h" #include "e-text-event-processor-emacs-like.h" @@ -75,7 +76,9 @@ enum { ARG_ELLIPSIS, ARG_LINE_WRAP, ARG_BREAK_CHARACTERS, - ARG_MAX_LINES + ARG_MAX_LINES, + ARG_WIDTH, + ARG_HEIGHT }; @@ -95,6 +98,7 @@ static void e_text_destroy (GtkObject *object); static void e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id); static void e_text_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); +static void e_text_reflow (GnomeCanvasItem *item, int flags); static void e_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags); static void e_text_realize (GnomeCanvasItem *item); @@ -250,6 +254,10 @@ e_text_class_init (ETextClass *klass) GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_BREAK_CHARACTERS); gtk_object_add_arg_type ("EText::max_lines", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_MAX_LINES); + gtk_object_add_arg_type ("EText::width", + GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_WIDTH); + gtk_object_add_arg_type ("EText::height", + GTK_TYPE_DOUBLE, GTK_ARG_READABLE, ARG_HEIGHT); if (!clipboard_atom) clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); @@ -325,6 +333,8 @@ e_text_init (EText *text) text->line_wrap = FALSE; text->break_characters = NULL; text->max_lines = -1; + + e_canvas_item_set_reflow_callback(GNOME_CANVAS_ITEM(text), e_text_reflow); } /* Destroy handler for the text item */ @@ -460,43 +470,14 @@ get_bounds_item_relative (EText *text, double *px1, double *py1, double *px2, do } } - -static gboolean -idle_resize(gpointer data) -{ - EText *text = E_TEXT(data); - gtk_signal_emit_by_name (GTK_OBJECT (text), "resize"); - return FALSE; -} - -static void -queue_resize_signal(EText *text) -{ - if (text->idle == 0) - text->idle = g_idle_add(idle_resize, text); -} - static void get_bounds (EText *text, double *px1, double *py1, double *px2, double *py2) { GnomeCanvasItem *item; double wx, wy; - int old_height; item = GNOME_CANVAS_ITEM (text); - /* Calculate text dimensions */ - - old_height = text->height; - - if (text->text && text->font) - text->height = (text->font->ascent + text->font->descent) * text->num_lines; - else - text->height = 0; - - if (old_height != text->height) - queue_resize_signal(text); - /* Get canvas pixel coordinates for text position */ wx = text->x; @@ -573,6 +554,27 @@ get_bounds (EText *text, double *px1, double *py1, double *px2, double *py2) } static void +calc_height (EText *text) +{ + GnomeCanvasItem *item; + int old_height; + + item = GNOME_CANVAS_ITEM (text); + + /* Calculate text dimensions */ + + old_height = text->height; + + if (text->text && text->font) + text->height = (text->font->ascent + text->font->descent) * text->num_lines; + else + text->height = 0; + + if (old_height != text->height) + e_canvas_item_request_parent_reflow(item); +} + +static void calc_ellipsis (EText *text) { if (text->font) @@ -635,6 +637,16 @@ calc_line_widths (EText *text) } } +static void +e_text_free_lines(EText *text) +{ + if (text->lines) + g_free (text->lines); + + text->lines = NULL; + text->num_lines = 0; +} + #define IS_BREAKCHAR(text,c) ((text)->break_characters && strchr ((text)->break_characters, (c))) /* Splits the text of the text item into lines */ static void @@ -649,11 +661,8 @@ split_into_lines (EText *text) char *linestart; /* Free old array of lines */ + e_text_free_lines(text); - if (text->lines) - g_free (text->lines); - - text->lines = NULL; text->num_lines = 0; if (!text->text) @@ -850,6 +859,9 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) GdkColor *pcolor; gboolean color_changed; int have_pixel; + + gboolean needs_update = 0; + gboolean needs_reflow = 0; item = GNOME_CANVAS_ITEM (object); text = E_TEXT (object); @@ -863,17 +875,21 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) g_free (text->text); text->text = g_strdup (GTK_VALUE_STRING (*arg)); + e_text_free_lines(text); text->needs_split_into_lines = 1; + needs_reflow = 1; break; case ARG_X: text->x = GTK_VALUE_DOUBLE (*arg); text->needs_recalc_bounds = 1; + needs_update = 1; break; case ARG_Y: text->y = GTK_VALUE_DOUBLE (*arg); text->needs_recalc_bounds = 1; + needs_update = 1; break; case ARG_FONT: @@ -894,6 +910,7 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) text->needs_split_into_lines = 1; else text->needs_calc_line_widths = 1; + needs_reflow = 1; break; case ARG_FONTSET: @@ -914,6 +931,7 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) text->needs_split_into_lines = 1; else text->needs_calc_line_widths = 1; + needs_reflow = 1; break; case ARG_FONT_GDK: @@ -934,16 +952,19 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) text->needs_split_into_lines = 1; else text->needs_calc_line_widths = 1; + needs_reflow = 1; break; case ARG_ANCHOR: text->anchor = GTK_VALUE_ENUM (*arg); text->needs_recalc_bounds = 1; + needs_update = 1; break; case ARG_JUSTIFICATION: text->justification = GTK_VALUE_ENUM (*arg); text->needs_redraw = 1; + needs_update = 1; break; case ARG_CLIP_WIDTH: @@ -953,11 +974,13 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) text->needs_split_into_lines = 1; else text->needs_calc_line_widths = 1; + needs_reflow = 1; break; case ARG_CLIP_HEIGHT: text->clip_height = fabs (GTK_VALUE_DOUBLE (*arg)); text->needs_recalc_bounds = 1; + needs_reflow = 1; break; case ARG_CLIP: @@ -967,16 +990,19 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) text->needs_split_into_lines = 1; else text->needs_calc_line_widths = 1; + needs_reflow = 1; break; case ARG_X_OFFSET: text->xofs = GTK_VALUE_DOUBLE (*arg); text->needs_recalc_bounds = 1; + needs_update = 1; break; case ARG_Y_OFFSET: text->yofs = GTK_VALUE_DOUBLE (*arg); text->needs_recalc_bounds = 1; + needs_update = 1; break; case ARG_FILL_COLOR: @@ -989,6 +1015,7 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) 0xff); color_changed = TRUE; text->needs_redraw = 1; + needs_update = 1; break; case ARG_FILL_COLOR_GDK: @@ -1005,27 +1032,32 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) 0xff); color_changed = TRUE; text->needs_redraw = 1; + needs_update = 1; break; case ARG_FILL_COLOR_RGBA: text->rgba = GTK_VALUE_UINT (*arg); color_changed = TRUE; text->needs_redraw = 1; + needs_update = 1; break; case ARG_FILL_STIPPLE: set_stipple (text, GTK_VALUE_BOXED (*arg), FALSE); text->needs_redraw = 1; + needs_update = 1; break; case ARG_EDITABLE: text->editable = GTK_VALUE_BOOL (*arg); text->needs_redraw = 1; + needs_update = 1; break; case ARG_USE_ELLIPSIS: text->use_ellipsis = GTK_VALUE_BOOL (*arg); text->needs_calc_line_widths = 1; + needs_reflow = 1; break; case ARG_ELLIPSIS: @@ -1035,11 +1067,13 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) text->ellipsis = g_strdup (GTK_VALUE_STRING (*arg)); calc_ellipsis (text); text->needs_calc_line_widths = 1; + needs_reflow = 1; break; case ARG_LINE_WRAP: text->line_wrap = GTK_VALUE_BOOL (*arg); text->needs_split_into_lines = 1; + needs_reflow = 1; break; case ARG_BREAK_CHARACTERS: @@ -1050,11 +1084,23 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) if ( GTK_VALUE_STRING (*arg) ) text->break_characters = g_strdup( GTK_VALUE_STRING (*arg) ); text->needs_split_into_lines = 1; + needs_reflow = 1; break; case ARG_MAX_LINES: text->max_lines = GTK_VALUE_INT (*arg); text->needs_split_into_lines = 1; + needs_reflow = 1; + break; + + case ARG_WIDTH: + text->clip_width = fabs (GTK_VALUE_DOUBLE (*arg)); + calc_ellipsis (text); + if ( text->line_wrap ) + text->needs_split_into_lines = 1; + else + text->needs_calc_line_widths = 1; + needs_reflow = 1; break; default: @@ -1072,7 +1118,10 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) } - gnome_canvas_item_request_update (item); + if ( needs_reflow ) + e_canvas_item_request_reflow (item); + if ( needs_update ) + gnome_canvas_item_request_update (item); } /* Get_arg handler for the text item */ @@ -1176,6 +1225,14 @@ e_text_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) GTK_VALUE_INT (*arg) = text->max_lines; break; + case ARG_WIDTH: + GTK_VALUE_DOUBLE (*arg) = text->clip_width; + break; + + case ARG_HEIGHT: + GTK_VALUE_DOUBLE (*arg) = text->max_width / text->item.canvas->pixels_per_unit; + break; + default: arg->type = GTK_TYPE_INVALID; break; @@ -1184,18 +1241,12 @@ e_text_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) /* Update handler for the text item */ static void -e_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +e_text_reflow (GnomeCanvasItem *item, int flags) { EText *text; - double x1, y1, x2, y2; - ArtDRect i_bbox, c_bbox; - int i; text = E_TEXT (item); - if (parent_class->update) - (* parent_class->update) (item, affine, clip_path, flags); - if ( text->needs_split_into_lines ) { split_into_lines(text); text->needs_split_into_lines = 0; @@ -1204,9 +1255,30 @@ e_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int fla if ( text->needs_calc_line_widths ) { calc_line_widths(text); text->needs_calc_line_widths = 0; - text->needs_recalc_bounds = 1; + text->needs_calc_height = 1; text->needs_redraw = 1; } + if ( text->needs_calc_height ) { + calc_height (text); + gnome_canvas_item_request_update(item); + text->needs_calc_height = 0; + } +} + +/* Update handler for the text item */ +static void +e_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + EText *text; + double x1, y1, x2, y2; + ArtDRect i_bbox, c_bbox; + int i; + + text = E_TEXT (item); + + if (parent_class->update) + (* parent_class->update) (item, affine, clip_path, flags); + if ( text->needs_recalc_bounds || (flags & GNOME_CANVAS_UPDATE_AFFINE)) { if (!item->canvas->aa) { @@ -1232,6 +1304,7 @@ e_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int fla art_drect_affine_transform (&c_bbox, &i_bbox, affine); } text->needs_recalc_bounds = 0; + get_bounds (text, &x1, &y1, &x2, &y2); } if ( text->needs_redraw ) { gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2); @@ -1415,6 +1488,10 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable, if (!text->text || !text->font) return; + lines = text->lines; + if ( !lines ) + return; + clip_rect = NULL; if (text->clip) { rect.x = text->clip_cx - x; @@ -1426,7 +1503,6 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable, gdk_gc_set_clip_rectangle (fg_gc, &rect); clip_rect = ▭ } - lines = text->lines; ypos = text->cy + text->font->ascent; if (text->stipple) @@ -1583,6 +1659,9 @@ e_text_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf) gnome_canvas_buf_ensure_buf (buf); lines = text->lines; + if ( !lines ) + return; + start_i.y = get_line_ypos_item_relative (text); art_affine_scale (affine, item->canvas->pixels_per_unit, item->canvas->pixels_per_unit); @@ -1660,6 +1739,8 @@ e_text_point (GnomeCanvasItem *item, double x, double y, best = 1.0e36; lines = text->lines; + if ( lines ) + return 1; for (i = 0; i < text->num_lines; i++) { /* Compute the coordinates of rectangle for the current line, @@ -1790,12 +1871,15 @@ e_text_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double static void _get_xy_from_position (EText *text, gint position, gint *xp, gint *yp) { + if ( !text->lines ) + return; if (xp || yp) { struct line *lines = NULL; int x, y; + double xd, yd; int j; - x = get_line_xpos (text, lines); - y = text->cy; + x = get_line_xpos_item_relative (text, lines); + y = text->y + text->yofs; for (j = 0, lines = text->lines; j < text->num_lines; lines++, j++) { if (lines->text > text->text + position) break; @@ -1808,6 +1892,11 @@ _get_xy_from_position (EText *text, gint position, gint *xp, gint *yp) lines->text, position - (lines->text - text->text)); x -= text->xofs_edit; + + xd = x; yd = y; + gnome_canvas_item_i2w (GNOME_CANVAS_ITEM(text), &xd, &yd); + gnome_canvas_w2c (GNOME_CANVAS_ITEM(text)->canvas, xd, yd, &x, &y); + if (xp) *xp = x; if (yp) @@ -1819,9 +1908,17 @@ static gint _get_position_from_xy (EText *text, gint x, gint y) { int i, j; - int ypos = text->cy; + int ypos = text->y + text->yofs; int xpos; + double xd, yd; + struct line *lines; + + xd = x; yd = y; + gnome_canvas_c2w (GNOME_CANVAS_ITEM(text)->canvas, xd, yd, &xd, &yd); + gnome_canvas_item_w2i (GNOME_CANVAS_ITEM(text), &xd, &yd); + x = xd; y = yd; + j = 0; while (y > ypos) { ypos += text->font->ascent + text->font->descent; @@ -1834,9 +1931,13 @@ _get_position_from_xy (EText *text, gint x, gint y) j = 0; i = 0; lines = text->lines; + + if ( !lines ) + return 0; + lines += j; x += text->xofs_edit; - xpos = get_line_xpos (text, lines); + xpos = get_line_xpos_item_relative (text, lines); for(i = 0; i < lines->length; i++) { int charwidth = gdk_text_width(text->font, lines->text + i, @@ -1929,6 +2030,9 @@ _do_tooltip (gpointer data) return FALSE; lines = text->lines; + + if ( !lines ) + return FALSE; cut_off = FALSE; for ( lines = text->lines, i = 0; i < text->num_lines; lines++, i++ ) { @@ -2025,7 +2129,7 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event) text->needs_split_into_lines = 1; else text->needs_calc_line_widths = 1; - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(text)); + e_canvas_item_request_reflow (GNOME_CANVAS_ITEM(text)); } return_val = 0; break; @@ -2302,8 +2406,9 @@ e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gp text->selection_end = _get_position(text, command); } _delete_selection(text); + e_text_free_lines(text); text->needs_split_into_lines = 1; - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(text)); + e_canvas_item_request_reflow (GNOME_CANVAS_ITEM(text)); if (text->timer) { g_timer_reset(text->timer); } @@ -2314,8 +2419,9 @@ e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gp _delete_selection(text); } _insert(text, command->string, command->value); + e_text_free_lines(text); text->needs_split_into_lines = 1; - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(text)); + e_canvas_item_request_reflow (GNOME_CANVAS_ITEM(text)); if (text->timer) { g_timer_reset(text->timer); } @@ -2364,6 +2470,9 @@ e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gp int x; int i; struct line *lines = text->lines; + if ( !lines ) + return; + for (lines = text->lines, i = 0; i < text->num_lines ; i++, lines ++) { if (lines->text - text->text > text->selection_end) { break; diff --git a/widgets/e-text/e-text.h b/widgets/e-text/e-text.h index 3e1dcb5f0e..52fb951bc2 100644 --- a/widgets/e-text/e-text.h +++ b/widgets/e-text/e-text.h @@ -58,6 +58,8 @@ BEGIN_GNOME_DECLS * y_offset double RW Vertical offset distance from anchor position * text_width double R Used to query the width of the rendered text * text_height double R Used to query the rendered height of the text + * width double RW A synonym for clip_width + * height double R A synonym for text_height * * These are currently ignored in the AA version: * editable boolean RW Can this item be edited @@ -122,6 +124,7 @@ struct _EText { int clip_cx, clip_cy; /* Top-left canvas coordinates for clip rectangle */ int clip_cwidth, clip_cheight; /* Size of clip rectangle in pixels */ int max_width; /* Maximum width of text lines */ + int width; /* Rendered text width in pixels */ int height; /* Rendered text height in pixels */ guint clip : 1; /* Use clip rectangle? */ @@ -182,10 +185,9 @@ struct _EText { guint needs_redraw : 1; /* Needs redraw */ guint needs_recalc_bounds : 1; /* Need recalc_bounds */ + guint needs_calc_height : 1; /* Need calc_height */ guint needs_calc_line_widths : 1; /* Needs calc_line_widths */ guint needs_split_into_lines : 1; /* Needs split_into_lines */ - - gint idle; }; struct _ETextClass { 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)); -} diff --git a/widgets/text/e-text.c b/widgets/text/e-text.c index d9448fe783..ca41dc1d96 100644 --- a/widgets/text/e-text.c +++ b/widgets/text/e-text.c @@ -25,6 +25,7 @@ #include <libart_lgpl/art_rgb.h> #include <libart_lgpl/art_rgb_bitmap_affine.h> #include <gtk/gtkinvisible.h> +#include "e-util/e-canvas.h" #include "e-text-event-processor-emacs-like.h" @@ -75,7 +76,9 @@ enum { ARG_ELLIPSIS, ARG_LINE_WRAP, ARG_BREAK_CHARACTERS, - ARG_MAX_LINES + ARG_MAX_LINES, + ARG_WIDTH, + ARG_HEIGHT }; @@ -95,6 +98,7 @@ static void e_text_destroy (GtkObject *object); static void e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id); static void e_text_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); +static void e_text_reflow (GnomeCanvasItem *item, int flags); static void e_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags); static void e_text_realize (GnomeCanvasItem *item); @@ -250,6 +254,10 @@ e_text_class_init (ETextClass *klass) GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_BREAK_CHARACTERS); gtk_object_add_arg_type ("EText::max_lines", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_MAX_LINES); + gtk_object_add_arg_type ("EText::width", + GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_WIDTH); + gtk_object_add_arg_type ("EText::height", + GTK_TYPE_DOUBLE, GTK_ARG_READABLE, ARG_HEIGHT); if (!clipboard_atom) clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); @@ -325,6 +333,8 @@ e_text_init (EText *text) text->line_wrap = FALSE; text->break_characters = NULL; text->max_lines = -1; + + e_canvas_item_set_reflow_callback(GNOME_CANVAS_ITEM(text), e_text_reflow); } /* Destroy handler for the text item */ @@ -460,43 +470,14 @@ get_bounds_item_relative (EText *text, double *px1, double *py1, double *px2, do } } - -static gboolean -idle_resize(gpointer data) -{ - EText *text = E_TEXT(data); - gtk_signal_emit_by_name (GTK_OBJECT (text), "resize"); - return FALSE; -} - -static void -queue_resize_signal(EText *text) -{ - if (text->idle == 0) - text->idle = g_idle_add(idle_resize, text); -} - static void get_bounds (EText *text, double *px1, double *py1, double *px2, double *py2) { GnomeCanvasItem *item; double wx, wy; - int old_height; item = GNOME_CANVAS_ITEM (text); - /* Calculate text dimensions */ - - old_height = text->height; - - if (text->text && text->font) - text->height = (text->font->ascent + text->font->descent) * text->num_lines; - else - text->height = 0; - - if (old_height != text->height) - queue_resize_signal(text); - /* Get canvas pixel coordinates for text position */ wx = text->x; @@ -573,6 +554,27 @@ get_bounds (EText *text, double *px1, double *py1, double *px2, double *py2) } static void +calc_height (EText *text) +{ + GnomeCanvasItem *item; + int old_height; + + item = GNOME_CANVAS_ITEM (text); + + /* Calculate text dimensions */ + + old_height = text->height; + + if (text->text && text->font) + text->height = (text->font->ascent + text->font->descent) * text->num_lines; + else + text->height = 0; + + if (old_height != text->height) + e_canvas_item_request_parent_reflow(item); +} + +static void calc_ellipsis (EText *text) { if (text->font) @@ -635,6 +637,16 @@ calc_line_widths (EText *text) } } +static void +e_text_free_lines(EText *text) +{ + if (text->lines) + g_free (text->lines); + + text->lines = NULL; + text->num_lines = 0; +} + #define IS_BREAKCHAR(text,c) ((text)->break_characters && strchr ((text)->break_characters, (c))) /* Splits the text of the text item into lines */ static void @@ -649,11 +661,8 @@ split_into_lines (EText *text) char *linestart; /* Free old array of lines */ + e_text_free_lines(text); - if (text->lines) - g_free (text->lines); - - text->lines = NULL; text->num_lines = 0; if (!text->text) @@ -850,6 +859,9 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) GdkColor *pcolor; gboolean color_changed; int have_pixel; + + gboolean needs_update = 0; + gboolean needs_reflow = 0; item = GNOME_CANVAS_ITEM (object); text = E_TEXT (object); @@ -863,17 +875,21 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) g_free (text->text); text->text = g_strdup (GTK_VALUE_STRING (*arg)); + e_text_free_lines(text); text->needs_split_into_lines = 1; + needs_reflow = 1; break; case ARG_X: text->x = GTK_VALUE_DOUBLE (*arg); text->needs_recalc_bounds = 1; + needs_update = 1; break; case ARG_Y: text->y = GTK_VALUE_DOUBLE (*arg); text->needs_recalc_bounds = 1; + needs_update = 1; break; case ARG_FONT: @@ -894,6 +910,7 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) text->needs_split_into_lines = 1; else text->needs_calc_line_widths = 1; + needs_reflow = 1; break; case ARG_FONTSET: @@ -914,6 +931,7 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) text->needs_split_into_lines = 1; else text->needs_calc_line_widths = 1; + needs_reflow = 1; break; case ARG_FONT_GDK: @@ -934,16 +952,19 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) text->needs_split_into_lines = 1; else text->needs_calc_line_widths = 1; + needs_reflow = 1; break; case ARG_ANCHOR: text->anchor = GTK_VALUE_ENUM (*arg); text->needs_recalc_bounds = 1; + needs_update = 1; break; case ARG_JUSTIFICATION: text->justification = GTK_VALUE_ENUM (*arg); text->needs_redraw = 1; + needs_update = 1; break; case ARG_CLIP_WIDTH: @@ -953,11 +974,13 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) text->needs_split_into_lines = 1; else text->needs_calc_line_widths = 1; + needs_reflow = 1; break; case ARG_CLIP_HEIGHT: text->clip_height = fabs (GTK_VALUE_DOUBLE (*arg)); text->needs_recalc_bounds = 1; + needs_reflow = 1; break; case ARG_CLIP: @@ -967,16 +990,19 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) text->needs_split_into_lines = 1; else text->needs_calc_line_widths = 1; + needs_reflow = 1; break; case ARG_X_OFFSET: text->xofs = GTK_VALUE_DOUBLE (*arg); text->needs_recalc_bounds = 1; + needs_update = 1; break; case ARG_Y_OFFSET: text->yofs = GTK_VALUE_DOUBLE (*arg); text->needs_recalc_bounds = 1; + needs_update = 1; break; case ARG_FILL_COLOR: @@ -989,6 +1015,7 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) 0xff); color_changed = TRUE; text->needs_redraw = 1; + needs_update = 1; break; case ARG_FILL_COLOR_GDK: @@ -1005,27 +1032,32 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) 0xff); color_changed = TRUE; text->needs_redraw = 1; + needs_update = 1; break; case ARG_FILL_COLOR_RGBA: text->rgba = GTK_VALUE_UINT (*arg); color_changed = TRUE; text->needs_redraw = 1; + needs_update = 1; break; case ARG_FILL_STIPPLE: set_stipple (text, GTK_VALUE_BOXED (*arg), FALSE); text->needs_redraw = 1; + needs_update = 1; break; case ARG_EDITABLE: text->editable = GTK_VALUE_BOOL (*arg); text->needs_redraw = 1; + needs_update = 1; break; case ARG_USE_ELLIPSIS: text->use_ellipsis = GTK_VALUE_BOOL (*arg); text->needs_calc_line_widths = 1; + needs_reflow = 1; break; case ARG_ELLIPSIS: @@ -1035,11 +1067,13 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) text->ellipsis = g_strdup (GTK_VALUE_STRING (*arg)); calc_ellipsis (text); text->needs_calc_line_widths = 1; + needs_reflow = 1; break; case ARG_LINE_WRAP: text->line_wrap = GTK_VALUE_BOOL (*arg); text->needs_split_into_lines = 1; + needs_reflow = 1; break; case ARG_BREAK_CHARACTERS: @@ -1050,11 +1084,23 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) if ( GTK_VALUE_STRING (*arg) ) text->break_characters = g_strdup( GTK_VALUE_STRING (*arg) ); text->needs_split_into_lines = 1; + needs_reflow = 1; break; case ARG_MAX_LINES: text->max_lines = GTK_VALUE_INT (*arg); text->needs_split_into_lines = 1; + needs_reflow = 1; + break; + + case ARG_WIDTH: + text->clip_width = fabs (GTK_VALUE_DOUBLE (*arg)); + calc_ellipsis (text); + if ( text->line_wrap ) + text->needs_split_into_lines = 1; + else + text->needs_calc_line_widths = 1; + needs_reflow = 1; break; default: @@ -1072,7 +1118,10 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) } - gnome_canvas_item_request_update (item); + if ( needs_reflow ) + e_canvas_item_request_reflow (item); + if ( needs_update ) + gnome_canvas_item_request_update (item); } /* Get_arg handler for the text item */ @@ -1176,6 +1225,14 @@ e_text_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) GTK_VALUE_INT (*arg) = text->max_lines; break; + case ARG_WIDTH: + GTK_VALUE_DOUBLE (*arg) = text->clip_width; + break; + + case ARG_HEIGHT: + GTK_VALUE_DOUBLE (*arg) = text->max_width / text->item.canvas->pixels_per_unit; + break; + default: arg->type = GTK_TYPE_INVALID; break; @@ -1184,18 +1241,12 @@ e_text_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) /* Update handler for the text item */ static void -e_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +e_text_reflow (GnomeCanvasItem *item, int flags) { EText *text; - double x1, y1, x2, y2; - ArtDRect i_bbox, c_bbox; - int i; text = E_TEXT (item); - if (parent_class->update) - (* parent_class->update) (item, affine, clip_path, flags); - if ( text->needs_split_into_lines ) { split_into_lines(text); text->needs_split_into_lines = 0; @@ -1204,9 +1255,30 @@ e_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int fla if ( text->needs_calc_line_widths ) { calc_line_widths(text); text->needs_calc_line_widths = 0; - text->needs_recalc_bounds = 1; + text->needs_calc_height = 1; text->needs_redraw = 1; } + if ( text->needs_calc_height ) { + calc_height (text); + gnome_canvas_item_request_update(item); + text->needs_calc_height = 0; + } +} + +/* Update handler for the text item */ +static void +e_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + EText *text; + double x1, y1, x2, y2; + ArtDRect i_bbox, c_bbox; + int i; + + text = E_TEXT (item); + + if (parent_class->update) + (* parent_class->update) (item, affine, clip_path, flags); + if ( text->needs_recalc_bounds || (flags & GNOME_CANVAS_UPDATE_AFFINE)) { if (!item->canvas->aa) { @@ -1232,6 +1304,7 @@ e_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int fla art_drect_affine_transform (&c_bbox, &i_bbox, affine); } text->needs_recalc_bounds = 0; + get_bounds (text, &x1, &y1, &x2, &y2); } if ( text->needs_redraw ) { gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2); @@ -1415,6 +1488,10 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable, if (!text->text || !text->font) return; + lines = text->lines; + if ( !lines ) + return; + clip_rect = NULL; if (text->clip) { rect.x = text->clip_cx - x; @@ -1426,7 +1503,6 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable, gdk_gc_set_clip_rectangle (fg_gc, &rect); clip_rect = ▭ } - lines = text->lines; ypos = text->cy + text->font->ascent; if (text->stipple) @@ -1583,6 +1659,9 @@ e_text_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf) gnome_canvas_buf_ensure_buf (buf); lines = text->lines; + if ( !lines ) + return; + start_i.y = get_line_ypos_item_relative (text); art_affine_scale (affine, item->canvas->pixels_per_unit, item->canvas->pixels_per_unit); @@ -1660,6 +1739,8 @@ e_text_point (GnomeCanvasItem *item, double x, double y, best = 1.0e36; lines = text->lines; + if ( lines ) + return 1; for (i = 0; i < text->num_lines; i++) { /* Compute the coordinates of rectangle for the current line, @@ -1790,12 +1871,15 @@ e_text_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double static void _get_xy_from_position (EText *text, gint position, gint *xp, gint *yp) { + if ( !text->lines ) + return; if (xp || yp) { struct line *lines = NULL; int x, y; + double xd, yd; int j; - x = get_line_xpos (text, lines); - y = text->cy; + x = get_line_xpos_item_relative (text, lines); + y = text->y + text->yofs; for (j = 0, lines = text->lines; j < text->num_lines; lines++, j++) { if (lines->text > text->text + position) break; @@ -1808,6 +1892,11 @@ _get_xy_from_position (EText *text, gint position, gint *xp, gint *yp) lines->text, position - (lines->text - text->text)); x -= text->xofs_edit; + + xd = x; yd = y; + gnome_canvas_item_i2w (GNOME_CANVAS_ITEM(text), &xd, &yd); + gnome_canvas_w2c (GNOME_CANVAS_ITEM(text)->canvas, xd, yd, &x, &y); + if (xp) *xp = x; if (yp) @@ -1819,9 +1908,17 @@ static gint _get_position_from_xy (EText *text, gint x, gint y) { int i, j; - int ypos = text->cy; + int ypos = text->y + text->yofs; int xpos; + double xd, yd; + struct line *lines; + + xd = x; yd = y; + gnome_canvas_c2w (GNOME_CANVAS_ITEM(text)->canvas, xd, yd, &xd, &yd); + gnome_canvas_item_w2i (GNOME_CANVAS_ITEM(text), &xd, &yd); + x = xd; y = yd; + j = 0; while (y > ypos) { ypos += text->font->ascent + text->font->descent; @@ -1834,9 +1931,13 @@ _get_position_from_xy (EText *text, gint x, gint y) j = 0; i = 0; lines = text->lines; + + if ( !lines ) + return 0; + lines += j; x += text->xofs_edit; - xpos = get_line_xpos (text, lines); + xpos = get_line_xpos_item_relative (text, lines); for(i = 0; i < lines->length; i++) { int charwidth = gdk_text_width(text->font, lines->text + i, @@ -1929,6 +2030,9 @@ _do_tooltip (gpointer data) return FALSE; lines = text->lines; + + if ( !lines ) + return FALSE; cut_off = FALSE; for ( lines = text->lines, i = 0; i < text->num_lines; lines++, i++ ) { @@ -2025,7 +2129,7 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event) text->needs_split_into_lines = 1; else text->needs_calc_line_widths = 1; - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(text)); + e_canvas_item_request_reflow (GNOME_CANVAS_ITEM(text)); } return_val = 0; break; @@ -2302,8 +2406,9 @@ e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gp text->selection_end = _get_position(text, command); } _delete_selection(text); + e_text_free_lines(text); text->needs_split_into_lines = 1; - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(text)); + e_canvas_item_request_reflow (GNOME_CANVAS_ITEM(text)); if (text->timer) { g_timer_reset(text->timer); } @@ -2314,8 +2419,9 @@ e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gp _delete_selection(text); } _insert(text, command->string, command->value); + e_text_free_lines(text); text->needs_split_into_lines = 1; - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(text)); + e_canvas_item_request_reflow (GNOME_CANVAS_ITEM(text)); if (text->timer) { g_timer_reset(text->timer); } @@ -2364,6 +2470,9 @@ e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gp int x; int i; struct line *lines = text->lines; + if ( !lines ) + return; + for (lines = text->lines, i = 0; i < text->num_lines ; i++, lines ++) { if (lines->text - text->text > text->selection_end) { break; diff --git a/widgets/text/e-text.h b/widgets/text/e-text.h index 3e1dcb5f0e..52fb951bc2 100644 --- a/widgets/text/e-text.h +++ b/widgets/text/e-text.h @@ -58,6 +58,8 @@ BEGIN_GNOME_DECLS * y_offset double RW Vertical offset distance from anchor position * text_width double R Used to query the width of the rendered text * text_height double R Used to query the rendered height of the text + * width double RW A synonym for clip_width + * height double R A synonym for text_height * * These are currently ignored in the AA version: * editable boolean RW Can this item be edited @@ -122,6 +124,7 @@ struct _EText { int clip_cx, clip_cy; /* Top-left canvas coordinates for clip rectangle */ int clip_cwidth, clip_cheight; /* Size of clip rectangle in pixels */ int max_width; /* Maximum width of text lines */ + int width; /* Rendered text width in pixels */ int height; /* Rendered text height in pixels */ guint clip : 1; /* Use clip rectangle? */ @@ -182,10 +185,9 @@ struct _EText { guint needs_redraw : 1; /* Needs redraw */ guint needs_recalc_bounds : 1; /* Need recalc_bounds */ + guint needs_calc_height : 1; /* Need calc_height */ guint needs_calc_line_widths : 1; /* Needs calc_line_widths */ guint needs_split_into_lines : 1; /* Needs split_into_lines */ - - gint idle; }; struct _ETextClass { |