dialog_iemgui.html 21.7 KB
Newer Older
1
2
3
<!DOCTYPE html>
<html>
  <head>
Jonathan Wilkes's avatar
Jonathan Wilkes committed
4
5
    <link id="page_style" rel="stylesheet"
          type="text/css" href="css/default.css">
6
  </head>
7
  <body class="dialog_body">
8
9
10
11
12
13
14
15
16
17
18
19
20
    <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">
21
22
              <input type="text" name="size"
                     onchange="update_attr(this);">
23
24
            </td>
          </tr>
25
          <tr class="selection_size prop hidden">
26
27
28
29
30
31
            <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">
32
              <input type="text" name="selection_size"
33
                     onchange="update_attr(this);">
34
35
36
37
38
39
40
41
42
            </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">
43
44
              <input type="number" name="number"
                     onchange="update_attr(this);">
45
46
            </td>
          </tr>
47
          <tr class="nonzero_value prop hidden">
48
49
50
51
52
53
            <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">
54
              <input type="text" name="nonzero_value"
55
                     onchange="update_attr(this);">
56
57
58
59
            </td>
          </tr>
          <tr class="width prop hidden">
            <td>
60
61
              <label data-i18n="[title]iem.prop.width_tt" class="mknob_size_tt"> 
                <span data-i18n="iem.prop.width" class="mknob_size"></span>
62
63
              </label>
            </td>
64
            <td data-i18n="[title]iem.prop.width_tt" class="mknob_size_tt">
65
66
              <input type="text" name="width"
                     onchange="update_attr(this);">
67
68
            </td>
            <td>
69
70
              <label data-i18n="[title]iem.prop.height_tt" class="mknob_steps_tt">
                <span data-i18n="iem.prop.height" class="mknob_steps"></span>
71
72
              </label>
            </td>
73
            <td data-i18n="[title]iem.prop.height_tt" class="mknob_steps_tt">
74
75
              <input type="text" name="height"
                     onchange="update_attr(this);">
76
77
            </td>
          </tr>
78
          <tr class="visible_width prop hidden">
79
80
81
82
83
84
            <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">
85
              <input type="text" name="visible_width"
86
                     onchange="update_attr(this);">
87
88
89
90
91
92
93
            </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">
94
              <input type="text" name="visible_height"
95
                     onchange="update_attr(this);">
96
97
            </td>
          </tr>
98
          <tr class="minimum_range prop pair hidden">
99
100
101
102
103
104
            <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">
105
              <input type="text" name="minimum_range"
106
                     onchange="update_attr(this);">
107
108
109
110
111
112
            </td>
            <td>
              <label data-i18n="[title]iem.prop.maximum_tt">
                <span data-i18n="iem.prop.maximum"></span>
              </label>
            </td>
113
114
            <td data-i18n="[title]iem.prop.max_mum_tt">
              <input type="text" name="maximum_range"
115
                     onchange="update_attr(this);">
116
117
            </td>
          </tr>
118
          <tr class="flash_interrupt prop hidden">
119
120
121
122
123
124
            <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">
125
              <input type="text" name="flash_interrupt"
126
                     onchange="update_attr(this);">
127
128
129
130
131
132
133
            </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">
134
              <input type="text" name="flash_hold"
135
                     onchange="update_attr(this);">
136
137
            </td>
          </tr>
138
          <tr class="log_height prop hidden">
139
140
141
142
143
144
145
            <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>
146
              <input type="text" name="log_height"
147
                     onchange="update_attr(this);">
148
149
150
151
152
153
            </td>
          </tr>
        </table>

        <div class="init prop hidden">
          <label data-i18n="[title]iem.prop.init_tt">
154
155
            <input type="checkbox" name="init" value="on"
                   onchange="update_attr(this);">
156
157
158
159
160
            <span data-i18n="iem.prop.init"></span>
          </label>
          <br>
        </div>

161
        <div class="vu_scale prop hidden">
162
163
          <label data-i18n="[title]iem.prop.vu_scale_tt">
            <span data-i18n="iem.prop.vu_scale"></span>
