git.s-ol.nu inkscape / 81fe225
add draft janet interface for livecoding s-ol 3 years ago
16 changed file(s) with 941 addition(s) and 414 deletion(s). Raw diff Collapse all Expand all
8787 fontconfig
8888 gsl
8989 gmodule-2.0
90 libsoup-2.4>=2.42)
90 libsoup-2.4>=2.42
91 janet)
9192
9293 sanitize_ldflags_for_libs(INKSCAPE_DEP_LDFLAGS)
9394 list(APPEND INKSCAPE_LIBS ${INKSCAPE_DEP_LDFLAGS})
00 # SPDX-License-Identifier: GPL-2.0-or-later
11
22 set(livecode_SRC
3 api.cpp
3 context.cpp
44 input.cpp
5 api/context.cpp
6 api/input.cpp
7 api/point.cpp
58
69 # HEADERS
7 api.h
10 context.h
811 input.h
12 api/api.h
913 )
1014
1115 add_inkscape_source("${livecode_SRC}")
0 #ifndef JANET_2GEOM_POINT_INCLUDED
1 #define JANET_2GEOM_POINT_INCLUDED
2
3 #include <janet.h>
4 #include <2geom/point.h>
5 #include "livecode/context.h"
6 #include "livecode/input.h"
7
8 namespace Inkscape {
9 namespace Livecode {
10
11 /* context.cpp */
12 void janet_lib_context(JanetTable *env, Context &context);
13
14 Context &ctx();
15
16 /* point.cpp */
17 void janet_lib_geom_point(JanetTable *env);
18
19 extern const JanetAbstractType geom_point_type;
20
21 Janet janet_wrap_point(Geom::Point const &x);
22 Janet janet_wrap_point(Geom::IntPoint const &x);
23 Geom::Point janet_unwrap_point(Janet x);
24
25 /* input.cpp */
26 void janet_lib_input(JanetTable *env);
27
28 Janet janet_wrap_inputstate(InputState const &state);
29
30 }
31 }
32
33 #endif // JANET_2GEOM_POINT_INCLUDED
0 #include "livecode/api/api.h"
1
2 namespace Inkscape {
3 namespace Livecode {
4
5 static Context *_context = nullptr;
6
7 Context &ctx() {
8 if (!_context) {
9 janet_panic("Livecode Context uninitialized!!");
10 }
11
12 return *_context;
13 }
14
15 void janet_lib_context(JanetTable *env, Context &context) {
16 _context = &context;
17 }
18
19 }
20 }
0 #include "livecode/api/api.h"
1
2 #include <sstream>
3
4 namespace Inkscape {
5 namespace Livecode {
6
7 extern "C" Janet cfun_mouse_pos(int32_t argc, Janet *argv) {
8 janet_fixarity(argc, 0);
9 return janet_wrap_point(ctx().mouse().pos());
10 }
11
12 extern "C" Janet cfun_mouse_delta(int32_t argc, Janet *argv) {
13 janet_fixarity(argc, 0);
14 return janet_wrap_point(ctx().mouse().delta());
15 }
16
17 extern "C" Janet cfun_mouse_ui_pos(int32_t argc, Janet *argv) {
18 janet_fixarity(argc, 0);
19 return janet_wrap_point(ctx().mouse().ui_pos());
20 }
21
22 extern "C" Janet cfun_mouse_ui_delta(int32_t argc, Janet *argv) {
23 janet_fixarity(argc, 0);
24 return janet_wrap_point(ctx().mouse().ui_delta());
25 }
26
27 Janet janet_wrap_inputstate(InputState const &state) {
28 switch (state) {
29 case INPUTSTATE_NONE:
30 return janet_wrap_nil();
31 case INPUTSTATE_HOVER:
32 return janet_ckeywordv("hover");
33 case INPUTSTATE_PRESSED:
34 return janet_ckeywordv("pressed");
35 case INPUTSTATE_HELD:
36 return janet_ckeywordv("held");
37 case INPUTSTATE_RELEASED:
38 return janet_ckeywordv("released");
39 default:
40 janet_panic("unexpected event value");
41 }
42 }
43
44 extern "C" Janet cfun_mouse_event(int32_t argc, Janet *argv) {
45 janet_arity(argc, 0, 1);
46
47 guint button = janet_getsize(argv, 1);
48 if (button < 1 || button > 5) {
49 janet_panic("expected button to be between 1 and 5");
50 }
51
52 return janet_wrap_inputstate(ctx().mouse().event(button));
53 }
54
55 #define BUTTONMETHOD(name) \
56 extern "C" Janet cfun_mouse_##name(int32_t argc, Janet *argv) { \
57 janet_arity(argc, 0, 1); \
58 guint button = janet_getsize(argv, 1); \
59 if (button < 1 || button > 5) { \
60 janet_panic("expected button to be between 1 and 5"); \
61 } \
62 return janet_wrap_boolean(ctx().mouse().name(button)); \
63 }
64
65 BUTTONMETHOD(pressed)
66 BUTTONMETHOD(held)
67 BUTTONMETHOD(released)
68
69 const JanetReg it_cfuns[] = {
70 {
71 "mouse/pos", cfun_mouse_pos,
72 "(mouse/pos)\n\nGet the current mouse position as a geom/point."
73 },
74 {
75 "mouse/delta", cfun_mouse_delta,
76 "(mouse/pos)\n\nGet the mouse motion since last frame as a geom/point."
77 },
78 {
79 "mouse/ui-pos", cfun_mouse_ui_pos,
80 "(mouse/pos)\n\nGet the current mouse position as a geom/point, in UI space."
81 },
82 {
83 "mouse/ui-delta", cfun_mouse_ui_delta,
84 "(mouse/pos)\n\nGet the mouse motion since last frame as a geom/point, in UI space."
85 },
86 {
87 "mouse/event", cfun_mouse_event,
88 "(mouse/event [button])\n\nGet the current event/status for a mouse button.\n"
89 "Returns either nil, :pressed, :held or :released."
90 },
91 {
92 "mouse/pressed", cfun_mouse_pressed,
93 "(mouse/pressed [button])\n\nCheck whether a mouse button was pressed this frame.\n"
94 },
95 {
96 "mouse/held", cfun_mouse_held,
97 "(mouse/held [button])\n\nCheck whether a mouse button was held down this frame.\n"
98 },
99 {
100 "mouse/released", cfun_mouse_released,
101 "(mouse/released [button])\n\nCheck whether a mouse button was released this frame.\n"
102 },
103 {NULL, NULL, NULL}
104 };
105
106
107 void janet_lib_input(JanetTable *env) {
108 janet_cfuns(env, NULL, it_cfuns);
109 }
110
111 }
112 }
0 #include "livecode/api/api.h"
1
2 #include <sstream>
3
4 namespace Inkscape {
5 namespace Livecode {
6
7 extern "C" Janet geom_point_get(void *p, Janet key);
8 extern "C" void geom_point_set(void *p, Janet key, Janet value);
9
10 extern "C" void geom_point_tostring(void *p, JanetBuffer *buffer) {
11 std::stringstream stream;
12 stream << "<2geom/point " << *static_cast<Geom::Point *>(p) << ">";
13 janet_buffer_push_cstring(buffer, stream.str().c_str());
14 }
15
16
17 const JanetAbstractType geom_point_type = {
18 "2geom/point",
19 NULL,
20 NULL,
21 geom_point_get,
22 geom_point_set,
23 NULL,
24 NULL,
25 geom_point_tostring
26 };
27
28
29 Janet janet_wrap_point(Geom::Point const &x) {
30 Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
31 *box = Geom::Point(x);
32 return janet_wrap_abstract(box);
33 }
34
35 Janet janet_wrap_point(Geom::IntPoint const &x) {
36 Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
37 *box = Geom::Point(x);
38 return janet_wrap_abstract(box);
39 }
40
41 Geom::Point janet_unwrap_point(Janet x) {
42 if (janet_checktype(x, JANET_ABSTRACT)) {
43 void *abst = janet_unwrap_abstract(x);
44 if (janet_abstract_type(abst) == &geom_point_type)
45 return *(Geom::Point *)abst;
46 }
47
48 janet_panic("expected a geom/point");
49 }
50
51 Geom::Point janet_unwrap_point_or_scalar(Janet x) {
52 if (janet_checktype(x, JANET_ABSTRACT)) {
53 void *abst = janet_unwrap_abstract(x);
54 if (janet_abstract_type(abst) == &geom_point_type)
55 return *(Geom::Point *)abst;
56 } else if (janet_checktype(x, JANET_NUMBER)) {
57 double val = janet_unwrap_number(x);
58 return Geom::Point(val, val);
59 }
60
61 janet_panic("expected a geom/point");
62 }
63
64
65 Geom::Point& janet_unwrap_point_ref(Janet x) {
66 if (janet_checktype(x, JANET_ABSTRACT)) {
67 void *abst = janet_unwrap_abstract(x);
68 if (janet_abstract_type(abst) == &geom_point_type)
69 return *(Geom::Point *)abst;
70 }
71
72 janet_panic("expected a geom/point");
73 }
74
75 extern "C" Janet cfun_geom_point_new(int32_t argc, Janet *argv) {
76 janet_arity(argc, 0, 2);
77 double x = 0;
78 double y = 0;
79 if (argc == 2) {
80 x = janet_getnumber(argv, 0);
81 y = janet_getnumber(argv, 1);
82 } else if (argc == 1) {
83 x = janet_getnumber(argv, 0);
84 y = x;
85 }
86 return janet_wrap_point(Geom::Point(x, y));
87 }
88
89 const JanetReg it_cfuns[] = {
90 {
91 "point", cfun_geom_point_new,
92 "(geom/point x y)\n\nCreate a Point from x/y coordinate values."
93 },
94 {NULL, NULL, NULL}
95 };
96
97 static Janet cfun_geom_point_add(int32_t argc, Janet *argv) {
98 janet_arity(argc, 2, -1);
99 Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
100 *box = janet_unwrap_point(argv[0]);
101 for (int i = 1; i < argc; i++)
102 *box += janet_unwrap_point(argv[i]);
103 return janet_wrap_abstract(box);
104 }
105
106 static Janet cfun_geom_point_add_mut(int32_t argc, Janet *argv) {
107 janet_arity(argc, 2, -1);
108 Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
109 for (int i = 1; i < argc; i++)
110 *box += janet_unwrap_point(argv[i]);
111 return janet_wrap_abstract(box);
112 }
113
114 static Janet cfun_geom_point_sub(int32_t argc, Janet *argv) {
115 janet_arity(argc, 2, -1);
116 Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
117 *box = janet_unwrap_point(argv[0]);
118 for (int i = 1; i < argc; i++)
119 *box -= janet_unwrap_point(argv[i]);
120 return janet_wrap_abstract(box);
121 }
122
123 static Janet cfun_geom_point_sub_mut(int32_t argc, Janet *argv) {
124 janet_arity(argc, 2, -1);
125 Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
126 for (int i = 1; i < argc; i++)
127 *box -= janet_unwrap_point(argv[i]);
128 return janet_wrap_abstract(box);
129 }
130
131 static Janet cfun_geom_point_mul(int32_t argc, Janet *argv) {
132 janet_arity(argc, 2, -1);
133 Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
134 *box = janet_unwrap_point(argv[0]);
135 for (int i = 1; i < argc; i++) {
136 Geom::Point arg = janet_unwrap_point_or_scalar(argv[i]);
137 (*box)[0] *= arg[0];
138 (*box)[1] *= arg[1];
139 }
140 return janet_wrap_abstract(box);
141 }
142
143 static Janet cfun_geom_point_mul_mut(int32_t argc, Janet *argv) {
144 janet_arity(argc, 2, -1);
145 Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
146 for (int i = 1; i < argc; i++) {
147 Geom::Point arg = janet_unwrap_point_or_scalar(argv[i]);
148 (*box)[0] *= arg[0];
149 (*box)[1] *= arg[1];
150 }
151 return janet_wrap_abstract(box);
152 }
153
154 static Janet cfun_geom_point_div(int32_t argc, Janet *argv) {
155 janet_arity(argc, 2, -1);
156 Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
157 *box = janet_unwrap_point(argv[0]);
158 for (int i = 1; i < argc; i++) {
159 Geom::Point arg = janet_unwrap_point_or_scalar(argv[i]);
160 (*box)[0] /= arg[0];
161 (*box)[1] /= arg[1];
162 }
163 return janet_wrap_abstract(box);
164 }
165
166 static Janet cfun_geom_point_div_mut(int32_t argc, Janet *argv) {
167 janet_arity(argc, 2, -1);
168 Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
169 for (int i = 1; i < argc; i++) {
170 Geom::Point arg = janet_unwrap_point_or_scalar(argv[i]);
171 (*box)[0] /= arg[0];
172 (*box)[1] /= arg[1];
173 }
174 return janet_wrap_abstract(box);
175 }
176
177 static Janet cfun_geom_point_eq(int32_t argc, Janet *argv) {
178 janet_fixarity(argc, 2);
179 Geom::Point& v1 = janet_unwrap_point_ref(argv[0]);
180 Geom::Point& v2 = janet_unwrap_point_ref(argv[1]);
181 return janet_wrap_boolean(v1 == v2);
182 }
183
184 static Janet cfun_geom_point_lt(int32_t argc, Janet *argv) {
185 janet_fixarity(argc, 2);
186 Geom::Point& v1 = janet_unwrap_point_ref(argv[0]);
187 Geom::Point& v2 = janet_unwrap_point_ref(argv[1]);
188 return janet_wrap_boolean(v1 < v2);
189 }
190
191 #define CONSTMETHOD(name, method, type) \
192 static Janet cfun_geom_point_##name(int32_t argc, Janet *argv) { \
193 janet_fixarity(argc, 1); \
194 Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type); \
195 return janet_wrap_##type(box->method()); \
196 }
197
198 CONSTMETHOD(is_zero, isZero, boolean)
199 CONSTMETHOD(is_finite, isFinite, boolean)
200 CONSTMETHOD(is_normalized, isNormalized, boolean)
201
202 CONSTMETHOD(x, x, number)
203 CONSTMETHOD(y, y, number)
204 CONSTMETHOD(length, length, number)
205
206 CONSTMETHOD(cw, cw, point)
207 CONSTMETHOD(ccw, ccw, point)
208 CONSTMETHOD(round, round, point)
209 CONSTMETHOD(floor, floor, point)
210 CONSTMETHOD(ceil, ceil, point)
211 CONSTMETHOD(normalize, normalized, point)
212
213 static Janet cfun_geom_point_normalize_mut(int32_t argc, Janet *argv) {
214 janet_fixarity(argc, 1);
215 Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
216 box->normalize();
217 return janet_wrap_point(*box);
218 }
219
220 static JanetMethod geom_point_methods[] = {
221 {"+", cfun_geom_point_add},
222 {"-", cfun_geom_point_sub},
223 {"*", cfun_geom_point_mul},
224 {"/", cfun_geom_point_div},
225 {"<", cfun_geom_point_lt},
226 {"==", cfun_geom_point_eq},
227
228 {"+!", cfun_geom_point_add_mut},
229 {"-!", cfun_geom_point_sub_mut},
230 {"*!", cfun_geom_point_mul_mut},
231 {"/!", cfun_geom_point_div_mut},
232
233 {"zero?", cfun_geom_point_is_zero},
234 {"finite?", cfun_geom_point_is_finite},
235 {"normalized?", cfun_geom_point_is_normalized},
236
237 {"x", cfun_geom_point_x},
238 {"y", cfun_geom_point_y},
239 {"length", cfun_geom_point_length},
240
241 {"cw", cfun_geom_point_cw},
242 {"ccw", cfun_geom_point_ccw},
243 {"round", cfun_geom_point_round},
244 {"floor", cfun_geom_point_floor},
245 {"ceil", cfun_geom_point_ceil},
246 {"normalize", cfun_geom_point_normalize},
247
248 {"normalize!", cfun_geom_point_normalize_mut},
249
250 {NULL, NULL}
251 };
252
253 extern "C" Janet geom_point_get(void *p, Janet key) {
254 Geom::Point *box = (Geom::Point *)p;
255
256 if (janet_checktype(key, JANET_KEYWORD))
257 return janet_getmethod(janet_unwrap_keyword(key), geom_point_methods);
258
259 if (!janet_checksize(key)) janet_panic("expected size as key");
260
261 size_t const index = (size_t) janet_unwrap_number(key);
262 switch (index) {
263 case 0:
264 return janet_wrap_number((*box)[0]);
265 case 1:
266 return janet_wrap_number((*box)[1]);
267 default:
268 return janet_wrap_nil();
269 }
270 }
271
272 extern "C" void geom_point_set(void *p, Janet key, Janet value) {
273 Geom::Point *box = (Geom::Point *)p;
274
275 if (!janet_checksize(key)) janet_panic("expected size as key");
276 if (!janet_checktype(key, JANET_NUMBER)) janet_panic("expected number as value");
277
278 size_t const index = (size_t) janet_unwrap_number(key);
279 switch (index) {
280 case 0:
281 (*box)[0] = janet_unwrap_number(value);
282 break;
283 case 1:
284 (*box)[1] = janet_unwrap_number(value);
285 break;
286 default:
287 janet_panic("index out of bounds");
288 }
289 }
290
291 void janet_lib_geom_point(JanetTable *env) {
292 janet_cfuns(env, NULL, it_cfuns);
293 janet_register_abstract_type(&geom_point_type);
294 }
295
296 }
297 }
+0
-289
src/livecode/api.cpp less more
0 // SPDX-License-Identifier: GPL-2.0-or-later
1 /*
2 * API for the livecoding script language
3 *
4 * Authors:
5 * Sol Bekic <s+inkscape@s-ol.nu>
6 * Copyright (C) 2019 Authors
7 *
8 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
9 */
10
11 #include "svg/stringstream.h"
12 #include "svg/svg-color.h"
13 #include "svg/svg.h"
14 #include "document.h"
15 #include "display/sp-canvas-item.h"
16
17 #include "livecode/api.h"
18
19 namespace Inkscape {
20 namespace Livecode {
21
22 API::API(SPDesktop *desktop)
23 : desktop(desktop)
24 , doc_root(nullptr)
25 , ui_root(nullptr)
26 , _mouse(*this)
27 {
28 }
29
30 API::~API() {
31 if (doc_root) {
32 doc_root->deleteObject(true, true);
33 doc_root = nullptr;
34 }
35
36 if (ui_root) {
37 ui_root->deleteObject(true, true);
38 ui_root = nullptr;
39 }
40 }
41
42 Inkscape::XML::Node *API::make_rect(Geom::Rect const &rect, SPCSSAttr *css) {
43 SPDocument *doc = desktop->getDocument();
44 Inkscape::XML::Document *xml_doc = doc->getReprDoc();
45
46 Inkscape::XML::Node *repr = xml_doc->createElement("svg:rect");
47
48 sp_repr_set_svg_double(repr, "x", rect.left());
49 sp_repr_set_svg_double(repr, "y", rect.top());
50 sp_repr_set_svg_double(repr, "width", rect.width());
51 sp_repr_set_svg_double(repr, "height", rect.height());
52
53 if (css) {
54 Glib::ustring css_str;
55 sp_repr_css_write_string(css, css_str);
56 sp_repr_css_attr_unref(css);
57 repr->setAttribute("style", css_str.c_str());
58 }
59
60 return repr;
61 }
62
63 Inkscape::XML::Node *API::make_line(Geom::Point const &p1, Geom::Point const &p2, SPCSSAttr *css) {
64 SPDocument *doc = desktop->getDocument();
65 Inkscape::XML::Document *xml_doc = doc->getReprDoc();
66
67 Inkscape::XML::Node *repr = xml_doc->createElement("svg:line");
68
69 sp_repr_set_svg_double(repr, "x1", p1.x());
70 sp_repr_set_svg_double(repr, "y1", p1.y());
71 sp_repr_set_svg_double(repr, "x2", p2.x());
72 sp_repr_set_svg_double(repr, "y2", p2.y());
73
74 if (css) {
75 Glib::ustring css_str;
76 sp_repr_css_write_string(css, css_str);
77 sp_repr_css_attr_unref(css);
78 repr->setAttribute("style", css_str.c_str());
79 }
80
81 return repr;
82 }
83
84 Inkscape::XML::Node *API::make_path(Glib::ustring d, Geom::Point const &pos, SPCSSAttr *css) {
85 SPDocument *doc = desktop->getDocument();
86 Inkscape::XML::Document *xml_doc = doc->getReprDoc();
87
88 Inkscape::XML::Node *repr = xml_doc->createElement("svg:path");
89
90 sp_repr_set_svg_double(repr, "x", pos.x());
91 sp_repr_set_svg_double(repr, "y", pos.y());
92 repr->setAttribute("d", d.c_str());
93
94 if (css) {
95 Glib::ustring css_str;
96 sp_repr_css_write_string(css, css_str);
97 sp_repr_css_attr_unref(css);
98 repr->setAttribute("style", css_str.c_str());
99 }
100
101 return repr;
102 }
103
104 Inkscape::XML::Node *API::make_arrow(Geom::Point const &from, Geom::Point const &to, SPCSSAttr *css) {
105 SPDocument *doc = desktop->getDocument();
106 Inkscape::XML::Document *xml_doc = doc->getReprDoc();
107
108 Inkscape::XML::Node *repr = xml_doc->createElement("svg:path");
109
110 Geom::Point back = from - to;
111 back.normalize();
112 Geom::Point const cross_a = back.cw() + back * 2.0;
113 Geom::Point const cross_b = back.cw() + back * 2.0;
114
115 gchar* d = g_strdup_printf("M %f,%f %f,%f l %f,%f M %f,%f l %f,%f",
116 from.x(), from.y(),
117 to.x(), to.y(),
118 cross_a.x(), cross_a.y(),
119 to.x(), to.y(),
120 cross_b.x(), cross_b.y());
121 repr->setAttribute("d", d);
122 g_free(d);
123
124 Glib::ustring css_str;
125 if (css) {
126 sp_repr_css_write_string(css, css_str);
127 sp_repr_css_attr_unref(css);
128 } else {
129 css_str = "stroke: #000000;";
130 }
131 repr->setAttribute("style", css_str.c_str());
132
133 return repr;
134 }
135
136 namespace {
137 SPCSSAttr *handle_style() {
138 SPCSSAttr *css = sp_repr_css_attr_new();
139 sp_repr_css_set_property(css, "fill", "#ffffff");
140 sp_repr_css_set_property(css, "stroke-width", "0.2");
141 sp_repr_css_set_property(css, "stroke", "#000000");
142
143 return css;
144 }
145 }
146
147 bool API::input_point(Glib::ustring const &id, Geom::Point *point) {
148 auto const half_handle_size = Geom::Point(2, 2);
149 auto ui_point = *point * desktop->w2d().inverse();
150 Geom::Rect const rect(ui_point - half_handle_size, ui_point + half_handle_size);
151
152 SPCSSAttr *css = handle_style();
153 guint32 color = 0xffaaaaff;
154
155 if (rect.interiorContains(_mouse.ui_pos())) {
156 hot = id;
157 sp_repr_css_set_property(css, "fill", "#ff0000");
158 }
159
160 if (hot == id && _mouse.pressed()) {
161 active = id;
162 }
163
164 bool change = false;
165
166 if (active == id) {
167 sp_repr_css_set_property(css, "fill", "#0000ff");
168
169 auto const delta = _mouse.delta();
170 change = !delta.isZero();
171 *point += delta;
172 if (_mouse.released()) {
173 active = "";
174 }
175 }
176
177 Inkscape::XML::Node *repr = make_rect(rect, css);
178 draw_ui(id, repr);
179 return change;
180 }
181
182 bool API::input_line(Glib::ustring const &id, Geom::Point *p1, Geom::Point *p2) {
183 bool change = false;
184 if (input_point(id + "_p1", p1)) {
185 change = true;
186 }
187 if (input_point(id + "_p2", p2)) {
188 change = true;
189 }
190 draw_doc("", make_line(*p1, *p2));
191 return change;
192 }
193
194 bool API::input_arrow(Glib::ustring const &id, Geom::Point *from, Geom::Point *to) {
195 bool change = false;
196 if (input_point(id + "_from", from)) {
197 change = true;
198 }
199 if (input_point(id + "_to", to)) {
200 change = true;
201 }
202 draw_doc("", make_line(*from, *to));
203 return change;
204 }
205
206 bool API::input_rect(Glib::ustring const &id, Geom::Rect *rect) {
207 Geom::Point min = rect->min();
208 Geom::Point max = rect->max();
209
210 bool change = false;
211 if (input_point(id + "_min", &min)) {
212 Geom::Point const delta = min - rect->min();
213 *rect += delta;
214 change = true;
215 }
216 if (input_point(id + "_max", &max)) {
217 rect->setMax(max);
218 change = true;
219 }
220
221 draw_doc("", make_rect(*rect));
222 return change;
223 }
224
225 Mouse const &API::mouse() {
226 return _mouse;
227 }
228
229 void API::push_event(GdkEvent *event) {
230 _mouse.push_event(event);
231 }
232
233 void API::setup_frame() {
234 hot = "";
235
236 if (doc_root) {
237 doc_root->deleteObject(true, true);
238 doc_root = nullptr;
239 }
240
241 if (ui_root) {
242 ui_root->deleteObject(true, true);
243 ui_root = nullptr;
244 }
245
246 Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
247 Inkscape::XML::Node *rdoc = xml_doc->createElement("svg:g");
248 Inkscape::XML::Node *rui = xml_doc->createElement("svg:g");
249
250 doc_root = SP_ITEM(desktop->currentLayer()->appendChildRepr(rdoc));
251 doc_root->updateRepr();
252 Inkscape::GC::release(rdoc);
253
254 ui_root = SP_ITEM(desktop->currentLayer()->appendChildRepr(rui));
255 ui_root->doWriteTransform(ui2doc(), nullptr, true);
256 Inkscape::GC::release(rui);
257 }
258
259 void API::finish_frame() {
260 doc_root->updateRepr();
261 ui_root->updateRepr();
262 _mouse.finish_frame();
263 }
264
265 void API::draw_doc(Glib::ustring const &id, Inkscape::XML::Node *repr) {
266 repr->setAttribute("inkscape:livecode-id", id);
267 doc_root->appendChildRepr(repr);
268 Inkscape::GC::release(repr);
269 }
270 void API::draw_ui(Glib::ustring const &id, Inkscape::XML::Node *repr) {
271 repr->setAttribute("inkscape:livecode-id", id);
272 ui_root->appendChildRepr(repr);
273 Inkscape::GC::release(repr);
274 }
275
276 }
277 }
278
279 /*
280 Local Variables:
281 mode:c++
282 c-file-style:"stroustrup"
283 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
284 indent-tabs-mode:nil
285 fill-column:99
286 End:
287 */
288 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+0
-101
src/livecode/api.h less more
0 // SPDX-License-Identifier: GPL-2.0-or-later
1 #ifndef INK_LIVECODE_API_H
2 #define INK_LIVECODE_API_H
3
4 /*
5 * API for the livecoding script language
6 *
7 * Authors:
8 * Sol Bekic <s+inkscape@s-ol.nu>
9 * Copyright (C) 2019 Authors
10 *
11 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
12 */
13
14 #include <cstddef>
15 #include <2geom/point.h>
16 #include <2geom/rect.h>
17 #include <gdk/gdk.h>
18
19 #include "xml/repr.h"
20 #include "desktop.h"
21 #include "livecode/input.h"
22
23
24 class SPDocument;
25 class SPItem;
26
27 namespace Inkscape {
28 namespace Livecode {
29
30 class Mouse;
31
32 class API {
33 public:
34 API(SPDesktop *desktop);
35 ~API();
36
37 Inkscape::XML::Node *make_rect(Geom::Rect const &rect, SPCSSAttr *css = nullptr);
38 Inkscape::XML::Node *make_line(Geom::Point const &p1, Geom::Point const &p2, SPCSSAttr *css = nullptr);
39 Inkscape::XML::Node *make_path(Glib::ustring d, Geom::Point const &pos = Geom::Point(), SPCSSAttr *css = nullptr);
40 Inkscape::XML::Node *make_arrow(Geom::Point const &from, Geom::Point const &to, SPCSSAttr *css = nullptr);
41
42 bool input_point(Glib::ustring const &id, Geom::Point *point);
43 bool input_line(Glib::ustring const &id, Geom::Point *p1, Geom::Point *p2);
44 bool input_arrow(Glib::ustring const &id, Geom::Point *from, Geom::Point *to);
45 bool input_rect(Glib::ustring const &id, Geom::Rect *rect);
46
47 void draw_doc(Glib::ustring const &id, Inkscape::XML::Node *item);
48 void draw_ui(Glib::ustring const &id, Inkscape::XML::Node *item);
49
50 void push_event(GdkEvent *event);
51 void setup_frame();
52 void finish_frame();
53
54 inline Geom::Affine ui2dt() const {
55 return doc_root->i2doc_affine();
56 }
57 inline Geom::Affine dt2ui() const {
58 return ui2dt().inverse();
59 }
60
61 inline Geom::Affine ui2doc() const {
62 return desktop->w2d();
63 }
64 inline Geom::Affine doc2ui() const {
65 return ui2doc().inverse();
66 }
67 inline Geom::Affine ui2doc_vec() const {
68 return desktop->w2d().withoutTranslation();
69 }
70 inline Geom::Affine doc2ui_vec() const {
71 return ui2doc_vec().inverse();
72 }
73
74 Mouse const &mouse();
75
76 private:
77 SPDesktop *desktop;
78 SPItem *doc_root, *ui_root;
79
80 Mouse _mouse;
81
82 Glib::ustring hot, active;
83 std::vector<SPItem *> drawn_items;
84 };
85
86 }
87 }
88
89 #endif // INK_LIVECODE_API_H
90
91 /*
92 Local Variables:
93 mode:c++
94 c-file-style:"stroustrup"
95 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
96 indent-tabs-mode:nil
97 fill-column:99
98 End:
99 */
100 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
0 // SPDX-License-Identifier: GPL-2.0-or-later
1 /*
2 * Context for the livecoding script language
3 *
4 * Authors:
5 * Sol Bekic <s+inkscape@s-ol.nu>
6 * Copyright (C) 2019 Authors
7 *
8 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
9 */
10
11 #include <giomm/file.h>
12
13 #include "svg/stringstream.h"
14 #include "svg/svg-color.h"
15 #include "svg/svg.h"
16 #include "document.h"
17 #include "display/sp-canvas-item.h"
18
19 #include "livecode/context.h"
20 #include "livecode/api/api.h"
21
22 namespace Inkscape {
23 namespace Livecode {
24
25 Context::Context(SPDesktop *desktop)
26 : desktop(desktop)
27 , doc_root(nullptr)
28 , ui_root(nullptr)
29 , _mouse(*this)
30 , script_function(nullptr)
31 {
32 janet_init();
33
34 env = janet_core_env(NULL);
35 janet_lib_context(env, *this);
36 janet_lib_input(env);
37 janet_lib_geom_point(env);
38 }
39
40 Context::~Context() {
41 janet_deinit();
42
43 if (doc_root) {
44 doc_root->deleteObject(true, true);
45 doc_root = nullptr;
46 }
47
48 if (ui_root) {
49 ui_root->deleteObject(true, true);
50 ui_root = nullptr;
51 }
52 }
53
54 Inkscape::XML::Node *Context::make_rect(Geom::Rect const &rect, SPCSSAttr *css) {
55 SPDocument *doc = desktop->getDocument();
56 Inkscape::XML::Document *xml_doc = doc->getReprDoc();
57
58 Inkscape::XML::Node *repr = xml_doc->createElement("svg:rect");
59
60 sp_repr_set_svg_double(repr, "x", rect.left());
61 sp_repr_set_svg_double(repr, "y", rect.top());
62 sp_repr_set_svg_double(repr, "width", rect.width());
63 sp_repr_set_svg_double(repr, "height", rect.height());
64
65 if (css) {
66 Glib::ustring css_str;
67 sp_repr_css_write_string(css, css_str);
68 sp_repr_css_attr_unref(css);
69 repr->setAttribute("style", css_str.c_str());
70 }
71
72 return repr;
73 }
74
75 Inkscape::XML::Node *Context::make_line(Geom::Point const &p1, Geom::Point const &p2, SPCSSAttr *css) {
76 SPDocument *doc = desktop->getDocument();
77 Inkscape::XML::Document *xml_doc = doc->getReprDoc();
78
79 Inkscape::XML::Node *repr = xml_doc->createElement("svg:line");
80
81 sp_repr_set_svg_double(repr, "x1", p1.x());
82 sp_repr_set_svg_double(repr, "y1", p1.y());
83 sp_repr_set_svg_double(repr, "x2", p2.x());
84 sp_repr_set_svg_double(repr, "y2", p2.y());
85
86 if (css) {
87 Glib::ustring css_str;
88 sp_repr_css_write_string(css, css_str);
89 sp_repr_css_attr_unref(css);
90 repr->setAttribute("style", css_str.c_str());
91 }
92
93 return repr;
94 }
95
96 Inkscape::XML::Node *Context::make_path(Glib::ustring d, Geom::Point const &pos, SPCSSAttr *css) {
97 SPDocument *doc = desktop->getDocument();
98 Inkscape::XML::Document *xml_doc = doc->getReprDoc();
99
100 Inkscape::XML::Node *repr = xml_doc->createElement("svg:path");
101
102 sp_repr_set_svg_double(repr, "x", pos.x());
103 sp_repr_set_svg_double(repr, "y", pos.y());
104 repr->setAttribute("d", d.c_str());
105
106 if (css) {
107 Glib::ustring css_str;
108 sp_repr_css_write_string(css, css_str);
109 sp_repr_css_attr_unref(css);
110 repr->setAttribute("style", css_str.c_str());
111 }
112
113 return repr;
114 }
115
116 Inkscape::XML::Node *Context::make_arrow(Geom::Point const &from, Geom::Point const &to, SPCSSAttr *css) {
117 SPDocument *doc = desktop->getDocument();
118 Inkscape::XML::Document *xml_doc = doc->getReprDoc();
119
120 Inkscape::XML::Node *repr = xml_doc->createElement("svg:path");
121
122 Geom::Point back = from - to;
123 back.normalize();
124 Geom::Point const cross_a = back.cw() + back * 2.0;
125 Geom::Point const cross_b = back.cw() + back * 2.0;
126
127 gchar* d = g_strdup_printf("M %f,%f %f,%f l %f,%f M %f,%f l %f,%f",
128 from.x(), from.y(),
129 to.x(), to.y(),
130 cross_a.x(), cross_a.y(),
131 to.x(), to.y(),
132 cross_b.x(), cross_b.y());
133 repr->setAttribute("d", d);
134 g_free(d);
135
136 Glib::ustring css_str;
137 if (css) {
138 sp_repr_css_write_string(css, css_str);
139 sp_repr_css_attr_unref(css);
140 } else {
141 css_str = "stroke: #000000;";
142 }
143 repr->setAttribute("style", css_str.c_str());
144
145 return repr;
146 }
147
148 namespace {
149 SPCSSAttr *handle_style() {
150 SPCSSAttr *css = sp_repr_css_attr_new();
151 sp_repr_css_set_property(css, "fill", "#ffffff");
152 sp_repr_css_set_property(css, "stroke-width", "0.2");
153 sp_repr_css_set_property(css, "stroke", "#000000");
154
155 return css;
156 }
157 }
158
159 bool Context::input_point(Glib::ustring const &id, Geom::Point *point) {
160 auto const half_handle_size = Geom::Point(2, 2);
161 auto ui_point = *point * desktop->w2d().inverse();
162 Geom::Rect const rect(ui_point - half_handle_size, ui_point + half_handle_size);
163
164 SPCSSAttr *css = handle_style();
165 guint32 color = 0xffaaaaff;
166
167 if (rect.interiorContains(_mouse.ui_pos())) {
168 hot = id;
169 sp_repr_css_set_property(css, "fill", "#ff0000");
170 }
171
172 if (hot == id && _mouse.pressed()) {
173 active = id;
174 }
175
176 bool change = false;
177
178 if (active == id) {
179 sp_repr_css_set_property(css, "fill", "#0000ff");
180
181 auto const delta = _mouse.delta();
182 change = !delta.isZero();
183 *point += delta;
184 if (_mouse.released()) {
185 active = "";
186 }
187 }
188
189 Inkscape::XML::Node *repr = make_rect(rect, css);
190 draw_ui(id, repr);
191 return change;
192 }
193
194 bool Context::input_line(Glib::ustring const &id, Geom::Point *p1, Geom::Point *p2) {
195 bool change = false;
196 if (input_point(id + "_p1", p1)) {
197 change = true;
198 }
199 if (input_point(id + "_p2", p2)) {
200 change = true;
201 }
202 draw_doc("", make_line(*p1, *p2));
203 return change;
204 }
205
206 bool Context::input_arrow(Glib::ustring const &id, Geom::Point *from, Geom::Point *to) {
207 bool change = false;
208 if (input_point(id + "_from", from)) {
209 change = true;
210 }
211 if (input_point(id + "_to", to)) {
212 change = true;
213 }
214 draw_doc("", make_line(*from, *to));
215 return change;
216 }
217
218 bool Context::input_rect(Glib::ustring const &id, Geom::Rect *rect) {
219 Geom::Point min = rect->min();
220 Geom::Point max = rect->max();
221
222 bool change = false;
223 if (input_point(id + "_min", &min)) {
224 Geom::Point const delta = min - rect->min();
225 *rect += delta;
226 change = true;
227 }
228 if (input_point(id + "_max", &max)) {
229 rect->setMax(max);
230 change = true;
231 }
232
233 draw_doc("", make_rect(*rect));
234 return change;
235 }
236
237 Mouse const &Context::mouse() {
238 return _mouse;
239 }
240
241 void Context::push_event(GdkEvent *event) {
242 _mouse.push_event(event);
243 }
244
245 void Context::setup_frame() {
246 hot = "";
247
248 if (doc_root) {
249 doc_root->deleteObject(true, true);
250 doc_root = nullptr;
251 }
252
253 if (ui_root) {
254 ui_root->deleteObject(true, true);
255 ui_root = nullptr;
256 }
257
258 Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
259 Inkscape::XML::Node *rdoc = xml_doc->createElement("svg:g");
260 Inkscape::XML::Node *rui = xml_doc->createElement("svg:g");
261
262 doc_root = SP_ITEM(desktop->currentLayer()->appendChildRepr(rdoc));
263 doc_root->updateRepr();
264 Inkscape::GC::release(rdoc);
265
266 ui_root = SP_ITEM(desktop->currentLayer()->appendChildRepr(rui));
267 ui_root->doWriteTransform(ui2doc(), nullptr, true);
268 Inkscape::GC::release(rui);
269
270 if (script_file) {
271 try {
272 char *data;
273 gsize length;
274 script_file->load_contents(data, length);
275
276 Janet result;
277 janet_dobytes(env, (uint8_t *)data, length, script_file->get_path().c_str(), &result);
278 if (janet_checktype(result, JANET_FUNCTION)) {
279 script_function = janet_unwrap_function(result);
280 }
281 } catch (...) {
282 g_message("error loading file");
283 }
284 }
285
286 if (script_function) {
287 Janet result;
288 janet_pcall(script_function, 0, NULL, &result, NULL);
289 }
290 }
291
292 void Context::finish_frame() {
293 doc_root->updateRepr();
294 ui_root->updateRepr();
295 _mouse.finish_frame();
296 }
297
298 void Context::load_script(Glib::ustring const &path) {
299 g_message("loading file %s", path.c_str());
300 script_file = Gio::File::create_for_path(path);
301 }
302
303 void Context::draw_doc(Glib::ustring const &id, Inkscape::XML::Node *repr) {
304 repr->setAttribute("inkscape:livecode-id", id);
305 doc_root->appendChildRepr(repr);
306 Inkscape::GC::release(repr);
307 }
308 void Context::draw_ui(Glib::ustring const &id, Inkscape::XML::Node *repr) {
309 repr->setAttribute("inkscape:livecode-id", id);
310 ui_root->appendChildRepr(repr);
311 Inkscape::GC::release(repr);
312 }
313
314 }
315 }
316
317 /*
318 Local Variables:
319 mode:c++
320 c-file-style:"stroustrup"
321 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
322 indent-tabs-mode:nil
323 fill-column:99
324 End:
325 */
326 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
0 // SPDX-License-Identifier: GPL-2.0-or-later
1 #ifndef INK_LIVECODE_API_H
2 #define INK_LIVECODE_API_H
3
4 /*
5 * Context for the livecoding script language
6 *
7 * Authors:
8 * Sol Bekic <s+inkscape@s-ol.nu>
9 * Copyright (C) 2019 Authors
10 *
11 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
12 */
13
14 #include <cstddef>
15 #include <2geom/point.h>
16 #include <2geom/rect.h>
17 #include <gdk/gdk.h>
18 #include <janet.h>
19
20 #include "xml/repr.h"
21 #include "desktop.h"
22 #include "livecode/input.h"
23
24
25 class SPDocument;
26 class SPItem;
27
28 namespace Gio {
29 class File;
30 };
31
32 namespace Inkscape {
33 namespace Livecode {
34
35 class Mouse;
36
37 class Context {
38 public:
39 Context(SPDesktop *desktop);
40 ~Context();
41
42 Inkscape::XML::Node *make_rect(Geom::Rect const &rect, SPCSSAttr *css = nullptr);
43 Inkscape::XML::Node *make_line(Geom::Point const &p1, Geom::Point const &p2, SPCSSAttr *css = nullptr);
44 Inkscape::XML::Node *make_path(Glib::ustring d, Geom::Point const &pos = Geom::Point(), SPCSSAttr *css = nullptr);
45 Inkscape::XML::Node *make_arrow(Geom::Point const &from, Geom::Point const &to, SPCSSAttr *css = nullptr);
46
47 bool input_point(Glib::ustring const &id, Geom::Point *point);
48 bool input_line(Glib::ustring const &id, Geom::Point *p1, Geom::Point *p2);
49 bool input_arrow(Glib::ustring const &id, Geom::Point *from, Geom::Point *to);
50 bool input_rect(Glib::ustring const &id, Geom::Rect *rect);
51
52 void draw_doc(Glib::ustring const &id, Inkscape::XML::Node *item);
53 void draw_ui(Glib::ustring const &id, Inkscape::XML::Node *item);
54
55 void push_event(GdkEvent *event);
56 void setup_frame();
57 void finish_frame();
58
59 inline Geom::Affine ui2dt() const {
60 return doc_root->i2doc_affine();
61 }
62 inline Geom::Affine dt2ui() const {
63 return ui2dt().inverse();
64 }
65
66 inline Geom::Affine ui2doc() const {
67 return desktop->w2d();
68 }
69 inline Geom::Affine doc2ui() const {
70 return ui2doc().inverse();
71 }
72 inline Geom::Affine ui2doc_vec() const {
73 return desktop->w2d().withoutTranslation();
74 }
75 inline Geom::Affine doc2ui_vec() const {
76 return ui2doc_vec().inverse();
77 }
78
79 Mouse const &mouse();
80 void load_script(Glib::ustring const &path);
81
82 private:
83 SPDesktop *desktop;
84 SPItem *doc_root, *ui_root;
85
86 JanetTable *env;
87 JanetFunction *script_function;
88 Glib::RefPtr<Gio::File> script_file;
89
90 Mouse _mouse;
91
92 Glib::ustring hot, active;
93 std::vector<SPItem *> drawn_items;
94 };
95
96 }
97 }
98
99 #endif // INK_LIVECODE_API_H
100
101 /*
102 Local Variables:
103 mode:c++
104 c-file-style:"stroustrup"
105 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
106 indent-tabs-mode:nil
107 fill-column:99
108 End:
109 */
110 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
99 */
1010
1111 #include "livecode/input.h"
12 #include "livecode/api.h"
12 #include "livecode/context.h"
1313 #include "desktop.h"
1414
1515 namespace Inkscape {
1616 namespace Livecode {
1717
1818
19 Mouse::Mouse(API &api)
20 : api(api)
19 Mouse::Mouse(Context &context)
20 : context(context)
2121 {
2222 }
2323
3939 break;
4040 }
4141 case GDK_MOTION_NOTIFY: {
42 last_pos = Geom::Point(event->motion.x, event->motion.y) * api.dt2ui();
42 last_pos = Geom::Point(event->motion.x, event->motion.y) * context.dt2ui();
4343 break;
4444 }
4545 default:
7373 }
7474
7575 Geom::Point Mouse::pos() const {
76 return ui_pos() * api.ui2doc();
76 return ui_pos() * context.ui2doc();
7777 }
7878 Geom::Point Mouse::delta() const {
79 return ui_delta() * api.ui2doc_vec();
79 return ui_delta() * context.ui2doc_vec();
8080 }
8181
8282 Geom::Point Mouse::ui_pos() const {
1919 namespace Inkscape {
2020 namespace Livecode {
2121
22 class API;
22 class Context;
2323
2424 enum InputState {
2525 INPUTSTATE_NONE,
4343 bool released(guint button = 1) const;
4444
4545 private:
46 API& api;
46 Context& context;
4747
4848 guint last_mask, prev_mask;
4949 Geom::Point last_pos, prev_pos;
5050
51 Mouse(API &api);
51 Mouse(Context &context);
5252
5353 void push_event(GdkEvent *event);
5454 void finish_frame();
5555
56 friend class API;
56 friend class Context;
5757 };
5858
5959 }
+0
-0
src/livecode/janet-2geom less more
(Empty file)
4545 static void update_script_list(GtkListStore *model_files) {
4646 gtk_list_store_clear(model_files);
4747 auto prefs = Inkscape::Preferences::get();
48 Glib::ustring library_path= prefs->getString("/tools/livecode/library_dir");
48 Glib::ustring const library_path = prefs->getString("/tools/livecode/library_dir");
4949 Glib::RefPtr<Gio::File> library_dir = Gio::File::create_for_path(library_path);
5050
5151 auto enumerator = library_dir->enumerate_children();
7171 namespace Toolbar {
7272 LivecodeToolbar::LivecodeToolbar(SPDesktop *desktop)
7373 : Toolbar(desktop)
74 , _freeze(false)
7475 {
7576 auto prefs = Inkscape::Preferences::get();
7677
131132
132133 LivecodeTool *tool = get_livecode_tool();
133134 if (tool) {
134 // tool->loadScript(path);
135 tool->load_script(path);
135136 }
136137
137138 _freeze = false;
5252
5353 LivecodeTool::LivecodeTool()
5454 : ToolBase(nullptr, false)
55 , api(SP_ACTIVE_DESKTOP)
55 , context(SP_ACTIVE_DESKTOP)
5656 {
5757 }
5858
8282
8383 ret = ToolBase::root_handler(event);
8484 if (!ret) {
85 api.push_event(event);
85 context.push_event(event);
8686 }
8787
8888 return ret;
89 }
90
91 void LivecodeTool::load_script(Glib::ustring const &path)
92 {
93 context.load_script(path);
8994 }
9095
9196 static Geom::Point p(100, 100);
9499
95100 bool LivecodeTool::handle_tick(Glib::RefPtr<Gdk::FrameClock> const &frame_clock)
96101 {
97 api.setup_frame();
102 context.setup_frame();
98103
99 api.input_point("p", &p);
100 api.input_arrow("a->b", &a, &b);
101 api.input_rect("rect", &rect);
104 context.input_point("p", &p);
105 context.input_arrow("a->b", &a, &b);
106 context.input_rect("rect", &rect);
102107
103 api.finish_frame();
108 context.finish_frame();
104109 return true;
105110 }
106111
1818 #include "display/canvas-text.h"
1919 #include "display/canvas-temporary-item.h"
2020 #include "ui/control-manager.h"
21 #include "livecode/api.h"
21 #include "livecode/context.h"
2222 #include <boost/optional.hpp>
2323
2424 #define SP_LIVECODE_CONTEXT(obj) (dynamic_cast<Inkscape::UI::Tools::LivecodeTool*>((Inkscape::UI::Tools::ToolBase*)obj))
4242 bool root_handler(GdkEvent* event) override;
4343 const std::string& getPrefsPath() override;
4444
45 void load_script(Glib::ustring const &path);
46
4547 private:
4648 bool handle_tick(Glib::RefPtr<Gdk::FrameClock> const &frame_clock);
4749
4850 guint tick_callback;
49 Livecode::API api;
51 Livecode::Context context;
5052 };
5153
5254 }