summaryrefslogtreecommitdiffstats
path: root/src/livecode
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2019-12-02 20:33:28 +0000
committers-ol <s-ol@users.noreply.github.com>2019-12-02 20:33:28 +0000
commit1b69cd09de1e70d36cbca5f0c4a3f289ec684343 (patch)
tree42a91646b60d7879c1d541e921adddff4052a732 /src/livecode
parentadd draft janet interface for livecoding (diff)
downloadinkscape-1b69cd09de1e70d36cbca5f0c4a3f289ec684343.tar.gz
inkscape-1b69cd09de1e70d36cbca5f0c4a3f289ec684343.zip
more janet bindings
Diffstat (limited to 'src/livecode')
-rw-r--r--src/livecode/api/api.h2
-rw-r--r--src/livecode/api/context.cpp43
-rw-r--r--src/livecode/api/input.cpp1
-rw-r--r--src/livecode/api/point.cpp27
-rw-r--r--src/livecode/context.cpp116
-rw-r--r--src/livecode/context.h34
6 files changed, 161 insertions, 62 deletions
diff --git a/src/livecode/api/api.h b/src/livecode/api/api.h
index 94694ca56..4df3f40be 100644
--- a/src/livecode/api/api.h
+++ b/src/livecode/api/api.h
@@ -21,7 +21,7 @@ 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);
+Geom::Point &janet_unwrap_point(Janet x);
/* input.cpp */
void janet_lib_input(JanetTable *env);
diff --git a/src/livecode/api/context.cpp b/src/livecode/api/context.cpp
index 43c6881d1..f5da3f7cd 100644
--- a/src/livecode/api/context.cpp
+++ b/src/livecode/api/context.cpp
@@ -13,8 +13,51 @@ Context &ctx() {
return *_context;
}
+extern "C" Janet cfun_input_point(int32_t argc, Janet *argv) {
+ janet_fixarity(argc, 2);
+ ctx().input_point(janet_getcstring(argv, 0),
+ &janet_unwrap_point(argv[1]));
+ return janet_wrap_nil();
+}
+
+extern "C" Janet cfun_input_line(int32_t argc, Janet *argv) {
+ janet_fixarity(argc, 3);
+ ctx().input_line(janet_getcstring(argv, 0),
+ &janet_unwrap_point(argv[1]),
+ &janet_unwrap_point(argv[2]));
+ return janet_wrap_nil();
+}
+
+extern "C" Janet cfun_input_arrow(int32_t argc, Janet *argv) {
+ janet_fixarity(argc, 3);
+ ctx().input_arrow(janet_getcstring(argv, 0),
+ &janet_unwrap_point(argv[1]),
+ &janet_unwrap_point(argv[2]));
+ return janet_wrap_nil();
+}
+
+const JanetReg it_cfuns[] = {
+ {
+ "input/point", cfun_input_point,
+ "(input/point id p)\n\nMake p modifiable via a handle.\n"
+ "This function mutates p."
+ },
+ {
+ "input/line", cfun_input_line,
+ "(input/line id p1 p2)\n\nMake a modifiable line between p1 and p2\n"
+ "This function mutates p1 and p2."
+ },
+ {
+ "input/arrow", cfun_input_arrow,
+ "(input/arrow id from to)\n\nMake a modifiable arrow between from and to\n"
+ "This function mutates from and to."
+ },
+ {NULL, NULL, NULL}
+};
+
void janet_lib_context(JanetTable *env, Context &context) {
_context = &context;
+ janet_cfuns(env, NULL, it_cfuns);
}
}
diff --git a/src/livecode/api/input.cpp b/src/livecode/api/input.cpp
index 0fc820bbd..1677e68eb 100644
--- a/src/livecode/api/input.cpp
+++ b/src/livecode/api/input.cpp
@@ -106,6 +106,7 @@ const JanetReg it_cfuns[] = {
void janet_lib_input(JanetTable *env) {
+ janet_printf("yoloading");
janet_cfuns(env, NULL, it_cfuns);
}
diff --git a/src/livecode/api/point.cpp b/src/livecode/api/point.cpp
index 6eab6af1d..25d03d4bb 100644
--- a/src/livecode/api/point.cpp
+++ b/src/livecode/api/point.cpp
@@ -10,13 +10,13 @@ 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) << ">";
+ stream << "<geom/point " << *static_cast<Geom::Point *>(p) << ">";
janet_buffer_push_cstring(buffer, stream.str().c_str());
}
const JanetAbstractType geom_point_type = {
- "2geom/point",
+ "geom/point",
NULL,
NULL,
geom_point_get,
@@ -39,7 +39,7 @@ Janet janet_wrap_point(Geom::IntPoint const &x) {
return janet_wrap_abstract(box);
}
-Geom::Point janet_unwrap_point(Janet x) {
+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)
@@ -62,17 +62,6 @@ Geom::Point janet_unwrap_point_or_scalar(Janet x) {
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;
@@ -89,7 +78,7 @@ extern "C" Janet cfun_geom_point_new(int32_t argc, Janet *argv) {
const JanetReg it_cfuns[] = {
{
- "point", cfun_geom_point_new,
+ "geom/point", cfun_geom_point_new,
"(geom/point x y)\n\nCreate a Point from x/y coordinate values."
},
{NULL, NULL, NULL}
@@ -177,15 +166,15 @@ static Janet cfun_geom_point_div_mut(int32_t argc, Janet *argv) {
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]);
+ Geom::Point &v1 = janet_unwrap_point(argv[0]);
+ Geom::Point &v2 = janet_unwrap_point(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]);
+ Geom::Point &v1 = janet_unwrap_point(argv[0]);
+ Geom::Point &v2 = janet_unwrap_point(argv[1]);
return janet_wrap_boolean(v1 < v2);
}
diff --git a/src/livecode/context.cpp b/src/livecode/context.cpp
index a4b59e9b0..a22191400 100644
--- a/src/livecode/context.cpp
+++ b/src/livecode/context.cpp
@@ -9,7 +9,7 @@
* Released under GNU GPL v2+, read the file 'COPYING' for more information.
*/
-#include <giomm/file.h>
+#include <memory>
#include "svg/stringstream.h"
#include "svg/svg-color.h"
@@ -23,12 +23,56 @@
namespace Inkscape {
namespace Livecode {
+Script::Script(JanetTable *env, std::string const &path)
+ : env(env)
+ , function(nullptr)
+ , file(Gio::File::create_for_path(path))
+ , monitor(file->monitor_file())
+{
+ monitor->signal_changed().connect(sigc::mem_fun(this, &Script::file_changed));
+ reload();
+}
+
+void Script::frame() {
+ if (function) {
+ Janet result;
+ janet_pcall(function, 0, NULL, &result, NULL);
+ }
+}
+
+void Script::commit() {
+}
+
+void Script::reload() {
+ try {
+ uint8_t *data;
+ size_t length;
+ file->load_contents((char *&)data, (gsize &)length);
+
+ Janet result;
+ janet_dobytes(env, data, length, file->get_path().c_str(), &result);
+ if (janet_checktype(result, JANET_FUNCTION)) {
+ function = janet_unwrap_function(result);
+ } else {
+ g_message("Janet script didn't return a function");
+ }
+ } catch (...) {
+ g_message("error loading file");
+ }
+}
+
+void Script::file_changed(const Glib::RefPtr<Gio::File>& file,
+ const Glib::RefPtr<Gio::File>& other_file,
+ Gio::FileMonitorEvent event)
+{
+ reload();
+}
+
Context::Context(SPDesktop *desktop)
: desktop(desktop)
+ , _mouse(*this)
, doc_root(nullptr)
, ui_root(nullptr)
- , _mouse(*this)
- , script_function(nullptr)
{
janet_init();
@@ -122,8 +166,8 @@ Inkscape::XML::Node *Context::make_arrow(Geom::Point const &from, Geom::Point co
Geom::Point back = from - to;
back.normalize();
- Geom::Point const cross_a = back.cw() + back * 2.0;
- Geom::Point const cross_b = back.cw() + back * 2.0;
+ Geom::Point const cross_a = back.cw() * 5.0 + back * 10.0;
+ Geom::Point const cross_b = back.ccw() * 5.0 + back * 10.0;
gchar* d = g_strdup_printf("M %f,%f %f,%f l %f,%f M %f,%f l %f,%f",
from.x(), from.y(),
@@ -134,14 +178,12 @@ Inkscape::XML::Node *Context::make_arrow(Geom::Point const &from, Geom::Point co
repr->setAttribute("d", d);
g_free(d);
- Glib::ustring css_str;
if (css) {
+ Glib::ustring css_str;
sp_repr_css_write_string(css, css_str);
sp_repr_css_attr_unref(css);
- } else {
- css_str = "stroke: #000000;";
+ repr->setAttribute("style", css_str.c_str());
}
- repr->setAttribute("style", css_str.c_str());
return repr;
}
@@ -200,7 +242,12 @@ bool Context::input_line(Glib::ustring const &id, Geom::Point *p1, Geom::Point *
if (input_point(id + "_p2", p2)) {
change = true;
}
- draw_doc("", make_line(*p1, *p2));
+
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property(css, "stroke-width", "1");
+ sp_repr_css_set_property(css, "stroke", "#000000");
+ sp_repr_css_set_property(css, "fill", "none");
+ draw_doc("", make_line(*p1, *p2, css));
return change;
}
@@ -212,7 +259,12 @@ bool Context::input_arrow(Glib::ustring const &id, Geom::Point *from, Geom::Poin
if (input_point(id + "_to", to)) {
change = true;
}
- draw_doc("", make_line(*from, *to));
+
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property(css, "stroke-width", "1");
+ sp_repr_css_set_property(css, "stroke", "#000000");
+ sp_repr_css_set_property(css, "fill", "none");
+ draw_doc("", make_arrow(*from, *to, css));
return change;
}
@@ -243,6 +295,16 @@ void Context::push_event(GdkEvent *event) {
_mouse.push_event(event);
}
+void Context::frame() {
+ setup_frame();
+
+ if (_script) {
+ _script->frame();
+ }
+
+ finish_frame();
+}
+
void Context::setup_frame() {
hot = "";
@@ -267,27 +329,6 @@ void Context::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 Context::finish_frame() {
@@ -297,8 +338,15 @@ void Context::finish_frame() {
}
void Context::load_script(Glib::ustring const &path) {
- g_message("loading file %s", path.c_str());
- script_file = Gio::File::create_for_path(path);
+ g_message("loading script %s", path.c_str());
+ _script = nullptr;
+
+ try {
+ _script.reset(new Script(env, path));
+ g_message("loaded.");
+ } catch (...) {
+ g_message("error creating script");
+ }
}
void Context::draw_doc(Glib::ustring const &id, Inkscape::XML::Node *repr) {
diff --git a/src/livecode/context.h b/src/livecode/context.h
index fb6b59ff7..4ebb73609 100644
--- a/src/livecode/context.h
+++ b/src/livecode/context.h
@@ -16,6 +16,8 @@
#include <2geom/point.h>
#include <2geom/rect.h>
#include <gdk/gdk.h>
+#include <giomm/file.h>
+#include <giomm/filemonitor.h>
#include <janet.h>
#include "xml/repr.h"
@@ -26,15 +28,30 @@
class SPDocument;
class SPItem;
-namespace Gio {
-class File;
-};
-
namespace Inkscape {
namespace Livecode {
class Mouse;
+class Script {
+public:
+ Script(JanetTable *env, std::string const &path);
+
+ void frame();
+ void commit();
+
+private:
+ JanetTable *env;
+ JanetFunction *function;
+ Glib::RefPtr<Gio::File> file;
+ Glib::RefPtr<Gio::FileMonitor> monitor;
+
+ void reload();
+ void file_changed(const Glib::RefPtr<Gio::File>& file,
+ const Glib::RefPtr<Gio::File>& other_file,
+ Gio::FileMonitorEvent event);
+};
+
class Context {
public:
Context(SPDesktop *desktop);
@@ -54,8 +71,7 @@ public:
void draw_ui(Glib::ustring const &id, Inkscape::XML::Node *item);
void push_event(GdkEvent *event);
- void setup_frame();
- void finish_frame();
+ void frame();
inline Geom::Affine ui2dt() const {
return doc_root->i2doc_affine();
@@ -81,13 +97,15 @@ public:
void load_script(Glib::ustring const &path);
private:
+ void setup_frame();
+ void finish_frame();
+
SPDesktop *desktop;
SPItem *doc_root, *ui_root;
JanetTable *env;
- JanetFunction *script_function;
- Glib::RefPtr<Gio::File> script_file;
+ std::unique_ptr<Script> _script;
Mouse _mouse;
Glib::ustring hot, active;