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

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  example
  4. //
  5. //  This file demonstrates many of the features of the gem++ library.
  6. //
  7. /////////////////////////////////////////////////////////////////////////////
  8. //
  9. //  This file is Copyright 1992 by Warwick W. Allison,
  10. //  and is freely distributable providing no charge is made.
  11. //
  12. /////////////////////////////////////////////////////////////////////////////
  13.  
  14. #include "gem++.h"
  15. #include "example.h"
  16. #include <time.h>
  17. #include <string.h>
  18.  
  19.  
  20.  
  21. //
  22. // Demonstrates a simple derived class of GEMobject
  23. //
  24. // Objects of this class will become Checked when clicked upon.
  25. //
  26. class MenuItemToggle : public GEMobject {
  27. public:
  28.     GEMfeedback Touch(int x, int y, const GEMevent& e)
  29.     {
  30.         Checked(bool(!Checked()));
  31.         Deselect();
  32.         Redraw();
  33.         return ContinueInteraction;
  34.     }
  35. };
  36.  
  37.  
  38. static char* monthtext[12]={"JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"};
  39.  
  40. //
  41. // Demonstrates GEMtimer and GEMhotform used for popup menus.
  42. //
  43. // This class encapsulates all the RSCindices required to setup
  44. // the clock, so only of of these objects could be created, since
  45. // they use the single graphics in the GEMrsc.  See the GEMringfiw
  46. // below for a more complex example that allows duplicates.
  47. //
  48. // This class has quite a few components...
  49. //
  50. //  - it is a GEMformwindow with no window-parts, so it is a form
  51. //       in a window.
  52. //  - it is a GEMtimer, so its Expire() method is called at the intervals
  53. //       requested with Interval().
  54. //  - it is a GEMobject based on the GRABBER object, so its Touch() method
  55. //       is called when the GRABBER is touched.
  56. //  - it has two GEMtextobjects, timetext and datetext, which we can just
  57. //       treat as if they are char*'s since they have conversion operators.
  58. //  - it has a GEMhotform, popup, used for a pop-up menu.
  59. //  - it has a MenuItemToggle (defined above), gmt, which is in the popup
  60. //       menu, and which we test the Checked() state of when deciding to
  61. //       use local or Greenwich time.
  62. //  - it has a GEMalert, gmjoke, which makes the whole GMT thing worthwhile.
  63. //
  64. // The member functions are described within.
  65. //
  66. class Clock : public GEMformwindow, GEMtimer, GEMobject {
  67. public:
  68.     Clock(GEMactivity& act, const GEMrsc& rsc) :
  69.         GEMformwindow(act,rsc,CLOCK,0),
  70.         GEMtimer(act,0), // Initially interval==0, ie. Expire() immediately.
  71.         GEMobject(*this,GRABBER),
  72.         timetext(*this,TIME),
  73.         datetext(*this,DATE),
  74.         popup(rsc,POPUP),
  75.         gmt(popup,GMT),
  76.         gmjoke(rsc,GMJOKE)
  77.     {
  78.         strcpy(timetext,"    ");
  79.         strcpy(datetext,"     ");
  80.     }
  81.  
  82. private:
  83.  
  84.     // The Update() method gets the local time or Greenwich time, according
  85.     // to whether the gmt GEMobject is Checked.  It then sets the timetext
  86.     // and datetext strings (they are actually GEMtextobjects).  It then
  87.     // Redraws those strings.  Update() is a local member, called by the
  88.     // methods below it.
  89.     //
  90.     void Update()
  91.     {
  92.         time_t ti=time(0);
  93.         tm* T;
  94.         if (gmt.Checked())
  95.             T=gmtime(&ti);
  96.         else
  97.             T=localtime(&ti);
  98.         timetext[0]=T->tm_hour/10 ? T->tm_hour/10+'0' : ' ';
  99.         timetext[1]=T->tm_hour%10+'0';
  100.         timetext[2]=T->tm_min/10+'0';
  101.         timetext[3]=T->tm_min%10+'0';
  102.         strncpy(datetext,monthtext[T->tm_mon],3);
  103.         datetext[3]=T->tm_mday/10 ? T->tm_mday/10+'0' : ' ';
  104.         datetext[4]=T->tm_mday%10+'0';
  105.         if (IsOpen()) {
  106.             timetext.Redraw();
  107.             datetext.Redraw();
  108.         }
  109.     }
  110.  
  111. protected:
  112.  
  113.     // The Expire() method overrides that inherited from GEMtimer.
  114.     // It is called when the interval expires.  Its action it
  115.     // to merely Update the time and wait set the interval to
  116.     // be 60000 milliseconds.  We only need to reset the interval
  117.     // because when we created the object, we requested the interval
  118.     // to be 0 so that the Expire (and hence Update) would be
  119.     // immediate.
  120.     //
  121.     virtual GEMfeedback Expire(const GEMevent&)
  122.     {
  123.         Update();
  124.         Interval(60000); // Every minute, approx.
  125.         return ContinueInteraction;
  126.     }
  127.  
  128.     // The Touch() method overrides that inheritted from GEMobject.
  129.     // It is called whenever the user touches the GRABBER object
  130.     // on which the object was defined.
  131.     //
  132.     // If the touch is made using the right button (button 1), the
  133.     // popup menu is displayed.  If the exitor of the popup is
  134.     // the "close" menuitem, the Close() method inheritted from
  135.     // GEMformwindow is called.  If the exitor is the smiley-face
  136.     // icon (DOGMJOKE, that's Do-GM-joke), the gmjoke alert is
  137.     // popped up.  If the exitor is the "quit" menuitem, EndInteraction
  138.     // is returned, ending the GEMactivity.Do() loop.  Note that
  139.     // the "GMT" menuitem is handled by using the Touch() method of
  140.     // MenuItemToggle as described above.
  141.     //
  142.     // If the touch is not made by the right button, we employ a bit
  143.     // of AES code (hmm, maybe that ugly stuff needs a class) to drag
  144.     // a box the size of the BorderRect of this window, then we
  145.     // GEMformwindow::Move this window to that dragged location.
  146.     //
  147.     virtual GEMfeedback Touch(int x, int y, const GEMevent& e)
  148.     {
  149.         if (e.Button(1)) {
  150.             switch (popup.Do(e.X(),e.Y())) {
  151.              case QCLOCK:
  152.                 Close();
  153.             break; case DOGMJOKE:
  154.                 gmjoke.Alert();
  155.             break; case QPROG:
  156.                 return EndInteraction;
  157.             }
  158.             Update();
  159.             return ContinueInteraction;
  160.         } else {
  161.             int bx,by,bw,bh;
  162.             int nx,ny;
  163.             wind_get(0,WF_WORKXYWH,&bx,&by,&bw,&bh);
  164.             GRect w=BorderRect();
  165.             graf_dragbox(w.g_w,w.g_h,w.g_x,w.g_y,bx,by,bw,bh,&nx,&ny);
  166.  
  167.             GEMformwindow::Move(nx,ny);
  168.  
  169.             return ContinueInteraction;
  170.         }
  171.     }
  172.  
  173. private:
  174.     GEMtextobject timetext,datetext;
  175.     GEMhotform popup;
  176.     MenuItemToggle gmt;
  177.     GEMalert gmjoke;
  178. };
  179.  
  180. //
  181. // Demonstrates GEMvdiobject
  182. //
  183. class GEMliney : public GEMvdiobject {
  184. protected:
  185.     virtual void Draw(int x, int y)
  186.         {
  187.             int j=Width() < Height() ? Width() : Height();
  188.             for (int i=0; i<j; i+=3) {
  189.                 vdi.line(x,y+j-i,x+i,y);
  190.             }
  191.         }
  192. };
  193.  
  194. //
  195. // Demonstrates GEMvdiobject, with special "Selected" state display.
  196. //
  197. class GEMellipse : public GEMvdiobject {
  198. protected:
  199.     virtual void Draw(int x, int y)
  200.         {
  201.             vdi.sf_interior(2); // Patterned
  202.             if (Selected()) vdi.sf_style(20);
  203.             else vdi.sf_style(10);
  204.             vdi.ellipse(x+Width()/2,y+Height()/2,Width()/2,Height()/2);
  205.         }
  206. };
  207.  
  208. //
  209. // Demonstrates that GEMuserobjects (and GEMvdiobjects) retain
  210. // the features of the object that is having its display representation
  211. // redefined.
  212. //
  213. class GEMroundbutton : public GEMvdiobject {
  214. private:
  215.     int texth;
  216.  
  217. public:
  218.     GEMroundbutton(GEMform& f, int RSCindex, VDI& v) :
  219.         GEMvdiobject(f,RSCindex,v)
  220.     {
  221.         int j;
  222.         graf_handle(&j,&texth,&j,&j);
  223.     }
  224.  
  225. protected:
  226.     virtual void Draw(int x, int y)
  227.         {
  228.             if (Selected()) vdi.sf_interior(1);
  229.             else vdi.sf_interior(0);
  230.             vdi.rfbox(x,y,x+Width()-1,y+Height()-1);
  231.             vdi.swr_mode(MD_XOR);
  232.             int j;
  233.             vdi.st_alignment(1,3,&j,&j); // Centre-Bottom aligned
  234.             vdi.gtext(x+Width()/2,y+(Height()+texth)/2-1,Text());
  235.             vdi.swr_mode(MD_REPLACE);
  236.         }
  237. };
  238.  
  239.  
  240. //
  241. // Demonstrates various GEMobjects, and the GEMformiconwindow
  242. //
  243. class Various : public GEMformiconwindow {
  244. public:
  245.     Various(GEMactivity& in, const GEMrsc& rsc) :
  246.         GEMformiconwindow(in,rsc,VARIOUS,VARIOUSI),
  247.         image("example.img"),
  248.         picture(*this,PIC,image),
  249.         SimpleSlider(*this,SIMPKNOB,SIMPSLID),
  250.         VertSlider(*this,VKNOB,VRACK,UP,DOWN),
  251.         HorzSlider(*this,HKNOB,HRACK,LEFT,RIGHT),
  252.         vdi(),
  253.         Ellipse(*this,ELLIPSE,vdi),
  254.         Liney(*this,LINEY,vdi),
  255.         R1(*this,RBUT1,vdi),
  256.         R2(*this,RBUT2,vdi)
  257.     {
  258.         SetName(" Various GEM++ objects ");
  259.     }
  260.  
  261. private:
  262.     IMG image;
  263.     GEMimageobject picture;
  264.     GEMslider SimpleSlider;
  265.     GEMslider VertSlider;
  266.     GEMslider HorzSlider;
  267.     VDI vdi;
  268.     GEMellipse Ellipse;
  269.     GEMliney Liney;
  270.     GEMroundbutton R1;
  271.     GEMroundbutton R2;
  272. };
  273.  
  274.  
  275. //
  276. // Demonstrates a sophisticated duplicatable window with shared objects
  277. //
  278. class GEMringfiw : public GEMformiconwindow {
  279. private:
  280.     GEMringfiw*& head;
  281.     GEMringfiw* next;
  282.     GEMringfiw* prev;
  283.  
  284. protected:
  285.     virtual GEMfeedback UserClosed() {
  286.         GEMformwindow::Close();
  287.         delete this;
  288.         return ContinueInteraction;
  289.     }
  290.  
  291.     GEMringfiw(GEMactivity& in, const GEMrsc& rsc, int RSCform, int RSCicon, GEMringfiw*& h) :
  292.         GEMformiconwindow(in,rsc,RSCform,RSCicon),
  293.         head(h)
  294.     {
  295.         next=prev=this;
  296.     }
  297.  
  298.     GEMringfiw(GEMringfiw& copy, GEMringfiw*& h) :
  299.         GEMformiconwindow(copy),
  300.         next(©), prev(copy.prev),
  301.         head(h)
  302.     {
  303.         next->prev=this;
  304.         prev->next=this;
  305.     }
  306.  
  307.     ~GEMringfiw()
  308.     {
  309.         if (next==this) {
  310.             head=0;
  311.         } else {
  312.             if (head==this) head=next;
  313.             prev->next=next;
  314.             next->prev=prev;
  315.         }
  316.     }
  317.  
  318. public:
  319.     static bool OpenNew(GEMactivity& act, const GEMrsc& rsc, int RSCform, int RSCicon, GEMringfiw*& head)
  320.     {
  321.         GEMringfiw* newhead;
  322.  
  323.         if (head)
  324.             newhead=new GEMringfiw(*head,head);
  325.         else
  326.             newhead=new GEMringfiw(act,rsc,RSCform,RSCicon,head);
  327.  
  328.         head=newhead;
  329.         head->Open();
  330.         if (head->IsOpen()) {
  331.             return TRUE;
  332.         } else {
  333.             delete newhead;
  334.             return FALSE;
  335.         }
  336.     }
  337. };
  338.  
  339.  
  340. //
  341. // Demonstrates GEMmenu as central to the interaction.
  342. //
  343. class Menu : GEMmenu {
  344. public:
  345.     Menu(GEMactivity& in, const GEMrsc& r) :
  346.         GEMmenu(in,r,MENU),
  347.         act(in),
  348.         rsc(r),
  349.         about(rsc,ABOUT),
  350.         itisfree(rsc,FREE),
  351.         authors(rsc,AUTHORS),
  352.         gnu(rsc,GNU),
  353.         errwin(rsc,ERRWIN),
  354.         clocknote(rsc,CLOCKNOTE),
  355.         various(in,rsc),
  356.         clock(in,rsc),
  357.         windows(0),
  358.         bigform(in,rsc,BIGFORM,BIGFORMI,CLOSER|MOVER|NAME|FULLER|SIZER|UPARROW|DNARROW|LFARROW|RTARROW|VSLIDE|HSLIDE)
  359.     {
  360.         bigform.Resize(200,100);
  361.     }
  362.  
  363. protected:
  364.     virtual GEMfeedback DoItem(int item, const GEMevent& e)
  365.     {
  366.         switch (item) {
  367.          case DOABOUT:
  368.             about.Do();
  369.         break; case DOFREE:    
  370.             itisfree.Do();
  371.         break; case DOAUTHORS:
  372.             authors.Do();
  373.         break; case DOGNU:
  374.             gnu.Do();
  375.         break; case DOQUIT:
  376.             return EndInteraction;
  377.         break; case DOVARIOUS:
  378.             various.Open();
  379.         break; case DOBIGFORM:
  380.             bigform.Open();
  381.         break; case DOSHARING:
  382.             if (!GEMringfiw::OpenNew(act,rsc,SHARING,SHARINGI,windows))
  383.                 switch (errwin.Alert()) {
  384.                  case 1: return DoItem(item,e);
  385.                 break; case 2: about.Do();
  386.                 }
  387.         break; case DOCLOCK:
  388.             clocknote.Alert();
  389.             clock.Open();
  390.         }
  391.  
  392.         return ContinueInteraction;
  393.     }
  394.  
  395. private:
  396.     Clock clock;
  397.     GEMringfiw* windows;
  398.     GEMactivity& act;
  399.     GEMrsc& rsc;
  400.     GEMform about,itisfree,authors,gnu;
  401.     GEMformiconwindow bigform;
  402.     Various various;
  403.     GEMalert errwin;
  404.     GEMalert clocknote;
  405. };
  406.  
  407.  
  408. //
  409. // Demonstrates GEMfileselector
  410. //
  411. class FileChooser : public GEMobject, public GEMfileselector {
  412. public:
  413.     FileChooser(GEMform& f, int RSCibutn, GEMobject& disp, char* prmpt) :
  414.         GEMobject(f,RSCibutn),
  415.         GEMfileselector(disp.Text()),
  416.         display(disp),
  417.         prompt(prmpt)
  418.     {
  419.         display.Redraw();
  420.     }
  421.  
  422.     virtual GEMfeedback Touch(int x, int y, const GEMevent& e)
  423.     {
  424.         if (Get(prompt)) display.Redraw();
  425.  
  426.         return ContinueInteraction;
  427.     }
  428.  
  429. private:
  430.     GEMobject& display;
  431.     char* prompt;
  432. };
  433.  
  434. //
  435. // Demonstrates GEMdesktop
  436. //
  437. class Desktop : public GEMdesktop {
  438. public:
  439.     Desktop(GEMactivity& in, const GEMrsc& rsc) :
  440.         GEMdesktop(in,rsc,DESKTOP),
  441.         display(*this,FILEDISPLAY),
  442.         files(*this,FILES,display,rsc.String(FILEPROMPT))
  443.     {
  444.     }
  445.  
  446. private:
  447.     GEMobject display;
  448.     FileChooser files;
  449. };
  450.  
  451.  
  452. main()
  453. {
  454.     // Before we do ANYTHING with GEM, we must declare a GEMapplication.
  455.     GEMapplication example;
  456.  
  457.     // Next, we declare a GEMrsc, which we then use to create other objects.
  458.     GEMrsc rsc("example.rsc",8,16);
  459.     // GEMrsc rsc("example.rsc");
  460.  
  461.     if (!rsc) {
  462.         // If the GEMrsc file cannot be created, we have to resort to a
  463.         // GEMalert constructed from strings rather than from the GEMrsc.
  464.         GEMalert dammit("Could not load \"example.rsc\".","Quit");
  465.         dammit.Alert();
  466.     } else {
  467.         // But if everything goes fine, we create a GEMactivity, and
  468.         // our own Menu and Desktop (see definitions above) in that
  469.         // GEMactivity.
  470.  
  471.         GEMactivity activity;
  472.  
  473.         Menu menu(activity,rsc);
  474.  
  475.         Desktop desktop(activity,rsc);
  476.  
  477.         // Then, conduct the GEMactivity - returns when all done.
  478.         activity.Do();
  479.     }
  480. }
  481.