3 * The GtkTextView widget displays a GtkTextBuffer. One GtkTextBuffer
4 * can be displayed by multiple GtkTextViews. This demo has two views
5 * displaying a single buffer, and shows off the widget's text
11 #include <stdlib.h> /* for exit() */
13 #include "demo-common.h"
15 static void easter_egg_callback (GtkWidget *button, gpointer data);
17 #define gray50_width 2
18 #define gray50_height 2
19 static char gray50_bits[] = {
24 create_tags (GtkTextBuffer *buffer)
28 /* Create a bunch of tags. Note that it's also possible to
29 * create tags with gtk_text_tag_new() then add them to the
30 * tag table for the buffer, gtk_text_buffer_create_tag() is
31 * just a convenience function. Also note that you don't have
32 * to give tags a name; pass NULL for the name to create an
35 * In any real app, another useful optimization would be to create
36 * a GtkTextTagTable in advance, and reuse the same tag table for
37 * all the buffers with the same tag set, instead of creating
38 * new copies of the same tags for every buffer.
40 * Tags are assigned default priorities in order of addition to the
41 * tag table. That is, tags created later that affect the same text
42 * property affected by an earlier tag will override the earlier
43 * tag. You can modify tag priorities with
44 * gtk_text_tag_set_priority().
47 gtk_text_buffer_create_tag (buffer, "heading",
48 "weight", PANGO_WEIGHT_BOLD,
49 "size", 15 * PANGO_SCALE,
52 gtk_text_buffer_create_tag (buffer, "italic",
53 "style", PANGO_STYLE_ITALIC, NULL);
55 gtk_text_buffer_create_tag (buffer, "bold",
56 "weight", PANGO_WEIGHT_BOLD, NULL);
58 gtk_text_buffer_create_tag (buffer, "big",
59 /* points times the PANGO_SCALE factor */
60 "size", 20 * PANGO_SCALE, NULL);
62 gtk_text_buffer_create_tag (buffer, "xx-small",
63 "scale", PANGO_SCALE_XX_SMALL, NULL);
65 gtk_text_buffer_create_tag (buffer, "x-large",
66 "scale", PANGO_SCALE_X_LARGE, NULL);
68 gtk_text_buffer_create_tag (buffer, "monospace",
69 "family", "monospace", NULL);
71 gtk_text_buffer_create_tag (buffer, "blue_foreground",
72 "foreground", "blue", NULL);
74 gtk_text_buffer_create_tag (buffer, "red_background",
75 "background", "red", NULL);
77 stipple = gdk_bitmap_create_from_data (NULL,
78 gray50_bits, gray50_width,
81 gtk_text_buffer_create_tag (buffer, "background_stipple",
82 "background_stipple", stipple, NULL);
84 gtk_text_buffer_create_tag (buffer, "foreground_stipple",
85 "foreground_stipple", stipple, NULL);
87 g_object_unref (stipple);
89 gtk_text_buffer_create_tag (buffer, "big_gap_before_line",
90 "pixels_above_lines", 30, NULL);
92 gtk_text_buffer_create_tag (buffer, "big_gap_after_line",
93 "pixels_below_lines", 30, NULL);
95 gtk_text_buffer_create_tag (buffer, "double_spaced_line",
96 "pixels_inside_wrap", 10, NULL);
98 gtk_text_buffer_create_tag (buffer, "not_editable",
99 "editable", FALSE, NULL);
101 gtk_text_buffer_create_tag (buffer, "word_wrap",
102 "wrap_mode", GTK_WRAP_WORD, NULL);
104 gtk_text_buffer_create_tag (buffer, "char_wrap",
105 "wrap_mode", GTK_WRAP_CHAR, NULL);
107 gtk_text_buffer_create_tag (buffer, "no_wrap",
108 "wrap_mode", GTK_WRAP_NONE, NULL);
110 gtk_text_buffer_create_tag (buffer, "center",
111 "justification", GTK_JUSTIFY_CENTER, NULL);
113 gtk_text_buffer_create_tag (buffer, "right_justify",
114 "justification", GTK_JUSTIFY_RIGHT, NULL);
116 gtk_text_buffer_create_tag (buffer, "wide_margins",
117 "left_margin", 50, "right_margin", 50,
120 gtk_text_buffer_create_tag (buffer, "strikethrough",
121 "strikethrough", TRUE, NULL);
123 gtk_text_buffer_create_tag (buffer, "underline",
124 "underline", PANGO_UNDERLINE_SINGLE, NULL);
126 gtk_text_buffer_create_tag (buffer, "double_underline",
127 "underline", PANGO_UNDERLINE_DOUBLE, NULL);
129 gtk_text_buffer_create_tag (buffer, "superscript",
130 "rise", 10 * PANGO_SCALE, /* 10 pixels */
131 "size", 8 * PANGO_SCALE, /* 8 points */
134 gtk_text_buffer_create_tag (buffer, "subscript",
135 "rise", -10 * PANGO_SCALE, /* 10 pixels */
136 "size", 8 * PANGO_SCALE, /* 8 points */
139 gtk_text_buffer_create_tag (buffer, "rtl_quote",
140 "wrap_mode", GTK_WRAP_WORD,
141 "direction", GTK_TEXT_DIR_RTL,
149 insert_text (GtkTextBuffer *buffer)
152 GtkTextIter start, end;
155 GtkTextChildAnchor *anchor;
158 /* demo_find_file() looks in the the current directory first,
159 * so you can run gtk-demo without installing GTK, then looks
160 * in the location where the file is installed.
163 filename = demo_find_file ("gtk-logo-rgb.gif", NULL);
166 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
172 g_printerr ("Failed to load image file gtk-logo-rgb.gif\n");
176 scaled = gdk_pixbuf_scale_simple (pixbuf, 32, 32, GDK_INTERP_BILINEAR);
177 g_object_unref (pixbuf);
180 /* get start of buffer; each insertion will revalidate the
181 * iterator to point to just after the inserted text.
183 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
185 gtk_text_buffer_insert (buffer, &iter, "The text widget can display text with all kinds of nifty attributes. It also supports multiple views of the same buffer; this demo is showing the same buffer in two places.\n\n", -1);
187 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Font styles. ", -1,
190 gtk_text_buffer_insert (buffer, &iter, "For example, you can have ", -1);
191 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
194 gtk_text_buffer_insert (buffer, &iter, ", ", -1);
195 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
198 gtk_text_buffer_insert (buffer, &iter, ", or ", -1);
199 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
200 "monospace (typewriter)", -1,
202 gtk_text_buffer_insert (buffer, &iter, ", or ", -1);
203 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
206 gtk_text_buffer_insert (buffer, &iter, " text. ", -1);
207 gtk_text_buffer_insert (buffer, &iter, "It's best not to hardcode specific text sizes; you can use relative sizes as with CSS, such as ", -1);
208 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
211 gtk_text_buffer_insert (buffer, &iter, " or ", -1);
212 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
215 gtk_text_buffer_insert (buffer, &iter, " to ensure that your program properly adapts if the user changes the default font size.\n\n", -1);
217 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Colors. ", -1,
220 gtk_text_buffer_insert (buffer, &iter, "Colors such as ", -1);
221 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
222 "a blue foreground", -1,
223 "blue_foreground", NULL);
224 gtk_text_buffer_insert (buffer, &iter, " or ", -1);
225 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
226 "a red background", -1,
227 "red_background", NULL);
228 gtk_text_buffer_insert (buffer, &iter, " or even ", -1);
229 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
230 "a stippled red background", -1,
232 "background_stipple",
235 gtk_text_buffer_insert (buffer, &iter, " or ", -1);
236 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
237 "a stippled blue foreground on solid red background", -1,
240 "foreground_stipple",
242 gtk_text_buffer_insert (buffer, &iter, " (select that to read it) can be used.\n\n", -1);
244 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Underline, strikethrough, and rise. ", -1,
247 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
249 "strikethrough", NULL);
250 gtk_text_buffer_insert (buffer, &iter, ", ", -1);
251 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
254 gtk_text_buffer_insert (buffer, &iter, ", ", -1);
255 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
256 "double underline", -1,
257 "double_underline", NULL);
258 gtk_text_buffer_insert (buffer, &iter, ", ", -1);
259 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
261 "superscript", NULL);
262 gtk_text_buffer_insert (buffer, &iter, ", and ", -1);
263 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
266 gtk_text_buffer_insert (buffer, &iter, " are all supported.\n\n", -1);
268 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Images. ", -1,
271 gtk_text_buffer_insert (buffer, &iter, "The buffer can have images in it: ", -1);
272 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
273 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
274 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
275 gtk_text_buffer_insert (buffer, &iter, " for example.\n\n", -1);
277 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Spacing. ", -1,
280 gtk_text_buffer_insert (buffer, &iter, "You can adjust the amount of space before each line.\n", -1);
282 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
283 "This line has a whole lot of space before it.\n", -1,
284 "big_gap_before_line", "wide_margins", NULL);
285 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
286 "You can also adjust the amount of space after each line; this line has a whole lot of space after it.\n", -1,
287 "big_gap_after_line", "wide_margins", NULL);
289 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
290 "You can also adjust the amount of space between wrapped lines; this line has extra space between each wrapped line in the same paragraph. To show off wrapping, some filler text: the quick brown fox jumped over the lazy dog. Blah blah blah blah blah blah blah blah blah.\n", -1,
291 "double_spaced_line", "wide_margins", NULL);
293 gtk_text_buffer_insert (buffer, &iter, "Also note that those lines have extra-wide margins.\n\n", -1);
295 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Editability. ", -1,
298 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
299 "This line is 'locked down' and can't be edited by the user - just try it! You can't delete this line.\n\n", -1,
300 "not_editable", NULL);
302 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Wrapping. ", -1,
305 gtk_text_buffer_insert (buffer, &iter,
306 "This line (and most of the others in this buffer) is word-wrapped, using the proper Unicode algorithm. Word wrap should work in all scripts and languages that GTK+ supports. Let's make this a long paragraph to demonstrate: blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah\n\n", -1);
308 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
309 "This line has character-based wrapping, and can wrap between any two character glyphs. Let's make this a long paragraph to demonstrate: blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah\n\n", -1,
312 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
313 "This line has all wrapping turned off, so it makes the horizontal scrollbar appear.\n\n\n", -1,
316 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Justification. ", -1,
319 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
320 "\nThis line has center justification.\n", -1,
323 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
324 "This line has right justification.\n", -1,
325 "right_justify", NULL);
327 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
328 "\nThis line has big wide margins. Text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text.\n", -1,
329 "wide_margins", NULL);
331 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Internationalization. ", -1,
334 gtk_text_buffer_insert (buffer, &iter,
335 "You can put all sorts of Unicode text in the buffer.\n\nGerman (Deutsch Süd) Grüß Gott\nGreek (Ελληνικά) Γειά σας\nHebrew שלום\nJapanese (日本語)\n\nThe widget properly handles bidirectional text, word wrapping, DOS/UNIX/Unicode paragraph separators, grapheme boundaries, and so on using the Pango internationalization framework.\n", -1);
337 gtk_text_buffer_insert (buffer, &iter, "Here's a word-wrapped quote in a right-to-left language:\n", -1);
338 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "وقد بدأ ثلاث من أكثر المؤسسات تقدما في شبكة اكسيون برامجها كمنظمات لا تسعى للربح، ثم تحولت في السنوات الخمس الماضية إلى مؤسسات مالية منظمة، وباتت جزءا من النظام المالي في بلدانها، ولكنها تتخصص في خدمة قطاع المشروعات الصغيرة. وأحد أكثر هذه المؤسسات نجاحا هو »بانكوسول« في بوليفيا.\n\n", -1,
341 gtk_text_buffer_insert (buffer, &iter, "You can put widgets in the buffer: Here's a button: ", -1);
342 anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
343 gtk_text_buffer_insert (buffer, &iter, " and a menu: ", -1);
344 anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
345 gtk_text_buffer_insert (buffer, &iter, " and a scale: ", -1);
346 anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
347 gtk_text_buffer_insert (buffer, &iter, " and an animation: ", -1);
348 anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
349 gtk_text_buffer_insert (buffer, &iter, " finally a text entry: ", -1);
350 anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
351 gtk_text_buffer_insert (buffer, &iter, ".\n", -1);
353 gtk_text_buffer_insert (buffer, &iter, "\n\nThis demo doesn't demonstrate all the GtkTextBuffer features; it leaves out, for example: invisible/hidden text (doesn't work in GTK 2, but planned), tab stops, application-drawn areas on the sides of the widget for displaying breakpoints and such...", -1);
355 /* Apply word_wrap tag to whole buffer */
356 gtk_text_buffer_get_bounds (buffer, &start, &end);
357 gtk_text_buffer_apply_tag_by_name (buffer, "word_wrap", &start, &end);
359 g_object_unref (pixbuf);
363 find_anchor (GtkTextIter *iter)
365 while (gtk_text_iter_forward_char (iter))
367 if (gtk_text_iter_get_child_anchor (iter))
374 attach_widgets (GtkTextView *text_view)
377 GtkTextBuffer *buffer;
380 buffer = gtk_text_view_get_buffer (text_view);
382 gtk_text_buffer_get_start_iter (buffer, &iter);
385 while (find_anchor (&iter))
387 GtkTextChildAnchor *anchor;
390 anchor = gtk_text_iter_get_child_anchor (&iter);
394 widget = gtk_button_new_with_label ("Click Me");
396 g_signal_connect (widget, "clicked",
397 G_CALLBACK (easter_egg_callback),
402 GtkWidget *menu_item;
405 menu = gtk_menu_new ();
407 widget = gtk_option_menu_new ();
409 menu_item = gtk_menu_item_new_with_label ("Option 1");
410 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
411 menu_item = gtk_menu_item_new_with_label ("Option 2");
412 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
413 menu_item = gtk_menu_item_new_with_label ("Option 3");
414 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
416 gtk_option_menu_set_menu (GTK_OPTION_MENU (widget), menu);
420 widget = gtk_hscale_new (NULL);
421 gtk_range_set_range (GTK_RANGE (widget), 0, 100);
422 gtk_widget_set_size_request (widget, 70, -1);
426 gchar *filename = demo_find_file ("floppybuddy.gif", NULL);
427 widget = gtk_image_new_from_file (filename);
432 widget = gtk_entry_new ();
436 widget = NULL; /* avoids a compiler warning */
437 g_assert_not_reached ();
440 gtk_text_view_add_child_at_anchor (text_view,
444 gtk_widget_show_all (widget);
453 static GtkWidget *window = NULL;
461 GtkTextBuffer *buffer;
463 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
464 gtk_window_set_default_size (GTK_WINDOW (window),
467 g_signal_connect (window, "destroy",
468 G_CALLBACK (gtk_widget_destroyed), &window);
470 gtk_window_set_title (GTK_WINDOW (window), "TextView");
471 gtk_container_set_border_width (GTK_CONTAINER (window), 0);
473 vpaned = gtk_vpaned_new ();
474 gtk_container_set_border_width (GTK_CONTAINER(vpaned), 5);
475 gtk_container_add (GTK_CONTAINER (window), vpaned);
477 /* For convenience, we just use the autocreated buffer from
478 * the first text view; you could also create the buffer
479 * by itself with gtk_text_buffer_new(), then later create
482 view1 = gtk_text_view_new ();
483 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view1));
484 view2 = gtk_text_view_new_with_buffer (buffer);
486 sw = gtk_scrolled_window_new (NULL, NULL);
487 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
488 GTK_POLICY_AUTOMATIC,
489 GTK_POLICY_AUTOMATIC);
490 gtk_paned_add1 (GTK_PANED (vpaned), sw);
492 gtk_container_add (GTK_CONTAINER (sw), view1);
494 sw = gtk_scrolled_window_new (NULL, NULL);
495 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
496 GTK_POLICY_AUTOMATIC,
497 GTK_POLICY_AUTOMATIC);
498 gtk_paned_add2 (GTK_PANED (vpaned), sw);
500 gtk_container_add (GTK_CONTAINER (sw), view2);
502 create_tags (buffer);
503 insert_text (buffer);
505 attach_widgets (GTK_TEXT_VIEW (view1));
506 attach_widgets (GTK_TEXT_VIEW (view2));
508 gtk_widget_show_all (vpaned);
511 if (!GTK_WIDGET_VISIBLE (window))
513 gtk_widget_show (window);
517 gtk_widget_destroy (window);
525 recursive_attach_view (int depth,
527 GtkTextChildAnchor *anchor)
529 GtkWidget *child_view;
530 GtkWidget *event_box;
537 child_view = gtk_text_view_new_with_buffer (gtk_text_view_get_buffer (view));
539 /* Event box is to add a black border around each child view */
540 event_box = gtk_event_box_new ();
541 gdk_color_parse ("black", &color);
542 gtk_widget_modify_bg (event_box, GTK_STATE_NORMAL, &color);
544 align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
545 gtk_container_set_border_width (GTK_CONTAINER (align), 1);
547 gtk_container_add (GTK_CONTAINER (event_box), align);
548 gtk_container_add (GTK_CONTAINER (align), child_view);
550 gtk_text_view_add_child_at_anchor (view, event_box, anchor);
552 recursive_attach_view (depth + 1, GTK_TEXT_VIEW (child_view), anchor);
556 easter_egg_callback (GtkWidget *button,
559 static GtkWidget *window = NULL;
560 GtkTextBuffer *buffer;
563 GtkTextChildAnchor *anchor;
568 gtk_window_present (GTK_WINDOW (window));
572 buffer = gtk_text_buffer_new (NULL);
574 gtk_text_buffer_get_start_iter (buffer, &iter);
576 gtk_text_buffer_insert (buffer, &iter,
577 "This buffer is shared by a set of nested text views.\n Nested view:\n", -1);
578 anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
579 gtk_text_buffer_insert (buffer, &iter,
580 "\nDon't do this in real applications, please.\n", -1);
582 view = gtk_text_view_new_with_buffer (buffer);
584 recursive_attach_view (0, GTK_TEXT_VIEW (view), anchor);
586 g_object_unref (buffer);
588 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
589 sw = gtk_scrolled_window_new (NULL, NULL);
590 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
591 GTK_POLICY_AUTOMATIC,
592 GTK_POLICY_AUTOMATIC);
594 gtk_container_add (GTK_CONTAINER (window), sw);
595 gtk_container_add (GTK_CONTAINER (sw), view);
597 g_object_add_weak_pointer (G_OBJECT (window),
598 (gpointer *) &window);
600 gtk_window_set_default_size (GTK_WINDOW (window), 300, 400);
602 gtk_widget_show_all (window);