164
            <input type="checkbox" name="vu_scale" value="on"
165
                   onchange="update_attr(this);">
166
167
168
169
          </label>
          <br>
        </div>

170
        <div class="log_scaling prop hidden">
171
          <label data-i18n="[title]iem.prop.log_scale_tt">
172
            <input type="checkbox" name="log_scaling" value="on"
173
                   onchange="update_attr(this);">
174
175
176
177
178
            <span data-i18n="iem.prop.log_scale"></span>
          </label>
          <br>
        </div>

179
        <div class="steady_on_click prop hidden">
180
          <label data-i18n="[title]iem.prop.steady_tt">
181
            <input type="checkbox" name="steady_on_click" value="on"
182
                   onchange="update_attr(this);">
183
184
185
186
187
188
189
190
191
192
            <span data-i18n="iem.prop.steady"></span>
          </label>
          <br>
        </div>
      </fieldset> 

      <fieldset> 
        <legend data-i18n="iem.prop.heading.messages"></legend> 

        <table>
193
          <tr class="send_symbol prop hidden">
194
195
196
197
198
199
            <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">
200
              <input type="text" name="send_symbol"
201
                     onchange="update_attr(this, true);">
202
203
            </td>
            <td>
204
          <tr class="receive_symbol prop hidden">
205
206
207
208
209
210
            <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">
211
              <input type="text" name="receive_symbol"
212
                     onchange="update_attr(this, true);">
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
            </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">
230
              <input type="text" name="label"
231
                     onchange="update_attr(this, true);">
232
233
234
235
236
237
238
            </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">
239
              <input type="text" name="x_offset"
240
                     onchange="update_attr(this);">
241
242
243
244
245
246
247
            </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">
248
              <input type="text" name="y_offset"
249
                     onchange="update_attr(this);">
250
251
            </td>
          </tr>
252
          <tr class="font_style prop hidden">
253
254
255
256
257
            <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">
258
              <select name="font_style"
259
                      onchange="update_attr(this);">
260
261
262
                <option>DejaVu Sans Mono</option>
                <option>Helvetica</option>
                <option>Times</option>
263
264
265
266
267
              </select>
            </td>
            <td colspan="4">
              <label data-i18n="[title]iem.prop.fontsize_tt">
                <span data-i18n="iem.prop.fontsize"></span>
268
                <input type="text" name="font_size"
269
                       onchange="update_attr(this);">
270
271
272
273
274
275
276
277
278
              <label>
            </td>
          </tr>
        </table>
      </fieldset> 

      <fieldset> 
      <legend data-i18n="iem.prop.heading.colors"></legend> 

279
      <div class="background_color prop hidden">
280
        <label data-i18n="[title]iem.prop.bgcolor_tt">
281
          <input type="color" name="background_color"
282
                 onchange="update_attr(this);">
283
284
285
286
287
          <span data-i18n="iem.prop.bgcolor"></span>
        </label>
        <br>
      </div>

288
      <div class="foreground_color prop hidden">
289
        <label data-i18n="[title]iem.prop.fgcolor_tt">
290
          <input type="color" name="foreground_color"
291
                 onchange="update_attr(this);">
292
293
294
295
296
          <span data-i18n="iem.prop.fgcolor"></span>
        </label>
        <br>
      </div>

297
      <div class="label_color prop hidden">
298
        <label data-i18n="[title]iem.prop.label_color_tt">
299
          <input type="color" name="label_color"
300
                 onchange="update_attr(this);">
301
302
303
304
305
306
307
          <span data-i18n="iem.prop.label_color"></span>
        </label>
        <br>
      </div>
    </fieldset> 

    <div class="prop hidden">
308
309
310
      <input type="hidden" name="minimum_size">
      <input type="hidden" name="range_schedule">
      <input type="hidden" name="hide_frame">
311
312
313
314
315
316
317
318
319
    </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>
320
      <button type="button" onClick="cancel(true)" data-i18n="[title]iem.prop.cancel_tt">
