From 08a3de2ddaf4aca63d17553853c30cfb03edf125 Mon Sep 17 00:00:00 2001 From: Jonathan Wilkes <jon.w.wilkes@gmail.com> Date: Wed, 15 Apr 2015 01:25:50 -0400 Subject: [PATCH] some code cleanup, and first attempt at array settings inside canvas dialog --- pd/nw/dialog_canvas.css | 138 ++++ pd/nw/dialog_canvas.html | 678 +++++++++++++++++ pd/nw/dialog_iemgui.css | 113 +++ pd/nw/dialog_iemgui.html | 604 ++++++++++++++++ pd/nw/index.html | 6 +- pd/nw/locales/en/translation.json | 59 ++ pd/nw/pd_canvas.css | 102 +++ pd/nw/pd_canvas.html | 1125 +++++++++++++++++++++++++++++ pd/nw/pdgui.js | 246 +++++-- pd/nw/todo.txt | 20 + pd/src/g_all_guis.c | 13 +- pd/src/g_array.c | 57 +- pd/src/g_canvas.c | 2 + pd/src/g_editor.c | 114 ++- pd/src/g_graph.c | 15 +- pd/src/g_magicglass.c | 4 +- pd/src/g_mycanvas.c | 4 +- pd/src/g_rtext.c | 4 +- pd/src/g_scalar.c | 5 +- pd/src/g_template.c | 99 ++- pd/src/g_text.c | 50 +- pd/src/s_inter.c | 10 +- 22 files changed, 3317 insertions(+), 151 deletions(-) create mode 100644 pd/nw/dialog_canvas.css create mode 100644 pd/nw/dialog_canvas.html create mode 100644 pd/nw/dialog_iemgui.css create mode 100644 pd/nw/dialog_iemgui.html create mode 100644 pd/nw/pd_canvas.css create mode 100644 pd/nw/pd_canvas.html diff --git a/pd/nw/dialog_canvas.css b/pd/nw/dialog_canvas.css new file mode 100644 index 000000000..5a2e244d0 --- /dev/null +++ b/pd/nw/dialog_canvas.css @@ -0,0 +1,138 @@ +@font-face { + font-family: "DejaVu Sans Mono"; + src: url("DejaVuSansMono.ttf"); +} + +body { + font-family:Verdana; + margin: 0px; +} + +fieldset { + font-family:Georgia; + background-color:#eeeeee; + border-radius:3px; + border:2px solid black; + margin-left:auto; + margin-right:auto; + padding: 10px; +} + +input[type="text"]{ + width:3em; +} + +input[type="number"]{ + width:3em; +} + +div.x-scale { + padding: 3px; + text-align: center; +} + +div.gop-range { +} + +div.y1 { + text-align: center; + padding: 3px; +} + +div.x1 { + text-align: center; + padding: 3px; +} + +div.y2 { + text-align: center; + padding: 3px; +} + + +.disabled { + color: #aaa; +} + +.prop{ +} + +.hidden { + display: none; +} + +.container{ + display: none; +} + +body { +} + +.noselect { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +text { + // fill: red; + cursor: default; +} + +.selected_border { + stroke: blue; + stroke-dasharray: none; + stroke-width: 1; +} + +label { + text-align: right; +// margin-right: auto; +// margin-left: auto; +} + +.pair { + width: 75%; + text-align: left; + align: left; +} + +.item1 { + width: 50%; +} + +.item2 { + width: 50%; +} + +input[name="x-offset"] { + width: 2em; +} + +input[name="y-offset"] { + width: 2em; +} + +input[name="send-symbol"] { + width: 8em; +} + +input[name="receive-symbol"] { + width: 8em; +} + +input[name="label"] { + width: 8em; +} + +input[name="font-size"] { + width: 3em; +} + +.submit_buttons { + text-align: center; + padding: 8px; +} diff --git a/pd/nw/dialog_canvas.html b/pd/nw/dialog_canvas.html new file mode 100644 index 000000000..f44304c8c --- /dev/null +++ b/pd/nw/dialog_canvas.html @@ -0,0 +1,678 @@ +<!DOCTYPE html> +<html> + <head> + <link rel="stylesheet" type="text/css" href="dialog_canvas.css"> + </head> + <body> + <div class="container noselect"> + <form> + + <fieldset> + <legend data-i18n="canvas.prop.heading.gop"></legend> + + <table class="pairs"> + <tr class="display-flags prop hidden" data-i18n="[title]canvas.prop.gop_tt"> + <td> + <input type="checkbox" name="gop" value="on"> + </td> + <td> + <span id="gop_label" data-i18n="canvas.prop.gop"></span> + </td> + </tr> + <tr class="x-pix prop hidden"> + <td> + </td> + <td> + <table> + <tr> + <td> + <label class="gop_opt" data-i18n="[title]canvas.prop.x_pix_tt"> + <span data-i18n="canvas.prop.x_pix"></span> + </label> + </td> + <td data-i18n="[title]canvas.prop.x_pix_tt"> + <input class="gop_opt" type="text" name="x-pix"> + </td> + <td> + <label class="gop_opt" data-i18n="[title]canvas.prop.y_pix_tt"> + <span data-i18n="canvas.prop.y_pix"></span> + </label> + </td> + <td data-i18n="[title]canvas.prop.y_pix_tt"> + <input class="gop_opt" type="text" name="y-pix"> + </td> + </tr> + <tr class="x-margin prop hidden"> + <td> + <label class="gop_opt" data-i18n="[title]canvas.prop.x_margin_tt"> + <span data-i18n="canvas.prop.x_margin"></span> + </label> + </td> + <td data-i18n="[title]canvas.prop.x_margin_tt"> + <input class="gop_opt" type="text" name="x-margin"> + </td> + <td> + <label class="gop_opt" data-i18n="[title]canvas.prop.y_margin_tt"> + <span data-i18n="canvas.prop.y_margin"></span> + </label> + </td> + <td data-i18n="[title]canvas.prop.y_margin_tt"> + <input class="gop_opt" type="text" name="y-margin"> + </td> + </tr> + </table> + </td> + </tr> + <tr class="display-flags prop"> + <td> + </td> + <td> + <label class="gop_opt" data-i18n="[title]canvas.prop.hide_name_tt"> + <input class="gop_opt" type="checkbox" name="hide-name" value="on"> + <span data-i18n="canvas.prop.hide_name"></span> + </label> + </td> + </tr> + </table> + </fieldset> + + + <fieldset> + <legend data-i18n="canvas.prop.heading.data_scaling"></legend> + + <div class="x-scale prop hidden"> + <label class="no_gop_opt" data-i18n="[title]canvas.prop.x_scale_tt"> + <span data-i18n="canvas.prop.x_scale"></span> + <input class="no_gop_opt" type="text" name="x-scale"> + </label> + <label class="no_gop_opt" data-i18n="[title]canvas.prop.y_scale_tt"> + <span data-i18n="canvas.prop.y_scale"></span> + <input class="no_gop_opt" type="text" name="y-scale"> + </label> + </div> + + <div class="gop-range"> + <div class="y1 prop hidden"> + <label class="gop_opt" data-i18n="[title]canvas.prop.y1_tt"> + <span data-i18n="canvas.prop.y1"></span> + <br> + <input class="gop_opt" type="text" name="y1"> + </label> + <br> + </div> + + <div class="x1 prop hidden"> + <label class="gop_opt" data-i18n="[title]canvas.prop.x1_tt"> + <span data-i18n="canvas.prop.x1"></span> + <input class="gop_opt" type="text" name="x1"> + </label> + <label class="gop_opt" data-i18n="[title]canvas.prop.x2_tt"> + <input class="gop_opt" type="text" name="x2"> + <span data-i18n="canvas.prop.x2"></span> + </label> + <br> + </div> + + <div class="y2"> + <label class="gop_opt" data-i18n="[title]canvas.prop.y2_tt"> + <input class="gop_opt" type="text" name="y2"> + <br> + <span data-i18n="canvas.prop.y2"></span> + </label> + </div> + </div> + + </fieldset> + + + <fieldset id="arrays" class="hidden"> + <legend data-i18n="canvas.prop.heading.arrays"></legend> + + <label class="arrays" data-i18n="[title]canvas.prop.array_name"> + <select id="arrays_select" class="hidden"></select> + </label> + + <div class="array-name prop"> + <label class="array-name" data-i18n="[title]canvas.prop.array_name_tt"> + <span data-i18n="canvas.prop.array_name"></span> + <input onchange="attr_change(this);" class="array-name" type="text" name="array_name"> + </label> + <label class="array-size" data-i18n="[title]canvas.prop.array_size_tt"> + <span data-i18n="canvas.prop.array_size"></span> + <input onchange="attr_change(this);" class="array-size" type="text" name="array_size"> + </label> + + <label class="array-save" data-i18n="[title]canvas.prop.array_save_tt"> + <span data-i18n="canvas.prop.array_save"></span> + <input onchange="flag_change(this);" type="checkbox" name="array_save" value="on"> + </label> + + <label class="array-jump" data-i18n="[title]canvas.prop.array_jump_tt"> + <span data-i18n="canvas.prop.array_jump"></span> + <input onchange="flag_change(this);" type="checkbox" name="array_jump" value="on"> + </label> + + <span data-i18n="canvas.prop.array_style"></span> + + <label class="polygon" data-i18n="[title]canvas.prop.array_polygon_tt"> + <span data-i18n="canvas.prop.array_polygon"></span> + <input class="array-style" + type="radio" + id="polygon" + value="0" + name="array_style" + onchange="flag_change(this);"> + </label> + + + <label class="points" data-i18n="[title]canvas.prop.array_points_tt"> + <span data-i18n="canvas.prop.array_points"></span> + <input class="array-style" + type="radio" + id="points" + value="1" + name="array_style" + onchange="flag_change(this);"> + </label> + + + <label class="bezier-curve" data-i18n="[title]canvas.prop.array_bezier_tt"> + <span data-i18n="canvas.prop.array_bezier"></span> + <input class="array-style" + type="radio" + id="bezier" + value="2" + name="array_style" + onchange="flag_change(this);"> + </label> + + + <label class="bar-graph" data-i18n="[title]canvas.prop.array_bars_tt"> + <span data-i18n="canvas.prop.array_bars"></span> + <input class="array-style" + type="radio" + id="bar-graph" + value="3" + name="array_style" + onchange="flag_change(this);"> + </label> + + + </div> + + <div class="array-fill"> + <label data-i18n="[title]canvas.prop.array_fill_tt"> + <input onchange="attr_change(this);" type="color" name="array_fill"> + <span data-i18n="canvas.prop.array_fill"></span> + </label> + <br> + </div> + + <div class="array-outline"> + <label data-i18n="[title]canvas.prop.array_outline_tt"> + <input onchange="attr_change(this);" type="color" name="array_outline"> + <span data-i18n="canvas.prop.array_outline"></span> + </label> + <br> + </div> + + + + <div class="gop-range"> + <div class="y1 prop hidden"> + <label class="gop_opt" data-i18n="[title]canvas.prop.y1_tt"> + <span data-i18n="canvas.prop.y1"></span> + <br> + <input class="gop_opt" type="text" name="y1"> + </label> + <br> + </div> + + <div class="x1 prop hidden"> + <label class="gop_opt" data-i18n="[title]canvas.prop.x1_tt"> + <span data-i18n="canvas.prop.x1"></span> + <input class="gop_opt" type="text" name="x1"> + </label> + <label class="gop_opt" data-i18n="[title]canvas.prop.x2_tt"> + <input class="gop_opt" type="text" name="x2"> + <span data-i18n="canvas.prop.x2"></span> + </label> + <br> + </div> + + <div class="y2"> + <label class="gop_opt" data-i18n="[title]canvas.prop.y2_tt"> + <input class="gop_opt" type="text" name="y2"> + <br> + <span data-i18n="canvas.prop.y2"></span> + </label> + </div> + </div> + + </fieldset> + + + <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="apply()" data-i18n="[title]iem.prop.apply_tt"> + <span data-i18n="iem.prop.apply"></span> + </button> + <button type="button" onClick="cancel()" data-i18n="[title]iem.prop.cancel_tt"> + <span data-i18n="iem.prop.cancel"></span> + </button> + </div> + + </form> + </div> + + <script> + 'use strict'; + var nw = require('nw.gui'); + var pdgui = require('./pdgui.js'); + + // For translations + var l = pdgui.get_local_string; + + console.log("my working dire is " + pdgui.get_pwd()); + + var pd_object_callback; + + // nested arrays of attributes for each garray + // in this canvas + var pd_garray_attrs; + + function ok() { + apply(); + cancel(); + } + +// function toggler(evt) { +// evt.value = evt.checked ? 1 : 0; +// } + + function flag_change(elem) { + var attr, arrays_select, name, value, flag; + arrays_select = document.getElementById('arrays_select'); + attr = pd_garray_attrs[arrays_select.value]; + name = elem.name; +// pdgui.gui_post("name is " + name); + // get value from radio group, checked from checkboxes + if (name === 'array_style') { + value = document.querySelector('input[name="array_style"]:checked').value; + pdgui.gui_post("array style found: " + value); + } else { + // '+' for casting boolean to number + value = +elem.checked; + } +// pdgui.gui_post("value is " + value); + flag = attr[attr.indexOf('array_flags') + 1]; + pdgui.gui_post("flag before is " + flag); + switch (name) { + case "array_save": + flag &= ~1; // clear the save bit + flag |= value; // set it + break; + case "array_style": + flag &= ~(1 << 2); // clear style bit 2... + flag &= ~(1 << 1); // ... and 1 ... + flag += (2 * value); // set them + break; + case "array_jump": + flag &= ~(1 << 3); + flag += (16 * value); + break; + } + attr[attr.indexOf('array_flags') + 1] = flag; + pdgui.gui_post("array is " + attr); + } + + function attr_change(elem) { + var array_index, attr, arrays_select, name; + arrays_select = document.getElementById('arrays_select'); + attr = pd_garray_attrs[arrays_select.value]; + name = elem.name; + attr[attr.indexOf(name) + 1] = elem.value; + pdgui.gui_post("name is " + elem.name); + pdgui.gui_post("value is " + elem.value); + } + + function array_choose(array_index) { + var i, name, value, elem, style_index, style_opts, + array_attr = pd_garray_attrs[array_index]; + for (i = 0; i < array_attr.length; i+=2) { + name = array_attr[i]; + value = array_attr[i+1]; + switch (name) { + case "array_gfxstub": break; + case "array_flags": + // save contents + elem = document.getElementsByName('array_save')[0]; + elem.checked = (value & 1) != 0; + // jump on click + elem = document.getElementsByName('array_jump')[0]; + elem.checked = (value & 16) != 0; + // draw style + style_opts = document.getElementsByName('array_style'); + style_index = (value & 6) >> 1; + elem = style_opts[style_index]; + elem.checked = true; + break; + default: + // name, size, fill, and outline + pdgui.gui_post("name is " + name); + elem = document.getElementsByName(name)[0]; + elem.value = value; + break; + } + } + } + + var arrays_select = document.getElementById('arrays_select'); + arrays_select.addEventListener('change', function() { + pdgui.gui_post('changed the thing is ' + this.value); + array_choose(this.value); + }); + + var gop_label = document.getElementById('gop_label'); + gop_label.addEventListener('click', function() { + document.getElementsByName('gop')[0].click(); + }); + + var gop_button = document.getElementsByName('gop')[0]; + gop_button.addEventListener('click', function(evt) { + set_gop(this.checked); + }); + + function update_gop_form(opts, state) { + var elem, i; + for(i = 0; i < opts.length; i++) { + elem = opts[i]; + if (elem.type === 'checkbox' || + elem.type === 'text') { + elem.disabled = state ? false : true; + } + if (state) { + elem.classList.remove('disabled'); + } else { + elem.classList.add('disabled'); + } + } + } + + var gop_click_count = 0; + + function show_sane_defaults() { + var w, h, xoff, yoff; + w = document.getElementsByName('x-pix')[0]; + h = document.getElementsByName('y-pix')[0]; + xoff = document.getElementsByName('x-margin')[0]; + yoff = document.getElementsByName('y-margin')[0]; + if (w.value === '0' && h.value === '0') { + w.value = 85; + h.value = 60; + xoff.value = 100; + yoff.value = 100; + } + gop_click_count++; + } + + function set_gop(state) { + var gop_opts, no_gop_opts; + if (state === true && gop_click_count === 0) { + show_sane_defaults(); + } + gop_opts = document.getElementsByClassName('gop_opt'); + no_gop_opts = document.getElementsByClassName('no_gop_opt'); + update_gop_form(gop_opts, state); + update_gop_form(no_gop_opts, state === false); + } + + + function substitute_space(arg) { + var fake_space = String.fromCharCode(11); + return arg.split(' ').join(fake_space); + } + + function strip_problem_chars(arg) { + var problem_chars = [';', ',', '{', '}', '\\']; + var ret = arg; + for(var i = 0; i < problem_chars.length; i++) { + ret = ret.split(';').join(''); + } + return ret; + } + + function get_input(name) { + var val = document.getElementsByName(name)[0].value; + return val === 0 ? '0' : val; + } + + // get a value from the garray attr array + function get_array_value(name, attrs) { + return attrs[attrs.indexOf(name) + 1]; + } + + + function apply() { + var i, attrs; + pdgui.gui_post("we're applying shits!"); + + // Note: the "+" casts Boolean to Number + var gop = +document.getElementsByName('gop')[0].checked; + var hide_name = +document.getElementsByName('hide-name')[0].checked; + + pdgui.pdsend([pd_object_callback, 'donecanvasdialog', + get_input('x-scale'), + get_input('y-scale'), + (gop + 2 * hide_name), + get_input('x1'), + get_input('y1'), + get_input('x2'), + get_input('y2'), + get_input('x-pix'), + get_input('y-pix'), + get_input('x-margin'), + get_input('y-margin'), + ].join(' ')); + + // Now send the array properties, in a separate + // message for each array + for (i = 0; i < pd_garray_attrs.length; i++) { + attrs = pd_garray_attrs[i]; + name = get_array_value('array_name', attrs); + if (name.slice(0, 1) === '$') { + name = '#' + name.slice(1); + } + pdgui.pdsend([ + get_array_value('array_gfxstub', attrs), + 'arraydialog', + name, + get_array_value('array_size', attrs), + get_array_value('array_flags', attrs), + 0, // create an array in a new graph -- we don't + // need this in a prexisting graph + 0, // xdraw-- not sure if this is still used + 0, // ydraw-- not sure if this is still used + get_array_value('array_fill', attrs), + get_array_value('array_outline', attrs), + ].join(' ')); + + } +/* + pd [concat $id donecanvasdialog \ + $::dialog($vid:xscale) \ + $::dialog($vid:yscale) \ + [expr $::dialog($vid:graphme)+2*$::dialog($vid:hidetext)] \ + $::dialog($vid:x1) \ + $::dialog($vid:y1) \ + $::dialog($vid:x2) \ + $::dialog($vid:y2) \ + $::dialog($vid:xpix) \ + $::dialog($vid:ypix) \ + $::dialog($vid:xmargin) \ + $::dialog($vid:ymargin) \ + \;] +} +*/ + } + + function cancel() { + var i, attrs, gfxstub; + pdgui.gui_post("closing the window at this point"); +// window.close(true); + pdgui.pdsend(pd_object_callback + " cancel"); + for (i = 0; i < pd_garray_attrs.length; i++) { + attrs = pd_garray_attrs[i]; + gfxstub = attrs[attrs.indexOf("array_gfxstub") + 1]; +pdgui.gui_post("guistub is " + gfxstub); + pdgui.pdsend(gfxstub + " cancel"); + } + } + + function populate_array_form(arrays) { + var arrays_select, a_field = document.getElementById('arrays'); + var i, opt; + a_field.classList.remove('hidden'); + arrays_select = document.getElementById('arrays_select'); + for (i = 0; i < arrays.length; i++) { + if (i > 0) { + // unhide select element if there's more than one array + arrays_select.classList.remove('hidden'); + } + opt = document.createElement('option'); + opt.setAttribute('value', i); + opt.textContent = 'Array #' + (i+1); + arrays_select.appendChild(opt); + } + array_choose(0); + } + + // Set up arrays in an object + + function init_arrays(attr_arrays) { + pd_garray_attrs = attr_arrays; + if (attr_arrays.length > 0) { + // populate form with first array + populate_array_form(attr_arrays); + } + } + + // 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_canvas_id(gfxstub, attr_arrays) { + pd_object_callback = gfxstub; + + // attr_arrays[0]: canvas properties + // attr_arrays[1...n-1]: array properties + for (var i = 0; i < attr_arrays.length; i+=2) { + pdgui.gui_post(attr_arrays[i] + ": " + attr_arrays[i+1]); + } + add_events(gfxstub); + // not sure that we need this for properties windows +// pdgui.canvas_map(gfxstub); + translate_form(); + populate_form(attr_arrays[0]); + init_arrays(attr_arrays.slice(1)); + // 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'); +// document.getElementsByClass("fumbles")[0].setAttribute('style', 'display: inline;'); + } + +function tr_text(id) { + var elem = document.getElementById('iem.prop.' + id); + elem.textContent = l('iem.prop.' + id); +} + +// Stop-gap translator +function translate_form() { + var i + var elements = document.querySelectorAll('[data-i18n]'); + for (i = 0; i < elements.length; i++) { + var 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 populate_form(attr_array) { + + // First, let's put the translated text for the form labels: + +// tr_text('heading.size'); +// tr_text('heading.messages'); +// tr_text('heading.label'); +// tr_text('heading.colors'); +// tr_prop('width'); +// tr_tooltip('width'); + +// var headings = ["size", "messages", "label", "colors"]; +// for (var i = 0; i < headings.length; i++) { +// var str = "iem.prop.heading." + headings[i]; +// var heading = document.getElementById(str); +// heading.textContent = l(str); +// } + + for(var i = 0; i < attr_array.length; i+=2) { + // Unhide the span with the class with the same name as the id + var prop_group = document.getElementsByClassName(attr_array[i])[0]; + if (prop_group !== undefined) { + console.log("the thing here is " + attr_array[i]); + prop_group.classList.remove('hidden'); + } else { + pdgui.gui_post("Error: couldn't find iemgui prop group for " + attr_array[i]); + } + + if (attr_array[i] === 'display-flags') { + // protip: '!!' forces Boolean, '+' forces Number type + var flag = +attr_array[i+1]; + document.getElementsByName('gop')[0].checked = !!flag; + document.getElementsByName('hide-name')[0].checked = !!(flag & 2); + // Set the gop-related parts of the form to be enabled/disabled based on state + set_gop(!!flag); + } + + var elem = document.getElementsByName(attr_array[i]); + if (elem.length > 0) { + if(attr_array[i].slice(-5) === 'color') { + var hex_string = Number(attr_array[i+1]).toString(16); + var color_string = "#" + (hex_string === '0' ? '000000' : hex_string); + pdgui.gui_post("color is " + color_string); + elem[0].value = color_string; + } else if (elem[0].type === 'checkbox') { + // The attr here is a string, so we need to + // force it to number, hence the "+" below + gui_post("found a CHECKED ITEM!!!"); + elem[0].checked = +attr_array[i+1]; + } else { + elem[0].value = attr_array[i+1]; + } + } + } +} + +function add_events(name) { + // let's handle some events for this window... + + // closing the Window + nw.Window.get().on("close", function() { + // this needs to do whatever the "cancel" button does +// pdgui.pdsend(name + " menuclose 0"); +// cancel(); + pdgui.remove_dialogwin(pd_object_callback); + this.close(true); + }); + +} + + </script> + </body> +</html> diff --git a/pd/nw/dialog_iemgui.css b/pd/nw/dialog_iemgui.css new file mode 100644 index 000000000..b62808614 --- /dev/null +++ b/pd/nw/dialog_iemgui.css @@ -0,0 +1,113 @@ +@font-face { + font-family: "DejaVu Sans Mono"; + src: url("DejaVuSansMono.ttf"); +} + +body { + font-family:Verdana; + margin: 0px; +} + +fieldset { + font-family:Georgia; + background-color:#eeeeee; + border-radius:3px; + border:2px solid black; + margin-left:auto; + margin-right:auto; + padding: 10px; +} + +input[type="text"]{ + width:3em; +} + +input[type="number"]{ + width:3em; +} + + +.prop{ +} + +.hidden { + display: none; +} + +.container{ + display: none; +} + + + +body { +} + +.noselect { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +text { + // fill: red; + cursor: default; +} + +.selected_border { + stroke: blue; + stroke-dasharray: none; + stroke-width: 1; +} + +label { + text-align: right; +// margin-right: auto; +// margin-left: auto; +} + +.pair { + width: 75%; + text-align: left; + align: left; +} + +.item1 { + width: 50%; +} + +.item2 { + width: 50%; +} + +input[name="x-offset"] { + width: 2em; +} + +input[name="y-offset"] { + width: 2em; +} + +input[name="send-symbol"] { + width: 8em; +} + +input[name="receive-symbol"] { + width: 8em; +} + +input[name="label"] { + width: 8em; +} + +input[name="font-size"] { + width: 3em; +} + +.submit_buttons { + text-align: center; + padding: 8px; +} diff --git a/pd/nw/dialog_iemgui.html b/pd/nw/dialog_iemgui.html new file mode 100644 index 000000000..1db283656 --- /dev/null +++ b/pd/nw/dialog_iemgui.html @@ -0,0 +1,604 @@ +<!DOCTYPE html> +<html> + <head> + <link rel="stylesheet" type="text/css" href="dialog_iemgui.css"> + </head> + <body> + <div class="container"> + <form> + <fieldset> + <legend data-i18n="iem.prop.heading.size"></legend> + + <table class="pairs"> + <tr class="size prop hidden"> + <td> + <label data-i18n="[title]iem.prop.size_tt"> + <span data-i18n="iem.prop.size"></span> + </label> + </td> + <td data-i18n="[title]iem.prop.size_tt"> + <input type="text" name="size"> + </td> + </tr> + <tr class="selection-size prop hidden"> + <td> + <label data-i18n="[title]iem.select_size_tt"> + <span data-i18n="iem.prop.select_size"></span> + </label> + </td> + <td data-i18n="[title]iem.prop.select_size_tt"> + <input type="text" name="selection-size"> + </td> + </tr> + <tr class="number prop hidden"> + <td> + <label data-i18n="[title]iem.prop.number_tt"> + <span data-i18n="iem.prop.number"></span> + </label> + </td> + <td data-i18n="[title]iem.prop.number_tt"> + <input type="number" name="number"> + </td> + </tr> + <tr class="nonzero-value prop hidden"> + <td> + <label data-i18n="[title]iem.prop.nonzero_value_tt"> + <span data-i18n="iem.prop.nonzero_value"></span> + </label> + </td> + <td data-i18n="[title]iem.prop.nonzero_value_tt"> + <input type="text" name="nonzero-value"> + </td> + </tr> + <tr class="width prop hidden"> + <td> + <label data-i18n="[title]iem.prop.width_tt"> + <span data-i18n="iem.prop.width"></span> + </label> + </td> + <td data-i18n="[title]iem.prop.width_tt"> + <input type="text" name="width"> + </td> + <td> + <label data-i18n="[title]iem.prop.height_tt"> + <span data-i18n="iem.prop.height"></span> + </label> + </td> + <td data-i18n="[title]iem.prop.height_tt"> + <input type="text" name="height"> + </td> + </tr> + <tr class="visible-width prop hidden"> + <td> + <label data-i18n="[title]iem.prop.visible_width_tt"> + <span data-i18n="iem.prop.visible_width"></span> + </label> + </td> + <td data-i18n="[title]iem.prop.visible_width_tt"> + <input type="text" name="visible-width"> + </td> + <td> + <label data-i18n="iem.prop.visible_height"> + <span data-i18n="iem.prop.visible_height"></span> + </label> + </td> + <td data-i18n="[title]iem.prop.visible_height_tt"> + <input type="text" name="visible-height"> + </td> + </tr> + <tr class="minimum-range prop pair hidden"> + <td> + <label data-i18n="[title]iem.prop.minimum_tt"> + <span data-i18n="iem.prop.minimum"></span> + </label> + </td> + <td data-i18n="[title]iem.prop.minimum_tt"> + <input type="text" name="minimum-range"> + </td> + <td> + <label data-i18n="[title]iem.prop.maximum_tt"> + <span data-i18n="iem.prop.maximum"></span> + </label> + </td> + <td data-i18n="[title]iem.prop.maximum_tt"> + <input type="text" name="maximum-range"> + </td> + </tr> + <tr class="flash-interrupt prop hidden"> + <td> + <label data-i18n="[title]iem.prop.flash_interrupt_tt"> + <span data-i18n="iem.prop.flash_interrupt"></span> + </label> + </td> + <td data-i18n="[title]iem.prop.flash_interrupt_tt"> + <input type="text" name="flash-interrupt"> + </td> + <td> + <label data-i18n="[title]iem.prop.flash_hold_tt"> + <span data-i18n="iem.prop.flash_hold"></span> + </label> + </td> + <td data-i18n="[title]iem.prop.flash_hold_tt"> + <input type="text" name="flash-hold"> + </td> + </tr> + <tr class="log-height prop hidden"> + <td></td><td></td> + <td> + <label data-i18n="[title]iem.prop.log_height_tt"> + <span data-i18n="iem.prop.log_height"></span> + </label> + </td> + <td> + <input type="text" name="log-height"> + </td> + </tr> + </table> + + <div class="init prop hidden"> + <label data-i18n="[title]iem.prop.init_tt"> + <input type="checkbox" name="init" value="on"> + <span data-i18n="iem.prop.init"></span> + </label> + <br> + </div> + + <div class="vu-scale prop hidden"> + <label data-i18n="[title]iem.prop.vu_scale_tt"> + <span data-i18n="iem.prop.vu_scale"></span> + <input type="checkbox" name="vu-scale" value="on"> + </label> + <br> + </div> + + <div class="log-scaling prop hidden"> + <label data-i18n="[title]iem.prop.log_scale_tt"> + <input type="checkbox" name="log-scaling" value="on"> + <span data-i18n="iem.prop.log_scale"></span> + </label> + <br> + </div> + + <div class="steady-on-click prop hidden"> + <label data-i18n="[title]iem.prop.steady_tt"> + <input type="checkbox" name="steady-on-click" value="on"> + <span data-i18n="iem.prop.steady"></span> + </label> + <br> + </div> + </fieldset> + + <fieldset> + <legend data-i18n="iem.prop.heading.messages"></legend> + + <table> + <tr class="send-symbol prop hidden"> + <td> + <label data-i18n="[title]iem.prop.send_tt"> + <span data-i18n="iem.prop.send"></span> + </label> + </td> + <td data-i18n="[title]iem.prop.send_tt"> + <input type="text" name="send-symbol"> + </td> + <td> + <tr class="receive-symbol prop hidden"> + <td> + <label data-i18n="[title]iem.prop.receive_tt"> + <span data-i18n="iem.prop.receive"></span> + </label> + </td> + <td data-i18n="[title]iem.prop.receive_tt"> + <input type="text" name="receive-symbol"> + </td> + <td> + </tr> + </table> + </fieldset> + + <fieldset> + <legend data-i18n="iem.prop.heading.label">wrong stuff</legend> + + <table class="pairs"> + <tr class="label prop hidden"> + <td> + <label data-i18n="[title]iem.prop.label_tt"> + <span data-i18n="iem.prop.label"></span> + </label> + </td> + <td data-i18n="[title]iem.prop.label_tt"> + <input type="text" name="label"> + </td> + <td> + <label data-i18n="[title]iem.prop.xoffset_tt"> + <span data-i18n="iem.prop.xoffset"></span> + </label> + </td> + <td data-i18n="[title]iem.prop.xoffset_tt"> + <input type="text" name="x-offset"> + </td> + <td> + <label data-i18n="[title]iem.prop.yoffset_tt"> + <span data-i18n="iem.prop.yoffset"></span> + </label> + </td> + <td data-i18n="[title]iem.prop.yoffset_tt"> + <input type="text" name="y-offset"> + </td> + </tr> + <tr class="font-style prop hidden"> + <td> + <label data-i18n="[title]iem.prop.font_tt"> + <span data-i18n="iem.prop.font"></span> + </td> + <td data-i18n="[title]iem.prop.font_tt"> + <select name="font-style"> + <option>Font Number 0</option> + <option>Font #1</option> + <option>Font 2</option> + </select> + </td> + <td colspan="4"> + <label data-i18n="[title]iem.prop.fontsize_tt"> + <span data-i18n="iem.prop.fontsize"></span> + <input type="text" name="font-size"> + <label> + </td> + </tr> + </table> + </fieldset> + + <fieldset> + <legend data-i18n="iem.prop.heading.colors"></legend> + + <div class="background-color prop hidden"> + <label data-i18n="[title]iem.prop.bgcolor_tt"> + <input type="color" name="background-color"> + <span data-i18n="iem.prop.bgcolor"></span> + </label> + <br> + </div> + + <div class="foreground-color prop hidden"> + <label data-i18n="[title]iem.prop.fgcolor_tt"> + <input type="color" name="foreground-color"> + <span data-i18n="iem.prop.fgcolor"></span> + </label> + <br> + </div> + + <div class="label-color prop hidden"> + <label data-i18n="[title]iem.prop.label_color_tt"> + <input type="color" name="label-color"> + <span data-i18n="iem.prop.label_color"></span> + </label> + <br> + </div> + </fieldset> + + <div class="prop hidden"> + <input type="hidden" name="minimum-size"> + <input type="hidden" name="range-schedule"> + <input type="hidden" name="hide-frame"> + </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="apply()" data-i18n="[title]iem.prop.apply_tt"> + <span data-i18n="iem.prop.apply"></span> + </button> + <button type="button" onClick="cancel()" data-i18n="[title]iem.prop.cancel_tt"> + <span data-i18n="iem.prop.cancel"></span> + </button> + </div> + + </form> + </div> + + <script> + 'use strict'; + var nw = require('nw.gui'); + var pdgui = require('./pdgui.js'); + + // For translations + var l = pdgui.get_local_string; + + console.log("my working dire is " + pdgui.get_pwd()); + + var pd_object_callback; + + function ok() { + apply(); + cancel(); + } + +// function toggler(evt) { +// evt.value = evt.checked ? 1 : 0; +// } + + function substitute_space(arg) { + var fake_space = String.fromCharCode(11); + return arg.split(' ').join(fake_space); + } + + function strip_problem_chars(arg) { + var problem_chars = [';', ',', '{', '}', '\\']; + var ret = arg; + for(var i = 0; i < problem_chars.length; i++) { + ret = ret.split(';').join(''); + } + return ret; + } + + function apply() { + pdgui.gui_post("we're applying shits!"); + + /* Not sure what these are... + iemgui_clip_dim $id + iemgui_clip_num $id + iemgui_sched_rng $id + iemgui_verify_rng $id + iemgui_sched_rng $id + iemgui_clip_fontsize $id + */ + + + + var send_symbol = document.getElementsByName('send-symbol')[0].value; + var receive_symbol = document.getElementsByName('receive-symbol')[0].value; + var label = document.getElementsByName('label')[0].value; + if (send_symbol === null || send_symbol === '') { send_symbol = 'empty'; } + if (receive_symbol === null || receive_symbol === '') { receive_symbol = 'empty'; } + if (label === null || label === '') { label = 'empty'; } + + console.log("send_symbol is " + send_symbol); + + if (send_symbol.charAt(0) === '$') { + send_symbol = '#' + send_symbol.slice(1); + } + if (receive_symbol.charAt(0) === '$') { + receive_symbol = '#' + receive_symbol.slice(1); + } + if (label.charAt(0) === '$') { + label = '#' + label.slice(1); + } + + send_symbol = substitute_space(send_symbol); + receive_symbol = substitute_space(receive_symbol); + label = substitute_space(label); + + send_symbol = strip_problem_chars(send_symbol); + receive_symbol = strip_problem_chars(receive_symbol); + label = strip_problem_chars(label); + + var label_x_offset = document.getElementsByName('x-offset')[0].value; + var label_y_offset = document.getElementsByName('y-offset')[0].value; + + // make sure the offset boxes have a value + if (label_x_offset === null) { label_x_offset = 0; } + if (label_y_offset === null) { label_y_offset = 0; } + + var height, width; + var size = document.getElementsByName('size')[0].value; + if (size === '') { + var size = document.getElementsByName('selection-size')[0].value; + } + + if (size !== '') { + width = size; + height = size; + } else { + width = document.getElementsByName('width')[0].value; + height = document.getElementsByName('height')[0].value; + } + + var slot3 = document.getElementsByName('minimum-range')[0].value; + var slot4 = document.getElementsByName('maximum-range')[0].value; + + if (slot3 === '') { + slot3 = document.getElementsByName('flash-interrupt')[0].value; + slot4 = document.getElementsByName('flash-hold')[0].value; + } + + if (slot3 === '') { + slot3 = document.getElementsByName('visible-width')[0].value; + slot4 = document.getElementsByName('visible-height')[0].value; + } + + if (slot3 === '') { // toggle + slot3 = document.getElementsByName('nonzero-value')[0].value; + if (slot3 === '') { + slot3 = 0; + } + slot4 = 0; + } + + var slot5 = +document.getElementsByName('log-scaling')[0].checked; + // Hack to accomodate the vu-scale property, which exists in the same + // slot as this one + var log_scaling_spanner = document.getElementsByClassName('log-scaling')[0]; + var log_display = log_scaling_spanner.style.getPropertyValue('display'); + + if (log_display === null) { + slot5 = +document.getElementsByName('vu-scale')[0].checked; + pdgui.gui_post('slot five is ' + slot5); + } + pdgui.gui_post('slot five is ' + slot5); + + var init = +document.getElementsByName('init')[0].checked; + if (init === '') { init = 0; } + + var slot7 = document.getElementsByName('log-height')[0].value; + if (slot7 === '') { + slot7 = document.getElementsByName('number')[0].value; + } + if (slot7 === '') { + slot7 = 0; + } + + var font_style = document.getElementsByName('font-style')[0].value; + if (font_style !== null) { font_style = 0; } + + var font_size = document.getElementsByName('font-size')[0].value; + if (font_size === '') { font_size = 0; } + + var foreground_color = parseInt(document.getElementsByName('foreground-color')[0].value.slice(1), 16); + var background_color = parseInt(document.getElementsByName('background-color')[0].value.slice(1), 16); + var label_color = parseInt(document.getElementsByName('label-color')[0].value.slice(1), 16); + + var slot18 = +document.getElementsByName('steady-on-click')[0].checked; + + pdgui.pdsend([pd_object_callback, 'dialog', + width, height, + slot3, // bng: flash-interrupt + // slider: min-range + // toggle: nonzero-value + // my_canvas: visible_width + slot4, // bng: flash-hold + // slider: max-range + // my_canvas: visible_height + slot5, // slider: lin/log thingy + // nbx: lin/log + // vu: vu-scale + init, + slot7, // log-height or vradio/hradio number + send_symbol, receive_symbol, label, + label_x_offset, label_y_offset, + font_style, font_size, + background_color, foreground_color, + label_color, + slot18, // steady on click + 0].join(' ')); +/* + pd [concat $id dialog \ + $::dialog($vid:wdt) $::dialog($vid:hgt) \ + $::dialog($vid:min_rng) $::dialog($vid:max_rng) \ + $::dialog($vid:lin0_log1) $::dialog($vid:loadbang) \ + $::dialog($vid:num) \ + $hhhsnd $hhhrcv $hhhgui_nam \ + $::dialog($vid:gn_dx) $::dialog($vid:gn_dy) \ + $::dialog($vid:gn_f) $::dialog($vid:gn_fs) \ + $::dialog($vid:bcol) $::dialog($vid:fcol) \ + $::dialog($vid:lcol) \ + $::dialog($vid:steady) $::dialog($vid:hide) \;] +*/ + + } + + function cancel() { + pdgui.gui_post("closing the window at this point"); +// window.close(true); + pdgui.pdsend(pd_object_callback + " cancel"); + } + + // 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_canvas_id(gfxstub, attr_array) { + pd_object_callback = gfxstub; + + console.log('attr array is ' + attr_array.toString()); + for (var i = 0; i < attr_array.length; i+=2) { + console.log(attr_array[i] + ": " + attr_array[i+1]); + } + add_events(gfxstub); + // not sure that we need this for properties windows +// pdgui.canvas_map(gfxstub); + translate_form(); + populate_form(attr_array); + // 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'); +// document.getElementsByClass("fumbles")[0].setAttribute('style', 'display: inline;'); + } + +function tr_text(id) { + var elem = document.getElementById('iem.prop.' + id); + elem.textContent = l('iem.prop.' + id); +} + +// Stop-gap translator +function translate_form() { + var i + var elements = document.querySelectorAll('[data-i18n]'); + for (i = 0; i < elements.length; i++) { + var 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 populate_form(attr_array) { + + // First, let's put the translated text for the form labels: + +// tr_text('heading.size'); +// tr_text('heading.messages'); +// tr_text('heading.label'); +// tr_text('heading.colors'); +// tr_prop('width'); +// tr_tooltip('width'); + +// var headings = ["size", "messages", "label", "colors"]; +// for (var i = 0; i < headings.length; i++) { +// var str = "iem.prop.heading." + headings[i]; +// var heading = document.getElementById(str); +// heading.textContent = l(str); +// } + + for(var i = 0; i < attr_array.length; i+=2) { + // Unhide the span with the class with the same name as the id + var prop_group = document.getElementsByClassName(attr_array[i])[0]; + if (prop_group !== undefined) { + console.log("the thing here is " + attr_array[i]); + prop_group.classList.remove('hidden'); + } else { + pdgui.gui_post("Error: couldn't find iemgui prop group for " + attr_array[i]); + } + // iemguis use the string 'empty' for null because of + // the limitations of Pd's state-saving API. So we have + // to filter that one out + if(attr_array[i+1] !== 'empty') { + var elem = document.getElementsByName(attr_array[i]); + if (elem.length > 0) { + if(attr_array[i].slice(-5) === 'color') { + var hex_string = Number(attr_array[i+1]).toString(16); + var color_string = "#" + (hex_string === '0' ? '000000' : hex_string); + pdgui.gui_post("color is " + color_string); + elem[0].value = color_string; + } else if (elem[0].type === 'checkbox') { + // The attr here is a string, so we need to + // force it to number, hence the "+" below + elem[0].checked = +attr_array[i+1]; + } else { + elem[0].value = attr_array[i+1]; + } + } + } + } +} + +function add_events(name) { + // let's handle some events for this window... + + // closing the Window + nw.Window.get().on("close", function() { + // this needs to do whatever the "cancel" button does +// pdgui.pdsend(name + " menuclose 0"); +// cancel(); + pdgui.remove_dialogwin(pd_object_callback); + this.close(true); + }); + +} + + </script> + </body> +</html> diff --git a/pd/nw/index.html b/pd/nw/index.html index 46a70896f..acf725e54 100644 --- a/pd/nw/index.html +++ b/pd/nw/index.html @@ -494,7 +494,8 @@ function nw_create_window(cid, type, width, height, xpos, ypos, menu_flag, resiz canvas_string, dir, dirty_flag, cargs, attr_array) { // todo: make a separate way to format the title for OSX var my_title = pdgui.format_window_title(canvas_string, dirty_flag, cargs, dir); - var my_file = (type === 'pd-canvas' ? 'pdcanvas.html' : 'pdproperties.html'); + var my_file = + type === 'pd_canvas' ? 'pd_canvas.html' : 'dialog_' + type + '.html'; var new_win = nw.Window.open(my_file, { title: my_title, @@ -506,7 +507,8 @@ function nw_create_window(cid, type, width, height, xpos, ypos, menu_flag, resiz x: xpos, y: ypos }); - var eval_string = "register_canvas_id('" + cid + "', [" + attr_array + "]);"; + pdgui.gui_post("attr_array is " + attr_array); + var eval_string = "register_canvas_id(" + JSON.stringify(cid) + ", " + JSON.stringify(attr_array) + ");"; pdgui.gui_post("eval string is " + eval_string); if (attr_array !== null) { pdgui.gui_post("attr_array is " + attr_array.toString()); diff --git a/pd/nw/locales/en/translation.json b/pd/nw/locales/en/translation.json index 0962fd7e2..f96cbaf5a 100644 --- a/pd/nw/locales/en/translation.json +++ b/pd/nw/locales/en/translation.json @@ -210,5 +210,64 @@ "forums_tt": "Open a link in a browser for the Pd Forum", "irc": "IRC Chat", "irc_tt": "Open a link in a browser for IRC Chat" + }, + "canvas": { + "prop": { + "heading": { + "gop": "appearance on parent", + "data_scaling": "data scaling", + "size": "size", + "viewbox_offsets": "viewbox offsets", + "arrays": "array options" + }, + "gop": "graph on parent", + "gop_tt": "show the inner contents of this canvas in a rectangle on the containing canvas", + "hide_name": "hide object name and arguments", + "hide_name_tt": "blah blah blah", + "gop_0": "Object", + "gop_1": "Window", + "gop_2": "Window (no text)", + "x_pix": "width", + "x_pix_tt": "width of the object", + "y_pix": "height", + "y_pix_tt": "height of the object", + "x_scale": "x scale", + "x_scale_tt": "horizontal scaling factor", + "y_scale": "y scale", + "y_scale_tt": "vertical scaling factor", + "x_margin": "x offset", + "x_margin_tt": "horizontal offset into the subpatch for the view area", + "y_margin": "y offset", + "y_margin_tt": "vertical offset into the subpatch for the view area", + "x1": "left", + "x1_tt": "lowest x value (left edge)", + "x2": "right", + "x2_tt": "highest x value (right edge)", + "y1": "top", + "y1_tt": "highest y value (top)", + "y2": "bottom", + + "array_name": "name", + "array_name_tt": "receiver name for the array", + "array_size": "size", + "array_size_tt": "number of elements in the array", + "array_polygon": "polygon", + "array_polygon_tt": "the array trace is drawn as a polygon", + "array_points": "points", + "array_points_tt": "the array trace is drawn as horizontal line segments", + "array_bezier": "Bezier curve", + "array_bezier_tt": "the array trace is drawn as a Bezier curve", + "array_bars": "bar graph", + "array_bars_tt": "each element of the array is drawn as a bar in a bar graph", + "array_save": "save contents", + "array_save_tt": "save array contents with this patch", + "array_jump": "jump on click", + "array_jump_tt": "update the element to the position of the click", + "array_style": "draw as:", + "array_outline": "outline color", + "array_outline_tt": "color for outline around the bars", + "array_fill": "fill color", + "array_fill_tt": "inner color of the bars" + } } } diff --git a/pd/nw/pd_canvas.css b/pd/nw/pd_canvas.css new file mode 100644 index 000000000..f78ee752b --- /dev/null +++ b/pd/nw/pd_canvas.css @@ -0,0 +1,102 @@ +@font-face { + font-family: "DejaVu Sans Mono"; + src: url("DejaVuSansMono.ttf"); +} + +body { + margin: 0px; + font-family: "DejaVu Sans Mono"; +} + +.noselect { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +text { + // fill: red; + cursor: default; +} + +.selected_border { + stroke: blue; + stroke-dasharray: none; + stroke-width: 1; +} + +/* a message when it flashes on a mouse-click */ +.msg.flashed .border { + stroke-width: 4; +} + +/* Border color for selected objects + In plain English: + Any element with a class 'border' that is contained inside + a parent element that is not in class 'gop' but is + in class 'selected' (whew!) +*/ +:not(.gop).selected .border { + stroke: blue; +} + +.selected_line { + stroke: blue; +} + +.broken_border { + fill: #f7f7f7; + stroke: red; + stroke-dasharray: 3 2; +} + +.xlet_control { + stroke: red; + fill: gray; +// stroke-width: 1; +} + +.xlet_signal { + stroke: green; + fill: green; + stroke-width: 1; +} + +.xlet_iemgui { + stroke: black; + fill: black; + stroke-width: 1; +} + +.iemgui_label_selected { + fill: blue; +} + +@-webkit-keyframes fizzle { + 0% { + stroke-width: 1; + stroke-opacity: 1; + x: 0; + rx: 1; + ry: 1; + } + 100% { + stroke-width: 20; + stroke-opacity: 0.2; + x: 100; + rx: 50; + ry: 50; + } +} + +.xlet_selected { + stroke: purple !important; + -webkit-animation: fizzle 0.5s linear 1; +} + +//.xlet:hover { +// stroke: red; +//} diff --git a/pd/nw/pd_canvas.html b/pd/nw/pd_canvas.html new file mode 100644 index 000000000..d823ab07c --- /dev/null +++ b/pd/nw/pd_canvas.html @@ -0,0 +1,1125 @@ +<!DOCTYPE html> +<html> + <head> + <link rel="stylesheet" type="text/css" href="pd_canvas.css"> + </head> + <body> + <input style="display:none;" id="fileDialog" type="file" multiple /> + <input style="display:none;" id="saveDialog" type="file" nwsaveas nwworkingdir accept=".pd" /> + + <input style="display:none;" id="openpanel_dialog" type="file" /> + <input style="display:none;" id="savepanel_dialog" type="file" nwsaveas nwworkingdir /> + + + <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="patchsvg" height="1000" width="1000" class="noselect"> + </svg> + <script> + 'use strict'; + var nw = require('nw.gui'); + var pdgui = require('./pdgui.js'); + + //var name = pdgui.last_loaded(); + + var l = pdgui.get_local_string; + + console.log("my working dire is " + pdgui.get_pwd()); + document.getElementById("saveDialog").setAttribute("nwworkingdir", pdgui.get_pwd()); + + document.getElementById("fileDialog").setAttribute("nwworkingdir", pdgui.get_pwd()); + document.getElementById("fileDialog").setAttribute("accept", + Object.keys(pdgui.pd_filetypes).toString()); + + var last_keydown = ""; + + // This gets called from the nw_create_window function in index.html + // It provides us with our canvas id from the C side. Once we have it + // we can create the menu and register event callbacks + function register_canvas_id(cid) { +console.log("fuck you"); + create_popup_menu(cid); + add_events(cid); + nw_create_patch_window_menus(cid); + pdgui.canvas_map(cid); + } + + + +// This could probably be in pdgui.js +function add_keymods(key, evt) { + var shift = evt.shiftKey ? "Shift" : ""; + var ctrl = evt.ctrlKey ? "Ctrl" : ""; + return shift + ctrl + key; +} + +function create_popup_menu(name) { + // The right-click popup menu + var popup_menu = new nw.Menu(); + pdgui.add_popup(name, popup_menu); + + popup_menu.append(new nw.MenuItem({ + label: 'Properties', + click: function() { + pdgui.popup_action(name, 0); + } + })); + popup_menu.append(new nw.MenuItem({ + label: 'Open', + click: function() { + pdgui.popup_action(name, 1); + } + })); + popup_menu.append(new nw.MenuItem({ + label: 'Help', + click: function() { + pdgui.popup_action(name, 2); + } + })); +} + +function add_events(name) { + document.querySelector("#saveDialog").addEventListener("change", function(evt) { + pdgui.saveas_callback(name, this.value); + console.log("tried to open something"); + }, false); + + + document.querySelector("#fileDialog").addEventListener("change", function(evt) { + var file_array = this.value; + // reset value so that we can open the same file twice + this.value = null; + pdgui.menu_open(file_array); + console.log("tried to open something"); + }, false); + + document.querySelector("#openpanel_dialog").addEventListener("change", + function(evt) { + var file_string = this.value; + // reset value so that we can open the same file twice + this.value = null; + pdgui.file_dialog_callback(file_string); + console.log("tried to openpanel something"); + }, false + ); + + document.querySelector("#savepanel_dialog").addEventListener("change", + function(evt) { + var file_string = this.value; + // reset value so that we can open the same file twice + this.value = null; + pdgui.file_dialog_callback(file_string); + console.log("tried to savepanel something"); + }, false + ); + + + document.addEventListener("mousemove", function(evt) { + //pdgui.gui_post("x: " + evt.pageX + " y: " + evt.pageY + + // " modifier: " + (evt.shiftKey + (evt.ctrlKey << 1))); + pdgui.pdsend(name + " motion " + evt.pageX + " " + evt.pageY + " " + + (evt.shiftKey + (evt.ctrlKey << 1))); + evt.stopPropagation(); +// evt.preventDefault(); + return false; + }); + + document.addEventListener("keydown", function(evt) { + var key_code = evt.keyCode; + var hack = null; // hack for unprintable ascii codes + switch(key_code) { + case 8: + case 9: + case 10: + case 27: +// case 32: + case 127: hack = key_code; break; + + + case 37: hack = add_keymods('Left', evt); break; + case 38: hack = add_keymods('Up', evt); break; + case 39: hack = add_keymods('Right', evt); break; + case 40: hack = add_keymods('Down', evt); break; + case 33: hack = add_keymods('Prior', evt); break; + case 34: hack = add_keymods('Next', evt); break; + case 35: hack = add_keymods('End', evt); break; + case 36: hack = add_keymods('Home', evt); break; + + // Need to handle Control key, Alt + + case 16: hack = 'Shift'; break; + case 17: hack = 'Control'; break; + case 18: hack = 'Alt'; break; + } + if (hack !== null) { + pdgui.gui_canvas_sendkey(name, 1, evt, hack); + pdgui.set_keymap(key_code, hack); + } + pdgui.gui_post("keydown time: keycode is " + evt.keyCode); + last_keydown = evt.keyCode; + evt.stopPropagation(); + }); + + document.addEventListener("keypress", function(evt) { + pdgui.gui_canvas_sendkey(name, 1, evt, evt.charCode); + pdgui.set_keymap(last_keydown, evt.charCode); + pdgui.gui_post("keypress time: charcode is " + evt.charCode); + // Don't do things like scrolling on space, arrow keys, etc. + evt.stopPropagation(); + evt.preventDefault(); + }); + + document.addEventListener("keyup", function(evt) { + var my_char_code = pdgui.get_char_code(evt.keyCode); + pdgui.gui_canvas_sendkey(name, 0, evt, my_char_code); + pdgui.gui_post("keyup time: charcode is: " + my_char_code); + }); + + // just left-clicks for the moment + document.onmousedown = function(evt) { + //pdgui.gui_post("mousedown: x: " + evt.pageX + " y: " + evt.pageY + + // " button: " + (evt.button + 1) + " modifier: " + (evt.shiftKey + (evt.ctrlKey << 1))); + // tk events are one greater than html5... + var b = evt.button + 1; + var mod; + // For some reason right-click sends a modifier value of "8", and canvas_doclick in + // g_editor.c depends on that value to do the right thing. So let's hack... + if (b === 3) { // right-click + mod = 8; + } else { + mod = (evt.shiftKey + (evt.ctrlKey << 1)); + } + pdgui.pdsend(name + " mouse " + evt.pageX + " " + evt.pageY + " " + + b + " " + mod); + evt.stopPropagation(); + evt.preventDefault(); + } + + document.onmouseup = function(evt) { + //pdgui.gui_post("mouseup: x: " + evt.pageX + " y: " + evt.pageY + + // " button: " + (evt.button + 1)); + pdgui.pdsend(name + " mouseup " + evt.pageX + " " + evt.pageY + " " + + (evt.button + 1)); + } + + + + + // let's handle some events for this window... + + // closing the Window + // this isn't actually closing the window yet + nw.Window.get().on("close", function() { + pdgui.pdsend(name + " menuclose 0"); + }); + + +} + + + + + + +//nw_create_patch_window_menus(name); + + function menu_generic () { + alert("Please implement this"); + } + + function pdmenu_copy () { + alert("Please implement pdmenu_copy"); + } + + function pdmenu_selectall () { + alert("Please implement pdmenu_selectall"); + } + + function pdmenu_preferences () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_next_win () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_previous_win () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_parent_win () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_console_win () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_audio_on () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_audio_off () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_test_audio () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_load_meter () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_about_pd () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_manual () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_help_browser () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_l2ork_mailinglist () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_pd_mailinglists () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_forums () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_irc () { + alert("Please implement pdmenu_preferences"); + } + +// Menus for the Patch window +function nw_create_patch_window_menus (name) { + + // Window menu + var windowMenu = new nw.Menu({ + type: 'menubar' + }); + + // File menu + var fileMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: l('menu.file'), + submenu: fileMenu + })); + + // File sub-entries + fileMenu.append(new nw.MenuItem({ + label: l('menu.new'), + click: pdgui.menu_new, + key: 'n', + modifiers: "ctrl", + tooltip: l('menu.new_tt') + })); + + fileMenu.append(new nw.MenuItem({ + label: l('menu.open'), + key: 'o', + modifiers: "ctrl", + tooltip: l('menu.open_tt'), + click: function() { + var chooser = document.querySelector('#fileDialog'); + chooser.click(); + } + })); + + if (pdgui.k12_mode == 1) { + fileMenu.append(new nw.MenuItem({ + label: l('menu.k12_demos'), + tooltip: l('menu.k12_demos_tt'), + click: pdgui.menu_k12_open_demos + })); + } + + fileMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + // Note: this must be different for the main Pd window + fileMenu.append(new nw.MenuItem({ + label: l('menu.save'), + click: function () { + pdgui.menu_save(name); + }, + key: 's', + modifiers: "ctrl", + tooltip: l('menu.save_tt') + })); + + fileMenu.append(new nw.MenuItem({ + label: l('menu.saveas'), + click: function (){ + pdgui.menu_saveas(name); + }, + key: 's', + modifiers: "ctrl+shift", + tooltip: l('menu.saveas_tt') + })); + + if (pdgui.k12_mode == 0) { + fileMenu.append(new nw.MenuItem({ + type: 'separator' + })); + } + + fileMenu.append(new nw.MenuItem({ + label: l('menu.message'), + click: pdgui.menu_send, + key: 'm', + modifiers: "ctrl", + tooltip: l('menu.message_tt') + })); + + if (pdgui.k12_mode == 0) { + fileMenu.append(new nw.MenuItem({ + type: 'separator' + })); + } + + // recent files go here + + // anther separator goes here if there are any recent files + + fileMenu.append(new nw.MenuItem({ + label: l('menu.close'), + tooltip: l('menu.close_tt'), + click: function() { + pdgui.menu_close(name); + } + })); + + // Quit Pd + fileMenu.append(new nw.MenuItem({ + label: l('menu.quit'), + click: pdgui.menu_quit, + key: 'q', + modifiers: "ctrl", + tooltip: l('menu.quit_tt') + })); + + + // Edit menu + var editMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: l('menu.edit'), + submenu: editMenu + })); + + // Edit sub-entries + editMenu.append(new nw.MenuItem({ + label: l('menu.undo'), + click: menu_generic, + key: 'z', + modifiers: "ctrl", + tooltip: l('menu.undo_tt') + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.redo'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.redo_tt') + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.cut'), + click: function () { + pdgui.pdsend(name + " cut"); + }, + key: 'x', + modifiers: "ctrl", + tooltip: l('menu.cut_tt') + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.copy'), + click: function () { + pdgui.pdsend(name + " copy"); + }, + key: 'c', + modifiers: "ctrl", + tooltip: l('menu.copy_tt') + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.paste'), + click: function () { + pdgui.pdsend(name + " paste"); + }, + key: 'v', + modifiers: "ctrl", + tooltip: l('menu.paste_tt') + })); + + + editMenu.append(new nw.MenuItem({ + label: l('menu.duplicate'), + click: function () { + pdgui.pdsend(name + " duplicate"); + }, + key: 'd', + modifiers: "ctrl", + tooltip: l('menu.duplicate_tt') + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.selectall'), + click: function () { + pdgui.pdsend(name + " selectall"); + }, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.selectall_tt'), + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.reselect'), + // Unfortunately nw.js doesn't allow + // key: "Return" or key: "Enter", so we + // can't bind to ctrl-Enter here. (Even + // tried fromCharCode...) + click: function () { + pdgui.pdsend(name + " reselect"); + }, + key: String.fromCharCode(10), + modifiers: "ctrl", + tooltip: l('menu.reselect_tt') + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.zoomin'), + click: function () { + var z = nw.Window.get().zoomLevel; + if (z < 8) { z++; } + nw.Window.get().zoomLevel = z; + pdgui.gui_post("zoom level is " + nw.Window.get().zoomLevel); + }, + key: '=', + modifiers: "ctrl", + tooltip: l('menu.zoomin') + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.zoomout'), + click: function () { + var z = nw.Window.get().zoomLevel; + if (z > -7) { z--; } + nw.Window.get().zoomLevel = z; + pdgui.gui_post("zoom level is " + nw.Window.get().zoomLevel); + }, + key: '-', + modifiers: "ctrl", + tooltip: l('menu.zoomout_tt'), + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.tidyup'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.tidyup_tt') + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.tofront'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.tofront_tt'), + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.toback'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.toback_tt'), + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.font'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.font_tt'), + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.cordinspector'), + click: function() { + pdgui.pdsend(name + " magicglass 0"); + }, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.cordinspector_tt'), + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.find'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.find_tt'), + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.findagain'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.findagain') + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.finderror'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.finderror_tt'), + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.autotips'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.autotips_tt'), + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.editmode'), + click: function() { pdgui.pdsend(name + " editmode 0"); }, + key: 'e', + modifiers: "ctrl", + tooltip: l('menu.editmode_tt') + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.preferences'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.preferences_tt') + })); + + // Put menu + var putMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: l('menu.put'), + submenu: putMenu + })); + + // Put menu sub-entries + putMenu.append(new nw.MenuItem({ + label: l('menu.object'), + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " obj 0"); + }, + key: '1', + modifiers: "ctrl", + tooltip: l('menu.object_tt'), + })); + +/* + +proc menu_floatatom {name accel} { + pd [concat $name dirty 1 \;] + pd [concat $name floatatom $accel \;] +} + +proc menu_symbolatom {name accel} { + pd [concat $name dirty 1 \;] + pd [concat $name symbolatom $accel \;] +} + +proc menu_comment {name accel} { + pd [concat $name dirty 1 \;] + pd [concat $name text $accel \;] +} + +proc menu_graph {name} { + pd [concat $name dirty 1 \;] + set xdraw [expr int([$name.c canvasx 0])] + set ydraw [expr int([$name.c canvasy 0])] + pd [concat $name graph NULL 0 0 0 0 [expr $xdraw+30] [expr $ydraw+30] 0 [expr $ydraw+30]\;] + #pd [concat $name graph \;] +} + +proc menu_array {name} { + pd [concat $name dirty 1 \;] + pd [concat $name menuarray \;] +} + + +*/ + + putMenu.append(new nw.MenuItem({ + label: l('menu.msgbox'), + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " msg 0"); + }, + key: '2', + modifiers: "ctrl", + tooltip: l('menu.msgbox_tt'), + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.number'), + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " floatatom 0"); + }, + key: '3', + modifiers: "ctrl", + tooltip: l('menu.number_tt') + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.symbol'), + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " symbolatom 0"); + }, + key: '4', + modifiers: "ctrl", + tooltip: l('menu.symbol_tt') + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.comment'), + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " text 0"); + }, + key: '5', + modifiers: "ctrl", + tooltip: l('menu.comment_tt') + })); + + putMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.bang'), + click: function(e) { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " bng 0"); + }, + key: 'b', + modifiers: "ctrl-shift", + tooltip: l('menu.bang_tt') + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.toggle'), + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " toggle 0"); + }, + key: 't', + modifiers: "ctrl-shift", + tooltip: l('menu.toggle_tt') + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.number2'), + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " numbox 0"); + }, + key: 'n', + modifiers: "ctrl-shift", + tooltip: l('menu.number2') + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.vslider'), + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " vslider 0"); + }, + key: 'v', + modifiers: "ctrl-shift", + tooltip: l('menu.vslider_tt'), + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.hslider'), + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " hslider 0"); + }, + key: 'h', + modifiers: "ctrl-shift", + tooltip: l('menu.hslider_tt'), + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.vradio'), + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " vradio 0"); + }, + key: 'd', + modifiers: "ctrl-shift", + tooltip: l('menu.vradio_tt'), + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.hradio'), + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " hradio 0"); + }, + key: 'i', + modifiers: "ctrl", + tooltip: l('menu.hradio_tt'), + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.vu'), + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " vumeter 0"); + }, + key: 'u', + modifiers: "ctrl", + tooltip: l('menu.vu_tt'), + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.cnv'), + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " mycnv 0"); + }, + key: 'c', + modifiers: "ctrl-shift", + tooltip: l('menu.cnv_tt') + })); + + putMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.graph'), + click: function() { + pdgui.pdsend(name + " dirty 1"); + // leaving out some placement logic... see pd.tk menu_graph + pdgui.pdsend(name + " graph NULL 0 0 0 0 30 30 0 30"); + }, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.graph_tt'), + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.array'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.array_tt'), + })); + + + // Windows menu... call it "winman" (i.e., window management) to avoid confusion + var winmanMenu = new nw.Menu(); + + // Add to windows menu + windowMenu.append(new nw.MenuItem({ + label: l('menu.windows'), + submenu: winmanMenu + })); + + // Winman sub-entries + winmanMenu.append(new nw.MenuItem({ + label: l('menu.nextwin'), + click: menu_generic, + key: String.fromCharCode(12), // Page down + modifiers: "ctrl", + tooltip: l('menu.nextwin_tt'), + })); + + winmanMenu.append(new nw.MenuItem({ + label: l('menu.prevwin'), + click: menu_generic, + key: String.fromCharCode(11), // Page up + modifiers: "ctrl", + tooltip: l('menu.prevwin_tt'), + })); + + winmanMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + winmanMenu.append(new nw.MenuItem({ + label: l('menu.parentwin'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.parentwin_tt'), + })); + + winmanMenu.append(new nw.MenuItem({ + label: l('menu.pdwin'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.pdwin_tt'), + })); + + // Media menu + var mediaMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: l('menu.media'), + submenu: mediaMenu + })); + + // Media sub-entries + mediaMenu.append(new nw.MenuItem({ + label: l('menu.audio_on'), + click: menu_generic, + key: '/', + modifiers: "ctrl", + tooltip: l('menu.audio_on_tt'), + })); + + mediaMenu.append(new nw.MenuItem({ + label: l('menu.audio_off'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.audio_off_tt'), + })); + + mediaMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + mediaMenu.append(new nw.MenuItem({ + label: l('menu.test'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.test_tt'), + })); + + mediaMenu.append(new nw.MenuItem({ + label: l('menu.loadmeter'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.loadmeter_tt'), + })); + + // Help menu + var helpMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: l('menu.help'), + submenu: helpMenu + })); + + // Help sub-entries + helpMenu.append(new nw.MenuItem({ + label: l('menu.about'), + click: menu_generic, + //key: 'c', + //modifiers: "ctrl", + tooltip: l('menu.about_tt'), + })); + + helpMenu.append(new nw.MenuItem({ + label: l('menu.manual'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.manual'), + })); + + helpMenu.append(new nw.MenuItem({ + label: l('menu.browser'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.browser_tt'), + })); + + helpMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + helpMenu.append(new nw.MenuItem({ + label: l('menu.l2ork_list'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.l2ork_list_tt'), + })); + + helpMenu.append(new nw.MenuItem({ + label: l('menu.pd_list'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.pd_list_tt'), + })); + + helpMenu.append(new nw.MenuItem({ + label: l('menu.forums'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.forums_tt'), + })); + + helpMenu.append(new nw.MenuItem({ + label: l('menu.irc'), + click: menu_generic, + key: 'a', + modifiers: "ctrl", + tooltip: l('menu.irc_tt'), + })); + + // Assign to window + nw.Window.get().menu = windowMenu; + +} + + + +/* +function nw_create_canvas_window_menus(name) { + // Window menu + var windowMenu = new nw.Menu; + var windowMenu = new nw.Menu({ + type: 'menubar' + }); + + + // File menu + var fileMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: 'File', + submenu: fileMenu + })); + + // File sub-entries + fileMenu.append(new nw.MenuItem({ + label: 'New', + click: pdgui.menu_new, + key: 'n', + modifiers: "ctrl" + })); + + fileMenu.append(new nw.MenuItem({ + label: 'Open', + key: 'o', + modifiers: "ctrl", + click: function (){ + var chooser = document.querySelector('#fileDialog'); + chooser.click(); + chooser.addEventListener("change", function(evt) { + menu_open(this.value); + console.log("tried to open something"); + }, false); + } + })); + + if (pdgui.k12_mode == 1) { + fileMenu.append(new nw.MenuItem({ + label: 'K12 Demos', + click: pdgui.menu_k12_open_demos + })); + } + + fileMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + // Note: this must be different for the main Pd window + fileMenu.append(new nw.MenuItem({ + label: 'Save', + click: function (){ + pdgui.menu_save(name); + }, + key: 's', + modifiers: "ctrl" + })); + + fileMenu.append(new nw.MenuItem({ + label: 'Save as...', + click: function (){ + pdgui.menu_saveas(name); + }, + key: 'S', + modifiers: "ctrl" + })); + + if (pdgui.k12_mode == 0) { + fileMenu.append(new nw.MenuItem({ + type: 'separator' + })); + } + + // Assign to window + nw.Window.get().menu = windowMenu; +} +*/ + + </script> + </body> +</html> diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js index 62d144132..9400311c6 100644 --- a/pd/nw/pdgui.js +++ b/pd/nw/pdgui.js @@ -993,7 +993,7 @@ function gui_canvas_new(cid, width, height, geometry, editable, name, dir, dirty } last_loaded = cid; // Not sure why resize and topmost are here-- but we'll pass them on for the time being... - patchwin[cid] = nw_create_window(cid, 'pd-canvas', width, height, xpos, ypos, menu_flag, + patchwin[cid] = nw_create_window(cid, 'pd_canvas', width, height, xpos, ypos, menu_flag, resize[cid], topmost[cid], my_canvas_color, name, dir, dirty_flag, cargs, null); // initialize variable to reflect that this window has been opened @@ -1006,6 +1006,14 @@ function canvas_map(name) { pdsend(name + " map 1"); } +function gui_canvas_erase_all_gobjs(cid) { + var top = get_item(cid, 'patchsvg'); + var elem; + while (elem = top.firstChild) { + top.removeChild(elem); + } +} + exports.canvas_map = canvas_map; /* @@ -1709,16 +1717,29 @@ exports.connect = connect; // can be removed. +var plums = require('string_decoder').StringDecoder; +var rufus = new plums('utf8'); + var nextCmd = ""; // Build up a command across lines (or buffers) +var cmdHeader = 0; function init_socket_events () { client.on('data', function(data) { // console.log('DATA: ' + data); var dataStr = data.toString('utf-8'); + + var mumps = rufus.write(data); + if (rufus.end() !== "") { + console.log("fuckkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk, we got hitchikers... " + rufus.end()); + } + + // console.log("The whole buffer is " + dataStr); +// if (nextCmd !== "") { +// console.log("fuckkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk nextCmd is " + nextCmd); +// } var arr = dataStr.split("\n"); var arrLen = arr.length; - var cmdHeader = 0; for (var i = 0; i < arrLen; i++) { var prefix = arr[i].substring(0, 2); if (prefix == 'nw' || prefix == 'nn') { @@ -1733,12 +1754,12 @@ function init_socket_events () { } // check if we end with a semicolon followed by a newline if (nextCmd.slice(-1) === ";" && nextCmd.slice(-2) !== '\\') { -// console.log("raw cmd is: " + nextCmd); - nextCmd = nextCmd.replace(/\n/g, "\\n"); +//console.log("raw cmd is: " + nextCmd); +// nextCmd = nextCmd.replace(/\n/g, "\\n"); // nextCmd = nextCmd.replace(/'/g, "\\\'"); var selector = nextCmd.slice(0, nextCmd.indexOf(" ")); var args = nextCmd.slice(selector.length + 1, -1); -// console.log(selector + '(' + args + ');'); +// console.log("About to eval: " + selector + '(' + args + ');'); eval(selector + '(' + args + ');'); nextCmd = ""; cmdHeader = 0; @@ -1837,22 +1858,25 @@ function gui_configure_item(cid, tag, attributes) { } // Most of these map either to pd.tk procs, or in some cases Tk canvas subcommands -function gui_text_create_gobj(cid, tag, xpos, ypos) { +function gui_text_create_gobj(cid, tag, type, xpos, ypos, is_toplevel) { var svg = get_item(cid, "patchsvg"); // "patchsvg" is id for the svg in the DOM // Put objects on half-pixels to make them crisp (look in to the difference between // this and the object-rendering 'crispEdges' attribute) xpos += 0.5; ypos += 0.5; - var transform_string = 'translate(' + xpos + ',' + ypos + ')'; + var transform_string = 'matrix(1,0,0,1,' + xpos + ',' + ypos + ')'; var g = create_item(cid, 'g', { id: tag + 'gobj', - transform: transform_string + transform: transform_string, + class: type + (is_toplevel !== 0 ? '' : ' gop') }); svg.appendChild(g); +// hm... why returning g and not the return value of appendChild? +// console.log("create gobj tag is " + tag + " and ret is " + g); return g; } -function gui_text_drawborder(cid, tag, isbroken, x1, y1, x2, y2) { +function gui_text_drawborder(cid, tag, bgcolor, isbroken, x1, y1, x2, y2) { var g = get_gobj(cid, tag); // isbroken means either // a) the object couldn't create or @@ -1863,9 +1887,11 @@ function gui_text_drawborder(cid, tag, isbroken, x1, y1, x2, y2) { stroke: 'black', fill: 'none', 'shape-rendering': 'optimizeSpeed', - id: tag + 'border', - class: (isbroken ? 'broken_border' : '') + class: 'border' }); + if (isbroken === 1) { + rect.classList.add('broken_border'); + } g.appendChild(rect); } @@ -1898,6 +1924,11 @@ function gui_canvas_drawio(cid, parenttag, tag, x1, y1, x2, y2, basex, basey, ty gui_post("the tag for this XLET is " + tag); } +function gui_canvas_redraw_io(cid, parenttag, tag, x, type, i, basex) { + var xlet = get_item(cid, tag + type + i); + configure_item(xlet, { x: x - basex}); +} + function gui_eraseio(cid, tag) { gui_post("the tag for this bout-to-ba-leted XLET is " + tag); var xlet = get_item(cid, tag); @@ -1943,21 +1974,29 @@ function gui_message_drawborder(cid,tag,width,height) { points: p_array.join(), fill: 'none', stroke: 'black', - 'stroke-width': 1, - id: tag + 'border' +// 'stroke-width': 1, + class: 'border' +// id: tag + 'border' }); g.appendChild(polygon); } function gui_message_flash(cid, tag, state) { - var b = get_item(cid, tag + 'border'); - var w; - if (state != 0) { w = 4; } else { w = 1; } - configure_item(b, { 'stroke-width': w }); + var g = get_gobj(cid, tag); + if (state !== 0) { + g.classList.add('flashed'); + } else { + g.classList.remove('flashed'); + } +// var b = get_item(cid, tag + 'border'); +// var w; +// if (state != 0) { w = 4; } else { w = 1; } +// configure_item(b, { 'stroke-width': w }); } function gui_message_redraw_border(cid,tag,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14) { - var b = get_item(cid, tag + 'border'); + var g = get_gobj(cid, tag); + var b = g.querySelector('.border'); var p_array = [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14]; configure_item(b, { points: p_array.join(" "), @@ -2035,7 +2074,8 @@ function gui_canvas_updateline(cid,tag,x1,y1,x2,y2,yoff) { configure_item(cord, { d: d_array.join(" ") }); } -function gui_text_new(canvasname, myname, type, isselected, x, y, text, font) { +function gui_text_new(canvasname, myname, type, isselected, left_margin, top_margin, + bottom_margin, pix_high, text, font) { // gui_post("font is " + font); var g = get_gobj(canvasname, myname); @@ -2044,8 +2084,8 @@ function gui_text_new(canvasname, myname, type, isselected, x, y, text, font) { // at the top-right corner of the text's bbox. SVG uses the baseline. // There's probably a programmatic way to do this, but for now-- fudge factors // based on the DejaVu Sans Mono font. :) - x: x, - y: y + 10, + x: left_margin, + y: pix_high - bottom_margin - top_margin - 1, // Turns out we can't do 'hanging' baseline // because it's borked when scaled. Bummer... // 'dominant-baseline': 'hanging', @@ -2068,6 +2108,8 @@ function gui_text_new(canvasname, myname, type, isselected, x, y, text, font) { } } +// Because of the overly complex code path inside +// canvas_setgraph, multiple erasures can be triggered in a row. function gui_gobj_erase(cid, tag) { var g = get_gobj(cid, tag); if (g !== null) { @@ -2087,42 +2129,40 @@ function gui_text_set (cid, tag, text) { } } -// Not sure whether this is even used anymore function gui_text_redraw_border(cid, tag, x1, y1, x2, y2) { - var b = get_item(cid, tag + 'border'); - configure_item(b, { - width: x2 - x1, - height: y2 - y1 - }); + var i; + var g = get_gobj(cid, tag); + var b = g.querySelectorAll('.border'); + for (i = 0; i < b.length; b++) { + configure_item(b[i], { + width: x2 - x1, + height: y2 - y1 + }); + } } function gui_text_select(cid, tag) { var g = get_gobj(cid, tag); - var b = get_item(cid, tag + 'border'); +// var b = get_item(cid, tag + 'border'); if (g !== null) { - configure_item(g, { class: 'selected' }); + g.classList.add('selected'); +// configure_item(g, { class: 'selected' }); } else { console.log("text_select: something wrong with group tag: " + tag); } - if (b !== null) { - configure_item(b, { class: 'selected_border' }); - } +// if (b !== null) { +// configure_item(b, { class: 'selected_border' }); +// } } function gui_text_deselect(cid, tag) { - gui_post("deselecting text with tag..." + tag); +// gui_post("deselecting text with tag..." + tag); var gobj = get_gobj(cid, tag) - var border = get_item(cid, tag + 'border'); if (gobj !== null) { - configure_item(gobj, { class: "" }); + gobj.classList.remove('selected'); } else { console.log("text_deselect: something wrong with tag: " + tag + 'gobj'); } - if (border !== null) { - configure_item(border, { class: "" }); - } else { - console.log("text_select: something wrong with tag: " + tag + 'border'); - } } function gui_text_select_color(cid, tag) { @@ -2144,11 +2184,15 @@ function gui_canvas_displace_withtag(name, dx, dy) { var pwin = patchwin[name]; var ol = pwin.window.document.getElementsByClassName('selected'); for (var i = 0; i < ol.length; i++) { - var new_tx = dx + ol[i].transform.baseVal.getItem(0).matrix.e; - var new_ty = dy + ol[i].transform.baseVal.getItem(0).matrix.f; - ol[i].setAttributeNS(null, 'transform', - 'translate(' + new_tx + ',' + new_ty + ')'); + var elem = ol[i].transform.baseVal.getItem(0); + var new_tx = dx + elem.matrix.e; + var new_ty = dy + elem.matrix.f; + elem.matrix.e = new_tx; + elem.matrix.f = new_ty; } +// elem.setAttributeNS(null, 'transform', +// 'translate(' + new_tx + ',' + new_ty + ')'); +// } } function gui_create_selection_rectangle(cid, x1, y1, x2, y2) { @@ -2204,7 +2248,7 @@ function gui_bng_flash(cid, tag, color) { configure_item(button, { fill: color }); } -function gui_create_toggle(cid, tag, color, state, width, p1,p2,p3,p4,p5,p6,p7,p8,basex,basey) { +function gui_create_toggle(cid, tag, color, width, state, p1,p2,p3,p4,p5,p6,p7,p8,basex,basey) { var g = get_gobj(cid, tag); var points_array = [p1 - basex, p2 - basey, p3 - basex, p4 - basey @@ -2257,7 +2301,7 @@ function gui_toggle_resize_cross(cid,tag,w,p1,p2,p3,p4,p5,p6,p7,p8,basex,basey) function gui_toggle_update(cid, tag, state, color) { var cross1 = get_item(cid, tag + 'cross1'); var cross2 = get_item(cid, tag + 'cross2'); - if (state) { + if (!!state) { configure_item(cross1, { display: 'inline', stroke: color }); configure_item(cross2, { display: 'inline', stroke: color }); } else { @@ -2554,7 +2598,8 @@ function gui_iemgui_drawborder(cid, tag, bgcolor, x1, y1, x2, y2) { stroke: 'black', 'shape-rendering': 'optimizeSpeed', 'stroke-width': 1, - id: tag + 'border' + class: 'border' +// id: tag + 'border' }); g.appendChild(rect); } @@ -2580,6 +2625,9 @@ function gui_iemgui_label_new(cid, tag, x, y, color, text, font) { var text_node = patchwin[cid].window.document.createTextNode(text); svg_text.appendChild(text_node); g.appendChild(svg_text); + var foo = patchwin[cid].window.document.getElementById(tag + 'label'); +// console.log("foo is " + foo); +// console.log("label_new tag is " + tag); } function gui_iemgui_label_set(cid, tag, text) { @@ -2603,6 +2651,7 @@ function gui_iemgui_label_color(cid, tag, color) { function gui_iemgui_label_select(cid, tag, is_selected) { var svg_text = get_item(cid, tag + 'label'); +// console.log("tag is " + tag + " and svg_text is " + svg_text); if (is_selected) { svg_text.classList.add('iemgui_label_selected'); } else { @@ -2664,9 +2713,13 @@ function gui_mycanvas_select_color(cid,tag,color) { var item = get_item(cid,tag + 'drag_handle'); configure_item(item, {stroke: color}); } - -// This should be merged with gui_create_gobj somehow -function gui_create_scalar(cid, tag, isselected, t1, t2, t3, t4, t5, t6) { + +function gui_create_scalar(cid, tag, isselected, t1, t2, t3, t4, t5, t6, + is_toplevel) { +gui_post("creating a scalar..."); +gui_post("is_toplevel is " + is_toplevel); + // we should probably use create_gobj here, but we're doing some initial + // scaling that normal gobjs don't need... var svg = get_item(cid, "patchsvg"); // "patchsvg" is id for the svg in the DOM // Normally put objects on half-pixels to make them crisp, but if we create a // scalar in an object box we already did that. This unfortunately creates a 0.5 @@ -2680,26 +2733,34 @@ function gui_create_scalar(cid, tag, isselected, t1, t2, t3, t4, t5, t6) { var g = create_item(cid, 'g', { id: tag + 'gobj', transform: transform_string, - class: (isselected ? 'selected' : '') }); + if (isselected !== 0) { + g.classList.add('selected'); + } + if (is_toplevel === 0) { + g.classList.add('gop'); + } // Let's make a selection rect... but we can't make it // a child of the gobj group because the getrect fn gives // us a bbox in the canvas coord system var selection_rect = create_item(cid, 'rect', { - id: tag + 'selection_rect', +// id: tag + 'selection_rect', + class: 'border', display: 'none', fill: 'none', 'pointer-events': 'none' }); g.appendChild(selection_rect); svg.appendChild(g); - gui_post("made a scalar..."); +// gui_post("made a scalar..."); return g; } function gui_scalar_erase(cid, tag) { var g = get_gobj(cid, tag); - g.parentNode.removeChild(g); + if (g !== null) { + g.parentNode.removeChild(g); + } // selection rect... // var sr = get_item(cid, tag + 'selection_rect'); // sr.parentNode.removeChild(sr); @@ -2712,14 +2773,15 @@ function gui_scalar_draw_select_rect(cid, tag, state, x1, y1, x2, y2, basex, bas // the coords relative to the scalar's x/y-- hence we subtract the scalar's basex/basey // from the coords below //gui_post("drawselectrect: " + x1 + " " + y1 + " " + x2 + " " + y2 + " " + basex + " " + basey); - var r = get_item(cid, tag + 'selection_rect'); - configure_item(r, { + var g = get_gobj(cid, tag); + var b = g.querySelector('.border'); + configure_item(b, { display: (state ? 'inline' : 'none'), x: (x1 - basex), y: (y1 - basey), width: x2 - x1, height: y2 - y1, - stroke: 'blue', +// stroke: 'blue', }); } @@ -2731,7 +2793,6 @@ function gui_create_scalar_group(cid, tag, parent_tag, attr_array) { attr_array.push("id", tag); var g = create_item(cid, 'g', attr_array); parent.appendChild(g); - gui_post("made an innder scalar group"); return g; } @@ -2832,6 +2893,22 @@ function gui_draw_configure_all(cid, tag, attr_array) { configure_item(item, attr_array); } +// Plots for arrays and data structures +function gui_plot_vis(cid, basex, basey, data_array, attr_array, tag_array) { + var g = get_item(cid, tag_array[0]); + var p = create_item(cid, 'path', { + d: data_array.join(" "), + id: tag_array[1], +// stroke: 'red', +// fill: 'black', +// 'stroke-width': '0' + }); + configure_item(p, attr_array); + if (g !== null) { + g.appendChild(p); + } +} + function add_popup(cid, popup) { popup_menu[cid] = popup; } @@ -2906,11 +2983,16 @@ exports.popup_action = popup_action; // g.appendChild(b); //} +// refactor-- use a class so this can happen in css function gui_graph_fill_border(cid, tag) { - var b = get_item(cid, tag + 'border'); - configure_item(b, { - fill: 'gray' - }); + var i; + var g = get_gobj(cid, tag); + var b = g.querySelectorAll('.border'); + for (i = 0; i < b.length; i++) { + configure_item(b[i], { + fill: 'gray' + }); + } } function gui_graph_deleteborder(cid, tag) { @@ -2995,7 +3077,18 @@ function gui_canvas_drawredrect(cid, x1, y1, x2, y2) { function gui_canvas_deleteredrect(cid) { var r = get_item(cid, 'GOP'); - r.parentNode.removeChild(r); + // We need to check for existence here, because the first + // time setting GOP in properties, there is no red rect yet. + // But setting properties when the subpatch's window is + // visible calls glist_redraw, and glist_redraw will try to delete + // the red rect _before_ it's been drawn in this case. + // Unfortunately, it's quite difficult to refactor those c + // functions without knowing the side effects. But ineffectual + // gui calls should really be minimized-- otherwise it's simply + // too difficult to debug what's being passed over the socket. + if (r !== null) { + r.parentNode.removeChild(r); + } } // Magic Glass (aka Cord Inspector) @@ -3098,16 +3191,33 @@ exports.file_dialog_callback = function(file_string) { function gui_iemgui_dialog(did, attr_array) { gui_post("got a gfxstub " + did + "!!!"); - for (var i = 0; i < attr_array.length; i++) { - attr_array[i] = '"' + attr_array[i] + '"'; - } - dialogwin[did] = nw_create_window(did, 'pd-properties', 265, 540, 20, 20, 0, +// for (var i = 0; i < attr_array.length; i++) { +// attr_array[i] = '"' + attr_array[i] + '"'; +// } + dialogwin[did] = nw_create_window(did, 'iemgui', 265, 540, 20, 20, 0, 0, 1, 'white', 'Properties', '', 0, null, attr_array); } +function gui_canvas_dialog(did, attr_arrays) { + var i, j, inner_array; + gui_post("got a gfxstub " + did + "!!!"); + gui_post("attr_arrays are " + attr_arrays); +// for (i = 0; i < attr_arrays.length; i++) { +// inner_array = attr_arrays[i]; +// if (inner_array !== undefined) { +// for (j = 0; j < inner_array.length; j++) { +// inner_array[i] = '"' + inner_array[i] + '"'; +// } +// } +// } + dialogwin[did] = nw_create_window(did, 'canvas', 265, 540, 20, 20, 0, + 0, 1, 'white', 'Properties', '', 0, null, attr_arrays); +} + function gui_remove_gfxstub(did) { - if (dialogwin[did] !== null) { +gui_post("did is " + did + " and dialogwin[did] is " + dialogwin[did]); + if (dialogwin[did] !== undefined && dialogwin[did] !== null) { dialogwin[did].window.close(true); dialogwin[did] = null; } diff --git a/pd/nw/todo.txt b/pd/nw/todo.txt index b6d02cf42..3bf0e2321 100644 --- a/pd/nw/todo.txt +++ b/pd/nw/todo.txt @@ -110,6 +110,26 @@ Everything else: * tgl 'X' doesn't show up * gui_graph_fill_border: use css class selectors instead of configuration * standardize javascript function names +* in gui_plot_vis, we have to check for gobj existence. For some reason, at + very fast drawing rates we end up with two svg elements if we don't check + for this. Not sure why +* add garray_update for changing the path coords without having to recreate + the entire scalar edifice +* add "p" type to gui_vmess for pointers +* when duplicating a large number of iemguis, the label or border will eventually try to append to null. + It looks like it's receiving the correct gui calls from Pd, in the correct order. But for some reason the + calls from Pd are getting split in the middle of a string. Not sure why, probably something to do + with the hacky parser I wrote to split on newlines. Anyway, when we can just split on semis this problem + should hopefully go away. Make sure to test for it once that happens. + + Some gui_posts that show the problem-- the string is split between lines 2 and 3: + nextCmd is gui_create_toggle ".x98be5e8","x99c0740","#000000",1,0,181,67,192,78,181,78,192,67,179,65; + nextCmd is gui_iemgui_label_new ".x98be5e + 8","x99c0740",17,7,"#000000","","{{DejaVu Sans Mono} -10 normal}"; + nextCmd is gui_canvas_drawio ".x98be5e8","x99c0740",".x98be5e8.t99c0de0o0",179,79,186,80,179,65,"o",0,0,1; + the tag for this XLET is .x98be5e8.t99c0de0o0 + +remove gui_text_select_color (css takes care of this) Crashers -------- diff --git a/pd/src/g_all_guis.c b/pd/src/g_all_guis.c index bb97505d1..67e3cd43e 100644 --- a/pd/src/g_all_guis.c +++ b/pd/src/g_all_guis.c @@ -1209,13 +1209,16 @@ void iemgui_base_draw_new(t_iemgui *x) { // "-stroke $pd_colors(iemgui_border) -fill #%6.6x " // "-tags {%lxBASE x%lx text iemgui border}\n", // canvas, x1,y1,x2,y2, x->x_bcol, x, x); - gui_vmess("gui_text_create_gobj", "ssii", canvas_tag(canvas), gobj_tag(x), - x1, y1); + gui_vmess("gui_text_create_gobj", "sssiii", canvas_tag(canvas), gobj_tag(x), + "iemgui", x1, y1, glist_istoplevel(x->x_glist)); char colorbuf[MAXPDSTRING]; sprintf(colorbuf, "#%6.6x", x->x_bcol); - gui_vmess("gui_iemgui_drawborder", "sssiiii", - canvas_tag(canvas), gobj_tag(x), - colorbuf, x1, y1, x2, y2); + gui_vmess("gui_text_drawborder", "sssiiiii", + canvas_tag(canvas), + gobj_tag(x), + colorbuf, + 0, + x1, y1, x2, y2); } void iemgui_base_draw_move(t_iemgui *x) { diff --git a/pd/src/g_array.c b/pd/src/g_array.c index 796f1895f..2536eb759 100644 --- a/pd/src/g_array.c +++ b/pd/src/g_array.c @@ -152,7 +152,7 @@ static char garray_arraytemplatefile[] = "\ #N canvas 0 0 458 153 10;\n\ #X obj 43 31 struct _float_array array z float float style\n\ float linewidth float color symbol fillcolor symbol outlinecolor;\n\ -#X obj 43 70 old_plot z color linewidth 0 0 1 style fillcolor outlinecolor;\n\ +#X obj 43 70 plot z color linewidth 0 0 1 style fillcolor outlinecolor;\n\ "; static char garray_floattemplatefile[] = "\ #N canvas 0 0 458 153 10;\n\ @@ -525,27 +525,49 @@ void canvas_menuarray(t_glist *canvas) gfxstub_new(&x->gl_pd, x, cmdbuf); } - /* called from graph_dialog to set properties */ -void garray_properties(t_garray *x, t_glist *canvas) + /* called from canvas_dialog to return array properties for the gui */ +int garray_properties(t_garray *x, t_symbol **gfxstubp, t_symbol **namep, + int *sizep, int *flagsp, t_symbol **fillp, t_symbol **outlinep) { - char cmdbuf[200]; + char namebuf[MAXPDSTRING]; t_array *a = garray_getarray(x); if (!a) - return; - gfxstub_deleteforkey(x); - /* create dialog window. LATER fix this to escape '$' + return 0; + //gfxstub_deleteforkey(x); + /* LATER fix this to escape '$' properly; right now we just detect a leading '$' and escape it. There should be a systematic way of doing this. */ + /* still don't understand this filestyle business... */ int filestyle = (x->x_style == 0 ? PLOTSTYLE_POLY : (x->x_style == 1 ? PLOTSTYLE_POINTS : x->x_style)); - //fprintf(stderr," garray_properties %d\n", filestyle); - sprintf(cmdbuf, ((x->x_name->s_name[0] == '$') ? - "pdtk_array_dialog %%s \\%s %d %d 0 .x%lx %s %s\n" : - "pdtk_array_dialog %%s %s %d %d 0 .x%lx %s %s\n"), x->x_name->s_name, - a->a_n, x->x_saveit + 2 * filestyle + 8 * x->x_hidename + - 16 * x->x_joc, (long unsigned int)glist_getcanvas(canvas), - x->x_fillcolor->s_name, x->x_outlinecolor->s_name); - gfxstub_new(&x->x_gobj.g_pd, x, cmdbuf); + int flags = x->x_saveit + 2 * filestyle + 8 * x->x_hidename + 16 * x->x_joc; + + if (x->x_name->s_name[0] == '$') + { + sprintf(namebuf, "\\%s", x->x_name->s_name); + } + else + { + sprintf(namebuf, "%s", x->x_name->s_name); + } + + *gfxstubp = gensym(gfxstub_new2(&x->x_gobj.g_pd, x)); + *namep = gensym(namebuf); + *sizep = a->a_n; + *flagsp = flags; + *fillp = x->x_fillcolor; + *outlinep = x->x_outlinecolor; + //sprintf(cmdbuf, ((x->x_name->s_name[0] == '$') ? + // "pdtk_array_dialog %%s \\%s %d %d 0 .x%lx %s %s\n" : + // "pdtk_array_dialog %%s %s %d %d 0 .x%lx %s %s\n"), + // x->x_name->s_name, + // a->a_n, + // x->x_saveit + 2 * filestyle + 8 * x->x_hidename + 16 * x->x_joc, + // (long unsigned int)glist_getcanvas(canvas), + // x->x_fillcolor->s_name, + // x->x_outlinecolor->s_name); + //gfxstub_new(&x->x_gobj.g_pd, x, cmdbuf); + return 1; } /* this is called back from the dialog window to create a garray. @@ -1386,7 +1408,8 @@ static void garray_select(t_gobj *z, t_glist *glist, int state) t_garray *x = (t_garray *)z; sys_vgui("pdtk_select_all_gop_widgets .x%lx %lx %d\n", glist_getcanvas(glist), x->x_glist, state); - /* fill in later */ + + scalar_select((t_gobj *)x->x_scalar, glist, state); } static void garray_activate(t_gobj *z, t_glist *glist, int state) @@ -1564,7 +1587,7 @@ void garray_redraw(t_garray *x) /* } jsarlo */ } - /* This functiopn gets the template of an array; if we can't figure + /* This function gets the template of an array; if we can't figure out what template an array's elements belong to we're in grave trouble when it's time to free or resize it. */ t_template *garray_template(t_garray *x) diff --git a/pd/src/g_canvas.c b/pd/src/g_canvas.c index 62f94ca00..9d5b89b39 100644 --- a/pd/src/g_canvas.c +++ b/pd/src/g_canvas.c @@ -862,6 +862,8 @@ void canvas_map(t_canvas *x, t_floatarg f) sys_vgui(".x%lx.c dtag all selected\n", x); //sys_vgui(".x%lx.c delete all\n", x); sys_vgui("foreach item [.x%lx.c find withtag {(!root)}] { .x%lx.c delete $item }\n", x, x); + gui_vmess("gui_canvas_erase_all_gobjs", "s", + canvas_tag(x)); x->gl_mapped = 0; } } diff --git a/pd/src/g_editor.c b/pd/src/g_editor.c index df54b6a97..6593e85b6 100644 --- a/pd/src/g_editor.c +++ b/pd/src/g_editor.c @@ -1858,6 +1858,7 @@ void canvas_undo_canvas_apply(t_canvas *x, void *z, int action) //redraw canvas_setgraph(x, x->gl_isgraph + 2*x->gl_hidetext, 0); canvas_dirty(x, 1); + if (x->gl_havewindow) { canvas_redraw(x); @@ -2658,13 +2659,15 @@ void canvas_setgraph(t_glist *x, int flag, int nogoprect) } if (x->gl_owner && !x->gl_loading && glist_isvisible(x->gl_owner)) { + gobj_vis(&x->gl_gobj, x->gl_owner, 0); gobj_vis(&x->gl_gobj, x->gl_owner, 1); canvas_fixlinesfor(x->gl_owner, &x->gl_obj); } } } -void garray_properties(t_garray *x, t_glist *canvas); +int garray_properties(t_garray *x, t_symbol **gfxstubp, t_symbol **namep, + int *sizep, int *flagsp, t_symbol **fillp, t_symbol **outlinep); /* tell GUI to create a properties dialog on the canvas. We tell the user the negative of the "pixel" y scale to make it appear to grow @@ -2672,27 +2675,98 @@ void garray_properties(t_garray *x, t_glist *canvas); void canvas_properties(t_glist *x) { t_gobj *y; - char graphbuf[200]; + char graphbuf[200], *gfx_tag; + + gfx_tag = gfxstub_new2(&x->gl_pd, x); + + /* We need to go through and delete any + gfxstubs for the arrays in this glist. + Otherwise we could get a message to the + GUI in the middle of our properties + message below. This is needed because + the array properties just share the + same window with the canvas properties. + */ + for (y = x->gl_list; y; y = y->g_next) + if (pd_class(&y->g_pd) == garray_class) + gfxstub_deleteforkey((t_garray *)y); + + gui_start_vmess("gui_canvas_dialog", "s", gfx_tag); + gui_start_array(); /* Main array for nested arrays of attributes */ + + gui_start_array(); /* Nested array for canvas attributes */ if (glist_isgraph(x) != 0) - sprintf(graphbuf, - "pdtk_canvas_dialog %%s %g %g %d %g %g %g %g %d %d %d %d\n", - 0., 0., - glist_isgraph(x) ,//1, - x->gl_x1, x->gl_y1, x->gl_x2, x->gl_y2, - (int)x->gl_pixwidth, (int)x->gl_pixheight, - (int)x->gl_xmargin, (int)x->gl_ymargin); - else sprintf(graphbuf, - "pdtk_canvas_dialog %%s %g %g %d %g %g %g %g %d %d %d %d\n", - glist_dpixtodx(x, 1), -glist_dpixtody(x, 1), - 0, - 0., -1., 1., 1., - (int)x->gl_pixwidth, (int)x->gl_pixheight, - (int)x->gl_xmargin, (int)x->gl_ymargin); - gfxstub_new(&x->gl_pd, x, graphbuf); - /* if any arrays are in the graph, put out their dialogs too */ + { + //sprintf(graphbuf, + // "pdtk_canvas_dialog %%s %g %g %d %g %g %g %g %d %d %d %d\n", + // 0., 0., + // glist_isgraph(x) ,//1, + // x->gl_x1, x->gl_y1, x->gl_x2, x->gl_y2, + // (int)x->gl_pixwidth, (int)x->gl_pixheight, + // (int)x->gl_xmargin, (int)x->gl_ymargin); + gui_s("x-scale"); gui_f(0.); + gui_s("y-scale"); gui_f(0.); + gui_s("display-flags"); gui_i(glist_isgraph(x)); + gui_s("x1"); gui_f(x->gl_x1); + gui_s("y1"); gui_f(x->gl_y1); + gui_s("x2"); gui_f(x->gl_x2); + gui_s("y2"); gui_f(x->gl_y2); + gui_s("x-pix"); gui_i((int)x->gl_pixwidth); + gui_s("y-pix"); gui_i((int)x->gl_pixheight); + gui_s("x-margin"); gui_i((int)x->gl_xmargin); + gui_s("y-margin"); gui_i((int)x->gl_ymargin); + } + else + { + //sprintf(graphbuf, + // "pdtk_canvas_dialog %%s %g %g %d %g %g %g %g %d %d %d %d\n", + // glist_dpixtodx(x, 1), -glist_dpixtody(x, 1), + // 0, + // 0., -1., 1., 1., + // (int)x->gl_pixwidth, (int)x->gl_pixheight, + // (int)x->gl_xmargin, (int)x->gl_ymargin); + gui_s("x-scale"); gui_f(glist_dpixtodx(x, 1)); + gui_s("y-scale"); gui_f(-glist_dpixtody(x, 1)); + gui_s("display-flags"); gui_i(0); + gui_s("x1"); gui_f(0.); + gui_s("y1"); gui_f(-1.); + gui_s("x2"); gui_f(1.); + gui_s("y2"); gui_f(1.); + gui_s("x-pix"); gui_i((int)x->gl_pixwidth); + gui_s("y-pix"); gui_i((int)x->gl_pixheight); + gui_s("x-margin"); gui_i((int)x->gl_xmargin); + gui_s("y-margin"); gui_i((int)x->gl_ymargin); + } + //gfxstub_new(&x->gl_pd, x, graphbuf); + + gui_end_array(); /* end of nested array for canvas attributes */ + + /* if any arrays are in the graph, pull out their attributes */ for (y = x->gl_list; y; y = y->g_next) + { if (pd_class(&y->g_pd) == garray_class) - garray_properties((t_garray *)y, x); + { + t_garray *garray = (t_garray *)y; + t_symbol *gfxstub, *name, *fill, *outline; + int size, flags; + /* garray_properties can fail to find an array, so we won't + send props if it has a return value of zero */ + if (garray_properties((t_garray *)y, &gfxstub, &name, &size, &flags, + &fill, &outline)) + { + gui_start_array(); /* inner array for this array's attributes */ + gui_s("array_gfxstub"); gui_s(gfxstub->s_name); + gui_s("array_name"); gui_s(name->s_name); + gui_s("array_size"); gui_i(size); + gui_s("array_flags"); gui_i(flags); + gui_s("array_fill"); gui_s(fill->s_name); + gui_s("array_outline"); gui_s(outline->s_name); + gui_end_array(); + } + } + } + gui_end_array(); + gui_end_vmess(); } /* called from the gui when "OK" is selected on the canvas properties @@ -2798,6 +2872,8 @@ static void canvas_donecanvasdialog(t_glist *x, canvas_setgraph(x, graphme, 0); canvas_dirty(x, 1); +// we're drawn at this point + // make sure gop is never smaller than its text // if one wants smaller gop window, make sure to disable text if (x->gl_isgraph && !x->gl_hidetext && x->gl_owner) diff --git a/pd/src/g_graph.c b/pd/src/g_graph.c index 9d1a8cca9..2071cc48d 100644 --- a/pd/src/g_graph.c +++ b/pd/src/g_graph.c @@ -862,6 +862,9 @@ int garray_getname(t_garray *x, t_symbol **namep); graph decorations in toplevels... */ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis) { + +post("inside graph vis"); + t_glist *x = (t_glist *)gr; //fprintf(stderr,"graph vis canvas=%lx gobj=%lx %d\n", // (t_int)parent_glist, (t_int)gr, vis); @@ -897,9 +900,9 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis) int xpix, ypix; xpix = text_xpix(&x->gl_obj, parent_glist); ypix = text_ypix(&x->gl_obj, parent_glist); - gui_vmess("gui_text_create_gobj", "ssii", + gui_vmess("gui_text_create_gobj", "sssiii", canvas_tag(glist_getcanvas(x->gl_owner)), - tag, xpix, ypix); + tag, "graph", xpix, ypix, 1); if (canvas_showtext(x)) rtext_draw(glist_findrtext(parent_glist, &x->gl_obj)); } @@ -930,9 +933,10 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis) // glist_getcanvas(x->gl_owner), ////parent_glist, // x1, y1, x1, y2, x2, y2, x2, y1, x1, y1, tag); - gui_vmess("gui_text_drawborder", "ssiiiii", + gui_vmess("gui_text_drawborder", "sssiiiii", canvas_tag(glist_getcanvas(x->gl_owner)), tag, + "none", 0, x1, y1, x2, y2); glist_noselect(x->gl_owner); gui_vmess("gui_graph_fill_border", "ssi", @@ -973,9 +977,10 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis) char tagbuf[MAXPDSTRING]; sprintf(tagbuf, "%sR", tag); - gui_vmess("gui_text_drawborder", "ssiiiii", + gui_vmess("gui_text_drawborder", "sssiiiii", canvas_tag(glist_getcanvas(x->gl_owner)), tag, + "none", 0, x1, y1, x2, y2); /* write garrays' names along the top */ for (i = (y1 < y2 ? y1 : y2)-1, g = x->gl_list; g; g = g->g_next) @@ -1521,6 +1526,7 @@ static void graph_select(t_gobj *z, t_glist *glist, int state) (g->g_pd->c_wb->w_displacefnwtag != NULL) || (g && pd_class((t_pd *)g) == garray_class))) { + post("inside flub... selecting a fluarg"); gobj_select(g, x, state); } } @@ -1558,6 +1564,7 @@ static void graph_delete(t_gobj *z, t_glist *glist) static void graph_delete(t_gobj *z, t_glist *glist) { //fprintf(stderr,"graph_delete\n"); + post("how many more times..."); t_glist *x = (t_glist *)z; t_gobj *y; text_widgetbehavior.w_deletefn(z, glist); diff --git a/pd/src/g_magicglass.c b/pd/src/g_magicglass.c index efacecd13..9a7f36c63 100644 --- a/pd/src/g_magicglass.c +++ b/pd/src/g_magicglass.c @@ -144,8 +144,8 @@ void magicGlass_drawNew(t_magicGlass *x) x->x_c); sys_vgui(".x%x.c raise magicGlassText\n", x->x_c); - gui_vmess("gui_text_create_gobj", "ssii", - canvas_tag(x->x_c), "cord_inspector", 0, 0); + gui_vmess("gui_text_create_gobj", "sssiii", + canvas_tag(x->x_c), "cord_inspector", "cord_inspector", 0, 0, 0); gui_vmess("gui_create_cord_inspector", "s", canvas_tag(x->x_c)); magicGlass_updateText(x, 0); diff --git a/pd/src/g_mycanvas.c b/pd/src/g_mycanvas.c index 18c504bd5..00fbf8024 100644 --- a/pd/src/g_mycanvas.c +++ b/pd/src/g_mycanvas.c @@ -35,8 +35,8 @@ void my_canvas_draw_new(t_my_canvas *x, t_glist *glist) x->x_gui.x_bcol, x, x); char colorbuf[MAXPDSTRING]; sprintf(colorbuf, "#%6.6x", x->x_gui.x_bcol); - gui_vmess("gui_text_create_gobj", "ssii", canvas_tag(canvas), - gobj_tag(x), x1, y1); + gui_vmess("gui_text_create_gobj", "sssiii", canvas_tag(canvas), + gobj_tag(x), "iemgui", x1, y1, glist_istoplevel(canvas)); gui_vmess("gui_create_mycanvas", "sssiiiiii", canvas_tag(canvas), gobj_tag(x), colorbuf, x1, y1, x1+x->x_vis_w, y1+x->x_vis_h, x1+x->x_gui.x_w, y1+x->x_gui.x_h); diff --git a/pd/src/g_rtext.c b/pd/src/g_rtext.c index 116f01ed1..4d9596770 100644 --- a/pd/src/g_rtext.c +++ b/pd/src/g_rtext.c @@ -362,11 +362,13 @@ static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp, // dispx + LMARGIN, dispy + TMARGIN, // outchars_b, tempbuf, sys_hostfontsize(font), // (glist_isselected(x->x_glist, ((t_gobj*)x->x_text)) ? "$pd_colors(selection)" : "$pd_colors(text)")); - gui_vmess("gui_text_new", "sssiiisi", + gui_vmess("gui_text_new", "sssiiiiisi", canvas_tag(canvas), x->x_tag, rtext_gettype(x)->s_name, glist_isselected(x->x_glist, ((t_gobj*)x->x_text)), LMARGIN, TMARGIN, + BMARGIN, + pixhigh, // dispx + LMARGIN, // dispy + TMARGIN, tempbuf, diff --git a/pd/src/g_scalar.c b/pd/src/g_scalar.c index cc4616c7c..a0b4cd11e 100644 --- a/pd/src/g_scalar.c +++ b/pd/src/g_scalar.c @@ -861,13 +861,14 @@ static void scalar_vis(t_gobj *z, t_glist *owner, int vis) // ); char tagbuf[MAXPDSTRING]; sprintf(tagbuf, "scalar%lx", (long unsigned int)x->sc_vec); - gui_vmess("gui_create_scalar", "ssiffffii", + gui_vmess("gui_create_scalar", "ssiffffiii", canvas_tag(glist_getcanvas(owner)), tagbuf, glist_isselected(owner, &x->sc_gobj), xscale, 0.0, 0.0, yscale, (int)glist_xtopixels(owner, basex), - (int)glist_ytopixels(owner, basey)); + (int)glist_ytopixels(owner, basey), + glist_istoplevel(owner)); //sys_vgui(".x%lx.c create group -tags {.dgroup%lx.%lx} " // "-parent {.scalar%lx}\n", // glist_getcanvas(owner), templatecanvas, x->sc_vec, x->sc_vec); diff --git a/pd/src/g_template.c b/pd/src/g_template.c index bf5bdf153..0ffd8ad67 100644 --- a/pd/src/g_template.c +++ b/pd/src/g_template.c @@ -5456,6 +5456,20 @@ static void plot_groupvis(t_scalar *x, t_glist *owner, t_word *data, } } +/* see if the elements we're plotting have any drawing commands */ +int plot_has_drawcommand(t_canvas *elemtemplatecanvas) +{ + t_gobj *y; + for (y = elemtemplatecanvas->gl_list; y; y = y->g_next) + { + if (pd_class(&y->g_pd) == canvas_class && ((t_glist *)y)->gl_svg) + return 1; + else if (class_isdrawcommand(y->g_pd)) + return 1; + } + return 0; +} + static void plot_vis(t_gobj *z, t_glist *glist, t_glist *parentglist, t_scalar *sc, t_word *data, t_template *template, t_float basex, t_float basey, int tovis) @@ -5515,6 +5529,7 @@ static void plot_vis(t_gobj *z, t_glist *glist, t_glist *parentglist, if (tovis) { int in_array = (sc->sc_vec == data) ? 0 : 1; + int draw_scalars = plot_has_drawcommand(elemtemplatecanvas); /* check if old 3-digit color field is being used... */ int dscolor = fielddesc_getfloat(&x->x_outlinecolor, template, data, 1); if (dscolor != 0) @@ -5525,12 +5540,26 @@ static void plot_vis(t_gobj *z, t_glist *glist, t_glist *parentglist, } if (symoutline == &s_) symoutline = gensym("#000000"); if (symfill == &s_) symfill = gensym("#000000"); + if (style == PLOTSTYLE_POINTS || style == PLOTSTYLE_BARS) { + t_float xscale = glist_xtopixels(glist, 1) - glist_xtopixels(glist, 0); + t_float yscale = glist_ytopixels(glist, 1) - glist_ytopixels(glist, 0); + t_float testy_y = 1 / yscale; +// post("testy_y is %g", testy_y); + symfill = (style == PLOTSTYLE_POINTS ? symoutline : symfill); t_float minyval = 1e20, maxyval = -1e20; int ndrawn = 0; - sys_vgui(".x%lx.c create path { \\\n", glist_getcanvas(glist)); + //sys_vgui(".x%lx.c create path { \\\n", glist_getcanvas(glist)); + + gui_start_vmess("gui_plot_vis", "sii", + canvas_tag(glist_getcanvas(glist)), + basex, + basey); + + gui_start_array(); + for (xsum = xloc, i = 0; i < nelem; i++) { t_float yval; @@ -5618,12 +5647,30 @@ static void plot_vis(t_gobj *z, t_glist *glist, t_glist *parentglist, /* For efficiency, we make a single path item for the trace or bargraph */ int mex1 = ixpix; - int mey1 = (int)fielddesc_cvttocoord(yfielddesc, minyval) - 1; + t_float mey1 = fielddesc_cvttocoord(yfielddesc, minyval) - 1; int mex2 = inextx; int mey2 = py2; - sys_vgui("M %d %d H %d V %d H %d z \\\n", - mex1, mey1, mex2, mey2, mex1); + //sys_vgui("M %d %d H %d V %d H %d z \\\n", + // mex1, mey1, mex2, mey2, mex1); + + gui_s("M"); + gui_i(mex1); + gui_f(yval); +// gui_f(mey1); + + gui_s("H"); + gui_i(mex2); + + gui_s("V"); + gui_f(yval + testy_y * linewidth); +// gui_i(mey2); + + gui_s("H"); + gui_i(mex1); + + gui_s("z"); + //} //part of experimental code above ndrawn++; minyval = 1e20; @@ -5636,13 +5683,41 @@ static void plot_vis(t_gobj *z, t_glist *glist, t_glist *parentglist, // already gives us the thickness matching that of vanilla pd // The code is left here in its redundant form for future reference // in case we encounter regressions. - sys_vgui("} -fill %s -stroke %s -strokewidth %d " - "-parent {.dgroup%lx.%lx} " - "-tags {.x%lx.x%lx.template%lx array}\n", - symfill->s_name, symoutline->s_name, - style == PLOTSTYLE_POINTS ? 0 : 0, - x->x_canvas, data, - glist_getcanvas(glist), glist, data); + //sys_vgui("} -fill %s -stroke %s -strokewidth %d " + // "-parent {.dgroup%lx.%lx} " + // "-tags {.x%lx.x%lx.template%lx array}\n", + // symfill->s_name, symoutline->s_name, + // style == PLOTSTYLE_POINTS ? 0 : 0, + // x->x_canvas, data, + // glist_getcanvas(glist), glist, data); + + gui_end_array(); + + gui_start_array(); + gui_s("fill"); + gui_s(symfill->s_name); + + gui_s("stroke"); + gui_s(symoutline->s_name); + + gui_s("stroke-width"); + gui_i(style == PLOTSTYLE_POINTS ? 0 : 0); + gui_end_array(); + + gui_start_array(); + char pbuf[MAXPDSTRING]; + char tbuf[MAXPDSTRING]; + sprintf(pbuf, "dgroup%lx.%lx", (long unsigned int)x->x_canvas, + (long unsigned int)data); + sprintf(tbuf, ".x%lx.x%lx.template%lx", + (long unsigned int)glist_getcanvas(glist), + (long unsigned int)glist, + (long unsigned int)data); + gui_s(pbuf); + gui_s(pbuf); + gui_end_array(); + + gui_end_vmess(); } else { @@ -5794,7 +5869,7 @@ static void plot_vis(t_gobj *z, t_glist *glist, t_glist *parentglist, /* We're done with the outline; now draw all the points. This code is inefficient since the template has to be searched for drawing instructions for every last point. */ - if (scalarvis != 0) + if (scalarvis != 0 && draw_scalars) { //t_float xoffset = in_array ? basex: 0; //t_float yoffset = in_array ? basey: 0; diff --git a/pd/src/g_text.c b/pd/src/g_text.c index ffcca0418..c7c1aeb73 100644 --- a/pd/src/g_text.c +++ b/pd/src/g_text.c @@ -1562,6 +1562,7 @@ static void text_select(t_gobj *z, t_glist *glist, int state) { if (glist_istoplevel(glist)) { +post("inside text selecting..."); sys_vgui(".x%lx.c itemconfigure %sR -stroke %s\n", glist_getcanvas(glist), rtext_gettag(y), (state? "$pd_colors(selection)" : outline)); @@ -1660,12 +1661,25 @@ static void text_delete(t_gobj *z, t_glist *glist) canvas_deletelinesfor(glist, x); } +static void text_get_typestring(int type, char *buf) +{ + if (type == T_OBJECT) + sprintf(buf, "%s", "obj"); + else if (type == T_MESSAGE) + sprintf(buf, "%s", "msg"); + else if (type == T_TEXT) + sprintf(buf, "%s", "comment"); + else + sprintf(buf, "%s", "atom"); +} + static void text_vis(t_gobj *z, t_glist *glist, int vis) { //fprintf(stderr,"text_vis %d\n", vis); t_text *x = (t_text *)z; int x1, y1, x2, y2; - + char type[8]; + text_get_typestring(x->te_type, type); #ifdef PDL2ORK //if we are in k12 mode and this is hub with level 1 (global) //don't draw it and make its width/height 0 @@ -1692,8 +1706,9 @@ static void text_vis(t_gobj *z, t_glist *glist, int vis) // make a group text_getrect(&x->te_g, glist, &x1, &y1, &x2, &y2); - gui_vmess("gui_text_create_gobj", "ssii", - canvas_tag(glist), rtext_gettag(y), x1, y1); + gui_vmess("gui_text_create_gobj", "sssiii", + canvas_tag(glist_getcanvas(glist)), + rtext_gettag(y), type, x1, y1, glist_istoplevel(glist)); if (x->te_type == T_ATOM) glist_retext(glist, x); @@ -1920,16 +1935,20 @@ void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime, else { //fprintf(stderr,"glist_drawiofor o redraw\n"); - sys_vgui(".x%lx.c coords %so%d %d %d %d %d\n", - glist_getcanvas(glist), tag, i, - onset, y2 - 2, - onset + IOWIDTH, y2); + //sys_vgui(".x%lx.c coords %so%d %d %d %d %d\n", + // glist_getcanvas(glist), tag, i, + // onset, y2 - 2, + // onset + IOWIDTH, y2); // jsarlo /*sys_vgui(".x%x.c raise %so%d\n", glist_getcanvas(glist), tag, i);*/ // end jsarlo + + gui_vmess("gui_canvas_redraw_io", "sssisii", + canvas_tag(glist_getcanvas(glist)), rtext_gettag(y), tag, + onset, "o", i, x1); } } n = obj_ninlets(ob); @@ -1960,16 +1979,20 @@ void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime, else { //fprintf(stderr,"glist_drawiofor i firsttime\n"); - sys_vgui(".x%lx.c coords %si%d %d %d %d %d\n", - glist_getcanvas(glist), tag, i, - onset, y1, - onset + IOWIDTH, y1 + EXTRAPIX); + //sys_vgui(".x%lx.c coords %si%d %d %d %d %d\n", + // glist_getcanvas(glist), tag, i, + // onset, y1, + // onset + IOWIDTH, y1 + EXTRAPIX); // jsarlo /*sys_vgui(".x%x.c raise %si%d\n", glist_getcanvas(glist), tag, i);*/ // end jsarlo + + gui_vmess("gui_canvas_redraw_io", "sssisii", + canvas_tag(glist_getcanvas(glist)), rtext_gettag(y), tag, + onset, "i", i, x1); } } } @@ -2110,8 +2133,9 @@ void text_drawborder(t_text *x, t_glist *glist, fill, tag, tag, box_tag, (selected ? "selected" : "")); */ - gui_vmess("gui_text_drawborder", "ssiiiii", - canvas_tag(glist_getcanvas(glist)), tag, broken, x1, y1, x2, y2); + gui_vmess("gui_text_drawborder", "sssiiiii", + canvas_tag(glist_getcanvas(glist)), tag, "none", + broken, x1, y1, x2, y2); //-dash %s -> pattern disabled for tkpath } diff --git a/pd/src/s_inter.c b/pd/src/s_inter.c index 11c9ba329..15658b24b 100644 --- a/pd/src/s_inter.c +++ b/pd/src/s_inter.c @@ -823,8 +823,11 @@ void gui_start_vmess(const char *sel, char *fmt, ...) static int gui_array_head; void gui_start_array(void) { + if (gui_array_head) + sys_gui("["); + else + sys_gui(",["); gui_array_head = 1; - sys_gui(",["); } void gui_f(t_float f) @@ -1267,9 +1270,8 @@ int sys_startgui(const char *guidir) /* SUPERHACK - let's just load node-webkit and see what happens */ sprintf(cmdbuf, - "/home/nu/Downloads/nwjs-v0.12.0-alpha2-linux-ia32/nw " -// "/home/user/Downloads/node-webkit-v0.11.6-linux-ia32/nw " -// "/home/user/Downloads/atom/atom/atom " + "/home/nu/Downloads/nwjs-v0.12.0-linux-ia32/nw " +// "/home/nu/Downloads/nwjs-v0.12.0-alpha2-linux-ia32/nw " "/home/nu/Downloads/test/ %d localhost %s\n", portno, (sys_k12_mode ? "pd-l2ork-k12" : "pd-l2ork")); -- GitLab