home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / program / gempp15b / gemf.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-23  |  5.8 KB  |  270 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  This file is Copyright 1992,1993 by Warwick W. Allison.
  4. //  This file is part of the gem++ library.
  5. //  You are free to copy and modify these sources, provided you acknowledge
  6. //  the origin by retaining this notice, and adhere to the conditions
  7. //  described in the file COPYING.LIB.
  8. //
  9. /////////////////////////////////////////////////////////////////////////////
  10.  
  11. #include <aesbind.h>
  12. #include <values.h>
  13. #include "gemf.h"
  14. #include "gemo.h"
  15. #include "geme.h"
  16. #include "gemr.h"
  17.  
  18.  
  19. GEMform::GEMform(const GEMrsc& in, int RSCindex) :
  20.     myindex(RSCindex),
  21.     ZoomOn(FALSE)
  22. {
  23.     Obj=in.Tree(myindex);
  24.     AlignObject(ROOT,1,1);
  25. }
  26.  
  27. static int global_count;
  28. static GEMrawobject* global_obj;
  29. static int CountObj(GEMrawobject* o, int i) { global_count++; return -1; }
  30.  
  31. // Why is "foo=bar" different from "foo=GEMrawobject(bar)"?
  32. static int CopyObj(GEMrawobject* o, int i) { global_obj[i]=GEMrawobject(o[i]); return -1; }
  33. //static int CopyObj(GEMrawobject* o, int i) { global_obj[i]=o[i]; return -1; }
  34.  
  35. GEMform::GEMform(const GEMform& copy) :
  36.     myindex(copy.myindex),
  37.     ZoomOn(copy.ZoomOn),
  38.     xoffset(copy.xoffset),
  39.     yoffset(copy.yoffset),
  40.     xmult(copy.xmult),
  41.     ymult(copy.ymult)
  42. {
  43.     global_count=0;
  44.  
  45.     // CountObj doesn't modify copy, so safe to cast off constness
  46.     ((GEMform&)copy).Map(CountObj,FALSE);
  47.  
  48.     Obj=new GEMrawobject[global_count];
  49.     global_obj=Obj;
  50.  
  51.     ((GEMform&)copy).Map(CopyObj,FALSE);
  52. }
  53.  
  54. GEMform::~GEMform()
  55. {
  56. }
  57.  
  58. static int FindEdit(GEMrawobject* o, int i)
  59. {
  60.     return o[i].Editable() ? i : -1;
  61. }
  62.  
  63. int GEMform::FormDo()
  64. {
  65.     int edit=Map(FindEdit,TRUE);
  66.     return form_do(Obj,edit);
  67. }
  68.  
  69. int GEMform::Do()
  70. {
  71.     int x,y,w,h;
  72.     form_center(Obj,&x,&y,&w,&h);
  73.     return Do(x,y);
  74. }
  75.  
  76. int GEMform::Do(int x, int y)
  77. {
  78.     int X,Y,w,h;
  79.  
  80.     int bx,by,bw,bh;
  81.     wind_get(0,WF_WORKXYWH,&bx,&by,&bw,&bh);
  82.  
  83.     // We use form_center, because it accounts for outline width.
  84.     form_center(Obj,&X,&Y,&w,&h);
  85.  
  86.     if (w < bw) { // Can't do anything if it fills the width
  87.         // We cancel the "centering" effect - just need w.
  88.         Obj[ROOT].MoveBy(x-X,0);
  89.  
  90.         // Then, align the object tree, AND adjust the save-area/clip accordingly.
  91.         int dx=(Obj[ROOT].X()+xoffset+xmult/2)/xmult*xmult-xoffset-Obj[ROOT].X();
  92.         x+=dx;
  93.         Obj[ROOT].MoveBy(dx,0);
  94.  
  95.         // But... make sure it is within the root window (if possible without resizing)
  96.         if (x+w > bx+bw) {
  97.             // Off right side - flushright.
  98.             dx=(bx+bw)-(x+w);
  99.         } else if (x<bx) {
  100.             // Off left side - flushleft.
  101.             dx=bx-x;
  102.         } else {
  103.             dx=0;
  104.         }
  105.  
  106.         x+=dx;
  107.         Obj[ROOT].MoveBy(dx,0);
  108.     }
  109.  
  110.     if (h < bh) { // Can't do anything if it fills the height
  111.         // Then we cancel the "centering" effect - just need (w,h).
  112.         Obj[ROOT].MoveBy(0,y-Y);
  113.  
  114.         // Then, align the object tree, AND adjust the save-area/clip accordingly.
  115.         int dy=(Obj[ROOT].Y()+yoffset+ymult/2)/ymult*ymult-yoffset-Obj[ROOT].Y();
  116.         Obj[ROOT].MoveBy(0,dy);
  117.         y+=dy;
  118.  
  119.         // But... make sure it is within the root window (if possible without resizing)
  120.         if (y+h > by+bh) {
  121.             dy=(by+bh)-(y+h);
  122.         } else if (y<by) {
  123.             dy=by-y;
  124.         } else {
  125.             dy=0;
  126.         }
  127.  
  128.         y+=dy;
  129.         Obj[ROOT].MoveBy(0,dy);
  130.     }
  131.  
  132.     wind_update(BEG_UPDATE);
  133.  
  134.     form_dial(FMD_START,0,0,0,0,x,y,w,h);
  135.     if (ZoomOn) form_dial(FMD_GROW,0,0,0,0,x,y,w,h);
  136.  
  137.     objc_draw(Obj, ROOT, MAX_DEPTH, x, y, w, h);
  138.  
  139.     GEMfeedback NowWhat=ContinueInteraction;
  140.     int exitor=0;
  141.  
  142.     while (NowWhat!=EndInteraction) {
  143.         // The guts of the interaction is virtual
  144.         exitor=FormDo();
  145.  
  146.         // But the response handling is not... until the DoItem().
  147.         if (exitor != -1) {
  148.             exitor&=0x7fff; // Ignore the "TOUCHEXIT double click" bit for now.
  149.  
  150.             // Should be only for EXIT buttons, or some such...
  151.             Obj[exitor].Deselect();
  152.  
  153.             GEMevent e; // Current mouse state.
  154.             NowWhat=DoItem(exitor,e);
  155.  
  156.             if (NowWhat==IgnoredClick && Obj[exitor].Exit())
  157.                 NowWhat=EndInteraction;
  158.         } else {
  159.             NowWhat=EndInteraction;
  160.         }
  161.     }
  162.  
  163.     if (ZoomOn) form_dial(FMD_SHRINK,0,0,0,0,x,y,w,h);
  164.     form_dial(FMD_FINISH,0,0,0,0,x,y,w,h);
  165.  
  166.     wind_update(END_UPDATE);
  167.  
  168.     return exitor;
  169. }
  170.  
  171. void GEMform::RedrawObject(int RSCindex)
  172. {
  173.     objc_draw(Obj,RSCindex,MAX_DEPTH,0,0,MAXSHORT,MAXSHORT);
  174. }
  175.  
  176. void GEMform::RedrawObject(int RSCindex,int Cx,int Cy,int Cw,int Ch) // Clipped
  177. {
  178.     int X,Y;
  179.     objc_offset(Obj,RSCindex,&X,&Y);
  180.     objc_draw(Obj,RSCindex,MAX_DEPTH,Cx+X,Cy+Y,Cw,Ch);
  181. }
  182.  
  183. int GEMform::Parent(int o) const
  184. {
  185.     int n=o;
  186.  
  187.     do {
  188.         o=n;
  189.         n=Obj[n].Next();
  190.     } while (n>=0 && Obj[n].Tail()!=o);
  191.  
  192.     return n;
  193. }
  194.  
  195. void GEMform::AlignObject(int RSCindex, int xmlt=8, int ymlt=1)
  196. {
  197.     int x,y;
  198.     objc_offset(Obj,RSCindex,&x,&y);
  199.  
  200.     int rx,ry;
  201.     objc_offset(Obj,ROOT,&rx,&ry);
  202.  
  203.     xoffset=x-rx;
  204.     yoffset=y-ry;
  205.     xmult=xmlt;
  206.     ymult=ymlt;
  207. }
  208.  
  209. /* Non-cursive traverse of an object tree. */
  210. int GEMform::Map(int Do(GEMrawobject*, int), bool skiphidden, int RSCfrom, int RSCto)
  211. {
  212.     int tmp = RSCfrom;        // Initialize to impossible value
  213.  
  214.     // Look until final node, or off
  215.     // the end of tree
  216.     while (RSCfrom != RSCto && RSCfrom >= 0) {
  217.         // Did we 'pop' into RSCfrom node for the second time?
  218.         // Is this subtree hidden?
  219.         if (Obj[RSCfrom].Tail() == tmp
  220.          || (skiphidden && Obj[RSCfrom].HideTree())) {
  221.             // Yes - move right.
  222.             tmp = RSCfrom;
  223.             RSCfrom = Obj[tmp].Next();
  224.         } else {
  225.             // No, this is a new node
  226.             tmp = RSCfrom;
  227.             RSCfrom = -1;
  228.  
  229.             // Apply operation
  230.             int reply=Do(Obj, tmp);
  231.  
  232.             // Found object to return?
  233.             if (reply>=0) return reply;
  234.  
  235.             // Traverse subtree?
  236.             if (reply==-1) RSCfrom = Obj[tmp].Head();
  237.  
  238.             // Traverse right if nowhere to go
  239.             if (RSCfrom < 0)
  240.                 RSCfrom = Obj[tmp].Next();
  241.         }
  242.     }
  243.  
  244.     return -1;
  245. }
  246.  
  247. GEMfeedback GEMform::DoItem(int obj, const GEMevent& e)
  248. {
  249.     GEMfeedback result=IgnoredClick;
  250.  
  251.     // CallBacks
  252.     GEMobject* O=operator[](obj).Cook();
  253.  
  254.     if (O) {
  255.         int ox,oy;
  256.         objc_offset(Obj,obj,&ox,&oy);
  257.         result=O->Touch(e.X()-ox,e.Y()-oy,e);
  258.  
  259.         switch (result) {
  260.          case RedrawMe:
  261.             RedrawObject(obj);
  262.         break; case RedrawMyParent:
  263.             RedrawObject(Parent(obj));
  264.         break; default: ;
  265.         }
  266.     }
  267.  
  268.     return result;
  269. }
  270.