[dia] Misc - Ngon: add density parameter for mote star variants
- From: Hans Breuer <hans src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dia] Misc - Ngon: add density parameter for mote star variants
- Date: Sun, 8 Jun 2014 09:00:18 +0000 (UTC)
commit 2946acb4b603dfe5abe2b2dce056f439d3c0752a
Author: Hans Breuer <hans breuer org>
Date: Thu May 29 13:44:07 2014 +0200
Misc - Ngon: add density parameter for mote star variants
The n-gon density value depends on num_rays. Only a limited set of values
can be supported, where min/max/step is not enough to reflect it.
So this object is the first user of PropEventHandler to keep density in
valid range (or better it's edit control).
lib/propdialogs.c | 15 ++++++++++
objects/Misc/n_gon.c | 74 +++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 83 insertions(+), 6 deletions(-)
---
diff --git a/lib/propdialogs.c b/lib/propdialogs.c
index 273e1d1..3c0a208 100644
--- a/lib/propdialogs.c
+++ b/lib/propdialogs.c
@@ -200,8 +200,23 @@ property_signal_handler(GObject *obj,
for (j = 0; j < dialog->prop_widgets->len; j++) {
PropWidgetAssoc *pwa =
&g_array_index(dialog->prop_widgets,PropWidgetAssoc,j);
+ /* The event handler above might have changed every property
+ * so we would have to mark them all as set (aka. to be applied).
+ * But doing so would not work well with multiple/grouped objects
+ * with unchanged and unequal object properties. Idea: keep as
+ * set, what was before calling reset (but it's too late after get_props).
+ *
+ * See also commonprop_reset_widget() for more information
+ */
+ gboolean was_set = (pwa->prop->experience & PXP_NOTSET == 0);
pwa->prop->ops->reset_widget(pwa->prop,pwa->widget);
+ if (was_set)
+ pwa->prop->experience &= ~PXP_NOTSET;
}
+ /* once more at least for _this_ property otherwise a property with
+ * signal handler attached would not be changed at all ...
+ */
+ prop->experience &= ~PXP_NOTSET;
} else {
g_assert_not_reached();
}
diff --git a/objects/Misc/n_gon.c b/objects/Misc/n_gon.c
index 85a0b06..3d92477 100644
--- a/objects/Misc/n_gon.c
+++ b/objects/Misc/n_gon.c
@@ -24,6 +24,7 @@
#include "diarenderer.h"
#include "attributes.h"
#include "properties.h"
+#include "prop_inttypes.h" /* PropEventHandler needs internals */
#include "boundingbox.h"
#include "element.h"
#include "pattern.h"
@@ -55,6 +56,9 @@ struct _Ngon {
int num_rays;
NgonKind kind;
+ int density;
+ int last_density; /*!< last value to decide direction */
+
LineStyle line_style;
LineJoin line_join;
real dashlength;
@@ -102,6 +106,10 @@ static PropEnumData _ngon_type_data[] = {
{ NULL, }
};
static PropNumData _num_rays_range_data = { 3, 360, 1 };
+static PropNumData _density_range_data = { 2, 180, 1 };
+
+/* PropEventHandler to keep the density property valid */
+static gboolean _ngon_density_constraints_handler (DiaObject *obj, Property *prop);
static PropDescription _ngon_props[] = {
ELEMENT_COMMON_PROPERTIES,
@@ -109,6 +117,9 @@ static PropDescription _ngon_props[] = {
N_("N-gon kind"), NULL, &_ngon_type_data },
{ "num_rays", PROP_TYPE_INT, PROP_FLAG_VISIBLE,
N_("Number of rays"), NULL, &_num_rays_range_data },
+ { "density", PROP_TYPE_INT, PROP_FLAG_VISIBLE|PROP_FLAG_OPTIONAL,
+ N_("Density"), N_("Winding number for Crossing"), &_density_range_data,
+ &_ngon_density_constraints_handler },
{ "center", PROP_TYPE_POINT, PROP_FLAG_NO_DEFAULTS, /* no property widget, but still to be serialized */
N_("Center position"), NULL, NULL },
{ "ray_len", PROP_TYPE_REAL, PROP_FLAG_NO_DEFAULTS, /* no property widget, but still to be serialized */
@@ -136,6 +147,7 @@ static PropOffset _ngon_offsets[] = {
ELEMENT_COMMON_PROPERTIES_OFFSETS,
{ "ngon_kind", PROP_TYPE_ENUM, offsetof(Ngon, kind) },
{ "num_rays", PROP_TYPE_INT, offsetof(Ngon, num_rays) },
+ { "density", PROP_TYPE_INT, offsetof(Ngon, density) },
{ "center", PROP_TYPE_POINT, offsetof(Ngon, center) },
{ "ray_len", PROP_TYPE_REAL, offsetof(Ngon, ray_len) },
{ PROP_STDNAME_LINE_WIDTH, PROP_STDTYPE_LINE_WIDTH, offsetof(Ngon, line_width) },
@@ -150,12 +162,13 @@ static PropOffset _ngon_offsets[] = {
};
static void
_ngon_get_props(Ngon *ng, GPtrArray *props)
-{
+{
object_get_props_from_offsets(&ng->element.object, _ngon_offsets, props);
}
static void
_ngon_set_props(Ngon *ng, GPtrArray *props)
{
+ ng->last_density = ng->density;
object_set_props_from_offsets(&ng->element.object, _ngon_offsets, props);
_ngon_update_data(ng);
}
@@ -254,10 +267,46 @@ _gcd (int a, int b)
static int
_calc_step (int a, int b)
{
+ if (b > a / 2)
+ b = a / 2;
while (_gcd (a, b) != 1)
--b;
return b;
}
+static int
+_calc_step_up (int a, int b)
+{
+ while (_gcd (a, b) != 1)
+ ++b;
+ return b;
+}
+
+/*!
+ * \brief Event handler called for property change by user
+ *
+ * The n-gon density value depends on num_rays. Only a limited set of values
+ * can be supported, where min/max/step is not enough to reflect it.
+ *
+ * This function gets called between Ngon::set_props() and
+ * Ngon::get_props(). It does need to do anything cause Ngon::update_data()
+ * already ensured data consistency. The pure existance of this of this
+ * property handler leads to bidirectional communication between property
+ * dialog and object's property change.
+ */
+static gboolean
+_ngon_density_constraints_handler (DiaObject *obj, Property *prop)
+{
+ Ngon *ng = (Ngon *)obj;
+ IntProperty *p = (IntProperty *)prop;
+ int maxDensity = _calc_step (ng->num_rays, ng->num_rays / 2);
+
+ g_return_val_if_fail (strcmp(prop->descr->type, PROP_TYPE_INT) == 0, FALSE);
+
+ if (p->int_data > maxDensity) {
+ ng->density = maxDensity;
+ }
+ return TRUE;
+}
static void
_ngon_make_name (Ngon *ng)
@@ -309,8 +358,7 @@ _ngon_make_name (Ngon *ng)
if (ng->kind == NGON_CONVEX)
ng->name = g_strdup_printf ("%s {%d}", name, ng->num_rays);
else
- ng->name = g_strdup_printf ("%s {%d/%d}", name, ng->num_rays,
- _calc_step (ng->num_rays, ng->num_rays / 2));
+ ng->name = g_strdup_printf ("%s {%d/%d}", name, ng->num_rays, ng->density);
}
/*!
@@ -324,7 +372,7 @@ _ngon_make_name (Ngon *ng)
static void
_ngon_adjust_for_crossing (Ngon *ng)
{
- int n = ng->points->len, i, step = _calc_step (ng->points->len, ng->points->len / 2);
+ int n = ng->points->len, i, step = _calc_step (ng->num_rays, ng->density);
GArray *points = g_array_new (FALSE /* zero_terminated */,
FALSE /* clear_ */, sizeof(Point));
@@ -356,6 +404,12 @@ _ngon_update_data (Ngon *ng)
else
n = ng->num_rays * 2;
+ /* ensure density stays in range */
+ if (ng->last_density > ng->density)
+ ng->density = _calc_step (ng->num_rays, ng->density);
+ else
+ ng->density = _calc_step_up (ng->num_rays, ng->density);
+
_ngon_make_name (ng);
if (1 || n != ng->points->len) {
/* recalculate all points */
@@ -454,7 +508,7 @@ static ObjectOps _ngon_ops = {
DiaObjectType _ngon_type =
{
"Misc - Ngon", /* name */
- 0, /* version */
+ 1, /* version */
n_gon_xpm, /* pixmap */
&_ngon_type_ops, /* ops */
NULL, /* pixmap_file */
@@ -498,6 +552,7 @@ _ngon_create (Point *startpoint,
FALSE /* clear_ */, sizeof(Point));
ng->kind = NGON_CONVEX;
ng->num_rays = 5;
+ ng->last_density = ng->density = _calc_step (ng->num_rays, ng->num_rays / 2);
ng->ray_len = 1.0; /* for intial object size */
ng->center = *startpoint;
@@ -520,7 +575,14 @@ _ngon_load (ObjectNode obj_node, int version, DiaContext *ctx)
Ngon *ng;
obj = object_load_using_properties (&_ngon_type, obj_node, version, ctx);
- /* XXX: do some sanity check? */
+ ng = (Ngon *)obj;
+ if (version == 0) { /* default to maximum */
+ ng->last_density = ng->density = _calc_step (ng->num_rays, ng->num_rays/2);
+ _ngon_update_data(ng);
+ }
+ /* the density value is optional, so calculate if not valid */
+ if (_calc_step (ng->num_rays, ng->density) != ng->density)
+ ng->density = _calc_step (ng->num_rays, ng->num_rays/2);
return obj;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]