summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/g_graph.c
diff options
context:
space:
mode:
authorPeter D'Hoye <peter.dhoye@gmail.com>2009-05-24 21:28:16 +0000
committerPeter D'Hoye <peter.dhoye@gmail.com>2009-05-24 21:28:16 +0000
commit526b5580dabbfed7cfe5439dc3a90ec727f563c2 (patch)
tree22b1af92348785daad16714ee5e2b633017e0e48 /apps/plugins/pdbox/PDa/src/g_graph.c
parent4f2dfcc01b260d946044ef2b6af5fe36cb772c8d (diff)
downloadrockbox-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.c1111
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);
-}