home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Programming / Triton / Source / demos / customclass.c next >
C/C++ Source or Header  |  1998-05-23  |  11KB  |  342 lines

  1. /*
  2.  *  OpenTriton -- A free release of the triton.library source code
  3.  *  Copyright (C) 1993-1998  Stefan Zeiger
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  CustomClass.c - A simple custom class
  20.  *
  21.  *  ****    ***   *   *  *  *****     ****    ***   *   *  ***   ***     *
  22.  *  *   *  *   *  **  *  *    *       *   *  *   *  **  *   *   *        *
  23.  *  *   *  *   *  * * *       *       ****   *****  * * *   *   *        *
  24.  *  *   *  *   *  *  **       *       *      *   *  *  **   *   *
  25.  *  ****    ***   *   *       *       *      *   *  *   *  ***   ***     *
  26.  *
  27.  *  It's easier than it looks!
  28.  *
  29.  */
  30.  
  31.  
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <math.h>
  36.  
  37. #include <libraries/triton.h>
  38. #include <graphics/gfx.h>
  39. #include <intuition/intuition.h>
  40.  
  41. #ifdef __GNUC__
  42. #ifndef __OPTIMIZE__
  43. #include <clib/triton_protos.h>
  44. #include <clib/graphics_protos.h>
  45. #include <clib/intuition_protos.h>
  46. #else
  47. #include <inline/triton.h>
  48. #include <inline/graphics.h>
  49. #include <inline/intuition.h>
  50. #endif /* __OPTIMIZE__ */
  51. #else
  52. #include <proto/triton.h>
  53. #include <proto/graphics.h>
  54. #include <proto/intuition.h>
  55. #endif /* __GNUC__ */
  56.  
  57.  
  58. /**** So it shall be written, so it shall be done: ****/
  59.  
  60. /****** class_Clock ******
  61. *
  62. *   NAME    
  63. *    class_Clock -- Display an analog clock.
  64. *
  65. *   SUPERCLASS
  66. *    class_DisplayObject
  67. *
  68. *   SYNOPSIS
  69. *    TROB_Clock
  70. *
  71. *   ATTRIBUTES
  72. *    <Default>        : <unused>
  73. *    TRAT_Clock_Hours : ULONG hours
  74. *                       (Default: 0)
  75. *                       [create, set, get]
  76. *    TRAT_Clock_Mins  : ULONG minutes
  77. *                       (Default: 0)
  78. *                       [create, set, get]
  79. *    TRAT_Clock_Secs  : ULONG seconds
  80. *                       (Default: 0)
  81. *                       [create, set, get]
  82. *    TRAT_Clock_DisplaySeconds : BOOL displayseconds
  83. *                       (Default: TRUE)
  84. *                       [create, set, get]
  85. *
  86. ******/
  87.  
  88. /**** The class tag ****/
  89. #define TROB_Clock                  TRTG_PRVCLS(1)
  90.  
  91. /**** The attribute tags ****/
  92. #define TRAT_Clock_Hours            TRTG_PRVOAT(1)
  93. #define TRAT_Clock_Mins             TRTG_PRVOAT(2)
  94. #define TRAT_Clock_Secs             TRTG_PRVOAT(3)
  95. #define TRAT_Clock_DisplaySeconds   TRTG_PRVOAT(4)
  96.  
  97. /**** The internal representation of instances of our class ****/
  98. struct TROD_Clock
  99. {
  100.   struct TROD_DisplayObject DO; /* Superclass object data */
  101.   ULONG Hours, Mins, Secs;      /* The currently displayed time */
  102.   BOOL DisplaySecs;             /* Display seconds? */
  103. };
  104.  
  105. TR_CONSTRUCTOR(Clock) /* This one's called for creating an instance */
  106. {
  107.   /* Initialize default values */
  108.   Self.DisplaySecs=TRUE;
  109.  
  110.   /* Let the superclass do its work (mainly argument parsing) */
  111.   if(!TR_SUPERMETHOD) return NULL;
  112.  
  113.   /* Set some DisplayObject fields */
  114.   Self.DO.XResize=TRUE;
  115.   Self.DO.YResize=TRUE;
  116.   Self.DO.MinHeight=50;
  117.   Self.DO.MinWidth=(Self.DO.MinHeight*Self.DO.O.Project->trp_AspectFixing)/16;
  118.  
  119.   /* We need to see some IDCMP messages */
  120.   Self.DO.O.Project->trp_IDCMPFlags|=IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE|IDCMP_INACTIVEWINDOW;
  121.  
  122.   /* You asked for it? Here you got it! */
  123.   return object;
  124. }
  125.  
  126. TR_SIMPLEMETHOD(Clock,INSTALL_REFRESH) /* 2 messages but only 1 method! */
  127. {
  128.   ULONG left,top,width,height;
  129.   struct TR_Project *project;
  130.   double r;
  131.   int d;
  132.  
  133.   TR_SUPERMETHOD; /* Call DisplayObject's INSTALL or REFRESH method */
  134.  
  135.   project = Self.DO.O.Project;
  136.   left    = Self.DO.Left;
  137.   top     = Self.DO.Top;
  138.   width   = Self.DO.Width;
  139.   height  = Self.DO.Height;
  140.  
  141.   /* Fill background */
  142.   TR_AreaFill(project,NULL,left,top,left+width-1,top+height-1,TRBF_NONE,NULL);
  143.  
  144.   /* Draw ticks */
  145.   SetAPen(project->trp_Window->RPort,TR_GetPen(project,TRPT_SYSTEMPEN,FILLPEN));
  146.   for(d=0;d<360;d+=5)
  147.     {
  148.       r=((double)d)*PI/180.0;
  149.       if(d%30==0)
  150.     {
  151.       SetAPen(project->trp_Window->RPort,TR_GetPen(project,TRPT_SYSTEMPEN,TEXTPEN));
  152.       Move(project->trp_Window->RPort,
  153.            (LONG)(left+width/2+(cos(r)*(width/2-1))),(LONG)(top+height/2+(sin(r)*(height/2-1))));
  154.       Draw(project->trp_Window->RPort,
  155.            (LONG)(left+width/2+(cos(r)*(width/2-1))*0.9),(LONG)(top+height/2+(sin(r)*(height/2-1))*0.9));
  156.       SetAPen(project->trp_Window->RPort,TR_GetPen(project,TRPT_SYSTEMPEN,FILLPEN));
  157.     }
  158.       else
  159.     {
  160.       Move(project->trp_Window->RPort,
  161.            (LONG)(left+width/2+(cos(r)*(width/2-1))),(LONG)(top+height/2+(sin(r)*(height/2-1))));
  162.       Draw(project->trp_Window->RPort,
  163.            (LONG)(left+width/2+(cos(r)*(width/2-1))*0.95),
  164.            (LONG)(top+height/2+(sin(r)*(height/2-1))*0.95));
  165.     }
  166.     }
  167.  
  168.   /* Draw Circle */
  169.   SetAPen(project->trp_Window->RPort,TR_GetPen(project,TRPT_SYSTEMPEN,TEXTPEN));
  170.   DrawEllipse(project->trp_Window->RPort,left+width/2,top+height/2,width/2-1,height/2-1);
  171.  
  172.   /* Draw second hand (even though this code is new and original :-) */
  173.   if(Self.DisplaySecs)
  174.     {
  175.       SetAPen(project->trp_Window->RPort,TR_GetPen(project,TRPT_SYSTEMPEN,FILLPEN));
  176.       d=270+(((double)(Self.Secs))*360.0/60.0);
  177.       r=((double)d)*PI/180.0;
  178.       Move(project->trp_Window->RPort,left+width/2,top+height/2);
  179.       Draw(project->trp_Window->RPort,
  180.        (LONG)(left+width/2+(cos(r)*(width/2-1))*0.85),(LONG)(top+height/2+(sin(r)*(height/2-1))*0.85));
  181.     }
  182.  
  183.   /* Draw minute hand */
  184.   SetAPen(project->trp_Window->RPort,TR_GetPen(project,TRPT_SYSTEMPEN,SHINEPEN));
  185.   d=270+(((double)(Self.Mins))*360.0/60.0);
  186.   r=((double)d)*PI/180.0;
  187.   Move(project->trp_Window->RPort,left+width/2,top+height/2);
  188.   Draw(project->trp_Window->RPort,
  189.        (LONG)(left+width/2+(cos(r)*(width/2-1))*0.75),(LONG)(top+height/2+(sin(r)*(height/2-1))*0.75));
  190.  
  191.   /* Draw hour hand */
  192.   d=270+(((double)(Self.Hours%12))*360.0/12.0+((double)(Self.Mins))*30.0/60.0);
  193.   r=((double)d)*PI/180.0;
  194.   Move(project->trp_Window->RPort,left+width/2,top+height/2);
  195.   Draw(project->trp_Window->RPort,
  196.        (LONG)(left+width/2+(cos(r)*(width/2-1))*0.60),(LONG)(top+height/2+(sin(r)*(height/2-1))*0.60));
  197.  
  198.   return 1; /* Everything OK */
  199. }
  200.  
  201. TR_METHOD(Clock,SETATTRIBUTE,SetAttributeData) /* Set an attribute (upon creation or later) */
  202. {
  203.   /* A good way to do this properly would be:
  204.      1) If a hand is changing erase the old hand with the background pen.
  205.      2) Modify the value.
  206.      3) If a hand was erased in step 1 redraw it.
  207.  
  208.      But since this is only an example program we'll do it the easy (and short) way:
  209.      1) Modify the value.
  210.      2) Refresh the display. */
  211.  
  212.   switch(data->attribute)
  213.   {
  214.     case TRAT_Clock_Hours:
  215.       Self.Hours=data->value;
  216.       goto dorefresh;
  217.     case TRAT_Clock_Mins:
  218.       Self.Mins=data->value;
  219.       goto dorefresh;
  220.     case TRAT_Clock_Secs:
  221.       Self.Secs=data->value;
  222.       goto dorefresh;
  223.     case TRAT_Clock_DisplaySeconds:
  224.       Self.DisplaySecs=data->value;
  225.       goto dorefresh;
  226.     default:
  227.       /* Pass messages for unknown attributes on to the superclass */
  228.       return TR_SUPERMETHOD;
  229.     }
  230.  
  231. dorefresh:
  232.   /* Attention! You can receive TROM_SETATTRIBUTE messages when the object
  233.      isn't currently installed. You have to make sure the object is indeed
  234.      installed before sending it a refresh message! */
  235.   if(Self.DO.Installed) return TR_DoMethod(&Self.DO.O,TROM_REFRESH,NULL);
  236.   else return 1;
  237. }
  238.  
  239. TR_SIMPLEMETHOD(Clock,GETATTRIBUTE) /* Return a requested attribute */
  240. {
  241.   switch((ULONG)data)
  242.   {
  243.     case TRAT_Clock_Hours:
  244.       return Self.Hours;
  245.     case TRAT_Clock_Mins:
  246.       return Self.Mins;
  247.     case TRAT_Clock_Secs:
  248.       return Self.Secs;
  249.     case TRAT_Clock_DisplaySeconds:
  250.       return (ULONG)(Self.DisplaySecs?TRUE:FALSE);
  251.     default:
  252.       /* Pass queries for unknown attributes on to the superclass */
  253.       return TR_SUPERMETHOD;
  254.   }
  255. }
  256.  
  257. TR_METHOD(Clock,EVENT,EventData) /* React on IDCMP messages */
  258. {
  259.   struct TR_Message *trmsg;
  260.  
  261.   if((data->imsg->Class==IDCMP_MOUSEBUTTONS)
  262.      &&(data->imsg->MouseX>=Self.DO.Left)
  263.      &&(data->imsg->MouseX<Self.DO.Left+Self.DO.Width)
  264.      &&(data->imsg->MouseY>=Self.DO.Top)
  265.      &&(data->imsg->MouseY<Self.DO.Top+Self.DO.Height)
  266.      &&(data->imsg->Code==SELECTDOWN))
  267.     {
  268.       DisplayBeep(NULL);
  269. /*       if(trmsg=TR_CreateMsg(Self.DO.O.Project->trp_App)) */
  270. /*     { */
  271. /*       trmsg->trm_ID=Self.DO.ID; */
  272. /*       trmsg->trm_Class=TRMS_ACTION; */
  273. /*       return TROM_EVENT_SWALLOWED; */
  274. /*     } */
  275.     }
  276.   return TROM_EVENT_CONTINUE;
  277. }
  278.  
  279.  
  280. /**** Let's see if our class works... ****/
  281.  
  282. int main(void)
  283. {
  284.   int retval=20;
  285.   BOOL close_me=FALSE;
  286.   struct TR_Message *trmsg;
  287.   struct TR_Project *project;
  288.  
  289.   if(TR_OpenTriton(TRITON20VERSION,TRCA_Name,"CustomClass",TRCA_Info,"Triton Custom Class Demo",TRCA_Version,"1.0",TAG_END))
  290.     {
  291.       if(TR_AddClassTags(Application, TROB_Clock, TROB_DisplayObject, NULL, sizeof(struct TROD_Clock),
  292.              TROM_NEW,          TRDP_Clock_NEW,
  293.              TROM_INSTALL,      TRDP_Clock_INSTALL_REFRESH,
  294.              TROM_REFRESH,      TRDP_Clock_INSTALL_REFRESH,
  295.              TROM_SETATTRIBUTE, TRDP_Clock_SETATTRIBUTE,
  296.              TROM_GETATTRIBUTE, TRDP_Clock_GETATTRIBUTE,
  297.              TROM_EVENT,        TRDP_Clock_EVENT,
  298.              TAG_END))
  299.     {
  300.       if(project=TR_OpenProjectTags(Application,
  301.                     WindowID(1), WindowPosition(TRWP_CENTERDISPLAY),
  302.                     WindowTitle("CustomClass (under construction!)"), WindowFlags(TRWF_NOMINTEXTWIDTH),
  303.                     QuickHelpOn(TRUE),
  304.                     HorizGroupA, Space, VertGroupA,
  305.                       Space,
  306.                       NamedFrameBox("Triton Clock"), ObjectBackfillB,
  307.                         HorizGroupA, Space, VertGroupA,
  308.                           Space,
  309.                           TROB_Clock, NULL, TRAT_Clock_Hours, 5, TRAT_Clock_Mins, 42,
  310.                             ID(1), QuickHelp("Use the mouse to drag the hands\n(NOT IMPLEMENTED YET!)"),
  311.                           Space,
  312.                                             EndGroup, Space, EndGroup,
  313.                       Space, EndGroup, Space, EndGroup, EndProject))
  314.         {
  315.           while(!close_me)
  316.         {
  317.           TR_Wait(Application,NULL);
  318.           while(trmsg=TR_GetMsg(Application))
  319.             {
  320.               if(trmsg->trm_Project==project) switch(trmsg->trm_Class)
  321.             {
  322.             case TRMS_CLOSEWINDOW:
  323.               close_me=TRUE;
  324.               break;
  325.  
  326.             case TRMS_ERROR:
  327.               puts(TR_GetErrorString(trmsg->trm_Data));
  328.               break;
  329.             }
  330.               TR_ReplyMsg(trmsg);
  331.             }
  332.         }
  333.           TR_CloseProject(project);
  334.         } else puts(TR_GetErrorString(trmsg->trm_Data));
  335.     } else puts("Can't initialize 'Clock' custom class.");
  336.       retval=0;
  337.       TR_CloseTriton();
  338.     } else puts("Can't open triton.library v6+.");
  339.  
  340.   return retval;
  341. }
  342.