GenGui V2.0 =========== ©1994-95 by Matthias Meixner Read the README file for the legal issues This package is for layout and creation of graphical user interfaces (GUI). Unlike some other programs like Gadtools, you do not draw your GUI just like in a paint-program, but you describe the GUI in a kind of description language. From this description GenGui generates a C-headerfile, wich containes the description data in a form that is needed by the routines which must be linked to your program and which do the real work on runtime. For the legal issues read the "readme"-file. 1. Preface ========== From version 36 of the Amiga operating system it on is possible to select the font that should be used. Since there are now several new display- resolutions it is highly recommended, that applications should be able to use higher resolutions and therefore it is required, that programs can adapt to a variable windowsize. OK, lets face the current situation. There are half a dozen different systems out there, that all allow to create font-sensitive and resizeable GUIs. Most of them come with a shared library, that implemets its own gadgets, and they are all about 100kBytes in size. Since there is no standard for these tools yet, every programmer uses his preferred generator and every program uses another shared library. But what's the use of shared- libraries, if every program uses another one? If you have got three programs running, that all use a different library, then the libraries allocate already 300kBytes just for three layout-engines and for many unused button- types, each implementing their own version of the same types of buttons. Therefore I wrote Gengui. It uses GadTools-gadgets, which already come with the operating system and implements a layout-enging for these gadgets. It does not use a shared-library, but comes as a quite small link-library. 2. The basic idea: ================== The description of the Gui is box oriented. Every box affects the size and position of the objects inside the box. A box has an orientation, which determines the positions of the objects in a box, in a vertical box the first object is on top and all other objects are below this one, in a horizontal box, the first one is on the most left side. Within a box every object can have a relative size, a size absolut in characters or a size absolut in pixels or a mixture of the last two. This object can be a new box, a gadget or a custom "gadget". This allows an easy generation of resizeable GUI's. Maybe you should get an example now: Imagine you want to have a GUI, which looks like that: +-------------------------+ | | | +-----+ +-----+ +-----+ | | |Text1| |Text2| |Text3| | | +-----+ +-----+ +-----+ | | | | | | | +-------------------------+ The description would look like this: PROJECTNAME Project1 // This is the name, which will be used // in the generated source HBOX // horizontal box VREL 1 // the box has relative height HREL 1 // and relative width BUTTON // We want to generate a button STDLINE 1 // with a height of one line plus spacing HREL 1 // and relative width TEXT "Text1" // "Text1" should be written in it ID 1 // and maybe we want to identify it later END BUTTON STDLINE 1 HREL 1 TEXT "Text2" ID 2 END BUTTON STDLINE 1 HREL 1 TEXT "Text3" ID 3 END END This would describe a GUI with three gadgets, each has (including an adequate spacing) one third of the width of the window, and a height of one line. Gengui offers some reasonable defaultvalues for the different types of objects, which significantly reduce the size of the description: PROJECTNAME Project1 HBOX BUTTON TEXT "Text1" ID 1 END BUTTON TEXT "Text2" ID 2 END BUTTON TEXT "Text3" ID 3 END END Maybe you want the first button to be double as wide as the other two buttons: PROJECTNAME Project1 HBOX BUTTON HREL 2 // now this button gets 2 parts of the width of this box TEXT "Text1" ID 1 END BUTTON // whereas this button gets only one part, TEXT "Text2" ID 2 END BUTTON // and this one too TEXT "Text3" ID 3 END END Now lets think of something like that: +-----------------+ | | | +-------------+ | | | | | | +-------------+ | | | | +--------+ | | | | | | +--------+ | | | | +---+ | | | | | | +---+ | | | +-----------------+ The first button has three times the size and the second one two times the size of the last button. PROJECTNAME Project1 VBOX // Now one button is above the other ! BUTTON HREL 3 // Three thimes the size TEXT "Text1" ID 1 END BUTTON HREL 2 // two times the size of the last button. TEXT "Text2" ID 2 END BUTTON TEXT "Text3" ID 3 END END And now a last example for this topic: +---------------+ | | | +------+ | | | | | | +------+ | | | | +--+ +------+ | | | | | | | | | | | | | | | | | | | | | | | | | | +--+ +------+ | | | +---------------+ PROJECTNAME Pro2 HBOX VBOX // left box HREL 1 VBOX // this creates the empty place in the top left corner END BUTTON VREL2 END END VBOX // right box HREL 2 // of double width BUTTON VREL 1 END BUTTON VREL 2 END END END 3. Installation =============== Installation is quite easy: copy gengui.h to your include: directory or you will have to add the path where it can be found to your include-path. 4. The description language =========================== These are the keywords of the description languange. It does not distinguish between lower- and uppercase. Some keywords have more than one name, since i could not decide wich one would be more easy to remember :). These other names can be found in the brackets (). Every command must be on a separate line, comments begin with '//' and mark the rest of the line as comment. #c_source #end_source Everything between these two lines will be directly included in the generated output. These keywords must begin on the first column ! These are the commands that are used to describe the objects of the GUI: BACKFILL Hook: Install a Backfill Hook, that is used for rendering the background of this box. BAR BAR : Insert a bar between two objects. The direction depends on the containing object. If this is a VBOX, then a horizontal bar will be generated, otherwise a vertical bar. BUTTON BUTTON : Normal button, default size HREL 1, STDLINE 1, MINHCHAR strlen(Text), MINHPIX 4 CHECKBOX CHECKBOX : Checkbox, default size HCAR 2, VCHAR 1 CUSTOM CUSTOM : Custom Gadget, default size HREL 1, VREL 1, Read also the chapter about custom gadgets ! CYCLE CYCLE : Cycle-gadget, default size HREL 1, STDLINE 1 MINHCHAR max(strlen(Texts in the Cyclegadget)), MINHPIX 24 FRAME FRAME RAISED|RECESSED : Draw a frame around this Box (VBOX or HBOX). It is raised (FRAME RAISED) or recessed (FRAME RECESSED). GFXBUTTON : Graphical button. It supports two highlight-methods: complement and highlight-image. The images are selected within this block with the "IMAGE" command. If there is one such command, then complement is used, if there are two of them, then the second one is used for highlighting. You can adjust the alignment within its space with the following flags: Horizontal alignment: GG_Left,GG_HCentered,GG_Right Vertical alignment: GG_Top,GG_VCentered,GG_Bottom default: GG_Left,GG_Top You can switch off highlighting by the GG_NoHighlight-flag. HBOX HBOX : horizontal box, default size: HREL 1, VREL 1 INTEGER INTEGER : Integer-gadget, default size HREL 1, STDLINE 1 LISTVIEW LISTVIEW : default size HREL 1, VREL 1 MX MX : MX-gadget, default size HREL 1, VREL 1, MINVCHAR # of entries, MINVPIX 6 NUMBER NUMBER : Number-gadget, default size HREL 1, STDLINE 1 PALETTE PALETTE : Palette-gadget, default size HREL 1, VREL 1 PLAINTEXT PLAINTEXT: Formatted Text, default size HREL 1, STDLINE 1. MINHPIX and MINVPIX are set according to the size of the text as default. Plaintext supports the following format descriptions: \n : Newline %% : '%' %Cx : Set foreground color to x (e.g. %C1 : set color to 1) %cx : Set background color to x %B : Bold on %b : Bold off %I : Italics on %i : Italics off %N : Normal style (Bold,Italics,Underlined off) %U : Underlined on %u : Underlined off You can adjust the alignment within its space with the following flags: Horizontal alignment: GG_Left,GG_HCentered,GG_Right Vertical alignment: GG_Top,GG_VCentered,GG_Bottom default: GG_Left,GG_Top Unlike TEXT this is not a gadtools gadget, but allows easier formatting of text, since it allows texts, that use more than one color, style or that span more than one line. See also GfxPrint(); SCROLLER SCROLLER : Scroller, default size HREL 1, VREL 1 SLIDER SLIDER : Slider, default size HREL 1, VREL 1 STRING STRING : String-gadget, default size HREL 1, STDLINE 1 TEXT TEXT : Text-gadget, default size HREL 1, STDLINE 1 See also PLAINTEXT VBOX VBOX : vertical box, default size: HREL 1, VREL 1 Each of these commads defines a block, which must be terminated by "END" Commands specifying the size of the objects: HCHAR (XCHAR) HCHAR chars : Absolute width of 'chars' characters HPIX (XPIX) HPIX pixel : Absolute width of 'pixel' pixels HREL (XREL) HREL size : Relative width STDCOL STDCOL chars : Absolute width of 'chars' characters plus 4 pixels space STDLINE STDLINE chars : Absolute height of 'chars' characters plus 4 pixels space VCHAR (YCHAR) VCHAR chars : Absolute height of 'chars' characters VPIX (YPIX) VPIX pixel : Absolute height of 'pixel' pixels VREL (YREL) VREL size : Relative height XSPACE XSPACE xs : Set the amount of horizontal space between gadgets to xs pixels, defaults to INTERWIDTH (only allowed within HBOX/VBOX) YSPACE YSPACE ys : Set the amount of vertical space between gadgets to ys pixels, defaults to INTERHEIGHT (only allowed within HBOX/VBOX) Commands specifying the minimal size for relative objects: MINHCHAR (MINXCHAR) MINHCHAR chars : Minimal width of 'chars' characters MINHPIX (MINXPIX) MINHPIX pixel : Minimal width of 'pixel' pixels MINSTDCOL MINSTDCOL chars : Minimal width of 'chars' characters plus 4 pixels space MINSTDLINE MINSTDLINE chars : Minimal height of 'chars' characters plus 4 pixels space MINVCHAR (MINYCHAR) MINVCHAR chars : Minimal height of 'chars' characters MINVPIX (MINYPIX) MINVPIX pixel : Minimal height of 'pixel' pixels These commands specify the minimal width/height for objects with relative width/height. It does not affect the relative sizes of different objects. Thus if you have two objects within one box, each having the same relative width and one of these has a minimal width of 5 chars and the other one of 6 chars, then the minimal width of the first one will also be 6 chars, since the relative size says, that the two objects have always the same width. The default values used by Gengui for the minimal sizes are often sufficient enougth, therefore you will not need to use these commands too often. (At least I hope so :-) ) Commands for the description of gadget-specific data: CUSTOM CUSTOM func : Set the custom function for custom-gadgets. NOTE: this is only valid within a custom-object and since it is written the same way as the CUSTOM-object the meaning of CUSTOM only depends on the context. FLAGS FLAGS flagset : Set the flags of the gadget (-> ng_Flags) NOTE: it is possible spread the flags to more than one FLAGS command e.g.: FLAGS a|b would have the same effect as FLAGS a FLAGS b HOOK HOOK function : Set a hook function that is called, when the gadget sends a message. See also the chapter on hook-functions. ID ID id : Set the ID of the gadget (-> ng_GadgetID) NOTE: id must not contain any whitespace characters ! The value of the ID must be >=0. IMAGE IMAGE image : This sets the image-data for GFXBUTTONs. "image" must point to a "struct Image" variable. You can generate this data using IconEdit when you have set "SRC" in the tooltypes of IconEdit. Then you will find "Save as C..." in the projects menu. Since IconEdit generates some additional information for the icons, you will need to delete this information from the generated sourcecode. You may define up to two images for every GFXBUTTON. If there are two of them, then the second one is used for highlighting. TAGS TAGS tags : Set the tags for a gadget. You need not set TAG_DONE, since this is automatically done. You may use more than one TAGS command per gadget, e.g. TAGS a,b TAGS c,d would have the same effect as TAGS a,b,c,d TEXT TEXT string : Set the text for the gadget (-> ng_GadgetText) If you specify more than one text, then all these texts are concatenated. TEXTATTR TEXTATTR textattr : Set ng_TextAttr. By default the standart font of the window is used for the gadgets. USER USER userdata : Set user data. You can access the user data via the macro GetUserData(). NOTE: the field ng_UserData is required by GenGui itself, but therefore it has another field reserved for this purpose. General note: The parameters of all these commands may be preprocessor symbols, in fact they are just passed on to the generated source. 5. What's generated by GenGui ============================= GenGui takes the descriptionfile and generates two headerfile. The first headerfile contains the full data of the descriptionfile and some required or useful defines. First it contains a struct WinInfo that has the name which was set using the command projectname. This struct is required for rendering the GUI to the window, therefore it is the most important structure in the headerfile. It allocates GadInfo structures, which store the information of the look of the GUI. To make these accessible for GG_SetLowlevelAttrs() Gengui generates defines which are used to supersede the generic names of the structure valiables. The names have the form: 'Projectname'_GadInfo_'GadgetID' They identify the variables themselves. Therefore you will need to use the &-operator to get the address of them for use with GG_SetLowlevelAttrs(). Furthermore an array of pointers to gadgets is allocated in the headerfile. The name of this array has the form: 'Projectname'_Gadgets This array contains the pointers to the gadgets which you require for e.g. setting new attributes of the gadgets via GG_SetGadgetAttrs(). But note, that these entries are only valid as long as the GUI is rendered to the window and that these entries change when the GUI is resized or changed in other ways. To know which entry in this array belongs to a certain gadget, GenGui generates a definition for every Gadget, which tells you which entry belongs to a certain gadget. The name of this definition has the form: 'Projectname'_'GadgetID' OK, let's have a simple example to illustrate, how you would use it. The second headerfile has the extension "_def.h" and contains only the structure definitions, the prototypes, the "extern" references and the #defines. It is useful if you want to access the GUI from another module. This could be a description of a GUI: #c_source #define ExampleButton 1 // I want to have a more telling name than a number #end_source Projectname Test VBOX BUTTON TEXT "Test" ID ExampleButton end end To render the GUI to the window you would use: RenderGui(window,&Test); And to change the attributes of the gadget you would use: GG_SetGadgetAttrs(Test_Gadgets[Test_ExampleButton],window,NULL, ... ); Or for lowlevel changes: GG_SetLowlevelAttrs(&Test_GadInfo_ExampleButton, .... ); For the handling of gadgets, there are some useful macros in gengui.h, which is automatically included in the generated headerfiles: GetGadget() generates the address of the selected gadget from the received IntuiMessage: struct Gadget *GetGadget(struct IntuiMessage *) GetInfo() calculates the address of the GadInfo structure from the address of the gadget. struct GadInfo *GetInfo(struct Gadget *) GetString() takes the address of a string-gadget and retrieves a pointer to the contents of the buffer. UBYTE *GetString(struct Gadget *) GetNumber() retrieves the value stored in a number-gadget. LONG GetNumber(struct Gadget *) GetUserData(): Since Gengui needs the field "UserData" for internal use, it reserves another field for this purpose, it generates a this macro GetUserData() that fullfills the purpose of accessing this field for userdata. ULONG GetUserData(struct Gadget *) For the handling of customgadgets you require some additional defines: First there are some "modes" defined, whose meaning is explained in the chapter for customgadgets. The other structures in the headerfile contain the actual data that describes the GUI. Since they are not important for the programmer their names consist of the projectname and an extension of some numbers and characters. If you want to know more of what can be found in the headerfile you should have a look at the generated source :). 6. Writing code using GenGui ============================ The first thing you have to do is to write the file with the description of the GUI in the description-language, that was presented in chapter 2. The filename must have the extension .gui. The next step is to compile this description to a normal C-headerfile using GenGui: GenGui file.gui You will get two headerfiles: file.h and file_def.h "file.h" contains the data of the GUI and "file_def.h" contains all from "file.h" except for the data itself. There are two important aspects: - You must use Gui_GetIMsg() instead of GT_GetIMsg()! - You must use Gui_SetGadgetAttrs() instead of GT_SetGadgetAttrs()! The following example will show you how to use these GUI's within your own programs: #include "file.h" // include the headerfile that was generated by GenGui main() { struct IntuiMessage *msg; struct WIndow *win; int run=1; /* . Now open all required libraries and the window. "win" must point to . the newly opened window. */ /* The Projectname of the GUI is TestPro */ if(RenderGui(win,&TestPro)) {/* do the cleanup, send an error msg .... */} /* RenderGui returns 0 if successful, an error code on failure */ while(run) { WaitPort(win->UserPort); // you may use Wait instead, if you like :) while(msg=GG_GetIMsg(win->UserPort)) { /* It is very important that you use this function instead of GetMsg or GT_GetIMsg(), since it does some additional actions !!! */ switch(msg->Class) { case IDCMP_CLOSEWINDOW: run=0;break; case IDCMP_NEWSIZE: ResizeGui(&TestPro); // do the resizing break; case IDCMP_REFRESHWINDOW: RefreshGui(&TestPro); // and the refresh break; // ... and some more actions you need } GG_ReplyIMsg(msg); } } FreeGui(&TestPro); // Free the gadgets /* close the window and free the sources etc. */ } When opening the window you should consider that it must be large enough to have room for all gadgets. If the window is too small then the GUI will look quite messed up. You can determine the minimal required size with the GG_MinSize function, at least when the MIN-sizes are correctly set. Or you can use GG_SmartRenderGui, which takes care of the needed size and moves or resizes the window due to these requirements. It even substitutes the font used in the window by a smaller one, if required. 5. Hook functions ================= For every gadget you may define a hook-function. This function is called whenever Intuition sends a message for this gadget. It receives the address of the Intuimessage as parameter and must return an int as result. If you return null then the Intuimessage is passed on to your main program, in the other case the Intuimessage is ignored and your program will not receive this message any more: int __stdargs HookFunction(struct IntuiMessage *msg) { int ignore=1; /* The IntuiMessage will not be passed on to the program */ /* do some actions */ return ignore; } 7. Custom gadgets ================= Custom gadgets are a very powerful element for generating graphical user interfaces. They not only allow you to add gadgets other than gadtools gadgets, you can also use it to render information to the window, that is not really a gadget, for example some borders or texts, which should be resizeable. And a special thing which you can create using customgadgets are multiplexed user interfaces. "What's that?", you may ask. OK, I'll give you an idea, what you can achieve by this. Imagine that there is not enough room in the window to place all gadgets in it. Then you could have e.g. a cyclegadget with which you can select the group of gadgets you want to be visible in the window. First at all every customgadget requires a function that handles the creation of the "gadget". This function gets 7 arguments, the first one is a pointer to a WinInfo structure, the second one is a pointer to a NewGadget structure which was filled with all needed data (only MODE_NEW,MODE_RESIZE and MODE_REFRESH). The third one is a pointer to a GadInfo and the last four parameters describe the position and the width/height of the area of gadget. NOTE: The area of the gadget also contains the spacing around the gadget. The (suggested) dimensions of the gadget itself can be found in the newgadget structure. This function is called in several cases. It is not only called when the gadget should be created, but also when it should be removed. There are 6 Modes, which are marked in 'Mode' field of the WinInfo structure. The Modes are: GG_MODE_NEW: A new gadget should be created. If you create gadgets you should add them to the GList 'Gadgets' in the WinInfo structure and fill 'Prev' in the same structure with the pointer to the last gadget. GG_MODE_RESIZE: The gadget should be resized. You must not use GT_SetGadgetAttrs() to change the state of gadtools gadgets, since during the GG_MODE_RESIZE call the gadgets are not bound to any window and GG_SetGadgetAttrs() would not work at this point, but you might use GG_SetLowlevelAttrs(). GG_MODE_REFRESH: Redraw the gadget. You need not redraw system-gadgets, since RefreshGList() is called internally. GG_MODE_FREE: Free the gadget and delete all stored contents GG_MODE_STOP: Delete the gadget, but keep the contents, that were stored by GG_MODE_BACKUP. GG_MODE_BACKUP: Store the complete information of the gadget e.g. if the gadget is disabled and the selection-state. You may store that information in the Code field of the delivered GadInfo structure and the information if it is disabled can be stored using the flag GG_FLAG_DISABLED in 'dim.Flags' of this structure. You must not change any other bits in this field. GG_MODE_RESTORE: Restore the information that was stored with GG_MODE_BACKUP. If you just want to draw some lines, you should ignore the latter three cases that are only important for the handling of gadgets or 'SubGui's. In these cases the contents of the NewGadget structure are not valid, however you will get a pointer to such a structure to avoid enforcer-hits. You can also use the field Render in the WinInfo structure to determine if you have draw your lines. It is set to 1 if drawing is needed and to 0 if not. You must return 0 if everything was OK and any value !=0 if an error occurred. If you want to draw some lines and render another GUI in this area you can use "SubGuis". Therefore you must describe a complete GUI just like before and render this GUI with GG_SubGui() to the window. This function takes the same parameters as RenderGui() plus four additional parameters which describe the position and the dimensions of the GUI. You must call this every time your customfunction is called. This function returns 0 on success and a value !=0 if an error occurred. In this case your function must also return a value !=0 to tell that there was an error. There is another thing that is possible using 'SubGuis', that are multiplexed user-interfaces. You might have several groups of gadgets that are rendered to the same place in the window and e.g. a global variable decides which of these groups is displayed in the window. Note that you must remove the complete GUI from the window first, if you want to switch the groups, but you cannot use FreeGui(), since this would lose the complete information that is stored in the GUI. StopGui() exists for this case. It stores this information and removes the GUI after this. The next time you call RenderGUI this information is restored. StopGUI() can also be used if you want to keep informations although you want to close the window, because you might reopen it later. See also the example for multiplexed interfaces. 8. The functions in the runtime-library "gengui_lnk.o" ====================================================== GG_BeginResizeGui: void GG_BeginResizeGui(struct WinInfo *winfo) You can use this function to speed up the process of resizing the GUI. Therefore you have to use IDCMP_SIZEVERIFY, which signals your program, that the user wants to resize the GUI. If you call GG_BeginResizeGui, when this happens, all gadgets are detached from the window and intuition does no refresh on these gadgets, which would be useless anyways, since the GUI is refreshed after it has been resized. But note, you really should know, that if you don't handle this message immediately, you may get a deadlock of your system. Therefore don't use IDCMP_SIZEVERIFY if you are not sure about the side-effects of switching on this message-type. It's probably better to have a slightly slower program, than a buggy program. GG_ClearWindow: void GG_ClearWindow(struct Window *) Removes all contents from the window, erases the inner of the window with the EraseRect() and refreshes the windowborders. GG_FreeGui: void GG_FreeGui(struct WinInfo *winfo) GG_FreeGui removes the gadgets from the window. It is save to call this functions for already freed GUIs. GG_GetIMsg: struct IntuiMessage *GG_GetIMsg(struct MsgPort *) You must call this function instead of GT_GetIMsg() or GetMsg(). It returns a pointer to an IntuiMessage, if there is a message of interest for the program, otherwise it returns NULL. This is for example the case if you have a hook-function seleced for a gadget which returns a value !=0 to indicate that the message may be ignored. GG_GfxPrint: void GG_GfxPrint(struct RastPort *rast,char *text,int left,int top); This function is used to format and print a text to a RastPort. The following format-specifiers are supported: \n : Newline: the next character is printed at the start of the next line. %% : '%' %Cx : Set foreground color to x (e.g. %C1 : set color to 1) %cx : Set background color to x %B : Bold on %b : Bold off %I : Italics on %i : Italics off %N : Normal style (Bold,Italics,Underlined off) %U : Underlined on %u : Underlined off Parameters: rast : Pointer to your RastPort text : A pointer to your textstring left,top : Left, top corner of the textblock GG_GfxPrintSize: void GG_GfxPrintSize(struct RastPort *rast,char *text,struct TextSize *size); This function is used to calculate the width and height a text would occupy when printed with GG_GfxPrint(). Parameters: rast : Pointer to your RastPort text : A pointer to your textstring size : A pointer to the struct, in which the result will be stored. GG_MinSize: void GG_MinSize(struct Window *win, struct WinInfo *gui, struct GG_ObjectSize *size); GG_MinSize calculates the minimal size for the window win, such that the gui will fit within this window. The result is written to 'size', which must point to some valid memory-position. This size does not cover any bordersizes of the window, these must be added to the calculated sizes. GG_MinSizeFont: void GG_MinSizeFont(struct TextFont *font, struct WinInfo *gui, struct GG_ObjectSize *size); GG_MinSizeFont calculates the minimal size for the font 'font', such that the gui will fit within window of this (inner) size. The result is written to 'size', which must point to some valid memory-position. This size does not cover any bordersizes of the window. Therefore it would be suitable for opening a window with WA_InnerWidth and WA_InnerHeight. GG_RefreshGui: int GG_RefreshGui(struct WinInfo *winfo) This function is used to refresh the gadgets within the window. It is only important if you are using SimpleRefresh, since only then it is your job to refresh the window. If you are using SmartRefresh windows then it should not be required since the system does that job for you. It returns 0 if everything was OK. GG_RenderGui: int GG_RenderGui(struct Window *win, struct WinInfo *winfo) GG_RenderGui draws the gadgets to the window. You must supply the pointer to the window and the pointer to the WinInfo structure of your GUI. This one can be obtained by using the & operator on the name that was selected using "PROJECTNAME" in the descriptionfile. It returns 0 if everything was OK. GG_ResizeGui: int GG_ResizeGui(struct WinInfo *winfo) This function is used to adapt the GUI to the new size when a window has been resized. You must call this function every time you receive a IDCMP_NEWSIZE message. It returns 0 if everything was OK. You can speed up the resizing-process by using GG_BeginResizeGui. GG_SetGadgetAttrs / GG_SetGadgetAttrsA: BOOL GG_SetGadgetAttrsA(struct Gadget *, struct Window *, struct Requester *, struct TagItem *) BOOL GG_SetGadgetAttrs(struct Gadget *, struct Window *, struct Requester *, Tag, ...) This is a replacemet for the function GT_SetGadgetAttrs of gadtools.library. You must call this function instead of that of gadtools, since Gengui needs to keep track of the information stored in the gadgets. NOTE: Whereas the gadtools function returns VOID this one returns if it was successful to modify the attributes. If there is not enough memory it returns 0 to indicate that there was an error and the attributes are not changed. GG_SetLowlevelAttrs / GG_SetLowlevelAttrsA: BOOL GG_SetLowlevelAttrsA(struct GadInfo *, struct TagItem *) BOOL GG_SetLowlevelAttrs(struct GadInfo *, Tag, ...) Whereas the GG_SetAttrs function cannot be used, as long as the GUI is not rendered to a window, and cannot be used for changing tags, that cannot be changed as long as Gadgets are rendered to a window, e.g. the depth of a palette-gadget, these functions can do this magic thing. If the GUI is already rendered to a window, you must call GG_ResizeGui after this function, to make these changes take effect. GG_ResizeGui removes and recreates all gadgets and this allows to change really all tags. GG_SmartRenderGui: int GG_SmartRenderGui(struct Window *win, struct WinInfo *winfo, struct TextFont **font) GG_SmartRenderGui determines the minimum size of the GUI and adjusts the window according to this information. Therefore it may resize and move the window and if this is not sufficient, it will switch to another font. Therefore you must call it with a pointer to a pointer to a font. If this pointer is a nullpointer, then it will open the topaz 80 font, in the other case it will use the delivered font as a fall-back font. It is up to you to close this font, when your program exits. If the GUI would not fit within the window, although it already uses the fall-back- font, it ignores that and the display might look messed up, but that's probably better, than not being able to display anything at all, since the user then really has no chance to use the program. GG_SmartRenderGui draws the gadgets to the window. You must supply the pointer to the window and the pointer to the WinInfo structure of your GUI. This one can be obtained by using the & operator on the name that was selected using "PROJECTNAME" in the descriptionfile. It returns 0 if everything was OK. Input: win: Pointer to an open Window winfo: Pointer to your GUI, You can obtain this pointer by using the & operator on the name, you have given for PROJECTNAME in the descriptionfile font: Pointer to an pointer to an fall-back-font or to a NULL-pointer. Result: 0 if everything was OK Example: struct TextFont *font=NULL; ... /* Open your window */ if(GG_SmartRenderGui(win,&Gui,&font)) { /* failed */ CloseWindow(win); if(font) CloseFont(font); /* additional error-handling */ } ... /* Your code goes here */ CloseWindow(win) if(font) CloseFont(font); /* you must not close it, as long as the window stays open, since it will be uses as long as this window exists */ Notes: - If you call it with your own fall-back font, that was obtained by OpenDiskFont, you must call CloseDiskFont instead of CloseFont. - The fall-back font should definitely be smaller than the default-font, GG_StopGui: void GG_StopGui(struct WinInfo *winfo) GG_StopGui() stores the information of the gadgets and removes them after this from the window. GG_RenderGui() will recognize if the information was stored and will restore them if this was the case. GG_SubGui: int GG_SubGui(struct WinInfo *parent, struct WinInfo *winfo, int left,int top,int width, int height) GG_SubGui allows to draw GUIs within another GUI. You must not use this function for other purposes. It is not possible to render a GUI only with this function. You must use GG_RenderGui() for this, since it allocates some additional resources wich are also required by GG_SubGui and must be already allocated when GG_SubGui is called. Useful Macros: -------------- GetString: UBYTE * GetString(struct Gadget *) This macro returns a pointer to the contents of a string-gadget if passed a pointer to the string-gadget. GetNumber: LONG GetNumber(struct Gadget *) This macro returns the contents of a integer-gadget if passed a pointer to the integer-gadget. GetInfo: struct GadInfo * GetInfo(struct Gadget *) This macro returns a pointer to the correlated GadInfo structure of a given gadget. GetUserData: ULONG GetUserData(struct Gadget *) This macro returns a the userdata of the given gadget. NOTE: You cannot use the udserdata-field of gadtools gadgets, since this field is required by the gengui link-library for internal use. GetGadget: struct Gadget * GetGadget(struct IntuiMessage *) This macro calculates the address of the gadget in an intuimessage of the type IDCMP_GADGETUP or IDCMP_GADGETDOWN 9. Compiling ============ You need to compile gengui_lnk.c in the Gui_lib directory and link this to your program. Of course you need not recompile it every time. Just compile it with your favourite C-compiler and then link gengui_lnk.o to your program. If you are using SAS-C, then you can use the already compiled module in this directory. 10. What's new ============= GenGui has some additional capabilities for designing GUI's. There are: - frames - bars - graphical buttons - formatted texts - backgound patterns Furthermore GenGui is now able to determine the minimum size of the window the GUI should be rendered to. Therefore there is a new set of commands for the description language, to determine the minimum size for boxes or gadgets with relative size. The user is supported by a quite complex default-mechanism, so that he need not give any information in most cases. Then I have cleaned up the names of the interface for gengui. But don't panic, if you define GG_OLDSTYLE you will get the old names for compatibility reasons. NOTE: It is not possible just to link with the new link-library, you have also to recompile the GUI-description with the new gengui, but that shouldn't be a problem. NOTE2: You should not use Gui_GetIMsg any more, which internally replies the Intuimessage, since this could mess up multi-selections of menus. Instead you should use GG_GetIMsg() and GG_ReplyMsg(). 11. Credits =========== Thanks to all who have sent me bug-reports and / or suggestions for improvements of this tool. @EndNode