home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 357.lha / Skel / skel.doc < prev    next >
Text File  |  1990-03-13  |  12KB  |  242 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6. "z
  7.  
  8.                  Skeleton Workbench Application
  9.                           by Joel Swank
  10.                          January 9, 1989
  11.  
  12.  
  13.  
  14.     The Skeleton  Workbench  Application  is  my  attempt to make
  15. writing  workbench  applications  (almost) as easy as writing CLI
  16. applications.   When  I began adding Intuition interfaces to some
  17. of  my  CLI  utilities  I found that I needed esentially the same
  18. routines  in  each.  So I decided to make a skeleton program that
  19. provides  all  the  basic routines needed by most applications. I
  20. now  have  a  'Skel'  directory  that  I  copy  to  start   a new
  21. application.  Then  I rename and modify each of the files to suit
  22. the new application.  
  23.    The Skel directory contains the following files:
  24.  
  25.      * makefile: File to compile Skeleton using Aztec C.
  26.      * skel.c:   Mainline, initialization/termination,
  27.                  Gadget and Menu handling.
  28.      * skwindow.h: Data structures for main window.
  29.      * doargs.c: Agrument processing for Workbench and CLI.
  30.      * abouthelp.c: Help window and About Requester processing.
  31.      * helpwin.h: Data structures for help window.
  32.      * skel.info: Tool icon for workbench startup.
  33.  
  34.    Following is   a   description  of  the  Skeleton  and  how  I
  35. customize it  for a new application.  
  36.    I rename  skel.c  and  edit it to be the new main routine. The
  37. main()  routine  first sets up any defaults needed. Then it opens
  38. any   libraries  that  are  needed.  Next  it  calls  either  the
  39. Workbench  or  CLI argument routine. Next it sets up the gadgets,
  40. opens  the  main   window,  and  attaches  the  menu. Finally, it
  41. writes the window text and waits for a message from Intuition.  
  42.    The done()  subroutine  is  the termination routine. It closes
  43. or  frees everything opened or allocated by the program. Whenever
  44. I  add  something  to  the  initialization,  I add a coresponding
  45. entry  to  done().  This  is very important since AmigaDOS has no
  46. resource  tracking. If a program allocates a resource and doesn't
  47. free  it,  that  resource  is  gone  until  next  boot.  The done
  48. routine  is  called  from  wherever  program exit is required. It
  49. accepts  a  return  code  that  is  passed to the exit routine to
  50. become  the error code for the program. Notice that done() checks
  51. to  see  if a resource is allocated before closing or freeing it.
  52. This  allows  it  to be called at any time and it will only close
  53. that  which  has  been  opened.  For  this  to work, all resource
  54. pointers  must  be set to NULL before  initialization, and set to
  55. NULL if they are closed anywhere else in the  program.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.    The main  loop  waits  for  an  IDCMP message to arrive at the
  65. main  window message port. When one does, it uses the Class field
  66. of  the  message  to determine what type of message was received.
  67. It  only  reacts to CLOSEWINDOW, GADGETUP, and MENUPICK messages.
  68. There  are  lots  of  other  types  that might be used. I can add
  69. cases  for  these  here  and  add  the  corresponding  bit to the
  70. IDCMPFlags  of the NewWindow structure before opening the window,
  71. or  use  the  ModifyIDCMP()  subroutine  to change the IDCMPFlags
  72. after the window is open.  
  73.    The CLOSEWINDOW  message  just  causes  done(0)  to be called.
  74. This   message  is  the  result  of  the  user clicking the Close
  75. Gadget.   Of  course,  the  WINDOWCLOSE  bit  must  be set in the
  76. NewWindow Flags field for this gadget to be created.  
  77.    A GADGETUP  message  indicates  that  user has selected one of
  78. the  gadgets  in  my  gadget list. I use the RELVERIFY flag in my
  79. boolean  gadgets so that the user must click and release over the
  80. gadget  to  activate  it.   The  IAddress  field  of  the message
  81. contains  the address of the Gadget structure of  the gadget that
  82. was  selected.   I compare this to a list of my gadget addresses(
  83. a  list  of 1 in skel) to see which was selected. The only active
  84. gadget  in  Skel  is  the  'GO'  gadget  which causes the do_it()
  85. routine to be executed. I can add checks for more gadgets here.  
  86.    Another type  of  boolean  gadget  I can use is a TOGGLESELECT
  87. gadget.   These gadgets are toggled on and off each time the user
  88. clicks  them.  The  current state is kept by intuition and can be
  89. read  any  time by testing the SELECTED bit of the Flags field of
  90. the  Gadget  structure.   No  message  is  generated  when  these
  91. gadgets are clicked.  
  92.    A MENUPICK  message  arrives  each time the user brings up the
  93. menus  for  my  window.  The message Code field contains a number
  94. indicating  which  menu was picked. The processing of a menu pick
  95. is handled in the do_pick() subroutine.  
  96.    The do_pick()   subroutine  determines  which  menu  has  been
  97. selected.   It uses the standard macros to break the message code
  98. into  the  menu  number,  item  number,  and  subitem number. The
  99. proper  routine  is  selected  with  a  series  of  nested switch
  100. statements.  Menus  and  items are numbered from zero starting in
  101. the  upper  left.  The  Project  menu  has 4 items, each of which
  102. cause  the  execution of a routine. The Options menu has only one
  103. item  that  is  an example of using MUTUALEXCLUDE subitems. I can
  104. ignore  the  messages  for  these items because Intuition totally
  105. handles  turning  on  and off the check marks as the user selects
  106. options.  All I have to do is test the CHECKED bit in the SubItem
  107. Flags  field  to  see  which  item  is selected.  The only time I
  108. might  want  to  do something in response to a message for one of
  109. these   items   is   if   the  option  being  selected  needs  an
  110. initialization   routine   to   be  run.   After  processing  the
  111. selection,  I  use the ItemAddress() subroutine to get the actual
  112. address  of  the menuitem structure and get its NextSelect field.
  113. This  is  either the number of another selection to be processed,
  114. or  MENUNULL.  Selection  processing repeats until all selections
  115. in the chain have been processed.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.    The do_it()  subroutine  is  the main action routine and it is
  125. activated  by the GO gadget. It first checks the options and then
  126. calls  off_gads().  off_gads()  disables  all  gadgets except the
  127. STOP  gadget.  In  order  to  do  this  properly I must first use
  128. RemoveGList()  to  remove all the gadgets from the window. Then I
  129. can  make  any  changes  to  the gadgets. I have made a couple of
  130. macros  (OffGad  & OnGad) to set and clear the GADDISABLED bit in
  131. the  Gadget structure. There are Intuition subroutines to do this
  132. (OffGadget()  and  OnGadget()),  but  these routines also refresh
  133. the  image of each gadget. It is more efficient and more visually
  134. pleasing,  when  changing  several  gadgets,  to  to make all the
  135. changes  and  refresh  all  the  gadgets at the same time.  I use
  136. AddGList  to put them back in the window, and then RefreshGlist()
  137. to  refresh  the  image  of  all  gadgets.  Some  gadgets are not
  138. redrawn  properly unless they are drawn on background color, so I
  139. use  RectFill()  to  clear  the  window  first.  Notice  that thr
  140. redraw_scr()  subroutine  is  actually  part  of  on_gadds()  and
  141. off_gads()  and  should  not be called elsewhere. Off_gads() also
  142. removes  the menus from the window so that the user cannot select
  143. them while do_it() is running.  
  144.   After adjusting  the gadgets do_it() enters a loop of drawing a
  145. graphic  and  checking  for  a message at the window port. Notice
  146. that  I  cannot  wait on the port this time because I have things
  147. to  do. So I have to call GetMsg() until I get a non-NULL pointer
  148. back.   I  only  recognize  the  CLOSEWINDOW  and  Stop  gadgets.
  149. CLOSEWINDOW  executes  done(). On Stop I exit the loop and finish
  150. do_it()  with  the   off_gads()  subroutine. It swaps the gadgets
  151. back and attaches the menu.  
  152.   The Open  menu  item  executes  the do_open subroutine. This is
  153. where  I normally would have my interface to a File Requester and
  154. the  open  of the returned filename. Instead Skel has just a test
  155. of my standard 'Open Fail' error Requester.  
  156.   I have  included an _abort() routine. This routine is called by
  157. the  Aztec  Chk_Abort  routine.  Chk_Abort is called by the Aztec
  158. I/O  routines  to  check for the cancel signal. It calls abort to
  159. clean  up  and  exit when it detects cancel.  If the program uses
  160. none  of  the  Aztec  I/O  routines  and  doesn't call Chk_Abort,
  161. _abort()  is  not needed. The only other use for _abort() is with
  162. Manx's  source  level  debugger (SDB).  SDB calls _abort() when I
  163. use  the q command to exit the program early.  If I put a call to
  164. done() in _abort() the q command will release all my resources.  
  165.   The doargs.c  file  contains  a  subroutine  to  get  workbench
  166. arguments  and  a  subroutine  to  get CLI arguments. getWBargs()
  167. finds  the Workbench startup message and reads in the icon of the
  168. first  argument  in  the  argument list. This is the icon used to
  169. start  the  program.  It  should  be  a  Tool  icon.  It may have
  170. parameters  set in the ToolTypes array.  I use the FindToolType()
  171. subroutine  to  check for my 3 possible tooltypes. FindToolType()
  172. is  case  sensitive,  so  to change the DELAY argument 'DELAY=20'
  173. must  be  entered,  'delay=20'  won't work.  I could also use the
  174. MatchToolValue()  subroutine  to  check  for specific values of a
  175. ToolType.   The  user  can  use  Workbench  Info tool to edit the
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183.  
  184. ToolTypes   array.    In   order   to   read  the  arguments  the
  185. icon.library  is  needed.  Since getWBargs() is the only place it
  186. is  needed,  I  open  and  close  it here and it is not closed in
  187. done().  getCLIargs()  scans the C argument  array for the same 3
  188. arguments.  There  is also an empty subroutine called _wb_parse()
  189. in  this  file. It is a dummy to keep the Aztec subroutine of the
  190. same  name  from  being  included  from the library.  _wb_parse()
  191. scans  the ToolTypes array for a Window specification and opens a
  192. window  if it finds one. Since I am handling the ToolTypes array,
  193. and opening my own window, I don't need the Aztec routine.  
  194.    The files  abouthelp.c and helpwin.h contain everything needed
  195. for  two  items I always have on my Project menu, About and Help.
  196. about()  displays  a requester with program name, version, author
  197. and  date.  help()  Opens  its  own  full  sized window and pages
  198. through  an  array  of text lines. The text is stored as an array
  199. of  pointers  to  lines of text. A NULL pointer ends the array. A
  200. line  with  only  a formfeed is a signal to stop and wait for the
  201. user  to  click  the  'MORE'  gadget. This file also contains the
  202. text  structures  for  my  AutoRequest()  error requesters. I use
  203. single  and  multi-line  requesters  to inform the user of errors
  204. and other important information.  
  205.    The skel.info  file  is  a tool icon that can be used to start
  206. skel.  I edit this file using the icon editor to make an icon for
  207. the  new  application. I use the Workbench Info menu selection to
  208. edit  the  ToolTypes  array  and add any entrys needed by the new
  209. application.  I  then  rename  it  to  match  the name of the new
  210. command.  
  211.    The remaining   file,   skwindow.h,   contains  all  the  data
  212. structures  defining  my main window, all its gadgets and all its
  213. menus.  This  code  was  generated  with  PowerWindows 2.0. I use
  214. PowerWindows  to  create  all my window definitions. PowerWindows
  215. makes  designing  and  editing  Screens  and  windows and all the
  216. trimmings  very  easy.  I  always  keep my PowerWindows generated
  217. source  unedited,  so that it is easy to alter the definition and
  218. generate  new source. If you don't have PowerWindows, you can use
  219. skwindow.h as a guide for creating your own window.  
  220.    There are  a  lot  of  other  things  needed  to  flesh out an
  221. application.   One  of  the  most  common  is  a  file Requester.
  222. Fortunately  there  are  several of these available in the public
  223. domain.  There is FileReq by Peter da Silva on Fish Disk #85, amd
  224. Getfile  by  Charlie  Heath  on  Fish Disk #41. I have been using
  225. FileIO  by  RJ Mical from the prosuite package on Fish Disk #107.
  226. Prosuite  also  has  several  other  good  utilities.  There is a
  227. ColorWindow  for  editing  the  palette of any screen. There is a
  228. requester  handler  to help with more elegant requesters than the
  229. AutoRequest() requesters I use.  
  230.     Skel doesn't   begin   to   exercise   all  the  features  of
  231. Intuition,  but  it  provides  me  with a good starting point for
  232. getting  my application up and running quickly. It should also be
  233. a good way for a novice to learn Intuition a step at a time.  "z
  234.  
  235.  
  236.  
  237.  
  238.  
  239.  
  240.