home *** CD-ROM | disk | FTP | other *** search
-
- GadLayout version 36.26 release 1.7
- The Dynamic Gadget Layout System
-
- Copyright © 1992, 1993 by
- Timothy J. Aston
- All Rights Reserved
-
-
- * IMPORTANT - Read This (PLEASE):
-
- GadLayout is copyright, so you can't go ahead and just use it however you
- want, there are some restrictions. GadLayout consists of the C source
- files, all header files, and all documentation included. You may not
- modify GadLayout in any way. GadLayout exists for you, the software
- developer, to use it; however, certain conditions must be complied with
- before you do:
-
- 1. Your documentation must clearly state that it is making use of the
- GadLayout dynamic gadget layout system by Timothy Aston.
- 2. You must provide me with, free of charge, a copy of the software you use
- GadLayout in, and any subsequent updates to it that use GadLayout, also
- free of charge. This means that if the software you use it in is
- shareware, I must be considered a full-registered user of the software.
- Similarly for commercial software, you must provide me with a
- complimentary copy. And in all cases, as long as your software continues
- to use GadLayout, you must provide with all publically released updates.
- See the end of this document to find out how to get the stuff to me.
- I hope this isn't being too unreasonable, I basically just want to see
- all the software that uses GadLayout.
- 3. If you modify the GadLayout source at all, you must send your
- modifications to me. You may not under any circumstances use the
- GadLayout sources to create any kind of runtime-linking module, such
- as a standard Amiga shared-library.
- 4. You may not distribute modified GadLayout source, or include GadLayout
- source in a distribution without permission from the author.
- 5. Any modified versions of GadLayout will fall under this same licensing
- agreement.
-
-
- * Requirements:
-
- GadLayout is designed for use by programmers developing software for Release 2
- and higher of the Amiga's operating system. Though it can make use of
- locale.library, this is not required if you do not wish to make your gadgets
- locale-sensitive. In fact, software using GadLayout only absolutely
- requires V36 of the OS to run (unless you make use of some of the locale
- features), however, it does REQUIRE V38 or greater of amiga.lib, because
- it needs the locale symbols to compile.
-
-
- * Introduction:
-
- Anyone that tried to design an attractive GUI in the days before Release 2
- has tremendous appreciation for the addition of gadtools.library. Nice
- looking 3-D gadgets can be created and controlled with ease. Though this
- was a major innovation, it is still lacking. Another nice addition in
- Release 2 was much better support for user-definable fonts. The problem
- is the GadTools does very little to help you adjust on the fly to different
- font sizes, you must do all the calculations yourself. Anyone that has
- tried to do this realizes that this is quite a tedious task indeed. What
- most people end up doing (including Commodore themselves :( ) is hard-code
- their programmes to use the Topaz 8 font. As an added complication, with
- the advent of localization, programmes should now be able to adjust to adjust
- to different languages.
-
- GadLayout is an attempt to take care of these problems. It takes away the
- job of having to calculate gadget sizes and positions relative to font
- size and language being used. Under GadTools, size and position have to
- be specified simply in absolute pixels. GadLayout is partly a frontend to
- GadTools, allowing you to define size and height in much more complex ways
- (though you can still specify absolute pixels, this will still be easier
- than using straight GadTools, but it is not really taking advantage of the
- power GadLayout offers). Gadgets can be automatically sized to fit text in
- any font (including proportional), and can be aligned with other gadgets.
- The actual technique is very simple, but gives you tremendous control over
- the placement of your gadgets. GadLayout also expands on GadTools by
- offering you some new gadget kinds.
-
- This document is meant to be a tutorial in C for using GadLayout in your
- programmes. Not every detail of GadLayout will be given here, for a full
- reference, use the autodoc and includes file GadLayout.doc and gadlayout.h.
- In fact, to properly learn about programming with GadLayout, you should be
- consulting this document, the reference files and the examples concurrently.
-
-
- * Before You Do Anything:
-
- Though it maybe your software, you don't really have total freedom in the
- design of its user interface. Commodore has a book called the User Interface
- Style Guide that defines some standards in how programmes should appear and
- opperate. So before you decide how your programme will look, you study this
- book and make sure that it complies with the conventions Commodore has set
- out.
-
-
- * The Basics:
-
- GadLayout requires that LocaleBase be declared. You do not need to open
- locale.library if you don't want to use make your gadgets locale-sensitive,
- but you will get a linker error if you don't declare it. In C, you would
- use:
-
- struct Library *LocaleBase = NULL;
-
- Next comes the definitions of your gadgets. Each gadget you define as a
- tag list. If you are not familiar with tag lists, please consult the
- Amiga ROM Kernal Reference Manual: Libraries, it explains how to use them.
- You should be able to get the jist from the examples as well. As with
- any tag list, a GadLayout gadget tag list consists of a tag followed by
- some piece of information. All the tags supported are defined in the C
- header file gadlayout.h (sorry, no header files for other languages, C is all
- I know). The only required tag is GL_GadgetKind, though you will always want
- to use at least a few others. You only have to include tags for data that
- has changed from the previous gadget, and tags can be given in any order
- (NOTE: there are cases where this is not necessarily the case, see later
- on). A basic gadget could be defined as follows:
-
- struct TagItem mygad_layout_tags[] =
- {
- { GL_GadgetKind, BUTTON_KIND },
- { GL_GadgetText, "Test Button" },
- { GL_Top, 4 },
- { GL_Left, 4 },
- { GL_Width, 140 },
- { GL_Height, 12 },
- { GL_Flags, PLACETEXT_IN },
- { TAG_DONE, NULL },
- };
-
- (The label before the comma is the tag, the expression to the left is that
- tag data, and the two together are called a tag item. The examples given here
- will use a variety of the available tags, but for a full listing with
- explanations, you will need to consult the autodoc and header files.)
-
- This example is very simple, and you really should not ever use something like
- this in real life. The reason you shouldn't is because of the use of absolute
- co-ordinates, this is not much better than using straight GadTools. If the
- font we were using here was something large, even like Times 13, the text
- would not fit in the gadget bounds and we'd get a mess. The idea is that
- gadgets should adjust in size to different user fonts. Here's how you'd
- really want to do it:
-
- struct TagItem mygad_layout_tags[] =
- {
- { GL_GadgetKind, BUTTON_KIND },
- { GL_LocaleText, MSG_GAD_TESTBUTTON },
- { GL_Top, 4 },
- { GL_Left, 4 },
- { GL_AutoWidth, 12 },
- { GL_AutoHeight, 4 },
- { GL_Flags, PLACETEXT_IN },
- { TAG_DONE, NULL }
- };
-
- We've made only three changes here. First of all, instead of hard-coding a
- string, we'll be getting a string from our locale language catalog (how to
- specify which catalog to use will be explained later on). Next problem is
- fitting the text instead the gadget. For this, we use the GL_AutoHeight and
- GL_AutoWidth tags. GL_AutoHeight will make the gadget's height adjust
- automatically to whatever font the user is using (how to tell your gadgets
- which font to use will also be explained later on). The data field in the
- tag list (4 in our example) is a constant that gets added to the height
- calculation, this is just so the text doesn't looked cramped inside the
- gadget's border. GL_AutoWidth is similar, it looks at the gadget text and
- makes the gadget wide enough to fit that text with the current font, and
- also allows you to add a constant to that calculate to give a bit of a
- border. Note that this is one of those cases where the order of the tags
- DOES matter: if you want to use GL_AutoWidth you MUST use either GL_GadgetText
- or GL_LocaleText beforehand; this is since GL_AutoWidth must know what the
- text is in order to calculate its width.
-
- You make tag lists such as the one above for every gadget you want to include
- in your gadget list. After these are all defined, you need to group them
- together in an array of LayoutGadget structures (see gadlayout.h). Each
- element in the array is a gadget, it needs the gadget Intuition ID, and a
- pointer to its GadLayout tag list. It also may need a pointer to its
- GadTools tag list. GadTools tags are the tags that you would normally pass
- to the GadTools function CreateGadgetA() when creating a GadTools function.
- A very simple example might be:
-
- struct mygad_gadtools_tags[] =
- {
- { GT_Underscore, '_' },
- { TAG_DONE, NULL }
- }
-
- Lastly, each element in the array needs a spot where it will store the Gadget
- structure pointer of the gadget once it gets created. This should be
- initialized to NULL. All these go in an array, eg:
-
- struct LayoutGadget mygadgets[] =
- {
- { GAD_MYGAD1, mygad1_layout_tags, mygad1_gadtools_tags, NULL },
- { GAD_MYGAD2, mygad2_layout_tags, mygad2_gadtools_tags, NULL },
- { -1, NULL, NULL, NULL } /* Gadget ID of -1 marks the end */
- }
-
- All that's left is the actual creation and laying out of the gadgets. This is
- done in one batch using a single call to the GadLayout function
- LayoutGadgetsA() (or its var args stub, LayoutGadgets()). This routine takes
- a pointer to your initialized gadget list pointer, the screen the gadgets are
- going to made on, your LayoutGadget array, plus some tag lists for setting
- various options. Here's how you might use it:
-
- struct Gadget *glist;
- WORD right_extreme, lower_extreme;
- [...]
- gi = LayoutGadgets(&glist, mygadgets, screen,
- GL_RightExtreme, &right_extreme,
- GL_LowerExtreme, &lower_extreme,
- GL_DefTextAttr, screen->Font,
- TAG_DONE);
-
- The value returned is a pointer to a private structure. You must keep this
- value in order to use the FreeLayoutGadgets() to properly free all resources.
- If the gadgets couldn't be laid out for some reason (eg. no memory), then
- the return value will be NULL.
-
- This example makes use of some the tags that you can pass to LayoutGadgets().
- The first two tags are used in conjunction to find out how far right and how
- far down a window gadget imagery will be rendered. You use these values when
- you open your window, so that you can have it sized to perfectly fit in all
- your gadgets. The last tag, GL_DefTextAttr tells us which font to use for
- all the gadgets defined (not that it is possible to use different fonts for
- each gadget, but if they're all going to have the same font, this is a much
- easier way of specifying it). Here we just grab the font that is being used
- by whatever screen we are to open on. It is good practice to use the font
- that the user has selected as the Screen font in his/her Font preferences
- (you can get this by looking at wbscreen->Font) since you can very easily
- make your gadgets adjust to any font using GadLayout.
-
- If the call was successful, glist will be an initialized gadget list, ready to
- be passed to OpenWindowTags(), AddGList(), etc. This is a GadTools gadget
- list, so you must use gadtools.library functions such as GT_GetMsg() and
- GT_RefreshWindow() to handle the processing of these gadgets.
-
- You finish off with a called FreeLayoutGadgets() in order to release the
- resources used by your gadgets. NOTE: Do NOT use the GadTools function
- FreeGadgets() to free your gadgets, GadLayout uses some additional resources
- that this function will not free.
-
-
- * Fancy Stuff:
-
- GadLayout provides you with tremendous power and flexability in defining your
- gadgets. So far we've only just touched in this with the automatic sizing.
- Another concept that GadLayout introduces is the idea of positioning and
- sizing gadgets relative to others. Often times, you'll have gadgets generally
- laid out in columns of some sort. Because gadget size will vary depending on
- font size, you'll specify a gadget's top edge relative to the bottom edge of
- the gadget immediately above it, using the GL_TopRel gadget. Usually you
- will want all their widths to be the same, so you will use the GL_DupeWidth
- tag to make the width of a gadget the same as another (you should duplicate
- the width of the gadget with the longest string, so that others will be wide
- enough). These are just a couple of examples, see the descriptions of the
- available tags to see the extensive list of options you have available to
- you in positioning gadgets.
-
- You have to be a little careful when using tags like these that reference
- other gadgets. It was stated before earlier that you need not specify tags
- for items that haven't changed from the previous gadget, and that the order
- of tags doesn't really matter. But you'll see that you have to be a little
- more careful of this when using tags that reference other gadgets. To see
- how, we'll have to look at how the gadgets are setup and laid-out by
- GadLayout:
-
- Each gadget in the array is processed sequentially, and all the values
- calculated for it are preserved for the next gadget, so for a field that
- doesn't change (eg. say you're making a column of gadgets, the left edge won't
- change until you start a new column) you won't have to bother specifying it
- again and again. But, once GadLayout hits a tag that refers to another
- gadget, it must stop the processing of that gadget and process the referenced
- gadget if it has not already been processed. Where problems can arise is if
- this gadget attempts to reference back to the gadget that referenced it. That
- gadget has only been partially processed, so not all fields in it will
- necessarily be defined. And if the referencing tag needs to look at a field
- that has not yet been calculated, you'll get a wrong result. Here's an
- example:
-
- struct TagItem button1_layout_tags[]
- {
- { GL_GadgetKind, BUTTON_KIND },
- { GL_GadgetText, "A Button" },
- { GL_DupeWidth, GAD_BUTTON2 },
- { GL_AutoHeight, 4 },
- { GL_Top, 4 },
- { GL_Left, 4 },
- { GL_Flags, PLACETEXT_IN },
- { TAG_DONE, NULL }
- };
-
- struct TagItem button2_layout_tags[]
- {
- { GL_GadgetKind, BUTTON_KIND },
- { GL_GadgetText, "Another Button" },
- { GL_AutoWidth, 12 },
- { GL_TopRel, GAD_BUTTTON1 },
- { GL_AddTop, 4 },
- { GL_Left, 4 },
- { GL_Flags, PLACETEXT_IN },
- { TAG_DONE, NULL }
- };
-
- This will not yield the correct result at all. When the GL_DupeWidth tag is
- hit, processing will jump to the second gadget. Once it hits the GL_TopRel
- gadget, it will look back at the first gadget, and see that it is already
- being processed, so it won't try to process it now. It grab its top edge
- and height fields to find its bottom edge so that the second gadget gets
- placed relative to that. Problem is that the top edge and height for the
- first gadget have not been calculated, so the second gadget will not get the
- value you wanted for its top edge. In order to get what we want, we just
- have to make sure that the top edge and height are already calculated before
- the second gadget will reference them:
-
- struct TagItem button1_layout_tags[]
- {
- { GL_GadgetKind, BUTTON_KIND },
- { GL_GadgetText, "A Button" },
- { GL_Top, 4 },
- { GL_AutoHeight, 4 },
- { GL_DupeWidth, GAD_BUTTON2 },
- { GL_Left, 4 },
- { GL_Flags, PLACETEXT_IN },
- { TAG_DONE, NULL }
- };
-
- struct TagItem button2_layout_tags[]
- {
- { GL_GadgetKind, BUTTON_KIND },
- { GL_GadgetText, "Another Button" },
- { GL_AutoWidth, 12 },
- { GL_TopRel, GAD_BUTTTON1 },
- { GL_AddTop, 4 },
- { GL_Left, 4 },
- { GL_Flags, PLACETEXT_IN },
- { TAG_DONE, NULL }
- };
-
- Its a little confusing, you just have to follow the order in which gadgets
- will get processed, and you should be able to see why the first example is
- wrong.
-
-
- * GadLayout Gadget Kinds:
-
- As mentioned in the introduction, GadLayout expands upon the gadget kinds
- that GadTools supports. Currently, GadLayout adds three kinds: IMAGE_KIND,
- DRAWER_KIND and FILE_KIND. IMAGE_KIND is very similar to the GadTools
- BUTTON_KIND gadget, expect that instead of displaying text within, it will
- show an Intuition Image structure. The DRAWER_KIND and FILE_KIND gadgets
- are both very similar, and are essentially just special kinds of IMAGE_KIND
- gadgets. You use them to allow the user to select a path of filename
- respectively. When the user clicks a DRAWER_KIND gadget, you should bring
- up an ASL file requester to allow the user to select a path (for example,
- the directory where downloads are placed by a terminal programme). Likewise
- for a FILE_KIND gadget so that the user may choose a filename (for example,
- the name of a script to run). As a matter of style, accompany the DRAWER_KIND
- and FILE_KIND gadgets with a string gadget to their immediate right so that
- the user may type his/her selection instead of having to go through the file
- requester.
-
- These gadgets have tags specific to them, just like the GadTools gadgets do.
- But instead of putting them in a seperate tag list like you do with the tags
- for all GadTools gadget kinds, you include them with the GadLayout tags, eg:
-
- struct TagItem drawergad_layout_tags[] =
- {
- { GL_GadgetKind, IMAGE_KIND },
- { GL_GadgetText, "My _Image" },
- { GL_Top, 4 },
- { GL_Left, 4 },
- { GL_Width, 100 },
- { GL_Height, 60 },
- { GL_Flags, PLACETEXT_ABOVE },
- { GLIM_Image, NULL },
- { TAG_DONE, NULL }
- };
- [...]
- drawergad_layout_tags[6].ti_Data = image;
-
- The GLIM_Image tag is a tag specific for IMAGE_KIND gadgets. You use this to
- point to the Image structure that you want displayed within the gadget. Note
- here how we actually set this AFTER the tag list has been defined. This is
- something you will need to do sometimes with GadLayout, since all information
- is not necessarily known at initialization time (an excellent example of this
- will be with a LISTVIEW_KIND gadget and the GTLV_Labels task, you will have
- to first build the list, then you can set that pointer).
-
- If you want to modify attributes of a GadLayout gadget kind, you must use the
- GadLayout function GL_SetGadgetAttrsA() (or the var args stub
- SetGadgetAttrs()) as opposed the the GadTools functions that you would use for
- modifying a GadTools gadget kind.
-
-
- * Acknowledgements:
-
- I'd like to thank the following people, all of them were a great help in
- getting GadLayout out the door:
-
- - Mark Rickan (general input and support)
- - Ralph Schmidt (for answers to various gadget related questions)
- - Olaf Barthel (used some of the code from his Term 2.4)
- - Pasi Ilola, for porting the assembler headers, and some suggestions.
- - Commodore (for writing the Style Guide)
- - U2, for the music (which I listen to most of the time while developing :)
-
-
- * About the Author:
-
- I (Tim Aston) am a university student, taking specialized honours computing
- and information science at the University of Guelph. My hobbies include
- computing, hockey (Montreal Canadiens all the way!), politics, etc. My
- key interests in computing are personal computer application software and
- operating systems, in particular how they relate to user interface design.
-
- Some of you may know me as the author of TransAmiga BBS, and I've also been
- around the FidoNet and IRC scene for a bit now, and may know me from there.
- My current project is a text editor, and it was while writing this that I
- realized how much a better system for laying out gadgets was needed. From its
- initial conception to the first release, it has taken a little less than 2
- months to produce GadLayout. I plan to continue to expand upon GadLayout
- (particularly with new gadget kinds) for as long as there is a need and
- sufficient demand.
-
- If you're designing a programme with a GUI (whether it uses GadLayout or
- not), feel free to get in contact with me for some suggestions and ideas
- to improve upon it, I think I've got quite a knack for pointing out
- deficiences in a GUI.
-
- If you wish to contact me, any of the following means are fine:
-
- IRC: Timmer @ #amiga
- InterNet E-Mail: cs1087@snowhite.cis.uoguelph.ca
- FidoNet: Tim Aston @ 1:247/192
- FAX: (416)682-3501
- Regular Mail: Tim Aston
- 128 Riverview Blvd.
- St. Catharines, Ont.
- L2T 3M2
- Canada
-
- Those are listed in the order in which I will generally be most swift in
- replying. When you are releasing software that uses GadLayout, initially you
- must send it through the mail to my home address, however you can use my
- InterNet address to E-Mail me uuencoded updates. I may be open to other
- means, just ask.
-
- I thank you for you interest in GadLayout, and I'll be happy to listen to any
- questions of comments you might have. I especially look forward to seeing
- your programmes' high quality GUIs using GadLayout!
-
-
- -Tim
- ¬