summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2019-12-02 14:32:42 +0000
committers-ol <s-ol@users.noreply.github.com>2019-12-02 14:32:42 +0000
commit81fe2250a70c892eeb195725117d566a042e5c93 (patch)
treee2c70bd1b0f9e9d9063f6ff7aa11f6fa6b8ced80 /src
parentadd basic livecode toolbar (diff)
downloadinkscape-81fe2250a70c892eeb195725117d566a042e5c93.tar.gz
inkscape-81fe2250a70c892eeb195725117d566a042e5c93.zip
add draft janet interface for livecoding
Diffstat (limited to 'src')
-rw-r--r--src/livecode/CMakeLists.txt8
-rw-r--r--src/livecode/api/api.h34
-rw-r--r--src/livecode/api/context.cpp21
-rw-r--r--src/livecode/api/input.cpp113
-rw-r--r--src/livecode/api/point.cpp298
-rw-r--r--src/livecode/context.cpp (renamed from src/livecode/api.cpp)74
-rw-r--r--src/livecode/context.h (renamed from src/livecode/api.h)18
-rw-r--r--src/livecode/input.cpp12
-rw-r--r--src/livecode/input.h8
m---------src/livecode/janet-2geom0
-rw-r--r--src/ui/toolbar/livecode-toolbar.cpp5
-rw-r--r--src/ui/tools/livecode-tool.cpp19
-rw-r--r--src/ui/tools/livecode-tool.h6
13 files changed, 571 insertions, 45 deletions
diff --git a/src/livecode/CMakeLists.txt b/src/livecode/CMakeLists.txt
index ba266998e..96e1574fc 100644
--- a/src/livecode/CMakeLists.txt
+++ b/src/livecode/CMakeLists.txt
@@ -1,12 +1,16 @@
# SPDX-License-Identifier: GPL-2.0-or-later
set(livecode_SRC
- api.cpp
+ context.cpp
input.cpp
+ api/context.cpp
+ api/input.cpp
+ api/point.cpp
# HEADERS
- api.h
+ context.h
input.h
+ api/api.h
)
add_inkscape_source("${livecode_SRC}")
diff --git a/src/livecode/api/api.h b/src/livecode/api/api.h
new file mode 100644
index 000000000..94694ca56
--- /dev/null
+++ b/src/livecode/api/api.h
@@ -0,0 +1,34 @@
+#ifndef JANET_2GEOM_POINT_INCLUDED
+#define JANET_2GEOM_POINT_INCLUDED
+
+#include <janet.h>
+#include <2geom/point.h>
+#include "livecode/context.h"
+#include "livecode/input.h"
+
+namespace Inkscape {
+namespace Livecode {
+
+/* context.cpp */
+void janet_lib_context(JanetTable *env, Context &context);
+
+Context &ctx();
+
+/* point.cpp */
+void janet_lib_geom_point(JanetTable *env);
+
+extern const JanetAbstractType geom_point_type;
+
+Janet janet_wrap_point(Geom::Point const &x);
+Janet janet_wrap_point(Geom::IntPoint const &x);
+Geom::Point janet_unwrap_point(Janet x);
+
+/* input.cpp */
+void janet_lib_input(JanetTable *env);
+
+Janet janet_wrap_inputstate(InputState const &state);
+
+}
+}
+
+#endif // JANET_2GEOM_POINT_INCLUDED
diff --git a/src/livecode/api/context.cpp b/src/livecode/api/context.cpp
new file mode 100644
index 000000000..43c6881d1
--- /dev/null
+++ b/src/livecode/api/context.cpp
@@ -0,0 +1,21 @@
+#include "livecode/api/api.h"
+
+namespace Inkscape {
+namespace Livecode {
+
+static Context *_context = nullptr;
+
+Context &ctx() {
+ if (!_context) {
+ janet_panic("Livecode Context uninitialized!!");
+ }
+
+ return *_context;
+}
+
+void janet_lib_context(JanetTable *env, Context &context) {
+ _context = &context;
+}
+
+}
+}
diff --git a/src/livecode/api/input.cpp b/src/livecode/api/input.cpp
new file mode 100644
index 000000000..0fc820bbd
--- /dev/null
+++ b/src/livecode/api/input.cpp
@@ -0,0 +1,113 @@
+#include "livecode/api/api.h"
+
+#include <sstream>
+
+namespace Inkscape {
+namespace Livecode {
+
+extern "C" Janet cfun_mouse_pos(int32_t argc, Janet *argv) {
+ janet_fixarity(argc, 0);
+ return janet_wrap_point(ctx().mouse().pos());
+}
+
+extern "C" Janet cfun_mouse_delta(int32_t argc, Janet *argv) {
+ janet_fixarity(argc, 0);
+ return janet_wrap_point(ctx().mouse().delta());
+}
+
+extern "C" Janet cfun_mouse_ui_pos(int32_t argc, Janet *argv) {
+ janet_fixarity(argc, 0);
+ return janet_wrap_point(ctx().mouse().ui_pos());
+}
+
+extern "C" Janet cfun_mouse_ui_delta(int32_t argc, Janet *argv) {
+ janet_fixarity(argc, 0);
+ return janet_wrap_point(ctx().mouse().ui_delta());
+}
+
+Janet janet_wrap_inputstate(InputState const &state) {
+ switch (state) {
+ case INPUTSTATE_NONE:
+ return janet_wrap_nil();
+ case INPUTSTATE_HOVER:
+ return janet_ckeywordv("hover");
+ case INPUTSTATE_PRESSED:
+ return janet_ckeywordv("pressed");
+ case INPUTSTATE_HELD:
+ return janet_ckeywordv("held");
+ case INPUTSTATE_RELEASED:
+ return janet_ckeywordv("released");
+ default:
+ janet_panic("unexpected event value");
+ }
+}
+
+extern "C" Janet cfun_mouse_event(int32_t argc, Janet *argv) {
+ janet_arity(argc, 0, 1);
+
+ guint button = janet_getsize(argv, 1);
+ if (button < 1 || button > 5) {
+ janet_panic("expected button to be between 1 and 5");
+ }
+
+ return janet_wrap_inputstate(ctx().mouse().event(button));
+}
+
+#define BUTTONMETHOD(name) \
+extern "C" Janet cfun_mouse_##name(int32_t argc, Janet *argv) { \
+ janet_arity(argc, 0, 1); \
+ guint button = janet_getsize(argv, 1); \
+ if (button < 1 || button > 5) { \
+ janet_panic("expected button to be between 1 and 5"); \
+ } \
+ return janet_wrap_boolean(ctx().mouse().name(button)); \
+}
+
+BUTTONMETHOD(pressed)
+BUTTONMETHOD(held)
+BUTTONMETHOD(released)
+
+const JanetReg it_cfuns[] = {
+ {
+ "mouse/pos", cfun_mouse_pos,
+ "(mouse/pos)\n\nGet the current mouse position as a geom/point."
+ },
+ {
+ "mouse/delta", cfun_mouse_delta,
+ "(mouse/pos)\n\nGet the mouse motion since last frame as a geom/point."
+ },
+ {
+ "mouse/ui-pos", cfun_mouse_ui_pos,
+ "(mouse/pos)\n\nGet the current mouse position as a geom/point, in UI space."
+ },
+ {
+ "mouse/ui-delta", cfun_mouse_ui_delta,
+ "(mouse/pos)\n\nGet the mouse motion since last frame as a geom/point, in UI space."
+ },
+ {
+ "mouse/event", cfun_mouse_event,
+ "(mouse/event [button])\n\nGet the current event/status for a mouse button.\n"
+ "Returns either nil, :pressed, :held or :released."
+ },
+ {
+ "mouse/pressed", cfun_mouse_pressed,
+ "(mouse/pressed [button])\n\nCheck whether a mouse button was pressed this frame.\n"
+ },
+ {
+ "mouse/held", cfun_mouse_held,
+ "(mouse/held [button])\n\nCheck whether a mouse button was held down this frame.\n"
+ },
+ {
+ "mouse/released", cfun_mouse_released,
+ "(mouse/released [button])\n\nCheck whether a mouse button was released this frame.\n"
+ },
+ {NULL, NULL, NULL}
+};
+
+
+void janet_lib_input(JanetTable *env) {
+ janet_cfuns(env, NULL, it_cfuns);
+}
+
+}
+}
diff --git a/src/livecode/api/point.cpp b/src/livecode/api/point.cpp
new file mode 100644
index 000000000..6eab6af1d
--- /dev/null
+++ b/src/livecode/api/point.cpp
@@ -0,0 +1,298 @@
+#include "livecode/api/api.h"
+
+#include <sstream>
+
+namespace Inkscape {
+namespace Livecode {
+
+extern "C" Janet geom_point_get(void *p, Janet key);
+extern "C" void geom_point_set(void *p, Janet key, Janet value);
+
+extern "C" void geom_point_tostring(void *p, JanetBuffer *buffer) {
+ std::stringstream stream;
+ stream << "<2geom/point " << *static_cast<Geom::Point *>(p) << ">";
+ janet_buffer_push_cstring(buffer, stream.str().c_str());
+}
+
+
+const JanetAbstractType geom_point_type = {
+ "2geom/point",
+ NULL,
+ NULL,
+ geom_point_get,
+ geom_point_set,
+ NULL,
+ NULL,
+ geom_point_tostring
+};
+
+
+Janet janet_wrap_point(Geom::Point const &x) {
+ Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
+ *box = Geom::Point(x);
+ return janet_wrap_abstract(box);
+}
+
+Janet janet_wrap_point(Geom::IntPoint const &x) {
+ Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
+ *box = Geom::Point(x);
+ return janet_wrap_abstract(box);
+}
+
+Geom::Point janet_unwrap_point(Janet x) {
+ if (janet_checktype(x, JANET_ABSTRACT)) {
+ void *abst = janet_unwrap_abstract(x);
+ if (janet_abstract_type(abst) == &geom_point_type)
+ return *(Geom::Point *)abst;
+ }
+
+ janet_panic("expected a geom/point");
+}
+
+Geom::Point janet_unwrap_point_or_scalar(Janet x) {
+ if (janet_checktype(x, JANET_ABSTRACT)) {
+ void *abst = janet_unwrap_abstract(x);
+ if (janet_abstract_type(abst) == &geom_point_type)
+ return *(Geom::Point *)abst;
+ } else if (janet_checktype(x, JANET_NUMBER)) {
+ double val = janet_unwrap_number(x);
+ return Geom::Point(val, val);
+ }
+
+ janet_panic("expected a geom/point");
+}
+
+
+Geom::Point& janet_unwrap_point_ref(Janet x) {
+ if (janet_checktype(x, JANET_ABSTRACT)) {
+ void *abst = janet_unwrap_abstract(x);
+ if (janet_abstract_type(abst) == &geom_point_type)
+ return *(Geom::Point *)abst;
+ }
+
+ janet_panic("expected a geom/point");
+}
+
+extern "C" Janet cfun_geom_point_new(int32_t argc, Janet *argv) {
+ janet_arity(argc, 0, 2);
+ double x = 0;
+ double y = 0;
+ if (argc == 2) {
+ x = janet_getnumber(argv, 0);
+ y = janet_getnumber(argv, 1);
+ } else if (argc == 1) {
+ x = janet_getnumber(argv, 0);
+ y = x;
+ }
+ return janet_wrap_point(Geom::Point(x, y));
+}
+
+const JanetReg it_cfuns[] = {
+ {
+ "point", cfun_geom_point_new,
+ "(geom/point x y)\n\nCreate a Point from x/y coordinate values."
+ },
+ {NULL, NULL, NULL}
+};
+
+static Janet cfun_geom_point_add(int32_t argc, Janet *argv) {
+ janet_arity(argc, 2, -1);
+ Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
+ *box = janet_unwrap_point(argv[0]);
+ for (int i = 1; i < argc; i++)
+ *box += janet_unwrap_point(argv[i]);
+ return janet_wrap_abstract(box);
+}
+
+static Janet cfun_geom_point_add_mut(int32_t argc, Janet *argv) {
+ janet_arity(argc, 2, -1);
+ Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
+ for (int i = 1; i < argc; i++)
+ *box += janet_unwrap_point(argv[i]);
+ return janet_wrap_abstract(box);
+}
+
+static Janet cfun_geom_point_sub(int32_t argc, Janet *argv) {
+ janet_arity(argc, 2, -1);
+ Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
+ *box = janet_unwrap_point(argv[0]);
+ for (int i = 1; i < argc; i++)
+ *box -= janet_unwrap_point(argv[i]);
+ return janet_wrap_abstract(box);
+}
+
+static Janet cfun_geom_point_sub_mut(int32_t argc, Janet *argv) {
+ janet_arity(argc, 2, -1);
+ Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
+ for (int i = 1; i < argc; i++)
+ *box -= janet_unwrap_point(argv[i]);
+ return janet_wrap_abstract(box);
+}
+
+static Janet cfun_geom_point_mul(int32_t argc, Janet *argv) {
+ janet_arity(argc, 2, -1);
+ Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
+ *box = janet_unwrap_point(argv[0]);
+ for (int i = 1; i < argc; i++) {
+ Geom::Point arg = janet_unwrap_point_or_scalar(argv[i]);
+ (*box)[0] *= arg[0];
+ (*box)[1] *= arg[1];
+ }
+ return janet_wrap_abstract(box);
+}
+
+static Janet cfun_geom_point_mul_mut(int32_t argc, Janet *argv) {
+ janet_arity(argc, 2, -1);
+ Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
+ for (int i = 1; i < argc; i++) {
+ Geom::Point arg = janet_unwrap_point_or_scalar(argv[i]);
+ (*box)[0] *= arg[0];
+ (*box)[1] *= arg[1];
+ }
+ return janet_wrap_abstract(box);
+}
+
+static Janet cfun_geom_point_div(int32_t argc, Janet *argv) {
+ janet_arity(argc, 2, -1);
+ Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point));
+ *box = janet_unwrap_point(argv[0]);
+ for (int i = 1; i < argc; i++) {
+ Geom::Point arg = janet_unwrap_point_or_scalar(argv[i]);
+ (*box)[0] /= arg[0];
+ (*box)[1] /= arg[1];
+ }
+ return janet_wrap_abstract(box);
+}
+
+static Janet cfun_geom_point_div_mut(int32_t argc, Janet *argv) {
+ janet_arity(argc, 2, -1);
+ Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
+ for (int i = 1; i < argc; i++) {
+ Geom::Point arg = janet_unwrap_point_or_scalar(argv[i]);
+ (*box)[0] /= arg[0];
+ (*box)[1] /= arg[1];
+ }
+ return janet_wrap_abstract(box);
+}
+
+static Janet cfun_geom_point_eq(int32_t argc, Janet *argv) {
+ janet_fixarity(argc, 2);
+ Geom::Point& v1 = janet_unwrap_point_ref(argv[0]);
+ Geom::Point& v2 = janet_unwrap_point_ref(argv[1]);
+ return janet_wrap_boolean(v1 == v2);
+}
+
+static Janet cfun_geom_point_lt(int32_t argc, Janet *argv) {
+ janet_fixarity(argc, 2);
+ Geom::Point& v1 = janet_unwrap_point_ref(argv[0]);
+ Geom::Point& v2 = janet_unwrap_point_ref(argv[1]);
+ return janet_wrap_boolean(v1 < v2);
+}
+
+#define CONSTMETHOD(name, method, type) \
+static Janet cfun_geom_point_##name(int32_t argc, Janet *argv) { \
+ janet_fixarity(argc, 1); \
+ Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type); \
+ return janet_wrap_##type(box->method()); \
+}
+
+CONSTMETHOD(is_zero, isZero, boolean)
+CONSTMETHOD(is_finite, isFinite, boolean)
+CONSTMETHOD(is_normalized, isNormalized, boolean)
+
+CONSTMETHOD(x, x, number)
+CONSTMETHOD(y, y, number)
+CONSTMETHOD(length, length, number)
+
+CONSTMETHOD(cw, cw, point)
+CONSTMETHOD(ccw, ccw, point)
+CONSTMETHOD(round, round, point)
+CONSTMETHOD(floor, floor, point)
+CONSTMETHOD(ceil, ceil, point)
+CONSTMETHOD(normalize, normalized, point)
+
+static Janet cfun_geom_point_normalize_mut(int32_t argc, Janet *argv) {
+ janet_fixarity(argc, 1);
+ Geom::Point *box = (Geom::Point *)janet_getabstract(argv, 0, &geom_point_type);
+ box->normalize();
+ return janet_wrap_point(*box);
+}
+
+static JanetMethod geom_point_methods[] = {
+ {"+", cfun_geom_point_add},
+ {"-", cfun_geom_point_sub},
+ {"*", cfun_geom_point_mul},
+ {"/", cfun_geom_point_div},
+ {"<", cfun_geom_point_lt},
+ {"==", cfun_geom_point_eq},
+
+ {"+!", cfun_geom_point_add_mut},
+ {"-!", cfun_geom_point_sub_mut},
+ {"*!", cfun_geom_point_mul_mut},
+ {"/!", cfun_geom_point_div_mut},
+
+ {"zero?", cfun_geom_point_is_zero},
+ {"finite?", cfun_geom_point_is_finite},
+ {"normalized?", cfun_geom_point_is_normalized},
+
+ {"x", cfun_geom_point_x},
+ {"y", cfun_geom_point_y},
+ {"length", cfun_geom_point_length},
+
+ {"cw", cfun_geom_point_cw},
+ {"ccw", cfun_geom_point_ccw},
+ {"round", cfun_geom_point_round},
+ {"floor", cfun_geom_point_floor},
+ {"ceil", cfun_geom_point_ceil},
+ {"normalize", cfun_geom_point_normalize},
+
+ {"normalize!", cfun_geom_point_normalize_mut},
+
+ {NULL, NULL}
+};
+
+extern "C" Janet geom_point_get(void *p, Janet key) {
+ Geom::Point *box = (Geom::Point *)p;
+
+ if (janet_checktype(key, JANET_KEYWORD))
+ return janet_getmethod(janet_unwrap_keyword(key), geom_point_methods);
+
+ if (!janet_checksize(key)) janet_panic("expected size as key");
+
+ size_t const index = (size_t) janet_unwrap_number(key);
+ switch (index) {
+ case 0:
+ return janet_wrap_number((*box)[0]);
+ case 1:
+ return janet_wrap_number((*box)[1]);
+ default:
+ return janet_wrap_nil();
+ }
+}
+
+extern "C" void geom_point_set(void *p, Janet key, Janet value) {
+ Geom::Point *box = (Geom::Point *)p;
+
+ if (!janet_checksize(key)) janet_panic("expected size as key");
+ if (!janet_checktype(key, JANET_NUMBER)) janet_panic("expected number as value");
+
+ size_t const index = (size_t) janet_unwrap_number(key);
+ switch (index) {
+ case 0:
+ (*box)[0] = janet_unwrap_number(value);
+ break;
+ case 1:
+ (*box)[1] = janet_unwrap_number(value);
+ break;
+ default:
+ janet_panic("index out of bounds");
+ }
+}
+
+void janet_lib_geom_point(JanetTable *env) {
+ janet_cfuns(env, NULL, it_cfuns);
+ janet_register_abstract_type(&geom_point_type);
+}
+
+}
+}
diff --git a/src/livecode/api.cpp b/src/livecode/context.cpp
index 4617968c2..a4b59e9b0 100644
--- a/src/livecode/api.cpp
+++ b/src/livecode/context.cpp
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * API for the livecoding script language
+ * Context for the livecoding script language
*
* Authors:
* Sol Bekic <s+inkscape@s-ol.nu>
@@ -9,26 +9,38 @@
* Released under GNU GPL v2+, read the file 'COPYING' for more information.
*/
+#include <giomm/file.h>
+
#include "svg/stringstream.h"
#include "svg/svg-color.h"
#include "svg/svg.h"
#include "document.h"
#include "display/sp-canvas-item.h"
-#include "livecode/api.h"
+#include "livecode/context.h"
+#include "livecode/api/api.h"
namespace Inkscape {
namespace Livecode {
-API::API(SPDesktop *desktop)
+Context::Context(SPDesktop *desktop)
: desktop(desktop)
, doc_root(nullptr)
, ui_root(nullptr)
, _mouse(*this)
+ , script_function(nullptr)
{
+ janet_init();
+
+ env = janet_core_env(NULL);
+ janet_lib_context(env, *this);
+ janet_lib_input(env);
+ janet_lib_geom_point(env);
}
-API::~API() {
+Context::~Context() {
+ janet_deinit();
+
if (doc_root) {
doc_root->deleteObject(true, true);
doc_root = nullptr;
@@ -40,7 +52,7 @@ API::~API() {
}
}
-Inkscape::XML::Node *API::make_rect(Geom::Rect const &rect, SPCSSAttr *css) {
+Inkscape::XML::Node *Context::make_rect(Geom::Rect const &rect, SPCSSAttr *css) {
SPDocument *doc = desktop->getDocument();
Inkscape::XML::Document *xml_doc = doc->getReprDoc();
@@ -61,7 +73,7 @@ Inkscape::XML::Node *API::make_rect(Geom::Rect const &rect, SPCSSAttr *css) {
return repr;
}
-Inkscape::XML::Node *API::make_line(Geom::Point const &p1, Geom::Point const &p2, SPCSSAttr *css) {
+Inkscape::XML::Node *Context::make_line(Geom::Point const &p1, Geom::Point const &p2, SPCSSAttr *css) {
SPDocument *doc = desktop->getDocument();
Inkscape::XML::Document *xml_doc = doc->getReprDoc();
@@ -82,7 +94,7 @@ Inkscape::XML::Node *API::make_line(Geom::Point const &p1, Geom::Point const &p2
return repr;
}
-Inkscape::XML::Node *API::make_path(Glib::ustring d, Geom::Point const &pos, SPCSSAttr *css) {
+Inkscape::XML::Node *Context::make_path(Glib::ustring d, Geom::Point const &pos, SPCSSAttr *css) {
SPDocument *doc = desktop->getDocument();
Inkscape::XML::Document *xml_doc = doc->getReprDoc();
@@ -102,7 +114,7 @@ Inkscape::XML::Node *API::make_path(Glib::ustring d, Geom::Point const &pos, SPC
return repr;
}
-Inkscape::XML::Node *API::make_arrow(Geom::Point const &from, Geom::Point const &to, SPCSSAttr *css) {
+Inkscape::XML::Node *Context::make_arrow(Geom::Point const &from, Geom::Point const &to, SPCSSAttr *css) {
SPDocument *doc = desktop->getDocument();
Inkscape::XML::Document *xml_doc = doc->getReprDoc();
@@ -145,7 +157,7 @@ SPCSSAttr *handle_style() {
}
}
-bool API::input_point(Glib::ustring const &id, Geom::Point *point) {
+bool Context::input_point(Glib::ustring const &id, Geom::Point *point) {
auto const half_handle_size = Geom::Point(2, 2);
auto ui_point = *point * desktop->w2d().inverse();
Geom::Rect const rect(ui_point - half_handle_size, ui_point + half_handle_size);
@@ -180,7 +192,7 @@ bool API::input_point(Glib::ustring const &id, Geom::Point *point) {
return change;
}
-bool API::input_line(Glib::ustring const &id, Geom::Point *p1, Geom::Point *p2) {
+bool Context::input_line(Glib::ustring const &id, Geom::Point *p1, Geom::Point *p2) {
bool change = false;
if (input_point(id + "_p1", p1)) {
change = true;
@@ -192,7 +204,7 @@ bool API::input_line(Glib::ustring const &id, Geom::Point *p1, Geom::Point *p2)
return change;
}
-bool API::input_arrow(Glib::ustring const &id, Geom::Point *from, Geom::Point *to) {
+bool Context::input_arrow(Glib::ustring const &id, Geom::Point *from, Geom::Point *to) {
bool change = false;
if (input_point(id + "_from", from)) {
change = true;
@@ -204,7 +216,7 @@ bool API::input_arrow(Glib::ustring const &id, Geom::Point *from, Geom::Point *t
return change;
}
-bool API::input_rect(Glib::ustring const &id, Geom::Rect *rect) {
+bool Context::input_rect(Glib::ustring const &id, Geom::Rect *rect) {
Geom::Point min = rect->min();
Geom::Point max = rect->max();
@@ -223,15 +235,15 @@ bool API::input_rect(Glib::ustring const &id, Geom::Rect *rect) {
return change;
}
-Mouse const &API::mouse() {
+Mouse const &Context::mouse() {
return _mouse;
}
-void API::push_event(GdkEvent *event) {
+void Context::push_event(GdkEvent *event) {
_mouse.push_event(event);
}
-void API::setup_frame() {
+void Context::setup_frame() {
hot = "";
if (doc_root) {
@@ -255,20 +267,46 @@ void API::setup_frame() {
ui_root = SP_ITEM(desktop->currentLayer()->appendChildRepr(rui));
ui_root->doWriteTransform(ui2doc(), nullptr, true);
Inkscape::GC::release(rui);
+
+ if (script_file) {
+ try {
+ char *data;
+ gsize length;
+ script_file->load_contents(data, length);
+
+ Janet result;
+ janet_dobytes(env, (uint8_t *)data, length, script_file->get_path().c_str(), &result);
+ if (janet_checktype(result, JANET_FUNCTION)) {
+ script_function = janet_unwrap_function(result);
+ }
+ } catch (...) {
+ g_message("error loading file");
+ }
+ }
+
+ if (script_function) {
+ Janet result;
+ janet_pcall(script_function, 0, NULL, &result, NULL);
+ }
}
-void API::finish_frame() {
+void Context::finish_frame() {
doc_root->updateRepr();
ui_root->updateRepr();
_mouse.finish_frame();
}
-void API::draw_doc(Glib::ustring const &id, Inkscape::XML::Node *repr) {
+void Context::load_script(Glib::ustring const &path) {
+ g_message("loading file %s", path.c_str());
+ script_file = Gio::File::create_for_path(path);
+}
+
+void Context::draw_doc(Glib::ustring const &id, Inkscape::XML::Node *repr) {
repr->setAttribute("inkscape:livecode-id", id);
doc_root->appendChildRepr(repr);
Inkscape::GC::release(repr);
}
-void API::draw_ui(Glib::ustring const &id, Inkscape::XML::Node *repr) {
+void Context::draw_ui(Glib::ustring const &id, Inkscape::XML::Node *repr) {
repr->setAttribute("inkscape:livecode-id", id);
ui_root->appendChildRepr(repr);
Inkscape::GC::release(repr);
diff --git a/src/livecode/api.h b/src/livecode/context.h
index d2974a01d..fb6b59ff7 100644
--- a/src/livecode/api.h
+++ b/src/livecode/context.h
@@ -3,7 +3,7 @@
#define INK_LIVECODE_API_H
/*
- * API for the livecoding script language
+ * Context for the livecoding script language
*
* Authors:
* Sol Bekic <s+inkscape@s-ol.nu>
@@ -16,6 +16,7 @@
#include <2geom/point.h>
#include <2geom/rect.h>
#include <gdk/gdk.h>
+#include <janet.h>
#include "xml/repr.h"
#include "desktop.h"
@@ -25,15 +26,19 @@
class SPDocument;
class SPItem;
+namespace Gio {
+class File;
+};
+
namespace Inkscape {
namespace Livecode {
class Mouse;
-class API {
+class Context {
public:
- API(SPDesktop *desktop);
- ~API();
+ Context(SPDesktop *desktop);
+ ~Context();
Inkscape::XML::Node *make_rect(Geom::Rect const &rect, SPCSSAttr *css = nullptr);
Inkscape::XML::Node *make_line(Geom::Point const &p1, Geom::Point const &p2, SPCSSAttr *css = nullptr);
@@ -73,11 +78,16 @@ public:
}
Mouse const &mouse();
+ void load_script(Glib::ustring const &path);
private:
SPDesktop *desktop;
SPItem *doc_root, *ui_root;
+ JanetTable *env;
+ JanetFunction *script_function;
+ Glib::RefPtr<Gio::File> script_file;
+
Mouse _mouse;
Glib::ustring hot, active;
diff --git a/src/livecode/input.cpp b/src/livecode/input.cpp
index 4dab43fc9..b3b505712 100644
--- a/src/livecode/input.cpp
+++ b/src/livecode/input.cpp
@@ -10,15 +10,15 @@
*/
#include "livecode/input.h"
-#include "livecode/api.h"
+#include "livecode/context.h"
#include "desktop.h"
namespace Inkscape {
namespace Livecode {
-Mouse::Mouse(API &api)
- : api(api)
+Mouse::Mouse(Context &context)
+ : context(context)
{
}
@@ -40,7 +40,7 @@ void Mouse::push_event(GdkEvent *event)
break;
}
case GDK_MOTION_NOTIFY: {
- last_pos = Geom::Point(event->motion.x, event->motion.y) * api.dt2ui();
+ last_pos = Geom::Point(event->motion.x, event->motion.y) * context.dt2ui();
break;
}
default:
@@ -74,10 +74,10 @@ bool Mouse::released(guint button) const {
}
Geom::Point Mouse::pos() const {
- return ui_pos() * api.ui2doc();
+ return ui_pos() * context.ui2doc();
}
Geom::Point Mouse::delta() const {
- return ui_delta() * api.ui2doc_vec();
+ return ui_delta() * context.ui2doc_vec();
}
Geom::Point Mouse::ui_pos() const {
diff --git a/src/livecode/input.h b/src/livecode/input.h
index 0b9977af8..570415836 100644
--- a/src/livecode/input.h
+++ b/src/livecode/input.h
@@ -20,7 +20,7 @@
namespace Inkscape {
namespace Livecode {
-class API;
+class Context;
enum InputState {
INPUTSTATE_NONE,
@@ -44,17 +44,17 @@ public:
bool released(guint button = 1) const;
private:
- API& api;
+ Context& context;
guint last_mask, prev_mask;
Geom::Point last_pos, prev_pos;
- Mouse(API &api);
+ Mouse(Context &context);
void push_event(GdkEvent *event);
void finish_frame();
- friend class API;
+ friend class Context;
};
}
diff --git a/src/livecode/janet-2geom b/src/livecode/janet-2geom
deleted file mode 160000
-Subproject a3495ede6711d3221780ebbc9adb9a230120655
diff --git a/src/ui/toolbar/livecode-toolbar.cpp b/src/ui/toolbar/livecode-toolbar.cpp
index 81533fec7..ee3a8b3c0 100644
--- a/src/ui/toolbar/livecode-toolbar.cpp
+++ b/src/ui/toolbar/livecode-toolbar.cpp
@@ -46,7 +46,7 @@ static LivecodeTool *get_livecode_tool()
static void update_script_list(GtkListStore *model_files) {
gtk_list_store_clear(model_files);
auto prefs = Inkscape::Preferences::get();
- Glib::ustring library_path= prefs->getString("/tools/livecode/library_dir");
+ Glib::ustring const library_path = prefs->getString("/tools/livecode/library_dir");
Glib::RefPtr<Gio::File> library_dir = Gio::File::create_for_path(library_path);
auto enumerator = library_dir->enumerate_children();
@@ -72,6 +72,7 @@ namespace UI {
namespace Toolbar {
LivecodeToolbar::LivecodeToolbar(SPDesktop *desktop)
: Toolbar(desktop)
+ , _freeze(false)
{
auto prefs = Inkscape::Preferences::get();
@@ -132,7 +133,7 @@ void LivecodeToolbar::active_script_value_changed()
LivecodeTool *tool = get_livecode_tool();
if (tool) {
- // tool->loadScript(path);
+ tool->load_script(path);
}
_freeze = false;
diff --git a/src/ui/tools/livecode-tool.cpp b/src/ui/tools/livecode-tool.cpp
index 0071f47b3..8b096dbf0 100644
--- a/src/ui/tools/livecode-tool.cpp
+++ b/src/ui/tools/livecode-tool.cpp
@@ -53,7 +53,7 @@ const std::string LivecodeTool::prefsPath = "/tools/livecode";
LivecodeTool::LivecodeTool()
: ToolBase(nullptr, false)
- , api(SP_ACTIVE_DESKTOP)
+ , context(SP_ACTIVE_DESKTOP)
{
}
@@ -83,25 +83,30 @@ bool LivecodeTool::root_handler(GdkEvent* event)
ret = ToolBase::root_handler(event);
if (!ret) {
- api.push_event(event);
+ context.push_event(event);
}
return ret;
}
+void LivecodeTool::load_script(Glib::ustring const &path)
+{
+ context.load_script(path);
+}
+
static Geom::Point p(100, 100);
static Geom::Point a(50, 100), b(120, 300);
static Geom::Rect rect(Geom::Point(20, 200), Geom::Point(220, 20));
bool LivecodeTool::handle_tick(Glib::RefPtr<Gdk::FrameClock> const &frame_clock)
{
- api.setup_frame();
+ context.setup_frame();
- api.input_point("p", &p);
- api.input_arrow("a->b", &a, &b);
- api.input_rect("rect", &rect);
+ context.input_point("p", &p);
+ context.input_arrow("a->b", &a, &b);
+ context.input_rect("rect", &rect);
- api.finish_frame();
+ context.finish_frame();
return true;
}
diff --git a/src/ui/tools/livecode-tool.h b/src/ui/tools/livecode-tool.h
index fdeb61264..63d85c2e8 100644
--- a/src/ui/tools/livecode-tool.h
+++ b/src/ui/tools/livecode-tool.h
@@ -19,7 +19,7 @@
#include "display/canvas-text.h"
#include "display/canvas-temporary-item.h"
#include "ui/control-manager.h"
-#include "livecode/api.h"
+#include "livecode/context.h"
#include <boost/optional.hpp>
#define SP_LIVECODE_CONTEXT(obj) (dynamic_cast<Inkscape::UI::Tools::LivecodeTool*>((Inkscape::UI::Tools::ToolBase*)obj))
@@ -43,11 +43,13 @@ public:
bool root_handler(GdkEvent* event) override;
const std::string& getPrefsPath() override;
+ void load_script(Glib::ustring const &path);
+
private:
bool handle_tick(Glib::RefPtr<Gdk::FrameClock> const &frame_clock);
guint tick_callback;
- Livecode::API api;
+ Livecode::Context context;
};
}