2 #include "common-context.h"
4 #include <gtk/gtk.h>
6 #include "config.h"
8 #include "forward.h"
9 #include "message-context.h"
10 #include "streq.h"
12 #define MIN_PRESSURE 0.0
13 #define MAX_PRESSURE 1.0
14 #define DEFAULT_PRESSURE 1.0
16 #define DRAG_MIN 0.0
17 #define DRAG_DEFAULT 1.0
18 #define DRAG_MAX 1.0
21 static void sp_common_context_class_init(SPCommonContextClass *klass);
22 static void sp_common_context_init(SPCommonContext *erc);
23 static void sp_common_context_dispose(GObject *object);
25 static void sp_common_context_setup(SPEventContext *ec);
26 static void sp_common_context_set(SPEventContext *ec, gchar const *key, gchar const *value);
28 static gint sp_common_context_root_handler(SPEventContext *event_context, GdkEvent *event);
31 static SPEventContextClass *common_parent_class = 0;
33 GType sp_common_context_get_type(void)
34 {
35 static GType type = 0;
36 if (!type) {
37 GTypeInfo info = {
38 sizeof(SPCommonContextClass),
39 0, // base_init
40 0, // base_finalize
41 (GClassInitFunc)sp_common_context_class_init,
42 0, // class_finalize
43 0, // class_data
44 sizeof(SPCommonContext),
45 0, // n_preallocs
46 (GInstanceInitFunc)sp_common_context_init,
47 0 // value_table
48 };
49 type = g_type_register_static(SP_TYPE_EVENT_CONTEXT, "SPCommonContext", &info, static_cast<GTypeFlags>(0));
50 }
51 return type;
52 }
55 static void sp_common_context_class_init(SPCommonContextClass *klass)
56 {
57 GObjectClass *object_class = (GObjectClass *) klass;
58 SPEventContextClass *event_context_class = (SPEventContextClass *) klass;
60 common_parent_class = (SPEventContextClass*)g_type_class_peek_parent(klass);
62 object_class->dispose = sp_common_context_dispose;
64 event_context_class->setup = sp_common_context_setup;
65 event_context_class->set = sp_common_context_set;
66 event_context_class->root_handler = sp_common_context_root_handler;
67 }
69 static void sp_common_context_init(SPCommonContext *ctx)
70 {
71 // ctx->cursor_shape = cursor_eraser_xpm;
72 // ctx->hot_x = 4;
73 // ctx->hot_y = 4;
75 ctx->accumulated = 0;
76 ctx->segments = 0;
77 ctx->currentcurve = 0;
78 ctx->currentshape = 0;
79 ctx->npoints = 0;
80 ctx->cal1 = 0;
81 ctx->cal2 = 0;
82 ctx->repr = 0;
84 /* Common values */
85 ctx->cur = NR::Point(0,0);
86 ctx->last = NR::Point(0,0);
87 ctx->vel = NR::Point(0,0);
88 ctx->vel_max = 0;
89 ctx->acc = NR::Point(0,0);
90 ctx->ang = NR::Point(0,0);
91 ctx->del = NR::Point(0,0);
93 /* attributes */
94 ctx->dragging = FALSE;
96 ctx->mass = 0.3;
97 ctx->drag = DRAG_DEFAULT;
98 ctx->angle = 30.0;
99 ctx->width = 0.2;
100 ctx->pressure = DEFAULT_PRESSURE;
102 ctx->vel_thin = 0.1;
103 ctx->flatness = 0.9;
104 ctx->cap_rounding = 0.0;
106 ctx->abs_width = false;
107 }
109 static void sp_common_context_dispose(GObject *object)
110 {
111 SPCommonContext *ctx = SP_COMMON_CONTEXT(object);
113 if (ctx->accumulated) {
114 ctx->accumulated = ctx->accumulated->unref();
115 ctx->accumulated = 0;
116 }
118 while (ctx->segments) {
119 gtk_object_destroy(GTK_OBJECT(ctx->segments->data));
120 ctx->segments = g_slist_remove(ctx->segments, ctx->segments->data);
121 }
123 if (ctx->currentcurve) {
124 ctx->currentcurve = ctx->currentcurve->unref();
125 ctx->currentcurve = 0;
126 }
127 if (ctx->cal1) {
128 ctx->cal1 = ctx->cal1->unref();
129 ctx->cal1 = 0;
130 }
131 if (ctx->cal2) {
132 ctx->cal2 = ctx->cal2->unref();
133 ctx->cal2 = 0;
134 }
136 if (ctx->currentshape) {
137 gtk_object_destroy(GTK_OBJECT(ctx->currentshape));
138 ctx->currentshape = 0;
139 }
141 if (ctx->_message_context) {
142 delete ctx->_message_context;
143 ctx->_message_context = 0;
144 }
146 G_OBJECT_CLASS(common_parent_class)->dispose(object);
147 }
150 static void sp_common_context_setup(SPEventContext *ec)
151 {
152 if ( common_parent_class->setup ) {
153 common_parent_class->setup(ec);
154 }
155 }
157 static inline bool
158 get_bool_value(char const *const val)
159 {
160 return ( val && *val == '1' );
161 /* The only possible values if written by inkscape are NULL (attribute not present)
162 * or "0" or "1".
163 *
164 * For other values (e.g. if modified by a human without following the above rules), the
165 * current implementation does the right thing for empty string, "no", "false", "n", "f"
166 * but the wrong thing for "yes", "true", "y", "t". */
167 }
169 static void sp_common_context_set(SPEventContext *ec, gchar const *key, gchar const *value)
170 {
171 SPCommonContext *ctx = SP_COMMON_CONTEXT(ec);
173 if (streq(key, "mass")) {
174 double const dval = ( value ? g_ascii_strtod (value, NULL) : 0.2 );
175 ctx->mass = CLAMP(dval, -1000.0, 1000.0);
176 } else if (streq(key, "wiggle")) {
177 double const dval = ( value ? g_ascii_strtod (value, NULL) : (1 - DRAG_DEFAULT));
178 ctx->drag = CLAMP((1 - dval), DRAG_MIN, DRAG_MAX); // drag is inverse to wiggle
179 } else if (streq(key, "angle")) {
180 double const dval = ( value ? g_ascii_strtod (value, NULL) : 0.0);
181 ctx->angle = CLAMP (dval, -90, 90);
182 } else if (streq(key, "width")) {
183 double const dval = ( value ? g_ascii_strtod (value, NULL) : 0.1 );
184 ctx->width = CLAMP(dval, -1000.0, 1000.0);
185 } else if (streq(key, "thinning")) {
186 double const dval = ( value ? g_ascii_strtod (value, NULL) : 0.1 );
187 ctx->vel_thin = CLAMP(dval, -1.0, 1.0);
188 } else if (streq(key, "tremor")) {
189 double const dval = ( value ? g_ascii_strtod (value, NULL) : 0.0 );
190 ctx->tremor = CLAMP(dval, 0.0, 1.0);
191 } else if (streq(key, "flatness")) {
192 double const dval = ( value ? g_ascii_strtod (value, NULL) : 1.0 );
193 ctx->flatness = CLAMP(dval, 0, 1.0);
194 } else if (streq(key, "usepressure")) {
195 ctx->usepressure = get_bool_value(value);
196 } else if (streq(key, "usetilt")) {
197 ctx->usetilt = get_bool_value(value);
198 } else if (streq(key, "abs_width")) {
199 ctx->abs_width = get_bool_value(value);
200 } else if (streq(key, "cap_rounding")) {
201 ctx->cap_rounding = ( value ? g_ascii_strtod (value, NULL) : 0.0 );
202 }
203 }
205 static gint sp_common_context_root_handler(SPEventContext *event_context, GdkEvent *event)
206 {
207 gint ret = FALSE;
209 // TODO add common hanlding
212 if ( !ret ) {
213 if ( common_parent_class->root_handler ) {
214 ret = common_parent_class->root_handler(event_context, event);
215 }
216 }
218 return ret;
219 }
221 /*
222 Local Variables:
223 mode:c++
224 c-file-style:"stroustrup"
225 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
226 indent-tabs-mode:nil
227 fill-column:99
228 End:
229 */
230 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :