[gtk/matthiasc/for-master: 2/2] gtk-demo: Beef up the hypertext demo




commit 18e46bd6f8b0c0b37b9e979ab0b21e8f3369feb2
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Sep 16 22:31:34 2020 -0400

    gtk-demo: Beef up the hypertext demo
    
    Its almost a dictionary.

 demos/gtk-demo/hypertext.c | 139 ++++++++++++++++++++++++++++++++++++++-------
 1 file 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))


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]