321
322
323
324
325
326
327
328
        <span data-i18n="iem.prop.cancel"></span>
      </button>
    </div>

  </form> 
  </div>      

  <script>
329
"use strict";
330
var gui = require("nw.gui");
331
var pdgui = require("./pdgui.js");
332

333
334
// For translations
var l = pdgui.get_local_string;
335

Jonathan Wilkes's avatar
Jonathan Wilkes committed
336
// gui preset
337
pdgui.skin.apply(window);
Jonathan Wilkes's avatar
Jonathan Wilkes committed
338

339
340
341
var pd_object_callback,
    old_attrs = {}, // original state. Used if we cancel the dialog
    new_attrs = {}; // changed state. Used if we apply or click "Ok"
342

343
344
function substitute_space(arg) {
    var fake_space = String.fromCharCode(11);
345
    return arg.split(" ").join(fake_space);
346
}
347

348
function strip_problem_chars(arg) {
349
    var problem_chars = [";", ",", "\\"],
350
351
352
        ret = arg,
        i;
    for(i = 0; i < problem_chars.length; i++) {
353
        ret = ret.split(problem_chars[i]).join("");
354
    }
355
356
    return ret;
}
357

358
function update_attr(elem, symbol_field) {
359
360
361
362
363
364
    if (!new_attrs.hasOwnProperty(elem.name)) {
        pdgui.post("warning: new_attrs[" + elem.name + "] doesn't exist");
    }
    if (elem.type === "checkbox") {
        new_attrs[elem.name] = elem.checked ? 1 : 0;
    } else if (elem.type === "select-one") {
365
366
367
        new_attrs[elem.name] = elem.selectedIndex;
    } else if (elem.type === "color") {
        new_attrs[elem.name] = parseInt(elem.value.slice(1), 16)
368
    } else {
369
370
        new_attrs[elem.name] = (elem.value === "" && !symbol_field) ?
            "0" : elem.value;
371
372
373
    }
}

374
//Clean up strings to send as symbol arguments to Pd
375
function iemgui_escape(s) {
376
    s = !s ? "empty" : s;
377
378
379
380
381
382
    var arr = s.split("");
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] === "$" && i+1 < arr.length &&
            arr[i+1] >= "0" && arr[i+1] <= "9") {
            arr[i] = "#";
        }
383
    }
384
    s = arr.join("");
385
386
    s = substitute_space(s);
    s = strip_problem_chars(s);
387
    return s;
388
389
}

390
391
392
393
394
395
396
397
398
399
400
401
function iemgui_unescape(s) {
    var arr = s.split("");
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] === "#" && i+1 < arr.length &&
            arr[i+1] >= "0" && arr[i+1] <= "9") {
            arr[i] = "$";
        }
    }
    s = arr.join("");
    return s;
}

