home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 2: PC
/
frozenfish_august_1995.bin
/
bbs
/
d09xx
/
d0911.lha
/
GadLayout
/
gadlayout.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-03
|
54KB
|
1,642 lines
/*
** $Filename: gadlayout/gadlayout.c $
** $Release: 1.6 $
** $Revision: 36.22 $
** $Date: 93/07/04 $
**
** GadLayout functions, a dynamic gadget layout system.
**
** (C) Copyright 1992, 1993, Timothy J. Aston
** All Rights Reserved
**
** 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.
**
**
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <utility/tagitem.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <graphics/clip.h>
#include <graphics/layers.h>
#include <libraries/gadtools.h>
#include <libraries/locale.h>
#include <clib/exec_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <clib/layers_protos.h>
#include <clib/locale_protos.h>
#include <clib/utility_protos.h>
#include "gadlayout.h"
/* #define GL_DEBUG 1 */
#define MAX(a, b) (a > b) ? a : b
#define MIN(a, b) (a < b) ? a : b
#define GADLAYOUT_KIND 0xF001
#define GLFLG_READONLY 0x002
/* Local structure used to hold the definitions for the gadgets once they
* have been laid out.
*/
struct LaidOutGadget
{
BOOL log_IsEvaluated;
ULONG log_GadgetKind;
struct NewGadget log_NewGadget;
};
/* Structure used to hold the application strings, used incase we couldn't
* get a string from the locale catalog.
*/
struct AppString
{
LONG as_ID;
STRPTR as_Str;
};
/* Private Local structure used to hold all gadget information that needs to
* be freed.
*/
struct PrivateInfo
{
struct Screen *pi_Screen;
APTR pi_VisualInfo;
struct DrawInfo *pi_DrawInfo;
struct Gadget *pi_GadList;
struct Catalog *pi_Catalog;
struct AppString *pi_AppStrings;
struct Remember *pi_Remember;
};
/* Local function prototypes.
*/
VOID evaluate_gadget(struct PrivateInfo *, WORD, struct LayoutGadget *, struct NewGadget *, struct LaidOutGadget *);
LONG text_width(char *, struct TextAttr *);
STRPTR get_locale_string(struct Catalog *, struct AppString *, LONG);
struct Gadget * create_layout_gad(struct PrivateInfo *, WORD, struct Gadget *, struct NewGadget *, struct TagItem *);
struct Image * create_gad_images(WORD, UWORD, UWORD, struct PrivateInfo *, struct Image *, BOOL);
/* Public function prototypes. These function definitions may differ slightly
* from what appears in gadlayout_protos.h (the public definitions) since we
* must hide private structures by using APTRs.
*/
struct PrivateInfo * LayoutGadgets(struct Gadget **, struct LayoutGadget *, struct Screen *, Tag *, ...);
struct PrivateInfo * LayoutGadgetsA(struct Gadget **gad_list, struct LayoutGadget *g, struct Screen *, struct TagItem *);
VOID GL_SetGadgetAttrs(struct PrivateInfo *, struct Gadget *, struct Window *, struct Requester *, Tag *, ...);
VOID GL_SetGadgetAttrsA(struct PrivateInfo *, struct Gadget *, struct Window *, struct Requester *, struct TagItem *taglist);
WORD GadgetArrayIndex(WORD, struct LayoutGadget *);
VOID FreeLayoutGadgets(struct PrivateInfo *);
extern struct Library *LocaleBase;
/* Data for the drawer image.
*/
__chip static UWORD drawer_data[10] =
{
0x03C0,
0x0420,
0xF810,
0xFC10,
0xC3F0,
0xC010,
0xC010,
0xC010,
0xC010,
0xFFF0
};
/* Data for the file image.
*/
__chip static UWORD file_data[10] =
{
0xFF00,
0xC180,
0xC140,
0xC120,
0xC1F0,
0xC030,
0xC030,
0xC030,
0xC030,
0xFFF0
};
struct Image file_image =
{
0, 0,
12, 10,
2,
file_data,
0x01, 0x00,
NULL,
};
/* Data for the drawer image.
*/
struct Image drawer_image =
{
0, 0,
12, 10,
2,
drawer_data,
0x01, 0x00,
NULL,
};
/****** gadlayout/LayoutGadgetsA ********************************************
*
* NAME
* LayoutGadgetsA -- Formats an array of GadTools gadgets.
* LayoutGadgets -- Varargs stub for LayoutGadgetsA().
*
* SYNOPSIS
* gad_info = LayoutGadgetsA(gad_list, gadgets, screen, taglist)
* APTR LayoutGadgetsA(struct Gadget **, struct LayoutGadget *,
* struct Screen *, struct TagItem *)
*
* gad_info = LayoutGadgets(gad_list, gadgets, screen, firsttag, ...)
* APTR LayoutGadgets(struct Gadget **, struct LayoutGadget *,
* struct Screen *, Tag *, ...)
*
* FUNCTION
* Creates a laid-out gadget list from a LayoutGadget array, which
* describes each gadget you want to create. Gadgets you create
* can be any of the gadget kinds supported by GadTools, as well
* as any of the extended gadget kinds provided by GadLayout.
* Gadgets can easily be defined so that the automatically adjust
* their sizes and positions to accomodate fonts of any size
* (including proportional fonts) and also to adapt to different
* locale strings. The real power of GadLayout is that allows you
* to create a gadget layout that dynamically adjusts to different
* user's environments.
*
* INPUTS
* gad_list - Pointer to the gadget list pointer, this will be
* ready to pass to OpenWindowTags() or AddGList().
*
* gadgets - An array of LayoutGadget structures. Each element
* in the array describes one of the gadgets that you will
* be creating. Each LayoutGadget structure in the array
* should be initialized as follows:
*
* lg_GadgetID - The ID for this gadget.
* lg_LayoutTags - A taglist consisting of the following tags:
* GL_GadgetKind (ULONG) - Which gadget kind to use. This
* may be any of the GadTools gadget kinds (defined in
* libraries/gadtools.h), or one of the additional kinds
* provided by GadLayout, which are:
* IMAGEBUTTON_KIND : A button gadget with that uses an
* Intuition Image structure for its
* contents. The image will be centred
* automatically.
* DRAWER_KIND : A drawer button gadget. Use this to
* allow the user to use the ASL file
* requester to select a path.
* FILE_KIND : A file button gadget. Use this to allow
* the user to use the ASL file requester
* to select a file.
* Additional kinds may be added in the future.
* GL_Width (WORD) - Absolute gadget width, in pixels.
* GL_DupeWidth (UWORD) - Duplicate the width of another
* gadget.
* GL_AutoWidth (WORD) - Set width according to length of
* text label + ti_Data. Note that this function
* does not take into account the amount of space any
* gadget imagery might take within the gadgets area.
* GL_Columns (UWORD) - Set width of gadget so that
* approximately ti_Data columns of text with the
* gadget's font will fit. This will only be an
* approximation, because with proportional fonts the
* width of character varies. Note that this function
* does not take into account the amount of space any
* gadget imagery might take within the gadgets area.
* GL_AddWidth (WORD) - Add some value to the total width
* calculation.
* GL_MinWidth (WORD) - Make sure that the final width of
* the gadget is at least this.
* GL_MaxWidth (WORD) - Make sure that the final width of
* the gadget is at most this.
* GL_Height (WORD) - Absolute gadget width.
* GL_HeightFactor (UWORD) - Make the gadget height a multiple
* of the font height (useful for LISTVIEW_KIND gadgets).
* GL_AutoHeight (WORD) - Set height according to height of
* text font + ti_Data.
* GL_AddHeight (WORD) - Add some value to the total height
* calculation.
* GL_MinHeight (WORD) - Make sure that the final height of
* the gadget is at least this.
* GL_MaxHeight (WORD) - Make sure that the final height of
* the gadget is at most this.
* GL_Top (WORD) - Absolute top edge.
* GL_TopRel (UWORD) - Top edge relative to bottom edge of
* another gadget (specified by its gadget ID).
* GL_AdjustTop (WORD) - ADD the height of the text font +
* ti_Data to the top edge (often used to to properrly
* position gadgets that have their label above).
* GL_AddTop (WORD) - Add some value to the final top edge
* calculation.
* GL_Bottom (WORD) - Absolute bottom edge.
* GL_BottomRel (UWORD) - Bottom edge relative to top edge of
* another gadget (specified by its gadget ID).
* GL_AddBottom (WORD) - Add some value to the final bottom edge
* calculation.
* GL_Left (WORD) - Absolute left edge.
* GL_LeftRel (UWORD) - Left edge relative to right edge of
* another gadget (specified by its gadget ID).
* GL_AdjustLeft (WORD) - ADD the width of the text label +
* ti_Data to the left edge.
* GL_AlignLeft (UWORD) - Align the left edge of the gadget
* with the left edge of another gadget (specified by its
* gadget ID).
* GL_AddLeft (WORD) - Add some value to the final left edge
* calculation.
* GL_Right (WORD) - Absolute right edge.
* GL_RightRel (UWORD) - Right edge relative to left edge of
* another gadget (specified by its gadget ID).
* GL_AlignRight (UWORD) - Align the right edge of the gadget
* with the right edge of another gadget (specified by its
* gadget ID).
* GL_AddRight (WORD) - Add some value to the final right edge
* calculation.
* GL_GadgetText (STRPTR) - Gadget text label.
* GL_TextAttr (struct TextAttr *) - Desired font for gadget
* label, will override the GL_DefTextAttr if used.
* GL_Flags - (ULONG) Gadget flags.
* GL_UserData (VOID *)- Gadget UserData.
* GL_LocaleText - Gadget label taken from a locale catalog,
* you supply the locale string ID. If you use this tag
* you MUST have used GL_AppStrings in your call to
* LayoutGadgets().
*
* If you've specified one of GadLayout's own gadget kinds
* with GL_GadgetKind, the following tags are available for
* defining attributes of those gadgets:
*
* GLIM_Image (struct Image *) - Provide a pointer to the
* Image structure to to be used in an IMAGEBUTTON_KIND
* structure. This pointer only need be valid when
* LayoutGadgets() is called.
* GLIM_ReadOnly (BOOL) - Specifies that the gadget is read-
* only. It will get a recessed border and will not be
* highlighted when clicked on.
*
* Generally you need only specify the tags when the data
* has changed from the previously gadget. This gets a
* little tricky when you use the relation tags like
* GL_TopRel, as this means that gadgets will not be
* processed in sequential order necessarily.
*
* lg_GadToolsTags - When defining a GadTools gadgets, you
* can pass a GadTools taglist to set options for that
* gadget. This would be the same set of tags that you
* might pass to CreateGadgetA() if you were using GadTools
* directly.
* lg_Gadget - The pointer to the Gadget structure created for
* this gadget will be placed here. You should initialize
* this field to NULL. WARNING: The gadget structure
* created READ-ONLY!
*
* screen - A pointer to the screen that the gadgets will be
* created for. The is required so that the layout routines
* can get display info about the screen, no rendering will
* be done.
*
* taglist - Pointer to a TagItem list (see below for allowed tags)
*
* TAGS
* GL_RightExtreme (LONG *) - A pointer to a LONG where GadLayout
* will put the co-ordinate of the rightmost point where any
* imagery of the laid-out gadgets will be drawn. Use this to
* open a window exactly big enough to hold all your gadgets.
* Use this value alone with the WA_InnerWidth window tag and
* NOT WA_Width, since you do not know how big the window
* border will be.
* GL_LowerExtreme (LONG *) - A pointer to a LONG where GadLayout
* will put the co-ordinate of the lowermost point where any
* imagery of the laid-out gadget will be drawn. Use this to open
* a window exactly big enough to hold all your gadgets.
* Use this value alone with the WA_InnerHeight window tag and
* NOT WA_Height, since you do not know how big the window
* border will be.
* GL_DefTextAttr (struct TextAttr *) - Instead of having to indicate
* a TextAttr for each gadget, you can specify a font to be used
* by default for all your gadgets.
* GL_Catalog (struct Catalog *) - Specify the locale catalog to use
* to get your strings from. If you wish to localize your gadget
* string via GL_LocaleText you MUST use this tag as well as
* GL_AppStrings. You must also make certain that locale.library
* has been opened successfully with LocaleBase pointing to the
* library base.
* GL_AppStrings (struct AppString **) - If you wish to make your
* gadgets localized, you you must pass a list of strings and
* their IDs. The format of these strings is an array of
* structures, with a LONG that contains the ID and a STRPTR
* pointing to the string, i.e.:
* struct AppString
* {
* LONG as_ID;
* STRPTR as_Str;
* };
* These strings serve as the default language for the gadgets.
* See locale.library documentation for more information on
* localizing applications. You MUST use this tag in addition to
* GL_Catalog if you wish to use GL_LocaleText to localize your
* gadgets.
* GL_NoCreate (BOOL) - Set to TRUE if you don't want the layout
* routine to actually create any gadgets. This is used when
* you want to use the GL_RightExtreme and GL_LowerExtreme tags
* to find out how much space your gadgets will take, but don't
* actually want to create the gadgets just yet.
* GL_BorderTop (UWORD) - The size of the top border of your window.
* If your window does not have the WFLG_GIMMEZEROZERO flag set,
* it will be necessary to pass the size of the window borders.
* This value can be gotten either from the Window structure of
* your window (if it is already open), or from the Screen
* structure of your screen (see intuition/screens.h for details
* about this). NOTE: This value is NOT added to the value
* returned by GL_LowerExtreme!
* GL_BorderLeft (UWORD) - The size of the left border of your window.
* If your window does not have the WFLG_GIMMEZEROZERO flag set,
* it will be necessary to pass the size of the window borders.
* This value can be gotten either from the Window structure of
* your window (if it is already open), or from the Screen
* structure of your screen (see intuition/screens.h for details
* about this). NOTE: This value is NOT added to the value
* returned by GL_RightExtreme.
*
* RESULT
* gad_info - A pointer to a private structure. You must keep this
* value and pass it to FreeLayoutGadgets() later on in order to
* free up all resources used by your gadgets.
*
* NOTES
* You must be careful with the taglist in the lg_LayoutTags field.
* Tags are processed sequentally in the order you give them in, and
* if a tag references another gadget (eg. the GL_TopRel tag), then
* processing of the current gadget halts while the referenced gadget
* is processed (if it has not already been processed). Problems can
* arise if this gadget refers back to the original gadget that
* referenced it, if it is referring to a field that has not yet been
* processed in that gadget. For example, gadget GAD_BUTTON1 may use
* the GL_TopRel tag to refer to GAD_BUTTON2, which may subsequently
* make use of GL_LeftRel to refer back to GAD_BUTTON1. The gadgets
* left edge must already be defined in GAD_BUTTON1 (i.e. a tag such
* as GL_Left MUST appear before the GL_TopRel tag) if GAD_BUTTON2 is
* to get the left edge desired.
*
* BUGS
* Doesn't do any checking to make sure gadgets don't overlap.
* Essentially assumes you know what you're doing with the layout.
*
* Bad things will happen if you provide an IMAGEBUTTON_KIND gadget
* with an image too big to fit within the dimensions you've provided
* for the gadget.
*
* SEE ALSO
* FreeLayoutGadgets(), gadlayout/gadlayout.h, libraries/gadtools.h,
* GadTools documentation.
*
*****************************************************************************
*
* Have you read the license info? It tells you that you must send your
* modifications of GadLayout to me, and that you may not make GadLayout
* into a shared library.
*
*/
struct PrivateInfo * LayoutGadgets(struct Gadget **gad_list, struct LayoutGadget *gadgets,
struct Screen *screen, Tag *firsttag, ...)
{
return( LayoutGadgetsA(gad_list, gadgets, screen, &firsttag) );
}
struct PrivateInfo * LayoutGadgetsA(struct Gadget **gad_list, struct LayoutGadget *gadgets,
struct Screen *screen, struct TagItem *taglist)
{
struct PrivateInfo *pi;
struct Gadget *last_gad;
struct NewGadget ng;
struct LaidOutGadget gad_array[100]; /* Cop-out, should be dynamic */
struct TagItem *tag=NULL;
struct TextAttr *tattr=NULL;
UWORD bordertop=0, borderleft=0;
WORD *rightextreme=NULL, *lowerextreme=NULL;
BOOL nocreate=FALSE;
WORD num_gads=0, i;
/* Allocate and initialize the PrivateInfo structure.
*/
if (!(pi = (struct PrivateInfo *)AllocVec(sizeof(struct PrivateInfo), MEMF_CLEAR)))
return(NULL);
pi->pi_Screen = screen;
if (!(pi->pi_VisualInfo = GetVisualInfo(screen, TAG_DONE)))
return(NULL);
if (!(pi->pi_DrawInfo = GetScreenDrawInfo(pi->pi_Screen)))
return(NULL);
pi->pi_Remember = NULL;
/* Count the number of gadgets that we have, and allocate space for
* NewGadget structures for all of them.
*/
while (gadgets[num_gads].lg_GadgetID != -1)
num_gads++;
/* if (!(gad_array = (struct LaidOutGadget *)AllocVec(num_gads * sizeof(struct LaidOutGadget), MEMF_ANY | MEMF_CLEAR)))
return(NULL); */
/* Evaluate the tag list. Order does not make any difference with the
* tags supported at the moment. In the case of duplicate tags, only
* the first will be recognized.
*/
/* ti_Data is a pointer to a LONG to store the right-most point that a
* gadget will exist in.
*/
if (tag = FindTagItem(GL_RightExtreme, taglist))
{
#ifdef GL_DEBUG
Printf("Tag: GL_RightExtreme Data: %ld\n",tag->ti_Data);
#endif
rightextreme = (WORD *)tag->ti_Data;
}
/* ti_Data is a pointer to a LONG to store the lower-most point that a
* a gadget will exist in.
*/
if (tag = FindTagItem(GL_LowerExtreme, taglist))
{
#ifdef GL_DEBUG
Printf("Tag: GL_LowerExtreme Data: %ld\n",tag->ti_Data);
#endif
lowerextreme = (WORD *)tag->ti_Data;
}
/* Indicates locale for the gadgets.
*/
if (tag = FindTagItem(GL_Catalog, taglist))
{
#ifdef GL_DEBUG
Printf("Tag: GL_Catalog Data: %ld\n",tag->ti_Data);
#endif
pi->pi_Catalog = (struct Catalog *)tag->ti_Data;
}
/* Indicates locale for the gadgets.
*/
if (tag = FindTagItem(GL_AppStrings, taglist))
{
#ifdef GL_DEBUG
Printf("Tag: GL_AppStrings Data: %ld\n",tag->ti_Data);
#endif
pi->pi_AppStrings = (struct AppString *)tag->ti_Data;
}
/* Specifies a default font for use with all gadgets, can still be
* over-ridden with GL_TextAttr.
*/
if (tag = FindTagItem(GL_DefTextAttr, taglist))
{
#ifdef GL_DEBUG
Printf("Tag: GL_DefTextAttr Data: %ld\n",tag->ti_Data);
#endif
tattr = (struct TextAttr *)tag->ti_Data;
}
/* Specifies the size of the top window border.
*/
if (tag = FindTagItem(GL_BorderTop, taglist))
{
#ifdef GL_DEBUG
Printf("Tag: GL_BorderTop Data: %ld\n",tag->ti_Data);
#endif
bordertop = (UWORD)tag->ti_Data;
}
/* Specifies the size of the left window border.
*/
if (tag = FindTagItem(GL_BorderLeft, taglist))
{
#ifdef GL_DEBUG
Printf("Tag: GL_BorderLeft Data: %ld\n",tag->ti_Data);
#endif
borderleft = (UWORD)tag->ti_Data;
}
/* Specifies that we don't actually want to create the gadgets.
*/
if (tag = FindTagItem(GL_NoCreate, taglist))
{
#ifdef GL_DEBUG
Printf("Tag: GL_NoCreate Data: %ld\n",tag->ti_Data);
#endif
nocreate = (BOOL)tag->ti_Data;
}
for (i = 0; i <= num_gads; i++)
gad_array[i].log_IsEvaluated = FALSE;
/* Initialize the gadget linked list.
*/
#ifdef GL_DEBUG
PutStr("Creating gadget context\n");
#endif
if (nocreate == FALSE)
{
if (!(last_gad = CreateContext(gad_list)))
return(NULL);
}
/* Initialize some suitable defaults for the gadgets.
*/
ng.ng_Height = ng.ng_Width = 0;
ng.ng_LeftEdge = ng.ng_TopEdge = 0;
ng.ng_GadgetText = NULL;
ng.ng_TextAttr = tattr;
ng.ng_GadgetID = 0;
ng.ng_Flags = 0;
ng.ng_VisualInfo = pi->pi_VisualInfo;
ng.ng_UserData = NULL;
if (rightextreme)
*rightextreme = 0;
if (lowerextreme)
*lowerextreme = 0;
/* Read each gadget in the layout array, setting up its NewGadget structure.
*/
#ifdef GL_DEBUG
PutStr("Evaluating each gadget\n");
#endif
for (i = 0; i < num_gads; i++)
evaluate_gadget(pi, i, gadgets, &ng, gad_array);
/* OK, the gagdets have all been laid out into NewGadget structures, we
* now go ahead and create them all.
*/
#ifdef GL_DEBUG
PutStr("Creating each gadget\n");
#endif
for (i = 0; i < num_gads; i++)
{
#ifdef GL_DEBUG
Printf("Creating gadget %ld\n", (WORD)i);
#endif
if (rightextreme)
*rightextreme = MAX(*rightextreme, gad_array[i].log_NewGadget.ng_LeftEdge + gad_array[i].log_NewGadget.ng_Width);
if (lowerextreme)
*lowerextreme = MAX(*lowerextreme, gad_array[i].log_NewGadget.ng_TopEdge + gad_array[i].log_NewGadget.ng_Height);
if (nocreate == FALSE)
{
gad_array[i].log_NewGadget.ng_LeftEdge += borderleft;
gad_array[i].log_NewGadget.ng_TopEdge += bordertop;
switch (gad_array[i].log_GadgetKind)
{
case IMAGEBUTTON_KIND:
case FILE_KIND:
case DRAWER_KIND:
gadgets[i].lg_Gadget = last_gad = create_layout_gad(pi,
gad_array[i].log_GadgetKind,
last_gad,
&(gad_array[i].log_NewGadget),
gadgets[i].lg_LayoutTags);
break;
default:
gadgets[i].lg_Gadget = last_gad = CreateGadgetA(gad_array[i].log_GadgetKind,
last_gad,
&(gad_array[i].log_NewGadget),
gadgets[i].lg_GadToolsTags);
break;
}
}
#ifdef GL_DEBUG
if (last_gad == NULL)
PutStr("Couldn't create gadget\n");
#endif
}
/* FreeVec(gad_array); */
#ifdef GL_DEBUG
PutStr("Done\n");
#endif
if (nocreate == FALSE)
{
if (last_gad != NULL)
{
pi->pi_GadList = *gad_list;
return(pi);
}
}
else
FreeVec(pi);
return(NULL);
}
/****** gadlayout/GL_SetGadgetAttrsA ****************************************
*
* NAME
* GL_SetGadgetAttrsA -- Change attributes of a GadLayout gadget.
* GL_SetGadgetAttrs -- Varargs stub for GL_SetGadgetAttrsA.
*
* SYNOPSIS
* GL_SetGadgetAttrsA(gad_info, gad, win, req, taglist)
* VOID GL_SetGadgetAttrsA(APTR, struct Gadget *, struct Window *,
* struct Requester *, struct TagItem *)
*
* GL_SetGadgetAttrs(gad_info, gad, win, req, firsttag, ...)
* VOID GL_SetGadgetAttrs(APTR, struct Gadget *, struct Window *,
* struct Requester *, Tag *, ...)
*
* FUNCTION
* Changes attributes for one of the GadLayout gadget kinds according
* according to the attributes chosen in the tag list.
*
* INPUTS
* gad_info - The value returned by LayoutGadgetsA().
* gad - Pointer to the gadget in question.
* win - Pointer to the window containing the gadget.
* req - Pointer to the requester containing the gadget, or NULL if
* not in a requester. (Not implemented yet, use NULL.)
* taglist - Pointer to a TagItem list.
*
* TAGS
* IMAGEBUTTON_KIND:
* GLIM_Image (struct Image *) - Changes the image displayed in the
* gadget.
*
* BUGS
* This function is not compatable with itself in versions releases
* 1.5 and lower, because of the new pi parameter! ALL OLD CODE
* WILL HAVE TO BE CHANGED!!!
*
* Attributes not pertaining to a specific gadget kind will not
* always be ignored, so you will need to be careful that you only
* try to change attributes that are valid for the gadget's kind.
*
*****************************************************************************
*
* Have you read the license info? It tells you that you must send your
* modifications of GadLayout to me, and that you may not make GadLayout
* into a shared library.
*
*/
VOID GL_SetGadgetAttrs(struct PrivateInfo *pi, struct Gadget *gad, struct Window *win, struct Requester *req,
Tag *firsttag, ...)
{
return( GL_SetGadgetAttrsA(pi, gad, win, req, &firsttag) );
}
VOID GL_SetGadgetAttrsA(struct PrivateInfo *pi, struct Gadget *gad,
struct Window *win, struct Requester *req,
struct TagItem *taglist)
{
struct TagItem *tag;
if (tag = FindTagItem(GLIM_Image, taglist))
{
if ((gad->MutualExclude & GADLAYOUT_KIND) == GADLAYOUT_KIND)
{
struct Image *image = (struct Image *)gad->GadgetRender;
struct Image *new_image = (struct Image *)tag->ti_Data;
/* Remove the gadget while we work on it.
*/
RemoveGadget(win, gad);
/* Setup the new gadget imagery.
*/
gad->GadgetRender = create_gad_images(IMAGEBUTTON_KIND, gad->Width, gad->Height,
pi, new_image,
gad->MutualExclude & GLFLG_READONLY);
/* Re-add the gadget and refresh it.
*/
AddGadget(win, gad, ~0);
RefreshGList(gad, win, req, 1);
}
}
}
/****** gadlayout/GadgetArrayIndex ******************************************
*
* NAME
* GadgetArrayIndex -- Get a gadget's index in the LayoutGadget array.
*
* SYNOPSIS
* i = GadgetArrayIndex(gad_id, gadgets)
* WORD GadgetArrayIndex(WORD, struct LayoutGadget *)
*
* FUNCTION
* Given a gadget ID, returns the index of that gadget's definition
* in the LayoutGadget array. For example, in cases where you need
* to know a gadget's Gadget structure (eg. if you wanted to use
* the Intuition function ActivateGadget() to make a string or an
* integer gadget active), you would need to lookup the lg_Gadget
* field in the LayoutGadget array. You MUST NOT GIVE THE ARRAY
* INDEX YOURSELF, THIS IS NOT GUARUNTEED TO REMAIN VALID! Instead,
* pass the id of the gadget that you want and this function will
* return the array index for you.
*
* INPUTS
* gad_id - The ID of the gadget you want to find.
* gadgets - The LayoutGadget array that this gadget is defined in.
*
* RESULT
* i - The index into the LayoutGadget array of the entry of the
* gadget ID you asked for.
*
*****************************************************************************
*
* Have you read the license info? It tells you that you must send your
* modifications of GadLayout to me, and that you may not make GadLayout
* into a shared library.
*
*/
WORD GadgetArrayIndex(WORD gad_id, struct LayoutGadget *gadgets)
{
WORD i=0;
while ( (gadgets[i].lg_GadgetID != gad_id) && (gadgets[i].lg_GadgetID != -1) )
i++;
return(i);
}
/****** gadlayout/FreeLayoutGadgets *****************************************
*
* NAME
* FreeLayoutGadgets -- Frees gadgets laid out with LayoutGadgets().
*
* SYNOPSIS
* FreeLayoutGadgets(gad_info);
* VOID FreeLayoutGadgets(APTR);
*
* FUNCTION
* Frees all resources used in creating and laying out gadgets with
* LayoutGadgets(). This frees all gadgets as well as other
* resources used. Generally this will be called after a call to
* CloseWindow() in Intuition.
*
* INPUTS
* gad_info - The pointer returned by LayoutGadgets().
*
* SEE ALSO
* LayoutGadgetsA()
*
*****************************************************************************
*
* PrivateInfo is a private data-type, and therefore this function is
* documented as taking APTR.
*
* Have you read the license info? It tells you that you must send your
* modifications of GadLayout to me, and that you may not make GadLayout
* into a shared library.
*
*/
VOID FreeLayoutGadgets(struct PrivateInfo *pi)
{
struct Gadget *g;
if (pi)
{
g = pi->pi_GadList;
/* while (g)
{
if ((g->MutualExclude & GADLAYOUT_KIND) == GADLAYOUT_KIND)
{
struct Image *image = (struct Image *)g->GadgetRender;
WORD i;
for(i = 0 ; i < 2 ; i++)
FreeVec(image[i].ImageData);
FreeVec(image);
}
g = g->NextGadget;
} */
FreeRemember(&(pi->pi_Remember), TRUE);
if (pi->pi_VisualInfo)
FreeVisualInfo(pi->pi_VisualInfo);
if (pi->pi_DrawInfo)
FreeScreenDrawInfo(pi->pi_Screen, pi->pi_DrawInfo);
if (pi->pi_GadList)
FreeGadgets(pi->pi_GadList);
FreeVec(pi);
}
}
/* Local routine that handles the layout tag list. Each tag is evaluated
* and the NewGadget structure for the gadget is setup.
*/
VOID evaluate_gadget(struct PrivateInfo *pi, WORD gad_num, struct LayoutGadget *gadgets,
struct NewGadget *ng, struct LaidOutGadget *gad_array)
{
struct TagItem *tag=NULL, *tstate;
struct NewGadget temp_ng;
ULONG gad_kind=BUTTON_KIND;
LONG textwidth;
WORD found_num=0;
BOOL extended_kind=FALSE;
/* If we are already evaluating this gadgeting, then we won't risk a
* recursive state by trying to do it again.
*/
if (gad_array[gad_num].log_IsEvaluated)
return;
gad_array[gad_num].log_IsEvaluated = TRUE;
ng->ng_GadgetID = gadgets[gad_num].lg_GadgetID;
/* Look at each tag item sequentially.
*/
tstate = gadgets[gad_num].lg_LayoutTags;
while (tag = NextTagItem(&tstate))
{
switch (tag->ti_Tag)
{
case GL_GadgetKind:
/* Use a GadTools gadget, ti_Data indicates which kind (from
* libraries/gadtools.h).
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_GadgetKind Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID ,tag->ti_Data);
#endif
gad_kind = tag->ti_Data;
switch (tag->ti_Data)
{
case IMAGEBUTTON_KIND:
case BORDERBUTTON_KIND:
case DRAWER_KIND:
case FILE_KIND:
extended_kind = TRUE;
break;
default:
extended_kind = FALSE;
break;
}
break;
case GL_GadgetText:
/* Gadget label.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_GadgetText Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID ,tag->ti_Data);
#endif
ng->ng_GadgetText = (STRPTR)tag->ti_Data;
break;
case GL_LocaleText:
/* Gadget label.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_LocaleText Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID ,tag->ti_Data);
#endif
ng->ng_GadgetText = get_locale_string(pi->pi_Catalog, pi->pi_AppStrings, tag->ti_Data);
break;
case GL_TextAttr:
/* Desired font for gadget label.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_TextAttr Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
ng->ng_TextAttr = (struct TextAttr *)tag->ti_Data;
break;
case GL_Flags:
/* Gadget flags.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_Flags Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
ng->ng_Flags = tag->ti_Data;
break;
case GL_UserData:
/* Gadget UserData.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_UserData Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
ng->ng_UserData = (APTR)tag->ti_Data;
break;
case GL_Width:
/* Absolute gadget width.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_Width Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
ng->ng_Width = tag->ti_Data;
break;
case GL_AutoWidth:
/* Set width according to length of text label + (LONG)ti_Data.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_AutoWidth Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
textwidth = text_width(ng->ng_GadgetText, ng->ng_TextAttr);
ng->ng_Width = textwidth + (LONG)tag->ti_Data;
break;
case GL_Columns:
/* Set width according to approximately fit ti_Data columns.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_Columns Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
{
char tempstr[2] = "X";
textwidth = text_width(tempstr, ng->ng_TextAttr) * (WORD)tag->ti_Data;
ng->ng_Width = textwidth;
}
break;
case GL_MinWidth:
/* Make sure the width is at least a certain value.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_MinWidth Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
if (ng->ng_Width < (LONG)tag->ti_Data)
ng->ng_Width = (LONG)tag->ti_Data;
break;
case GL_MaxWidth:
/* Make sure the width is at most a certain value.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_MaxWidth Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
if (ng->ng_Width > (LONG)tag->ti_Data)
ng->ng_Width = (LONG)tag->ti_Data;
break;
case GL_Height:
/* Absolute gadget height.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_Height Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
ng->ng_Height = tag->ti_Data;
break;
case GL_HeightFactor:
/* Make height a multiple of the font height.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_HeightFactor Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
ng->ng_Height = tag->ti_Data * ng->ng_TextAttr->ta_YSize;
break;
case GL_AutoHeight:
/* Set height according to height of text font + (LONG)ti_Data.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_AutoHeight Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
ng->ng_Height = ng->ng_TextAttr->ta_YSize + 2 + (LONG)tag->ti_Data;
break;
case GL_AddHeight:
/* Add some value to the total height calculation.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_AddHeight Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
ng->ng_Height += (LONG)tag->ti_Data;
break;
case GL_MinHeight:
/* Make sure the height is at least a certain value.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_MinHeight Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
if (ng->ng_Height < (LONG)tag->ti_Data)
ng->ng_Height = (LONG)tag->ti_Data;
break;
case GL_MaxHeight:
/* Make sure the height is at most a certain value.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_MaxHeight Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
if (ng->ng_Height > (LONG)tag->ti_Data)
ng->ng_Height = (LONG)tag->ti_Data;
break;
case GL_Top:
/* Absolute top edge.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_Top Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
ng->ng_TopEdge = tag->ti_Data;
break;
case GL_Bottom:
/* Absolute bottom edge.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_Bottom Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
ng->ng_TopEdge = tag->ti_Data - ng->ng_Height;
break;
case GL_Left:
/* Absolute left edge.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_Left Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
ng->ng_LeftEdge = tag->ti_Data;
break;
case GL_Right:
/* Absolute right edge.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_Right Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
ng->ng_LeftEdge = tag->ti_Data - ng->ng_Width;
break;
case GL_DupeWidth:
/* Duplicate the width of another gadget.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_DupeWidth Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
found_num = GadgetArrayIndex(tag->ti_Data, gadgets);
gad_array[gad_num].log_GadgetKind = gad_kind;
CopyMem(ng, &(gad_array[gad_num].log_NewGadget),
sizeof(struct NewGadget));
CopyMem(ng, &temp_ng, sizeof(struct NewGadget));
evaluate_gadget(pi, found_num, gadgets, &temp_ng, gad_array);
ng->ng_Width = gad_array[found_num].log_NewGadget.ng_Width;
break;
case GL_AddWidth:
/* Add some value to the total width calculation.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_AddWidth Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
ng->ng_Width += (LONG)tag->ti_Data;
break;
case GL_LeftRel:
/* Left edge relative to right edge of previous gadget.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_LeftRel Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
found_num = GadgetArrayIndex(tag->ti_Data, gadgets);
gad_array[gad_num].log_GadgetKind = gad_kind;
CopyMem(ng, &(gad_array[gad_num].log_NewGadget),
sizeof(struct NewGadget));
CopyMem(ng, &temp_ng, sizeof(struct NewGadget));
evaluate_gadget(pi, found_num, gadgets, &temp_ng, gad_array);
ng->ng_LeftEdge = gad_array[found_num].log_NewGadget.ng_LeftEdge + gad_array[tag->ti_Data].log_NewGadget.ng_Width;
break;
case GL_AlignLeft:
/* Align left edge with the left edge of another gadget.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_AlignLeft Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
found_num = GadgetArrayIndex(tag->ti_Data, gadgets);
gad_array[gad_num].log_GadgetKind = gad_kind;
CopyMem(ng, &(gad_array[gad_num].log_NewGadget),
sizeof(struct NewGadget));
CopyMem(ng, &temp_ng, sizeof(struct NewGadget));
evaluate_gadget(pi, found_num, gadgets, &temp_ng, gad_array);
ng->ng_LeftEdge = gad_array[found_num].log_NewGadget.ng_LeftEdge;
break;
case GL_AdjustLeft:
/* ADD the width of the text label + ti_Data to the left edge.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_AdjustLeft Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
textwidth = text_width(ng->ng_GadgetText, ng->ng_TextAttr);
ng->ng_LeftEdge += textwidth + (LONG)tag->ti_Data;
break;
case GL_AddLeft:
/* Add some value to the final left edge calculation.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_AddLeft Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
ng->ng_LeftEdge += (LONG)tag->ti_Data;
break;
case GL_TopRel:
/* Top edge relative to bottom edge of another gadget.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_TopRel Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
found_num = GadgetArrayIndex(tag->ti_Data, gadgets);
gad_array[gad_num].log_GadgetKind = gad_kind;
CopyMem(ng, &(gad_array[gad_num].log_NewGadget),
sizeof(struct NewGadget));
CopyMem(ng, &temp_ng, sizeof(struct NewGadget));
evaluate_gadget(pi, found_num, gadgets, &temp_ng, gad_array);
ng->ng_TopEdge = gad_array[found_num].log_NewGadget.ng_TopEdge
+ gad_array[found_num].log_NewGadget.ng_Height;
break;
case GL_BottomRel:
/* Bottom edge relative to top edge of another gadget.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_BottomRel Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
found_num = GadgetArrayIndex(tag->ti_Data, gadgets);
gad_array[gad_num].log_GadgetKind = gad_kind;
CopyMem(ng, &(gad_array[gad_num].log_NewGadget),
sizeof(struct NewGadget));
CopyMem(ng, &temp_ng, sizeof(struct NewGadget));
evaluate_gadget(pi, found_num, gadgets, &temp_ng, gad_array);
ng->ng_TopEdge = gad_array[found_num].log_NewGadget.ng_TopEdge - ng->ng_Height;
break;
case GL_AdjustTop:
/* ADD the height of the text font + ti_Data to the top edge.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_AdjustTop Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
ng->ng_TopEdge += ng->ng_TextAttr->ta_YSize + (LONG)tag->ti_Data;
break;
case GL_AddTop:
/* Add some value to the final top edge calculation.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_AddTop Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
ng->ng_TopEdge += (LONG)tag->ti_Data;
break;
case GL_AddBottom:
/* Add some value to the final bottom edge calculation.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_AddBottom Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
ng->ng_TopEdge += (LONG)tag->ti_Data;
break;
case GL_RightRel:
/* Right edge relative to left edge of another gadget.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_RightRel Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
found_num = GadgetArrayIndex(tag->ti_Data, gadgets);
gad_array[gad_num].log_GadgetKind = gad_kind;
CopyMem(ng, &(gad_array[gad_num].log_NewGadget),
sizeof(struct NewGadget));
CopyMem(ng, &temp_ng, sizeof(struct NewGadget));
evaluate_gadget(pi, found_num, gadgets, &temp_ng, gad_array);
ng->ng_LeftEdge = gad_array[found_num].log_NewGadget.ng_LeftEdge
- ng->ng_Width;
break;
case GL_AlignRight:
/* Align right edge with the right edge of another gadget.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_AlignRight Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
found_num = GadgetArrayIndex(tag->ti_Data, gadgets);
gad_array[gad_num].log_GadgetKind = gad_kind;
CopyMem(ng, &(gad_array[gad_num].log_NewGadget),
sizeof(struct NewGadget));
CopyMem(ng, &temp_ng, sizeof(struct NewGadget));
evaluate_gadget(pi, found_num, gadgets, &temp_ng, gad_array);
ng->ng_LeftEdge = gad_array[found_num].log_NewGadget.ng_LeftEdge
+ gad_array[found_num].log_NewGadget.ng_Width
- ng->ng_Width;
break;
case GL_AddRight:
/* Add some value to the final right edge calculation.
*/
#ifdef GL_DEBUG
Printf("Gadget: %ld Tag: GL_AddRight Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
#endif
ng->ng_LeftEdge += (LONG)tag->ti_Data;
break;
default:
break;
}
}
/* Now copy everything we know into the NewGadget structure.
*/
gad_array[gad_num].log_GadgetKind = gad_kind;
CopyMem(ng, &(gad_array[gad_num].log_NewGadget), sizeof(struct NewGadget));
}
/* Local routine to determine how many pixels wide a string will be with a
* given font.
*/
LONG text_width(char *str, struct TextAttr *font)
{
struct IntuiText itext;
itext.IText=str;
itext.ITextFont=font;
itext.FrontPen=1;
itext.BackPen=0;
itext.DrawMode=JAM1;
itext.LeftEdge=0;
itext.TopEdge=0;
itext.NextText=NULL;
return(IntuiTextLength(&itext));
}
/* Local routine to get a localized text string, given its ID.
*/
STRPTR get_locale_string(struct Catalog *catalog, struct AppString *appstrings,
LONG id)
{
UWORD i=0;
STRPTR local = NULL;
if (appstrings)
{
while (!local)
{
if (appstrings[i].as_ID == id)
local = appstrings[i].as_Str;
i++;
}
if (LocaleBase)
return(GetCatalogStr(catalog, id, local));
}
return(local);
}
/* Locale function to create one of GadLayout's extended gadgets.
*/
struct Gadget * create_layout_gad(struct PrivateInfo *pi, WORD gad_kind,
struct Gadget *last_gad, struct NewGadget *ng,
struct TagItem *taglist)
{
struct Gadget *gad=NULL, *textgad=NULL;
struct TagItem *tag;
struct Image *image, *temp_image;
struct NewGadget textng;
BOOL readonly=FALSE;
switch (gad_kind)
{
case IMAGEBUTTON_KIND:
case FILE_KIND:
case DRAWER_KIND:
if (gad_kind == IMAGEBUTTON_KIND)
{
if (tag = FindTagItem(GLIM_Image, taglist))
temp_image = (struct Image *)tag->ti_Data;
if (tag = FindTagItem(GLIM_ReadOnly, taglist))
readonly = tag->ti_Data;
}
else if (gad_kind == DRAWER_KIND)
temp_image = &drawer_image;
else if (gad_kind == FILE_KIND)
temp_image = &file_image;
/* Since GENERIC_KIND gadgets don't full support the ng_GadgetText
* field, we'll get around this by creating a TEXT_KIND gadget
* that displays the text for us.
*/
CopyMem(ng, &textng, sizeof(struct NewGadget));
textng.ng_GadgetID = 1000;
switch (textng.ng_Flags)
{
case PLACETEXT_LEFT:
textng.ng_Width = 0;
break;
case PLACETEXT_RIGHT:
textng.ng_LeftEdge += textng.ng_Width;
textng.ng_Width = 0;
break;
case PLACETEXT_ABOVE:
textng.ng_Height = 0;
break;
case PLACETEXT_BELOW:
textng.ng_LeftEdge += textng.ng_Height;
textng.ng_Height = 0;
break;
default:
break;
}
textgad = last_gad = CreateGadget(TEXT_KIND, last_gad, &textng,
GT_Underscore, '_',
TAG_DONE);
ng->ng_GadgetText = NULL;
/* Create the image structure, then make the gadget.
*/
if (image = create_gad_images(gad_kind, ng->ng_Width, ng->ng_Height,
pi, temp_image, readonly))
{
if (gad = last_gad = CreateGadget(GENERIC_KIND, last_gad, ng,
TAG_DONE))
{
gad->GadgetType |= GTYP_BOOLGADGET;
gad->GadgetRender = &image[0];
gad->SelectRender = &image[1];
gad->Flags |= GFLG_GADGIMAGE | ((readonly)? GFLG_GADGHNONE : GFLG_GADGHIMAGE);
gad->Activation |= GACT_RELVERIFY;
gad->MutualExclude = GADLAYOUT_KIND | ((readonly)? GLFLG_READONLY : 0);
}
}
ng->ng_GadgetText = textng.ng_GadgetText;
break;
default:
break;
}
return(gad);
}
/* Local routine to return image structures for IMAGEBUTTON_KIND, DRAWER_KIND and
* FILE_KIND gadgets.
*/
struct Image * create_gad_images(WORD gad_kind, UWORD width, UWORD height,
struct PrivateInfo *pi, struct Image *image,
BOOL readonly)
{
struct Image *new_image = NULL;
struct Remember *image_rem = NULL;
UWORD image_width = 8, image_height = 8;
/* Minimum size required.
*/
if (image)
{
image_width = image->Width;
image_height = image->Height;
}
if ((width >= image_width + 4) && (height >= image_height + 2))
{
struct RastPort *rport;
/* Allocate local dummy rastport.
*/
if (rport = (struct RastPort *)AllocRemember(&image_rem, sizeof(struct RastPort), MEMF_ANY))
{
struct BitMap *bitmap[2] = { NULL, NULL };
struct Layer_Info *layer_info[2] = { NULL, NULL };
struct Layer *layer[2] = { NULL, NULL };
BYTE success = FALSE;
WORD depth, i,j;
/* Determine screen depth.
*/
depth = pi->pi_Screen->RastPort.BitMap->Depth;
/* Set up rastport.
*/
InitRastPort(rport);
/* Allocate bitmaps and bitplane data.
*/
success = TRUE;
for (i = 0 ; success && i < 2 ; i++)
{
if (bitmap[i] = (struct BitMap *)AllocRemember(&image_rem, sizeof(struct BitMap), MEMF_ANY))
{
InitBitMap(bitmap[i], depth, width, height);
if (bitmap[i]->Planes[0] = (PLANEPTR)AllocRemember(&(pi->pi_Remember), bitmap[i]->BytesPerRow * bitmap[i]->Rows * bitmap[i]->Depth, MEMF_CHIP | MEMF_CLEAR))
{
for (j = 1 ; j < depth ; j++)
bitmap[i]->Planes[j] = bitmap[i]->Planes[j - 1] + bitmap[i]->BytesPerRow * bitmap[i]->Rows;
}
else
success = FALSE;
}
else
success = FALSE;
}
/* Did we get what we wanted?
*/
if (success)
{
__aligned struct BitMap temp_bitmap;
WORD left, top;
/* Centre the image.
*/
left = (width - image_width) / 2;
top = (height - image_height) / 2;
/* Set up the drawer bitmap.
*/
InitBitMap(&temp_bitmap, depth, image_width, image_height);
/* Put the mask into all bitplanes.
*/
if (image)
for (i = 0 ; i < depth ; i++)
temp_bitmap.Planes[i] = (PLANEPTR)image->ImageData;
/* Manipulate the first bitmap.
*/
rport->BitMap = bitmap[0];
/* Clear the bitmap.
*/
SetRast(rport, pi->pi_DrawInfo->dri_Pens[BACKGROUNDPEN]);
/* Draw the button box.
*/
DrawBevelBox(rport, 0, 0, width, height,
((readonly)? GTBB_Recessed : TAG_IGNORE), TRUE,
GT_VisualInfo, pi->pi_VisualInfo,
TAG_DONE);
if ((gad_kind == DRAWER_KIND) || (gad_kind == FILE_KIND))
{
UBYTE minterm, mask;
/* Clear the drawer mask.
*/
minterm = 0x20;
mask = (1 << depth) - 1;
BltBitMap(&temp_bitmap, 0, 0,
bitmap[0], left, top,
image_width, image_height,
minterm, mask, NULL);
minterm = 0xe0;
mask = pi->pi_DrawInfo->dri_Pens[TEXTPEN];
BltBitMap(&temp_bitmap, 0, 0,
bitmap[0], left, top,
image_width, image_height,
minterm, mask, NULL);
}
else if (gad_kind == IMAGEBUTTON_KIND)
{
if (image)
DrawImage(rport, image, left, top);
}
/* Manipulate the second bitmap.
*/
rport->BitMap = bitmap[1];
/* Set the bitmap to the selected button colour.
*/
SetRast(rport, pi->pi_DrawInfo->dri_Pens[FILLPEN]);
/* Create the selected imagery if needed.
*/
if ((pi->pi_DrawInfo->dri_Flags & DRIF_NEWLOOK) && depth > 1)
{
/* Draw the selected button box.
*/
DrawBevelBox(rport, 0, 0, width, height,
((!readonly)? GTBB_Recessed : TAG_IGNORE), TRUE,
GT_VisualInfo, pi->pi_VisualInfo,
TAG_DONE);
if ((gad_kind == DRAWER_KIND) || (gad_kind == FILE_KIND))
{
/* Clear the drawer mask.
*/
BltBitMap(&temp_bitmap, 0, 0,
bitmap[1], left, top,
image_width, image_height,
0x20, (1 << depth) - 1, NULL);
/* Draw the drawer mask.
*/
BltBitMap(&temp_bitmap, 0, 0,
bitmap[1], left, top,
image_width, image_height,
0xe0, pi->pi_DrawInfo->dri_Pens[FILLTEXTPEN], NULL);
}
else if (gad_kind == IMAGEBUTTON_KIND)
{
if (image)
DrawImage(rport, image, left, top);
}
}
/* Otherwise, just regular inverted imagery,
*/
else
{
/* Copy the image.
*/
BltBitMap(bitmap[0], 0, 0,
bitmap[1], 0, 0,
width, height,
0xc0, (1 << depth) - 1, NULL);
/* Invert the inner area.
*/
BltBitMap(bitmap[0], 0, 0,
bitmap[1], 2, 1,
width - 4, height - 2,
0x50, (1 << depth) - 1, NULL);
}
/* Allocate space for standard image and selected image.
*/
if (new_image = (struct Image *)AllocRemember(&(pi->pi_Remember), 2 * sizeof(struct Image), MEMF_CHIP | MEMF_CLEAR))
{
/* Fill in the standard data.
*/
for (i = 0 ; i <= 1 ; i++)
{
new_image[i].Width = width;
new_image[i].Height = height;
new_image[i].Depth = depth;
new_image[i].ImageData = (UWORD *)bitmap[i]->Planes[0];
new_image[i].PlanePick = (1 << depth) - 1;
}
}
/* for (i = 0; i < 2; i++)
FreeVec(bitmap[i]->Planes[0]); */
}
}
}
/* Free all memory.
*/
FreeRemember(&image_rem, TRUE);
return(new_image);
}