From 24912ce5b3f77c2cc558c03eb91f91b6ac272eae Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 22 Nov 2020 00:52:20 -0500 Subject: [PATCH] Introduce point types This is a bit more organized than the ad hoc smooth and symmetric booleans, and will let us introduce more types in the future. --- tests/curve-editor.c | 165 ++++++++++++++++++++++--------------------- 1 file changed, 85 insertions(+), 80 deletions(-) diff --git a/tests/curve-editor.c b/tests/curve-editor.c index 4975ae2c14..fe5ab1492a 100644 --- a/tests/curve-editor.c +++ b/tests/curve-editor.c @@ -42,6 +42,42 @@ op_from_string (const char *s) g_assert_not_reached (); } +typedef enum +{ + CUSP, + SMOOTH, + SYMMETRIC +} PointType; + +static const char * +point_type_to_string (PointType type) +{ + switch (type) + { + case CUSP: + return "cusp"; + case SMOOTH: + return "smooth"; + case SYMMETRIC: + return "symmetric"; + default: + g_assert_not_reached (); + } +} + +static PointType +point_type_from_string (const char *s) +{ + if (strcmp (s, "cusp") == 0) + return CUSP; + else if (strcmp (s, "smooth") == 0) + return SMOOTH; + else if (strcmp (s, "symmetric") == 0) + return SYMMETRIC; + else + g_assert_not_reached (); +} + /* We don't store Bezier segments, but an array of points on * the line. Each point comes with its two neighboring control * points, so each Bezier segment contains p[1] and p[2] from @@ -53,9 +89,8 @@ typedef struct { /* 0 and 2 are control points, 1 is the point on the line */ graphene_point_t p[3]; + PointType type; gboolean edit; - gboolean smooth; - gboolean symmetric; int dragged; int hovered; /* refers to the segment following the point */ @@ -414,48 +449,35 @@ maintain_smoothness (CurveEditor *self, { PointData *pd; Operation op, op1; - graphene_point_t *p; + graphene_point_t *p, *c, *c2, *p2; + float d; pd = &self->points[point]; - if (!pd->smooth) + if (pd->type == CUSP) return; op = pd->op; op1 = self->points[(point - 1 + self->n_points) % self->n_points].op; p = &pd->p[1]; + c = &pd->p[0]; + c2 = &pd->p[2]; if (op == CURVE && op1 == CURVE) { - graphene_point_t *c, *c2; - float d; - - c = &pd->p[0]; - c2 = &pd->p[2]; - d = graphene_point_distance (c, p, NULL, NULL); opposite_point (p, c2, d, c); } else if (op == CURVE && op1 == LINE) { - graphene_point_t *c, *p2; - float d; - - c = &pd->p[2]; p2 = &self->points[(point - 1 + self->n_points) % self->n_points].p[1]; - - d = graphene_point_distance (c, p, NULL, NULL); - opposite_point (p, p2, d, c); + d = graphene_point_distance (c2, p, NULL, NULL); + opposite_point (p, p2, d, c2); } else if (op == LINE && op1 == CURVE) { - graphene_point_t *c, *p2; - float d; - - c = &pd->p[0]; p2 = &self->points[(point + 1) % self->n_points].p[1]; - d = graphene_point_distance (c, p, NULL, NULL); opposite_point (p, p2, d, c); } @@ -471,7 +493,7 @@ maintain_symmetry (CurveEditor *self, pd = &self->points[point]; - if (!pd->symmetric) + if (pd->type != SYMMETRIC) return; c = &pd->p[0]; @@ -491,7 +513,7 @@ maintain_symmetry (CurveEditor *self, } /* Check if the points arount point currently satisfy - * smoothness conditions. Set PointData.smooth accordingly. + * smoothness conditions. Set PointData.type accordingly. */ static void check_smoothness (CurveEditor *self, @@ -519,10 +541,10 @@ check_smoothness (CurveEditor *self, else p1 = NULL; - if (p1 && p2) - pd->smooth = collinear (&pd->p[1], p1, p2); + if (!p1 || !p2 || !collinear (&pd->p[1], p1, p2)) + pd->type = CUSP; else - pd->smooth = TRUE; + pd->type = SMOOTH; } static void @@ -553,7 +575,7 @@ insert_point (CurveEditor *self, point1 = (point + 1) % self->n_points; point2 = (point + 2) % self->n_points; - self->points[point1].smooth = TRUE; + self->points[point1].type = SMOOTH; self->points[point1].hovered = -1; if (op == LINE) @@ -808,7 +830,7 @@ drag_update (GtkGestureDrag *gesture, /* the other endpoint of the line */ p = &pd1->p[1]; - if (op == CURVE && pd->smooth) + if (op == CURVE && pd->type != CUSP) { /* adjust the control point after the line segment */ opposite_point (d, p, l2, &pd->p[2]); @@ -824,7 +846,7 @@ drag_update (GtkGestureDrag *gesture, op11 = self->points[((self->dragged - 2 + self->n_points) % self->n_points)].op; - if (op11 == CURVE && pd1->smooth) + if (op11 == CURVE && pd1->type != CUSP) { double l; @@ -839,7 +861,7 @@ drag_update (GtkGestureDrag *gesture, /* the other endpoint of the line */ p = &pd2->p[1]; - if (op1 == CURVE && pd->smooth) + if (op1 == CURVE && pd->type != CUSP) { /* adjust the control point before the line segment */ opposite_point (d, p, l1, &pd->p[0]); @@ -853,7 +875,7 @@ drag_update (GtkGestureDrag *gesture, pd->p[2].x += dx; pd->p[2].y += dy; - if (op2 == CURVE && pd2->smooth) + if (op2 == CURVE && pd2->type != CUSP) { double l; @@ -900,7 +922,7 @@ drag_update (GtkGestureDrag *gesture, else g_assert_not_reached (); - if (op == CURVE && pd->smooth) + if (op == CURVE && pd->type != CUSP) { if (op1 == CURVE) { @@ -911,7 +933,7 @@ drag_update (GtkGestureDrag *gesture, d->y = y; /* then adjust the other control point */ - if (pd->symmetric) + if (pd->type == SYMMETRIC) l = graphene_point_distance (d, p, NULL, NULL); else l = graphene_point_distance (c, p, NULL, NULL); @@ -951,28 +973,15 @@ drag_end (GtkGestureDrag *gesture, /* }}} */ /* {{{ Action callbacks */ static void -set_smooth (GSimpleAction *action, - GVariant *value, - gpointer data) +set_point_type (GSimpleAction *action, + GVariant *value, + gpointer data) { CurveEditor *self = CURVE_EDITOR (data); - self->points[self->context].smooth = g_variant_get_boolean (value); + self->points[self->context].type = point_type_from_string (g_variant_get_string (value, NULL)); maintain_smoothness (self, self->context); - - gtk_widget_queue_draw (GTK_WIDGET (self)); -} - -static void -set_symmetric (GSimpleAction *action, - GVariant *value, - gpointer data) -{ - CurveEditor *self = CURVE_EDITOR (data); - - self->points[self->context].symmetric = g_variant_get_boolean (value); - maintain_symmetry (self, self->context); gtk_widget_queue_draw (GTK_WIDGET (self)); @@ -1042,23 +1051,10 @@ pressed (GtkGestureClick *gesture, 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 (pd->smooth)); - - action = g_action_map_lookup_action (self->actions, "symmetric"); - if (pd->smooth) - { - g_simple_action_set_enabled (G_SIMPLE_ACTION (action), TRUE); - g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_boolean (pd->symmetric)); - } - else - { - g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE); - g_simple_action_set_state (G_SIMPLE_ACTION (action), FALSE); - } + action = g_action_map_lookup_action (self->actions, "type"); + g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_string (point_type_to_string (pd->type))); action = g_action_map_lookup_action (self->actions, "operation"); - g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_string (op_to_string (pd->op))); gtk_popover_set_pointing_to (GTK_POPOVER (self->menu), @@ -1265,7 +1261,7 @@ curve_editor_snapshot (GtkWidget *widget, if (j == pd->hovered) continue; - if (!(j == 1 && pd->smooth)) + if (!(j == 1 && pd->type != CUSP)) continue; break; @@ -1273,7 +1269,7 @@ curve_editor_snapshot (GtkWidget *widget, if (j == pd->hovered) continue; - if (!(j == 1 && !pd->smooth)) + if (!(j == 1 && pd->type == CUSP)) continue; break; @@ -1406,13 +1402,8 @@ curve_editor_init (CurveEditor *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 (set_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)); - - action = g_simple_action_new_stateful ("symmetric", NULL, g_variant_new_boolean (FALSE)); - g_signal_connect (action, "change-state", G_CALLBACK (set_symmetric), self); + action = g_simple_action_new_stateful ("type", G_VARIANT_TYPE_STRING, g_variant_new_string ("smooth")); + g_signal_connect (action, "change-state", G_CALLBACK (set_point_type), 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)); @@ -1428,14 +1419,23 @@ curve_editor_init (CurveEditor *self) menu = g_menu_new (); - item = g_menu_item_new ("Smooth", "point.smooth"); - g_menu_append_item (menu, item); + section = g_menu_new (); + + item = g_menu_item_new ("Cusp", "point.type::cusp"); + g_menu_append_item (section, item); g_object_unref (item); - item = g_menu_item_new ("Symmetric", "point.symmetric"); - g_menu_append_item (menu, item); + item = g_menu_item_new ("Smooth", "point.type::smooth"); + g_menu_append_item (section, item); g_object_unref (item); + item = g_menu_item_new ("Symmetric", "point.type::symmetric"); + g_menu_append_item (section, item); + g_object_unref (item); + + g_menu_append_section (menu, NULL, G_MENU_MODEL (section)); + g_object_unref (section); + section = g_menu_new (); item = g_menu_item_new ("Move", "point.operation::move"); @@ -1453,10 +1453,15 @@ curve_editor_init (CurveEditor *self) g_menu_append_section (menu, NULL, G_MENU_MODEL (section)); g_object_unref (section); + section = g_menu_new (); + item = g_menu_item_new ("Remove", "point.remove"); g_menu_append_item (section, item); g_object_unref (item); + g_menu_append_section (menu, NULL, G_MENU_MODEL (section)); + g_object_unref (section); + self->menu = gtk_popover_menu_new_from_model (G_MENU_MODEL (menu)); g_object_unref (menu); @@ -1515,7 +1520,7 @@ curve_editor_set_path (CurveEditor *self, self->points = g_new0 (PointData, self->n_points); for (i = 0; i < self->n_points; i++) { - self->points[i].smooth = FALSE; + self->points[i].type = CUSP; self->points[i].hovered = -1; }