home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / dev / e / amigae / src / tools / easygui / easygui.doc < prev   
INI File  |  1994-11-08  |  17KB  |  448 lines

  1. [Here's the new EasyGUI! This version is really usable.
  2.  NOTE: read this first before recompiling any old EasyGUI stuff!]
  3.  
  4.                               Introducing:
  5.  
  6.                              E A S Y G U I
  7.  
  8.      An interface builder for E, with the following highlights:
  9.  
  10.     - It's totally Font-Sensitive
  11.     - It's Resizable
  12.     - It's Self-Organising, i.e. it arranges gadgets
  13.     - It's more StyleGuide compliant than your granny
  14.     - It's Fast and Flexible
  15.     - It's relatively small, needs no extra external libraries
  16.     - And above all: It's extremely easy to use!!!
  17.  
  18. changes from the v3.1a version (features):
  19. - new functions to access/modify gadgets while GUI is active
  20. - easily add gadtools menus
  21. - more complete docs
  22. - works better with multiple simultanuous EasyGUIs
  23. - LISTV, MX and CYCLE have an extra "current" parameter now
  24. - STR now takes an _estring_ as value (make sure you change
  25.   this in old sources!)
  26. bugs:
  27. - current gadget values would reset upon resize
  28. - would open in middle of screen instead of visible part
  29. - many tiny bugs removed
  30.  
  31. +---------------------------------------------------------------+
  32. |    1. EasyGUI Intro                    |
  33. +---------------------------------------------------------------+
  34.  
  35. EasyGUI takes the form a module file that needs to be included into your
  36. E source (needless to say, it needs v2.04/v37 of the OS). The most simple
  37. form of constructing a GUI consist of calling the function easygui() with
  38. a (possibly nested) E list which describes your GUI. just to show how Easy,
  39. try this source:
  40.  
  41.     MODULE 'tools/EasyGUI'
  42.     PROC main() IS easygui('um,...',[BUTTON,0,'Ok!'])
  43.  
  44. This'll open a window with just one gadget in it, and wait for the
  45. user to push it. If easygui() can't get what it wants, it'll start
  46. throwing around exceptions, so we'll probably need an exception
  47. handler to be able to inform the user properly (see below).
  48.  
  49. The first arg of easygui() is the window title, the second one is the
  50. GUI description. The form of these desciptions is quite simple: It's a
  51. list with as first element the type of gadget, the second is called an
  52. action value (more later), and the rest is gadget-specific.
  53.  
  54. To be able to build GUI's outof more components than just one gadget,
  55. one can group gadgets with a ROW and a COL list:
  56.  
  57. [COLS,
  58.   [BUTTON,1,'Ok'],
  59.   [BUTTON,0,'Cancel']
  60. ]
  61.  
  62. This'll create a new group, consisting of two gadgets next to each other.
  63. COLS and ROWS groups are like a single gadget, i.e. you can easily put them
  64. into other groups, to create GUI's of infinite complexity.
  65.  
  66. Other Grouping functions are EQCOLS and EQCOLS, which try to align gadgets
  67. in a group.
  68.  
  69. [BEVEL,a] will put a bevel box around a, whatever it is (a gadget, a group...),
  70. and BEVELR is the recessed version.
  71.  
  72. Other elements of groups are mostly gadgets, which have a specific #of
  73. arguments. [If the number of arguments is incorrect, EasyGUI will raise
  74. the "Egui" exception.]
  75.  
  76. The first element is always the type of gadget to create (see below). The
  77. second element is always something called an "actionvalue", which tells
  78. EasyGUI what needs to be done when the user interacts with the gadget.
  79. All elements after that are gadget specific.
  80.  
  81. An action value may be:
  82. - a small positive integer (0-1000). If the user selects this gadget,
  83.   EasyGUI will close the window, and return that value as returnvalue
  84.   from the easygui() call. This is meant for "Ok" / "Cancel" type buttons.
  85. - a pointer to an "actionfunction". If the user selects this gadget,
  86.   EasyGUI will call the function with as arguments depending on the
  87.   type of gadget (for example a slider will get it's current value).
  88.   After the actionfunction returns, EasyGUI continues processing messages
  89.   from the GUI.
  90.   example:
  91.  
  92.     ...[BUTTON,{load},'Load'],...
  93.  
  94.     PROC load(info) IS WriteF('You pushed the "Load" button!\n')
  95.  
  96.   
  97.   the value of `info' is explained below. Or:
  98.  
  99.     DEF s[100]:STRING
  100.  
  101.     ...[STR,{str},'input:',s,50,4],
  102.            [CYCLE,{cycle},'choose:',['Yep','Nope',NIL],1],...
  103.  
  104.     PROC str(info,news) IS WriteF('the new string is: \s\n',news)
  105.     PROC cycle(info,newc) IS WriteF('the new choice is: \d\n',newc)
  106.  
  107.   In the action function, you can store the new value, however EasyGUI keeps
  108.   track of it itself too: In the case of the STR above it will StrCopy() new
  109.   values into your estring, so it automatically has the correct value after
  110.   closing. In the case of all other gadgets it stores the new (integer) value
  111.   in the list (so that `1' in `CYCLE' may become `0'). This has the added
  112.   benefit that windows that are opened and then closed again will automatically
  113.   start with the current values.
  114.  
  115. The easygui() function:
  116.  
  117.     easygui(windowtitle,gui,info=0,screen=0,textattr=0,newmenus=0)
  118.  
  119. `info' may be ANY value, and is always passed as first arg to the
  120.   action functions. For example if you write a prefsrequester, this may
  121.   be the the prefs OBJECT. Your actionfunctions then have a simple task
  122.   changing the value of the element in question.
  123. `screen' is an optional screen to open on. if not present, EasyGUI opens
  124.   on the current public screen.
  125. `textattr' is a fontdescription, and is best left NIL. If NIL, EasyGUI
  126.   will pick the font the user selected as "screenfont" in fontprefs.
  127. `newmenus' can be a newmenus structure (as in gadtools.library). EasyGUI
  128.   will then automatically attach it to the window and arrange any messages.
  129.   You can give the same actionvalues as gadgets in the newmenu.userdata,
  130.   and the actionfunction can be the same as for a `BUTTON', i.e.:
  131.  
  132.     [...,2,0,'Load','l',0,0,{load},...]:newmenu
  133.  
  134.   can use the same load() as in the example further above.
  135.  
  136.  
  137. +---------------------------------------------------------------+
  138. |    2. Gadgets                        |
  139. +---------------------------------------------------------------+
  140.  
  141.  
  142. general format: [NAME,action,text,...]
  143. in {}: which direction it may resize.
  144. * = not implemented or things missing.
  145. + = a value that can be affected lateron with the set#? functions
  146.  
  147. Each gadget shows the gadget template, explanation, the form of the
  148. actionfunction, and a typical example).
  149.  
  150.  
  151. [BUTTON,action,intext]
  152. buttonaction(info)
  153. example: [BUTTON,0,'Cancel']
  154.  
  155. [CHECK,action,righttext,checkedbool+,lefttextbool]
  156. checkedbool = whether gadget should initially be check-marked
  157. checkaction(info,checkedbool)
  158. example: [CHECK,{case},'Ignore case',TRUE,FALSE]
  159.  
  160. [INTEGER,action,lefttext,num+,relsize]
  161. num = initial value
  162. integeraction(info,newnum) {x}
  163. example: [INTEGER,{v},'int:',5,3]
  164.  
  165. [LISTV,action,textabove,relx,rely,execlist+,readbool,selected,current+]
  166. execlist = ptr to an execlist. (see tools/constructors.m)
  167. readbool = whether listview is read-only
  168. *selected = 0=none, 1=read, 2=strgad (fill in 0 for compat.)
  169. listviewaction(info,num_selected) {x,y}
  170. example: [LISTV,0,NIL,5,5,filenamelist,0,NIL,0]
  171.  
  172. [MX,action,abovetext,nil_term_elist,lefttextbool,current]
  173. mxaction(info,num_selected)
  174. example: [MX,{v},NIL,['One','Two','Three',NIL],FALSE,1]
  175.  
  176. [CYCLE,action,lefttext,nil_term_elist,current]
  177. cycleaction(info,num_selected)
  178. example: [CYCLE,{v},'choose:',['Yep','Nope',NIL],1]
  179.  
  180. [PALETTE,action,lefttext,depth,relx,rely]
  181. depth = 1..8, number of bitplanes this color is for
  182. paletteaction(info,colour) {x,y}
  183. example: [PALETTE,{v},'color:',3,5,2]
  184.  
  185. [SCROLL,action,isvert,total+,top+,visible+,relsize]
  186. total = resolution of scroller
  187. top = current top represented
  188. visible = current
  189. scolleraction(info,curtop) {x|y}
  190. example: [SCROLL,{v},FALSE,10,0,2,2]
  191.  
  192. [SLIDE,action,lefttext,isvert,min,max,cur+,relsize,levelformat]
  193. min,max = value range of slider
  194. cur = current value
  195. levelformat = string that shows levelformat, example '%2ld'. leave
  196. a large amount of spaces left in lefttext for this.
  197. slideraction(info,cur) {x|y}
  198. example: [SLIDE,0,'Colors:',FALSE,1,8,3,5,'']
  199.  
  200. [STR,action,lefttext,initial+,maxchars,relsize]
  201. initial = initial string contents: NOTE: HAS TO BE AN ESTRING!
  202. maxchars = max #of chars for string
  203. stringaction(info,newstring) {x}
  204. example: [STR,0,'Pattern',s,200,5]      (DEF s[100]:STRING)
  205.  
  206. [TEXT,text,lefttext,borderbool,relsize] {x}
  207. borderbool = whether or not a recessed bevelbox should be placed around 'text'
  208. example: [TEXT,'Selected Fonts',NIL,FALSE,3]
  209.  
  210. *[NUM,int,lefttext,borderbool,relsize] {x}
  211.  
  212. *[RENDER,actionr,actionp,x,y]               -> in fontunits
  213. renderrefresh(x,y,xs,ys)
  214. renderpress(x,y)                            -> relative to topcorner
  215.  
  216. *[RENDERFIXED,actionr,actionp,x,y]          -> in pixels
  217. renderfixedrefresh(x,y)
  218. renderfixedpress(x,y)
  219.  
  220. [SBUTTON] {x}
  221. same as button, only now resizes.
  222.  
  223. [BAR], [SPACE] {x,y}, [SPACEH] {x}, [SPACEV] {y}
  224. BAR places a nice divider-bar between gadgets/groups. Whether it's
  225. horizontal or vertical depends on which group it is in. SPACE/SPACEH/SPACEV
  226. do nothing, they only eat up space. This can be very handy in GUI design,
  227. they act like a spring between elements (do not use them on the borders of a
  228. GUI, only in the middle).
  229.  
  230. See the example GUI's how to use these.
  231.  
  232. #?text:
  233. (where #? is left/right etc.): a text to place next to the gadget. often
  234. is allowed to be NIL.
  235.  
  236. relsize,relx,rely:
  237. generally gadgets will automatically get a size depending on a number of
  238. factors, but relsize allows the programmer to give a minimum size for
  239. certain gadgets, thereby sizing a whole group. If other gadgets already
  240. account for the minimum size, this one can safely be set to a low value
  241. such as 2. All these sizes are calculate in terms of the hight of the font.
  242.  
  243. nil_term_elist:
  244. a nil-terminated E list, such as ['One','Two','Three',NIL]
  245.  
  246. isvert:
  247. TRUE if gadget needs to be vertical, horizontal by default.
  248.  
  249. +---------------------------------------------------------------+
  250. |    3. How Layout Works                    |
  251. +---------------------------------------------------------------+
  252.  
  253. EasyGUI works by automatically layouting the gadgets on the
  254. screen. In a first pass, it will compute the minimum size for
  255. each element: for gadgets this involves the size of fonts and
  256. various other things. For a ROWS list, for example, it will take
  257. the width of the biggest gadget as its width, and computes its
  258. height by adding the heights of all other gadgets. For EQROWS
  259. this is slightly more complicated: EasyGUI also computes a "middle"
  260. for various gadgets, often between the text that denotes what a
  261. gadget is about and the gadget itself. It then tries to align
  262. all of these. for EQCOLS it simply tries to make all columns
  263. equal width.
  264. In a second pass, EasyGUI assigns the final coordinates to all
  265. gadgets. Important to notice is that in a GUI often there is
  266. more space available than is required for a gadget, for example
  267. the gadget above it in a ROWS environment is much wider. Also, the
  268. user may have resized the window. To do something useful with this
  269. space, EasyGUI looks at which gadgets can do something useful
  270. with extra space, such as LISTV, or STR, SCROLL etc. This process
  271. of granting extra space propagates through ROWS/COLS, which act
  272. as gadgets themselves. Gadgets like BUTTON don't benefit from more
  273. space, so they give that away to their neighbours.
  274.  
  275.  
  276. +---------------------------------------------------------------+
  277. |    4. Advanced features                    |
  278. +---------------------------------------------------------------+
  279.  
  280. Throwing exceptions from actionfunctions
  281. ----------------------------------------
  282. is allowed: EasyGUI will catch it, close the window properly,
  283. and then ReThrow() it.
  284.  
  285. exceptions raised by EasyGUI itself:
  286.  
  287. "MEM"   -- no mem
  288. "GUI"   -- for things like CreateGadgetA, OpenWindowTagList etc.
  289. "GT"    -- couldn't open gadtools.library
  290. "bigg"    -- for "BIG Gui": interface is calculated to be bigger than the screen.
  291.        generally you should keep gui's small, so that they still fit on
  292.        640x200 topaz screens. If the user runs Times/30 on a screen this size,
  293.        he probably knows he has a problem.
  294. "Egui"  -- a design error: most probably handed over a list to dogui()
  295.            that was either to long or too short
  296. <other> -- Raise()ed by own function
  297.  
  298. You can also use a "quit" exception or somesuch if you need to quit from an
  299. actionfunction (i.e. other than with an actionvalue).
  300.  
  301.  
  302. Multiple Windows
  303. ----------------
  304. The simplest use of EasyGUI is just by calling easygui(). You can however
  305. open any number of windows, and check messages for all of them.
  306.  
  307.     guiinit(windowtitle,gui,info=0,screen=0,textattr=0,newmenus=0)
  308.     guimessage(guihandle)
  309.     cleangui(guihandle)
  310.  
  311. Call guiinit() for each window (exactly the same arguments as easygui(). Then,
  312. keep calling guimessage() for each of them, when messages arive. you can
  313. close them again with cleangui(), for example when a gui returns a
  314. positive integer (the actioncode). Negative integers signal that it simply
  315. finished processing all messages, but no need to close the window yet.
  316.  
  317. example of usage of these three function (= definition easygui())
  318.  
  319.  
  320.     EXPORT PROC easygui(windowtitle,gui,info=NIL,screen=NIL,textattr=NIL,newmenus=NIL) HANDLE
  321.       DEF gh=NIL:PTR TO guihandle,res=-1
  322.       gh:=guiinit(windowtitle,gui,info,screen,textattr,newmenus)
  323.       WHILE res<0
  324.         Wait(gh.sig)
  325.         res:=guimessage(gh)
  326.       ENDWHILE
  327.     EXCEPT DO
  328.       cleangui(gh)
  329.       ReThrow()
  330.     ENDPROC res
  331.  
  332.  
  333. the object you get has some handy field in there: the window in question,
  334. and the sigmask (i.e. Shl(1,sigbit)), if you want to do a proper Wait()
  335. (OR them).
  336.  
  337.     OBJECT guihandle
  338.       wnd:PTR TO window
  339.       sig:LONG
  340.     ENDOBJECT     /* SIZEOF=64 */
  341.                               ^^^^private!
  342.  
  343. if you want to draw into `wnd': stdrast is automatically set to the last
  344. EasyGUI opened.
  345.  
  346.  
  347. Multiple copies of a GUI
  348. ------------------------
  349. if your app allows to have multiple copies of the _same_ gui open
  350. at the same time (for example if you open windows recursively, or
  351. you use the multiple window technique described above to open more
  352. instances of one GUI), you might need to dynamically allocate the GUI
  353. description, because of the way dynamically computed values are
  354. put into static E lists. A GUI desciption with [] lists is static,
  355. i.e. only allocated once. Adding NEW to all of them is hard to deallocate,
  356. and this is where disposegui() comes in. To safely use this feature,
  357. allocate ALL lists belonging to the GUI desciption dynamically with
  358. NEW [...] (this does not include lists such as the one used for the
  359. various labels in CYCLE-gadgets).
  360.  
  361.     easygui('Bla',
  362.           gui:=NEW [ROWS,
  363.              NEW [STR,{str},'input:',s,50,4],
  364.                  NEW [CYCLE,{cycle},'choose:',['Yep','Nope',NIL],1]])
  365.     disposegui(gui)
  366.  
  367. Call disposegui() with the top-level list. on each gadget-list (i.e.
  368. NEW [CYCLE,...]) it will simply call FastDisposeList(), on COLS and
  369. ROWS etc. it will first deallocate each element recursively.
  370.  
  371.  
  372. Manipulating Gadgets
  373. --------------------
  374. [currently, this assumes you're using the DIY version of EasyGUI (as
  375.  described under "multiple windows".]
  376. You might need to modify gadgets while a GUI is active, for example
  377. to set a slider when a corresponding integer gadget is modified by
  378. the user, or to change the contents of a listview.
  379.  
  380. You can denote gadgets to change by simply storing their addresses,
  381. i.e.:
  382.  
  383.     [COLS,
  384.       mygad:=[CHECK,....],
  385.           ...
  386.         ]
  387.  
  388. Now you can use `mygad' with some of the functions below. Note that,
  389. of course `mygad' isn't a gadget, but it helps EasyGUI to find the
  390. real gadget.
  391.  
  392.     setscrollvisible(gh,gad,visible)
  393.     setscrolltop(gh,gad,top)
  394.     setscrolltotal(gh,gad,total)
  395.     setlistvselected(gh,gad,active)
  396.     setlistvlabels(gh,gad,labs)
  397.     setinteger(gh,gad,new)
  398.     setcycle(gh,gad,active)
  399.     setmx(gh,gad,active)
  400.     setstr(gh,gad,new)
  401.     setslide(gh,gad,new)
  402.     setcheck(gh,gad,bool)
  403.  
  404. for all these: `gh' is the gui you're talking about (as returned from
  405. guiinit()), `gad' is a value that denotes the gadget as described above.
  406. the third value is whatever you're changing about the gadget. Note that
  407. in doing so, you need to respect usual restrictions on gadtools gadgets,
  408. for example setlistlables() requires that you first set it to -1, then
  409. modify the list, and put it back.
  410.  
  411.     realgadget:=findgadget(gh,list)
  412.  
  413. allows you to find the gadget address, for all those modifications
  414. that aren't possible with the above set#? functions. It returns an intuition
  415. gadget structure. Note that preferably you will want to use the set#?
  416. functions, as these cooperate with EasyGUI very well (in keeping
  417. track of the current value, for example: setstr() also copies the new
  418. value to the estring you attached to the gadget).
  419.  
  420.  
  421. +---------------------------------------------------------------+
  422. |    5. bugs/future                        |
  423. +---------------------------------------------------------------+
  424.  
  425. bugs:
  426. - method of displaying slider values not bulletproof
  427. - sometimes problems with finding correct size for gadgets with a
  428.   lefttext in an EQROWS
  429.  
  430. future:
  431. - implement render spaces for draw/edit purposes
  432. - implement gadgets with images on them
  433. - implement a BOOPSI door
  434. - easy blocking (for now, look at the JRH's RKRM intuition/requesters_alerts/
  435.   blockinput.e if you need this)
  436.  
  437.  
  438.  
  439. ----------------------------------------------------------------
  440.  
  441. General advice: try out and modify the examples. Sometimes something won't work,
  442. but EasyGUI is flexible enough that at least one way of arranging groups etc.
  443. will give you a nice GUI :-). If you need more power than EasyGUI currently
  444. gives, you'll have to use MUI/BGUI/WhatEver instead.
  445.  
  446. Wouter
  447.  
  448.