402
function send_params(attrs, create_undo_point) {
403
404
405
406
407
408
409
410
    /* 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
    */
411

412
413
    var send_symbol = attrs.send_symbol,
        receive_symbol = attrs.receive_symbol,
414
        label =  attrs["label"];
415
416
417
    send_symbol = iemgui_escape(send_symbol);
    receive_symbol = iemgui_escape(receive_symbol);
    label = iemgui_escape(label);
418

419
420
    var label_x_offset =  attrs.x_offset;
    var label_y_offset =  attrs.y_offset;
421

422
    // make sure the offset boxes have a value
423
424
425
426
427
428
    if (!label_x_offset) {
        label_x_offset = 0;
    }
    if (!label_y_offset) {
        label_y_offset = 0;
    }
429

430
    var height, width;
431
    var size = attrs["size"];
Jonathan Wilkes's avatar
Jonathan Wilkes committed
432
    if (size === undefined) {
433
        size = attrs.selection_size;
434
    }
435

Jonathan Wilkes's avatar
Jonathan Wilkes committed
436
    if (size !== undefined) {
437
438
439
        width = size;
        height = size;
    } else {
440
441
        width = attrs.width;
        height = attrs.height;
442
    }
443

444
445
    var slot3 = attrs.minimum_range;
    var slot4 = attrs.maximum_range;
446

Jonathan Wilkes's avatar
Jonathan Wilkes committed
447
    if (slot3 === undefined) {
448
449
        slot3 = attrs.flash_interrupt;
        slot4 = attrs.flash_hold;
450
    }
451

Jonathan Wilkes's avatar
Jonathan Wilkes committed
452
    if (slot3 === undefined) {
453
454
        slot3 = attrs.visible_width;
        slot4 = attrs.visible_height;
455
    }
456

Jonathan Wilkes's avatar
Jonathan Wilkes committed
457
    if (slot3 === undefined) { // toggle
458
        slot3 = attrs.nonzero_value;
Jonathan Wilkes's avatar
Jonathan Wilkes committed
459
        if (slot3 === undefined) {
460
            slot3 = 0;
461
        }
462
463
        slot4 = 0;
    }
464

465
466
    var slot5 = attrs.log_scaling ? +attrs.log_scaling : 0;
    // Hack to accomodate the vu_scale property, which exists in the same
467
    // slot as this one
468
    var log_scaling_div = document.querySelector(".log_scaling");
469
    var no_log_display = log_scaling_div.classList.contains("hidden");
470

471
    if (no_log_display) {
472
        slot5 = attrs.vu_scale ? +attrs.vu_scale : 0;
473
    }
474

475
476
    var init = +attrs["init"];
    if (!init) { init = 0; }
477

478
    var slot7 = attrs.log_height;
Jonathan Wilkes's avatar
Jonathan Wilkes committed
479
    if (slot7 === undefined) {
480
        slot7 = attrs["number"];
481
    }
Jonathan Wilkes's avatar
Jonathan Wilkes committed
482
    if (slot7 === undefined) {
483
        slot7 = 0;
484
485
    }

486
    var font_style = attrs.font_style;
487
    //if (font_style !== null) { font_style = 0; }
488

489
    var font_size = attrs.font_size;
Jonathan Wilkes's avatar
Jonathan Wilkes committed
490
    if (font_size === undefined) { font_size = 0; }
491

492
    // [vu] doesn't have a foreground color
493
494
495
496
    var foreground_color = attrs.foreground_color ?
        attrs.foreground_color : 0;
    var background_color = attrs.background_color;
    var label_color = attrs.label_color;
497

498
    var slot18 = attrs.steady_on_click ? +attrs.steady_on_click : 0;
499

500
    pdgui.pdsend(pd_object_callback, "dialog",
501
        width, height,
502
503
504
        slot3, // bng: flash_interrupt
               // slider: min_range
               // toggle: nonzero_value
505
               // my_canvas: visible_width
506
507
        slot4, // bng: flash_hold
               // slider: max_range
508
509
510
               // my_canvas: visible_height
        slot5, // slider: lin/log thingy
               // nbx: lin/log
511
               // vu: vu_scale
512
        init,
513
        slot7, // log_height or vradio/hradio number
514
515
516
517
518
519
        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
520
521
522
        0, // not sure what this is doing here
        create_undo_point ? 1 : 0 // whether we set an undo point
    );
523
}
524

525
526
function cancel(revert_changes) {
    var dirty = false, attr;
527
    //window.close(true);
528
529
530
531
532
533
534
535
536
537
    if (revert_changes) {
        for (attr in old_attrs) {
            if (old_attrs[attr] !== new_attrs[attr]) {
                dirty = true;
            }
        }
        if (dirty) {
            send_params(old_attrs, false);
        }
    }
538
    pdgui.pdsend(pd_object_callback, "cancel");
539
540
}

541
542
543
544
545
546
547
548
function apply() {
    send_params(new_attrs, false);
}

function ok() {
    // Steal focus from any active input to make sure it triggers an
    // onchange event
    document.querySelector("button").focus();
549
550
    // send the old attrs first so we can set an undo point on them
    send_params(old_attrs, false);
551
552
553
554
    send_params(new_attrs, true);
    cancel(false);
}

