diff options
| author | Peter D'Hoye <peter.dhoye@gmail.com> | 2009-05-24 21:28:16 +0000 |
|---|---|---|
| committer | Peter D'Hoye <peter.dhoye@gmail.com> | 2009-05-24 21:28:16 +0000 |
| commit | 526b5580dabbfed7cfe5439dc3a90ec727f563c2 (patch) | |
| tree | 22b1af92348785daad16714ee5e2b633017e0e48 /apps/plugins/pdbox/PDa/src/g_graph.c | |
| parent | 4f2dfcc01b260d946044ef2b6af5fe36cb772c8d (diff) | |
| download | rockbox-526b5580dabbfed7cfe5439dc3a90ec727f563c2.zip rockbox-526b5580dabbfed7cfe5439dc3a90ec727f563c2.tar.gz rockbox-526b5580dabbfed7cfe5439dc3a90ec727f563c2.tar.bz2 rockbox-526b5580dabbfed7cfe5439dc3a90ec727f563c2.tar.xz | |
Cut the files in half and it might work better (note to self: check your tree is really clean before patching)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21070 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/g_graph.c')
| -rw-r--r-- | apps/plugins/pdbox/PDa/src/g_graph.c | 1111 |
1 files changed, 0 insertions, 1111 deletions
diff --git a/apps/plugins/pdbox/PDa/src/g_graph.c b/apps/plugins/pdbox/PDa/src/g_graph.c index 6a64900..c81bac1 100644 --- a/apps/plugins/pdbox/PDa/src/g_graph.c +++ b/apps/plugins/pdbox/PDa/src/g_graph.c @@ -1110,1115 +1110,4 @@ void g_graph_setup(void) class_addmethod(canvas_class, (t_method)glist_sort, gensym("sort"), A_NULL); } -/* 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" -#include "t_tk.h" -#include "g_canvas.h" -#include <stdio.h> -#include <string.h> - -/* ---------------------- forward definitions ----------------- */ - -static void graph_vis(t_gobj *gr, t_glist *unused_glist, int vis); -static 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); - -/* -------------------- maintaining the list -------------------- */ - -void glist_add(t_glist *x, t_gobj *y) -{ - t_object *ob; - y->g_next = 0; - if (!x->gl_list) x->gl_list = y; - else - { - t_gobj *y2; - for (y2 = x->gl_list; y2->g_next; y2 = y2->g_next); - y2->g_next = y; - } - if (x->gl_editor && (ob = pd_checkobject(&y->g_pd))) - rtext_new(x, ob); - if (glist_isvisible(x)) - gobj_vis(y, x, 1); - if (class_isdrawcommand(y->g_pd)) - canvas_redrawallfortemplate(glist_getcanvas(x)); -} - - /* 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); -} - - /* delete an object from a glist and free it */ -void glist_delete(t_glist *x, t_gobj *y) -{ - t_gobj *g; - t_object *ob; - t_gotfn chkdsp = zgetfn(&y->g_pd, gensym("dsp")); - t_canvas *canvas = glist_getcanvas(x); - int drawcommand = class_isdrawcommand(y->g_pd); - int wasdeleting; - - 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) - { - t_glist *gl = (t_glist *)y; - if (gl->gl_isgraph) - { - char tag[80]; - sprintf(tag, "graph%x", (int)gl); - glist_eraseiofor(x, &gl->gl_obj, tag); - } - else - { - text_eraseborder(&gl->gl_obj, x, - rtext_gettag(glist_findrtext(x, &gl->gl_obj))); - } - } - } - gobj_delete(y, x); - if (glist_isvisible(canvas)) - gobj_vis(y, x, 0); - if (x->gl_editor && (ob = pd_checkobject(&y->g_pd))) - rtext_new(x, ob); - if (x->gl_list == y) x->gl_list = y->g_next; - else for (g = x->gl_list; g; g = g->g_next) - if (g->g_next == y) - { - g->g_next = y->g_next; - break; - } - pd_free(&y->g_pd); - if (chkdsp) canvas_update_dsp(); - if (drawcommand) canvas_redrawallfortemplate(canvas); - canvas_setdeleting(canvas, wasdeleting); - x->gl_valid = ++glist_valid; -} - - /* remove every object from a glist. Experimental. */ -void glist_clear(t_glist *x) -{ - t_gobj *y, *y2; - int dspstate = canvas_suspend_dsp(); - while (y = x->gl_list) - glist_delete(x, y); - canvas_resume_dsp(dspstate); -} - -void glist_retext(t_glist *glist, t_text *y) -{ - t_canvas *c = glist_getcanvas(glist); - /* 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) -{ - 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) -{ - while (x->gl_owner && !x->gl_havewindow && x->gl_isgraph) - x = x->gl_owner; - return((t_canvas *)x); -} - -static float gobj_getxforsort(t_gobj *g) -{ - if (pd_class(&g->g_pd) == scalar_class) - { - float x1, y1; - 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; - float f1 = 0, f2 = 0; - 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; - float lastx = -1e37; - t_gobj *g; - for (g = x->gl_list; g; g = g->g_next) - { - 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); -} - -void glist_cleanup(t_glist *x) -{ - freebytes(x->gl_xlabel, x->gl_nxlabels * sizeof(*(x->gl_xlabel))); - freebytes(x->gl_ylabel, x->gl_nylabels * sizeof(*(x->gl_ylabel))); - gstub_cutoff(x->gl_stub); -} - -void glist_free(t_glist *x) -{ - glist_cleanup(x); - freebytes(x, sizeof(*x)); -} - -/* --------------- inlets and outlets ----------- */ - - -t_inlet *canvas_addinlet(t_canvas *x, t_pd *who, t_symbol *s) -{ - 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++; - - if (ninlets < 2) 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)) - canvas_fixlinesfor(x->gl_owner, &x->gl_obj); -} - -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++; - - if (noutlets < 2) return; - - 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)) - canvas_fixlinesfor(x->gl_owner, &x->gl_obj); -} - -/* ----------calculating coordinates and controlling appearance --------- */ - - -static void graph_bounds(t_glist *x, t_floatarg x1, t_floatarg y1, - t_floatarg x2, t_floatarg y2) -{ - x->gl_x1 = x1; - x->gl_x2 = x2; - x->gl_y1 = y1; - x->gl_y2 = y2; - if (x->gl_x2 == x->gl_x1 || - x->gl_y2 == x->gl_y1) - { - error("graph: empty bounds rectangle"); - x1 = y1 = 0; - x2 = y2 = 1; - } - glist_redraw(x); -} - -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 */ -float glist_pixelstox(t_glist *x, float xpix) -{ - /* 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)); - } -} - -float glist_pixelstoy(t_glist *x, 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) - bug("glist_pixelstox"); - 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 */ -float glist_xtopixels(t_glist *x, 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)); - } -} - -float glist_ytopixels(t_glist *x, 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) - bug("glist_pixelstox"); - 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. */ -float glist_dpixtodx(t_glist *x, float dxpix) -{ - return (dxpix * (glist_pixelstox(x, 1) - glist_pixelstox(x, 0))); -} - -float glist_dpixtody(t_glist *x, float dypix) -{ - 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. If it's not, we convert to pixels on the parent - window. */ -int text_xpix(t_text *x, t_glist *glist) -{ - if (glist->gl_havewindow || !glist->gl_isgraph) - return (x->te_xpix); - 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 return (glist_ytopixels(glist, - glist->gl_y1 + (glist->gl_y2 - glist->gl_y1) * - x->te_ypix / (glist->gl_screeny2 - glist->gl_screeny1))); -} - - /* 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) -{ - if (glist_isvisible(x)) - { - /* LATER fix the graph_vis() code to handle both cases */ - if (glist_istoplevel(x)) - { - 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)) - sys_vgui(".x%x.c coords l%x %d %d %d %d\n", - glist_getcanvas(x), oc, - t.tr_lx1, t.tr_ly1, t.tr_lx2, t.tr_ly2); - } - if (x->gl_owner) - { - graph_vis(&x->gl_gobj, x->gl_owner, 0); - graph_vis(&x->gl_gobj, x->gl_owner, 1); - } - } -} - -/* --------------------------- widget behavior ------------------- */ - -extern t_widgetbehavior text_widgetbehavior; - - /* 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; - 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; - } - - if (vis && canvas_showtext(x)) - rtext_draw(glist_findrtext(parent_glist, &x->gl_obj)); - graph_getrect(gr, parent_glist, &x1, &y1, &x2, &y2); - if (!vis) - rtext_erase(glist_findrtext(parent_glist, &x->gl_obj)); - - sprintf(tag, "graph%x", (int)x); - if (vis) - glist_drawiofor(parent_glist, &x->gl_obj, 1, - tag, x1, y1, x2, y2); - else glist_eraseiofor(parent_glist, &x->gl_obj, tag); - /* if we look like a graph but have been moved to a toplevel, - just show the bounding rectangle */ - if (x->gl_havewindow) - { - if (vis) - { - sys_vgui(".x%x.c create polygon\ - %d %d %d %d %d %d %d %d %d %d -tags %s -fill #c0c0c0\n", - glist_getcanvas(x->gl_owner), - x1, y1, x1, y2, x2, y2, x2, y1, x1, y1, tag); - } - else - { - sys_vgui(".x%x.c delete %s\n", - glist_getcanvas(x->gl_owner), tag); - } - return; - } - /* otherwise draw (or erase) us as a graph inside another glist. */ - if (vis) - { - int i; - float f; - - /* draw a rectangle around the graph */ - sys_vgui(".x%x.c create line\ - %d %d %d %d %d %d %d %d %d %d -tags %s\n", - glist_getcanvas(x->gl_owner), - x1, y1, x1, y2, x2, y2, x2, y1, x1, y1, tag); - - /* draw ticks on horizontal borders. If lperb field is - zero, this is disabled. */ - if (x->gl_xtick.k_lperb) - { - float upix, lpix; - if (y2 < y1) - upix = y1, lpix = y2; - else upix = y2, lpix = y1; - for (i = 0, f = x->gl_xtick.k_point; - f < 0.99 * x->gl_x2 + 0.01*x->gl_x1; i++, - f += x->gl_xtick.k_inc) - { - int tickpix = (i % x->gl_xtick.k_lperb ? 2 : 4); - sys_vgui(".x%x.c create line %d %d %d %d -tags %s\n", - glist_getcanvas(x->gl_owner), - (int)glist_xtopixels(x, f), (int)upix, - (int)glist_xtopixels(x, f), (int)upix - tickpix, tag); - sys_vgui(".x%x.c create line %d %d %d %d -tags %s\n", - glist_getcanvas(x->gl_owner), - (int)glist_xtopixels(x, f), (int)lpix, - (int)glist_xtopixels(x, f), (int)lpix + tickpix, tag); - } - for (i = 1, f = x->gl_xtick.k_point - x->gl_xtick.k_inc; - f > 0.99 * x->gl_x1 + 0.01*x->gl_x2; - i++, f -= x->gl_xtick.k_inc) - { - int tickpix = (i % x->gl_xtick.k_lperb ? 2 : 4); - sys_vgui(".x%x.c create line %d %d %d %d -tags %s\n", - glist_getcanvas(x->gl_owner), - (int)glist_xtopixels(x, f), (int)upix, - (int)glist_xtopixels(x, f), (int)upix - tickpix, tag); - sys_vgui(".x%x.c create line %d %d %d %d -tags %s\n", - glist_getcanvas(x->gl_owner), - (int)glist_xtopixels(x, f), (int)lpix, - (int)glist_xtopixels(x, f), (int)lpix + tickpix, tag); - } - } - - /* draw ticks in vertical borders*/ - if (x->gl_ytick.k_lperb) - { - float ubound, lbound; - if (x->gl_y2 < x->gl_y1) - ubound = x->gl_y1, lbound = x->gl_y2; - else ubound = x->gl_y2, lbound = x->gl_y1; - for (i = 0, f = x->gl_ytick.k_point; - f < 0.99 * ubound + 0.01 * lbound; - i++, f += x->gl_ytick.k_inc) - { - int tickpix = (i % x->gl_ytick.k_lperb ? 2 : 4); - sys_vgui(".x%x.c create line %d %d %d %d -tags %s\n", - glist_getcanvas(x->gl_owner), - x1, (int)glist_ytopixels(x, f), - x1 + tickpix, (int)glist_ytopixels(x, f), tag); - sys_vgui(".x%x.c create line %d %d %d %d -tags %s\n", - glist_getcanvas(x->gl_owner), - x2, (int)glist_ytopixels(x, f), - x2 - tickpix, (int)glist_ytopixels(x, f), tag); - } - for (i = 1, f = x->gl_ytick.k_point - x->gl_ytick.k_inc; - f > 0.99 * lbound + 0.01 * ubound; - i++, f -= x->gl_ytick.k_inc) - { - int tickpix = (i % x->gl_ytick.k_lperb ? 2 : 4); - sys_vgui(".x%x.c create line %d %d %d %d -tags %s\n", - glist_getcanvas(x->gl_owner), - x1, (int)glist_ytopixels(x, f), - x1 + tickpix, (int)glist_ytopixels(x, f), tag); - sys_vgui(".x%x.c create line %d %d %d %d -tags %s\n", - glist_getcanvas(x->gl_owner), - x2, (int)glist_ytopixels(x, f), - x2 - tickpix, (int)glist_ytopixels(x, f), tag); - } - } - /* draw x labels */ - for (i = 0; i < x->gl_nxlabels; i++) - sys_vgui(".x%x.c create text\ - %d %d -text {%s} -font -*-courier-bold--normal--%d-* -tags %s\n", - glist_getcanvas(x), - (int)glist_xtopixels(x, atof(x->gl_xlabel[i]->s_name)), - (int)glist_ytopixels(x, x->gl_xlabely), x->gl_xlabel[i]->s_name, - glist_getfont(x), tag); - - /* draw y labels */ - for (i = 0; i < x->gl_nylabels; i++) - sys_vgui(".x%x.c create text\ - %d %d -text {%s} -font -*-courier-bold--normal--%d-* -tags %s\n", - glist_getcanvas(x), - (int)glist_xtopixels(x, x->gl_ylabelx), - (int)glist_ytopixels(x, atof(x->gl_ylabel[i]->s_name)), - x->gl_ylabel[i]->s_name, - glist_getfont(x), tag); - - /* draw contents of graph as glist */ - for (g = x->gl_list; g; g = g->g_next) - gobj_vis(g, x, 1); - } - else - { - sys_vgui(".x%x.c delete %s\n", - glist_getcanvas(x->gl_owner), tag); - for (g = x->gl_list; g; g = g->g_next) - gobj_vis(g, x, 0); - } -} - - /* get the graph's rectangle, not counting extra swelling for controls - to keep them inside the graph. This is the "logical" pixel size. */ - -static void graph_graphrect(t_gobj *z, t_glist *glist, - int *xp1, int *yp1, int *xp2, int *yp2) -{ - t_glist *x = (t_glist *)z; - int x1 = text_xpix(&x->gl_obj, glist); - int y1 = text_ypix(&x->gl_obj, glist); - int x2, y2; -#if 0 /* this used to adjust graph size when it was in another graph; - now we just preserve the size. */ - /* same logic here as in text_xpix(): */ - if (glist->gl_havewindow) - { - x2 = x1 + x->gl_pixwidth; - y2 = y1 + x->gl_pixheight; - } - else - { - x2 = glist_xtopixels(glist, - glist->gl_x1 + (glist->gl_x2 - glist->gl_x1) * - (x->gl_obj.te_xpix + x->gl_pixwidth) / - (glist->gl_screenx2 - glist->gl_screenx1)); - y2 = glist_ytopixels(glist, - glist->gl_y1 + (glist->gl_y2 - glist->gl_y1) * - (x->gl_obj.te_ypix + x->gl_pixheight) / - (glist->gl_screeny2 - glist->gl_screeny1)); - } -#endif - x2 = x1 + x->gl_pixwidth; - y2 = y1 + x->gl_pixheight; - - *xp1 = x1; - *yp1 = y1; - *xp2 = x2; - *yp2 = y2; -} - - /* get the rectangle, enlarged to contain all the "contents" -- - meaning their formal bounds rectangles. */ -static void graph_getrect(t_gobj *z, t_glist *glist, - int *xp1, int *yp1, int *xp2, int *yp2) -{ - int x1 = 0x7fffffff, y1 = 0x7fffffff, x2 = -0x7fffffff, y2 = -0x7fffffff; - t_glist *x = (t_glist *)z; - if (x->gl_isgraph) - { - int hadwindow; - t_gobj *g; - t_text *ob; - int x21, y21, x22, y22; - - graph_graphrect(z, glist, &x1, &y1, &x2, &y2); - if (canvas_showtext(x)) - { - text_widgetbehavior.w_getrectfn(z, glist, &x21, &y21, &x22, &y22); - if (x22 > x2) - x2 = x22; - if (y22 > y2) - y2 = y22; - } - /* lie about whether we have our own window to affect gobj_getrect - calls below. (LATER add argument to gobj_getrect()?) */ - hadwindow = x->gl_havewindow; - x->gl_havewindow = 0; - for (g = x->gl_list; g; g = g->g_next) - if ((!(ob = pd_checkobject(&g->g_pd))) || text_shouldvis(ob, x)) - { - /* don't do this for arrays, just let them hang outsize the - box. */ - if (pd_class(&g->g_pd) == garray_class) - continue; - gobj_getrect(g, x, &x21, &y21, &x22, &y22); - if (x22 > x2) - x2 = x22; - if (y22 > y2) - y2 = y22; - } - x->gl_havewindow = hadwindow; - } - else text_widgetbehavior.w_getrectfn(z, glist, &x1, &y1, &x2, &y2); - *xp1 = x1; - *yp1 = y1; - *xp2 = x2; - *yp2 = y2; -} - -static void graph_displace(t_gobj *z, t_glist *glist, int dx, int dy) -{ - t_glist *x = (t_glist *)z; - if (!x->gl_isgraph) - text_widgetbehavior.w_displacefn(z, glist, dx, dy); - else - { - x->gl_obj.te_xpix += dx; - x->gl_obj.te_ypix += dy; - glist_redraw(x); - canvas_fixlinesfor(glist_getcanvas(glist), &x->gl_obj); - } -} - -static void graph_select(t_gobj *z, t_glist *glist, int state) -{ - t_glist *x = (t_glist *)z; - if (!x->gl_isgraph) - text_widgetbehavior.w_selectfn(z, glist, state); - else - { - t_rtext *y = glist_findrtext(glist, &x->gl_obj); - if (canvas_showtext(x)) - rtext_select(y, state); - sys_vgui(".x%x.c itemconfigure %sR -fill %s\n", glist, - rtext_gettag(y), (state? "blue" : "black")); - sys_vgui(".x%x.c itemconfigure graph%x -fill %s\n", - glist_getcanvas(glist), z, (state? "blue" : "black")); - } -} - -static void graph_activate(t_gobj *z, t_glist *glist, int state) -{ - t_glist *x = (t_glist *)z; - if (canvas_showtext(x)) - text_widgetbehavior.w_activatefn(z, glist, state); -} - -#if 0 -static void graph_delete(t_gobj *z, t_glist *glist) -{ - t_glist *x = (t_glist *)z; - if (!x->gl_isgraph) - text_widgetbehavior.w_deletefn(z, glist); - else - { - t_gobj *y; - while (y = x->gl_list) glist_delete(x, y); -#if 0 /* I think this was just wrong. */ - if (glist_isvisible(x)) - sys_vgui(".x%x.c delete graph%x\n", glist_getcanvas(glist), x); -#endif - } -} -#endif - -static void graph_delete(t_gobj *z, t_glist *glist) -{ - t_glist *x = (t_glist *)z; - t_gobj *y; - text_widgetbehavior.w_deletefn(z, glist); - while (y = x->gl_list) - glist_delete(x, y); -} - -static float graph_lastxpix, graph_lastypix; - -static void graph_motion(void *z, t_floatarg dx, t_floatarg dy) -{ - t_glist *x = (t_glist *)z; - float newxpix = graph_lastxpix + dx, newypix = graph_lastypix + dy; - t_garray *a = (t_garray *)(x->gl_list); - int oldx = 0.5 + glist_pixelstox(x, graph_lastxpix); - int newx = 0.5 + glist_pixelstox(x, newxpix); - t_sample *vec; - int nelem, i; - float oldy = glist_pixelstoy(x, graph_lastypix); - float newy = glist_pixelstoy(x, newypix); - graph_lastxpix = newxpix; - graph_lastypix = newypix; - /* verify that the array is OK */ - if (!a || pd_class((t_pd *)a) != garray_class) - return; - if (!garray_getfloatarray(a, &nelem, &vec)) - return; - if (oldx < 0) oldx = 0; - if (oldx >= nelem) - oldx = nelem - 1; - if (newx < 0) newx = 0; - if (newx >= nelem) - newx = nelem - 1; - if (oldx < newx - 1) - { - for (i = oldx + 1; i <= newx; i++) - vec[i] = newy + (oldy - newy) * - ((float)(newx - i))/(float)(newx - oldx); - } - else if (oldx > newx + 1) - { - for (i = oldx - 1; i >= newx; i--) - vec[i] = newy + (oldy - newy) * - ((float)(newx - i))/(float)(newx - oldx); - } - else vec[newx] = newy; - garray_redraw(a); -} - -static int graph_click(t_gobj *z, struct _glist *glist, - int xpix, int ypix, int shift, int alt, int dbl, int doit) -{ - t_glist *x = (t_glist *)z; - t_gobj *y; - int clickreturned = 0; - if (!x->gl_isgraph) - return (text_widgetbehavior.w_clickfn(z, glist, - xpix, ypix, shift, alt, dbl, doit)); - else if (x->gl_havewindow) - return (0); - else - { - for (y = x->gl_list; y; y = y->g_next) - { - int x1, y1, x2, y2; - /* check if the object wants to be clicked */ - if (canvas_hitbox(x, y, xpix, ypix, &x1, &y1, &x2, &y2) - && (clickreturned = gobj_click(y, x, xpix, ypix, - shift, alt, 0, doit))) - break; - } - if (!doit) - { - if (y) - canvas_setcursor(glist_getcanvas(x), clickreturned); - else canvas_setcursor(glist_getcanvas(x), CURSOR_RUNMODE_NOTHING); - } - return (clickreturned); - } -} - -void garray_properties(t_garray *x); - -t_widgetbehavior graph_widgetbehavior = -{ - graph_getrect, - graph_displace, - graph_select, - graph_activate, - graph_delete, - graph_vis, - graph_click, -}; - -void graph_properties(t_gobj *z, t_glist *owner) -{ - t_glist *x = (t_glist *)z; - { - t_gobj *y; - char graphbuf[200]; - sprintf(graphbuf, "pdtk_graph_dialog %%s %g %g %g %g %d %d\n", - x->gl_x1, x->gl_y1, x->gl_x2, x->gl_y2, - x->gl_pixwidth, x->gl_pixheight); - gfxstub_new(&x->gl_pd, x, graphbuf); - - for (y = x->gl_list; y; y = y->g_next) - if (pd_class(&y->g_pd) == garray_class) - garray_properties((t_garray *)y); - } -} - - /* find the graph most recently added to this glist; - if none exists, return 0. */ - -t_glist *glist_findgraph(t_glist *x) -{ - t_gobj *y = 0, *z; - for (z = x->gl_list; z; z = z->g_next) - if (pd_class(&z->g_pd) == canvas_class && ((t_glist *)z)->gl_isgraph) - y = z; - return ((t_glist *)y); -} - - /* message back from dialog GUI to set parameters. Args are: - 1-4: bounds in our coordinates; 5-6: size in parent */ -static void graph_dialog(t_glist *x, t_symbol *s, int argc, t_atom *argv) -{ - t_float x1 = atom_getfloatarg(0, argc, argv); - t_float y1 = atom_getfloatarg(1, argc, argv); - t_float x2 = atom_getfloatarg(2, argc, argv); - t_float y2 = atom_getfloatarg(3, argc, argv); - t_float xpix = atom_getfloatarg(4, argc, argv); - t_float ypix = atom_getfloatarg(5, argc, argv); - if (x1 != x->gl_x1 || x2 != x->gl_x2 || - y1 != x->gl_y1 || y2 != x->gl_y2) - graph_bounds(x, x1, y1, x2, y2); - if (xpix != x->gl_pixwidth || ypix != x->gl_pixheight) - { - x->gl_pixwidth = xpix; - x->gl_pixheight = ypix; - glist_redraw(x); - if (x->gl_owner) - canvas_fixlinesfor(x->gl_owner, &x->gl_obj); - } -} - -extern void canvas_menuarray(t_glist *canvas); - -void g_graph_setup(void) -{ - class_setwidget(canvas_class, &graph_widgetbehavior); - class_addmethod(canvas_class, (t_method)graph_bounds, gensym("bounds"), - A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); - class_addmethod(canvas_class, (t_method)graph_xticks, gensym("xticks"), - A_FLOAT, A_FLOAT, A_FLOAT, 0); - class_addmethod(canvas_class, (t_method)graph_xlabel, gensym("xlabel"), - A_GIMME, 0); - class_addmethod(canvas_class, (t_method)graph_yticks, gensym("yticks"), - A_FLOAT, A_FLOAT, A_FLOAT, 0); - class_addmethod(canvas_class, (t_method)graph_ylabel, gensym("ylabel"), - A_GIMME, 0); - class_addmethod(canvas_class, (t_method)graph_array, gensym("array"), - A_SYMBOL, A_FLOAT, A_SYMBOL, A_DEFFLOAT, A_NULL); - class_addmethod(canvas_class, (t_method)canvas_menuarray, - gensym("menuarray"), A_NULL); - class_addmethod(canvas_class, (t_method)graph_dialog, gensym("dialog"), - A_GIMME, 0); - class_addmethod(canvas_class, (t_method)glist_arraydialog, - gensym("arraydialog"), A_SYMBOL, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(canvas_class, (t_method)glist_sort, - gensym("sort"), A_NULL); -} |