"README.md" did not exist on "18c109f46f97ffb2fa4a23e33d5848c32d722202"
Newer
Older
/* Copyright (c) 1997-2001 Miller Puckette and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
/* This file deals with the behavior of glists as either "text objects" or
"graphs" inside another glist. LATER move the inlet/outlet code of g_canvas.c
to this file... */
#include <stdlib.h>
#include "m_pd.h"
Ivica Bukvic
committed
#include "g_all_guis.h" /* for canvas handle freeing */
#include "s_stuff.h" /* for sys_hostfontsize */
#include <stdio.h>
#include <string.h>
Ivica Bukvic
committed
extern int array_joc;
int garray_joc(t_garray *x);
/* ---------------------- forward definitions ----------------- */
static void graph_vis(t_gobj *gr, t_glist *unused_glist, int vis);
Ivica Bukvic
committed
void graph_graphrect(t_gobj *z, t_glist *glist,
int *xp1, int *yp1, int *xp2, int *yp2);
static void graph_getrect(t_gobj *z, t_glist *glist,
int *xp1, int *yp1, int *xp2, int *yp2);
Ivica Ico Bukvic
committed
void graph_checkgop_rect(t_gobj *z, t_glist *glist,
int *xp1, int *yp1, int *xp2, int *yp2);
extern t_template *template_findbydrawcommand(t_gobj *g);
extern int do_not_redraw;
int gop_redraw = 0;
/* -------------------- maintaining the list -------------------- */
void canvas_drawredrect(t_canvas *x, int doit);
pokergaming
committed
int canvas_isgroup(t_canvas *x)
Ivica Bukvic
committed
{
/* t_binbuf *b = x->gl_obj.te_binbuf;
if (!b)
{
bug("canvas_isgroup");
Ivica Bukvic
committed
}
t_atom *argv = binbuf_getvec(x->gl_obj.te_binbuf);
if (argv[0].a_type == A_SYMBOL &&
argv[0].a_w.w_symbol == gensym("group"))
return 1;
else
return 0;
*/
if (x->gl_svg)
return 1;
else
return 0;
}
extern t_template *canvas_findtemplate(t_canvas *c);
extern t_canvas *canvas_templatecanvas_forgroup(t_canvas *c);
//fprintf(stderr,"glist_add %lx %d\n", (t_int)x, (x->gl_editor ? 1 : 0));
t_object *ob;
if (!x->gl_list) x->gl_list = y;
else
{
t_gobj *y2;
for (y2 = x->gl_list; y2->g_next; y2 = y2->g_next)
if (x->gl_editor && (ob = pd_checkobject(&y->g_pd)))
{
//let's now set up create undo
//glist_select(x, y);
//canvas_setundo(x, canvas_undo_create,
// canvas_undo_set_create(x, index), "create");
//glist_noselect(x);
}
if (x->gl_editor && x->gl_isgraph && !x->gl_goprect
&& pd_checkobject(&y->g_pd))
{
x->gl_goprect = 1;
canvas_drawredrect(x, 1);
}
if (glist_isvisible(x))
gobj_vis(y, x, 1);
if (class_isdrawcommand(y->g_pd))
{
t_template *tmpl = template_findbydrawcommand(y);
canvas_redrawallfortemplate(tmpl, 0);
}
Ivica Bukvic
committed
if (pd_class(&y->g_pd) == canvas_class &&
canvas_isgroup((t_canvas *)y))
{
t_canvas *templatecanvas =
canvas_templatecanvas_forgroup((t_canvas *)y);
t_template *tmpl = canvas_findtemplate(templatecanvas);
canvas_redrawallfortemplate(tmpl, 0);
Ivica Bukvic
committed
}
}
/* this is to protect against a hairy problem in which deleting
a sub-canvas might delete an inlet on a box, after the box had
been invisible-ized, so that we have to protect against redrawing it! */
int canvas_setdeleting(t_canvas *x, int flag)
{
int ret = x->gl_isdeleting;
x->gl_isdeleting = flag;
return (ret);
}
Ivica Bukvic
committed
/* check if canvas has an array and return 1, otherwise return 0
this is used to prevent creation of new objects in an array window */
int canvas_hasarray(t_canvas *x)
{
Ivica Bukvic
committed
t_gobj *g = x->gl_list;
int hasarray = 0;
Ivica Bukvic
committed
if (pd_class(&g->g_pd) == garray_class) hasarray = 1;
g = g->g_next;
}
return(hasarray);
}
/* JMZ: emit a closebang message */
void canvas_closebang(t_canvas *x);
/* delete an object from a glist and free it */
void glist_delete(t_glist *x, t_gobj *y)
{
Ivica Bukvic
committed
//fprintf(stderr,"glist_delete y=%lx x=%lx glist_getcanvas=%lx\n", y, x, glist_getcanvas(x));
if (x->gl_list)
{
//fprintf(stderr,"glist_delete YES\n");
t_gobj *g;
t_object *ob;
t_template *tmpl = NULL;
t_gotfn chkdsp = zgetfn(&y->g_pd, gensym("dsp"));
t_canvas *canvas = glist_getcanvas(x);
int drawcommand = class_isdrawcommand(y->g_pd);
int wasdeleting;
t_rtext *rt = NULL;
int late_rtext_free = 0;
if (pd_class(&y->g_pd) == canvas_class)
{
/* JMZ: send a closebang to the canvas */
canvas_closebang((t_canvas *)y);
pokergaming
committed
/* and this little hack so drawing commands can tell
if a [group] is deleting them (and thus suppress
their own redraws) */
((t_canvas *)y)->gl_unloading = 1;
/* if we are a group, let's call ourselves a drawcommand */
if (((t_canvas *)y)->gl_svg)
drawcommand = 1;
}
wasdeleting = canvas_setdeleting(canvas, 1);
if (x->gl_editor)
{
if (x->gl_editor->e_grab == y) x->gl_editor->e_grab = 0;
if (glist_isselected(x, y)) glist_deselect(x, y);
/* HACK -- we had phantom outlets not getting erased on the
screen because the canvas_setdeleting() mechanism is too
crude. LATER carefully set up rules for when the rtexts
should exist, so that they stay around until all the
steps of becoming invisible are done. In the meantime, just
zap the inlets and outlets here... */
if (pd_class(&y->g_pd) == canvas_class)
{
Ivica Bukvic
committed
if (glist_isvisible(x))
Ivica Bukvic
committed
t_glist *gl = (t_glist *)y;
if (gl->gl_isgraph)
{
char tag[80];
//sprintf(tag, "graph%lx", (t_int)gl);
//t_glist *yy = (t_glist *)y;
sprintf(tag, "%s",
rtext_gettag(glist_findrtext(x, &gl->gl_obj)));
glist_eraseiofor(x, &gl->gl_obj, tag);
text_eraseborder(&gl->gl_obj, x,
rtext_gettag(glist_findrtext(x, &gl->gl_obj)));
}
else
{
text_eraseborder(&gl->gl_obj, x,
rtext_gettag(glist_findrtext(x, &gl->gl_obj)));
}
}
}
}
/* if we're a drawing command, erase all scalars that
belong to our template, before deleting
it; we'll redraw them once it's deleted below. */
if (drawcommand)
Ivica Bukvic
committed
{
tmpl = template_findbydrawcommand(y);
pokergaming
committed
if (!(canvas_isgroup(canvas) && canvas->gl_unloading))
pokergaming
committed
{
canvas_redrawallfortemplate(tmpl, 2);
}
Ivica Bukvic
committed
}
if (glist_isvisible(canvas))
Ivica Bukvic
committed
{
//fprintf(stderr,"...deleting %lx %lx\n", x, glist_getcanvas(x));
Ivica Bukvic
committed
}
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
if (x->gl_editor && (ob = pd_checkobject(&y->g_pd)))
{
//rtext_new(x, ob);
rt = glist_findrtext(x, ob);
if (rt)
late_rtext_free = 1;
}
if (x->gl_list == y)
{
if (y->g_next)
x->gl_list = y->g_next;
else
x->gl_list = NULL;
}
else for (g = x->gl_list; g; g = g->g_next)
{
if (g->g_next == y)
{
if (y->g_next)
g->g_next = y->g_next;
else g->g_next = NULL;
break;
}
}
gobj_delete(y, x);
pd_free(&y->g_pd);
if (chkdsp) canvas_update_dsp();
if (drawcommand)
pokergaming
committed
{
if (tmpl != NULL && !(canvas_isgroup(canvas) && canvas->gl_unloading))
pokergaming
committed
{
pokergaming
committed
canvas_redrawallfortemplate(tmpl, 1);
pokergaming
committed
}
pokergaming
committed
}
canvas_setdeleting(canvas, wasdeleting);
x->gl_valid = ++glist_valid;
if (late_rtext_free)
{
//fprintf(stderr,"glist_delete late_rtext_free\n");
rtext_free(rt);
}
}
}
/* remove every object from a glist. Experimental. */
void glist_clear(t_glist *x)
{
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
int dspstate = 0, suspended = 0;
t_symbol *dspsym = gensym("dsp");
while (y = x->gl_list)
{
/* to avoid unnecessary DSP resorting, we suspend DSP
only if we hit a patchable object. */
if (!suspended && pd_checkobject(&y->g_pd) && zgetfn(&y->g_pd, dspsym))
{
dspstate = canvas_suspend_dsp();
suspended = 1;
}
/* here's the real deletion. */
glist_delete(x, y);
}
if (suspended)
canvas_resume_dsp(dspstate);
}
void glist_retext(t_glist *glist, t_text *y)
{
/* check that we have built rtexts yet. LATER need a better test. */
if (glist->gl_editor && glist->gl_editor->e_rtext)
{
t_rtext *rt = glist_findrtext(glist, y);
if (rt)
rtext_retext(rt);
}
}
void glist_grab(t_glist *x, t_gobj *y, t_glistmotionfn motionfn,
t_glistkeyfn keyfn, int xpos, int ypos)
{
//fprintf(stderr,"glist_grab\n");
t_glist *x2 = glist_getcanvas(x);
if (motionfn)
x2->gl_editor->e_onmotion = MA_PASSOUT;
else x2->gl_editor->e_onmotion = 0;
x2->gl_editor->e_grab = y;
x2->gl_editor->e_motionfn = motionfn;
x2->gl_editor->e_keyfn = keyfn;
x2->gl_editor->e_xwas = xpos;
x2->gl_editor->e_ywas = ypos;
}
t_canvas *glist_getcanvas(t_glist *x)
{
//fprintf(stderr,"glist_getcanvas\n");
while (x->gl_owner && !x->gl_havewindow && x->gl_isgraph &&
gobj_shouldvis(&x->gl_gobj, x->gl_owner))
{
Ivica Bukvic
committed
//fprintf(stderr,"x=%lx x->gl_owner=%d x->gl_havewindow=%d x->gl_isgraph=%d gobj_shouldvis=%d\n",
// x, (x->gl_owner ? 1:0), x->gl_havewindow, x->gl_isgraph,
// gobj_shouldvis(&x->gl_gobj, x->gl_owner));
//fprintf(stderr,"+\n");
}
static t_float gobj_getxforsort(t_gobj *g)
{
if (pd_class(&g->g_pd) == scalar_class)
{
scalar_getbasexy((t_scalar *)g, &x1, &y1);
return(x1);
}
else return (0);
}
static t_gobj *glist_merge(t_glist *x, t_gobj *g1, t_gobj *g2)
{
t_gobj *g = 0, *g9 = 0;
t_float f1 = 0, f2 = 0;
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
if (g1)
f1 = gobj_getxforsort(g1);
if (g2)
f2 = gobj_getxforsort(g2);
while (1)
{
if (g1)
{
if (g2)
{
if (f1 <= f2)
goto put1;
else goto put2;
}
else goto put1;
}
else if (g2)
goto put2;
else break;
put1:
if (g9)
g9->g_next = g1, g9 = g1;
else g9 = g = g1;
if (g1 = g1->g_next)
f1 = gobj_getxforsort(g1);
g9->g_next = 0;
continue;
put2:
if (g9)
g9->g_next = g2, g9 = g2;
else g9 = g = g2;
if (g2 = g2->g_next)
f2 = gobj_getxforsort(g2);
g9->g_next = 0;
continue;
}
return (g);
}
static t_gobj *glist_dosort(t_glist *x,
t_gobj *g, int nitems)
{
if (nitems < 2)
return (g);
else
{
int n1 = nitems/2, n2 = nitems - n1, i;
t_gobj *g2, *g3;
for (g2 = g, i = n1-1; i--; g2 = g2->g_next)
;
g3 = g2->g_next;
g2->g_next = 0;
g = glist_dosort(x, g, n1);
g3 = glist_dosort(x, g3, n2);
return (glist_merge(x, g, g3));
}
}
void glist_sort(t_glist *x)
{
int nitems = 0, foo = 0;
t_gobj *g;
for (g = x->gl_list; g; g = g->g_next)
{
t_float x1 = gobj_getxforsort(g);
if (x1 < lastx)
foo = 1;
lastx = x1;
nitems++;
}
if (foo)
x->gl_list = glist_dosort(x, x->gl_list, nitems);
}
/* --------------- inlets and outlets ----------- */
t_inlet *canvas_addinlet(t_canvas *x, t_pd *who, t_symbol *s)
{
//fprintf(stderr,"canvas_addinlet %d %lx %d\n", x->gl_loading, x->gl_owner, glist_isvisible(x->gl_owner));
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
t_inlet *ip = inlet_new(&x->gl_obj, who, s, 0);
if (!x->gl_loading && x->gl_owner && 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);
}
if (!x->gl_loading) canvas_resortinlets(x);
return (ip);
}
void canvas_rminlet(t_canvas *x, t_inlet *ip)
{
t_canvas *owner = x->gl_owner;
int redraw = (owner && glist_isvisible(owner) && (!owner->gl_isdeleting)
&& glist_istoplevel(owner));
if (owner) canvas_deletelinesforio(owner, &x->gl_obj, ip, 0);
if (redraw)
gobj_vis(&x->gl_gobj, x->gl_owner, 0);
inlet_free(ip);
if (redraw)
{
gobj_vis(&x->gl_gobj, x->gl_owner, 1);
canvas_fixlinesfor(x->gl_owner, &x->gl_obj);
}
}
extern t_inlet *vinlet_getit(t_pd *x);
extern void obj_moveinletfirst(t_object *x, t_inlet *i);
void canvas_resortinlets(t_canvas *x)
{
int ninlets = 0, i, j, xmax;
t_gobj *y, **vec, **vp, **maxp;
for (ninlets = 0, y = x->gl_list; y; y = y->g_next)
if (pd_class(&y->g_pd) == vinlet_class) ninlets++;
Ivica Bukvic
committed
if (ninlets < 2 && !(canvas_isgroup(x))) return;
vec = (t_gobj **)getbytes(ninlets * sizeof(*vec));
for (y = x->gl_list, vp = vec; y; y = y->g_next)
if (pd_class(&y->g_pd) == vinlet_class) *vp++ = y;
for (i = ninlets; i--;)
{
t_inlet *ip;
for (vp = vec, xmax = -0x7fffffff, maxp = 0, j = ninlets;
j--; vp++)
{
int x1, y1, x2, y2;
t_gobj *g = *vp;
if (!g) continue;
gobj_getrect(g, x, &x1, &y1, &x2, &y2);
if (x1 > xmax) xmax = x1, maxp = vp;
}
if (!maxp) break;
y = *maxp;
*maxp = 0;
ip = vinlet_getit(&y->g_pd);
obj_moveinletfirst(&x->gl_obj, ip);
}
freebytes(vec, ninlets * sizeof(*vec));
if (x->gl_owner &&
glist_isvisible(x->gl_owner) && glist_isvisible(x) &&
!x->gl_owner->gl_loading && !x->gl_loading)
{
//fprintf(stderr,"good place to fix redrawing of inlets "
// ".x%lx owner=.x%lx %d (parent)%d\n",
// x, x->gl_owner, x->gl_loading, x->gl_owner->gl_loading);
/*
t_object *ob = pd_checkobject(&y->g_pd);
t_rtext *rt = glist_findrtext(x->gl_owner, (t_text *)&ob->ob_g);
for (i = 0; i < ninlets; i++)
{
//sys_vgui(".x%x.c itemconfigure %si%d -fill %s -width 1\n",
// x, rtext_gettag(rt), i,
// (obj_issignalinlet(ob, i) ?
// "$signal_nlet" : "$pd_colors_control_nlet)"));
sprintf(xlet_tag, "%si%d", rtext_gettag(rt), i);
char xlet_tag[MAXPDSTRING];
gui_vmess("gui_configure_io", "xsiii",
x,
xlet_tag,
0,
obj_issignalinlet(ob, i),
1);
}
*/
//glist_redraw(x);
graph_vis(&x->gl_gobj, x->gl_owner, 0);
graph_vis(&x->gl_gobj, x->gl_owner, 1);
}
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
}
t_outlet *canvas_addoutlet(t_canvas *x, t_pd *who, t_symbol *s)
{
t_outlet *op = outlet_new(&x->gl_obj, s);
if (!x->gl_loading && x->gl_owner && 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);
}
if (!x->gl_loading) canvas_resortoutlets(x);
return (op);
}
void canvas_rmoutlet(t_canvas *x, t_outlet *op)
{
t_canvas *owner = x->gl_owner;
int redraw = (owner && glist_isvisible(owner) && (!owner->gl_isdeleting)
&& glist_istoplevel(owner));
if (owner) canvas_deletelinesforio(owner, &x->gl_obj, 0, op);
if (redraw)
gobj_vis(&x->gl_gobj, x->gl_owner, 0);
outlet_free(op);
if (redraw)
{
gobj_vis(&x->gl_gobj, x->gl_owner, 1);
canvas_fixlinesfor(x->gl_owner, &x->gl_obj);
}
}
extern t_outlet *voutlet_getit(t_pd *x);
extern void obj_moveoutletfirst(t_object *x, t_outlet *i);
void canvas_resortoutlets(t_canvas *x)
{
int noutlets = 0, i, j, xmax;
t_gobj *y, **vec, **vp, **maxp;
for (noutlets = 0, y = x->gl_list; y; y = y->g_next)
if (pd_class(&y->g_pd) == voutlet_class) noutlets++;
Jonathan Wilkes
committed
if (noutlets < 2 && !(canvas_isgroup(x))) return;
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
vec = (t_gobj **)getbytes(noutlets * sizeof(*vec));
for (y = x->gl_list, vp = vec; y; y = y->g_next)
if (pd_class(&y->g_pd) == voutlet_class) *vp++ = y;
for (i = noutlets; i--;)
{
t_outlet *ip;
for (vp = vec, xmax = -0x7fffffff, maxp = 0, j = noutlets;
j--; vp++)
{
int x1, y1, x2, y2;
t_gobj *g = *vp;
if (!g) continue;
gobj_getrect(g, x, &x1, &y1, &x2, &y2);
if (x1 > xmax) xmax = x1, maxp = vp;
}
if (!maxp) break;
y = *maxp;
*maxp = 0;
ip = voutlet_getit(&y->g_pd);
obj_moveoutletfirst(&x->gl_obj, ip);
}
freebytes(vec, noutlets * sizeof(*vec));
if (x->gl_owner &&
glist_isvisible(x->gl_owner) && glist_isvisible(x) &&
!x->gl_owner->gl_loading && !x->gl_loading)
{
//fprintf(stderr,"good place to fix redrawing of outlets\n");
//fprintf(stderr,"found it\n");
//glist_redraw(x);
graph_vis(&x->gl_gobj, x->gl_owner, 0);
graph_vis(&x->gl_gobj, x->gl_owner, 1);
}
/* ----------calculating coordinates and controlling appearance --------- */
static void graph_bounds(t_glist *x, t_floatarg x1, t_floatarg y1,
t_floatarg x2, t_floatarg y2)
{
Mathieu L Bouchard
committed
if (x1==x2 || y1==y2) {
error("graph: empty bounds rectangle");
x1 = y1 = 0;
x2 = y2 = 1;
}
Mathieu L Bouchard
committed
if (x->gl_x1!=x1 || x->gl_y1!=y1 || x->gl_x2!=x2 || x->gl_y2!=y2) {
//printf("%f %f %f %f %f %f %f %f\n",x->gl_x1,x1,x->gl_y1,y1,x->gl_x2,x2,x->gl_y2,y2);
Mathieu L Bouchard
committed
x->gl_x1 = x1;
x->gl_x2 = x2;
x->gl_y1 = y1;
x->gl_y2 = y2;
if (!do_not_redraw)
glist_redraw(x);
Mathieu L Bouchard
committed
}
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
}
static void graph_xticks(t_glist *x,
t_floatarg point, t_floatarg inc, t_floatarg f)
{
x->gl_xtick.k_point = point;
x->gl_xtick.k_inc = inc;
x->gl_xtick.k_lperb = f;
glist_redraw(x);
}
static void graph_yticks(t_glist *x,
t_floatarg point, t_floatarg inc, t_floatarg f)
{
x->gl_ytick.k_point = point;
x->gl_ytick.k_inc = inc;
x->gl_ytick.k_lperb = f;
glist_redraw(x);
}
static void graph_xlabel(t_glist *x, t_symbol *s, int argc, t_atom *argv)
{
int i;
if (argc < 1) error("graph_xlabel: no y value given");
else
{
x->gl_xlabely = atom_getfloat(argv);
argv++; argc--;
x->gl_xlabel = (t_symbol **)t_resizebytes(x->gl_xlabel,
x->gl_nxlabels * sizeof (t_symbol *), argc * sizeof (t_symbol *));
x->gl_nxlabels = argc;
for (i = 0; i < argc; i++) x->gl_xlabel[i] = atom_gensym(&argv[i]);
}
glist_redraw(x);
}
static void graph_ylabel(t_glist *x, t_symbol *s, int argc, t_atom *argv)
{
int i;
if (argc < 1) error("graph_ylabel: no x value given");
else
{
x->gl_ylabelx = atom_getfloat(argv);
argv++; argc--;
x->gl_ylabel = (t_symbol **)t_resizebytes(x->gl_ylabel,
x->gl_nylabels * sizeof (t_symbol *), argc * sizeof (t_symbol *));
x->gl_nylabels = argc;
for (i = 0; i < argc; i++) x->gl_ylabel[i] = atom_gensym(&argv[i]);
}
glist_redraw(x);
}
/****** routines to convert pixels to X or Y value and vice versa ******/
/* convert an x pixel value to an x coordinate value */
t_float glist_pixelstox(t_glist *x, t_float xpix)
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
{
/* if we appear as a text box on parent, our range in our
coordinates (x1, etc.) specifies the coordinate range
of a one-pixel square at top left of the window. */
if (!x->gl_isgraph)
return (x->gl_x1 + (x->gl_x2 - x->gl_x1) * xpix);
/* if we're a graph when shown on parent, but own our own
window right now, our range in our coordinates (x1, etc.) is spread
over the visible window size, given by screenx1, etc. */
else if (x->gl_isgraph && x->gl_havewindow)
return (x->gl_x1 + (x->gl_x2 - x->gl_x1) *
(xpix) / (x->gl_screenx2 - x->gl_screenx1));
/* otherwise, we appear in a graph within a parent glist,
so get our screen rectangle on parent and transform. */
else
{
int x1, y1, x2, y2;
if (!x->gl_owner)
bug("glist_pixelstox");
graph_graphrect(&x->gl_gobj, x->gl_owner, &x1, &y1, &x2, &y2);
return (x->gl_x1 + (x->gl_x2 - x->gl_x1) *
(xpix - x1) / (x2 - x1));
}
}
t_float glist_pixelstoy(t_glist *x, t_float ypix)
{
if (!x->gl_isgraph)
return (x->gl_y1 + (x->gl_y2 - x->gl_y1) * ypix);
else if (x->gl_isgraph && x->gl_havewindow)
return (x->gl_y1 + (x->gl_y2 - x->gl_y1) *
(ypix) / (x->gl_screeny2 - x->gl_screeny1));
else
{
int x1, y1, x2, y2;
if (!x->gl_owner)
graph_graphrect(&x->gl_gobj, x->gl_owner, &x1, &y1, &x2, &y2);
return (x->gl_y1 + (x->gl_y2 - x->gl_y1) *
(ypix - y1) / (y2 - y1));
}
}
/* convert an x coordinate value to an x pixel location in window */
t_float glist_xtopixels(t_glist *x, t_float xval)
{
if (!x->gl_isgraph)
return ((xval - x->gl_x1) / (x->gl_x2 - x->gl_x1));
else if (x->gl_isgraph && x->gl_havewindow)
return (x->gl_screenx2 - x->gl_screenx1) *
(xval - x->gl_x1) / (x->gl_x2 - x->gl_x1);
else
{
int x1, y1, x2, y2;
if (!x->gl_owner)
bug("glist_pixelstox");
graph_graphrect(&x->gl_gobj, x->gl_owner, &x1, &y1, &x2, &y2);
return (x1 + (x2 - x1) * (xval - x->gl_x1) / (x->gl_x2 - x->gl_x1));
}
}
t_float glist_ytopixels(t_glist *x, t_float yval)
{
if (!x->gl_isgraph)
return ((yval - x->gl_y1) / (x->gl_y2 - x->gl_y1));
else if (x->gl_isgraph && x->gl_havewindow)
return (x->gl_screeny2 - x->gl_screeny1) *
(yval - x->gl_y1) / (x->gl_y2 - x->gl_y1);
else
{
int x1, y1, x2, y2;
if (!x->gl_owner)
graph_graphrect(&x->gl_gobj, x->gl_owner, &x1, &y1, &x2, &y2);
return (y1 + (y2 - y1) * (yval - x->gl_y1) / (x->gl_y2 - x->gl_y1));
}
}
/* convert an X screen distance to an X coordinate increment.
This is terribly inefficient;
but probably not a big enough CPU hog to warrant optimizing. */
t_float glist_dpixtodx(t_glist *x, t_float dxpix)
{
return (dxpix * (glist_pixelstox(x, 1) - glist_pixelstox(x, 0)));
}
t_float glist_dpixtody(t_glist *x, t_float dypix)
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
{
return (dypix * (glist_pixelstoy(x, 1) - glist_pixelstoy(x, 0)));
}
/* get the window location in pixels of a "text" object. The
object's x and y positions are in pixels when the glist they're
in is toplevel. Otherwise, if it's a new-style graph-on-parent
(so gl_goprect is set) we use the offset into the framing subrectangle
as an offset into the parent rectangle. Finally, it might be an old,
proportional-style GOP. In this case we do a coordinate transformation. */
int text_xpix(t_text *x, t_glist *glist)
{
if (glist->gl_havewindow || !glist->gl_isgraph)
return (x->te_xpix);
else if (glist->gl_goprect)
return (glist_xtopixels(glist, glist->gl_x1) +
x->te_xpix - glist->gl_xmargin);
else return (glist_xtopixels(glist,
glist->gl_x1 + (glist->gl_x2 - glist->gl_x1) *
x->te_xpix / (glist->gl_screenx2 - glist->gl_screenx1)));
}
int text_ypix(t_text *x, t_glist *glist)
{
if (glist->gl_havewindow || !glist->gl_isgraph)
return (x->te_ypix);
else if (glist->gl_goprect)
return (glist_ytopixels(glist, glist->gl_y1) +
x->te_ypix - glist->gl_ymargin);
else return (glist_ytopixels(glist,
glist->gl_y1 + (glist->gl_y2 - glist->gl_y1) *
x->te_ypix / (glist->gl_screeny2 - glist->gl_screeny1)));
}
extern void canvas_updateconnection(t_canvas *x, int lx1, int ly1, int lx2, int ly2, t_int tag);
/* redraw all the items in a glist. We construe this to mean
redrawing in its own window and on parent, as needed in each case.
This is too conservative -- for instance, when you draw an "open"
rectangle on the parent, you shouldn't have to redraw the window! */
void glist_redraw(t_glist *x)
pokergaming
committed
{
if (glist_isvisible(x))
{
/* LATER fix the graph_vis() code to handle both cases */
Ivica Ico Bukvic
committed
if (glist_istoplevel(x) && x->gl_havewindow)
{
t_gobj *g;
t_linetraverser t;
t_outconnect *oc;
for (g = x->gl_list; g; g = g->g_next)
{
gobj_vis(g, x, 0);
gobj_vis(g, x, 1);
}
/* redraw all the lines */
linetraverser_start(&t, x);
while (oc = linetraverser_next(&t))
Ivica Bukvic
committed
canvas_updateconnection(glist_getcanvas(x), t.tr_lx1, t.tr_ly1, t.tr_lx2, t.tr_ly2, (t_int)oc);
//sys_vgui(".x%lx.c coords l%lx %d %d %d %d\n",
// glist_getcanvas(x), oc,
// t.tr_lx1, t.tr_ly1, t.tr_lx2, t.tr_ly2);
canvas_drawredrect(x, 0);
if (x->gl_goprect)
{
/* update gop rect size on toplevel in case font has
changed and we are showing text */
/*if (!x->gl_hidetext) {
int x1, y1, x2, y2;
graph_getrect((t_gobj *)x, x, &x1, &y1, &x2, &y2);
if (x2-x1 > x->gl_pixwidth) x->gl_pixwidth = x2-x1;
if (y2-y1 > x->gl_pixheight) x->gl_pixheight = y2-y1;
}*/
}
if (x->gl_owner && glist_isvisible(x->gl_owner))
{
graph_vis(&x->gl_gobj, x->gl_owner, 0);
graph_vis(&x->gl_gobj, x->gl_owner, 1);
}
}
/* --------------------------- widget behavior ------------------- */
int garray_getname(t_garray *x, t_symbol **namep);
/* Note that some code in here would also be useful for drawing
graph decorations in toplevels... */
static void graph_vis(t_gobj *gr, t_glist *parent_glist, int 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);
//fprintf(stderr, "graph_vis gr=.x%lx parent_glist=.x%lx "
// "glist_getcanvas(x->gl_owner)=.x%lx vis=%d\n",
// (t_int)gr, (t_int)parent_glist,
// (t_int)glist_getcanvas(x->gl_owner), vis);
char tag[50];
t_gobj *g;
int x1, y1, x2, y2;
/* ordinary subpatches: just act like a text object */
if (!x->gl_isgraph)
{
text_widgetbehavior.w_visfn(gr, parent_glist, vis);
return;
}
// weird exception
//int exception = 0;
//t_canvas* tgt = glist_getcanvas(x->gl_owner);
//if (parent_glist->gl_owner && !parent_glist->gl_mapped &&
// parent_glist->gl_owner->gl_mapped) {
// tgt = parent_glist;
// exception = 1;
//}
//fprintf(stderr,"tgt=.x%lx %d\n", (t_int)tgt, exception);
sprintf(tag, "%s", rtext_gettag(glist_findrtext(parent_glist, &x->gl_obj)));
//post("before rtext_draw: %s", tag);
if (vis & gobj_shouldvis(gr, parent_glist))
{
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", "xssiii",
glist_getcanvas(x->gl_owner),
Jonathan Wilkes
committed
tag, "graph", xpix, ypix, 1);
if (canvas_showtext(x))
rtext_draw(glist_findrtext(parent_glist, &x->gl_obj));
}
// sprintf(tag, "%s", rtext_gettag(glist_findrtext(parent_glist, &x->gl_obj)));
//post("after rtext_draw: %s", tag);
// need the rect to create the gobj, so this should perhaps be above the
// conditional
graph_getrect(gr, parent_glist, &x1, &y1, &x2, &y2);
//fprintf(stderr,"%d %d %d %d\n", x1, y1, x2, y2);
if (!vis)
rtext_erase(glist_findrtext(parent_glist, &x->gl_obj));
//sprintf(tag, "graph%lx", (t_int)x);
//fprintf(stderr, "gettag=%s, tag=graph%lx\n",
// rtext_gettag(glist_findrtext(parent_glist, &x->gl_obj)),(t_int)x);
/* if we look like a graph but have been moved to a toplevel,
just show the bounding rectangle */
if (vis && gobj_shouldvis(gr, parent_glist))
{
//sys_vgui(".x%lx.c create ppolygon %d %d %d %d %d %d %d %d %d %d "
// "-tags {%sfill graph} -fill $pd_colors(graph_border) "
// "-stroke $pd_colors(graph_border)\n",
// glist_getcanvas(x->gl_owner),
////parent_glist,
// x1, y1, x1, y2, x2, y2, x2, y1, x1, y1, tag);
gui_vmess("gui_text_drawborder", "xssiiiii",
glist_getcanvas(x->gl_owner),
Jonathan Wilkes
committed
"none",
gui_vmess("gui_graph_fill_border", "xsi",
glist_getcanvas(x->gl_owner),
}
else if (gobj_shouldvis(gr, parent_glist))
{
//sys_vgui(".x%lx.c delete %sfill\n",
// glist_getcanvas(x->gl_owner), tag);
////parent_glist, tag);
gui_vmess("gui_gobj_erase", "xs",
glist_getcanvas(x->gl_owner),
return;
}
/* otherwise draw (or erase) us as a graph inside another glist. */
if (vis)
{
int i;
t_gobj *g;
t_symbol *arrayname;
/* draw a rectangle around the graph */
/*sys_vgui(".x%lx.c create polyline %d %d %d %d %d %d %d %d %d %d "
"-stroke $pd_colors(graph_border) -tags {%sR %s graph}\n",
Ivica Bukvic
committed
x1, y1, x1, y2, x2, y2, x2, y1, x1, y1, tag, tag);*/
//sys_vgui(".x%lx.c create prect %d %d %d %d "
// "-stroke $pd_colors(graph_border) -tags {%sR graph}\n",
// //REMOVED: -fill $pd_colors(graph)
// glist_getcanvas(x->gl_owner),
// x1, y1, x2, y2, tag); // -fill $pd_colors(graph)
char tagbuf[MAXPDSTRING];
sprintf(tagbuf, "%sR", tag);
gui_vmess("gui_text_drawborder", "xssiiiii",
glist_getcanvas(x->gl_owner),
Jonathan Wilkes
committed
"none",
/* write garrays' names along the top */
for (i = (y1 < y2 ? y1 : y2)-1, g = x->gl_list; g; g = g->g_next)
{
//fprintf(stderr,".\n");
//if (g->g_pd == garray_class)
// fprintf(stderr,"garray_getname=%d\n",garray_getname((t_garray *)g, &arrayname));
if (g->g_pd == garray_class &&
!garray_getname((t_garray *)g, &arrayname))
//sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor nw "
// "-font {{%s} -%d %s} -tags {%s label graph} -fill %s\n",
// (long)glist_getcanvas(x), x1+2, i, arrayname->s_name,
// sys_font, sys_hostfontsize(glist_getfont(x)), sys_fontweight,
// tag,
// (glist_isselected(x, gr) ?
// "$pd_colors(selection)" : "$pd_colors(graph_border)"));
gui_vmess("gui_graph_label", "xsissisi",
glist_getcanvas(x),