555
556
557
558
559
560
561
562
function change_width_and_height_labels() {
    [".mknob_steps", ".mknob_size"].forEach(function(sel) {
        document.body.querySelectorAll(sel).forEach(function(e) {
            e.setAttribute("data-i18n", "iem.prop" + sel);
        });
        document.body.querySelectorAll(sel + "_tt").forEach(function(e) {
            e.setAttribute("data-i18n", "[title]iem.prop" + sel + "_tt");
        });
563
564
565
    });
}

566
567
568
// 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
569
function register_window_id(gfxstub, attr_object) {
570
    var attr;
571
    pd_object_callback = gfxstub;
572
573
574
575
576
577
    old_attrs = attr_object;
    for (attr in old_attrs) {
        if (old_attrs.hasOwnProperty(attr)) {
            new_attrs[attr] = old_attrs[attr];
        }
    }
578
    console.log("attr object is " + attr_object.toString());
579
    add_events(gfxstub);
580
581
582
583

    // Special case for [moonlib/mknob] which leverages the iemgui dialog--
    // change the label for "height" to "steps"
    if (attr_object.type === "mknob") {
584
        change_width_and_height_labels();
585
586
587
        pdgui.post("Special case: mknob");
    }

588
    translate_form();
589
    populate_form(attr_object);
590
591
592
593
    // 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.
594
595
    document.getElementsByClassName("container")[0]
        .style.setProperty("display", "inline");
596
    pdgui.resize_window(pd_object_callback);
597
}
598
599

function tr_text(id) {
600
601
    var elem = document.getElementById("iem.prop." + id);
    elem.textContent = l("iem.prop." + id);
602
603
604
605
606
}

// Stop-gap translator
function translate_form() {
    var i
607
    var elements = document.querySelectorAll("[data-i18n]");
608
609
    for (i = 0; i < elements.length; i++) {
        var data = elements[i].dataset.i18n;
610
        if (data.slice(0,7) === "[title]") {
611
612
613
614
615
616
617
            elements[i].title = l(data.slice(7));
        } else {
            elements[i].textContent = l(data);
        }
    }
}

618
619
620
function populate_form(attr_object) {
    var attr;
    for(attr in attr_object) {
621
        // Unhide the span with the class with the same name as the id
622
        var prop_group = document.getElementsByClassName(attr)[0];
623
        if (prop_group !== undefined) {
624
            console.log("the thing here is " + attr);
625
            prop_group.classList.remove("hidden");
626
627
628
629
        }
        // 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
630
        if (attr_object[attr] !== "empty") {
631
            var elem = document.getElementsByName(attr);
632
            if (elem.length > 0) {
633
                if (attr.slice(-5) === "color") {
634
                    var hex_string = Number(attr_object[attr]).toString(16);
635
                    var color_string = "#" +
636
                        (hex_string === "0" ? "000000" : hex_string);
Jonathan Wilkes's avatar
Jonathan Wilkes committed
637
                    //pdgui.post("color is " + color_string);
638
                    elem[0].value = color_string;
639
                } else if (elem[0].type === "checkbox") {
640
641
                    // The attr here is a string, so we need to
                    // force it to number, hence the "+" below
642
                    elem[0].checked = +attr_object[attr];
643
                } else if (elem[0].type === "select-one") {
644
                    elem[0].selectedIndex = +attr_object[attr];
645
                } else if (attr === "send_symbol" ||
646
647
                           attr === "receive_symbol" ||
                           attr === "label") {
648
                    elem[0].value = iemgui_unescape(attr_object[attr]);
649
                } else {
650
                    elem[0].value = attr_object[attr];
651
652
653
654
655
656
657
658
                }
            }
        }
    }
}

function add_events(name) {
    // closing the Window
659
    gui.Window.get().on("close", function() {
660
        // this needs to do whatever the "cancel" button does
661
        cancel(false);
662
    });
663
    pdgui.dialog_bindings(name);
664
665
666
667
668
}

  </script>
  </body>
</html>