summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2020-09-16 22:31:34 -0400
committerMatthias Clasen <mclasen@redhat.com>2020-09-16 23:01:49 -0400
commit18e46bd6f8b0c0b37b9e979ab0b21e8f3369feb2 (patch)
treee2df111604457f274aa622c37cda0e30691c279c
parent7082624fd72dd42bbb1b8908195ed8b29a7baac5 (diff)
downloadgtk+-18e46bd6f8b0c0b37b9e979ab0b21e8f3369feb2.tar.gz
gtk-demo: Beef up the hypertext demo
Its almost a dictionary.
-rw-r--r--demos/gtk-demo/hypertext.c139
1 files changed, 117 insertions, 22 deletions
diff --git a/demos/gtk-demo/hypertext.c b/demos/gtk-demo/hypertext.c
index 9236d188a5..ab9c988fac 100644
--- a/demos/gtk-demo/hypertext.c
+++ b/demos/gtk-demo/hypertext.c
@@ -5,6 +5,9 @@
* bold or colored or underlined. But tags are not restricted to appearance.
* They can also affect the behavior of mouse and key presses, as this demo
* shows.
+ *
+ * We also demonstrate adding other things to a text view, such as
+ * clickable icons.
*/
#include <gtk/gtk.h>
@@ -31,35 +34,103 @@ insert_link (GtkTextBuffer *buffer,
gtk_text_buffer_insert_with_tags (buffer, iter, text, -1, tag, NULL);
}
+/* Quick-and-dirty text-to-speech for a single word. If you don't hear
+ * anything, you are missing espeak-ng on your system.
+ */
+static void
+say_word (GtkGestureClick *gesture,
+ guint n_press,
+ double x,
+ double y,
+ const char *word)
+{
+ const char *argv[3];
+
+ argv[0] = "espeak-ng";
+ argv[1] = word;
+ argv[2] = NULL;
+
+ g_spawn_async (NULL, (char **)argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL);
+}
+
/* Fills the buffer with text and interspersed links. In any real
* hypertext app, this method would parse a file to identify the links.
*/
static void
-show_page (GtkTextBuffer *buffer,
- int page)
+show_page (GtkTextView *text_view,
+ int page)
{
+ GtkTextBuffer *buffer;
GtkTextIter iter;
+ GtkWidget *child;
+ GtkTextChildAnchor *anchor;
+ GtkEventController *controller;
+ buffer = gtk_text_view_get_buffer (text_view);
gtk_text_buffer_set_text (buffer, "", 0);
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
gtk_text_buffer_begin_irreversible_action (buffer);
if (page == 1)
{
+ GtkIconPaintable *icon;
+ GtkIconTheme *theme;
+
gtk_text_buffer_insert (buffer, &iter, "Some text to show that simple ", -1);
- insert_link (buffer, &iter, "hyper text", 3);
+ insert_link (buffer, &iter, "hypertext", 3);
gtk_text_buffer_insert (buffer, &iter, " can easily be realized with ", -1);
insert_link (buffer, &iter, "tags", 2);
+ gtk_text_buffer_insert (buffer, &iter, ".\n", -1);
+ gtk_text_buffer_insert (buffer, &iter,
+ "Of course you can also embed Emoji 😋, "
+ "icons ", -1);
+
+ theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (text_view)));
+ icon = gtk_icon_theme_lookup_icon (theme,
+ "microphone-sensitivity-high-symbolic",
+ NULL,
+ 16,
+ 1,
+ GTK_TEXT_DIR_LTR,
+ 0);
+ gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE (icon));
+ g_object_unref (icon);
+ gtk_text_buffer_insert (buffer, &iter, ", or even widgets ", -1);
+ anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
+ child = gtk_level_bar_new_for_interval (0, 100);
+ gtk_level_bar_set_value (GTK_LEVEL_BAR (child), 50);
+ gtk_widget_set_size_request (child, 100, -1);
+ gtk_text_view_add_child_at_anchor (text_view, child, anchor);
gtk_text_buffer_insert (buffer, &iter, ".", -1);
}
else if (page == 2)
{
- gtk_text_buffer_insert (buffer, &iter,
- "A tag is an attribute that can be applied to some range of text. "
- "For example, a tag might be called \"bold\" and make the text inside "
- "the tag bold. However, the tag concept is more general than that; "
- "tags don't have to affect appearance. They can instead affect the "
- "behavior of mouse and key presses, \"lock\" a range of text so the "
- "user can't edit it, or countless other things.\n", -1);
+ GtkTextTag *tag;
+
+ tag = gtk_text_buffer_create_tag (buffer, NULL,
+ "weight", PANGO_WEIGHT_BOLD,
+ "scale", PANGO_SCALE_X_LARGE,
+ NULL);
+ gtk_text_buffer_insert_with_tags (buffer, &iter, "tag", -1, tag, NULL);
+ tag = gtk_text_buffer_create_tag (buffer, NULL,
+ "family", "monospace",
+ NULL);
+ gtk_text_buffer_insert_with_tags (buffer, &iter, " / tag / ", -1, tag, NULL);
+
+ anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
+ child = gtk_image_new_from_icon_name ("audio-volume-high-symbolic");
+ gtk_widget_set_cursor_from_name (child, "pointer");
+ controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
+ g_signal_connect (controller, "pressed", G_CALLBACK (say_word), (gpointer)"tag");
+ gtk_widget_add_controller (child, controller);
+ gtk_text_view_add_child_at_anchor (text_view, child, anchor);
+
+ gtk_text_buffer_insert (buffer, &iter, "\n"
+ "An attribute that can be applied to some range of text. For example, "
+ "a tag might be called “bold” and make the text inside the tag bold.\n"
+ "However, the tag concept is more general than that; "
+ "tags don't have to affect appearance. They can instead affect the "
+ "behavior of mouse and key presses, “lock” a range of text so the "
+ "user can't edit it, or countless other things.\n", -1);
insert_link (buffer, &iter, "Go back", 1);
}
else if (page == 3)
@@ -68,11 +139,25 @@ show_page (GtkTextBuffer *buffer,
tag = gtk_text_buffer_create_tag (buffer, NULL,
"weight", PANGO_WEIGHT_BOLD,
+ "scale", PANGO_SCALE_X_LARGE,
NULL);
- gtk_text_buffer_insert_with_tags (buffer, &iter, "hypertext:\n", -1, tag, NULL);
- gtk_text_buffer_insert (buffer, &iter,
- "machine-readable text that is not sequential but is organized "
- "so that related items of information are connected.\n", -1);
+ gtk_text_buffer_insert_with_tags (buffer, &iter, "hypertext", -1, tag, NULL);
+ tag = gtk_text_buffer_create_tag (buffer, NULL,
+ "family", "monospace",
+ NULL);
+ gtk_text_buffer_insert_with_tags (buffer, &iter, " / ˈhaɪ pərˌtɛkst / ", -1, tag, NULL);
+
+ anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
+ child = gtk_image_new_from_icon_name ("audio-volume-high-symbolic");
+ gtk_widget_set_cursor_from_name (child, "pointer");
+ controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
+ g_signal_connect (controller, "pressed", G_CALLBACK (say_word), (gpointer)"hypertext");
+ gtk_widget_add_controller (child, controller);
+ gtk_text_view_add_child_at_anchor (text_view, child, anchor);
+
+ gtk_text_buffer_insert (buffer, &iter, "\n"
+ "Machine-readable text that is not sequential but is organized "
+ "so that related items of information are connected.\n", -1);
insert_link (buffer, &iter, "Go back", 1);
}
gtk_text_buffer_end_irreversible_action (buffer);
@@ -96,7 +181,7 @@ follow_if_link (GtkWidget *text_view,
if (page != 0)
{
- show_page (gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view)), page);
+ show_page (GTK_TEXT_VIEW (text_view), page);
break;
}
}
@@ -163,7 +248,7 @@ released_cb (GtkGestureClick *gesture,
if (gtk_text_iter_get_offset (&start) != gtk_text_iter_get_offset (&end))
return;
- if (gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (text_view), &iter, x, y))
+ if (gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (text_view), &iter, tx, ty))
follow_if_link (text_view, &iter);
}
@@ -173,7 +258,13 @@ motion_cb (GtkEventControllerMotion *controller,
double y,
GtkTextView *text_view)
{
- set_cursor_if_appropriate (text_view, x, y);
+ int tx, ty;
+
+ gtk_text_view_window_to_buffer_coords (text_view,
+ GTK_TEXT_WINDOW_WIDGET,
+ x, y, &tx, &ty);
+
+ set_cursor_if_appropriate (text_view, tx, ty);
}
static gboolean hovering_over_link = FALSE;
@@ -183,9 +274,9 @@ static gboolean hovering_over_link = FALSE;
* typically used by web browsers.
*/
static void
-set_cursor_if_appropriate (GtkTextView *text_view,
- int x,
- int y)
+set_cursor_if_appropriate (GtkTextView *text_view,
+ int x,
+ int y)
{
GSList *tags = NULL, *tagp = NULL;
GtkTextIter iter;
@@ -237,13 +328,17 @@ do_hypertext (GtkWidget *do_widget)
gtk_window_set_title (GTK_WINDOW (window), "Hypertext");
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
- gtk_window_set_default_size (GTK_WINDOW (window), 450, 450);
+ gtk_window_set_default_size (GTK_WINDOW (window), 330, 330);
+ gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
view = gtk_text_view_new ();
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD);
+ gtk_text_view_set_top_margin (GTK_TEXT_VIEW (view), 20);
+ gtk_text_view_set_bottom_margin (GTK_TEXT_VIEW (view), 20);
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view), 20);
gtk_text_view_set_right_margin (GTK_TEXT_VIEW (view), 20);
+ gtk_text_view_set_pixels_below_lines (GTK_TEXT_VIEW (view), 10);
controller = gtk_event_controller_key_new ();
g_signal_connect (controller, "key-pressed", G_CALLBACK (key_pressed), view);
gtk_widget_add_controller (view, controller);
@@ -268,7 +363,7 @@ do_hypertext (GtkWidget *do_widget)
gtk_window_set_child (GTK_WINDOW (window), sw);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), view);
- show_page (buffer, 1);
+ show_page (GTK_TEXT_VIEW (view), 1);
}
if (!gtk_widget_get_visible (window))