gtk-demo: Add rotation to the scaling demo

Closing in on eog :)
This commit is contained in:
Matthias Clasen 2023-03-11 18:56:08 +01:00
parent 6dd273c3f1
commit dc50c790c5
3 changed files with 73 additions and 6 deletions

View File

@ -5,7 +5,8 @@ enum
{ {
PROP_TEXTURE = 1, PROP_TEXTURE = 1,
PROP_FILTER, PROP_FILTER,
PROP_SCALE PROP_SCALE,
PROP_ANGLE,
}; };
struct _Demo3Widget struct _Demo3Widget
@ -14,6 +15,7 @@ struct _Demo3Widget
GdkTexture *texture; GdkTexture *texture;
float scale; float scale;
float angle;
GskScalingFilter filter; GskScalingFilter filter;
GtkWidget *menu; GtkWidget *menu;
@ -30,6 +32,7 @@ static void
demo3_widget_init (Demo3Widget *self) demo3_widget_init (Demo3Widget *self)
{ {
self->scale = 1.f; self->scale = 1.f;
self->angle = 0.f;
self->filter = GSK_SCALING_FILTER_LINEAR; self->filter = GSK_SCALING_FILTER_LINEAR;
gtk_widget_init_template (GTK_WIDGET (self)); gtk_widget_init_template (GTK_WIDGET (self));
} }
@ -52,21 +55,34 @@ demo3_widget_snapshot (GtkWidget *widget,
{ {
Demo3Widget *self = DEMO3_WIDGET (widget); Demo3Widget *self = DEMO3_WIDGET (widget);
int x, y, width, height; int x, y, width, height;
double w, h; double w, h, w2, h2;
GskRenderNode *node; GskRenderNode *node;
width = gtk_widget_get_width (widget); width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget); height = gtk_widget_get_height (widget);
w = self->scale * gdk_texture_get_width (self->texture); w2 = w = self->scale * gdk_texture_get_width (self->texture);
h = self->scale * gdk_texture_get_height (self->texture); h2 = h = self->scale * gdk_texture_get_height (self->texture);
x = MAX (0, (width - ceil (w)) / 2); if (G_APPROX_VALUE (self->angle, 90.f, FLT_EPSILON) ||
y = MAX (0, (height - ceil (h)) / 2); G_APPROX_VALUE (self->angle, 270.f, FLT_EPSILON))
{
double s;
s = w2;
w2 = h2;
h2 = s;
}
x = MAX (0, (width - ceil (w2)) / 2);
y = MAX (0, (height - ceil (h2)) / 2);
gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (0, 0, width, height)); gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_save (snapshot); gtk_snapshot_save (snapshot);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y)); gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (w2 / 2, h2 / 2));
gtk_snapshot_rotate (snapshot, self->angle);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (- w / 2, - h / 2));
node = gsk_texture_scale_node_new (self->texture, node = gsk_texture_scale_node_new (self->texture,
&GRAPHENE_RECT_INIT (0, 0, w, h), &GRAPHENE_RECT_INIT (0, 0, w, h),
self->filter); self->filter);
@ -132,6 +148,11 @@ demo3_widget_set_property (GObject *object,
gtk_widget_queue_resize (GTK_WIDGET (object)); gtk_widget_queue_resize (GTK_WIDGET (object));
break; break;
case PROP_ANGLE:
self->angle = fmodf (g_value_get_float (value), 360.f);
gtk_widget_queue_resize (GTK_WIDGET (object));
break;
case PROP_FILTER: case PROP_FILTER:
self->filter = g_value_get_enum (value); self->filter = g_value_get_enum (value);
gtk_widget_queue_resize (GTK_WIDGET (object)); gtk_widget_queue_resize (GTK_WIDGET (object));
@ -161,6 +182,10 @@ demo3_widget_get_property (GObject *object,
g_value_set_float (value, self->scale); g_value_set_float (value, self->scale);
break; break;
case PROP_ANGLE:
g_value_set_float (value, self->angle);
break;
case PROP_FILTER: case PROP_FILTER:
g_value_set_enum (value, self->filter); g_value_set_enum (value, self->filter);
break; break;
@ -208,6 +233,19 @@ zoom_cb (GtkWidget *widget,
g_object_set (widget, "scale", scale, NULL); g_object_set (widget, "scale", scale, NULL);
} }
static void
rotate_cb (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
Demo3Widget *self = DEMO3_WIDGET (widget);
int angle;
g_variant_get (parameter, "i", &angle);
g_object_set (widget, "angle", fmodf (self->angle + angle, 360.f), NULL);
}
static void static void
demo3_widget_class_init (Demo3WidgetClass *class) demo3_widget_class_init (Demo3WidgetClass *class)
{ {
@ -232,6 +270,11 @@ demo3_widget_class_init (Demo3WidgetClass *class)
0.0, 10.0, 1.0, 0.0, 10.0, 1.0,
G_PARAM_READWRITE)); G_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_ANGLE,
g_param_spec_float ("angle", NULL, NULL,
0.0, 360.0, 0.0,
G_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_FILTER, g_object_class_install_property (object_class, PROP_FILTER,
g_param_spec_enum ("filter", NULL, NULL, g_param_spec_enum ("filter", NULL, NULL,
GSK_TYPE_SCALING_FILTER, GSK_SCALING_FILTER_LINEAR, GSK_TYPE_SCALING_FILTER, GSK_SCALING_FILTER_LINEAR,
@ -241,6 +284,7 @@ demo3_widget_class_init (Demo3WidgetClass *class)
gtk_widget_class_install_action (widget_class, "zoom.in", NULL, zoom_cb); gtk_widget_class_install_action (widget_class, "zoom.in", NULL, zoom_cb);
gtk_widget_class_install_action (widget_class, "zoom.out", NULL, zoom_cb); gtk_widget_class_install_action (widget_class, "zoom.out", NULL, zoom_cb);
gtk_widget_class_install_action (widget_class, "zoom.reset", NULL, zoom_cb); gtk_widget_class_install_action (widget_class, "zoom.reset", NULL, zoom_cb);
gtk_widget_class_install_action (widget_class, "rotate", "i", rotate_cb);
gtk_widget_class_set_template_from_resource (widget_class, "/menu/demo3widget.ui"); gtk_widget_class_set_template_from_resource (widget_class, "/menu/demo3widget.ui");
gtk_widget_class_bind_template_child (widget_class, Demo3Widget, menu); gtk_widget_class_bind_template_child (widget_class, Demo3Widget, menu);

View File

@ -12,6 +12,11 @@
<attribute name="label">11</attribute> <attribute name="label">11</attribute>
<attribute name="action">zoom.reset</attribute> <attribute name="action">zoom.reset</attribute>
</item> </item>
<item>
<attribute name="label">Rotate</attribute>
<attribute name="action">rotate</attribute>
<attribute name="target" type="i">90</attribute>
</item>
</menu> </menu>
<template class="Demo3Widget"> <template class="Demo3Widget">
<child> <child>

View File

@ -71,6 +71,19 @@ open_file (GtkWidget *picker,
g_object_unref (dialog); g_object_unref (dialog);
} }
static void
rotate (GtkWidget *button,
GtkWidget *demo)
{
float angle;
g_object_get (demo, "angle", &angle, NULL);
angle = fmodf (angle + 90.f, 360.f);
g_object_set (demo, "angle", angle, NULL);
}
GtkWidget * GtkWidget *
do_menu (GtkWidget *do_widget) do_menu (GtkWidget *do_widget)
{ {
@ -111,6 +124,11 @@ do_menu (GtkWidget *do_widget)
g_signal_connect (button, "clicked", G_CALLBACK (open_file), widget); g_signal_connect (button, "clicked", G_CALLBACK (open_file), widget);
gtk_box_append (GTK_BOX (box2), button); gtk_box_append (GTK_BOX (box2), button);
button = gtk_button_new_from_icon_name ("object-rotate-right-symbolic");
gtk_widget_set_tooltip_text (button, "Rotate");
g_signal_connect (button, "clicked", G_CALLBACK (rotate), widget);
gtk_box_append (GTK_BOX (box2), button);
scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0.01, 10.0, 0.1); scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0.01, 10.0, 0.1);
gtk_widget_set_tooltip_text (scale, "Zoom"); gtk_widget_set_tooltip_text (scale, "Zoom");
gtk_range_set_value (GTK_RANGE (scale), 1.0); gtk_range_set_value (GTK_RANGE (scale), 1.0);