[gtk/matthiasc/for-master] gtk-demo: Reorganize the dnd demo



commit 965483eb67bc7b67d6f5ffa63266235e1a329d2e
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri May 22 12:35:18 2020 -0400

    gtk-demo: Reorganize the dnd demo
    
    Introduce a CanvasItem widget to make things a
    bit less ad hoc.

 demos/gtk-demo/dnd.c | 381 ++++++++++++++++++++++++++++-----------------------
 1 file changed, 208 insertions(+), 173 deletions(-)
---
diff --git a/demos/gtk-demo/dnd.c b/demos/gtk-demo/dnd.c
index 5d7e11273c..fb164e41a2 100644
--- a/demos/gtk-demo/dnd.c
+++ b/demos/gtk-demo/dnd.c
@@ -7,6 +7,186 @@
 
 #include <gtk/gtk.h>
 
+G_DECLARE_FINAL_TYPE (CanvasItem, canvas_item, CANVAS, ITEM, GtkWidget)
+
+struct _CanvasItem {
+  GtkWidget parent;
+
+  GtkWidget *label;
+
+  double x, y;
+  double angle;
+  double delta;
+};
+
+struct _CanvasItemClass {
+  GtkWidgetClass parent_class;
+};
+
+G_DEFINE_TYPE (CanvasItem, canvas_item, GTK_TYPE_WIDGET)
+
+static int n_items = 0;
+
+static void
+set_color (CanvasItem *item,
+           GdkRGBA    *color)
+{
+  char *css;
+  char *str;
+  GtkStyleContext *context;
+  GtkCssProvider *provider;
+
+  str = gdk_rgba_to_string (color);
+  css = g_strdup_printf ("* { background: %s; padding: 10px; }", str);
+
+  context = gtk_widget_get_style_context (item->label);
+  provider = g_object_get_data (G_OBJECT (context), "style-provider");
+  if (provider)
+    gtk_style_context_remove_provider (context, GTK_STYLE_PROVIDER (provider));
+
+  provider = gtk_css_provider_new ();
+  gtk_css_provider_load_from_data (provider, css, -1);
+  gtk_style_context_add_provider (gtk_widget_get_style_context (item->label), GTK_STYLE_PROVIDER (provider), 
800);
+  g_object_set_data_full (G_OBJECT (context), "style-provider", provider, g_object_unref);
+
+  g_free (str);
+  g_free (css);
+}
+
+static gboolean
+item_drag_drop (GtkDropTarget *dest,
+                const GValue  *value,
+                double         x,
+                double         y)
+{
+  CanvasItem *item = CANVAS_ITEM (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest)));
+
+  set_color (item, g_value_get_boxed (value));
+
+  return TRUE;
+}
+
+static void
+apply_transform (CanvasItem *item)
+{
+  GtkWidget *canvas = gtk_widget_get_parent (GTK_WIDGET (item));
+  GskTransform *transform;
+
+  transform = gsk_transform_rotate (gsk_transform_translate (NULL, &(graphene_point_t){item->x, item->y}),
+                                    item->angle + item->delta);
+  gtk_fixed_set_child_transform (GTK_FIXED (canvas), GTK_WIDGET (item), transform);
+  gsk_transform_unref (transform);
+}
+
+static void
+angle_changed (GtkGestureRotate *gesture,
+               double            angle,
+               double            delta)
+{
+  CanvasItem *item = CANVAS_ITEM (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture)));
+
+  item->delta = angle / M_PI * 180.0;
+
+  apply_transform (item);
+}
+
+static void
+rotate_done (GtkGesture *gesture)
+{
+  CanvasItem *item = CANVAS_ITEM (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture)));
+
+  item->angle = item->angle + item->delta;
+  item->delta = 0;
+}
+
+static void
+click_done (GtkGesture *gesture)
+{
+  GtkWidget *item = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
+  GtkWidget *canvas = gtk_widget_get_parent (item);
+  GtkWidget *last_child;
+
+  last_child = gtk_widget_get_last_child (canvas);
+  if (item != last_child)
+    gtk_widget_insert_after (item, canvas, last_child);
+}
+
+static void
+canvas_item_init (CanvasItem *item)
+{
+  char *text;
+  char *id;
+  GdkRGBA rgba;
+  GtkDropTarget *dest;
+  GtkGesture *gesture;
+
+  n_items++;
+
+  text = g_strdup_printf ("Item %d", n_items);
+  item->label = gtk_label_new (text);
+  g_free (text);
+
+  gtk_widget_set_parent (item->label, GTK_WIDGET (item));
+
+  gtk_widget_add_css_class (item->label, "frame");
+
+  id = g_strdup_printf ("item%d", n_items);
+  gtk_widget_set_name (item->label, id);
+  g_free (id);
+
+  gdk_rgba_parse (&rgba, "yellow");
+  set_color (item, &rgba);
+
+  item->x = 0;
+  item->y = 0;
+  item->angle = 0;
+
+  dest = gtk_drop_target_new (GDK_TYPE_RGBA, GDK_ACTION_COPY);
+  g_signal_connect (dest, "drop", G_CALLBACK (item_drag_drop), NULL);
+  gtk_widget_add_controller (GTK_WIDGET (item), GTK_EVENT_CONTROLLER (dest));
+
+  gesture = gtk_gesture_rotate_new ();
+  g_signal_connect (gesture, "angle-changed", G_CALLBACK (angle_changed), NULL);
+  g_signal_connect (gesture, "end", G_CALLBACK (rotate_done), NULL);
+  gtk_widget_add_controller (GTK_WIDGET (item), GTK_EVENT_CONTROLLER (gesture));
+
+  gesture = gtk_gesture_click_new ();
+  g_signal_connect (gesture, "released", G_CALLBACK (click_done), NULL);
+  gtk_widget_add_controller (GTK_WIDGET (item), GTK_EVENT_CONTROLLER (gesture));
+}
+
+static void
+canvas_item_dispose (GObject *object)
+{
+  CanvasItem *item = CANVAS_ITEM (object);
+
+  g_clear_pointer (&item->label, gtk_widget_unparent);
+
+  G_OBJECT_CLASS (canvas_item_parent_class)->dispose (object);
+}
+
+static void
+canvas_item_class_init (CanvasItemClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+
+  object_class->dispose = canvas_item_dispose;
+
+  gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
+}
+
+static GtkWidget *
+canvas_item_new (double x,
+                 double y)
+{
+  CanvasItem *item = g_object_new (canvas_item_get_type (), NULL);
+  item->x = x;
+  item->y = y;
+
+  return GTK_WIDGET (item);
+}
+
 static GdkContentProvider *
 prepare (GtkDragSource *source,
          double         x,
@@ -18,7 +198,8 @@ prepare (GtkDragSource *source,
   canvas = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));
   item = gtk_widget_pick (canvas, x, y, GTK_PICK_DEFAULT);
 
