Newer
Older
sprintf(tagbuf, "scalar%lxgobj", (long unsigned int)x->sc_vec);
sprintf(groupbuf, "dgroup%lx.%lx", (long unsigned int)templatecanvas,
(long unsigned int)x->sc_vec);
gui_vmess("gui_create_scalar_group", "xss",
glist_getcanvas(owner), groupbuf, tagbuf);
Ivica Bukvic
committed
}
Ivica Bukvic
committed
/* warning: don't need--- have recursive func. */
for (y = templatecanvas->gl_list; y; y = y->g_next)
{
t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd);
Ivica Bukvic
committed
if (!wb)
{
/* check subpatches for more drawing commands.
(Optimized to only search [group] subpatches) */
Ivica Bukvic
committed
if (pd_class(&y->g_pd) == canvas_class &&
((t_glist *)y)->gl_svg)
{
Ivica Bukvic
committed
scalar_groupvis(x, owner, template,
(t_glist *)y, templatecanvas, vis);
Ivica Bukvic
committed
continue;
}
(*wb->w_parentvisfn)(y, owner, 0, x, x->sc_vec, template,
basex, basey, vis);
Ivica Bukvic
committed
if (!vis)
//sys_vgui(".x%lx.c delete .scalar%lx\n", glist_getcanvas(owner),
// x->sc_vec);
char tagbuf[MAXPDSTRING];
sprintf(tagbuf, "scalar%lx", (long unsigned int)x->sc_vec);
gui_vmess("gui_scalar_erase", "xs",
glist_getcanvas(owner), tagbuf);
Ivica Bukvic
committed
sys_unqueuegui(x);
if (glist_isselected(owner, &x->sc_gobj))
{
// we removed this because it caused infinite recursion
// in the scalar-help.pd example
//scalar_select(z, owner, 1);
post("here we are in scalar vis, selected...");
scalar_drawselectrect(x, owner, 0);
scalar_drawselectrect(x, owner, 1);
}
}
static void scalar_doredraw(t_gobj *client, t_glist *glist)
{
scalar_vis(client, glist, 0);
scalar_vis(client, glist, 1);
if (glist_isselected(glist_getcanvas(glist), (t_gobj *)glist))
{
//fprintf(stderr,"yes\n");
sys_vgui("pdtk_select_all_gop_widgets .x%lx %lx %d\n",
glist_getcanvas(glist), glist, 1);
}
Mathieu L Bouchard
committed
canvas_getscroll(glist_getcanvas(glist));
}
void scalar_redraw(t_scalar *x, t_glist *glist)
{
if (glist_isvisible(glist))
scalar_doredraw((t_gobj *)x, glist);
//sys_queuegui(x, glist, scalar_doredraw);
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
/* here we call the parentclickfns for drawing commands.
We recurse all the way to the end of the glist (and, for the
groups, as deep as they go) and then call the functions from the bottom up.
This way the clicks can "bubble" up from the bottom. This has the effect
that the shape visually closest to the front gets called first.
This is called "event bubbling" in the HTML5 DOM. You can also call
events in top down order in HTML5/SVG as well (called "capturing" or
"trickling"). But because some old version of Internet Explorer only did
bubbling, that is the most widely used model today, and the only one
I decided to implement here.
However, [group] doesn't yet have an outlet to report events. Only a
single [draw] should report a click here atm.
*/
int scalar_groupclick(struct _glist *groupcanvas,
t_word *data, t_template *template, t_scalar *sc,
t_array *ap, struct _glist *owner,
t_float xloc, t_float yloc, int xpix, int ypix,
int shift, int alt, int dbl, int doit, t_float basex, t_float basey,
t_gobj *obj)
{
int hit = 0;
t_gobj *nextobj = obj->g_next;
/* let's skip over any objects that aren't drawing instructions
or groups */
while (nextobj &&
!class_isdrawcommand(pd_class((t_pd *)nextobj)) &&
!(pd_class(&nextobj->g_pd) == canvas_class &&
((t_glist *)nextobj)->gl_svg))
nextobj = nextobj->g_next;
/* If there's another link in the list go ahead and recurse with it */
if (nextobj)
{
hit = (scalar_groupclick(groupcanvas, data, template, sc, ap,
owner, xloc, yloc, xpix, ypix,
shift, alt, dbl, doit, basex, basey, nextobj));
if (hit) return hit;
}
/* recurse inside a [group] object to look for more objects */
if (pd_class(&obj->g_pd) == canvas_class && ((t_glist *)obj)->gl_svg)
{
t_canvas *cnv = (t_canvas *)obj;
obj = cnv->gl_list;
if (obj)
return (scalar_groupclick(cnv, data, template, sc, ap,
owner, xloc, yloc, xpix, ypix,
shift, alt, dbl, doit, basex, basey, obj));
}
else /* finally, try to call the parent click function ... */
{
t_parentwidgetbehavior *wb = pd_getparentwidget(&obj->g_pd);
if (!wb) return hit;
if ((*wb->w_parentclickfn)(obj, owner,
data, template, sc, ap, basex + xloc, basey + yloc,
xpix, ypix, shift, alt, dbl, doit))
hit = 1;
}
return (hit);
}
/*
Ivica Bukvic
committed
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
int scalar_groupclick(struct _glist *groupcanvas,
t_word *data, t_template *template, t_scalar *sc,
t_array *ap, struct _glist *owner,
t_float xloc, t_float yloc, int xpix, int ypix,
int shift, int alt, int dbl, int doit, t_float basex, t_float basey)
{
int hit = 0;
t_gobj *y;
for (y = groupcanvas->gl_list; y; y = y->g_next)
{
if (pd_class(&y->g_pd) == canvas_class &&
((t_glist *)y)->gl_svg)
{
if (hit = scalar_groupclick((t_glist *)y, data, template, sc, ap,
owner, xloc, yloc, xpix, ypix,
shift, alt, dbl, doit, basex, basey))
{
return (hit);
}
}
t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd);
if (!wb) continue;
if (hit = (*wb->w_parentclickfn)(y, owner,
data, template, sc, ap, basex + xloc, basey + yloc,
xpix, ypix, shift, alt, dbl, doit))
{
return (hit);
}
}
return 0;
}
Ivica Bukvic
committed
int scalar_doclick(t_word *data, t_template *template, t_scalar *sc,
t_array *ap, struct _glist *owner,
t_float xloc, t_float yloc, int xpix, int ypix,
int shift, int alt, int dbl, int doit)
{
int hit = 0;
t_canvas *templatecanvas = template_findcanvas(template);
t_float basex = template_getfloat(template, gensym("x"), data, 0);
t_float basey = template_getfloat(template, gensym("y"), data, 0);
//fprintf(stderr,"=================scalar_doclick %f %f %f %f %d\n",
// basex, basey, xloc, yloc, doit);
SETFLOAT(at, basex + xloc);
SETFLOAT(at+1, basey + yloc);
if (doit)
{
//fprintf(stderr," doit\n");
template_notifyforscalar(template, owner,
sc, gensym("click"), 2, at);
// if we are nested ignore xloc and yloc, otherwise
// nested objects get their hitbox miscalculated
if (xloc != 0.0 || yloc != 0.0)
{
//fprintf(stderr,"ignoring\n");
//basex = 0.0;
//basey = 0.0;
if (templatecanvas)
{
if (!(obj = templatecanvas->gl_list)) return 0;
hit = scalar_groupclick(templatecanvas, data, template, sc, ap,
owner, xloc, yloc, xpix, ypix,
shift, alt, dbl, doit, basex, basey, obj);
}
Ivica Bukvic
committed
return hit;
/* Unfortunately, nested gops don't yet handle scalar clicks correctly. The
nested scalar seems not to receive the click. However, the enter/leave
messages happen just fine since most of their logic is in tcl/tk. */
static int scalar_click(t_gobj *z, struct _glist *owner,
int xpix, int ypix, int shift, int alt, int dbl, int doit)
{
//fprintf(stderr,"scalar_click %d %d\n", xpix, ypix);
Ivica Bukvic
committed
Ivica Bukvic
committed
x->sc_bboxcache = 0;
t_template *template = template_findbyname(x->sc_template);
return (scalar_doclick(x->sc_vec, template, x, 0,
owner, 0, 0, xpix, ypix, shift, alt, dbl, doit));
}
void canvas_writescalar(t_symbol *templatesym, t_word *w, t_binbuf *b,
int amarrayelement);
static void scalar_save(t_gobj *z, t_binbuf *b)
{
t_scalar *x = (t_scalar *)z;
t_binbuf *b2 = binbuf_new();
canvas_writescalar(x->sc_template, x->sc_vec, b2, 0);
binbuf_addv(b, "ss", &s__X, gensym("scalar"));
binbuf_addbinbuf(b, b2);
binbuf_addsemi(b);
binbuf_free(b2);
}
static void scalar_menuopen(t_scalar *x)
{
t_canvas *c = scalar_getcanvasfield(x);
canvas_vis(c, 1);
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
static void scalar_properties(t_gobj *z, struct _glist *owner)
{
t_scalar *x = (t_scalar *)z;
char *buf, buf2[80];
int bufsize;
t_binbuf *b;
glist_noselect(owner);
glist_select(owner, z);
b = glist_writetobinbuf(owner, 0);
binbuf_gettext(b, &buf, &bufsize);
binbuf_free(b);
buf = t_resizebytes(buf, bufsize, bufsize+1);
buf[bufsize] = 0;
sprintf(buf2, "pdtk_data_dialog %%s {");
gfxstub_new((t_pd *)owner, x, buf2);
sys_gui(buf);
sys_gui("}\n");
t_freebytes(buf, bufsize+1);
}
static t_widgetbehavior scalar_widgetbehavior =
{
scalar_getrect,
scalar_displace,
scalar_select,
scalar_activate,
scalar_delete,
scalar_vis,
scalar_click,
scalar_displace_withtag,
};
static void scalar_free(t_scalar *x)
{
t_symbol *templatesym = x->sc_template;
t_template *template = template_findbyname(templatesym);
if (!template)
{
error("scalar: couldn't find template %s", templatesym->s_name);
return;
}
word_free(x->sc_vec, template);
Ivica Bukvic
committed
char buf[50];
sprintf(buf, "x%lx", (long unsigned int)x);
Ivica Bukvic
committed
pd_unbind(&x->sc_gobj.g_pd, gensym(buf));
gfxstub_deleteforkey(x);
/* the "size" field in the class is zero, so Pd doesn't try to free
us automatically (see pd_free()) */
freebytes(x, sizeof(t_scalar) + (template->t_n - 1) * sizeof(*x->sc_vec));
}
/* ----------------- setup function ------------------- */
void g_scalar_setup(void)
{
scalar_class = class_new(gensym("scalar"), 0, (t_method)scalar_free, 0,
CLASS_GOBJ, 0);
class_addmethod(scalar_class, (t_method)scalar_menuopen,
gensym("menu-open"), 0);
class_setwidget(scalar_class, &scalar_widgetbehavior);
class_setsavefn(scalar_class, scalar_save);
class_setpropertiesfn(scalar_class, scalar_properties);
}