///////////////////////////////////////////////////////////////////////////// // // This file is Copyright 1992,1993 by Warwick W. Allison. // This file is part of the gem++ library. // You are free to copy and modify these sources, provided you acknowledge // the origin by retaining this notice, and adhere to the conditions // described in the file COPYING.LIB. // ///////////////////////////////////////////////////////////////////////////// #include #include #include "gemf.h" #include "gemo.h" #include "geme.h" #include "gemr.h" GEMform::GEMform(const GEMrsc& in, int RSCindex) : myindex(RSCindex), ZoomOn(FALSE) { Obj=in.Tree(myindex); AlignObject(ROOT,1,1); } static int global_count; static GEMrawobject* global_obj; static int CountObj(GEMrawobject* o, int i) { global_count++; return -1; } // Why is "foo=bar" different from "foo=GEMrawobject(bar)"? static int CopyObj(GEMrawobject* o, int i) { global_obj[i]=GEMrawobject(o[i]); return -1; } //static int CopyObj(GEMrawobject* o, int i) { global_obj[i]=o[i]; return -1; } GEMform::GEMform(const GEMform& copy) : myindex(copy.myindex), ZoomOn(copy.ZoomOn), xoffset(copy.xoffset), yoffset(copy.yoffset), xmult(copy.xmult), ymult(copy.ymult) { global_count=0; // CountObj doesn't modify copy, so safe to cast off constness ((GEMform&)copy).Map(CountObj,FALSE); Obj=new GEMrawobject[global_count]; global_obj=Obj; ((GEMform&)copy).Map(CopyObj,FALSE); } GEMform::~GEMform() { } static int FindEdit(GEMrawobject* o, int i) { return o[i].Editable() ? i : -1; } int GEMform::FormDo() { int edit=Map(FindEdit,TRUE); return form_do(Obj,edit); } int GEMform::Do() { int x,y,w,h; form_center(Obj,&x,&y,&w,&h); return Do(x,y); } int GEMform::Do(int x, int y) { int X,Y,w,h; int bx,by,bw,bh; wind_get(0,WF_WORKXYWH,&bx,&by,&bw,&bh); // We use form_center, because it accounts for outline width. form_center(Obj,&X,&Y,&w,&h); if (w < bw) { // Can't do anything if it fills the width // We cancel the "centering" effect - just need w. Obj[ROOT].MoveBy(x-X,0); // Then, align the object tree, AND adjust the save-area/clip accordingly. int dx=(Obj[ROOT].X()+xoffset+xmult/2)/xmult*xmult-xoffset-Obj[ROOT].X(); x+=dx; Obj[ROOT].MoveBy(dx,0); // But... make sure it is within the root window (if possible without resizing) if (x+w > bx+bw) { // Off right side - flushright. dx=(bx+bw)-(x+w); } else if (x by+bh) { dy=(by+bh)-(y+h); } else if (y=0 && Obj[n].Tail()!=o); return n; } void GEMform::AlignObject(int RSCindex, int xmlt=8, int ymlt=1) { int x,y; objc_offset(Obj,RSCindex,&x,&y); int rx,ry; objc_offset(Obj,ROOT,&rx,&ry); xoffset=x-rx; yoffset=y-ry; xmult=xmlt; ymult=ymlt; } /* Non-cursive traverse of an object tree. */ int GEMform::Map(int Do(GEMrawobject*, int), bool skiphidden, int RSCfrom, int RSCto) { int tmp = RSCfrom; // Initialize to impossible value // Look until final node, or off // the end of tree while (RSCfrom != RSCto && RSCfrom >= 0) { // Did we 'pop' into RSCfrom node for the second time? // Is this subtree hidden? if (Obj[RSCfrom].Tail() == tmp || (skiphidden && Obj[RSCfrom].HideTree())) { // Yes - move right. tmp = RSCfrom; RSCfrom = Obj[tmp].Next(); } else { // No, this is a new node tmp = RSCfrom; RSCfrom = -1; // Apply operation int reply=Do(Obj, tmp); // Found object to return? if (reply>=0) return reply; // Traverse subtree? if (reply==-1) RSCfrom = Obj[tmp].Head(); // Traverse right if nowhere to go if (RSCfrom < 0) RSCfrom = Obj[tmp].Next(); } } return -1; } GEMfeedback GEMform::DoItem(int obj, const GEMevent& e) { GEMfeedback result=IgnoredClick; // CallBacks GEMobject* O=operator[](obj).Cook(); if (O) { int ox,oy; objc_offset(Obj,obj,&ox,&oy); result=O->Touch(e.X()-ox,e.Y()-oy,e); switch (result) { case RedrawMe: RedrawObject(obj); break; case RedrawMyParent: RedrawObject(Parent(obj)); break; default: ; } } return result; }