-  if (!GTK_IS_LABEL (item))
+  item = gtk_widget_get_ancestor (item, canvas_item_get_type ());
+  if (!item)
     return NULL;
 
   g_object_set_data (G_OBJECT (canvas), "dragged-item", item);
@@ -66,47 +247,25 @@ drag_cancel (GtkDragSource       *source,
   return FALSE;
 }
 
-typedef struct {
-  double x, y;
-  double angle;
-  double delta;
-} TransformData;
-
-static void
-apply_transform (GtkWidget *item)
-{
-  GtkWidget *canvas = gtk_widget_get_parent (item);
-  TransformData *data;
-  GskTransform *transform;
-
-  data = g_object_get_data (G_OBJECT (item), "transform-data");
-  transform = gsk_transform_rotate (gsk_transform_translate (NULL, &(graphene_point_t){data->x, data->y}),
-                                    data->angle + data->delta);
-  gtk_fixed_set_child_transform (GTK_FIXED (canvas), item, transform);
-  gsk_transform_unref (transform);
-}
-
 static gboolean
 drag_drop (GtkDropTarget *target,
            const GValue  *value,
            double         x,
            double         y)
 {
-  GtkWidget *item;
-  TransformData *transform_data;
+  CanvasItem *item;
   GtkWidget *canvas;
   GtkWidget *last_child;
 
   item = g_value_get_object (value);
-  transform_data = g_object_get_data (G_OBJECT (item), "transform-data");
 
-  transform_data->x = x;
-  transform_data->y = y;
+  item->x = x;
+  item->y = y;
 
-  canvas = gtk_widget_get_parent (item);
+  canvas = gtk_widget_get_parent (GTK_WIDGET (item));
   last_child = gtk_widget_get_last_child (canvas);
-  if (item != last_child)
-    gtk_widget_insert_after (item, canvas, last_child);
+  if (GTK_WIDGET (item) != last_child)
+    gtk_widget_insert_after (GTK_WIDGET (item), canvas, last_child);
 
   apply_transform (item);
 
@@ -115,8 +274,6 @@ drag_drop (GtkDropTarget *target,
 
 static double pos_x, pos_y;
 
-static GtkWidget * canvas_item_new (double x, double y);
-
 static void
 new_item_cb (GtkWidget *button, gpointer data)
 {
@@ -125,7 +282,7 @@ new_item_cb (GtkWidget *button, gpointer data)
 
   item = canvas_item_new (pos_x, pos_y);
   gtk_fixed_put (GTK_FIXED (canvas), item, 0, 0);
-  apply_transform (item);
+  apply_transform (CANVAS_ITEM (item));
 
   gtk_popover_popdown (GTK_POPOVER (gtk_widget_get_ancestor (button, GTK_TYPE_POPOVER)));
 }
@@ -134,14 +291,14 @@ static void
 edit_label_done (GtkWidget *entry, gpointer data)
 {
   GtkWidget *canvas = gtk_widget_get_parent (entry);
-  GtkWidget *label;
+  CanvasItem *item;
   int x, y;
 
   gtk_fixed_get_child_position (GTK_FIXED (canvas), entry, &x, &y);
 
-  label = GTK_WIDGET (g_object_get_data (G_OBJECT (entry), "label"));
-  gtk_label_set_text (GTK_LABEL (label), gtk_editable_get_text (GTK_EDITABLE (entry)));
-  gtk_widget_show (label);
+  item = CANVAS_ITEM (g_object_get_data (G_OBJECT (entry), "item"));
+  gtk_label_set_text (GTK_LABEL (item->label), gtk_editable_get_text (GTK_EDITABLE (entry)));
+  gtk_widget_show (GTK_WIDGET (item));
 
   gtk_fixed_remove (GTK_FIXED (canvas), entry);
 }
@@ -150,23 +307,24 @@ static void
 edit_cb (GtkWidget *button, GtkWidget *child)
 {
   GtkWidget *canvas = gtk_widget_get_parent (child);
+  CanvasItem *item = CANVAS_ITEM (child);
+  GtkWidget *entry;
   int x, y;
 
   gtk_fixed_get_child_position (GTK_FIXED (canvas), child, &x, &y);
 
-  if (GTK_IS_LABEL (child))
-    {
-      GtkWidget *entry = gtk_entry_new ();
+  entry = gtk_entry_new ();
 
-      g_object_set_data (G_OBJECT (entry), "label", child);
+  g_object_set_data (G_OBJECT (entry), "item", item);
 
-      gtk_editable_set_text (GTK_EDITABLE (entry), gtk_label_get_text (GTK_LABEL (child)));
-      gtk_editable_set_width_chars (GTK_EDITABLE (entry), 12);
-      g_signal_connect (entry, "activate", G_CALLBACK (edit_label_done), NULL);
-      gtk_fixed_put (GTK_FIXED (canvas), entry, x, y);
-      gtk_widget_grab_focus (entry);
-      gtk_widget_hide (child);
-    }
+  gtk_editable_set_text (GTK_EDITABLE (entry),
+                         gtk_label_get_text (GTK_LABEL (item->label)));
+
+  gtk_editable_set_width_chars (GTK_EDITABLE (entry), 12);
+  g_signal_connect (entry, "activate", G_CALLBACK (edit_label_done), NULL);
+  gtk_fixed_put (GTK_FIXED (canvas), entry, x, y);
+  gtk_widget_grab_focus (entry);
+  gtk_widget_hide (child);
 
   if (button)
     gtk_popover_popdown (GTK_POPOVER (gtk_widget_get_ancestor (button, GTK_TYPE_POPOVER)));
@@ -194,6 +352,7 @@ pressed_cb (GtkGesture *gesture,
 
   widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
   child = gtk_widget_pick (widget, x, y, GTK_PICK_DEFAULT);
+  child = gtk_widget_get_ancestor (child, canvas_item_get_type ());
 
   if (gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture)) == GDK_BUTTON_SECONDARY)
     {
@@ -250,6 +409,7 @@ released_cb (GtkGesture *gesture,
 
   widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
   child = gtk_widget_pick (widget, x, y, 0);
+  child = gtk_widget_get_ancestor (child, canvas_item_get_type ());
 
   if (gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture)) == GDK_BUTTON_PRIMARY)
     {
@@ -292,131 +452,6 @@ canvas_new (void)
   return canvas;
 }
 
-static void
-set_color (GtkWidget *item,
-           GdkRGBA   *color)
-{
-  char *css;
-  char *str;
-  GtkStyleContext *context;
-  GtkCssProvider *provider;
-
-  str = gdk_rgba_to_string (color);
-  css = g_strdup_printf ("* { background: %s; padding: 10px; }", str);
-
-  context = gtk_widget_get_style_context (item);
-  provider = g_object_get_data (G_OBJECT (context), "style-provider");
-  if (provider)
-    gtk_style_context_remove_provider (context, GTK_STYLE_PROVIDER (provider));
-
-  provider = gtk_css_provider_new ();
-  gtk_css_provider_load_from_data (provider, css, -1);
-  gtk_style_context_add_provider (gtk_widget_get_style_context (item), GTK_STYLE_PROVIDER (provider), 800);
-  g_object_set_data_full (G_OBJECT (context), "style-provider", provider, g_object_unref);
-
-  g_free (str);
-  g_free (css);
-}
-
-static gboolean
-item_drag_drop (GtkDropTarget *dest,
-                const GValue  *value,
-                double         x,
-                double         y)
-{
-  GtkWidget *item = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
-
-  set_color (item, g_value_get_boxed (value));
-
-  return TRUE;
-}
-
-static void
-angle_changed (GtkGestureRotate *gesture,
-               double            angle,
-               double            delta)
-{
-  GtkWidget *item = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
-  TransformData *data = g_object_get_data (G_OBJECT (item), "transform-data");
-
-  data->delta = angle / M_PI * 180.0;
-
-  apply_transform (item);
-}
-
-static void
-rotate_done (GtkGesture *gesture)
-{
-  GtkWidget *item = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
-  TransformData *data = g_object_get_data (G_OBJECT (item), "transform-data");
-
-  data->angle = data->angle + data->delta;
-  data->delta = 0;
-}
-
-static void
-click_done (GtkGesture *gesture)
-{
-  GtkWidget *item = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
-  GtkWidget *canvas = gtk_widget_get_parent (item);
-  GtkWidget *last_child;
-
-  last_child = gtk_widget_get_last_child (canvas);
-  if (item != last_child)
-    gtk_widget_insert_after (item, canvas, last_child);
-}
-
-static int n_items = 0;
-
-static GtkWidget *
-canvas_item_new (double x,
-                 double y)
-{
-  GtkWidget *widget;
-  char *label;
-  char *id;
-  TransformData *transform_data;
-  GdkRGBA rgba;
-  GtkDropTarget *dest;
-  GtkGesture *gesture;
-
-  n_items++;
-
-  label = g_strdup_printf ("Item %d", n_items);
-  id = g_strdup_printf ("item%d", n_items);
-
-  gdk_rgba_parse (&rgba, "yellow");
-
-  widget = gtk_label_new (label);
-  gtk_widget_add_css_class (widget, "frame");
-  gtk_widget_set_name (widget, id);
-
-  set_color (widget, &rgba);
-  transform_data = g_new0 (TransformData, 1);
-  transform_data->x = x;
-  transform_data->y = y;
-  transform_data->angle = 0.0;
-  g_object_set_data_full (G_OBJECT (widget), "transform-data", transform_data, g_free);
-
-  g_free (label);
-  g_free (id);
-
-  dest = gtk_drop_target_new (GDK_TYPE_RGBA, GDK_ACTION_COPY);
-  g_signal_connect (dest, "drop", G_CALLBACK (item_drag_drop), NULL);
-  gtk_widget_add_controller (widget, GTK_EVENT_CONTROLLER (dest));
-
-  gesture = gtk_gesture_rotate_new ();
-  g_signal_connect (gesture, "angle-changed", G_CALLBACK (angle_changed), NULL);
-  g_signal_connect (gesture, "end", G_CALLBACK (rotate_done), NULL);
-  gtk_widget_add_controller (widget, GTK_EVENT_CONTROLLER (gesture));
-
-  gesture = gtk_gesture_click_new ();
-  g_signal_connect (gesture, "released", G_CALLBACK (click_done), NULL);
-  gtk_widget_add_controller (widget, GTK_EVENT_CONTROLLER (gesture));
-  
-  return widget;
-}
-
 static GtkWidget *window = NULL;
 
 GtkWidget *
@@ -465,7 +500,7 @@ do_dnd (GtkWidget *do_widget)
 
           item = canvas_item_new (x, y);
           gtk_fixed_put (GTK_FIXED (canvas), item, 0, 0);
-          apply_transform (item);
+          apply_transform (CANVAS_ITEM (item));
 
           x += 150;
           y += 100;


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