#include "flguiobj.h" #include #include #include #include #define USETAGS #define BUFSIZE 20000 #define ZONE 1000 #if FLEXT_SYS == FLEXT_SYS_PD bool FCanvas::store = true; bool FCanvas::debug = false; #endif FCanvas::FCanvas(t_canvas *c): canvas(c) #if FLEXT_SYS == FLEXT_SYS_PD ,buffer(new char[BUFSIZE]),bufix(0),waiting(0) #endif {} FCanvas::~FCanvas() { #if FLEXT_SYS == FLEXT_SYS_PD if(buffer) delete[] buffer; #endif } #if FLEXT_SYS == FLEXT_SYS_PD void FCanvas::Send(const char *t) { if(debug) post("GUI - %s",t); sys_gui((char *)t); } void FCanvas::SendBuf() { if(bufix) { Send(buffer); bufix = 0; } } void FCanvas::ToBuf(const char *t) { int len = strlen(t); if(!len) return; bool end = t[len-1] == '\n'; if((store && waiting) || !end) { int nxt = bufix+len; if(nxt >= BUFSIZE || (end && nxt >= BUFSIZE-ZONE)) SendBuf(); memcpy(buffer+bufix,t,len); buffer[bufix += len] = 0; } else { SendBuf(); Send(t); } } FCanvas &FCanvas::TkC() { char tmp[20]; sprintf(tmp,".x%x.c ",canvas); ToBuf(tmp); return *this; } FCanvas &FCanvas::TkE() { ToBuf("\n"); return *this; } FCanvas &FCanvas::Tk(char *fmt,...) { // int result, i; char buf[2048]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); ToBuf(buf); va_end(ap); return *this; } #endif bool FCanvas::Pre(int x,int y) { xpos = x,ypos = y; #if FLEXT_SYS == FLEXT_SYS_PD ++waiting; return true; #else svgp = patcher_setport(canvas); if(svgp != NULL) { GetForeColor(&svcol); GetPenState(&svpen); ::PenMode(patCopy); return true; } else return false; #endif } void FCanvas::Post() { #if FLEXT_SYS == FLEXT_SYS_PD if(!--waiting) SendBuf(); #else if(svgp) { RGBForeColor(&svcol); SetPenState(&svpen); SetPort(svgp); } #endif } // -------------------------------------------------------------------------- FRect &FRect::Add(const FPnt &p) { if(p.x < lo.x) lo.x = p.x; if(p.y < lo.y) lo.y = p.y; if(p.x > hi.x) hi.x = p.x; if(p.y > hi.y) hi.y = p.y; return *this; } FRect &FRect::Add(const FRect &r) { if(r.lo.x < lo.x) lo.x = r.lo.x; if(r.lo.y < lo.y) lo.y = r.lo.y; if(r.hi.x > hi.x) hi.x = r.hi.x; if(r.hi.y > hi.y) hi.y = r.hi.y; return *this; } bool FRect::In(const FPnt &p) const { return p.x >= lo.x && p.x <= hi.x && p.y >= lo.y && p.y <= hi.y; } bool FRect::Inter(const FRect &r) const { return true; } // -------------------------------------------------------------------------- GuiObj::GuiObj(FCanvas *c,GuiGroup *p): canvas(c),idsym(NULL), parent(p) // ,ori(0,0) {} GuiObj::~GuiObj() { // Delete(); } // -------------------------------------------------------------------------- GuiSingle::Event::Event(int evmask,bool (*m)(flext_gui &g,GuiSingle &obj,const flext_gui::CBParams &p)): methfl(evmask),method(m),ext(false),nxt(NULL) {} GuiSingle::Event::~Event() { if(nxt) delete nxt; } GuiSingle::GuiSingle(FCanvas *c,GuiGroup *p,const t_symbol *s): GuiObj(c,p),sym(s),active(false),event(NULL) { char tmp[20]; #ifdef __MWERKS__ std:: #endif sprintf(tmp,"GUI%x",this); idsym = MakeSymbol(tmp); } GuiSingle::~GuiSingle() { Delete(); if(event) delete event; } void GuiSingle::Symbol(const t_symbol *s) { sym = s; } GuiSingle *GuiSingle::Find(const t_symbol *s) { return sym == s?this:NULL; } GuiObj &GuiSingle::MoveTo(int x,int y) { #if FLEXT_SYS == FLEXT_SYS_PD if(active) { canvas->TkC().Tk("coords %s %i %i\n",GetString(Id()), x, y); } #endif rect.MoveTo(x,y); return *this; } GuiObj &GuiSingle::MoveRel(int dx,int dy) { #if FLEXT_SYS == FLEXT_SYS_PD if(active) { canvas->TkC().Tk("move %s %i %i\n",GetString(Id()), dx, dy); } #endif rect.Move(dx,dy); return *this; } GuiObj &GuiSingle::Delete() { #if FLEXT_SYS == FLEXT_SYS_PD if(active) { canvas->TkC().Tk("delete -tags %s\n",GetString(Id())); active = false; } #endif return *this; } GuiObj &GuiSingle::FillColor(unsigned long col) { #if FLEXT_SYS == FLEXT_SYS_PD if(active) { canvas->TkC().Tk("itemconfigure %s -fill #%06x\n",GetString(Id()),col); } #endif return *this; } GuiObj &GuiSingle::Outline(unsigned long col) { #if FLEXT_SYS == FLEXT_SYS_PD if(active) { canvas->TkC().Tk("itemconfigure %s -outline #%06x\n",GetString(Id()),col); } #endif return *this; } GuiObj &GuiSingle::Focus() { #if FLEXT_SYS == FLEXT_SYS_PD if(active) { canvas->TkC().Tk("focus %s\n",GetString(Id())); } #endif return *this; } bool GuiSingle::Method(flext_gui &g,const flext_gui::CBParams &p) { bool ret = true; for(Event *ei = event; ei && ret; ei = ei->nxt) ret = ret && ((ei->method && (ei->methfl&p.kind))?ei->method(g,*this,p):true); return ret; } void GuiSingle::AddEvent(int evmask,bool (*m)(flext_gui &g,GuiSingle &obj,const flext_gui::CBParams &p)) { Event *prv = NULL,*ix = event; for(; ix && ix->method != m; prv = ix,ix = ix->nxt) {} if(ix) // previous handler found -> update event mask ix->methfl |= evmask; else { // no previous handler was found -> make new one Event *nev = new Event(evmask,m); if(prv) prv->nxt = nev; else event = nev; } } void GuiSingle::RmvEvent(int evmask,bool (*m)(flext_gui &g,GuiSingle &obj,const flext_gui::CBParams &p)) { Event *prv = NULL,*ix = event; for(; ix && ix->method != m; prv = ix,ix = ix->nxt) {} if(ix) { // handler found if(!(ix->methfl &= ~evmask)) { // mask has become zero -> remove handler if(prv) prv->nxt = ix->nxt; else event = ix->nxt; ix->nxt = NULL; delete ix; } } } // -------------------------------------------------------------------------- GuiGroup::GuiGroup(FCanvas *c,GuiGroup *p): GuiObj(c,p),head(NULL),tail(NULL) { char tmp[20]; #ifdef __MWERKS__ std:: #endif sprintf(tmp,"GRP%x",this); idsym = MakeSymbol(tmp); } GuiGroup::~GuiGroup() { Clear(); } void GuiGroup::Clear() { for(Part *ix = head; ix; ) { Part *n = ix->nxt; #if FLEXT_SYS == FLEXT_SYS_PD RemoveTag(ix->obj); #endif if(ix->owner) delete ix->obj; delete ix; ix = n; } head = tail = NULL; } void GuiGroup::Add(GuiObj *o,bool owner) { o->canvas = canvas; #if FLEXT_SYS == FLEXT_SYS_PD AddTag(o); // valid only for GuiSingle! #endif Part *n = new Part(o,owner); if(!head) head = n; else tail->nxt = n; tail = n; rect.Add(o->rect); } GuiSingle *GuiGroup::Find(const t_symbol *s) { GuiSingle *r = NULL; for(Part *ix = head; ix && !r; ix = ix->nxt) { r = ix->obj->Find(s); } return r; } GuiSingle *GuiGroup::Detach(const t_symbol *s) { if(head) { Part *p = NULL,*ix = head; while(ix) { if(ix->obj->Symbol() == s) { // found if(p) p->nxt = ix->nxt; GuiSingle *ret = (GuiSingle *)(ix->obj); #if FLEXT_SYS == FLEXT_SYS_PD RemoveTag(ret); #endif if(head == ix) head = ix->nxt; if(tail == ix) tail = p; delete ix; return ret; } else p = ix,ix = ix->nxt; } } return NULL; } GuiObj &GuiGroup::MoveRel(int dx,int dy) { #if FLEXT_SYS == FLEXT_SYS_PD canvas->TkC().Tk("move %s %i %i\n",GetString(Id()), dx, dy); #endif for(Part *ix = head; ix; ix = ix->nxt) { ix->obj->rect.Move(dx,dy); } return *this; } GuiObj &GuiGroup::Delete() { #if FLEXT_SYS == FLEXT_SYS_PD canvas->TkC().Tk("delete -tags %s\n",GetString(Id())); for(Part *ix = head; ix; ix = ix->nxt) ix->obj->Inactive(); #endif return *this; } GuiObj &GuiGroup::Draw() { for(Part *ix = head; ix; ix = ix->nxt) ix->obj->Draw(); return *this; } #if FLEXT_SYS == FLEXT_SYS_PD void GuiGroup::AddTag(GuiObj *o) { canvas->TkC().Tk("addtag %s withtag %s\n",GetString(Id()),GetString(o->Id())); } void GuiGroup::RemoveTag(GuiObj *o) { canvas->TkC().Tk("dtag %s %s\n",GetString(o->Id()),GetString(Id())); } #endif GuiGroup *GuiGroup::Add_Group() { GuiGroup *obj = new GuiGroup(canvas,this); Add(obj); return obj; } GuiSingle *GuiGroup::Add_Point(int x,int y,long fill) { GuiPoint *obj = new GuiPoint(canvas,this); obj->Set(x,y,fill); Add(obj); return obj; } GuiSingle *GuiGroup::Add_Cloud(int n,const FPnt *p,long fill) { GuiCloud *obj = new GuiCloud(canvas,this); obj->Set(n,p,fill); Add(obj); return obj; } GuiSingle *GuiGroup::Add_Box(int x,int y,int xsz,int ysz,int width,long fill,long outl) { GuiBox *obj = new GuiBox(canvas,this); obj->Set(x,y,xsz,ysz,width,fill,outl); Add(obj); return obj; } GuiSingle *GuiGroup::Add_Rect(int x,int y,int xsz,int ysz,int width,long outl) { GuiRect *obj = new GuiRect(canvas,this); obj->Set(x,y,xsz,ysz,width,outl); Add(obj); return obj; } GuiSingle *GuiGroup::Add_Line(int x1,int y1,int x2,int y2,int width,long fill) { GuiLine *obj = new GuiLine(canvas,this); obj->Set(x1,y1,x2,y2,width,fill); Add(obj); return obj; } GuiSingle *GuiGroup::Add_Poly(int n,const FPnt *p,int width,long fill) { GuiPoly *obj = new GuiPoly(canvas,this); obj->Set(n,p,width,fill); Add(obj); return obj; } GuiSingle *GuiGroup::Add_Text(int x,int y,const char *txt,long fill,GuiText::just_t just) { GuiText *obj = new GuiText(canvas,this); obj->Set(x,y,txt,fill,just); Add(obj); return obj; } GuiSingle *GuiGroup::Remove(GuiSingle *go) { for(Part *prv = NULL,*ix = head; ix; prv = ix,ix = ix->nxt) if(ix->obj == go) { if(prv) prv->nxt = ix->nxt; else head = ix->nxt; if(!head) tail = NULL; GuiObj *ret = ix->obj; delete ix; if(head) { rect = head->obj->rect; for(ix = head->nxt; ix; ix = ix->nxt) rect.Add(ix->obj->rect); } return (GuiSingle *)ret; } return NULL; } bool GuiGroup::Method(flext_gui &g,const flext_gui::CBParams &p) { bool go = true; for(Part *ix = head; go && ix; ix = ix->nxt) go = go && ix->obj->Method(g,p); return go; } // -------------------------------------------------------------------------- GuiObj &GuiPoint::Set(int x,int y,long fl) { Delete(); fill = fl; rect(x,y,x,y); #if FLEXT_SYS == FLEXT_SYS_PD canvas->TkC(); canvas->Tk("create line %i %i %i %i -tags %s",x,y,x+1,y,GetString(Id())); if(fill >= 0) canvas->Tk(" -fill #%06x",fill); canvas->TkE(); active = true; #endif return *this; } GuiObj &GuiPoint::Draw() { #if FLEXT_SYS == FLEXT_SYS_MAX #endif return *this; } GuiObj &GuiCloud::Set(int n,const FPnt *p,long fl) { int i; Delete(); fill = fl; pnt = new FPnt[pnts = n]; rect(pnt[0] = p[0],p[0]); for(i = 1; i < n; ++i) rect.Add(pnt[i] = p[i]); #if FLEXT_SYS == FLEXT_SYS_PD canvas->TkC().Tk("create line"); for(i = 0; i < n; ++i) canvas->Tk(" %i %i",p[i].X(),p[i].Y()); canvas->Tk(" -tags %s",GetString(Id())); if(fill >= 0) canvas->Tk(" -fill #%06x",fill); canvas->TkE(); active = true; #endif return *this; } GuiObj &GuiCloud::Draw() { #if FLEXT_SYS == FLEXT_SYS_MAX #endif return *this; } GuiObj &GuiCloud::Delete() { if(pnt) { delete[] pnt; pnt = NULL; } return *this; } GuiObj &GuiBox::Set(int x,int y,int xsz,int ysz,int wd,long fl,long outl) { Delete(); rect(x,y,x+xsz-1,y+ysz-1); width = wd,fill = fl,outln = outl; #if FLEXT_SYS == FLEXT_SYS_PD canvas->TkC().Tk("create rectangle %i %i %i %i -tags %s",x,y,x+xsz,y+ysz,GetString(Id())); if(wd >= 0) canvas->Tk(" -width %i",wd); if(fl >= 0) canvas->Tk(" -fill #%06x",fl); if(outl >= 0) canvas->Tk(" -outline #%06x",outl); canvas->TkE(); active = true; #endif return *this; } GuiObj &GuiBox::Draw() { #if FLEXT_SYS == FLEXT_SYS_MAX ::Rect r; ::RGBColor col; int w = width; if(!w) w = 1; r.left = Canv().X()+rect.Lo().X(); r.top = Canv().Y()+rect.Lo().Y(); r.right = Canv().X()+rect.Hi().X(); r.bottom = Canv().Y()+rect.Hi().Y(); if(width >= 0) { col.red = (outln>>8)&0xff00; col.green = outln&0xff00; col.blue = (outln&0xff)<<8; ::RGBForeColor(&col); ::PenSize(w,w); ::FrameRect(&r); } col.red = (fill>>8)&0xff00; col.green = fill&0xff00; col.blue = (fill&0xff)<<8; ::RGBForeColor(&col); ::PaintRect(&r); #endif return *this; } GuiObj &GuiRect::Set(int x,int y,int xsz,int ysz,int wd,long outl) { Delete(); rect(x,y,x+xsz-1,y+ysz-1); width = wd,outln = outl; #if FLEXT_SYS == FLEXT_SYS_PD canvas->TkC().Tk("create line %i %i %i %i %i %i %i %i %i %i -tags %s",x,y,x+xsz,y,x+xsz,y+ysz,x,y+ysz,x,y,GetString(Id())); if(width >= 0) canvas->Tk(" -width %i",width); if(outl >= 0) canvas->Tk(" -fill #%06x",outl); canvas->TkE(); active = true; #endif return *this; } GuiObj &GuiRect::Draw() { #if FLEXT_SYS == FLEXT_SYS_MAX #endif return *this; } GuiObj &GuiLine::Set(int x1,int y1,int x2,int y2,int wd,long fl) { Delete(); rect(p1(x1,y1),p2(x2,y2)); width = wd,fill = fl; #if FLEXT_SYS == FLEXT_SYS_PD canvas->TkC().Tk("create line %i %i %i %i -tags %s",x1,y1,x2,y2,GetString(Id())); if(width >= 0) canvas->Tk(" -width %i",width); if(fill >= 0) canvas->Tk(" -fill #%06x",fill); canvas->TkE(); active = true; #endif return *this; } GuiObj &GuiLine::Draw() { #if FLEXT_SYS == FLEXT_SYS_MAX ::Point p; ::RGBColor col; int w = width; if(!w) w = 1; col.red = (fill>>8)&0xff00; col.green = fill&0xff00; col.blue = (fill&0xff)<<8; ::RGBForeColor(&col); ::PenSize(w,w); p.h = Canv().X()+p1.X(); p.v = Canv().Y()+p1.Y(); ::MoveTo(p.h,p.v); p.h = Canv().X()+p2.X(); p.v = Canv().Y()+p2.Y(); ::LineTo(p.h,p.v); #endif return *this; } GuiObj &GuiPoly::Set(int n,const FPnt *p,int wd,long fl) { int i; Delete(); width = wd,fill = fl; pnt = new FPnt[pnts = n]; rect(pnt[0] = p[0],p[0]); for(i = 1; i < n; ++i) rect.Add(pnt[i] = p[i]); #if FLEXT_SYS == FLEXT_SYS_PD canvas->TkC().Tk("create line"); for(i = 0; i < n; ++i) canvas->Tk(" %i %i",p[i].X(),p[i].Y()); canvas->Tk(" -tags %s",GetString(Id())); if(width >= 0) canvas->Tk(" -width %i",width); if(fill >= 0) canvas->Tk(" -fill #%06x",fill); canvas->TkE(); active = true; #endif return *this; } GuiObj &GuiPoly::Draw() { #if FLEXT_SYS == FLEXT_SYS_MAX ::Point p; ::RGBColor col; int ox = Canv().X(),oy = Canv().Y(); int w = width; if(!w) w = 1; col.red = (fill>>8)&0xff00; col.green = fill&0xff00; col.blue = (fill&0xff)<<8; ::RGBForeColor(&col); ::PenSize(w,w); p.h = ox+pnt[0].X(); p.v = oy+pnt[0].Y(); ::MoveTo(p.h,p.v); for(int i = 1; i < pnts; ++i) { p.h = ox+pnt[i].X(); p.v = oy+pnt[i].Y(); ::LineTo(p.h,p.v); } #endif return *this; } GuiObj &GuiPoly::Delete() { if(pnt) { delete[] pnt; pnt = NULL; } return *this; } GuiObj &GuiText::Set(int x,int y,const char *txt,long fl,just_t jt) { Delete(); rect(x,y,x,y); fill = fl,just = jt; #if FLEXT_SYS == FLEXT_SYS_PD canvas->TkC().Tk("create text %i %i -tags %s",x,y,GetString(Id())); if(txt) canvas->Tk(" -text %s",txt); if(fill >= 0) canvas->Tk(" -fill #%06x",fill); if(just != none) { static const char justtxt[][7] = {"left","right","center"}; canvas->Tk(" -justify %s",justtxt[(int)just]); } canvas->TkE(); active = true; #endif return *this; } GuiObj &GuiText::Draw() { #if FLEXT_SYS == FLEXT_SYS_MAX #endif return *this; }