home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / dev / e / EasyGUI_v33b2.lha / Docs / EasyGUI.doc < prev    next >
Text File  |  1997-02-23  |  62KB  |  1,316 lines

  1.                                Introducing:
  2.  
  3.                           E A S Y G U I   v3.3b.2
  4.  
  5.         An interface builder for E, with the following highlights:
  6.  
  7.           - It's totally Font-Sensitive
  8.           - It's Resizable
  9.           - It's Self-Organising, i.e. it arranges gadgets
  10.           - It's more StyleGuide compliant than your granny
  11.           - It's Fast and Flexible
  12.           - It's relatively small, needs no extra external libraries
  13.           - The layout-engine is user-extendable with PLUGINs
  14.           - And above all: It's extremely easy to use!!!
  15.  
  16. +---------------------------------------------------------------+
  17. |       0. History                                              |
  18. +---------------------------------------------------------------+
  19.  
  20. As of v3.3a, maintained by Jason R. Hulance, who you can contact at
  21. the addresses given in the Beginner's Guide to Amiga E.
  22. (Email: jason@fsel.com)
  23.  
  24. Changes from the v3.3b version:
  25. - Fixed bug: STR, INTEGER and CHECK gadgets' action functions were not
  26.   getting passed the correct new value parameter.
  27. - Fixed bug: LISTV wasn't always wide enough for label.
  28. - Added EG_HIDE tag to enable the GUI to be created with a hidden (closed)
  29.   window.
  30. - Changed blockwin()/unblockwin() so they now nest properly.
  31.  
  32. Changes from the v3.3a version:
  33. - MAJOR CHANGE: made the main functions use a taglist for their optional
  34.   arguments (it was getting a bit ridiculous...).  This gives a bit more
  35.   flexibility for the programmer and makes for much more readable code, so
  36.   I'm afraid it was inevitable.  To ease the change-over a bit there is an
  37.   example module which gives the old style versions of the functions (just
  38.   for EasyGUI.m; you can do your own for EasyGUI_lite.m).
  39. - MAJOR ADDITION: support for multi-window GUIs.  This is via the
  40.   multiinit(), addmultiA(), multimessage(), cleanmulti() and checkmulti()
  41.   functions.  The new scheme shares message ports, and efficiently
  42.   dispatches on the message data.  This is *massively* more efficient than
  43.   using the old scheme (OR-ing the signal masks of each window), and
  44.   effectively removes the limit of windows that a GUI can use.
  45. - Changed 'info' default to -1, which now gets translated to the guihandle.
  46.   This helps a lot with multi-window GUIs.
  47. - Changed 'data' default to -1, which now gets translated to the gadget
  48.   (not the *real* gadget, but the one that can be used with the setXXX()
  49.   functions). 
  50. - Changed the default screen to be the *default* public screen (rather than
  51.   specifically Workbench).
  52. - Changed AppWindow gadget location code to make it more robust, and now
  53.   includes the gadget label as "hittable".
  54. - Added a short description of the examples to this doc.
  55. - Added a reference to the guihandle to each PLUGIN so they can more easily
  56.   access the GUI window and use the GUI manipulation functions.
  57. - Added closewin()/openwin() to enable the window to be temporarily closed
  58.   and opened.  These are most useful for iconification (see the iconify and
  59.   toolify PLUGINs).  Note that this new feature may break old PLUGINs that
  60.   assume the GUI window will never change.
  61. - Added extra 'maxw' and 'maxh' parameters to make window open with maximum
  62.   width/height (taking into account position, too).
  63. - Added extra 'wintype' parameter to give control over window borders.
  64. - Added some more changeXXX() functions, and changed (sorry!) the other
  65.   changeXXX() functions to make them more uniform.
  66. - Added extra checking in message loop to ignore stray IDCMP_MOUSEMOVE
  67.   messages.  This is needed because GadTools doesn't identify the gadget if
  68.   you use GACT_FOLLOWMOUSE, so your PLUGIN finds it hard to trap this
  69.   message properly.
  70.   [Problem reported by Ralph Wermke <wermke@rz.uni-greifswald.de>]
  71. - Fixed bug in key handling code for the SLIDER gadget.
  72.   [Bug reported first by Fred van der Zee <free@xs4all.nl>]
  73. - Fixed an old bug: guihandles weren't deallocated by cleangui().
  74. - Fixed an old bug: some messages weren't getting replied.
  75. - Fixed an old bug: window wasn't being centred on screen if smaller than
  76.   display (and may not have been openable).
  77. - Minor changes to the layout of a couple of gadgets.
  78. - Made gadtoolsbase and workbenchbase public, mainly so that PLUGINs
  79.   can use them (if you have a GUI open then they must be valid).
  80. - Made things more friendly for multi-tasking: gh.wnd is NIL when the
  81.   GUI is in an unmodifiable state.
  82. - Made awprocs use a copy of the appmessage, mainly so that they can do
  83.   things like manipulate the GUI without problems.
  84. - Made a third version of EasyGUI.  This is EasyGUI_debug.m, which is the
  85.   same as EasyGUI.m except that it will print a short diagnostic message
  86.   before raising an exception.  This should be used when developing your
  87.   program to help track down the actual reason for a fault.
  88.  
  89. Changes from the v3.2e version:
  90. - Lots of minor fixes to most gadgets.
  91. - Added conditional resizing.
  92. - Added (optional) data field for all gadgets.
  93. - Added Style Guide compliant keyboard shortcuts.
  94. - Added extra arguments to some PLUGIN methods.
  95. - Added simple mechanism for PLUGINs to use GadTools gadgets (gtrender()).
  96. - Added AppWindow support for main window, *BUTTON, LISTV, STR and PLUGINs.
  97. - Added a lot of GUI manipulation functions.
  98. - Made an EasyGUI_lite version without a lot of features.
  99.  
  100. changes from the v3.2a version:
  101. - now supports PLUGINs for unlimited complex gui's!!! (check section 5)
  102. - added settext() and setnum()
  103. - fixed NUM gadget
  104. - added topaz-fallback version
  105. - bug: rendered into the border when used with sysihack
  106. - bug: could cause enforcer hits when some strings were NIL
  107. - bug: dealocation of resources in wrong order caused problems
  108.  
  109. changes from the v3.1a version:
  110. - new functions to access/modify gadgets while GUI is active
  111. - easily add gadtools menus
  112. - more complete docs
  113. - works better with multiple simultanuous EasyGUIs
  114. - LISTV, MX and CYCLE have an extra "current" parameter now
  115. - STR now takes an _estring_ as value (change this in old sources!)
  116. - bug: current gadget values would reset upon resize
  117. - bug: would open in middle of screen instead of visible part
  118. - many tiny bugs removed
  119.  
  120. +---------------------------------------------------------------+
  121. |       1. EasyGUI Intro                                        |
  122. +---------------------------------------------------------------+
  123.  
  124. EasyGUI takes the form a module file that needs to be included into your E
  125. source (needless to say, it needs v2.04/v37 of the OS).  The most simple
  126. form of constructing a GUI consist of calling the function easyguiA() with
  127. a (possibly nested) E list which describes your GUI.  just to show how
  128. Easy, try this source:
  129.  
  130.         MODULE 'tools/EasyGUI'
  131.         PROC main() IS easyguiA('um,...',[BUTTON,0,'Ok!'])
  132.  
  133. This'll open a window with just one gadget in it, and wait for the user to
  134. push it. If easyguiA() can't get what it wants, it'll start throwing around
  135. exceptions, so we'll probably need an exception handler to be able to
  136. inform the user properly (see below).
  137.  
  138. The first arg of easyguiA() is the window title, the second one is the GUI
  139. description. The form of these desciptions is quite simple: It's a list
  140. with as first element the type of gadget, the second is called an action
  141. value (more later), and the rest is gadget-specific.
  142.  
  143. To be able to build GUI's outof more components than just one gadget, one
  144. can group gadgets with a ROW and a COL list:
  145.  
  146.         [COLS,
  147.           [BUTTON,1,'Ok'],
  148.           [BUTTON,0,'Cancel']
  149.         ]
  150.  
  151. This'll create a new group, consisting of two gadgets next to each other.
  152. COLS and ROWS groups are like a single gadget, i.e. you can easily put them
  153. into other groups, to create GUI's of infinite complexity.
  154.  
  155. Other Grouping functions are EQCOLS and EQCOLS, which try to align gadgets
  156. in a group. IF you get strange layouts using these, you should try grouping
  157. subgroups before putting them in a larger group.
  158.  
  159. [BEVEL,a] will put a bevel box around a, whatever it is (a gadget, a
  160. group...), and BEVELR is the recessed version.
  161.  
  162. Other elements of groups are mostly gadgets, which have a specific #of
  163. arguments. [If the number of arguments is incorrect, EasyGUI will raise the
  164. "Egui" exception.]
  165.  
  166. The first element is always the type of gadget to create (see below). The
  167. second element is always something called an "actionvalue", which tells
  168. EasyGUI what needs to be done when the user interacts with the gadget.  All
  169. elements after that are gadget specific.
  170.  
  171. An action value may be:
  172. - a small positive integer (0-1000). If the user selects this gadget,
  173.   EasyGUI will close the window, and return that value as returnvalue from
  174.   the easyguiA() call. This is meant for "Ok" / "Cancel" type buttons.
  175. - a pointer to an "action function". If the user selects this gadget,
  176.   EasyGUI will call the function with as arguments depending on the type of
  177.   gadget (for example a slider will get it's current value).  After the
  178.   actionfunction returns, EasyGUI continues processing messages from the
  179.   GUI.
  180.   example:
  181.  
  182.         ...[BUTTON,{load},'Load'],...
  183.  
  184.         PROC load(info) IS WriteF('You pushed the "Load" button!\n')
  185.  
  186.   
  187.   the value of `info' is explained below. Or:
  188.  
  189.         DEF s[100]:STRING
  190.  
  191.         ...[STR,{str},'input:',s,50,4],
  192.            [CYCLE,{cycle},'choose:',['Yep','Nope',NIL],1],...
  193.  
  194.         PROC str(info,news) IS WriteF('the new string is: \s\n',news)
  195.         PROC cycle(info,newc) IS WriteF('the new choice is: \d\n',newc)
  196.  
  197.   In the action function, you can store the new value, however EasyGUI
  198.   keeps track of it itself too: In the case of the STR above it will
  199.   StrCopy() new values into your estring, so it automatically has the
  200.   correct value after closing. In the case of all other gadgets it stores
  201.   the new (integer) value in the list (so that `1' in `CYCLE' may become
  202.   `0').  This has the added benefit that windows that are opened and then
  203.   closed again will automatically start with the current values.
  204.  
  205.   If you want to close the GUI from an action function then you can call
  206.   the quitgui() function, which raises a "QUIT" exception (be careful to
  207.   not handle this exception in your code -- just ReThrow() it if your
  208.   action function has an exception handler).  The single argument to
  209.   quitgui() (which defaults to 0) will be returned from the easyguiA() call,
  210.   in the same way that action values are.  The definition of quitgui() is:
  211.  
  212.         PROC quitgui(ret=0) IS Throw("QUIT",ret)
  213.  
  214.   There are two new, optional arguments to action functions: `qual' and
  215.   `data'.  If you wish to use these arguments your action function must
  216.   include them at the beginning (and you must have a `data' argument if you
  217.   want to use the `qual' argument).  For instance, a button action function
  218.   can be defined in any of these three ways:
  219.  
  220.          PROC action(info) IS WriteF('info=$\h\n',
  221.                                      info)
  222.          PROC action(data,info) IS WriteF('info=$\h,data=$\h\n',
  223.                                           info,data)
  224.          PROC action(qual,data,info) IS WriteF('info=$\h,data=$\h,qual=$\h\n',
  225.                                                info,data,qual)
  226.  
  227.   (This scheme gives *full* compatibility with the old EasyGUI action
  228.   functions, whilst still allowing the new features to be used.)
  229.  
  230.   The `data' argument is the optional data field specified in the gadget.
  231.   If it is not specified or it's -1 then the actual data value that is used
  232.   is the gadget list pointer (for use with the setXXX() functions).  You
  233.   could use it, instead, to pass a pointer to an object specific to the
  234.   gadget.  The action function can then just call a method of that object.
  235.   This allows the same action function to be used by a number of different
  236.   gadgets, with the specific action being carried out via the data element
  237.   (since the data can be different for each gadget).
  238.  
  239.   The `qual' is basically the qualifier part of the intuimessage used to
  240.   indicate gadget clicks.  Use the IEQUALIFIER_XXX constants from the
  241.   module 'devices/inputevent' to see which qualifiers were pressed when
  242.   the gadget was clicked.  For example:
  243.  
  244.         PROC buttonaction(qual,data,info)
  245.           IF qual AND (IEQUALIFIER_LSHIFT OR IEQUALIFIER_RSHIFT)
  246.             PrintF('You were pressing a shift key when you clicked on me!\n')
  247.           ENDIF
  248.         ENDPROC
  249.  
  250. The easyguiA() function:
  251.  
  252.         easyguiA(windowtitle,gui,tags=NIL)
  253.  
  254. `tags' is a taglist which can use the following tags:
  255.  
  256. EG_INFO
  257.   the data may be ANY value, and is passed as an arg to the action
  258.   functions.  For example if you write a prefsrequester, this may be the
  259.   the prefs OBJECT.  Your actionfunctions then have a simple task changing
  260.   the value of the element in question.  (If this is -1 or not present,
  261.   then it the info used will be the 'guihandle' value for this GUI.  See
  262.   Chapter 4.)
  263.  
  264. EG_SCRN
  265.   the data is an optional screen ptr to open on. if NIL or not present
  266.   EasyGUI opens on the default public screen (usually Workbench).
  267.  
  268. EG_FONT
  269.   the data is a fontdescription (i.e., a `textattr').  If NIL or not
  270.   present, EasyGUI will use the same font as the screen (for Workbench this
  271.   is the font the user selected as "screenfont" in fontprefs).
  272.  
  273. EG_MENU
  274.   the data is a newmenus structure (as in gadtools.library). EasyGUI will
  275.   then automatically attach it to the window and arrange any messages.  You
  276.   can give the same actionvalues as gadgets in the newmenu.userdata, and
  277.   the actionfunction can be the same as for a `BUTTON', i.e.:
  278.  
  279.         [...,NM_ITEM,0,'Load','l',0,0,{load},...]:newmenu
  280.  
  281.   can use the same load() as in the example further above (the optional
  282.   `qual' and `data' arguments [see below] will always be NIL). [The
  283.   constants NM_ITEM, etc., are from the module 'libraries/gadtools'.]
  284.  
  285. EG_GHVAR
  286.   the data is the address of a LONG variable which gets a copy of the
  287.   guihandle (see Multiple Windows, below).  You just specify something like
  288.   {gh} instead of having to use guiinitA(), etc.  Note that you can also
  289.   get the guihandle by using the new default for the `info' of a GUI
  290.   (as described above).
  291.  
  292. EG_AWPROC
  293.   the data is a function to be called when the user drops icons on the
  294.   window (and no gadget handles the drop).  By default, this is NIL and
  295.   this means that the window will not to be made into an AppWindow.  If
  296.   it's *not* NIL then the window *will* be an AppWindow, and the *BUTTON,
  297.   LISTV and STR gadgets will get their awprocs called if icons are dropped
  298.   directly on them (PLUGIN gadgets can also react to AppWindow messages).
  299.   If the drop does not land on a gadget with an awproc then this awproc
  300.   (for the whole window) will be called.  (See the examples.)  awprocs are
  301.   like action functions and can be defined in one of two ways:
  302.  
  303.         PROC awproc(info,awmsg:PTR TO appmessage)
  304.         PROC awproc(data,info,awmsg:PTR TO appmessage)
  305.  
  306.   `info' is the GUI info, `awmsg' is a *copy* of the appmessage and `data'
  307.   is the optional data field for the gadget (or the `plugin_object' for
  308.   PLUGINs, and NIL for the window one).
  309.  
  310. EG_TOP, EG_LEFT
  311.   the data define the top-left coordinate of the window.  If either of them
  312.   is -1 (the default), then the window will be centred on that axis (in the
  313.   visible part of the screen).
  314.  
  315. EG_MAXW, EG_MAXH
  316.   the (boolean) data specify whether to try make the window size maximal in
  317.   width or height (based on screen size), rather than the default of
  318.   minimal (based on the GUI).  If you specify a position then the maximal
  319.   size of that axis will be the remaining part of the screen.  So, on a
  320.   screen of width 640, if you specify EG_LEFT of 100 then the maximum width
  321.   the window can be is 540.
  322.  
  323. EG_WTYPE
  324.   the data is a constant to dictate the window decoration (i.e., what
  325.   happens with the borders).  The choices are:
  326.  
  327.         WTYPE_SIZE     the default, which gives you all the standard
  328.                        gadgets and a size gadget at the bottom.
  329.         WTYPE_NOSIZE   omits the size gadget.
  330.         WTYPE_BASIC    just has a simple border around the window.
  331.         WTYPE_NOBORDER has (suprisingly) no border.
  332.  
  333.   Be careful with these last two options as there is no close gadget for
  334.   the user to click -- you must provide them with your own method of
  335.   closing the GUI (a menu item?).  (Note: the window title is ignored with
  336.   the last two types, since there's no title bar.)
  337.  
  338. EG_CLOSE
  339.   the data is an action value/function used when the user clicks the close
  340.   gadget on the GUI window.  This is most useful for multi-window GUIs (see
  341.   Multiple Windows), but it can be useful to prompt the user to confirm
  342.   before quitting the GUI.  The action value will be returned from
  343.   easyguiA()/guimessage()/multiloop()/multimessage(), as usual.  The action
  344.   function can be defined in one of two ways:
  345.  
  346.         PROC closeproc(info)
  347.         PROC closeproc(mh:PTR TO multihandle,info)
  348.  
  349.   `info' is the GUI's info parameter (see above), and `mh' is the
  350.   multi-window handle (see Multiple Windows) or NIL if it's a single window
  351.   GUI.
  352.  
  353. EG_CLEAN
  354.   the data is a function to be called when the GUI is destroyed (e.g., by
  355.   calling cleangui()).  This is most useful for multi-window GUIs (see
  356.   Multiple Windows), but it can generally be useful for cleaning up the
  357.   GUI's PLUGINs (see Chapter 5).  The function will be called *after* the
  358.   window and the GUI has been closed and deallocated, so, for example, the
  359.   PLUGINs will no longer be on screen.  It should be defined like this:
  360.  
  361.         PROC cleanproc(info)
  362.  
  363.   `info' is the GUI's info parameter (see above).  Note: if guiinitA() or
  364.   addmultiA() cause an exception then this function will *not* be called.
  365.   This makes it easier to setup a GUI (see the examples).
  366.  
  367. EG_HIDE
  368.   the (boolean) data specifies whether the GUI window is initially hidden
  369.   (closed).  The default is FALSE; if you specify TRUE then you can use
  370.   openwin() to show the window when you want it to be seen.  Note: this tag
  371.   is a bit useless for a normal call to easyguiA() as there's little chance
  372.   of it receiving any GUI messages if the window is closed (so the Wait()
  373.   will never return).
  374.  
  375.  
  376. +---------------------------------------------------------------+
  377. |       2. Gadgets                                              |
  378. +---------------------------------------------------------------+
  379.  
  380. general format: [NAME,action,text,...]
  381. in {}: which direction it may resize.
  382. + = a value that can be affected lateron with the set#? functions
  383. * = optional value (can be omitted)
  384.  
  385. Each gadget shows the gadget template, explanation, the form of the
  386. actionfunction, and a typical example.
  387.  
  388. The optional arguments to action functions (qual and data) are described in
  389. the above chapter.
  390.  
  391.  
  392. [BUTTON,action,intext,data*,key*,awproc*,disabled+*]
  393.   data = user data value passed to action function
  394.   key = keyboard shortcut (presses button)
  395.   awproc(data*,info,awmsg) = AppWindow proc (see above)
  396.   disabled = whether this gadget is disabled or not
  397.   buttonaction(qual*,data*,info)
  398.   example: [BUTTON,0,'Cancel']
  399.  
  400. [CHECK,action,righttext,checkedbool+,lefttextbool,data*,key*,disabled+*]
  401.   checkedbool = whether gadget should initially be check-marked
  402.   key = keyboard shortcut (toggles check)
  403.   disabled = whether this gadget is disabled or not
  404.   checkaction(qual*,data*,info,checkedbool)
  405.   example: [CHECK,{case},'Ignore case',TRUE,FALSE]
  406.  
  407. [INTEGER,action,lefttext,num+,relsize,data*,key*,disabled+*]
  408.   num = initial value
  409.   key = keyboard shortcut (activates gadget)
  410.   disabled = whether this gadget is disabled or not
  411.   integeraction(qual*,data*,info,newnum) {x}
  412.   example: [INTEGER,{v},'int:',5,3]
  413.   (Note: see discussion of getinteger() in chapter 4 below.)
  414.  
  415. [LISTV,action,textabove,relx,rely,execlist+,readbool,selected,current+,
  416.        data*,key*,awproc*,disabled+*]
  417.   execlist = ptr to an execlist. (see tools/constructors.m)
  418.   readbool = whether listview is read-only (action is ignored if it is!)
  419.   selected = 0=none, 1=highlight/show selected
  420.   key = keyboard shortcut (unshifted->select next, shifted->prev)
  421.   awproc(data*,info,awmsg) = AppWindow proc (see above)
  422.   disabled = whether this gadget is disabled or not
  423.   listviewaction(qual*,data*,info,num_selected) {x,y}
  424.   example: [LISTV,0,NIL,5,5,filenamelist,0,NIL,0]
  425.   (Note: disabling doesn't work under V37.)
  426.  
  427. [MX,action,righttext,nil_term_elist,lefttextbool,current,
  428.     data*,key*,disabled+*]
  429.   (Note: under v37 the righttext is spaced correctly but not rendered.)
  430.   key = keyboard shortcut (unshifted->next choice, shifted->prev, wraps)
  431.   disabled = whether this gadget is disabled or not
  432.   mxaction(qual*,data*,info,num_selected)
  433.   example: [MX,{v},NIL,['One','Two','Three',NIL],FALSE,1]
  434.   (Note: disabling doesn't work under V37.)
  435.  
  436. [CYCLE,action,lefttext,nil_term_elist,current,data*,key*,disabled+*]
  437.   key = keyboard shortcut (unshifted->next choice, shifted->prev, wraps)
  438.   disabled = whether this gadget is disabled or not
  439.   cycleaction(qual*,data*,info,num_selected)
  440.   example: [CYCLE,{v},'choose:',['Yep','Nope',NIL],1]
  441.  
  442. [PALETTE,action,lefttext,depth,relx,rely,current+,data*,key*,disabled+*]
  443.   (Note: the current field is new to v3.3a and is _not_ optional, so any
  444.   existing v3.2e sources using a PALETTE gadget will need a small edit.)
  445.   depth = 1..8, number of bitplanes this color is for
  446.   key = keyboard shortcut (unshifted->next pen, shifted->prev, wraps)
  447.   disabled = whether this gadget is disabled or not
  448.   paletteaction(qual*,data*,info,colour) {x,y}
  449.   example: [PALETTE,{v},'color:',3,5,2]
  450.  
  451. [SCROLL,action,isvert,total+,top+,visible+,relsize,data*,key*,disabled+*]
  452.   total = resolution of scroller
  453.   top = current top represented
  454.   visible = current
  455.   key = keyboard shortcut (unshifted->increment, shifted->decrement)
  456.   disabled = whether this gadget is disabled or not
  457.   scolleraction(qual*,data*,info,curtop) {x|y}
  458.   example: [SCROLL,{v},FALSE,10,0,2,2]
  459.  
  460. [SLIDE,action,lefttext,isvert,min,max,cur+,relsize,levelformat,
  461.        data*,key*,disabled+*]
  462.   min,max = value range of slider
  463.   cur = current value
  464.   levelformat = string that shows levelformat, example '%2ld'. leave
  465.     a large amount of spaces left in lefttext for this.
  466.   key = keyboard shortcut (unshifted->increment, shifted->decrement)
  467.   disabled = whether this gadget is disabled or not
  468.   slideraction(qual*,data*,info,cur) {x|y}
  469.   example: [SLIDE,0,'Colors:',FALSE,1,8,3,5,'']
  470.  
  471. [STR,action,lefttext,initial+,maxchars,relsize,
  472.      over*,data*,key*,awproc*,disabled+*]
  473.   initial = initial string contents: NOTE: HAS TO BE AN ESTRING!
  474.   maxchars = max #of chars for string
  475.   over = overwrite mode boolean (default is FALSE, i.e., insert mode)
  476.   key = keyboard shortcut (activates gadget)
  477.   awproc(data*,info,awmsg) = AppWindow proc (see above)
  478.   disabled = whether this gadget is disabled or not
  479.   stringaction(qual*,data*,info,string) {x}
  480.   (Note: action function is passed the E-string, not the gadget's buffer.)
  481.   example: [STR,0,'Pattern',s,100,5]      (DEF s[100]:STRING)
  482.   (Note: see discussion of getstr() in chapter 4 below.)
  483.  
  484. [TEXT,text,lefttext,borderbool,relsize] {x}
  485.   borderbool = whether or not a recessed bevelbox is placed around 'text'
  486.   example: [TEXT,'Selected Fonts',NIL,FALSE,3]
  487.  
  488. [NUM,int,lefttext,borderbool,relsize] {x}
  489.   borderbool: as TEXT
  490.   example: [NUM,123,'num:',TRUE,5]
  491.  
  492. [SBUTTON,action,intext,data*,key*,awproc*,disabled+*] {x}
  493.   same as button, only now resizes horizontally.
  494.  
  495. [PLUGIN,action,plugin_object,isgt*,awproc*]
  496.   isgt = whether this PLUGIN is made from GadTools gadgets (see chapter 5)
  497.   awproc(plugin_object*,info,awmsg) = AppWindow proc (see above)
  498.   pluginaction(info,plugin_object)
  499.   (see separate chapter 5 on using/implementing these).
  500.  
  501. [BAR], [SPACE] {x,y}, [SPACEH] {x}, [SPACEV] {y}
  502.   BAR places a nice divider-bar between gadgets/groups. Whether it's
  503.   horizontal or vertical depends on which group it is in.
  504.   SPACE/SPACEH/SPACEV do nothing, they only eat up space. This can be very
  505.   handy in GUI design, they act like a spring between elements (do not use
  506.   them on the borders of a GUI, only in the middle).
  507.  
  508.  
  509. #?text:
  510.   (where #? is left/right etc.): a text to place next to the gadget.  Often
  511.   is allowed to be NIL.
  512.  
  513. relsize,relx,rely:
  514.   Generally gadgets will automatically get a size depending on a number of
  515.   factors, but relsize allows the programmer to give a minimum size for
  516.   certain gadgets, thereby sizing a whole group.  If other gadgets already
  517.   account for the minimum size, this one can safely be set to a low value
  518.   such as 2.  All these sizes are calculated in terms of the _height_ of
  519.   the font.  Always try out your GUI with different fonts.  For example if
  520.   you design a gui that only just fits horizontally with an 8 point font on
  521.   640x200, when run on with a 13 point font on 640x512, the gui will be
  522.   quite a bit bigger horizontally, but the screen isn't, so it won't fit.
  523.   (see also: the "bigg" exception below).
  524.  
  525. nil_term_elist:
  526.   a nil-terminated E list, such as ['One','Two','Three',NIL]
  527.  
  528. isvert:
  529.   TRUE if gadget needs to be vertical, horizontal by default.
  530.  
  531. key:
  532.   All keyboard shortcuts are optional (so marked with a * in the following
  533.   descriptions).  If specified then they must be lowercase letters ("a" to
  534.   "z").  However, the shifted and unshifted keystrokes are *both* handled,
  535.   in the way described by the Style Guide (and this is briefly outlined for
  536.   each gadget).  Also, if a key is specified then an "_" in the gadget
  537.   label text indicates the character in the label which is to be
  538.   underscored (and this ought to be the same letter as the key).  If a key
  539.   is not specified then any "_"s in the label are not special.  (If an
  540.   action function is invoked as a result of a key press then the `qual'
  541.   will always be 0.)
  542.  
  543. disabled:
  544.   If this optional field is specified then the gadget can be disabled and
  545.   enabled using the setdisabled() function (see below, chapter 4), and the
  546.   current status of the gadget will be recorded in this field, too.
  547.  
  548.  
  549. The following constants/enumerations are defined in order to make
  550. referencing/creating the lists for each gadget a bit more readable.
  551.  
  552.   EXPORT ENUM BEV_GUI=1,
  553.     BUT_ACT=1, BUT_TXT,  BUT_DATA, BUT_KEY,  BUT_APPW, BUT_DIS,
  554.     CHK_ACT=1, CHK_TXT,  CHK_VAL,  CHK_LEFT, CHK_DATA, CHK_KEY,  CHK_DIS,
  555.     INT_ACT=1, INT_TXT,  INT_VAL,  INT_REL,  INT_DATA, INT_KEY,  INT_DIS,
  556.     LST_ACT=1, LST_TXT,  LST_RELX, LST_RELY, LST_LIST, LST_RO,   LST_SHOW,
  557.                LST_CURR, LST_DATA, LST_KEY,  LST_APPW, LST_DIS,
  558.      MX_ACT=1,  MX_TXT,   MX_LIST,  MX_LEFT,  MX_CURR,  MX_DATA,  MX_KEY,
  559.                 MX_DIS,
  560.     CYC_ACT=1, CYC_TXT,  CYC_LIST, CYC_CURR, CYC_DATA, CYC_KEY,  CYC_DIS,
  561.     PAL_ACT=1, PAL_TXT,  PAL_DEP,  PAL_RELX, PAL_RELY, PAL_CURR, PAL_DATA,
  562.                PAL_KEY,  PAL_DIS,
  563.     SCR_ACT=1, SCR_VERT, SCR_TOTL, SCR_TOP,  SCR_VIS,  SCR_REL,  SCR_DATA,
  564.                SCR_KEY,  SCR_DIS,
  565.     SLI_ACT=1, SLI_TXT,  SLI_VERT, SLI_MIN,  SLI_MAX,  SLI_CURR, SLI_REL,
  566.                SLI_FMT,  SLI_DATA, SLI_KEY,  SLI_DIS,
  567.     STR_ACT=1, STR_TXT,  STR_STR,  STR_MAX,  STR_REL,  STR_OVR,  STR_DATA,
  568.                STR_KEY,  STR_APPW, STR_DIS,
  569.     TXT_VAL=1, TXT_TXT,  TXT_BORD, TXT_REL,
  570.     NUM_VAL=1, NUM_TXT,  NUM_BORD, NUM_REL,
  571.     PLG_ACT=1, PLG_OBJ,  PLG_GT,   PLG_APPW
  572.  
  573.  
  574. +---------------------------------------------------------------+
  575. |       3. How Layout Works                                     |
  576. +---------------------------------------------------------------+
  577.  
  578. EasyGUI works by automatically layouting the gadgets on the screen. In a
  579. first pass, it will compute the minimum size for each element: for gadgets
  580. this involves the size of fonts and various other things. For a ROWS list,
  581. for example, it will take the width of the biggest gadget as its width, and
  582. computes its height by adding the heights of all other gadgets. For EQROWS
  583. this is slightly more complicated: EasyGUI also computes a "middle" for
  584. various gadgets, often between the text that denotes what a gadget is about
  585. and the gadget itself. It then tries to align all of these. for EQCOLS it
  586. simply tries to make all columns equal width.
  587.  
  588. In a second pass, EasyGUI assigns the final coordinates to all gadgets.
  589. Important to notice is that in a GUI often there is more space available
  590. than is required for a gadget, for example the gadget above it in a ROWS
  591. environment is much wider. Also, the user may have resized the window. To
  592. do something useful with this space, EasyGUI looks at which gadgets can do
  593. something useful with extra space, such as LISTV, or STR, SCROLL etc. This
  594. process of granting extra space propagates through ROWS/COLS, which act as
  595. gadgets themselves. Gadgets like BUTTON don't benefit from more space, so
  596. they give that away to their neighbours.
  597.  
  598.  
  599. +---------------------------------------------------------------+
  600. |       4. Advanced features                                    |
  601. +---------------------------------------------------------------+
  602.  
  603. Different versions of EasyGUI
  604. -----------------------------
  605. For those who care more about saving a few KB than the extra functionality,
  606. there are two different versions:
  607.  
  608.      1) EasyGUI_lite.m
  609.         This does not have multi-window support, keyboard support for
  610.         gadgets, AppWindow support or GUI manipulation functions (i.e.,
  611.         dynamically changing a GUI, window blocking and gadget disabling).
  612.           Current code size: 17324 bytes.
  613.      2) EasyGUI.m
  614.         The full version, with nothing taken out.
  615.           Current code size: 23968 bytes.
  616.  
  617. There's also a third version of EasyGUI which is just a variant of
  618. EasyGUI.m: this is a debug version, EasyGUI_debug.m, which gives some more
  619. information about an error before raising an exception (so you shouldn't
  620. really distribute programs compiled with this module -- it's just for
  621. development purposes).
  622.  
  623.  
  624. Throwing exceptions from actionfunctions
  625. ----------------------------------------
  626. is allowed: EasyGUI will catch it, close the window properly, and then
  627. ReThrow() if it wasn't a "QUIT" exception.  If it was "QUIT" then the
  628. exceptioninfo value will be the return value of the easyguiA()/guimessage()
  629. or multiloop()/multimessage() functions, just like the way actionvalues
  630. work (except for the slight difference in a multi-window GUI, as noted
  631. below).
  632.  
  633. Exceptions raised by EasyGUI itself:
  634.  
  635. "MEM"   -- no mem
  636. "GUI"   -- for things like CreateGadgetA, OpenWindowTagList etc.
  637. "GT"    -- couldn't open gadtools.library
  638.  
  639. "bigg"  -- for "BIG Gui": interface is calculated to be bigger than the
  640.            screen.  Generally you should keep gui's small, so that they
  641.            still fit on 640x200 topaz screens. If the user runs Times/30 on
  642.            a screen this size, he probably knows he has a problem.
  643. "Egui"  -- a design error: most probably handed over a list to dogui() that
  644.            was either to long or too short
  645. <other> -- Raise()ed by own function
  646.  
  647.  
  648. Multiple Windows
  649. ----------------
  650. There are two ways of handling multiple windows in EasyGUI.  The first
  651. has really been superseded by the second, though.
  652.  
  653. 1) The simplest use of EasyGUI is just by calling easyguiA(). You can
  654.   however open any number of windows, and check messages for all of them.
  655.  
  656.         guiinitA(windowtitle,gui,tags=NIL)
  657.         guimessage(guihandle)
  658.         cleangui(guihandle)
  659.  
  660.   Call guiinitA() for each window (exactly the same arguments as
  661.   easyguiA().  Then, keep calling guimessage() for each of them, when
  662.   messages arive.  you can close them again with cleangui(), for example
  663.   when a gui returns a positive integer (the actioncode). Negative integers
  664.   signal that it simply finished processing all messages, but no need to
  665.   close the window yet.  Note: it is *not* safe to call cleangui() from
  666.   *any* action function (except as noted below, in the description of
  667.   cleanmulti()).  (If you want to close the GUI prematurely, you can use
  668.   the closewin() function.)
  669.  
  670.   example of usage of these three function (= definition easyguiA())
  671.  
  672.         EXPORT PROC easyguiA(windowtitle,gui,tags=NIL) HANDLE
  673.           DEF gh=NIL:PTR TO guihandle,res=-1
  674.           gh:=guiinitA(windowtitle,gui,tags)
  675.           WHILE res<0
  676.             Wait(gh.sig)
  677.             res:=guimessage(gh)
  678.           ENDWHILE
  679.         EXCEPT DO
  680.           cleangui(gh)
  681.           ReThrow()
  682.         ENDPROC res
  683.  
  684.   the object you get has some handy fields in there: the window in question
  685.   `wnd' (or NIL if it's currently closed), the sigmask `sig' (i.e., _not_
  686.   the signal bits) if you want to do a proper Wait() (OR them), the GUI's
  687.   info and the handle for the multi-window group `mh' (or NIL if this is a
  688.   single GUI) [see below for more details on this].
  689.  
  690.         OBJECT guihandle
  691.         /* Public (read-only) parts: */
  692.           wnd:PTR TO window
  693.           sig:LONG
  694.           info
  695.           mh:PTR TO multihandle  -> See below...
  696.         ENDOBJECT
  697.  
  698.   The GUI's info is provided to make retrieving the info from the guihandle
  699.   easier (in an EG_CLEAN proc, for instance).  If you want to draw into
  700.   `wnd': stdrast is automatically set to the last EasyGUI opened.  `wnd'
  701.   can also be used a flag to indicate when it is safe to manipulate the
  702.   GUI (to help with multi-tasking): when it's NIL it's not safe to modify
  703.   the GUI directly, unless you've been passed the window pointer (e.g.,
  704.   render() and clear_render()).  The setXXX() functions are always safe.
  705.   Note: `wnd' can change due to closewin()/openwin() calls which mean that
  706.   the GUI may be in different windows during its life.
  707.  
  708. 2) But starting in v3.3b, there's a much more efficient (and simpler) way
  709.   of handling multiple-window GUIs.  This uses the functions multiinit(),
  710.   addmultiA(), multiloop() (which uses multimessage()) and cleanmulti(), in
  711.   roughly the same way as the single window versions.  It's all based
  712.   around a `multihandle':
  713.  
  714.         OBJECT multihandle
  715.         /* Public (read-only) parts: */
  716.           sig:LONG
  717.           opencount:LONG
  718.         ENDOBJECT
  719.  
  720.         multiinit()
  721.         addmultiA(multihandle,windowtitle,gui,tags=NIL)
  722.         multiloop(multihandle)
  723.         multimessage(multihandle)
  724.         cleanmulti(multihandle)
  725.  
  726.   multiinit() is used to initialise a new group of GUIs and produce a new
  727.   `multihandle'.  It takes no arguments.  You must call this function first
  728.   and use the multihandle with the other functions to refer to your group
  729.   of GUIs.  You can still refer to each individual GUI using a guihandle
  730.   (see below).  A quick example to show how simple the new multi-window
  731.   scheme is:
  732.  
  733.         PROC multiplewindows() HANDLE
  734.           DEF mh=NIL, gh1:PTR TO guihandle, gh2:PTR TO guihandle,res
  735.           mh:=multiinit()
  736.           gh1:=addmultiA(mh,'GUI One',[BUTTON,{but1},'Press Me'])
  737.           gh2:=addmultiA(mh,'GUI Two',[BUTTON,{but2},'Press Me'])
  738.           -> Could add more GUIs...
  739.           res:=multiloop(mh)
  740.         EXCEPT DO
  741.           cleanmulti(mh)
  742.         ENDPROC
  743.  
  744.   addmultiA() is very much like guiinitA().  It creates a new window with
  745.   your specified GUI and returns the guihandle.  You can call this function
  746.   even from action functions, when the GUI group is active.
  747.  
  748.         addmultiA(mh:PTR TO multihandle,windowtitle,gui,tags=NIL)
  749.  
  750.   The extra parameter is `mh' to indicate the group to which this window
  751.   will be added.
  752.  
  753.   If the tag EG_CLOSE is not specified or the data is an action value
  754.   (between 0 and 1000) then the GUI will be destroyed and removed from the
  755.   group (the guihandle will now be invalid) and the action value will be
  756.   returned (from multimessage()) -- just like a normal action value.  If it
  757.   is an action function then the window is *not* closed and the action
  758.   function is called.  As stated above, you define such an action function
  759.   in one of two ways:
  760.  
  761.         PROC closeproc(info)
  762.         PROC closeproc(mh:PTR TO multihandle,info)
  763.  
  764.   `info' is the GUI's info parameter and `mh' is the multihandle for this
  765.   group.  Use `mh' to find the `opencount' -- the number of GUIs with open
  766.   windows.  This count will include this GUI so if it's equal to one then
  767.   you know this is the last open window in the group.  Your action function
  768.   may want to prompt the user and then close the window (using closewin()),
  769.   destroy the GUI and remove it from the group (using cleangui()), or leave
  770.   the window open.
  771.  
  772.   multiloop() is defined in terms of multimessage() and opencount, and is
  773.   similar to the definition of easyguiA().
  774.  
  775.         EXPORT PROC multiloop(mh:PTR TO multihandle)
  776.           DEF res=-1
  777.           WHILE res<0
  778.           EXIT mh.opencount=0
  779.             Wait(mh.sig)
  780.             res:=multimessage(mh)
  781.           ENDWHILE
  782.         ENDPROC res
  783.  
  784.   The signal mask for waiting for messages is `sig' in the multihandle.
  785.   You can use this for more complex Wait()s, and then call multimessage()
  786.   to handle any messages that may have arrived for any of the GUIs.  Any
  787.   action values generated by a GUI (or via quitgui()) are returned by
  788.   multimessage() and hence terminate multiloop().  The above example calls
  789.   multiloop() only once, so an action value will eventually destroy the
  790.   whole group (by calling cleanmulti()).  Note: a real action value will
  791.   cause the GUI that produced it to be closed via cleangui(), but a value
  792.   returned through use of quitgui() will not -- this is because if you've
  793.   called quitgui() then you can just as easily write code to close the
  794.   window (or whatever) in the same action function.
  795.  
  796.   By using the `opencount', the loop will be terminated when there are no
  797.   more open GUI windows.  Alternatively, if you are using your own Wait()
  798.   you might want to check that there are no GUIs left (even ones with
  799.   closed windows).  To this end there's the function multiempty() which
  800.   returns TRUE if and only if there are no GUIs in the group.  (Note: if
  801.   there are only GUIs left with no window then the simple Wait() will never
  802.   return!)
  803.  
  804.   cleanmulti() destroys all GUIs in the group (whether they have an open or
  805.   closed window) and deallocates the multihandle.  It is *not* safe to use
  806.   the multihandle or any of the guihandles after this.  So, in particular,
  807.   it is *not* safe to call cleanmulti() from *any* action function.  It is,
  808.   however, safe to call cleangui() on GUIs in the group, if you are using
  809.   cleanmulti() to do the final cleanup (rather than calling cleangui() on
  810.   remembered guihandles).
  811.  
  812.   To help with manipulating a group there are the multiexists() and
  813.   multiforall() functions, which work in a very similar way to ForAll() and
  814.   Exists().
  815.  
  816.         multiforall(varaddr,mh:PTR TO multihandle,expr)
  817.         multiexists(varaddr,mh:PTR TO multihandle,expr)
  818.  
  819.   `varaddr' is the address of a (global) guihandle variable, `mh'
  820.   identifies the GUI group and `expr' is a quoted expression to be
  821.   evaluated.  multiforall() will evaluate the expression for every GUI in
  822.   the group (whether its window is open or closed) and return TRUE if the
  823.   expression is TRUE (non-zero) for all GUIs, else it will return FALSE.
  824.   multiexists() will stop at the first GUI for which the expression is
  825.   TRUE, and return the value of the expression.  Unlike Exists(), you are
  826.   guaranteed that the variable pointed to by `varaddr' will contain the
  827.   guihandle of the corresponding GUI (or NIL if none were found).  So, you
  828.   can use multiexists() to find GUIs.  Note: be careful what the expression
  829.   does with the guihandle and the GUI group; it is quite safe to cleangui()
  830.   on the supplied guihandle, but it is not safe to affect any other GUI in
  831.   this way.  Any GUIs added to the group by the expression will not be part
  832.   of the forall or exists (for those who can't live without knowing: the
  833.   list is explored from head to tail, and new GUIs are added to the head;
  834.   so the last GUI considered will be the oldest GUI).
  835.  
  836.   For example, you can print the title of each GUI with an open window:
  837.  
  838.         multiforall({gh},mh,`IF gh.wnd THEN WriteF('\s\n',gh.wnd.title) ELSE 0)
  839.  
  840.   A final reminder: `varaddr' must be the *address* of a *global* variable
  841.   (and so must all the variables used in the quoted expression).
  842.  
  843.   Useful note: as long as a guihandle is valid (i.e., as long as cleangui()
  844.   has not been called on it), the normal GUI functions checkgui() and
  845.   guimessage() will actually work on the whole group that a GUI is in.
  846.   (Note: the proper, safe functions to use for multi-window GUIs are
  847.   checkmulti() and multimessage(), respectively.)
  848.  
  849.  
  850. Multiple copies of a GUI
  851. ------------------------
  852. If your app allows to have multiple copies of the _same_ gui open at the
  853. same time (for example if you open windows recursively, or you use the
  854. multiple window technique described above to open more instances of one
  855. GUI), you might need to dynamically allocate the GUI description, because
  856. of the way dynamically computed values are put into static E lists. A GUI
  857. desciption with [] lists is static, i.e. only allocated once. Adding NEW to
  858. all of them is hard to deallocate, and this is where disposegui() comes in.
  859. To safely use this feature, allocate ALL lists belonging to the GUI
  860. desciption dynamically with NEW [...] (this does not include lists such as
  861. the one used for the various labels in CYCLE-gadgets).
  862.  
  863.         easyguiA('Bla',
  864.           gui:=NEW [ROWS,
  865.                  NEW [STR,{str},'input:',s,50,4],
  866.                  NEW [CYCLE,{cycle},'choose:',['Yep','Nope',NIL],1]])
  867.         disposegui(gui)
  868.  
  869. Call disposegui() with the top-level list. On each gadget-list (i.e.,
  870. NEW [CYCLE,...]) it will simply call FastDisposeList(), on COLS and ROWS
  871. etc.  it will first deallocate each element recursively.
  872.  
  873.  
  874. Manipulating Gadgets
  875. --------------------
  876. [This assumes you've got the guihandle by using the ghaddr argument of
  877. easyguiA(), the DIY version of EasyGUI (as described under 'Multiple
  878. Windows'), or you're using the new default for the 'info' of a GUI.]
  879.  
  880. You might need to modify gadgets while a GUI is active, for example to set
  881. a slider when a corresponding integer gadget is modified by the user, or to
  882. change the contents of a listview.
  883.  
  884. You can denote gadgets to change by simply storing their addresses, i.e.:
  885.  
  886.         [COLS,
  887.           mygad:=[CHECK,....],
  888.           ...
  889.         ]
  890.  
  891. Now you can use `mygad' with some of the functions below. Note that, of
  892. course `mygad' isn't a gadget, but it helps EasyGUI to find the real
  893. gadget.
  894.  
  895.         setcheck(gh,gad,bool)
  896.         setinteger(gh,gad,new)
  897.         setlistvlabels(gh,gad,labs)
  898.         setlistvselected(gh,gad,active)
  899.         setlistvvisible(gh,gad,vis)
  900.         setmx(gh,gad,active)
  901.         setcycle(gh,gad,active)
  902.         setpalette(gh,gad,colour)
  903.         setscrolltop(gh,gad,top)
  904.         setscrolltotal(gh,gad,total)
  905.         setscrollvisible(gh,gad,visible)
  906.         setslide(gh,gad,new)
  907.         setstr(gh,gad,new)
  908.         settext(gh,gad,newtext)
  909.         setnum(gh,gad,newnum)
  910.  
  911. for all these: `gh' is the gui you're talking about (as returned from
  912. guiinitA()/addmultiA(), or via the `ghaddr' argument of easyguiA() or the
  913. new default for the 'info' of a GUI), `gad' is a value that denotes the
  914. gadget as described above.  the third value is whatever you're changing
  915. about the gadget. Note that in doing so, you need to respect usual
  916. restrictions on gadtools gadgets, for example setlistvlabels() requires
  917. that you first set it to -1, then modify the list, and put it back.
  918. setlistvvisible() will try to make the indicated item in the LISTV visible.
  919. setlistvselected() will make a new selection and try to make it visible
  920. (and -1 turns off the selection).
  921.  
  922.         setdisabled(gh,gad,disabled=TRUE)
  923.  
  924. This applies to all gadgets, but works only if you've actually specified a
  925. value (TRUE or FALSE) for the optional `disabled' field for the gadget.
  926.  
  927.         realgadget:=findgadget(gh,list)
  928.  
  929. allows you to find the gadget address, for all those modifications that
  930. aren't possible with the above set#? functions. It returns an intuition
  931. gadget structure. Note that preferably you will want to use the set#?
  932. functions, as these cooperate with EasyGUI very well (in keeping track of
  933. the current value, for example: setstr() also copies the new value to the
  934. estring you attached to the gadget).  While there is at least one GUI still
  935. allocated the `gadtoolsbase' and `workbenchbase' are valid, so you can
  936. quite easily manipulate gadgets in action functions using GadTools
  937. functions.  (If you do open either of these libraries, be careful not to
  938. overwrite these variables with NIL!  That is, use an automatic exception on
  939. OpenLibrary() or otherwise check the return value before assigning it.)
  940.  
  941.         getstr(gh,gad)
  942.         getinteger(gh,gad)
  943.  
  944. These return and store the current value of a STR or INTEGER gadget (where
  945. gh and gad are as described above for the setxxx() functions).  They are
  946. useful because Intuition only sends a message (and so causes the current
  947. values to be stored) when the user hits the return or tab key in these
  948. gadgets.  So, if you really want to know a STR or INTEGER gadget's current
  949. value use getstr() or getinteger().
  950.  
  951.  
  952. Topaz Fallback
  953. --------------
  954. the function `easygui_fallbackA()' is equivalent to `easyguiA()' apart from
  955. the fact that when EasyGUI fails with the "bigg" exception, it will try
  956. again with topaz-8.  Note that you should never want to rely on topaz, this
  957. function was only added for emergency situations.  If your GUI is too big
  958. on some systems, you should redesign your GUI to fit comfortably instead.
  959. (see other parts of this doc that talk about GUI-size and testing).
  960.  
  961.  
  962. GUI Manipulation
  963. ----------------
  964.  
  965.         closewin(gh)
  966.  
  967. Temporarily closes the GUI window.  Use openwin() to reinstate the GUI.
  968. This function is useful for iconifying a GUI (see the iconify and toolify
  969. PLUGINs).  You can test whether a GUI's window is closed (or otherwise
  970. unmodifiable) by checking if the `wnd' element of the guihandle is NIL.
  971. Note that if your GUI is on the default public screen then it will no
  972. longer be a visitor (i.e., you can then use changescreen() to move it to a
  973. new screen).  (A blocked window is unblocked before it is closed.)
  974.  
  975.         openwin(gh)
  976.  
  977. Reopens a closed GUI window: it will reopen in the same position and size
  978. as it was when it closed.  Note that the window is not guaranteed to open
  979. correctly again (someone may have grabbed your memory, for example).  The
  980. window will always open unblocked.  Once open again, gh.wnd will be non-NIL
  981. (i.e., the address of the window).
  982.  
  983.         changegui(gh,gui)
  984.  
  985. Changes the GUI in a window (fairly) seamlessly.  The old GUI is removed
  986. and the new GUI tries to take its place, resizing if necessary (a NIL `gui'
  987. is just ignored).  The window will be resized if the new GUI's minimum size
  988. is bigger than the current size, or if the new GUI does not allow resizing.
  989. A side-effect of this new, dynamic ability to change GUIs is that the
  990. default window type is to have a size gadget, even the GUI can't be
  991. resized.  You can change this by specifying a different EG_WTYPE, or use
  992. changewindowtype().
  993.  
  994.         changemenus(gh,newmenus=NIL)
  995.  
  996. Changes the GUI's menus.  If `newmenus' is NIL or not present then the
  997. current menus are removed and the window is left with no menus.
  998.  
  999.         changeinfo(gh,info=-1)
  1000.  
  1001. Changes the GUI's info.  If `info' is -1 or not present then the GUI's
  1002. info is changed to be the guihandle for the window.  (Remember: the info is
  1003. passed to the GUI's action functions.)
  1004.  
  1005.         changetitle(gh,windowtitle=NIL)
  1006.  
  1007. Changes the title of the GUI's window.  (But remember that the title is
  1008. ignored for window type WTYPE_BASIC and WTYPE_NOBORDER.)
  1009.  
  1010.         changescreen(gh,scr=NIL)
  1011.  
  1012. If the GUI window is closed (gh.wnd=NIL) then this will alter the GUI's
  1013. screen (if it's open then this function does nothing).  If `scr' is NIL
  1014. then the default public screen will be used.  If the font was linked to the
  1015. screen then it will be updated, too.
  1016.  
  1017.         changefont(gh,tattr=NIL)
  1018.  
  1019. Again, this works only if the GUI window is closed.  If `tattr' is NIL then
  1020. the font of the screen is used.
  1021.  
  1022.         changewintype(gh,wintype=WTYPE_SIZE)
  1023.  
  1024. Another one that works only if the GUI window is closed.  This sets the
  1025. window border type.  You can use one of WTYPE_NOBORDER, WTYPE_BASIC,
  1026. WTYPE_NOSIZE and WTYPE_SIZE, as described above.
  1027.  
  1028.         movewin(gh,x=-1,y=-1)
  1029.  
  1030. Moves the window of the GUI referenced by gh to the new (top-left)
  1031. coordinate.  If x or y is -1 (the default) then that coordinate is not
  1032. changed.  (Note: the change is delayed until the next INTUITICK.)
  1033.  
  1034.         sizewin(gh,xs=-1,ys=-1)
  1035.  
  1036. Attempts to resize the window of the GUI referenced by gh.  If xs or ys is
  1037. -1 (the default) then that dimension is not changed.  The resizing is not
  1038. guaranteed to be carried out since the size may be smaller than the GUI's
  1039. minimum or the GUI may not be sizable.  (Note: the change is delayed until
  1040. the next INTUITICK.)
  1041.  
  1042. Simple window blocking to prevent the user using a GUI:
  1043.  
  1044.         blockwin(gh)
  1045.  
  1046. This puts up an invisible requester over the window of the GUI referenced
  1047. by gh, and disables window sizing.  If you're running v39+ then the busy
  1048. pointer will be set on this window.  You would use this to block a GUI
  1049. before you put up another one.  Note: the window can still be moved and
  1050. depth arranged.  (This works only if the GUI's window is open.)
  1051.  
  1052.         unblockwin(gh)
  1053.  
  1054. Reinstates the GUI, allowing the user to interact with it again.  The
  1055. blockwin() and unblockwin() calls nest, so you need an equal number of
  1056. unblockwin() calls to blockwin() calls before the window is actually
  1057. unblocked.  Note: a GUI window is implicitly unblocked (forcefully!) when
  1058. it is closed.  In general: try to design your GUIs such that the user can
  1059. use them all simultaneously, this is much friendlier (i.e., make use of the
  1060. multi-window support given by addmultiA()...).
  1061.  
  1062.         checkgui(gh)
  1063.  
  1064. Checks for any GUI messages and processes them, invoking actionfunctions if
  1065. necessary.  If this causes the GUI to want to be closed (e.g., the user has
  1066. pressed the close gadget), then a "QUIT" exception is thrown and the
  1067. exceptioninfo is the value that would have been returned by the easyguiA()
  1068. call (so, as with quitgui(), your exception handlers might like to make
  1069. "QUIT" a special case and just ReThrow() it).
  1070.  
  1071. This function is useful, for example, when you're in an action function
  1072. that's performing a long calculation.  By polling the GUI at convenient
  1073. points using this function you will make the GUI more responsive.  However,
  1074. you are responsible for coping with the possibility that the user may
  1075. cause, for instance, the same action function to be called again.  A simple
  1076. solution is use some kind of semaphore (a global boolean variable, for
  1077. example) to mark whether you are currently in an action function and busy.
  1078. See the led_test.e examples and the old CU Amiga tutorials on Amiga E.
  1079.  
  1080.         checkmulti(mh)
  1081.  
  1082. This is checkgui() for multi-window GUIs.  As mentioned above (in 'Multiple
  1083. Windows') you can use checkgui() to check and act on messages for *all* the
  1084. GUIs in the same group as the one identified by the guihandle, but the
  1085. guihandle must be valid.  This function uses the multihandle so is always
  1086. safe as long as the group exists.
  1087.  
  1088.  
  1089. +---------------------------------------------------------------+
  1090. |       5. PLUGINs                                              |
  1091. +---------------------------------------------------------------+
  1092.  
  1093. PLUGINs allow the programmer to extend EasyGUI with new functionality,
  1094. i.e., to add any kind of rendering/gadgets to the GUI, while cooperating
  1095. automatically with EasyGUI's layout/resizing.  You can use plugins to add
  1096. rendering areas in the midst of EasyGUI gadgetry (e.g., for graphics
  1097. programs), add BOOPSI gadgets to a GUIs etc.  You can supply ready-made
  1098. plugins for other programmers to use.
  1099.  
  1100.         OBJECT plugin
  1101.         /* Public (read-only) parts: */
  1102.           -> Position and size.
  1103.           x:INT,y:INT,xs:INT,ys:INT
  1104.           -> guihandle for the GUI the PLUGIN is on.
  1105.           gh:PTR TO guihandle
  1106.         ENDOBJECT
  1107.  
  1108. Any PLUGIN is an object inherited from the 'plugin' object found in
  1109. easygui.m.  To implement a new plugin all that needs to be done is redefine
  1110. a few methods.  Then, this PLUGIN can be plugged in to any EasyGUI with for
  1111. example:
  1112.  
  1113.         [PLUGIN,{plugaction},NEW mp.myplugin()]
  1114.  
  1115. in your GUI-spec. Whether the action-value is used depends on the PLUGIN,
  1116. as we'll see below.  If it is called it will be passed the PLUGIN object as
  1117. well as the GUI info:
  1118.  
  1119.   PROC pluginaction(info,plugin_object:PTR TO plugin)
  1120.  
  1121. Have a quick look at the plugin example sources, or keep them handy while
  1122. reading the bit below.
  1123.  
  1124. Creating the object
  1125. -------------------
  1126. create your new object as a 'plugin'-subtype.  You may add constructors/
  1127. destructors if you wish.  following methods implement the plugins
  1128. behaviour, and may be redefined:
  1129.  
  1130.         will_resize()
  1131.  
  1132. is called once just before the window is opened.  You should return a
  1133. flag-set telling in which ways your object can resize, making use of the
  1134. constants RESIZEX and RESIZEY, 0 of course meaning your object is fixed in
  1135. size (default method returns RESIZEX OR RESIZEY, i.e., resize in both
  1136. directions).  New to v3.3a is COND_RESIZEX and COND_RESIZEY, which allow
  1137. your PLUGIN to resize in the corresponding direction only if something else
  1138. in its gadget group is unconditionally resizable.  (For example, a BAR is
  1139. conditionally resizable, so that it does not force a group of BUTTONs to be
  1140. resizable.)
  1141.  
  1142.         min_size(ta:PTR TO textattr,fontheight)
  1143.  
  1144. is called once just before the window is opened.  ta is the font used
  1145. in the GUI.  you should return the _minimum_ x and y sizes of your
  1146. PLUGIN as _two_ returnvalues, making use of `fontheight' if you wish.
  1147. Note that EasyGUI may actually grant you a lot more space than just
  1148. the minimum space you ask for, depending on the other gadgets and
  1149. user-resizing.  If your object can have al sorts of sizes, pick a
  1150. relatively small one as minimum.  The default method just returns
  1151. (fontheight,fontheight)
  1152.  
  1153.         render(ta:PTR TO textattr,x,y,xs,ys,win:PTR TO window)
  1154.  
  1155. Here you should render your object to the window.  In the case of a gadget
  1156. this means creating the gadget and attaching it to the window (AddGList(),
  1157. RefreshGList(), make sure you render only your own gadget(s)).  ta is the
  1158. font used in the GUI.  (xs,ys) is always at least the minimum size you
  1159. asked for.  (x,y,xs,ys) is also copied to your object before this method is
  1160. called, for use in other methods).  The default method paints a nice black
  1161. box :-) You shouldn't take too long in this method as it will make window
  1162. redraw look slow.  (It is safe to use existing v3.2e PLUGIN modules, but to
  1163. recompile under v3.3a you will need to add the `ta' argument to your PLUGIN
  1164. render() method.)
  1165.  
  1166.         gtrender(gl,vis,ta:PTR TO textattr,x,y,xs,ys,win:PTR TO window)
  1167.  
  1168. New to v3.3a: a replacement for render() which enables simple addition of
  1169. GadTools gadgets to the standard EasyGUI gadgets.  If you want to use this
  1170. method instead of the normal render() then: 1) the PLUGIN must support it,
  1171. and 2) you must specify TRUE for the `isgt' field of the PLUGIN gadget.
  1172. gtrender() should simply create its gadgets by linking into the current
  1173. list (given by `gl') and using the visual info `vis'.  It should then
  1174. return the new gadget list (i.e., the last GadTools gadget linked in).  And
  1175. then that's it: your GadTools gadgets will be freed automatically, so if
  1176. your PLUGIN is just GadTools gadgets you don't need to override the normal
  1177. (empty) definition clear_render().  If you use gtrender() then you need not
  1178. override render(): this will help indicate a problem if users forget to
  1179. specify `isgt' with your PLUGIN.  See the password PLUGIN example.
  1180.  
  1181.         clear_render(win:PTR TO window)
  1182.  
  1183. mainly useful for gadgets to remove the gadget from the window and free it
  1184. (RemoveGList(), remove only your own gadget(s)!).  Normally render() is
  1185. called when the window opens, and clear_render() when the window closes,
  1186. when the user resizes, however, clear_render() and render() are called one
  1187. after another, in that order, to account for the changed window layout.
  1188. The default method does nothing.
  1189.  
  1190.         message_test(imsg:PTR TO intuimessage,win:PTR TO window)
  1191.  
  1192. is phase-1 of the message handling, splitted in two to not block intuition
  1193. too much.  In message_test() the only thing you should do is return TRUE
  1194. _if_ and _only_if_ the intuimessage is meant for your object, otherwise
  1195. FALSE.  (The only exceptions to this are IDCMP_MOUSEMOVE messages from a
  1196. GACT_FOLLOWMOUSE or WFLG_REPORTMOUSE, which can be ignored safely [i.e.,
  1197. you may return FALSE] as they cannot easily be attributed to an originating
  1198. gadget).  For a mouse-click, test if it was in your area (the current
  1199. dimensions of your object in the GUI are present in the `plugin' object),
  1200. for gadgets, make sure it is really your gadget causing the message (check
  1201. .iaddress).  If you reply TRUE to messages that are potentially meant for
  1202. other objects, you might choke them.  Do not engage in other actions in
  1203. this method, such as rendering; do these things in the message_action()
  1204. method.  The default method returns FALSE.
  1205.  
  1206. The GUI window uses the following IDCMP flags:
  1207.  
  1208.         IDCMP_ACTIVEWINDOW        IDCMP_INACTIVEWINDOW
  1209.         IDCMP_GADGETDOWN          IDCMP_GADGETUP
  1210.         IDCMP_INTUITICKS
  1211.         IDCMP_MOUSEBUTTONS        IDCMP_MOUSEMOVE
  1212.         IDCMP_NEWSIZE
  1213.         IDCMP_RAWKEY              IDCMP_VANILLAKEY
  1214.  
  1215. You may get your PLUGIN objects to generate these messages (via gadgets)
  1216. and then trap them (via message_test()), or you can just snoop on them in
  1217. message_test().
  1218.  
  1219.         message_action(class,qual,code,win:PTR TO window)
  1220.  
  1221. is the second part, and will only be called if you returned TRUE in the
  1222. previous method.  here you may do any action needed (additional rendering
  1223. based on the user action).  class, qual and code are copies of the class,
  1224. qualifier and code part of the intuimessage, so you don't need to remember
  1225. them in message_test().  You should return TRUE if you want the action the
  1226. user of the PLUGIN has written in his GUI-spec to be executed upon
  1227. termination of this method (do this if your object clearly can be "hit",
  1228. such as a gadget.  If you just do some rendering you might want to ignore
  1229. the actionvalue).  The default method returns FALSE.  (As noted above, the
  1230. action function is passed the PLUGIN object as well as the GUI info.)
  1231.  
  1232. Note: do not confuse message_action() with action values: the former is for
  1233. implementing the plugin's behaviour generally, while the latter is for
  1234. specific behaviour in a specific GUI, attached by the user of your plugin
  1235. (which could be you again :-).
  1236.  
  1237.         appmessage(amsg:PTR TO appmessage,win:PTR TO window)
  1238.  
  1239. Like the testing for window IDCMP, but for AppWindow message testing.
  1240. Return TRUE _only_if_ the message is meant for this PLUGIN.  The PLUGINs
  1241. (optional) awproc will then be called (as normal, with the optional data
  1242. field being the `plugin_object').  Note: for compatibility, the
  1243. appmessage() method is called only for PLUGINs that specify a non-NIL
  1244. `awproc' field.  Just be careful to *not* specify a non-NIL `awproc' field
  1245. with old PLUGIN modules.
  1246.  
  1247. If you supply a plugin as module for others, you'll have to state what
  1248. constructor(s) they may use, wether or not they have to supply a sensible
  1249. action-value.  END will almost always have to be called.
  1250.  
  1251.  
  1252. +---------------------------------------------------------------+
  1253. |       6. guide to the examples                                |
  1254. +---------------------------------------------------------------+
  1255.  
  1256. There are numerous examples to show the various features of EasyGUI.
  1257. Here's a small guide to help you find the ones that might be interesting:
  1258.  
  1259.         alldist.e          - The original example.
  1260.         alldist2.e         - The original example, using multi-windows and
  1261.                              blocking.  You can have all the example GUIs
  1262.                              open at once!
  1263.  
  1264.         testaw.e           - AppWindow example.
  1265.         testchange.e       - changegui() example.
  1266.         testchange2.e      - changeXXX() and multi-window example.
  1267.         testkey.e          - Keyboard shortcuts example, with window
  1268.                              blocking and gadget disabling.
  1269.         testmulti.e        - Multi-window example (recursive!).
  1270.         testmulti2.e       - Multi-window and multiforall() example.
  1271.         testqual.e         - Qualifier example.
  1272.  
  1273.         animcontrol_test.e - Tests animcontrol PLUGIN.
  1274.         button_test.e      - Tests flavours of button PLUGIN.
  1275.         calendar_test.e    - Tests calender PLUGIN.
  1276.         colorwheel_test.e  - Tests colorwheel PLUGIN.
  1277.         gradient_test.e    - Tests gradient (slider) PLUGIN.
  1278.         imagebutton_test.e - Tests flavours of imagebutton PLUGIN.
  1279.         led_test.e         - Tests led PLUGIN, with pseudo-async activity.
  1280.         led_test2.e        - Tests led PLUGIN, with multi-windows and
  1281.                              pseudo-async activities.
  1282.         led_test3.e        - Tests led PLUGIN, with multi-windows and
  1283.                              *real* async activities.
  1284.         led_test4.e        - Tests led and ticker PLUGINs, with
  1285.                              multi-windows and pseudo-async activities.
  1286.         password_test.e    - Tests password PLUGIN.
  1287.         tabs_test.e        - Tests tabs PLUGIN.
  1288.         tabs_test2.e       - Tests tabs PLUGIN and changegui() example.
  1289.         tapedeck_test.e    - Tests tapedeck PLUGIN.
  1290.         ticker_test.e      - Tests ticker PLUGIN.
  1291.  
  1292. These can be found in Src/EasyGUI.  The sources for the example PLUGINs are
  1293. in Src/Plugins.
  1294.  
  1295.  
  1296. +---------------------------------------------------------------+
  1297. |       7. bugs/future                                          |
  1298. +---------------------------------------------------------------+
  1299.  
  1300. bugs:
  1301. - method of displaying slider values not bulletproof
  1302. - GadTools sends two messages if your slider value is changed to a
  1303.   negative value, so your action function can get called twice.  
  1304.  
  1305. [the planned render spaces can now be done much better by using PLUGINs]
  1306.  
  1307.  
  1308. ----------------------------------------------------------------
  1309.  
  1310. General advice: try out and modify the examples.  Sometimes something won't
  1311. work, but EasyGUI is flexible enough that at least one way of arranging
  1312. groups etc.  will give you a nice GUI :-).  If you need more power than
  1313. EasyGUI currently gives, you'll have to use MUI/BGUI/WhatEver instead.
  1314.  
  1315. Wouter (and Jason!)
  1316.