aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/e-text/e-text.c
diff options
context:
space:
mode:
authorChristopher James Lahey <clahey@helixcode.com>2000-03-08 09:41:47 +0800
committerChris Lahey <clahey@src.gnome.org>2000-03-08 09:41:47 +0800
commit6f357b4c2d22d66d81be5ec3f0276ac3393805a1 (patch)
treef8c66838af485a217260dfb3c2e36dc48504af4a /widgets/e-text/e-text.c
parent0bfae7d16b83458d64b0957fd5e88bc54a131b2a (diff)
downloadgsoc2013-evolution-6f357b4c2d22d66d81be5ec3f0276ac3393805a1.tar.gz
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/e-text/e-text.c')
-rw-r--r--widgets/e-text/e-text.c189
1 files changed, 147 insertions, 42 deletions
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;