From e5e08cc0d77c298bcc0af2ec2f91b1c46c5aeca6 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 6 Mar 2023 20:59:14 -0500 Subject: wip: Add a drag surface resize demo Make the one of the image sources in the clipboard demo have a throbbing drag icon. --- demos/gtk-demo/clipboard.c | 22 ++++++ demos/gtk-demo/clipboard.ui | 1 + demos/gtk-demo/gtkthrobber.c | 174 +++++++++++++++++++++++++++++++++++++++++++ demos/gtk-demo/gtkthrobber.h | 36 +++++++++ demos/gtk-demo/meson.build | 1 + 5 files changed, 234 insertions(+) create mode 100644 demos/gtk-demo/gtkthrobber.c create mode 100644 demos/gtk-demo/gtkthrobber.h diff --git a/demos/gtk-demo/clipboard.c b/demos/gtk-demo/clipboard.c index 672a51ac44..07466069ec 100644 --- a/demos/gtk-demo/clipboard.c +++ b/demos/gtk-demo/clipboard.c @@ -12,6 +12,7 @@ #include #include #include "demoimage.h" +#include "gtkthrobber.h" static void copy_button_clicked (GtkStack *source_stack, @@ -364,6 +365,26 @@ drag_prepare (GtkDragSource *drag_source, return gdk_content_provider_new_for_value (&value); } +static void +drag_begin (GtkDragSource *drag_source, + GdkDrag *drag, + gpointer user_data) +{ + GtkWidget *button; + GdkFrameClock *clock; + GdkPaintable *paintable; + + button = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (drag_source)); + clock = gtk_widget_get_frame_clock (button); + paintable = gtk_throbber_new (clock, + "/transparent/portland-rose.jpg", + 0.02, 0.1, + drag); + + gtk_drag_source_set_icon (drag_source, paintable, 10, 10); + g_object_unref (paintable); +} + GtkWidget * do_clipboard (GtkWidget *do_widget) { @@ -384,6 +405,7 @@ do_clipboard (GtkWidget *do_widget) gtk_builder_cscope_add_callback (scope, open_folder_cb); gtk_builder_cscope_add_callback (scope, on_drop); gtk_builder_cscope_add_callback (scope, drag_prepare); + gtk_builder_cscope_add_callback (scope, drag_begin); builder = gtk_builder_new (); gtk_builder_set_scope (builder, scope); gtk_builder_add_from_resource (builder, "/clipboard/clipboard.ui", NULL); diff --git a/demos/gtk-demo/clipboard.ui b/demos/gtk-demo/clipboard.ui index a373537f6b..6f4cf287a9 100644 --- a/demos/gtk-demo/clipboard.ui +++ b/demos/gtk-demo/clipboard.ui @@ -91,6 +91,7 @@ + diff --git a/demos/gtk-demo/gtkthrobber.c b/demos/gtk-demo/gtkthrobber.c new file mode 100644 index 0000000000..c12df51b62 --- /dev/null +++ b/demos/gtk-demo/gtkthrobber.c @@ -0,0 +1,174 @@ +/* + * Copyright © 2018 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: Benjamin Otte + */ + +#include "gtkthrobber.h" + +#include "gtk.h" + +struct _GtkThrobber +{ + GObject parent_instance; + + GdkFrameClock *clock; + GdkTexture *texture; + guint clock_tick_id; + + float min, max, scale, delta; + float delta2, hot; + + GdkDrag *drag; +}; + +struct _GtkThrobberClass +{ + GObjectClass parent_class; +}; + +static void +gtk_throbber_paintable_snapshot (GdkPaintable *paintable, + GdkSnapshot *snapshot, + double width, + double height) +{ + GtkThrobber *self = GTK_THROBBER (paintable); + + gtk_snapshot_append_texture (snapshot, self->texture, &GRAPHENE_RECT_INIT (0, 0, width, height)); +} + +static int +gtk_throbber_paintable_get_intrinsic_width (GdkPaintable *paintable) +{ + GtkThrobber *self = GTK_THROBBER (paintable); + + return gdk_texture_get_width (self->texture) * self->scale; +} + +static int +gtk_throbber_paintable_get_intrinsic_height (GdkPaintable *paintable) +{ + GtkThrobber *self = GTK_THROBBER (paintable); + + return gdk_texture_get_height (self->texture) * self->scale; +} + +static void +gtk_throbber_paintable_init (GdkPaintableInterface *iface) +{ + iface->snapshot = gtk_throbber_paintable_snapshot; + iface->get_intrinsic_width = gtk_throbber_paintable_get_intrinsic_width; + iface->get_intrinsic_height = gtk_throbber_paintable_get_intrinsic_height; +} + +G_DEFINE_TYPE_EXTENDED (GtkThrobber, gtk_throbber, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE, + gtk_throbber_paintable_init)) + +static void +gtk_throbber_dispose (GObject *object) +{ + GtkThrobber *self = GTK_THROBBER (object); + + gdk_frame_clock_end_updating (self->clock); + g_signal_handler_disconnect (self->clock, self->clock_tick_id); + self->clock_tick_id = 0; + + g_clear_object (&self->clock); + g_clear_object (&self->texture); + g_clear_object (&self->drag); + + G_OBJECT_CLASS (gtk_throbber_parent_class)->dispose (object); +} + +static void +gtk_throbber_class_init (GtkThrobberClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->dispose = gtk_throbber_dispose; +} + +static void +gtk_throbber_init (GtkThrobber *self) +{ +} + +static void +on_frame_clock_update (GdkFrameClock *clock, + GtkThrobber *self) +{ + self->scale += self->delta; + if (self->scale >= self->max) + { + self->scale = self->max; + self->delta = - self->delta; + } + else if (self->scale <= self->min) + { + self->scale = self->min; + self->delta = - self->delta; + } + + self->hot += self->delta2; + if (self->hot >= 1.) + { + self->hot = 1.; + self->delta2 = - self->delta2; + } + else if (self->hot <= 0.) + { + self->hot = 0.; + self->delta2 = - self->delta2; + } + + gdk_paintable_invalidate_size (GDK_PAINTABLE (self)); + + gdk_drag_set_hotspot (self->drag, + gdk_texture_get_width (self->texture) * self->scale * self->hot, + gdk_texture_get_height (self->texture) * self->scale * self->hot); +} + + +GdkPaintable * +gtk_throbber_new (GdkFrameClock *clock, + const char *resource_path, + float min, + float max, + GdkDrag *drag) +{ + GtkThrobber *self; + + self = g_object_new (GTK_TYPE_THROBBER, NULL); + + self->clock = g_object_ref (clock); + self->texture = gdk_texture_new_from_resource (resource_path); + self->drag = g_object_ref (drag); + self->min = min; + self->max = max; + self->scale = min; + self->delta = (max - min) / (15 * 16); + self->delta2 = 1. / (10 * 16); + self->hot = 0.; + + self->clock_tick_id = g_signal_connect (self->clock, "update", + G_CALLBACK (on_frame_clock_update), self); + + gdk_frame_clock_begin_updating (self->clock); + + return GDK_PAINTABLE (self); +} diff --git a/demos/gtk-demo/gtkthrobber.h b/demos/gtk-demo/gtkthrobber.h new file mode 100644 index 0000000000..6011c63742 --- /dev/null +++ b/demos/gtk-demo/gtkthrobber.h @@ -0,0 +1,36 @@ +/* + * Copyright © 2023 Matthias Clasen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: Benjamin Otte + */ + +#pragma once + +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_THROBBER (gtk_throbber_get_type ()) + +G_DECLARE_FINAL_TYPE (GtkThrobber, gtk_throbber, GTK, THROBBER, GObject) + +GdkPaintable * gtk_throbber_new (GdkFrameClock *clock, + const char *resource_path, + float min, + float max, + GdkDrag *drag); + +G_END_DECLS diff --git a/demos/gtk-demo/meson.build b/demos/gtk-demo/meson.build index b1c21a9f9b..a0be24e73c 100644 --- a/demos/gtk-demo/meson.build +++ b/demos/gtk-demo/meson.build @@ -134,6 +134,7 @@ extra_demo_sources = files([ 'unicode-names.c', 'suggestionentry.c', 'language-names.c', + 'gtkthrobber.c', ]) if os_unix -- cgit v1.2.1