diff options
Diffstat (limited to 'widgets')
-rw-r--r-- | widgets/e-minicard/e-minicard-label.c | 11 | ||||
-rw-r--r-- | widgets/e-minicard/e-minicard-label.h | 20 | ||||
-rw-r--r-- | widgets/e-minicard/e-minicard.c | 17 | ||||
-rw-r--r-- | widgets/e-text/e-text-test.c | 6 | ||||
-rw-r--r-- | widgets/e-text/e-text.c | 189 | ||||
-rw-r--r-- | widgets/e-text/e-text.h | 6 | ||||
-rw-r--r-- | widgets/text/e-text-test.c | 6 | ||||
-rw-r--r-- | widgets/text/e-text.c | 189 | ||||
-rw-r--r-- | widgets/text/e-text.h | 6 |
9 files changed, 331 insertions, 119 deletions
diff --git a/widgets/e-minicard/e-minicard-label.c b/widgets/e-minicard/e-minicard-label.c index 5b528d6190..3f6a80a890 100644 --- a/widgets/e-minicard/e-minicard-label.c +++ b/widgets/e-minicard/e-minicard-label.c @@ -25,6 +25,7 @@ #include "e-text.h" #include "e-canvas.h" #include "e-util.h" +#include "e-canvas-utils.h" static void e_minicard_label_init (EMinicardLabel *card); static void e_minicard_label_class_init (EMinicardLabelClass *klass); static void e_minicard_label_set_arg (GtkObject *o, GtkArg *arg, guint arg_id); @@ -238,8 +239,6 @@ e_minicard_label_realize (GnomeCanvasItem *item) e_minicard_label->fieldname = gnome_canvas_item_new( group, e_text_get_type(), - "x", (double) 2, - "y", (double) 1, "anchor", GTK_ANCHOR_NW, "clip_width", (double) ( e_minicard_label->width / 2 - 4 ), "clip_height", (double) 1, @@ -248,6 +247,7 @@ e_minicard_label_realize (GnomeCanvasItem *item) "font_gdk", font, "fill_color", "black", NULL ); + e_canvas_item_move_absolute(e_minicard_label->fieldname, 2, 1); if ( e_minicard_label->fieldname_text ) { gnome_canvas_item_set( e_minicard_label->fieldname, @@ -263,8 +263,6 @@ e_minicard_label_realize (GnomeCanvasItem *item) e_minicard_label->field = gnome_canvas_item_new( group, e_text_get_type(), - "x", (double) ( e_minicard_label->width / 2 + 2 ), - "y", (double) 1, "anchor", GTK_ANCHOR_NW, "clip_width", (double) ( ( e_minicard_label->width + 1 ) / 2 - 4 ), "clip_height", (double) 1, @@ -274,6 +272,7 @@ e_minicard_label_realize (GnomeCanvasItem *item) "fill_color", "black", "editable", TRUE, NULL ); + e_canvas_item_move_absolute(e_minicard_label->field, ( e_minicard_label->width / 2 + 2), 1); if ( e_minicard_label->field_text ) { gnome_canvas_item_set( e_minicard_label->field, @@ -443,9 +442,9 @@ update_label( EMinicardLabel *e_minicard_label ) "clip_width", (double) ( e_minicard_label->width / 2 - 4 ), NULL ); gnome_canvas_item_set( e_minicard_label->field, - "x", (double) ( e_minicard_label->width / 2 + 2 ), "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"); @@ -454,9 +453,9 @@ update_label( EMinicardLabel *e_minicard_label ) } - 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 ddbe7ab191..3311e3c9af 100644 --- a/widgets/e-minicard/e-minicard-label.h +++ b/widgets/e-minicard/e-minicard-label.h @@ -52,16 +52,16 @@ typedef struct _EMinicardLabelClass EMinicardLabelClass; struct _EMinicardLabel { - GnomeCanvasGroup parent; - - /* item specific fields */ - double width; - double height; - GnomeCanvasItem *fieldname; - GnomeCanvasItem *field; - GnomeCanvasItem *rect; - char *fieldname_text; - char *field_text; + GnomeCanvasGroup parent; + + /* item specific fields */ + double width; + double height; + GnomeCanvasItem *fieldname; + GnomeCanvasItem *field; + GnomeCanvasItem *rect; + char *fieldname_text; + char *field_text; gboolean has_focus; }; diff --git a/widgets/e-minicard/e-minicard.c b/widgets/e-minicard/e-minicard.c index 805c4e78ff..b8d25f5dc6 100644 --- a/widgets/e-minicard/e-minicard.c +++ b/widgets/e-minicard/e-minicard.c @@ -26,6 +26,7 @@ #include "e-text.h" #include "e-canvas.h" #include "e-util.h" +#include "e-canvas-utils.h" static void e_minicard_init (EMinicard *card); static void e_minicard_class_init (EMinicardClass *klass); static void e_minicard_set_arg (GtkObject *o, GtkArg *arg, guint arg_id); @@ -235,8 +236,6 @@ e_minicard_realize (GnomeCanvasItem *item) e_minicard->header_text = gnome_canvas_item_new( group, e_text_get_type(), - "x", (double) 6, - "y", (double) 6, "anchor", GTK_ANCHOR_NW, "clip_width", (double) ( e_minicard->width - 12 ), "clip", TRUE, @@ -245,6 +244,7 @@ e_minicard_realize (GnomeCanvasItem *item) "fill_color", "black", "text", "Chris Lahey", NULL ); + e_canvas_item_move_absolute(e_minicard->header_text, 6, 6); gtk_signal_connect(GTK_OBJECT(e_minicard->header_text), "resize", @@ -253,13 +253,12 @@ e_minicard_realize (GnomeCanvasItem *item) if ( rand() % 2 ) { new_item = gnome_canvas_item_new( group, e_minicard_label_get_type(), - "x", (double) 2, - "y", e_minicard->height, "width", e_minicard->width - 4, "fieldname", "Full Name:", "field", "Christopher James Lahey", 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", @@ -270,13 +269,12 @@ e_minicard_realize (GnomeCanvasItem *item) if (rand() % 2) { new_item = gnome_canvas_item_new( group, e_minicard_label_get_type(), - "x", (double) 2, - "y", e_minicard->height, "width", e_minicard->width - 4, "fieldname", "Address:", "field", "100 Main St\nHome town, USA", 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", @@ -287,13 +285,12 @@ e_minicard_realize (GnomeCanvasItem *item) if (rand() % 2) { new_item = gnome_canvas_item_new( group, e_minicard_label_get_type(), - "x", (double) 2, - "y", e_minicard->height, "width", e_minicard->width - 4.0, "fieldname", "Email:", "field", "clahey@address.com", 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", @@ -432,9 +429,7 @@ _update_card( EMinicard *e_minicard ) gtk_object_get (GTK_OBJECT(list->data), "height", &text_height, NULL); - gnome_canvas_item_set(GNOME_CANVAS_ITEM(list->data), - "y", (double) e_minicard->height, - NULL); + e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(list->data), 2, e_minicard->height); e_minicard->height += text_height; } e_minicard->height += 2; diff --git a/widgets/e-text/e-text-test.c b/widgets/e-text/e-text-test.c index ae43d41611..41a24db6e8 100644 --- a/widgets/e-text/e-text-test.c +++ b/widgets/e-text/e-text-test.c @@ -8,14 +8,14 @@ #include "e-text.h" #include <gnome.h> -void +static void quit_cb (GtkWidget *widget, gpointer data) { gtk_main_quit (); } -void +static void change_text_cb (GtkEntry *entry, EText *text) { @@ -27,7 +27,7 @@ change_text_cb (GtkEntry *entry, NULL); } -void +static void change_font_cb (GtkEntry *entry, EText *text) { diff --git a/widgets/e-text/e-text.c b/widgets/e-text/e-text.c index daa607007e..d9448fe783 100644 --- a/widgets/e-text/e-text.c +++ b/widgets/e-text/e-text.c @@ -74,6 +74,7 @@ enum { ARG_USE_ELLIPSIS, ARG_ELLIPSIS, ARG_LINE_WRAP, + ARG_BREAK_CHARACTERS, ARG_MAX_LINES }; @@ -245,6 +246,8 @@ e_text_class_init (ETextClass *klass) GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_ELLIPSIS); gtk_object_add_arg_type ("EText::line_wrap", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_LINE_WRAP); + gtk_object_add_arg_type ("EText::break_characters", + 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); @@ -278,8 +281,8 @@ e_text_init (EText *text) text->y = 0.0; text->anchor = GTK_ANCHOR_CENTER; text->justification = GTK_JUSTIFY_LEFT; - text->clip_width = 0.0; - text->clip_height = 0.0; + text->clip_width = 1.0; + text->clip_height = -1.0; text->xofs = 0.0; text->yofs = 0.0; @@ -320,6 +323,7 @@ e_text_init (EText *text) text->default_cursor_shown = TRUE; text->line_wrap = FALSE; + text->break_characters = NULL; text->max_lines = -1; } @@ -420,14 +424,20 @@ get_bounds_item_relative (EText *text, double *px1, double *py1, double *px2, do case GTK_ANCHOR_CENTER: case GTK_ANCHOR_E: y -= text->height / 2; - clip_y -= text->clip_height / 2; + if ( text->clip_height >= 0 ) + clip_y -= text->clip_height / 2; + else + clip_y -= text->height / 2; break; case GTK_ANCHOR_SW: case GTK_ANCHOR_S: case GTK_ANCHOR_SE: y -= text->height; - clip_y -= text->clip_height; + if ( text->clip_height >= 0 ) + clip_y -= text->clip_height; + else + clip_y -= text->height; break; } @@ -438,7 +448,10 @@ get_bounds_item_relative (EText *text, double *px1, double *py1, double *px2, do *px1 = clip_x; *py1 = clip_y; *px2 = clip_x + text->clip_width; - *py2 = clip_y + text->clip_height; + if ( text->clip_height >= 0 ) + *py2 = clip_y + text->clip_height; + else + *py2 = clip_y + text->height; } else { *px1 = x; *py1 = y; @@ -447,6 +460,22 @@ 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) { @@ -456,6 +485,18 @@ get_bounds (EText *text, double *px1, double *py1, double *px2, double *py2) 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; @@ -467,19 +508,10 @@ get_bounds (EText *text, double *px1, double *py1, double *px2, double *py2) gnome_canvas_w2c (item->canvas, wx, wy, &text->clip_cx, &text->clip_cy); text->clip_cwidth = text->clip_width * item->canvas->pixels_per_unit; - text->clip_cheight = text->clip_height * item->canvas->pixels_per_unit; - - /* Calculate text dimensions */ - - old_height = text->height; - - if (text->text && text->font) - text->height = (text->font->ascent + text->font->descent) * text->num_lines; + if ( text->clip_height >= 0 ) + text->clip_cheight = text->clip_height * item->canvas->pixels_per_unit; else - text->height = 0; - - if (old_height != text->height) - gtk_signal_emit_by_name (GTK_OBJECT (text), "resize"); + text->clip_cheight = text->height * item->canvas->pixels_per_unit; /* Anchor text */ @@ -603,6 +635,7 @@ calc_line_widths (EText *text) } } +#define IS_BREAKCHAR(text,c) ((text)->break_characters && strchr ((text)->break_characters, (c))) /* Splits the text of the text item into lines */ static void split_into_lines (EText *text) @@ -647,6 +680,21 @@ split_into_lines (EText *text) laststart = p + 1; lastend = p; } + } else if (text->line_wrap && (IS_BREAKCHAR(text, *p))) { + if ( laststart != lastend + && p != linestart + 1 + && gdk_text_width(text->font, + linestart, + p + 1 - linestart) + > text->clip_width ) { + text->num_lines ++; + linestart = laststart; + laststart = p + 1; + lastend = p + 1; + } else { + laststart = p + 1; + lastend = p + 1; + } } if (*p == '\n') { text->num_lines ++; @@ -703,6 +751,25 @@ split_into_lines (EText *text) len ++; } handled = TRUE; + } else if (text->line_wrap && (IS_BREAKCHAR(text, *p))) { + if ( laststart != lastend + && p != lines->text + 1 + && gdk_text_width(text->font, + lines->text, + p + 1 - lines->text) + > text->clip_width ) { + lines->length = lastend - lines->text; + lines++; + line_num++; + len = p + 1 - laststart; + lines->text = laststart; + laststart = p + 1; + lastend = p + 1; + } else { + laststart = p + 1; + lastend = p + 1; + len ++; + } } if ( line_num >= text->num_lines ) break; @@ -974,6 +1041,16 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) text->line_wrap = GTK_VALUE_BOOL (*arg); text->needs_split_into_lines = 1; break; + + case ARG_BREAK_CHARACTERS: + if ( text->break_characters ) { + g_free(text->break_characters); + text->break_characters = NULL; + } + if ( GTK_VALUE_STRING (*arg) ) + text->break_characters = g_strdup( GTK_VALUE_STRING (*arg) ); + text->needs_split_into_lines = 1; + break; case ARG_MAX_LINES: text->max_lines = GTK_VALUE_INT (*arg); @@ -1090,6 +1167,10 @@ e_text_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) case ARG_LINE_WRAP: GTK_VALUE_BOOL (*arg) = text->line_wrap; break; + + case ARG_BREAK_CHARACTERS: + GTK_VALUE_STRING (*arg) = g_strdup (text->break_characters); + break; case ARG_MAX_LINES: GTK_VALUE_INT (*arg) = text->max_lines; @@ -1124,13 +1205,25 @@ e_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int fla calc_line_widths(text); text->needs_calc_line_widths = 0; text->needs_recalc_bounds = 1; + text->needs_redraw = 1; } - if ( text->needs_recalc_bounds ) { - gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2); + if ( text->needs_recalc_bounds + || (flags & GNOME_CANVAS_UPDATE_AFFINE)) { if (!item->canvas->aa) { set_text_gc_foreground (text); set_stipple (text, text->stipple, TRUE); get_bounds (text, &x1, &y1, &x2, &y2); + if ( item->x1 != x1 || + item->x2 != x2 || + item->y1 != y1 || + item->y2 != y2 ) { + gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2); + item->x1 = x1; + item->y1 = y1; + item->x2 = x2; + item->y2 = y2; + text->needs_redraw = 1; + } } else { /* aa rendering */ for (i = 0; i < 6; i++) @@ -1138,12 +1231,7 @@ e_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int fla get_bounds_item_relative (text, &i_bbox.x0, &i_bbox.y0, &i_bbox.x1, &i_bbox.y1); art_drect_affine_transform (&c_bbox, &i_bbox, affine); } - item->x1 = x1; - item->y1 = y1; - item->x2 = x2; - item->y2 = y2; text->needs_recalc_bounds = 0; - text->needs_redraw = 1; } if ( text->needs_redraw ) { gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2); @@ -1589,12 +1677,16 @@ e_text_point (GnomeCanvasItem *item, double x, double y, if (y1 < text->clip_cy) y1 = text->clip_cy; + + if ( text->clip_width >= 0 ) { + if (x2 > (text->clip_cx + text->clip_width)) + x2 = text->clip_cx + text->clip_width; + } - if (x2 > (text->clip_cx + text->clip_width)) - x2 = text->clip_cx + text->clip_width; - - if (y2 > (text->clip_cy + text->clip_height)) - y2 = text->clip_cy + text->clip_height; + if ( text->clip_height >= 0 ) { + if (y2 > (text->clip_cy + text->clip_height)) + y2 = text->clip_cy + text->clip_height; + } if ((x1 >= x2) || (y1 >= y2)) continue; @@ -1645,7 +1737,9 @@ e_text_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double if (text->clip) { width = text->clip_width; - height = text->clip_height; + if ( text->clip_height >= 0 ) + height = text->clip_height; + else height = text->height; } else { width = text->max_width / item->canvas->pixels_per_unit; height = text->height / item->canvas->pixels_per_unit; @@ -1829,13 +1923,21 @@ _do_tooltip (gpointer data) GtkWidget *label, *vbox; gint x, y, pointer_x, pointer_y, scr_w, scr_h, tip_w, tip_h; int i; + gboolean cut_off; if (text->editing) return FALSE; lines = text->lines; - - if (lines->length <= lines->ellipsis_length) + + cut_off = FALSE; + for ( lines = text->lines, i = 0; i < text->num_lines; lines++, i++ ) { + if (lines->length > lines->ellipsis_length) { + cut_off = TRUE; + break; + } + } + if ( ! cut_off ) return FALSE; scr_w = gdk_screen_width (); @@ -1844,6 +1946,7 @@ _do_tooltip (gpointer data) text->tooltip_window = gtk_window_new (GTK_WINDOW_POPUP); vbox = gtk_vbox_new (TRUE, 0); + lines = text->lines; for (i = 0; i < text->num_lines; i++) { gchar *linetext; @@ -1944,13 +2047,13 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event) break; case GDK_BUTTON_PRESS: /* Fall Through */ case GDK_BUTTON_RELEASE: - text->tooltip_count --; - if ( text->tooltip_count == 0 && text->clip) { + if (text->tooltip_timeout) { gtk_timeout_remove (text->tooltip_timeout); - if (text->tooltip_window) { - gtk_widget_destroy (text->tooltip_window); - text->tooltip_window = NULL; - } + text->tooltip_timeout = 0; + } + if (text->tooltip_window) { + gtk_widget_destroy (text->tooltip_window); + text->tooltip_window = NULL; } if ((!text->editing) && text->editable @@ -2005,10 +2108,9 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event) } break; case GDK_ENTER_NOTIFY: - if ( text->tooltip_count == 0 && text->clip) { + if ( text->tooltip_count == 0 && text->clip) text->tooltip_timeout = gtk_timeout_add (1000, _do_tooltip, text); - text->tooltip_count ++; - } + text->tooltip_count ++; text->pointer_in = TRUE; if (text->editing) { if ( text->default_cursor_shown ) { @@ -2020,7 +2122,10 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event) case GDK_LEAVE_NOTIFY: text->tooltip_count --; if ( text->tooltip_count == 0 && text->clip) { - gtk_timeout_remove (text->tooltip_timeout); + if ( text->tooltip_timeout ) { + gtk_timeout_remove (text->tooltip_timeout); + text->tooltip_timeout = 0; + } if (text->tooltip_window) { gtk_widget_destroy (text->tooltip_window); text->tooltip_window = NULL; diff --git a/widgets/e-text/e-text.h b/widgets/e-text/e-text.h index 710d6d1e64..3e1dcb5f0e 100644 --- a/widgets/e-text/e-text.h +++ b/widgets/e-text/e-text.h @@ -64,7 +64,8 @@ BEGIN_GNOME_DECLS * use_ellipsis boolean RW Whether to use ellipsises if text gets cut off. Meaningless if clip == false. * ellipsis string RW The characters to use as ellipsis. NULL = "...". * line_wrap boolean RW Line wrap when not editing. - * max_line_wrap int RW Number of lines possible when doing line wrap. + * break_characters string RW List of characters to optionally break on. + * max_lines int RW Number of lines possible when doing line wrap. */ #define E_TYPE_TEXT (e_text_get_type ()) @@ -168,6 +169,7 @@ struct _EText { guint default_cursor_shown : 1; /* Is the default cursor currently shown? */ guint line_wrap : 1; /* Do line wrap */ + gchar *break_characters; /* Characters to optionally break after */ gint max_lines; /* Max number of lines (-1 = infinite) */ @@ -182,6 +184,8 @@ struct _EText { guint needs_recalc_bounds : 1; /* Need recalc_bounds */ 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/text/e-text-test.c b/widgets/text/e-text-test.c index ae43d41611..41a24db6e8 100644 --- a/widgets/text/e-text-test.c +++ b/widgets/text/e-text-test.c @@ -8,14 +8,14 @@ #include "e-text.h" #include <gnome.h> -void +static void quit_cb (GtkWidget *widget, gpointer data) { gtk_main_quit (); } -void +static void change_text_cb (GtkEntry *entry, EText *text) { @@ -27,7 +27,7 @@ change_text_cb (GtkEntry *entry, NULL); } -void +static void change_font_cb (GtkEntry *entry, EText *text) { diff --git a/widgets/text/e-text.c b/widgets/text/e-text.c index daa607007e..d9448fe783 100644 --- a/widgets/text/e-text.c +++ b/widgets/text/e-text.c @@ -74,6 +74,7 @@ enum { ARG_USE_ELLIPSIS, ARG_ELLIPSIS, ARG_LINE_WRAP, + ARG_BREAK_CHARACTERS, ARG_MAX_LINES }; @@ -245,6 +246,8 @@ e_text_class_init (ETextClass *klass) GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_ELLIPSIS); gtk_object_add_arg_type ("EText::line_wrap", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_LINE_WRAP); + gtk_object_add_arg_type ("EText::break_characters", + 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); @@ -278,8 +281,8 @@ e_text_init (EText *text) text->y = 0.0; text->anchor = GTK_ANCHOR_CENTER; text->justification = GTK_JUSTIFY_LEFT; - text->clip_width = 0.0; - text->clip_height = 0.0; + text->clip_width = 1.0; + text->clip_height = -1.0; text->xofs = 0.0; text->yofs = 0.0; @@ -320,6 +323,7 @@ e_text_init (EText *text) text->default_cursor_shown = TRUE; text->line_wrap = FALSE; + text->break_characters = NULL; text->max_lines = -1; } @@ -420,14 +424,20 @@ get_bounds_item_relative (EText *text, double *px1, double *py1, double *px2, do case GTK_ANCHOR_CENTER: case GTK_ANCHOR_E: y -= text->height / 2; - clip_y -= text->clip_height / 2; + if ( text->clip_height >= 0 ) + clip_y -= text->clip_height / 2; + else + clip_y -= text->height / 2; break; case GTK_ANCHOR_SW: case GTK_ANCHOR_S: case GTK_ANCHOR_SE: y -= text->height; - clip_y -= text->clip_height; + if ( text->clip_height >= 0 ) + clip_y -= text->clip_height; + else + clip_y -= text->height; break; } @@ -438,7 +448,10 @@ get_bounds_item_relative (EText *text, double *px1, double *py1, double *px2, do *px1 = clip_x; *py1 = clip_y; *px2 = clip_x + text->clip_width; - *py2 = clip_y + text->clip_height; + if ( text->clip_height >= 0 ) + *py2 = clip_y + text->clip_height; + else + *py2 = clip_y + text->height; } else { *px1 = x; *py1 = y; @@ -447,6 +460,22 @@ 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) { @@ -456,6 +485,18 @@ get_bounds (EText *text, double *px1, double *py1, double *px2, double *py2) 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; @@ -467,19 +508,10 @@ get_bounds (EText *text, double *px1, double *py1, double *px2, double *py2) gnome_canvas_w2c (item->canvas, wx, wy, &text->clip_cx, &text->clip_cy); text->clip_cwidth = text->clip_width * item->canvas->pixels_per_unit; - text->clip_cheight = text->clip_height * item->canvas->pixels_per_unit; - - /* Calculate text dimensions */ - - old_height = text->height; - - if (text->text && text->font) - text->height = (text->font->ascent + text->font->descent) * text->num_lines; + if ( text->clip_height >= 0 ) + text->clip_cheight = text->clip_height * item->canvas->pixels_per_unit; else - text->height = 0; - - if (old_height != text->height) - gtk_signal_emit_by_name (GTK_OBJECT (text), "resize"); + text->clip_cheight = text->height * item->canvas->pixels_per_unit; /* Anchor text */ @@ -603,6 +635,7 @@ calc_line_widths (EText *text) } } +#define IS_BREAKCHAR(text,c) ((text)->break_characters && strchr ((text)->break_characters, (c))) /* Splits the text of the text item into lines */ static void split_into_lines (EText *text) @@ -647,6 +680,21 @@ split_into_lines (EText *text) laststart = p + 1; lastend = p; } + } else if (text->line_wrap && (IS_BREAKCHAR(text, *p))) { + if ( laststart != lastend + && p != linestart + 1 + && gdk_text_width(text->font, + linestart, + p + 1 - linestart) + > text->clip_width ) { + text->num_lines ++; + linestart = laststart; + laststart = p + 1; + lastend = p + 1; + } else { + laststart = p + 1; + lastend = p + 1; + } } if (*p == '\n') { text->num_lines ++; @@ -703,6 +751,25 @@ split_into_lines (EText *text) len ++; } handled = TRUE; + } else if (text->line_wrap && (IS_BREAKCHAR(text, *p))) { + if ( laststart != lastend + && p != lines->text + 1 + && gdk_text_width(text->font, + lines->text, + p + 1 - lines->text) + > text->clip_width ) { + lines->length = lastend - lines->text; + lines++; + line_num++; + len = p + 1 - laststart; + lines->text = laststart; + laststart = p + 1; + lastend = p + 1; + } else { + laststart = p + 1; + lastend = p + 1; + len ++; + } } if ( line_num >= text->num_lines ) break; @@ -974,6 +1041,16 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) text->line_wrap = GTK_VALUE_BOOL (*arg); text->needs_split_into_lines = 1; break; + + case ARG_BREAK_CHARACTERS: + if ( text->break_characters ) { + g_free(text->break_characters); + text->break_characters = NULL; + } + if ( GTK_VALUE_STRING (*arg) ) + text->break_characters = g_strdup( GTK_VALUE_STRING (*arg) ); + text->needs_split_into_lines = 1; + break; case ARG_MAX_LINES: text->max_lines = GTK_VALUE_INT (*arg); @@ -1090,6 +1167,10 @@ e_text_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) case ARG_LINE_WRAP: GTK_VALUE_BOOL (*arg) = text->line_wrap; break; + + case ARG_BREAK_CHARACTERS: + GTK_VALUE_STRING (*arg) = g_strdup (text->break_characters); + break; case ARG_MAX_LINES: GTK_VALUE_INT (*arg) = text->max_lines; @@ -1124,13 +1205,25 @@ e_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int fla calc_line_widths(text); text->needs_calc_line_widths = 0; text->needs_recalc_bounds = 1; + text->needs_redraw = 1; } - if ( text->needs_recalc_bounds ) { - gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2); + if ( text->needs_recalc_bounds + || (flags & GNOME_CANVAS_UPDATE_AFFINE)) { if (!item->canvas->aa) { set_text_gc_foreground (text); set_stipple (text, text->stipple, TRUE); get_bounds (text, &x1, &y1, &x2, &y2); + if ( item->x1 != x1 || + item->x2 != x2 || + item->y1 != y1 || + item->y2 != y2 ) { + gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2); + item->x1 = x1; + item->y1 = y1; + item->x2 = x2; + item->y2 = y2; + text->needs_redraw = 1; + } } else { /* aa rendering */ for (i = 0; i < 6; i++) @@ -1138,12 +1231,7 @@ e_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int fla get_bounds_item_relative (text, &i_bbox.x0, &i_bbox.y0, &i_bbox.x1, &i_bbox.y1); art_drect_affine_transform (&c_bbox, &i_bbox, affine); } - item->x1 = x1; - item->y1 = y1; - item->x2 = x2; - item->y2 = y2; text->needs_recalc_bounds = 0; - text->needs_redraw = 1; } if ( text->needs_redraw ) { gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2); @@ -1589,12 +1677,16 @@ e_text_point (GnomeCanvasItem *item, double x, double y, if (y1 < text->clip_cy) y1 = text->clip_cy; + + if ( text->clip_width >= 0 ) { + if (x2 > (text->clip_cx + text->clip_width)) + x2 = text->clip_cx + text->clip_width; + } - if (x2 > (text->clip_cx + text->clip_width)) - x2 = text->clip_cx + text->clip_width; - - if (y2 > (text->clip_cy + text->clip_height)) - y2 = text->clip_cy + text->clip_height; + if ( text->clip_height >= 0 ) { + if (y2 > (text->clip_cy + text->clip_height)) + y2 = text->clip_cy + text->clip_height; + } if ((x1 >= x2) || (y1 >= y2)) continue; @@ -1645,7 +1737,9 @@ e_text_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double if (text->clip) { width = text->clip_width; - height = text->clip_height; + if ( text->clip_height >= 0 ) + height = text->clip_height; + else height = text->height; } else { width = text->max_width / item->canvas->pixels_per_unit; height = text->height / item->canvas->pixels_per_unit; @@ -1829,13 +1923,21 @@ _do_tooltip (gpointer data) GtkWidget *label, *vbox; gint x, y, pointer_x, pointer_y, scr_w, scr_h, tip_w, tip_h; int i; + gboolean cut_off; if (text->editing) return FALSE; lines = text->lines; - - if (lines->length <= lines->ellipsis_length) + + cut_off = FALSE; + for ( lines = text->lines, i = 0; i < text->num_lines; lines++, i++ ) { + if (lines->length > lines->ellipsis_length) { + cut_off = TRUE; + break; + } + } + if ( ! cut_off ) return FALSE; scr_w = gdk_screen_width (); @@ -1844,6 +1946,7 @@ _do_tooltip (gpointer data) text->tooltip_window = gtk_window_new (GTK_WINDOW_POPUP); vbox = gtk_vbox_new (TRUE, 0); + lines = text->lines; for (i = 0; i < text->num_lines; i++) { gchar *linetext; @@ -1944,13 +2047,13 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event) break; case GDK_BUTTON_PRESS: /* Fall Through */ case GDK_BUTTON_RELEASE: - text->tooltip_count --; - if ( text->tooltip_count == 0 && text->clip) { + if (text->tooltip_timeout) { gtk_timeout_remove (text->tooltip_timeout); - if (text->tooltip_window) { - gtk_widget_destroy (text->tooltip_window); - text->tooltip_window = NULL; - } + text->tooltip_timeout = 0; + } + if (text->tooltip_window) { + gtk_widget_destroy (text->tooltip_window); + text->tooltip_window = NULL; } if ((!text->editing) && text->editable @@ -2005,10 +2108,9 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event) } break; case GDK_ENTER_NOTIFY: - if ( text->tooltip_count == 0 && text->clip) { + if ( text->tooltip_count == 0 && text->clip) text->tooltip_timeout = gtk_timeout_add (1000, _do_tooltip, text); - text->tooltip_count ++; - } + text->tooltip_count ++; text->pointer_in = TRUE; if (text->editing) { if ( text->default_cursor_shown ) { @@ -2020,7 +2122,10 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event) case GDK_LEAVE_NOTIFY: text->tooltip_count --; if ( text->tooltip_count == 0 && text->clip) { - gtk_timeout_remove (text->tooltip_timeout); + if ( text->tooltip_timeout ) { + gtk_timeout_remove (text->tooltip_timeout); + text->tooltip_timeout = 0; + } if (text->tooltip_window) { gtk_widget_destroy (text->tooltip_window); text->tooltip_window = NULL; diff --git a/widgets/text/e-text.h b/widgets/text/e-text.h index 710d6d1e64..3e1dcb5f0e 100644 --- a/widgets/text/e-text.h +++ b/widgets/text/e-text.h @@ -64,7 +64,8 @@ BEGIN_GNOME_DECLS * use_ellipsis boolean RW Whether to use ellipsises if text gets cut off. Meaningless if clip == false. * ellipsis string RW The characters to use as ellipsis. NULL = "...". * line_wrap boolean RW Line wrap when not editing. - * max_line_wrap int RW Number of lines possible when doing line wrap. + * break_characters string RW List of characters to optionally break on. + * max_lines int RW Number of lines possible when doing line wrap. */ #define E_TYPE_TEXT (e_text_get_type ()) @@ -168,6 +169,7 @@ struct _EText { guint default_cursor_shown : 1; /* Is the default cursor currently shown? */ guint line_wrap : 1; /* Do line wrap */ + gchar *break_characters; /* Characters to optionally break after */ gint max_lines; /* Max number of lines (-1 = infinite) */ @@ -182,6 +184,8 @@ struct _EText { guint needs_recalc_bounds : 1; /* Need recalc_bounds */ guint needs_calc_line_widths : 1; /* Needs calc_line_widths */ guint needs_split_into_lines : 1; /* Needs split_into_lines */ + + gint idle; }; struct _ETextClass { |