aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
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
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')
-rw-r--r--widgets/e-minicard/e-minicard-label.c11
-rw-r--r--widgets/e-minicard/e-minicard-label.h20
-rw-r--r--widgets/e-minicard/e-minicard.c17
-rw-r--r--widgets/e-text/e-text-test.c6
-rw-r--r--widgets/e-text/e-text.c189
-rw-r--r--widgets/e-text/e-text.h6
-rw-r--r--widgets/text/e-text-test.c6
-rw-r--r--widgets/text/e-text.c189
-rw-r--r--widgets/text/e-text.h6
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 {