[gtk/matthiasc/lottie] Use a context menu
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/matthiasc/lottie] Use a context menu
- Date: Sat, 21 Nov 2020 01:38:29 +0000 (UTC)
commit 8993756a845fca396eec1047cba9e80952431272
Author: Matthias Clasen <mclasen redhat com>
Date: Fri Nov 20 13:30:08 2020 -0500
Use a context menu
Move the toggling of smoothness to a context menu
on each point. This menu will carry more items in
the future.
tests/curve.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 124 insertions(+), 8 deletions(-)
---
diff --git a/tests/curve.c b/tests/curve.c
index 055b49f02f..cb2aec08a7 100644
--- a/tests/curve.c
+++ b/tests/curve.c
@@ -3,29 +3,33 @@
#define RADIUS 5
+G_DECLARE_FINAL_TYPE (DemoWidget, demo_widget, DEMO, WIDGET, GtkWidget)
+
typedef struct
{
gboolean edit;
gboolean smooth;
} PointData;
-typedef struct
+struct _DemoWidget
{
GtkWidget parent_instance;
graphene_point_t *points;
int n_points;
PointData *point_data; /* length is n_points / 3 */
int dragged;
+ int context;
gboolean symmetric;
gboolean edit;
-} DemoWidget;
-typedef struct
+ GtkWidget *menu;
+ GActionMap *actions;
+};
+
+struct _DemoWidgetClass
{
GtkWidgetClass parent_class;
-} DemoWidgetClass;
-
-GType demo_widget_get_type (void) G_GNUC_CONST;
+};
G_DEFINE_TYPE (DemoWidget, demo_widget, GTK_TYPE_WIDGET)
@@ -149,6 +153,72 @@ drag_end (GtkGestureDrag *gesture,
self->symmetric = FALSE;
}
+static void
+toggle_smooth (GSimpleAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ DemoWidget *self = DEMO_WIDGET (data);
+ gboolean smooth = g_variant_get_boolean (value);
+
+ self->point_data[self->context / 3].smooth = smooth;
+ if (smooth)
+ {
+ graphene_point_t *p, *c, *c2;
+ float a, d;
+
+ p = &self->points[self->context];
+ c = &self->points[(self->context - 1 + self->n_points) % self->n_points];
+ c2 = &self->points[(self->context + 1 + self->n_points) % self->n_points];
+
+ a = atan2 (c2->y - p->y, c2->x - p->x) + M_PI;
+ d = dist (c, p);
+ c->x = p->x + d * cos (a);
+ c->y = p->y + d * sin (a);
+ }
+
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
+static void
+pressed (GtkGestureClick *gesture,
+ int n_press,
+ double x,
+ double y,
+ DemoWidget *self)
+{
+ graphene_point_t m = GRAPHENE_POINT_INIT (x, y);
+ int i;
+ int button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
+
+ if (!self->edit)
+ return;
+
+ if (button != GDK_BUTTON_SECONDARY)
+ return;
+
+ for (i = 0; i < self->n_points; i++)
+ {
+ if (i % 3 != 0)
+ continue;
+
+ if (dist (&self->points[i], &m) < RADIUS)
+ {
+ GAction *action;
+
+ self->context = i;
+
+ action = g_action_map_lookup_action (self->actions, "smooth");
+ g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_boolean (self->point_data[i /
3].smooth));
+
+ gtk_popover_set_pointing_to (GTK_POPOVER (self->menu),
+ &(const GdkRectangle){ x, y, 1, 1 });
+ gtk_popover_popup (GTK_POPOVER (self->menu));
+ return;
+ }
+ }
+}
+
static void
released (GtkGestureClick *gesture,
int n_press,
@@ -175,6 +245,7 @@ released (GtkGestureClick *gesture,
}
else if (button == GDK_BUTTON_SECONDARY)
{
+ self->context = i;
self->point_data[i / 3].smooth = !self->point_data[i / 3].smooth;
if (self->point_data[i / 3].smooth)
{
@@ -191,8 +262,6 @@ released (GtkGestureClick *gesture,
c->y = p->y + d * sin (a);
}
}
-
- gtk_widget_queue_draw (GTK_WIDGET (self));
}
}
}
@@ -246,6 +315,9 @@ static void
demo_widget_init (DemoWidget *self)
{
GtkGesture *gesture;
+ GMenu *menu;
+ GMenuItem *item;
+ GSimpleAction *action;
self->dragged = -1;
self->edit = FALSE;
@@ -259,10 +331,27 @@ demo_widget_init (DemoWidget *self)
gesture = gtk_gesture_click_new ();
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), 0);
+ g_signal_connect (gesture, "pressed", G_CALLBACK (pressed), self);
g_signal_connect (gesture, "released", G_CALLBACK (released), self);
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture));
init_points (self);
+
+ self->actions = G_ACTION_MAP (g_simple_action_group_new ());
+ action = g_simple_action_new_stateful ("smooth", NULL, g_variant_new_boolean (FALSE));
+ g_signal_connect (action, "change-state", G_CALLBACK (toggle_smooth), self);
+ g_action_map_add_action (G_ACTION_MAP (self->actions), G_ACTION (action));
+ gtk_widget_insert_action_group (GTK_WIDGET (self), "point", G_ACTION_GROUP (self->actions));
+
+ menu = g_menu_new ();
+ item = g_menu_item_new ("Smooth", "point.smooth");
+ g_menu_append_item (menu, item);
+ g_object_unref (item);
+
+ self->menu = gtk_popover_menu_new_from_model (G_MENU_MODEL (menu));
+ g_object_unref (menu);
+
+ gtk_widget_set_parent (self->menu, GTK_WIDGET (self));
}
static void
@@ -410,13 +499,40 @@ demo_widget_measure (GtkWidget *widget,
*natural_size = 200;
}
+static void
+demo_widget_size_allocate (GtkWidget *widget,
+ int width,
+ int height,
+ int baseline)
+{
+ DemoWidget *self = DEMO_WIDGET (widget);
+
+ gtk_native_check_resize (GTK_NATIVE (self->menu));
+}
+
+static void
+demo_widget_dispose (GObject *object)
+{
+ DemoWidget *self = DEMO_WIDGET (object);
+
+ g_clear_pointer (&self->points, g_free);
+ g_clear_pointer (&self->point_data, g_free);
+ g_clear_pointer (&self->menu, gtk_widget_unparent);
+
+ G_OBJECT_CLASS (demo_widget_parent_class)->dispose (object);
+}
+
static void
demo_widget_class_init (DemoWidgetClass *class)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+ object_class->dispose = demo_widget_dispose;
+
widget_class->snapshot = demo_widget_snapshot;
widget_class->measure = demo_widget_measure;
+ widget_class->size_allocate = demo_widget_size_allocate;
}
static GtkWidget *
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]