Commit 7722303f authored by Jonathan Wilkes's avatar Jonathan Wilkes
Browse files

add text editor window for [text define]

parent 3d7a9406
<!DOCTYPE html>
<html>
<head>
<link id="page_style" rel="stylesheet" type="text/css" href="css/default.css">
</head>
<body class="dialog_body">
<div class="container">
<textarea id="text" style="width: 100%; box-sizing: border-box; height: 85vh; resize: none;">
</textarea>
</div>
<div class="submit_buttons">
<button type="button" onClick="ok()" data-i18n="[title]iem.prop.ok_tt">
<span data-i18n="iem.prop.ok"></span>
</button>
<button type="button" onClick="cancel()" data-i18n="[title]iem.prop.cancel_tt">
<span data-i18n="iem.prop.cancel"></span>
</button>
</div>
<dialog id="save_before_quit">
<h4>Do you want to save the changes you made before closing the window?
</h4>
<div class="submit_buttons">
<button type="button"
onClick="ok()"
id="dialog_yes_button"
data-i18n="[title]canvas.save_dialog.yes_tt">
<span data-i18n="canvas.save_dialog.yes"></span>
</button>
<button type="button"
onClick="cancel()"
id="dialog_no_button"
data-i18n="[title]canvas.save_dialog.no_tt">
<span data-i18n="canvas.save_dialog.no"></span>
</button>
<button type="button"
onClick="close_modal_dialog()"
id="dialog_cancel_button"
data-i18n="[title]canvas.save_dialog.cancel_tt">
<span data-i18n="canvas.save_dialog.cancel"></span>
</button>
</div>
</dialog>
<script>
"use strict";
var gui = require("nw.gui");
var pdgui = require("./pdgui.js");
// For translations
var l = pdgui.get_local_string;
pdgui.skin.apply(window);
var pd_object_callback;
var dirty = false;
function apply() {
var text_array = document.getElementById("text").value.split("\n");
pdgui.post("applying...");
// clear out Pd's binbuf for our text object
pdgui.pdsend(pd_object_callback, "clear");
text_array.forEach(function (line) {
line = line.replace(",", " \\, ");
line = line.replace(";", " \\; ");
line = line.replace("$", " \\$ ");
pdgui.pdsend(pd_object_callback, "addline", line);
});
dirty = 0;
}
function cancel() {
//window.close(true);
close_window();
}
function ok() {
apply();
cancel();
}
// Close the modal dialog that appears after clicking the window "x"
// with a dirty textarea
function close_modal_dialog() {
document.getElementById("save_before_quit").close();
}
function textarea_clear() {
document.getElementById("text").value = "";
dirty = true;
}
function textarea_append(line) {
document.getElementById("text").value += line;
dirty = true;
}
function set_dirty(state) {
dirty = state;
}
// This gets called from the nw_create_window function in index.html
// It provides us with our window id from the C side. Once we have it
// we can create the menu and register event callbacks
function register_window_id(gfxstub, text_string) {
var head, tail, templates, data, data_separator;
pd_object_callback = gfxstub;
add_events(gfxstub);
translate_form();
pdgui.pdsend(gfxstub, "map");
// populate_form(text_string); // Fill the form we created with the actual data
// We don't turn on rendering of the "container" div until
// We've finished displaying all the spans and populating the
// labels and form elements. That makes it more efficient and
// snappier, at least on older machines.
document.getElementsByClassName("container")[0]
.style.setProperty("display", "inline");
}
// Stop-gap translator
function translate_form() {
var elements = document.querySelectorAll("[data-i18n]"),
data,
i;
for (i = 0; i < elements.length; i++) {
data = elements[i].dataset.i18n;
if (data.slice(0, 7) === "[title]") {
elements[i].title = l(data.slice(7));
} else {
elements[i].textContent = l(data);
}
}
}
function get_attr(name, attrs) {
return attrs[attrs.indexOf(name) + 1];
}
function get_elem(name) {
return document.getElementById(name);
}
function close_window() {
pdgui.pdsend(pd_object_callback, "close");
pdgui.remove_dialogwin(pd_object_callback);
gui.Window.get().close(true);
}
function close_from_pd(signoff) {
if (signoff) {
pdgui.pdsend(pd_object_callback, "signoff");
}
pdgui.remove_dialogwin(pd_object_callback);
gui.Window.get().close(true);
}
function add_events(name) {
// closing the Window
gui.Window.get().on("close", function () {
// this needs to do whatever the "cancel" button does
//pdgui.pdsend(name, "menuclose 0");
//cancel();
// blur the textarea to trigger an onchange if it was modified
document.getElementById("text").blur();
if (dirty) {
document.getElementById("save_before_quit").showModal();
} else {
close_window();
}
});
document.getElementById("text").onchange = function() {
dirty = true;
}
// Right now the bindings are limited to "Enter = Ok" and "Escape = Cancel".
// We leave off those bindings since Enter starts a new line in the textarea
//pdgui.dialog_bindings(name);
}
</script>
</body>
</html>
......@@ -3727,6 +3727,42 @@ function gui_data_dialog(did, data_string) {
data_string);
}
function gui_text_dialog_clear(did) {
if (dialogwin[did]) {
dialogwin[did].window.textarea_clear();
}
}
function gui_text_dialog_append(did, line) {
if (dialogwin[did]) {
dialogwin[did].window.textarea_append(line);
}
}
function gui_text_dialog_set_dirty(did, state) {
if (dialogwin[did]) {
dialogwin[did].window.set_dirty(state !== 0);
}
}
function gui_text_dialog(did, width, height, font_size) {
dialogwin[did] = create_window(did, "text", width, height,
popup_coords[2], popup_coords[3],
font_size);
}
function gui_text_dialog_raise(did) {
if (dialogwin[did]) {
dialogwin[did].focus();
}
}
function gui_text_dialog_close_from_pd(did, signoff) {
if (dialogwin[did]) {
dialogwin[did].window.close_from_pd(signoff !== 0);
}
}
function gui_remove_gfxstub(did) {
if (dialogwin[did] !== undefined && dialogwin[did] !== null) {
dialogwin[did].window.close(true);
......
......@@ -61,46 +61,78 @@ static void textbuf_senditup(t_textbuf *x)
{
int i, ntxt;
char *txt;
/* I don't think the Pd Vanilla interface can handle cases
where a single line is greater than MAXPDSTRING, at least
coming from the GUI to Pd. So instead of the %.*s specifier
we just use a character array of MAXPDSTRING size. I suppose
that means we'll fail on the Pd side, while Pd Vanilla would
fail when the GUI tries to forward that line back to Pd.
*/
char buf[MAXPDSTRING];
if (!x->b_guiconnect)
return;
binbuf_gettext(x->b_binbuf, &txt, &ntxt);
sys_vgui("pdtk_textwindow_clear .x%lx\n", x);
//sys_vgui("pdtk_textwindow_clear .x%lx\n", x);
gui_vmess("gui_text_dialog_clear", "x", x);
for (i = 0; i < ntxt; )
{
char *j = strchr(txt+i, '\n');
if (!j) j = txt + ntxt;
sys_vgui("pdtk_textwindow_append .x%lx {%.*s\n}\n",
x, j-txt-i, txt+i);
//sys_vgui("pdtk_textwindow_append .x%lx {%.*s\n}\n",
// x, j-txt-i, txt+i);
if (j - txt - i >= MAXPDSTRING)
{
pd_error(x, "text: can't display lines greater than %d characters",
MAXPDSTRING);
break;
}
sprintf(buf, "%.*s\n", j-txt-i, txt+i);
gui_vmess("gui_text_dialog_append", "xs",
x, buf);
i = (j-txt)+1;
}
sys_vgui("pdtk_textwindow_setdirty .x%lx 0\n", x);
//sys_vgui("pdtk_textwindow_setdirty .x%lx 0\n", x);
gui_vmess("gui_text_dialog_set_dirty", "xi", x, 0);
t_freebytes(txt, ntxt);
}
static void textbuf_map(t_textbuf *x)
{
if (x->b_guiconnect)
textbuf_senditup(x);
}
static void textbuf_open(t_textbuf *x)
{
if (x->b_guiconnect)
{
sys_vgui("wm deiconify .x%lx\n", x);
sys_vgui("raise .x%lx\n", x);
sys_vgui("focus .x%lx.text\n", x);
//sys_vgui("wm deiconify .x%lx\n", x);
//sys_vgui("raise .x%lx\n", x);
//sys_vgui("focus .x%lx.text\n", x);
gui_vmess("gui_text_dialog_raise", "x", x);
}
else
{
char buf[40];
sys_vgui("pdtk_textwindow_open .x%lx %dx%d {%s: %s} %d\n",
x, 600, 340, "myname", "text",
sys_hostfontsize(glist_getfont(x->b_canvas)));//,
//sys_vgui("pdtk_textwindow_open .x%lx %dx%d {%s: %s} %d\n",
// x, 600, 340, "myname", "text",
// sys_hostfontsize(glist_getfont(x->b_canvas)));//,
//glist_getzoom(x->b_canvas)));
sprintf(buf, ".x%lx", (unsigned long)x);
sprintf(buf, "x%lx", (unsigned long)x);
x->b_guiconnect = guiconnect_new(&x->b_ob.ob_pd, gensym(buf));
textbuf_senditup(x);
gui_vmess("gui_text_dialog", "xiii",
x,
600,
340,
sys_hostfontsize(glist_getfont(x->b_canvas)));
//textbuf_senditup(x);
}
}
static void textbuf_close(t_textbuf *x)
{
sys_vgui("pdtk_textwindow_doclose .x%lx\n", x);
//sys_vgui("pdtk_textwindow_doclose .x%lx\n", x);
gui_vmess("gui_text_dialog_close_from_pd", "x", x, 1);
if (x->b_guiconnect)
{
guiconnect_notarget(x->b_guiconnect, 1000);
......@@ -197,7 +229,8 @@ static void textbuf_free(t_textbuf *x)
binbuf_free(x->b_binbuf);
if (x->b_guiconnect)
{
sys_vgui("destroy .x%lx\n", x);
//sys_vgui("destroy .x%lx\n", x);
gui_vmess("gui_text_dialog_close_from_pd", "xi", x, 0);
guiconnect_notarget(x->b_guiconnect, 1000);
}
/* just in case we're still bound to #A from loading... */
......@@ -1889,6 +1922,8 @@ void x_qlist_setup(void )
text_define_class = class_new(gensym("text define"),
(t_newmethod)text_define_new,
(t_method)text_define_free, sizeof(t_text_define), 0, A_GIMME, 0);
class_addmethod(text_define_class, (t_method)textbuf_map,
gensym("map"), 0);
class_addmethod(text_define_class, (t_method)textbuf_open,
gensym("click"), 0);
class_addmethod(text_define_class, (t_method)textbuf_close,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment