#include #include #include #include #ifdef _MSC_VER #pragma warning( disable : 4244 ) #pragma warning( disable : 4305 ) #endif #ifndef IOWIDTH #define IOWIDTH 4 #endif typedef struct _button { t_object x_obj; t_atom a_pos; t_glist * x_glist; int x_rect_width; int x_rect_height; t_symbol* x_sym; t_symbol* x_text; int x_height; int x_width; } t_button; /* widget helper functions */ #define DEBUG(x) static void draw_inlets(t_button *x, t_glist *glist, int firsttime, int nin, int nout) { int n = nin; int nplus, i; nplus = (n == 1 ? 1 : n-1); DEBUG(post("draw inlet");) for (i = 0; i < n; i++) { int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH) * i / nplus; if (firsttime) sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxo%d\n", glist_getcanvas(glist), onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 2, onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-1, x, i); else sys_vgui(".x%lx.c coords %lxo%d %d %d %d %d\n", glist_getcanvas(glist), x, i, onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 2, onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-1); } n = nout; nplus = (n == 1 ? 1 : n-1); for (i = 0; i < n; i++) { int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH) * i / nplus; if (firsttime) sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxi%d\n", glist_getcanvas(glist), onset, text_ypix(&x->x_obj, glist), onset + IOWIDTH, text_ypix(&x->x_obj, glist)+5, x, i); else sys_vgui(".x%lx.c coords %lxi%d %d %d %d %d\n", glist_getcanvas(glist), x, i, onset, text_ypix(&x->x_obj, glist), onset + IOWIDTH, text_ypix(&x->x_obj, glist)+5); } DEBUG(post("draw inlet end");) } static void draw_handle(t_button *x, t_glist *glist, int firsttime) { int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH+2); if (firsttime) sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxhandle\n", glist_getcanvas(glist), onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 12, onset + IOWIDTH-2, text_ypix(&x->x_obj, glist) + x->x_rect_height-4, x); else sys_vgui(".x%lx.c coords %lxhandle %d %d %d %d\n", glist_getcanvas(glist), x, onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 12, onset + IOWIDTH-2, text_ypix(&x->x_obj, glist) + x->x_rect_height-4); } static void create_widget(t_button *x, t_glist *glist) { char text[MAXPDSTRING]; int len,i; t_canvas *canvas=glist_getcanvas(glist); x->x_rect_width = x->x_width+10; x->x_rect_height = x->x_height*20+12; strncpy(text,x->x_text->s_name,MAXPDSTRING); len = strlen(text); for (i=0;ix_height,text, x); } static void button_drawme(t_button *x, t_glist *glist, int firsttime) { t_canvas *canvas=glist_getcanvas(glist); DEBUG(post("drawme %d",firsttime);) if (firsttime) { DEBUG(post("glist %lx canvas %lx",x->x_glist,canvas);) // if (x->x_glist != canvas) { create_widget(x,glist); x->x_glist = canvas; // } sys_vgui(".x%lx.c create window %d %d -anchor nw -window .x%lx.c.s%lx -tags %lxS\n", canvas,text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),x->x_glist,x,x); } else { sys_vgui(".x%lx.c coords %lxS \ %d %d\n", canvas, x, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)); } draw_inlets(x, glist, firsttime, 1,1); // draw_handle(x, glist, firsttime); } static void button_erase(t_button* x,t_glist* glist) { int n; DEBUG(post("erase");) sys_vgui("destroy .x%lx.c.s%lx\n",glist_getcanvas(glist),x); sys_vgui(".x%lx.c delete %lxS\n",glist_getcanvas(glist), x); /* inlets and outlets */ sys_vgui(".x%lx.c delete %lxi%d\n",glist_getcanvas(glist),x,0); sys_vgui(".x%lx.c delete %lxo%d\n",glist_getcanvas(glist),x,0); sys_vgui(".x%lx.c delete %lxhandle\n",glist_getcanvas(glist),x,0); } /* ------------------------ button widgetbehaviour----------------------------- */ static void button_getrect(t_gobj *z, t_glist *owner, int *xp1, int *yp1, int *xp2, int *yp2) { int width, height; t_button* s = (t_button*)z; width = s->x_rect_width; height = s->x_rect_height; *xp1 = text_xpix(&s->x_obj, owner); *yp1 = text_ypix(&s->x_obj, owner) - 1; *xp2 = text_xpix(&s->x_obj, owner) + width; *yp2 = text_ypix(&s->x_obj, owner) + height; } static void button_displace(t_gobj *z, t_glist *glist, int dx, int dy) { t_button *x = (t_button *)z; DEBUG(post("displace");) x->x_obj.te_xpix += dx; x->x_obj.te_ypix += dy; if (glist_isvisible(glist)) { sys_vgui(".x%lx.c coords %lxSEL %d %d %d %d\n", glist_getcanvas(glist), x, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)-1, text_xpix(&x->x_obj, glist) + x->x_rect_width, text_ypix(&x->x_obj, glist) + x->x_rect_height-2); button_drawme(x, glist, 0); canvas_fixlinesfor(glist,(t_text*) x); } DEBUG(post("displace end");) } static void button_select(t_gobj *z, t_glist *glist, int state) { t_button *x = (t_button *)z; if (state) { sys_vgui(".x%lx.c create rectangle \ %d %d %d %d -tags %lxSEL -outline blue\n", glist_getcanvas(glist), text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)-1, text_xpix(&x->x_obj, glist) + x->x_rect_width, text_ypix(&x->x_obj, glist) + x->x_rect_height-2, x); } else { sys_vgui(".x%lx.c delete %lxSEL\n", glist_getcanvas(glist), x); } } static void button_activate(t_gobj *z, t_glist *glist, int state) { /* t_text *x = (t_text *)z; t_rtext *y = glist_findrtext(glist, x); if (z->g_pd != gatom_class) rtext_activate(y, state);*/ } static void button_delete(t_gobj *z, t_glist *glist) { t_text *x = (t_text *)z; canvas_deletelinesfor(glist, x); } static void button_vis(t_gobj *z, t_glist *glist, int vis) { t_button* s = (t_button*)z; DEBUG(post("vis: %d",vis);) if (vis) { button_drawme(s, glist, 1); } else { button_erase(s,glist); sys_unqueuegui(z); } } static void button_save(t_gobj *z, t_binbuf *b); t_widgetbehavior button_widgetbehavior; void button_size(t_button* x,t_floatarg w,t_floatarg h) { x->x_width = w; x->x_height = h; } void button_color(t_button* x,t_symbol* col) { /* outlet_bang(x->x_obj.ob_outlet); only bang if there was a bang .. so color black does the same as bang, but doesn't forward the bang */ } static void button_bang(t_button* x) { sys_vgui(".x%lx.c.s%lx flash\n",x->x_glist,x); outlet_bang(x->x_obj.ob_outlet); } static void button_b(t_button* x) { outlet_bang(x->x_obj.ob_outlet); } static void button_save(t_gobj *z, t_binbuf *b) { t_button *x = (t_button *)z; binbuf_addv(b, "ssiiss", gensym("#X"), gensym("obj"), x->x_obj.te_xpix, x->x_obj.te_ypix , atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)), x->x_text); binbuf_addv(b, ";"); } static t_class *button_class; static void *button_new(t_symbol* text) { t_button *x = (t_button *)pd_new(button_class); char buf[256]; x->x_glist = (t_glist*)NULL; x->x_width = 30; x->x_height = 1; if (text == &s_) x->x_text = gensym("OK"); else x->x_text = text; /* TODO .. ask the button for its width */ x->x_width += strlen(x->x_text->s_name)*5.2; sprintf(buf,"button%lx", (long unsigned int)x); x->x_sym = gensym(buf); pd_bind(&x->x_obj.ob_pd, x->x_sym); /* pipe startup code to tk */ sys_vgui("proc button_cb%lx {} {pdsend {%s b}}\n", x, buf); outlet_new(&x->x_obj, &s_float); return (x); } void button_setup(void) { button_class = class_new(gensym("button"), (t_newmethod)button_new, 0, sizeof(t_button),0,A_DEFSYM,0); class_addbang(button_class, (t_method)button_bang); class_addmethod(button_class, (t_method)button_b,gensym("b"),0); button_widgetbehavior.w_getrectfn= button_getrect, button_widgetbehavior.w_displacefn= button_displace, button_widgetbehavior.w_selectfn= button_select, button_widgetbehavior.w_activatefn= button_activate, button_widgetbehavior.w_deletefn= button_delete, button_widgetbehavior.w_visfn= button_vis, #if PD_MINOR_VERSION < 37 button_widgetbehavior.w_savefn= button_save, #endif button_widgetbehavior.w_clickfn= NULL, #if PD_MINOR_VERSION < 37 button_widgetbehavior.w_propertiesfn= NULL, #endif class_setwidget(button_class,&button_widgetbehavior); #if PD_MINOR_VERSION >= 37 class_setsavefn(button_class,&button_save); #endif }