home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / easygui_os12 / docs / easygui_33b4 / easygui.doc next >
Encoding:
Text File  |  1997-06-09  |  60.8 KB  |  1,319 lines

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