diff options
author | Timm Bäder <mail@baedert.org> | 2018-08-11 22:19:13 +0200 |
---|---|---|
committer | Timm Bäder <mail@baedert.org> | 2019-02-19 08:26:38 +0100 |
commit | 410eeec99720c741539ea9e41d7d9f1f54470f95 (patch) | |
tree | 2da0feacc8cebde5da4ab09eef96e64f47b0f8e8 | |
parent | d7974c40e178032dffc94ae29b20954c649c6ebf (diff) | |
download | gtk+-410eeec99720c741539ea9e41d7d9f1f54470f95.tar.gz |
Add test for widget transforms
-rw-r--r-- | tests/meson.build | 1 | ||||
-rw-r--r-- | tests/testwidgettransforms.c | 353 |
2 files changed, 354 insertions, 0 deletions
diff --git a/tests/meson.build b/tests/meson.build index dddd00c124..1f4c8ee8fc 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -123,6 +123,7 @@ gtk_tests = [ ['testpopupat'], ['testgaction'], ['testwidgetfocus'], + ['testwidgettransforms'], ['testcenterbox'], ['testgridbaseline'], ['showrendernode'], diff --git a/tests/testwidgettransforms.c b/tests/testwidgettransforms.c new file mode 100644 index 0000000000..63496472a6 --- /dev/null +++ b/tests/testwidgettransforms.c @@ -0,0 +1,353 @@ + + +#include <gtk/gtk.h> + +static const char *css = +"test>button {" +" all: unset; " +" background-color: white;" +" border: 30px solid teal;" +" margin: 40px;" +" padding: 40px;" +"}" +"test>button:hover {" +" background-color: blue;" +"}" +"test image {" +" background-color: purple;" +"}" +; + +/* Just so we can avoid a signal */ +GtkWidget *transform_tester; +GtkWidget *test_widget; +GtkWidget *test_child; +float scale = 1; +gboolean do_picking = TRUE; + +static const GdkRGBA RED = {1, 0, 0, 0.4}; +static const GdkRGBA GREEN = {0, 1, 0, 0.7}; +static const GdkRGBA BLUE = {0, 0, 1, 0.4}; +static const GdkRGBA BLACK = {0, 0, 0, 1 }; + + + +/* ######################################################################### */ +/* ############################## MatrixChooser ############################ */ +/* ######################################################################### */ + + +#define GTK_TYPE_MATRIX_CHOOSER (gtk_matrix_chooser_get_type ()) +G_DECLARE_FINAL_TYPE (GtkMatrixChooser, gtk_matrix_chooser, GTK, MATRIX_CHOOSER, GtkWidget) + +struct _GtkMatrixChooser +{ + GtkWidget parent_instance; +}; + +G_DEFINE_TYPE (GtkMatrixChooser, gtk_matrix_chooser, GTK_TYPE_WIDGET) + +static void +gtk_matrix_chooser_init (GtkMatrixChooser *self) +{ + gtk_widget_set_has_surface (GTK_WIDGET (self), FALSE); +} + +static void +gtk_matrix_chooser_class_init (GtkMatrixChooserClass *klass) +{ + +} + + +/* ######################################################################### */ +/* ############################# TransformTester ########################### */ +/* ######################################################################### */ + +#define TEST_WIDGET_MIN_SIZE 100 + +#define GTK_TYPE_TRANSFORM_TESTER (gtk_transform_tester_get_type ()) +G_DECLARE_FINAL_TYPE (GtkTransformTester, gtk_transform_tester, GTK, TRANSFORM_TESTER, GtkWidget); + +struct _GtkTransformTester +{ + GtkWidget parent_instance; + + GtkWidget *test_widget; + int pick_increase; +}; + +G_DEFINE_TYPE (GtkTransformTester, gtk_transform_tester, GTK_TYPE_WIDGET); + +static void +gtk_transform_tester_measure (GtkWidget *widget, + GtkOrientation orientation, + int for_size, + int *minimum, + int *natural, + int *minimum_baseline, + int *natural_baseline) +{ + GtkTransformTester *self = (GtkTransformTester *)widget; + + if (self->test_widget) + { + gtk_widget_measure (self->test_widget, orientation, for_size, + minimum, natural, NULL, NULL); + } +} + +static void +gtk_transform_tester_size_allocate (GtkWidget *widget, + int width, + int height, + int baseline) +{ + GtkTransformTester *self = (GtkTransformTester *)widget; + graphene_matrix_t global_transform; + int w, h; + + if (!self->test_widget) + return; + + scale += 2.5f; + + gtk_widget_measure (self->test_widget, GTK_ORIENTATION_HORIZONTAL, -1, + &w, NULL, NULL, NULL); + gtk_widget_measure (self->test_widget, GTK_ORIENTATION_VERTICAL, w, + &h, NULL, NULL, NULL); + + g_message ("%s: %d, %d", __FUNCTION__, w, h); + + graphene_matrix_init_identity (&global_transform); + + graphene_matrix_translate (&global_transform, &(graphene_point3d_t){ -w/2.0f, -h/2.0f, 0}); + graphene_matrix_rotate (&global_transform, scale, + graphene_vec3_z_axis ()); + + graphene_matrix_translate (&global_transform, &(graphene_point3d_t){ width / 2.0f, height / 2.0f, 0}); + + +#if 0 + gtk_widget_size_allocate (self->test_widget, + &(GtkAllocation){ (width- w) / 2, (height - h) / 2, w,h }, -1); +#else + gtk_widget_allocate (self->test_widget, + w, h, + -1, + &global_transform); +#endif +} + +static void +gtk_transform_tester_snapshot (GtkWidget *widget, + GtkSnapshot *snapshot) +{ + GtkTransformTester *self = (GtkTransformTester *)widget; + const int width = gtk_widget_get_width (widget); + const int height = gtk_widget_get_height (widget); + const int inc = self->pick_increase; + graphene_rect_t child_bounds; + graphene_rect_t self_bounds; + int x, y; + + GTK_WIDGET_CLASS (gtk_transform_tester_parent_class)->snapshot (widget, snapshot); + + if (!do_picking) + return; + gtk_widget_compute_bounds (self->test_widget, widget, &child_bounds); + gtk_widget_compute_bounds (self->test_widget, self->test_widget, &self_bounds); + + { + const struct { + graphene_point_t coords; + GdkRGBA color; + } points[4] = { + { self_bounds.origin, {1, 0, 0, 1} }, + { GRAPHENE_POINT_INIT (self_bounds.origin.x + self_bounds.size.width, self_bounds.origin.y), {0, 1, 0, 1} }, + { GRAPHENE_POINT_INIT (self_bounds.origin.x + self_bounds.size.width, self_bounds.origin.y + self_bounds.size.height), {0, 0, 1, 1} }, + { GRAPHENE_POINT_INIT (self_bounds.origin.x, self_bounds.origin.y + self_bounds.size.height), {1, 0, 1, 1} } + }; + + for (x = 0; x < G_N_ELEMENTS (points); x ++) + { + int px, py; + + gtk_widget_translate_coordinates (self->test_widget, widget, + points[x].coords.x, points[x].coords.y, + &px, &py); + + gtk_snapshot_append_color (snapshot, &points[x].color, + &GRAPHENE_RECT_INIT (px, py, + 4, + 4)); + } + } + + /* Now add custom drawing */ + for (x = 0; x < width; x += inc) + { + for (y = 0; y < height; y += inc) + { + const float px = x; + const float py = y; + GtkWidget *picked; +#if 1 + picked = gtk_widget_pick (widget, px, py); +#else + { + int dx, dy; + gtk_widget_translate_coordinates (widget, self->test_widget, px, py, &dx, &dy); + picked = gtk_widget_pick (self->test_widget, dx, dy); + } +#endif + + if (picked == self->test_widget) + gtk_snapshot_append_color (snapshot, &GREEN, + &GRAPHENE_RECT_INIT (px - (inc / 2), py - (inc / 2), inc, inc)); + else if (picked == test_child) + gtk_snapshot_append_color (snapshot, &BLUE, + &GRAPHENE_RECT_INIT (px - (inc / 2), py - (inc / 2), inc, inc)); + + else + gtk_snapshot_append_color (snapshot, &RED, + &GRAPHENE_RECT_INIT (px - (inc / 2), py - (inc / 2), inc, inc)); + } + } + + gtk_snapshot_append_color (snapshot, &BLACK, + &GRAPHENE_RECT_INIT (child_bounds.origin.x, + child_bounds.origin.y, + child_bounds.size.width, + 1)); + + gtk_snapshot_append_color (snapshot, &BLACK, + &GRAPHENE_RECT_INIT (child_bounds.origin.x + child_bounds.size.width, + child_bounds.origin.y, + 1, + child_bounds.size.height)); + + gtk_snapshot_append_color (snapshot, &BLACK, + &GRAPHENE_RECT_INIT (child_bounds.origin.x, + child_bounds.origin.y + child_bounds.size.height, + child_bounds.size.width, + 1)); + + gtk_snapshot_append_color (snapshot, &BLACK, + &GRAPHENE_RECT_INIT (child_bounds.origin.x, + child_bounds.origin.y, + 1, + child_bounds.size.height)); +} + +static void +gtk_transform_tester_init (GtkTransformTester *self) +{ + gtk_widget_set_has_surface (GTK_WIDGET (self), FALSE); + + self->pick_increase = 4; +} + +static void +gtk_transform_tester_class_init (GtkTransformTesterClass *klass) +{ + GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; + + widget_class->measure = gtk_transform_tester_measure; + widget_class->size_allocate = gtk_transform_tester_size_allocate; + widget_class->snapshot = gtk_transform_tester_snapshot; + + gtk_widget_class_set_css_name (widget_class, "test"); +} + +static gboolean +tick_cb (GtkWidget *widget, + GdkFrameClock *frame_clock, + gpointer user_data) +{ + gtk_widget_queue_allocate (widget); + + return G_SOURCE_CONTINUE; +} + +static void +gtk_transform_tester_set_test_widget (GtkTransformTester *self, + GtkWidget *test_widget) +{ + g_assert (!self->test_widget); + + self->test_widget = test_widget; + gtk_widget_set_parent (test_widget, (GtkWidget *)self); + + gtk_widget_add_tick_callback (GTK_WIDGET (self), tick_cb, NULL, NULL); +} + +static void +toggled_cb (GtkToggleButton *source, + gpointer user_data) +{ + do_picking = gtk_toggle_button_get_active (source); +} + +int +main (int argc, char **argv) +{ + GtkWidget *window; + GtkWidget *matrix_chooser; + GtkWidget *box; + GtkWidget *titlebar; + GtkWidget *toggle_button; + GtkCssProvider *provider; + + gtk_init (); + + provider = gtk_css_provider_new (); + gtk_css_provider_load_from_data (provider, css, -1); + gtk_style_context_add_provider_for_display (gdk_display_get_default (), + GTK_STYLE_PROVIDER (provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + matrix_chooser = g_object_new (GTK_TYPE_MATRIX_CHOOSER, NULL); + transform_tester = g_object_new (GTK_TYPE_TRANSFORM_TESTER, NULL); + box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + titlebar = gtk_header_bar_new (); + + gtk_window_set_titlebar (GTK_WINDOW (window), titlebar); + gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (titlebar), TRUE); + + toggle_button = gtk_toggle_button_new (); + gtk_button_set_label (GTK_BUTTON (toggle_button), "Picking"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle_button), do_picking); + g_signal_connect (toggle_button, "toggled", G_CALLBACK (toggled_cb), NULL); + gtk_container_add (GTK_CONTAINER (titlebar), toggle_button); + + test_widget = gtk_button_new (); + gtk_widget_set_size_request (test_widget, TEST_WIDGET_MIN_SIZE, TEST_WIDGET_MIN_SIZE); + gtk_widget_set_halign (test_widget, GTK_ALIGN_CENTER); + gtk_widget_set_valign (test_widget, GTK_ALIGN_CENTER); + + + test_child = gtk_image_new_from_icon_name ("corebird"); + gtk_widget_set_halign (test_child, GTK_ALIGN_CENTER); + gtk_widget_set_valign (test_child, GTK_ALIGN_CENTER); + gtk_widget_set_size_request (test_child, TEST_WIDGET_MIN_SIZE / 2, TEST_WIDGET_MIN_SIZE / 2); + gtk_container_add (GTK_CONTAINER (test_widget), test_child); + + + gtk_transform_tester_set_test_widget (GTK_TRANSFORM_TESTER (transform_tester), test_widget); + + gtk_widget_set_vexpand (transform_tester, TRUE); + gtk_container_add (GTK_CONTAINER (box), transform_tester); + gtk_container_add (GTK_CONTAINER (box), matrix_chooser); + gtk_container_add (GTK_CONTAINER (window), box); + + gtk_window_set_default_size ((GtkWindow *)window, 200, 200); + g_signal_connect (window, "close-request", G_CALLBACK (gtk_main_quit), NULL); + gtk_widget_show (window); + + gtk_main (); + + return 0; +} |