#include "ext.h" #include "ext_user.h" #include "ext_common.h" fptr *FNS; #define BoolNotEq(a,b) (((a)&&!(b))||((b)&&!(a))) /* inverted button object, like PushButton */ typedef struct _ubutton { t_box b_box; void *b_clock; void *b_qelem; char b_pleaseinvert; char b_inverted; char b_togmode; char b_togstate; char b_hilite; char b_dragtrack; long b_stay; void *b_downoutlet; void *b_upoutlet; void *b_mouseoutlet; void *b_insideoutlet; void *b_idleqelem; } t_ubutton; void *ubutton_class; t_symbol *ps_list; void ubutton_clipregion(t_ubutton *x, RgnHandle *rgn, short *clipresult); void ubutton_int(t_ubutton *x, long n); void ubutton_set(t_ubutton *x, long n); void ubutton_float(t_ubutton *x, double f); void ubuttonblack(t_ubutton *x); void ubuttonwhite(t_ubutton *x); void ubutton_qfn(t_ubutton *x); void ubutton_drag(t_ubutton *x, Point pt, short but); void ubutton_tick(t_ubutton *x); void ubutton_click(t_ubutton *x, Point pt, short modifiers); void ubutton_bang(t_ubutton *x); void ubutton_outletpoint(t_ubutton *x, Point pt); void ubutton_update(t_ubutton *x); void ubutton_psave(t_ubutton *x, void *w); void ubutton_toggle(t_ubutton *x, long way); void ubutton_stay(t_ubutton *x, long n); void ubutton_hilite(t_ubutton *x, long n); void ubutton_dragtrack(t_ubutton *x, long n); void ubutton_assist(t_ubutton *x, void *b, long m, long a, char *s); void ubutton_free(t_ubutton *x); void *ubutton_make(void *patcher, short x, short y, short w, short s, short stay, short toggle); void *ubutton_new(Symbol *s, short ac, Atom *av); void *ubutton_marqdrag(void *p, Point pt, short but); void *ubutton_menu(void *p, long x, long y, long font); void inbox(t_box *b, Rect *r); void SetHilite(void); void main(fptr *f) { setup((t_messlist **)&ubutton_class, (method)ubutton_new, (method)ubutton_free, (short)sizeof(t_ubutton), (method)ubutton_menu, A_GIMME, 0); addint((method)ubutton_int); addfloat((method)ubutton_float); addbang((method)ubutton_bang); addmess((method)ubutton_set, "set", A_LONG, 0); addmess((method)ubutton_update, "update", A_CANT, 0); addmess((method)ubutton_click, "click", A_CANT, 0); addmess((method)ubutton_psave, "psave", A_CANT, 0); addmess((method)ubutton_assist, "assist", A_CANT, 0); addmess((method)ubutton_stay, "stay", A_LONG, 0); addmess((method)ubutton_hilite, "hilite", A_LONG, 0); addmess((method)ubutton_toggle, "toggle", A_LONG, 0); addmess((method)inspector_open, "info", A_CANT, 0); addmess((method)ubutton_bang, "anything", A_GIMME, 0); addmess((method)ubutton_clipregion, "clipregion", A_CANT, 0); addmess((method)ubutton_dragtrack,"dragtrack",A_LONG, 0); rescopy('STR#',3128); //rescopy('DITL',3128); //rescopy('DLOG',3128); ps_list = gensym("list"); } void ubutton_clipregion(t_ubutton *x, RgnHandle *rgn, short *clipresult) { *clipresult = CLIPRGN_EMPTY; } void ubutton_int(t_ubutton *x, long n) { if (x->b_stay) { if (x->b_stay==n) ubuttonblack(x); else ubuttonwhite(x); } else if (x->b_togmode) { if (n) { ubuttonblack(x); outlet_bang(x->b_downoutlet); x->b_togstate = 1; } else { ubuttonwhite(x); outlet_bang(x->b_upoutlet); x->b_togstate = 0; } } else ubutton_bang(x); } void ubutton_set(t_ubutton *x, long n) { if (x->b_stay) { if (x->b_stay==n) ubuttonblack(x); else ubuttonwhite(x); } else if (x->b_togmode) { if (n) { ubuttonblack(x); x->b_togstate = 1; } else { ubuttonwhite(x); x->b_togstate = 0; } } } void ubutton_float(t_ubutton *x, double f) { ubutton_int(x,(long)f); } void ubuttonblack(t_ubutton *x) { x->b_pleaseinvert = 1; qelem_set(x->b_qelem); } void ubuttonwhite(t_ubutton *x) { x->b_pleaseinvert = 0; qelem_set(x->b_qelem); } void ubutton_qfn(t_ubutton *x) { Rect r; GrafPort *gp; Boolean draw; if (x->b_pleaseinvert == x->b_inverted) { return; } x->b_box.b_transparent = 0; if (gp = patcher_setport(x->b_box.b_patcher)) { draw = !box_nodraw((Box *)x); inbox((t_box *)x, &r); if (x->b_pleaseinvert) { if (draw) { SetHilite(); InvertRect(&r); box_enddraw((t_box *)x); } x->b_inverted = 1; } else if (x->b_inverted) { if (draw) { SetHilite(); InvertRect(&r); ubutton_update(x); box_enddraw((t_box *)x); } x->b_inverted = 0; } SetPort(gp); /* bug fix -- was outside bracket */ } x->b_box.b_transparent = 1; } void ubutton_drag(t_ubutton *x, Point pt, short but) { long in = false; short savelock; if (PtInRect(pt,&x->b_box.b_rect)) { in = true; if (x->b_hilite) ubuttonblack(x); } else { if (x->b_hilite) ubuttonwhite(x); } if (x->b_dragtrack || !but) { savelock = lockout_set(true); outlet_int(x->b_insideoutlet,in); ubutton_outletpoint(x,pt); lockout_set(savelock); } if (!but) { if (in) { savelock = lockout_set(true); outlet_bang(x->b_upoutlet); lockout_set(savelock); } if (x->b_hilite) ubuttonwhite(x); } } void ubutton_tick(t_ubutton *x) { ubuttonwhite(x); /* bug fix */ } void ubutton_click(t_ubutton *x, Point pt, short modifiers) { Rect *r; char savelock; long val; r = &x->b_box.b_rect; val = PtInRect(pt,r); if (x->b_togmode) { savelock = lockout_set(1); outlet_int(x->b_insideoutlet,val); ubutton_outletpoint(x,pt); ubutton_bang(x); lockout_set(savelock); } else { savelock = lockout_set(1); outlet_int(x->b_insideoutlet,val); ubutton_outletpoint(x,pt); outlet_bang(x->b_downoutlet); lockout_set(savelock); if (x->b_hilite) ubuttonblack(x); /* blacken picture until mouse released */ wind_drag((method)ubutton_drag, x, pt); } } void ubutton_bang(t_ubutton *x) { if (x->b_togmode) { if (!x->b_togstate) { ubuttonblack(x); outlet_bang(x->b_downoutlet); x->b_togstate = 1; } else { ubuttonwhite(x); outlet_bang(x->b_upoutlet); x->b_togstate = 0; } } else { if (x->b_hilite) { if (!x->b_inverted) ubuttonblack(x); clock_delay(x->b_clock,150L); } outlet_bang(x->b_upoutlet); /* message sent out left most outlet */ } } void ubutton_outletpoint(t_ubutton *x, Point pt) { t_atom argv[2]; SETLONG(argv,pt.h - x->b_box.b_rect.left); SETLONG(argv+1,pt.v - x->b_box.b_rect.top); outlet_list(x->b_mouseoutlet,ps_list,2,argv); } void ubutton_update(t_ubutton *x) { Rect r,*br; Pattern p28; inbox((t_box *)x, &r); if ((x->b_togmode && x->b_togstate) || (x->b_inverted && x->b_pleaseinvert)) { SetHilite(); InvertRect(&r); } if (!box_ownerlocked(&x->b_box)) { br = &x->b_box.b_rect; if (br->right - br->left < 8) { box_size(x,8,br->bottom - br->top); } if (br->bottom - br->top < 8) { box_size(x,br->right - br->left,8); } GetIndPattern(&p28,sysPatListID,4); PenPat(&p28); /* gray actually */ FrameRect(&x->b_box.b_rect); PenNormal(); GetIndPattern(&p28,sysPatListID,28); InsetRect(&r,2,2); FillRect(&r,&p28); } } void ubutton_psave(t_ubutton *x, void *w) { Rect *r; long flags; r = &x->b_box.b_rect; flags = x->b_togmode ? 1 : 0; flags |= x->b_hilite ? 0 : 2; flags |= x->b_dragtrack? 4 : 0; if (x->b_box.b_hidden) { binbuf_vinsert(w,"ssssllllll", gensym("#P"),gensym("hidden"),gensym("user"), gensym("ubutton"), (long)(r->left), (long)(r->top), (long)(r->right - r->left), (long)(r->bottom - r->top),x->b_stay, (long)flags); } else { binbuf_vinsert(w,"sssllllll", gensym("#P"),gensym("user"), gensym("ubutton"), (long)(r->left), (long)(r->top), (long)(r->right - r->left), (long)(r->bottom - r->top),x->b_stay, (long)flags); } } void ubutton_toggle(t_ubutton *x, long way) { if (BoolNotEq(x->b_togmode,way)) { ubuttonwhite(x); } x->b_togmode = way; x->b_togstate = 0; if (way) x->b_stay = 0; } void ubutton_stay(t_ubutton *x, long n) { x->b_stay = n; if (n) ubutton_toggle(x,0L); } void ubutton_hilite(t_ubutton *x, long n) { x->b_hilite = n ? 1 : 0; } void ubutton_dragtrack(t_ubutton *x, long n) { x->b_dragtrack = n? 1 : 0; } void ubutton_assist(t_ubutton *x, void *b, long m, long a, char *s) { assist_string(3128,m,a,1,2,s); } void ubutton_free(t_ubutton *x) { notify_free((t_object *)x); freeobject(x->b_clock); qelem_free(x->b_qelem); box_free((Box *)x); } void *ubutton_make(void *patcher, short x, short y, short w, short s, short stay, short flags) { t_ubutton *p; p = (t_ubutton *)newobject(ubutton_class); p->b_clock = clock_new(p, (method)ubutton_tick); p->b_qelem = qelem_new(p, (method)ubutton_qfn); p->b_inverted = 0; box_new((Box *)p, patcher, F_DRAWFIRSTIN | F_GROWBOTH | F_NODRAWBOX | F_TRANSPARENT | F_SAVVY, x, y, x+w, y+s); p->b_insideoutlet = intout((t_object *)p); p->b_mouseoutlet = outlet_new(p,0); p->b_downoutlet = outlet_new(p,"bang"); p->b_upoutlet = outlet_new(p,"bang"); p->b_box.b_firstin = p; p->b_stay = stay; p->b_togmode = flags & 1; p->b_togstate = 0; p->b_hilite = flags & 2 ? 0 : 1; p->b_dragtrack = flags & 4? 1 : 0; box_ready((Box *)p); return (p); } void *ubutton_new(Symbol *s, short ac, Atom *av) { void *p,*res; p = av[0].a_w.w_obj; av++; ac--; res = patchbox(p, (method)ubutton_make, ac, av, SIZE1); return (res); } Point m_last; short firstTime; Rect marqRect; void *ubutton_marqdrag(void *p, Point pt, short but) { Pattern gry; void *x = 0; Boolean draw = TRUE; Rect newRect; patcher_setport(p); newRect = marqRect; if (pt.h > marqRect.left + 8 && pt.v > marqRect.top + 8) { newRect.right = pt.h; newRect.bottom = pt.v; } else firstTime = TRUE; if (!firstTime) { PenMode(patXor); GetIndPattern(&gry,sysPatListID,26); PenPat(&gry); /* gray actually */ FrameRect(&marqRect); PenNormal(); } else firstTime = FALSE; if (but) { if (!EqualRect(&newRect,&marqRect)) { marqRect = newRect; PenMode(patXor); GetIndPattern(&gry,sysPatListID,26); PenPat(&gry); /* gray actually */ FrameRect(&marqRect); PenNormal(); } } else { if (marqRect.right > marqRect.left+1 && marqRect.bottom > marqRect.top+1) x = ubutton_make(p,marqRect.left,marqRect.top,MAX(marqRect.right-marqRect.left,10), MAX(marqRect.bottom-marqRect.top,10),0,0); } return (x); } void *ubutton_menu(void *p, long x, long y, long font) { void *res; Pattern gry; Point pt; t_ubutton *obj = 0; SetRect(&marqRect,(short)x,(short)y,(short)x+18,(short)y+18); pt.h = x; pt.v = y; firstTime = TRUE; m_last = pt; PenMode(patXor); GetIndPattern(&gry,sysPatListID,26); PenPat(&gry); /* gray actually */ FrameRect(&marqRect); PenNormal(); while (StillDown()) { GetMouse(&pt); if (!EqualPt(pt,m_last)) { ubutton_marqdrag(p,pt,1); m_last = pt; } } obj = ubutton_marqdrag(p,pt,0); return (obj); } /* utility */ void inbox(t_box *b, Rect *r) { Rect *r2 = &b->b_rect; r->top = r2->top+1; r->left = r2->left+1; r->bottom = r2->bottom-1; r->right = r2->right-1; } void SetHilite(void) { LMSetHiliteMode(0); }