summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2020-01-03 10:14:19 -0500
committerMatthias Clasen <mclasen@redhat.com>2020-01-03 11:18:08 -0500
commit96d2bf10b9f985ce00aeeeaacb29c1e8c2d4f393 (patch)
treeaeb3bf16db28fefb16217f6fa1e1957292c793b7
parent7a1aefc7f3f7ad39498c58cf79d82c28e2e0b245 (diff)
downloadgtk+-96d2bf10b9f985ce00aeeeaacb29c1e8c2d4f393.tar.gz
Add a text view mark/cursor test
This has testcases for some issues around invalidation of marks.
-rw-r--r--tests/meson.build1
-rw-r--r--tests/testtextview2.c238
2 files changed, 239 insertions, 0 deletions
diff --git a/tests/meson.build b/tests/meson.build
index aa16f4fde7..e6041c3627 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -101,6 +101,7 @@ gtk_tests = [
['testtreepos'],
['testsensitive'],
['testtextview'],
+ ['testtextview2'],
['testpixbuf-scale'],
['testgmenu'],
['testlogout'],
diff --git a/tests/testtextview2.c b/tests/testtextview2.c
new file mode 100644
index 0000000000..83431bfc31
--- /dev/null
+++ b/tests/testtextview2.c
@@ -0,0 +1,238 @@
+/* simple.c
+ * Copyright (C) 2017 Red Hat, Inc
+ * Author: Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "config.h"
+#include <gtk/gtk.h>
+
+
+const char text[] =
+"This library is free software; you can redistribute it and/or\n"
+"modify it under the terms of the GNU Library General Public\n"
+"License as published by the Free Software Foundation; either\n"
+"version 2 of the License, or (at your option) any later version.\n"
+"\n"
+"This library is distributed in the hope that it will be useful,\n"
+"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
+"Library General Public License for more details.\n"
+"\n"
+"You should have received a copy of the GNU Library General Public\n"
+"License along with this library. If not, see <http://www.gnu.org/licenses/>.\n";
+
+static GtkWidget *tv;
+static GtkTextBuffer *buffer;
+static int len;
+
+static GtkTextMark **marks;
+static guint marks_timeout;
+
+static gboolean toggle_mark (gpointer data)
+{
+ int pos;
+ GtkTextMark *mark;
+
+ pos = g_random_int_range (0, len);
+ mark = marks[pos];
+
+ gtk_text_mark_set_visible (mark, !gtk_text_mark_get_visible (mark));
+
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+toggle_marks (GtkToggleButton *button)
+{
+ int i;
+ gboolean enable;
+
+ enable = gtk_toggle_button_get_active (button);
+
+ if (!marks)
+ {
+ marks = g_new (GtkTextMark*, len);
+
+ for (i = 0; i < len; i++)
+ {
+ marks[i] = gtk_text_mark_new (NULL, TRUE);
+ gtk_text_mark_set_visible (marks[i], i % 2);
+ }
+ }
+
+ if (enable)
+ {
+ for (i = 0; i < len; i++)
+ {
+ GtkTextIter iter;
+
+ gtk_text_buffer_get_iter_at_offset (buffer, &iter, i);
+ gtk_text_buffer_add_mark (buffer, marks[i], &iter);
+ }
+
+ marks_timeout = g_timeout_add (16, toggle_mark, NULL);
+ }
+ else
+ {
+ for (i = 0; i < len; i++)
+ gtk_text_buffer_delete_mark (buffer, marks[i]);
+
+ if (marks_timeout)
+ g_source_remove (marks_timeout);
+ marks_timeout = 0;
+ }
+}
+
+static gboolean
+move_insert (gpointer data)
+{
+ GtkTextMark *mark;
+ GtkTextIter iter, start, end;
+
+ mark = gtk_text_buffer_get_insert (buffer);
+ gtk_text_buffer_get_iter_at_mark (buffer, &iter, mark);
+ gtk_text_buffer_get_bounds (buffer, &start, &end);
+
+ if (gtk_text_iter_equal (&iter, &end))
+ gtk_text_iter_assign (&iter, &start);
+ else
+ gtk_text_iter_forward_cursor_position (&iter);
+
+ gtk_text_buffer_place_cursor (buffer, &iter);
+
+ return G_SOURCE_CONTINUE;
+}
+
+static guint cursor_timeout;
+
+static void
+toggle_cursor (GtkToggleButton *button)
+{
+ gboolean enable;
+
+ enable = gtk_toggle_button_get_active (button);
+ if (enable)
+ cursor_timeout = g_timeout_add (16, move_insert, NULL);
+ else
+ {
+ if (cursor_timeout)
+ g_source_remove (cursor_timeout);
+ cursor_timeout = 0;
+ }
+}
+
+static GtkTextMark *the_mark;
+static GtkWidget *mark_check;
+static GtkWidget *mark_visible;
+static GtkWidget *position_spin;
+
+static void
+update_mark_exists (void)
+{
+ int pos;
+ GtkTextIter iter;
+
+ pos = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (position_spin));
+ gtk_text_buffer_get_iter_at_offset (buffer, &iter, pos);
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mark_check)))
+ gtk_text_buffer_add_mark (buffer, the_mark, &iter);
+ else
+ gtk_text_buffer_delete_mark (buffer, the_mark);
+}
+
+static void
+update_mark_visible (void)
+{
+ gtk_text_mark_set_visible (the_mark, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mark_visible)));
+}
+
+static void
+update_mark_position (void)
+{
+ int pos;
+ GtkTextIter iter;
+
+ pos = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (position_spin));
+ gtk_text_buffer_get_iter_at_offset (buffer, &iter, pos);
+
+ gtk_text_buffer_move_mark (buffer, the_mark, &iter);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *window, *sw, *box, *box2, *button;
+
+ gtk_init ();
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
+ g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+ box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
+
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_set_hexpand (sw, TRUE);
+ gtk_widget_set_vexpand (sw, TRUE);
+ gtk_container_add (GTK_CONTAINER (window), box);
+ gtk_container_add (GTK_CONTAINER (box), sw);
+
+ tv = gtk_text_view_new ();
+ gtk_container_add (GTK_CONTAINER (sw), tv);
+
+ buffer = gtk_text_buffer_new (NULL);
+ gtk_text_view_set_buffer (GTK_TEXT_VIEW (tv), buffer);
+
+ gtk_text_buffer_set_text (buffer, text, -1);
+
+ len = strlen (text);
+
+ box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
+ g_object_set (box, "margin-start", 10, "margin-end", 10, NULL);
+ gtk_container_add (GTK_CONTAINER (box), box2);
+
+ the_mark = gtk_text_mark_new ("my mark", TRUE);
+ box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
+ gtk_container_add (GTK_CONTAINER (box), box2);
+ mark_check = gtk_check_button_new_with_label ("Mark");
+ g_signal_connect (mark_check, "notify::active", G_CALLBACK (update_mark_exists), NULL);
+ gtk_container_add (GTK_CONTAINER (box2), mark_check);
+ mark_visible = gtk_check_button_new_with_label ("Visible");
+ g_signal_connect (mark_visible, "notify::active", G_CALLBACK (update_mark_visible), NULL);
+ gtk_container_add (GTK_CONTAINER (box2), mark_visible);
+ gtk_container_add (GTK_CONTAINER (box2), gtk_label_new ("Position:"));
+ position_spin = gtk_spin_button_new_with_range (0, len, 1);
+ g_signal_connect (position_spin, "value-changed", G_CALLBACK (update_mark_position), NULL);
+ gtk_container_add (GTK_CONTAINER (box2), position_spin);
+
+ box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
+ g_object_set (box, "margin-start", 10, "margin-end", 10, NULL);
+ gtk_container_add (GTK_CONTAINER (box), box2);
+
+ button = gtk_toggle_button_new_with_label ("Random marks");
+ g_signal_connect (button, "notify::active", G_CALLBACK (toggle_marks), NULL);
+ gtk_container_add (GTK_CONTAINER (box2), button);
+
+ button = gtk_toggle_button_new_with_label ("Wandering cursor");
+ g_signal_connect (button, "notify::active", G_CALLBACK (toggle_cursor), NULL);
+ gtk_container_add (GTK_CONTAINER (box2), button);
+
+ gtk_widget_show (window);
+
+ gtk_main ();
+
+ return 0;
+}