aboutsummaryrefslogtreecommitdiff
path: root/test/imagebutton.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/imagebutton.c')
-rw-r--r--test/imagebutton.c415
1 files changed, 415 insertions, 0 deletions
diff --git a/test/imagebutton.c b/test/imagebutton.c
new file mode 100644
index 0000000..577924a
--- /dev/null
+++ b/test/imagebutton.c
@@ -0,0 +1,415 @@
+#include <m_pd.h>
+#include "g_canvas.h"
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+
+/* Append " x " to the following line to show debugging messages */
+#define DEBUG(x) x
+
+// TODO: NEED TO FREE UNUSED IMAGES!
+
+
+
+/* ------------------------ imagebutton ----------------------------- */
+
+static t_class *imagebutton_class;
+t_widgetbehavior imagebutton_widgetbehavior;
+
+
+typedef struct _imagebutton
+{
+ t_object x_obj;
+ t_glist * glist;
+ int width;
+ int height;
+ t_symbol* image_a;
+ t_symbol* image_b;
+ t_symbol* receive;
+ t_clock* clock_flash;
+ t_clock* clock_brk;
+ int flashing;
+ t_outlet* outlet;
+} t_imagebutton;
+
+
+static void imagebutton_bang(t_imagebutton *x)
+{
+
+ t_glist* glist = glist_getcanvas(x->glist);
+ if(x->flashing) {
+ sys_vgui(".x%x.c itemconfigure %ximage -image %x_imagebutton \n", glist, x,x->image_a);
+ clock_delay(x->clock_brk, 50);
+ //x->flashed = 1;
+ } else {
+ sys_vgui(".x%x.c itemconfigure %ximage -image %x_imagebutton \n", glist, x,x->image_b);
+ x->flashing = 1;
+
+ }
+ clock_delay(x->clock_flash, 250);
+
+ outlet_bang(x->outlet);
+}
+
+static void imagebutton_flash_timeout(t_imagebutton *x)
+{
+ t_glist* glist = glist_getcanvas(x->glist);
+ x->flashing = 0;
+ sys_vgui(".x%x.c itemconfigure %ximage -image %x_imagebutton \n", glist, x,x->image_a);
+
+}
+
+static void imagebutton_brk_timeout(t_imagebutton *x)
+{
+ t_glist* glist = glist_getcanvas(x->glist);
+ x->flashing = 1;
+ sys_vgui(".x%x.c itemconfigure %ximage -image %x_imagebutton \n", glist, x,x->image_b);
+
+}
+
+
+/* widget helper functions */
+
+static const char* imagebutton_get_filename(t_imagebutton *x,char *file) {
+ static char fname[MAXPDSTRING];
+ char *bufptr;
+ int fd;
+
+ fd=open_via_path(canvas_getdir(glist_getcanvas(x->glist))->s_name,
+ file, "",fname, &bufptr, MAXPDSTRING, 1);
+ if(fd>0){
+ fname[strlen(fname)]='/';
+ DEBUG(post("image file: %s",fname);)
+ close(fd);
+ return fname;
+ } else {
+ return 0;
+ }
+}
+
+static int imagebutton_click(t_imagebutton *x, struct _glist *glist,
+ int xpos, int ypos, int shift, int alt, int dbl, int doit) {
+ DEBUG(post("x:%i y:%i dbl:%i doit:%i",xpos,ypos,dbl,doit);)
+ //if ( doit) {
+ //sys_vgui(".x%x.c itemconfigure %ximage -state \"%s\"\n", x->glist, x, doit?"disabled":"normal");
+ if ( doit) imagebutton_bang(x) ;
+ //}
+ return (1);
+ }
+
+
+
+
+static void imagebutton_drawme(t_imagebutton *x, t_glist *glist, int firsttime) {
+ if (firsttime) {
+
+ sys_vgui(".x%x.c create image %d %d -anchor nw -image %x_imagebutton -disabledimage %x_imagebutton -tags %ximage\n",
+ glist_getcanvas(glist),
+ text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),x->image_a,x->image_b,x);
+
+
+ sys_vgui("pd [concat %s _imagesize [image width %x_imagebutton] [image height %x_imagebutton] \\;]\n",x->receive->s_name,x->image_a,x->image_a);
+
+
+ } else {
+ sys_vgui(".x%x.c coords %ximage %d %d\n",
+ glist_getcanvas(glist), x,
+ text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist));
+ }
+
+}
+
+
+void imagebutton_erase(t_imagebutton* x,t_glist* glist)
+{
+ int n;
+ sys_vgui(".x%x.c delete %ximage\n",
+ glist_getcanvas(glist), x);
+
+}
+
+
+
+/* ------------------------ image widgetbehaviour----------------------------- */
+
+
+static void imagebutton_getrect(t_gobj *z, t_glist *glist,
+ int *xp1, int *yp1, int *xp2, int *yp2)
+{
+ int width, height;
+ t_imagebutton* x = (t_imagebutton*)z;
+
+
+ width = x->width;
+ height = x->height;
+ *xp1 = text_xpix(&x->x_obj, glist);
+ *yp1 = text_ypix(&x->x_obj, glist);
+ *xp2 = text_xpix(&x->x_obj, glist) + width;
+ *yp2 = text_ypix(&x->x_obj, glist) + height;
+}
+
+static void imagebutton_displace(t_gobj *z, t_glist *glist,
+ int dx, int dy)
+{
+ t_imagebutton *x = (t_imagebutton *)z;
+ x->x_obj.te_xpix += dx;
+ x->x_obj.te_ypix += dy;
+ sys_vgui(".x%x.c coords %xSEL %d %d %d %d\n",
+ glist_getcanvas(glist), x,
+ text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),
+ text_xpix(&x->x_obj, glist) + x->width, text_ypix(&x->x_obj, glist) + x->height);
+
+ imagebutton_drawme(x, glist, 0);
+ canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x);
+}
+
+static void imagebutton_select(t_gobj *z, t_glist *glist, int state)
+{
+ t_imagebutton *x = (t_imagebutton *)z;
+ if (state) {
+ sys_vgui(".x%x.c create rectangle \
+%d %d %d %d -tags %xSEL -outline blue\n",
+ glist_getcanvas(glist),
+ text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),
+ text_xpix(&x->x_obj, glist) + x->width, text_ypix(&x->x_obj, glist) + x->height,
+ x);
+ }
+ else {
+ sys_vgui(".x%x.c delete %xSEL\n",
+ glist_getcanvas(glist), x);
+ }
+
+
+
+}
+
+
+static void imagebutton_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 imagebutton_delete(t_gobj *z, t_glist *glist)
+{
+ t_text *x = (t_text *)z;
+ //canvas_deletelinesfor(glist_getcanvas(glist), x);
+ canvas_deletelinesfor(glist, x);
+}
+
+
+static void imagebutton_vis(t_gobj *z, t_glist *glist, int vis)
+{
+ t_imagebutton* s = (t_imagebutton*)z;
+ if (vis)
+ imagebutton_drawme(s, glist, 1);
+ else
+ imagebutton_erase(s,glist);
+}
+
+/* can we use the normal text save function ?? */
+/*
+static void imagebutton_save(t_gobj *z, t_binbuf *b)
+{
+ t_imagebutton *x = (t_imagebutton *)z;
+ binbuf_addv(b, "ssiissi", 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_image,x->x_type);
+ binbuf_addv(b, ";");
+}
+*/
+
+
+static void imagebutton_size(t_imagebutton* x,t_floatarg w,t_floatarg h) {
+ x->width = w;
+ x->height = h;
+}
+
+static void imagebutton_color(t_imagebutton* 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 imagebutton_open(t_gobj *z,t_symbol* file)
+{
+ t_imagebutton* x = (t_imagebutton*)z;
+ const char *fname;
+ int oldtype=x->x_type;
+
+
+ fname=imagebutton_get_filename(x,file->s_name);
+ if(fname){
+ x->x_image=file;
+ x->x_type=0;
+ if(glist_isvisible(x->glist)) {
+ if(!x->x_localimage) {
+ sys_vgui("image create photo img%x\n",x);
+ x->x_localimage=1;
+ }
+ sys_vgui("img%x blank\n",x);
+ sys_vgui("img%x configure -file %s\n",x,fname);
+ if(oldtype) sys_vgui(".x%x.c itemconfigure %xS -image img%x\n",
+ glist_getcanvas(x->glist),x,x);
+ }
+ }
+}
+ */
+
+static void imagebutton_imagesize_callback(t_imagebutton *x, t_float w, t_float h) {
+ DEBUG(post("received w %f h %f",w,h);)
+ x->width = w;
+ x->height = h;
+ canvas_fixlinesfor(glist_getcanvas(x->glist),(t_text*) x);
+}
+
+
+static void imagebutton_free(t_imagebutton *x) {
+
+ // check first if variable has been unset and image is unused
+ // then delete image and unset variable
+ DEBUG(sys_vgui("pd [concat DEBUG b in use [image inuse %x_imagebutton] \\;]\n",x->image_b);)
+ DEBUG(sys_vgui("pd [concat DEBUG a in use [image inuse %x_imagebutton] \\;]\n",x->image_a);)
+
+ sys_vgui("if { [info exists %x_imagebutton] == 1 && [image inuse %x_imagebutton] == 0} { image delete %x_imagebutton \n unset %x_imagebutton\n} \n",x->image_b,x->image_b,x->image_b,x->image_b);
+ sys_vgui("if { [info exists %x_imagebutton] == 1 && [image inuse %x_imagebutton] == 0} { image delete %x_imagebutton \n unset %x_imagebutton\n} \n",x->image_a,x->image_a,x->image_a,x->image_a);
+
+ DEBUG(sys_vgui("pd [concat DEBUG b exists [info exists %x_imagebutton] \\;]\n",x->image_b);)
+ DEBUG(sys_vgui("pd [concat DEBUG a exists [info exists %x_imagebutton] \\;]\n",x->image_a);)
+
+ if (x->receive) {
+ pd_unbind(&x->x_obj.ob_pd,x->receive);
+ }
+ clock_free(x->clock_flash);
+ clock_free(x->clock_brk);
+
+}
+
+
+static void *imagebutton_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_imagebutton *x = (t_imagebutton *)pd_new(imagebutton_class);
+
+ x->glist = (t_glist*) canvas_getcurrent();
+
+ // Set up a callback to get the size
+ x->width = 10;
+ x->height = 10;
+
+ x->flashing = 0;
+
+ x->image_a = NULL;
+ x->image_b = NULL;
+
+ t_symbol* image_a = NULL;
+ t_symbol* image_b = NULL;
+
+ const char *fname;
+
+ // CREATE IMAGES
+ // images are only created if they have not been created yet
+ // we use the symbol pointer to distinguish between image files
+
+
+ if ( argc && (argv)->a_type == A_SYMBOL ) {
+ image_a= atom_getsymbol(argv);
+ fname = imagebutton_get_filename(x,image_a->s_name); // Get image file path
+ if (fname) {
+ x->image_a = gensym(fname);
+ //sys_vgui("set %x_a \"%s\" \n",x,fname);
+ // Create the image only if the class has not already loaded the same image (with the same symbolic path name)
+ sys_vgui("if { [info exists %x_imagebutton] == 0} { image create photo %x_imagebutton -file \"%s\"\n set %x_imagebutton 1\n} \n",x->image_a,x->image_a,fname,x->image_a);
+ //sys_vgui("pd [concat test %x_imagebutton \\;]\n",x->image_a);
+ }
+ }
+
+
+
+ if ( argc > 1 && (argv+1)->a_type == A_SYMBOL ) {
+ image_b= atom_getsymbol(argv+1);
+ fname = imagebutton_get_filename(x,image_b->s_name); // Get image file path
+ if (fname) {
+ x->image_b = gensym(fname);
+ //sys_vgui("set %x_b \"%s\" \n",x,fname);
+ sys_vgui("if { [info exists %x_imagebutton] == 0} { image create photo %x_imagebutton -file \"%s\"\n set %x_imagebutton 1\n} \n",x->image_b,x->image_b,fname,x->image_b);
+ //sys_vgui("pd [concat test %x_imagebutton \\;]\n",x->image_b);
+ }
+ }
+
+ if (image_a == NULL || image_b == NULL) {
+ pd_error(x,"[imagebutton] requires two gif images");
+ return NULL;
+ }
+ char buf[MAXPDSTRING];
+ sprintf(buf, "#%lx", (long)x);
+ x->receive = gensym(buf);
+ pd_bind(&x->x_obj.ob_pd, x->receive );
+
+ x->clock_flash = clock_new(x, (t_method)imagebutton_flash_timeout);
+ x->clock_brk = clock_new(x, (t_method)imagebutton_brk_timeout);
+
+
+ x->outlet = outlet_new(&x->x_obj, &s_float);
+
+
+ return (x);
+
+}
+
+void imagebutton_setup(void)
+{
+ imagebutton_class = class_new(gensym("imagebutton"), (t_newmethod)imagebutton_new, (t_method)imagebutton_free,
+ sizeof(t_imagebutton),0, A_GIMME,0);
+
+ class_addmethod(imagebutton_class, (t_method)imagebutton_imagesize_callback,\
+ gensym("_imagesize"), A_DEFFLOAT, A_DEFFLOAT, 0);
+
+
+/*
+ class_addmethod(imagebutton_class, (t_method)imagebutton_size, gensym("size"),
+ A_FLOAT, A_FLOAT, 0);
+
+ class_addmethod(imagebutton_class, (t_method)imagebutton_color, gensym("color"),
+ A_SYMBOL, 0);
+*/
+ /*
+ class_addmethod(imagebutton_class, (t_method)imagebutton_open, gensym("open"),
+ A_SYMBOL, 0);
+ */
+ /*
+ class_addmethod(imagebutton_class, (t_method)imagebutton_set, gensym("set"),
+ A_SYMBOL, 0);
+ */
+ /*
+ class_addmethod(imagebutton_class, (t_method)imagebutton_load, gensym("load"),
+ A_SYMBOL, A_SYMBOL, 0);
+*/
+
+ imagebutton_widgetbehavior.w_getrectfn = imagebutton_getrect;
+ imagebutton_widgetbehavior.w_displacefn = imagebutton_displace;
+ imagebutton_widgetbehavior.w_selectfn = imagebutton_select;
+ imagebutton_widgetbehavior.w_activatefn = imagebutton_activate;
+ imagebutton_widgetbehavior.w_deletefn = imagebutton_delete;
+ imagebutton_widgetbehavior.w_visfn = imagebutton_vis;
+
+ imagebutton_widgetbehavior.w_clickfn = (t_clickfn)imagebutton_click;
+
+
+#if PD_MINOR_VERSION < 37
+ imagebutton_widgetbehavior.w_propertiesfn = NULL;
+ //imagebutton_widgetbehavior.w_savefn = imagebutton_save;
+#endif
+
+
+ class_setwidget(imagebutton_class,&imagebutton_widgetbehavior);
+#if PD_MINOR_VERSION >= 37
+ // class_setsavefn(imagebutton_class,&imagebutton_save);
+#endif
+
+}
+
+