diff options
author | Christopher James Lahey <clahey@helixcode.com> | 2000-03-08 09:41:47 +0800 |
---|---|---|
committer | Chris Lahey <clahey@src.gnome.org> | 2000-03-08 09:41:47 +0800 |
commit | 6f357b4c2d22d66d81be5ec3f0276ac3393805a1 (patch) | |
tree | f8c66838af485a217260dfb3c2e36dc48504af4a /widgets | |
parent | 0bfae7d16b83458d64b0957fd5e88bc54a131b2a (diff) | |
download | gsoc2013-evolution-6f357b4c2d22d66d81be5ec3f0276ac3393805a1.tar gsoc2013-evolution-6f357b4c2d22d66d81be5ec3f0276ac3393805a1.tar.gz gsoc2013-evolution-6f357b4c2d22d66d81be5ec3f0276ac3393805a1.tar.bz2 gsoc2013-evolution-6f357b4c2d22d66d81be5ec3f0276ac3393805a1.tar.lz gsoc2013-evolution-6f357b4c2d22d66d81be5ec3f0276ac3393805a1.tar.xz gsoc2013-evolution-6f357b4c2d22d66d81be5ec3f0276ac3393805a1.tar.zst gsoc2013-evolution-6f357b4c2d22d66d81be5ec3f0276ac3393805a1.zip |
Added a "break_characters" argument. It lets you define a set of
2000-03-07 Christopher James Lahey <clahey@helixcode.com>
* widgets/e-text/e-text.c, widgets/e-text/e-text.h: Added a
"break_characters" argument. It lets you define a set of
characters which should cause optional linebreaks to occur. Made
setting the "clip_height" argument to -1 mean no height clipping.
Moved calling the "resize" signal into an idle handler to avoid
reentering the canvas update loop. Made EText recalc bounds if
the affine has changed. Fixed up tooltip_count (this counts the
number of ENTER and LEAVE events.)
* widgets/e-text/e-text-test.c: Got rid of a few warnings.
* widgets/e-minicard/e-minicard-label.h: Reindent a few lines.
* widgets/e-minicard/e-minicard.c,
widgets/e-minicard/e-minicard-label.c: Switch from using "x" and
"y" to set the children's position to using
e_canvas_item_move_absolute.
svn path=/trunk/; revision=2079
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 { |