2 * GooCanvas. Copyright (C) 2005 Damon Chaplin.
3 * Released under the GNU LGPL license. See COPYING for details.
5 * goocanvastext.c - text item.
9 * SECTION:goocanvastext
10 * @Title: GooCanvasText
11 * @Short_Description: a text item.
13 * GooCanvasText represents a text item.
15 * It is a subclass of #GooCanvasItemSimple and so inherits all of the style
16 * properties such as "fill-color".
18 * It also implements the #GooCanvasItem interface, so you can use the
19 * #GooCanvasItem functions such as goo_canvas_item_raise() and
20 * goo_canvas_item_rotate().
22 * The #GooCanvasText:width and #GooCanvasText:height properties specify the
23 * area of the item. If it exceeds that area because there is too much text,
24 * it is clipped. The properties can be set to -1 to disable clipping.
26 * To create a #GooCanvasText use goo_canvas_text_new().
28 * To get or set the properties of an existing #GooCanvasText, use
29 * g_object_get() and g_object_set().
32 #include <glib/gi18n-lib.h>
34 #include "goocanvastext.h"
35 #include "goocanvas.h"
37 typedef struct _GooCanvasTextPrivate GooCanvasTextPrivate
;
38 struct _GooCanvasTextPrivate
{
42 #define GOO_CANVAS_TEXT_GET_PRIVATE(text) \
43 (G_TYPE_INSTANCE_GET_PRIVATE ((text), GOO_TYPE_CANVAS_TEXT, GooCanvasTextPrivate))
44 #define GOO_CANVAS_TEXT_MODEL_GET_PRIVATE(text) \
45 (G_TYPE_INSTANCE_GET_PRIVATE ((text), GOO_TYPE_CANVAS_TEXT_MODEL, GooCanvasTextPrivate))
63 goo_canvas_text_create_layout (GooCanvasItemSimpleData
*simple_data
,
64 GooCanvasTextData
*text_data
,
67 GooCanvasBounds
*bounds
,
68 gdouble
*origin_x_return
,
69 gdouble
*origin_y_return
);
71 static void goo_canvas_text_finalize (GObject
*object
);
72 static void canvas_item_interface_init (GooCanvasItemIface
*iface
);
73 static void goo_canvas_text_get_property (GObject
*object
,
77 static void goo_canvas_text_set_property (GObject
*object
,
82 G_DEFINE_TYPE_WITH_CODE (GooCanvasText
, goo_canvas_text
,
83 GOO_TYPE_CANVAS_ITEM_SIMPLE
,
84 G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM
,
85 canvas_item_interface_init
))
89 goo_canvas_text_install_common_properties (GObjectClass
*gobject_class
)
92 g_object_class_install_property (gobject_class
, PROP_TEXT
,
93 g_param_spec_string ("text",
95 _("The text to display"),
99 g_object_class_install_property (gobject_class
, PROP_USE_MARKUP
,
100 g_param_spec_boolean ("use-markup",
102 _("Whether to parse PangoMarkup in the text, to support different styles"),
106 g_object_class_install_property (gobject_class
, PROP_ELLIPSIZE
,
107 g_param_spec_enum ("ellipsize",
109 _("The preferred place to ellipsize the string, if the label does not have enough room to display the entire string"),
110 PANGO_TYPE_ELLIPSIZE_MODE
,
111 PANGO_ELLIPSIZE_NONE
,
114 g_object_class_install_property (gobject_class
, PROP_WRAP
,
115 g_param_spec_enum ("wrap",
117 _("The preferred method of wrapping the string if a width has been set"),
118 PANGO_TYPE_WRAP_MODE
,
123 g_object_class_install_property (gobject_class
, PROP_X
,
124 g_param_spec_double ("x",
126 _("The x coordinate of the text"),
131 g_object_class_install_property (gobject_class
, PROP_Y
,
132 g_param_spec_double ("y",
134 _("The y coordinate of the text"),
139 g_object_class_install_property (gobject_class
, PROP_WIDTH
,
140 g_param_spec_double ("width",
142 _("The width to use to layout the text"),
147 g_object_class_install_property (gobject_class
, PROP_HEIGHT
,
148 g_param_spec_double ("height",
150 _("The height to use to layout the text, or -1 to use the natural height"),
156 g_object_class_install_property (gobject_class
, PROP_ANCHOR
,
157 g_param_spec_enum ("anchor",
159 _("How to position the text relative to the given x and y coordinates"),
160 GTK_TYPE_ANCHOR_TYPE
,
164 g_object_class_install_property (gobject_class
, PROP_ALIGN
,
165 g_param_spec_enum ("alignment",
167 _("How to align the text"),
168 PANGO_TYPE_ALIGNMENT
,
175 goo_canvas_text_init (GooCanvasText
*text
)
177 GooCanvasTextPrivate
*priv
= GOO_CANVAS_TEXT_GET_PRIVATE (text
);
179 text
->text_data
= g_slice_new0 (GooCanvasTextData
);
180 text
->text_data
->width
= -1.0;
181 text
->text_data
->anchor
= GTK_ANCHOR_NW
;
182 text
->text_data
->ellipsize
= PANGO_ELLIPSIZE_NONE
;
183 text
->text_data
->wrap
= PANGO_WRAP_WORD
;
185 text
->layout_width
= -1.0;
192 * goo_canvas_text_new:
193 * @parent: the parent item, or %NULL. If a parent is specified, it will assume
194 * ownership of the item, and the item will automatically be freed when it is
195 * removed from the parent. Otherwise call g_object_unref() to free it.
196 * @string: the text to display.
197 * @x: the x coordinate of the text.
198 * @y: the y coordinate of the text.
199 * @width: the width of the text item, or -1 for unlimited width.
200 * @anchor: the position of the text relative to the given @x and @y
201 * coordinates. For example an anchor of %GDK_ANCHOR_NW will result in the
202 * top-left of the text being placed at the given @x and @y coordinates.
203 * An anchor of %GDK_ANCHOR_CENTER will result in the center of the text being
204 * placed at the @x and @y coordinates.
205 * @...: optional pairs of property names and values, and a terminating %NULL.
207 * Creates a new text item.
211 * Here's an example showing how to create a text item with the bottom right
212 * of the text box placed at (500,500):
214 * <informalexample><programlisting>
215 * GooCanvasItem *text = goo_canvas_text_new (mygroup, "Hello World", 500.0, 500.0, 200.0, GTK_ANCHOR_SE,
216 * "fill-color", "blue",
218 * </programlisting></informalexample>
220 * Returns: a new text item.
223 goo_canvas_text_new (GooCanvasItem
*parent
,
228 GtkAnchorType anchor
,
233 GooCanvasTextData
*text_data
;
234 const char *first_property
;
237 item
= g_object_new (GOO_TYPE_CANVAS_TEXT
, NULL
);
238 text
= (GooCanvasText
*) item
;
240 text_data
= text
->text_data
;
241 text_data
->text
= g_strdup (string
);
244 text_data
->width
= width
;
245 text_data
->anchor
= anchor
;
247 va_start (var_args
, anchor
);
248 first_property
= va_arg (var_args
, char*);
250 g_object_set_valist ((GObject
*) item
, first_property
, var_args
);
255 goo_canvas_item_add_child (parent
, item
, -1);
256 g_object_unref (item
);
264 goo_canvas_text_finalize (GObject
*object
)
266 GooCanvasItemSimple
*simple
= (GooCanvasItemSimple
*) object
;
267 GooCanvasText
*text
= (GooCanvasText
*) object
;
269 /* Free our data if we didn't have a model. (If we had a model it would
270 have been reset in dispose() and simple_data will be NULL.) */
271 if (simple
->simple_data
)
273 g_free (text
->text_data
->text
);
274 g_slice_free (GooCanvasTextData
, text
->text_data
);
276 text
->text_data
= NULL
;
278 G_OBJECT_CLASS (goo_canvas_text_parent_class
)->finalize (object
);
282 /* Gets the private data to use, from the model or from the item itself. */
283 static GooCanvasTextPrivate
*
284 goo_canvas_text_get_private (GooCanvasText
*text
)
286 GooCanvasItemSimple
*simple
= (GooCanvasItemSimple
*) text
;
289 return GOO_CANVAS_TEXT_MODEL_GET_PRIVATE (simple
->model
);
291 return GOO_CANVAS_TEXT_GET_PRIVATE (text
);
296 goo_canvas_text_get_common_property (GObject
*object
,
297 GooCanvasTextData
*text_data
,
298 GooCanvasTextPrivate
*priv
,
306 g_value_set_double (value
, text_data
->x
);
309 g_value_set_double (value
, text_data
->y
);
312 g_value_set_double (value
, text_data
->width
);
315 g_value_set_double (value
, priv
->height
);
318 g_value_set_string (value
, text_data
->text
);
320 case PROP_USE_MARKUP
:
321 g_value_set_boolean (value
, text_data
->use_markup
);
324 g_value_set_enum (value
, text_data
->ellipsize
);
327 g_value_set_enum (value
, text_data
->wrap
);
330 g_value_set_enum (value
, text_data
->anchor
);
333 g_value_set_enum (value
, text_data
->alignment
);
336 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
343 goo_canvas_text_get_property (GObject
*object
,
348 GooCanvasText
*text
= (GooCanvasText
*) object
;
349 GooCanvasTextPrivate
*priv
= goo_canvas_text_get_private (text
);
351 goo_canvas_text_get_common_property (object
, text
->text_data
, priv
,
352 prop_id
, value
, pspec
);
357 goo_canvas_text_set_common_property (GObject
*object
,
358 GooCanvasTextData
*text_data
,
359 GooCanvasTextPrivate
*priv
,
367 text_data
->x
= g_value_get_double (value
);
370 text_data
->y
= g_value_get_double (value
);
373 text_data
->width
= g_value_get_double (value
);
376 priv
->height
= g_value_get_double (value
);
379 g_free (text_data
->text
);
380 text_data
->text
= g_value_dup_string (value
);
382 case PROP_USE_MARKUP
:
383 text_data
->use_markup
= g_value_get_boolean (value
);
386 text_data
->ellipsize
= g_value_get_enum (value
);
389 text_data
->wrap
= g_value_get_enum (value
);
392 text_data
->anchor
= g_value_get_enum (value
);
395 text_data
->alignment
= g_value_get_enum (value
);
398 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
405 goo_canvas_text_set_property (GObject
*object
,
410 GooCanvasItemSimple
*simple
= (GooCanvasItemSimple
*) object
;
411 GooCanvasText
*text
= (GooCanvasText
*) object
;
412 GooCanvasTextPrivate
*priv
= goo_canvas_text_get_private (text
);
416 g_warning ("Can't set property of a canvas item with a model - set the model property instead");
420 goo_canvas_text_set_common_property (object
, text
->text_data
, priv
, prop_id
,
422 goo_canvas_item_simple_changed (simple
, TRUE
);
427 goo_canvas_text_create_layout (GooCanvasItemSimpleData
*simple_data
,
428 GooCanvasTextData
*text_data
,
429 gdouble layout_width
,
431 GooCanvasBounds
*bounds
,
432 gdouble
*origin_x_return
,
433 gdouble
*origin_y_return
)
435 GooCanvasStyle
*style
= simple_data
->style
;
438 PangoContext
*context
;
439 PangoRectangle ink_rect
, logical_rect
;
440 double logical_width
, logical_height
, align_width
, origin_x
, origin_y
;
442 double x1_extension
, x2_extension
, y1_extension
, y2_extension
;
443 cairo_font_options_t
*font_options
;
444 cairo_hint_metrics_t hint_metrics
= CAIRO_HINT_METRICS_OFF
;
446 string
= text_data
->text
? text_data
->text
: "";
448 layout
= pango_cairo_create_layout (cr
);
449 context
= pango_layout_get_context (layout
);
451 if (layout_width
> 0)
452 pango_layout_set_width (layout
, (double) layout_width
* PANGO_SCALE
);
454 if (text_data
->use_markup
)
455 pango_layout_set_markup (layout
, string
, -1);
457 pango_layout_set_text (layout
, string
, -1);
459 svalue
= goo_canvas_style_get_property (style
,
460 goo_canvas_style_font_desc_id
);
462 pango_layout_set_font_description (layout
, svalue
->data
[0].v_pointer
);
464 svalue
= goo_canvas_style_get_property (style
,
465 goo_canvas_style_hint_metrics_id
);
467 hint_metrics
= svalue
->data
[0].v_long
;
469 font_options
= cairo_font_options_create ();
470 cairo_font_options_set_hint_metrics (font_options
, hint_metrics
);
471 pango_cairo_context_set_font_options (context
, font_options
);
472 cairo_font_options_destroy (font_options
);
474 if (text_data
->alignment
!= PANGO_ALIGN_LEFT
)
475 pango_layout_set_alignment (layout
, text_data
->alignment
);
477 pango_layout_set_ellipsize (layout
, text_data
->ellipsize
);
479 pango_layout_set_wrap (layout
, text_data
->wrap
);
483 /* Get size of the text, so we can position it according to anchor. */
484 pango_layout_get_extents (layout
, &ink_rect
, &logical_rect
);
486 logical_width
= (double) logical_rect
.width
/ PANGO_SCALE
;
487 logical_height
= (double) logical_rect
.height
/ PANGO_SCALE
;
489 /* If the text width has been set, that width is used to do the alignment
490 positioning. Otherwise the actual width is used. */
491 if (text_data
->width
> 0)
492 align_width
= text_data
->width
;
494 align_width
= logical_width
;
496 /* Now calculate the origin of the text, i.e. where we will tell Pango
498 origin_x
= text_data
->x
;
499 origin_y
= text_data
->y
;
501 switch (text_data
->anchor
)
504 case GTK_ANCHOR_CENTER
:
506 origin_x
-= align_width
/ 2.0;
511 origin_x
-= align_width
;
517 switch (text_data
->anchor
)
520 case GTK_ANCHOR_CENTER
:
522 origin_y
-= logical_height
/ 2.0;
527 origin_y
-= logical_height
;
533 /* Return the origin of the text if required. */
535 *origin_x_return
= origin_x
;
537 *origin_y_return
= origin_y
;
539 /* Now calculate the logical bounds. */
540 bounds
->x1
= origin_x
;
541 bounds
->y1
= origin_y
;
543 if (text_data
->width
> 0)
545 /* If the text width has been set, and the alignment isn't
546 PANGO_ALIGN_LEFT, we need to adjust for the difference between
547 the actual width of the text and the width that was used for
549 switch (text_data
->alignment
)
551 case PANGO_ALIGN_CENTER
:
552 bounds
->x1
+= (align_width
- logical_width
) / 2.0;
554 case PANGO_ALIGN_RIGHT
:
555 bounds
->x1
+= align_width
- logical_width
;
562 bounds
->x2
= bounds
->x1
+ logical_width
;
563 bounds
->y2
= bounds
->y1
+ logical_height
;
565 /* Now adjust it to take into account the ink bounds. Calculate how far
566 the ink rect extends outside each edge of the logical rect and adjust
567 the bounds as necessary. */
568 x1_extension
= logical_rect
.x
- ink_rect
.x
;
569 if (x1_extension
> 0)
570 bounds
->x1
-= x1_extension
/ PANGO_SCALE
;
572 x2_extension
= (ink_rect
.x
+ ink_rect
.width
)
573 - (logical_rect
.x
+ logical_rect
.width
);
574 if (x2_extension
> 0)
575 bounds
->x2
+= x2_extension
/ PANGO_SCALE
;
577 y1_extension
= logical_rect
.y
- ink_rect
.y
;
578 if (y1_extension
> 0)
579 bounds
->y1
-= y1_extension
/ PANGO_SCALE
;
581 y2_extension
= (ink_rect
.y
+ ink_rect
.height
)
582 - (logical_rect
.y
+ logical_rect
.height
);
583 if (y2_extension
> 0)
584 bounds
->y2
+= y2_extension
/ PANGO_SCALE
;
592 goo_canvas_text_update (GooCanvasItemSimple
*simple
,
595 GooCanvasText
*text
= (GooCanvasText
*) simple
;
596 GooCanvasTextPrivate
*priv
= goo_canvas_text_get_private (text
);
599 /* Initialize the layout width to the text item's specified width property.
600 It may get changed later in get_requested_height() according to the
601 layout container and settings. */
602 text
->layout_width
= text
->text_data
->width
;
604 /* Compute the new bounds. */
605 layout
= goo_canvas_text_create_layout (simple
->simple_data
, text
->text_data
,
606 text
->layout_width
, cr
,
607 &simple
->bounds
, NULL
, NULL
);
608 g_object_unref (layout
);
610 /* If the height is set, use that. */
611 if (priv
->height
> 0.0)
612 simple
->bounds
.y2
= simple
->bounds
.y1
+ priv
->height
;
617 goo_canvas_text_is_unpainted (GooCanvasStyle
*style
)
621 value
= goo_canvas_style_get_property (style
,
622 goo_canvas_style_fill_pattern_id
);
624 /* We only return TRUE if the value is explicitly set to NULL. */
625 if (value
&& !value
->data
[0].v_pointer
)
632 goo_canvas_text_is_item_at (GooCanvasItemSimple
*simple
,
636 gboolean is_pointer_event
)
638 GooCanvasItemSimpleData
*simple_data
= simple
->simple_data
;
639 GooCanvasText
*text
= (GooCanvasText
*) simple
;
640 GooCanvasTextPrivate
*priv
= goo_canvas_text_get_private (text
);
642 GooCanvasBounds bounds
;
643 PangoLayoutIter
*iter
;
644 PangoRectangle ink_rect
, log_rect
;
645 int px
, py
, x1
, y1
, x2
, y2
;
646 int log_x2
, ink_x2
, log_y2
, ink_y2
;
647 gdouble origin_x
, origin_y
;
648 gboolean in_item
= FALSE
;
650 /* If there is no text just return. */
651 if (!text
->text_data
->text
|| !text
->text_data
->text
[0])
655 && simple_data
->pointer_events
& GOO_CANVAS_EVENTS_PAINTED_MASK
656 && goo_canvas_text_is_unpainted (simple_data
->style
))
659 /* Check if the point is outside the clipped height. */
660 if (priv
->height
> 0.0 && y
> priv
->height
)
663 layout
= goo_canvas_text_create_layout (simple_data
, text
->text_data
,
664 text
->layout_width
, cr
, &bounds
,
665 &origin_x
, &origin_y
);
667 /* Convert the coordinates into Pango units. */
668 px
= (x
- origin_x
) * PANGO_SCALE
;
669 py
= (y
- origin_y
) * PANGO_SCALE
;
671 /* We use line extents here. Note that SVG uses character cells to determine
672 hits so we have slightly different behavior. */
673 iter
= pango_layout_get_iter (layout
);
676 pango_layout_iter_get_line_extents (iter
, &ink_rect
, &log_rect
);
678 /* We use a union of the ink rect and the logical rect, as we want to
679 let the user click on any part of the ink, even if it extends outside
680 the character cell (i.e. the ink rect), or click on the space in the
681 character cell (i.e. the logical rect). */
682 x1
= MIN (log_rect
.x
, ink_rect
.x
);
683 y1
= MIN (log_rect
.y
, ink_rect
.y
);
685 log_x2
= log_rect
.x
+ log_rect
.width
;
686 ink_x2
= ink_rect
.x
+ ink_rect
.width
;
687 x2
= MAX (log_x2
, ink_x2
);
689 log_y2
= log_rect
.y
+ log_rect
.height
;
690 ink_y2
= ink_rect
.y
+ ink_rect
.height
;
691 y2
= MAX (log_y2
, ink_y2
);
693 if (px
>= x1
&& px
< x2
&& py
>= y1
&& py
< y2
)
699 } while (pango_layout_iter_next_line (iter
));
701 pango_layout_iter_free (iter
);
703 g_object_unref (layout
);
710 goo_canvas_text_paint (GooCanvasItemSimple
*simple
,
712 const GooCanvasBounds
*bounds
)
714 GooCanvasText
*text
= (GooCanvasText
*) simple
;
715 GooCanvasTextPrivate
*priv
= goo_canvas_text_get_private (text
);
717 GooCanvasBounds layout_bounds
;
718 gdouble origin_x
, origin_y
;
720 /* If there is no text just return. */
721 if (!text
->text_data
->text
|| !text
->text_data
->text
[0])
724 goo_canvas_style_set_fill_options (simple
->simple_data
->style
, cr
);
727 layout
= goo_canvas_text_create_layout (simple
->simple_data
, text
->text_data
,
728 text
->layout_width
, cr
,
730 &origin_x
, &origin_y
);
733 if (priv
->height
> 0.0)
735 cairo_rectangle (cr
, origin_x
, origin_y
,
736 text
->layout_width
, priv
->height
);
739 cairo_move_to (cr
, origin_x
, origin_y
);
740 pango_cairo_show_layout (cr
, layout
);
743 g_object_unref (layout
);
748 goo_canvas_text_get_requested_height (GooCanvasItem
*item
,
752 GooCanvasItemSimple
*simple
= (GooCanvasItemSimple
*) item
;
753 GooCanvasItemSimpleData
*simple_data
= simple
->simple_data
;
754 GooCanvasText
*text
= (GooCanvasText
*) item
;
755 GooCanvasTextPrivate
*priv
= goo_canvas_text_get_private (text
);
759 /* If we have a transformation besides a simple scale & translation, just
760 return -1 as we can't adjust the height in that case. */
761 if (simple_data
->clip_path_commands
762 || (simple_data
->transform
&& (simple_data
->transform
->xy
!= 0.0
763 || simple_data
->transform
->yx
!= 0.0)))
767 if (simple_data
->transform
)
768 cairo_transform (cr
, simple_data
->transform
);
770 /* Convert the width from the parent's coordinate space. Note that we only
771 need to support a simple scale operation here. */
772 text
->layout_width
= width
;
773 if (simple_data
->transform
)
774 text
->layout_width
/= simple_data
->transform
->xx
;
776 if (priv
->height
< 0.0)
778 /* Create layout with given width. */
779 layout
= goo_canvas_text_create_layout (simple_data
, text
->text_data
,
780 text
->layout_width
, cr
,
781 &simple
->bounds
, NULL
, NULL
);
782 g_object_unref (layout
);
784 height
= simple
->bounds
.y2
- simple
->bounds
.y1
;
788 height
= priv
->height
;
791 /* Convert to the parent's coordinate space. As above, we only need to
792 support a simple scale operation here. */
793 if (simple_data
->transform
)
794 height
*= simple_data
->transform
->yy
;
796 /* Convert the item's bounds to device space. */
797 goo_canvas_item_simple_user_bounds_to_device (simple
, cr
, &simple
->bounds
);
801 /* Return the new requested height of the text. */
807 * goo_canvas_text_get_natural_extents:
808 * @text: a #GooCanvasText.
809 * @ink_rect: the location to return the ink rect, or %NULL.
810 * @logical_rect: the location to return the logical rect, or %NULL.
812 * Gets the natural extents of the text, in the text item's coordinate space.
814 * The final extents of the text may be different, if the text item is placed
815 * in a layout container such as #GooCanvasTable.
818 goo_canvas_text_get_natural_extents (GooCanvasText
*text
,
819 PangoRectangle
*ink_rect
,
820 PangoRectangle
*logical_rect
)
822 GooCanvasItem
*item
= (GooCanvasItem
*) text
;
823 GooCanvasItemSimple
*simple
= (GooCanvasItemSimple
*) text
;
827 if (simple
->need_update
)
828 goo_canvas_item_ensure_updated (item
);
830 cr
= goo_canvas_create_cairo_context (simple
->canvas
);
831 layout
= goo_canvas_text_create_layout (simple
->simple_data
, text
->text_data
,
832 text
->text_data
->width
, cr
, NULL
,
834 pango_layout_get_extents (layout
, ink_rect
, logical_rect
);
835 g_object_unref (layout
);
841 goo_canvas_text_set_model (GooCanvasItem
*item
,
842 GooCanvasItemModel
*model
)
844 GooCanvasItemSimple
*simple
= (GooCanvasItemSimple
*) item
;
845 GooCanvasText
*text
= (GooCanvasText
*) item
;
846 GooCanvasTextModel
*tmodel
= (GooCanvasTextModel
*) model
;
848 /* If our text_data was allocated, free it. */
850 g_slice_free (GooCanvasTextData
, text
->text_data
);
852 /* Now use the new model's text_data instead. */
853 text
->text_data
= &tmodel
->text_data
;
855 /* Let the parent GooCanvasItemSimple code do the rest. */
856 goo_canvas_item_simple_set_model (simple
, model
);
861 canvas_item_interface_init (GooCanvasItemIface
*iface
)
863 iface
->get_requested_height
= goo_canvas_text_get_requested_height
;
864 iface
->set_model
= goo_canvas_text_set_model
;
869 goo_canvas_text_class_init (GooCanvasTextClass
*klass
)
871 GObjectClass
*gobject_class
= (GObjectClass
*) klass
;
872 GooCanvasItemSimpleClass
*simple_class
= (GooCanvasItemSimpleClass
*) klass
;
874 g_type_class_add_private (gobject_class
, sizeof (GooCanvasTextPrivate
));
876 gobject_class
->finalize
= goo_canvas_text_finalize
;
878 gobject_class
->get_property
= goo_canvas_text_get_property
;
879 gobject_class
->set_property
= goo_canvas_text_set_property
;
881 simple_class
->simple_update
= goo_canvas_text_update
;
882 simple_class
->simple_paint
= goo_canvas_text_paint
;
883 simple_class
->simple_is_item_at
= goo_canvas_text_is_item_at
;
885 goo_canvas_text_install_common_properties (gobject_class
);
891 * SECTION:goocanvastextmodel
892 * @Title: GooCanvasTextModel
893 * @Short_Description: a model for text items.
895 * GooCanvasTextModel represents a model for text items.
897 * It is a subclass of #GooCanvasItemModelSimple and so inherits all of the
898 * style properties such as "fill-color".
900 * It also implements the #GooCanvasItemModel interface, so you can use the
901 * #GooCanvasItemModel functions such as goo_canvas_item_model_raise() and
902 * goo_canvas_item_model_rotate().
904 * To create a #GooCanvasTextModel use goo_canvas_text_model_new().
906 * To get or set the properties of an existing #GooCanvasTextModel, use
907 * g_object_get() and g_object_set().
909 * To respond to events such as mouse clicks on the text item you must connect
910 * to the signal handlers of the corresponding #GooCanvasText objects.
911 * (See goo_canvas_get_item() and #GooCanvas::item-created.)
914 static void item_model_interface_init (GooCanvasItemModelIface
*iface
);
915 static void goo_canvas_text_model_finalize (GObject
*object
);
916 static void goo_canvas_text_model_get_property (GObject
*object
,
920 static void goo_canvas_text_model_set_property (GObject
*object
,
925 G_DEFINE_TYPE_WITH_CODE (GooCanvasTextModel
, goo_canvas_text_model
,
926 GOO_TYPE_CANVAS_ITEM_MODEL_SIMPLE
,
927 G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM_MODEL
,
928 item_model_interface_init
))
932 goo_canvas_text_model_class_init (GooCanvasTextModelClass
*klass
)
934 GObjectClass
*gobject_class
= (GObjectClass
*) klass
;
936 g_type_class_add_private (gobject_class
, sizeof (GooCanvasTextPrivate
));
938 gobject_class
->finalize
= goo_canvas_text_model_finalize
;
940 gobject_class
->get_property
= goo_canvas_text_model_get_property
;
941 gobject_class
->set_property
= goo_canvas_text_model_set_property
;
943 goo_canvas_text_install_common_properties (gobject_class
);
948 goo_canvas_text_model_init (GooCanvasTextModel
*tmodel
)
950 GooCanvasTextPrivate
*priv
= GOO_CANVAS_TEXT_MODEL_GET_PRIVATE (tmodel
);
952 tmodel
->text_data
.width
= -1.0;
953 tmodel
->text_data
.anchor
= GTK_ANCHOR_NW
;
954 tmodel
->text_data
.ellipsize
= PANGO_ELLIPSIZE_NONE
;
955 tmodel
->text_data
.wrap
= PANGO_WRAP_WORD
;
962 * goo_canvas_text_model_new:
963 * @parent: the parent model, or %NULL. If a parent is specified, it will
964 * assume ownership of the item, and the item will automatically be freed when
965 * it is removed from the parent. Otherwise call g_object_unref() to free it.
966 * @string: the text to display.
967 * @x: the x coordinate of the text.
968 * @y: the y coordinate of the text.
969 * @width: the width of the text item, or -1 for unlimited width.
970 * @anchor: the position of the text relative to the given @x and @y
971 * coordinates. For example an anchor of %GDK_ANCHOR_NW will result in the
972 * top-left of the text being placed at the given @x and @y coordinates.
973 * An anchor of %GDK_ANCHOR_CENTER will result in the center of the text being
974 * placed at the @x and @y coordinates.
975 * @...: optional pairs of property names and values, and a terminating %NULL.
977 * Creates a new text model.
981 * Here's an example showing how to create a text item with the bottom right
982 * of the text box placed at (500,500):
984 * <informalexample><programlisting>
985 * GooCanvasItemModel *text = goo_canvas_text_model_new (mygroup, "Hello World", 500.0, 500.0, 200.0, GTK_ANCHOR_SE,
986 * "fill-color", "blue",
988 * </programlisting></informalexample>
990 * Returns: a new text model.
993 goo_canvas_text_model_new (GooCanvasItemModel
*parent
,
998 GtkAnchorType anchor
,
1001 GooCanvasItemModel
*model
;
1002 GooCanvasTextModel
*tmodel
;
1003 GooCanvasTextData
*text_data
;
1004 const char *first_property
;
1007 model
= g_object_new (GOO_TYPE_CANVAS_TEXT_MODEL
, NULL
);
1008 tmodel
= (GooCanvasTextModel
*) model
;
1010 text_data
= &tmodel
->text_data
;
1011 text_data
->text
= g_strdup (string
);
1014 text_data
->width
= width
;
1015 text_data
->anchor
= anchor
;
1017 va_start (var_args
, anchor
);
1018 first_property
= va_arg (var_args
, char*);
1020 g_object_set_valist ((GObject
*) model
, first_property
, var_args
);
1025 goo_canvas_item_model_add_child (parent
, model
, -1);
1026 g_object_unref (model
);
1034 goo_canvas_text_model_finalize (GObject
*object
)
1036 GooCanvasTextModel
*tmodel
= (GooCanvasTextModel
*) object
;
1038 g_free (tmodel
->text_data
.text
);
1040 G_OBJECT_CLASS (goo_canvas_text_model_parent_class
)->finalize (object
);
1045 goo_canvas_text_model_get_property (GObject
*object
,
1050 GooCanvasTextModel
*tmodel
= (GooCanvasTextModel
*) object
;
1051 GooCanvasTextPrivate
*priv
= GOO_CANVAS_TEXT_MODEL_GET_PRIVATE (tmodel
);
1053 goo_canvas_text_get_common_property (object
, &tmodel
->text_data
, priv
,
1054 prop_id
, value
, pspec
);
1059 goo_canvas_text_model_set_property (GObject
*object
,
1061 const GValue
*value
,
1064 GooCanvasTextModel
*tmodel
= (GooCanvasTextModel
*) object
;
1065 GooCanvasTextPrivate
*priv
= GOO_CANVAS_TEXT_MODEL_GET_PRIVATE (tmodel
);
1067 goo_canvas_text_set_common_property (object
, &tmodel
->text_data
, priv
,
1068 prop_id
, value
, pspec
);
1069 g_signal_emit_by_name (tmodel
, "changed", TRUE
);
1073 static GooCanvasItem
*
1074 goo_canvas_text_model_create_item (GooCanvasItemModel
*model
,
1077 GooCanvasItem
*item
;
1079 item
= g_object_new (GOO_TYPE_CANVAS_TEXT
, NULL
);
1080 goo_canvas_item_set_model (item
, model
);
1087 item_model_interface_init (GooCanvasItemModelIface
*iface
)
1089 iface
->create_item
= goo_canvas_text_model_create_item
;