Copyright (c) 2012-2016 Hyperion Entertainment and contributors.

Intuition Gadgets

From AmigaOS Documentation Wiki
Jump to: navigation, search

Intuition Gadgets

This article describes the multi-purpose software controls called gadgets. Gadgets are software controls symbolized by an image that the user can operate with the mouse or keyboard. They are the Amiga's equivalent of buttons, knobs and dials.

Much of the user's input to an application takes place through gadgets in the application's windows and requesters. Gadgets are also used by Intuition itself for handling screen and window movement and depth arrangement, as well as window sizing and closing.

Intuition maintains gadget imagery, watches for activation and deactivation and performs other management required by the gadget. The application can choose its level of involvement from simply receiving gadget activation messages to processing the actual mouse button presses and movements. To make gadget programming even easier the Amiga operating system includes the GadTools library.

About Gadgets

There are two kinds of gadgets: system gadgets and application gadgets. System gadgets are set up by Intuition to handle the positioning and depth arranging of screens, and to handle the positioning, sizing, closing and depth arranging of windows. System gadgets always use the same imagery and location giving the windows and screens of any application a basic set of controls that are familiar and easy to operate. In general, applications do not have to do any processing for system gadgets; Intuition does all the work.

Application gadgets are set up by an application program. These may be the basic gadget types described in this article, the pre-fabricated gadgets supplied by the GadTools library, or special gadget types defined through Intuition's custom gadget and BOOPSI facilities. Application gadgets can be placed anywhere within a window and can use just about any image. The action associated with an application gadget is carried out by the application.

There are four basic types of application gadgets:

  • Boolean (or button) gadgets elicit true/false or yes/no kinds of answers from the user.
  • Proportional gadgets allow the user to select from a continuous range of options, such as volume or speed.
  • String gadgets are used to get or display character based information (a special class of string gadget allows entry of numeric data.)
  • Custom gadgets, a new, generalized form of gadget, provide flexibility to perform any type of function.

The way a gadget is used varies according to the type of gadget. For a boolean gadget, the user operates the gadget by simply clicking the mouse select button. For a string gadget, a cursor appears, allowing the user to enter data from the keyboard. For a proportional gadget, the user can either drag the knob with the mouse or click in the gadget container to move the knob by a set increment.

Gadgets are chosen by positioning the pointer within an area called the select box, which is application defined, and pressing the mouse select button (left mouse button).

When a gadget is selected, its imagery is changed to indicate that it is activated. The highlighting method for the gadget may be set by the application. Highlighting methods include alternate image, alternate border, a box around the gadget and color complementing.

A gadget can be either enabled or disabled. Disabled gadgets cannot be operated and are indicated by ghosting the gadget, that is, overlaying its image with a pattern of dots. Gadgets may also be directly modified and redrawn by first removing the gadget from the system.

System and Application Gadgets

System Gadgets

System gadgets are predefined gadgets provided by Intuition to support standard operations of windows and screens. System gadgets have a standard image and location in the borders of screens or windows. Intuition manages the operation of all system gadgets except the close gadget.

The drag and depth gadgets are automatically attached to each screen in the system. The application cannot control the creation of these gadgets, but can control their display and operation. Screens may be opened "quiet" without any of the gadget imagery displayed. Applications should avoid covering the screen's gadgets with windows as this may prevent the user from freely positioning the screen. See Intuition Screens for more information on the positioning and use of system gadgets for screens.

The drag, depth, close, sizing and zoom gadgets are available to be attached to each window. These gadgets are not provided automatically, the application must specify which gadgets it requires. See Intuition Windows for more information on the positioning and use of system gadgets for windows.

Application Gadgets

Application gadgets imitate real life controls: they are the switches, knobs, handles and buttons of the Intuition environment. Gadgets can be created with almost any imaginable type of imagery and function. Visual imagery for gadgets can combine text with hand drawn imagery or lines of multiple colors.

A gadget is created by declaring and initializing a Gadget structure as defined in <intuition/intuition.h>. See Gadget Structure later in this article for more details.

Gadgets always appear in a window or requester. All windows and requesters keep a list of the gadgets they contain. Gadgets can be added when the window or requester is opened, or they can be added or removed from the window or requester after it is open.

As with other types of input events, Intuition notifies your application about gadget activity by sending a message to your window's I/O channels: the IDCMP (Window.UserPort) or the console device. The message is sent as an Intuition IntuiMessage structure. The Class field of this structure is set to IDCMP_GADGETDOWN or IDCMP_GADGETUP with the IAddress field set to the address of the Gadget that was activated. (See Intuition Input and Output Methods for details.)

Application gadgets can go anywhere in windows or requesters, including in the borders, and can be any size or shape. When application gadgets are placed into the window's border at the time the window is opened, Intuition will adjust the border size accordingly. Application gadgets are not supported in screens (although this may be simulated by placing the gadget in a backdrop window).

Gadget size can be fixed, or can change relative to the window size. Gadget position can be set relative to either the top or bottom border, and either the left or right border of the window, allowing the gadget to move with a border as the window is sized.

This flexibility provides the application designer the freedom to create gadgets that mimic real devices, such as light switches or joysticks, as well as the freedom to create controls that satisfy the unique needs of the application.

A Simple Gadget Example

The example below demonstrates a simple application gadget. The program declares a Gadget structure set up as a boolean gadget with complement mode highlighting. The gadget is attached to the window when it is opened by using the WA_Gadgets tag in the OpenWindowTags() call.

/*
** simplegad.c - show the use of a button gadget.
*/
 
#define INTUI_V36_NAMES_ONLY
 
#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
 
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
 
struct IntuitionIFace *IIntuition;
 
#define BUTTON_GAD_NUM   (3)
#define MYBUTTONGADWIDTH (100)
#define MYBUTTONGADHEIGHT (50)
 
/* NOTE that the use of constant size and positioning values are
** not recommended; it just makes it easy to show what is going on.
** The position of the gadget should be dynamically adjusted depending
** on the height of the font in the title bar of the window.
*/
 
uint16 buttonBorderData[] =
    {
    0,0, MYBUTTONGADWIDTH + 1,0, MYBUTTONGADWIDTH + 1,MYBUTTONGADHEIGHT + 1,
    0,MYBUTTONGADHEIGHT + 1, 0,0,
    };
 
struct Border buttonBorder =
    {
    -1,-1,1,0,JAM1,5,buttonBorderData,NULL,
    };
 
struct Gadget buttonGad =
    {
    NULL, 20,20, MYBUTTONGADWIDTH,MYBUTTONGADHEIGHT,
    GFLG_GADGHCOMP, GACT_RELVERIFY | GACT_IMMEDIATE,
    GTYP_BOOLGADGET, &buttonBorder, NULL, NULL,0,NULL,BUTTON_GAD_NUM,NULL,
    };
 
/*
** routine to show the use of a button (boolean) gadget.
*/
int main()
{
    struct Library *IntuitionBase = IExec->OpenLibrary("intuition.library", 50);
    IIntuition = (struct IntuitionIFace*)IExec->GetInterface(IntuitionBase, "main", 1, NULL);
 
    if (IIntuitionBase != NULL)
    {
        struct Window *win = IIntuition->OpenWindowTags(NULL,
                            WA_Width, 400,
                            WA_Height, 100,
                            WA_Gadgets, &buttonGad,
                            WA_Activate, TRUE,
                            WA_CloseGadget, TRUE,
                            WA_IDCMP, IDCMP_GADGETDOWN | IDCMP_GADGETUP |
                                      IDCMP_CLOSEWINDOW,
                            TAG_END);
        if (win != NULL)
        {
            BOOL done = FALSE;
            while (done == FALSE)
            {
                IExec->Wait(1L << win->UserPort->mp_SigBit);
 
                struct IntuiMessage *msg;
                while ( (done == FALSE) &&
                    (msg = (struct IntuiMessage *)IExec->GetMsg(win->UserPort)))
                {
                    /* Stash message contents and reply, important when message
                    ** triggers some lengthy processing
                    */
                    uint32 class = msg->Class;
 
                    /* gadget address is ONLY valid for gadget messages! */
                    struct Gadget *gad = NULL;
                    if ((class == IDCMP_GADGETUP) || (class == IDCMP_GADGETDOWN))
                        gad = (struct Gadget *)(msg->IAddress);
 
                    IExec->ReplyMsg((struct Message *)msg);
 
                    /* switch on the type of the event */
                    switch (class)
                    {
                    case IDCMP_GADGETUP:
                        /* caused by GACT_RELVERIFY */
                        IDOS->Printf("received an IDCMP_GADGETUP, gadget number %ld\n",
                               gad->GadgetID);
                        break;
                    case IDCMP_GADGETDOWN:
                        /* caused by GACT_IMMEDIATE */
                        IDOS->Printf("received an IDCMP_GADGETDOWN, gadget number %ld\n",
                               gad->GadgetID);
                        break;
                    case IDCMP_CLOSEWINDOW:
                        /* set a flag that we are done processing events... */
                        IDOS->Printf("received an IDCMP_CLOSEWINDOW\n");
                        done = TRUE;
                        break;
                    }
                }
            }
 
            IIntuition->CloseWindow(win);
        }
    }
 
    IExec->DropInterface((struct Interface*)IIntuition);
    IExec->CloseLibrary(IntuitionBase);
 
    return 0;
}

Adding and Removing Gadgets

Gadgets may be added to a window or requester when the window or requester is opened, or they may be added later. To add the gadgets when a window is opened, use the WA_Gadgets tag with the OpenWindowTagList() call. This technique is demonstrated in the example above. For a requester, set the ReqGadget field in the Requester structure to point to the first gadget in the list.

To add or remove gadgets in a window or requester that is already open, use AddGList() or RemoveGList(). These functions operate on gadgets arranged in a list. A gadget list is linked together by the NextGadget field of the Gadget structure (see the description of the Gadget Structure).

AddGList() adds a gadget list that you specify to the existing gadget list of a window or requester:

UWORD AddGList( struct Window *window, struct Gadget *agadget,
                ULONG position, LONG numGad, struct Requester *requester );

Up to numGad gadgets will be added from the gadget list you specify beginning with a gadget. The position argument determines where your gadgets will be placed in the existing list of gadgets for the window or requester. Use (~0) to add your gadget list to the end of the window or requester's gadget list. This function returns the actual position where your gadgets are added in the existing list.

To remove gadgets from a window or requester use RemoveGList():

UWORD RemoveGList( struct Window *remPtr, struct Gadget *agadget, LONG numGad );

This function removes up to numGad gadgets from a window or requester, beginning with the specified one. If one of the gadgets that is being removed is the active gadget, this routine will wait for the user to release the mouse button before deactivating and removing the gadget. This function returns the former position of the removed gadget or -1 if the specified gadget was not found.

The Gadget structure should never be directly modified after it has been added to a window or requester. To modify a gadget, first remove it with RemoveGList(), modify the structure as needed, and then add the gadget back to the system with AddGList(). Finally, refresh the gadget imagery with RefreshGList(). (See Gadget Refreshing for more information.)

Some attributes of a gadget may be modified through special Intuition functions that perform the modification. When using such functions it is not necessary to remove, add or refresh the gadget. These functions, such as NewModifyProp(), OnGadget() and OffGadget(), are described later in this article.

Gadget Imagery

Gadget imagery can be rendered with a series of straight lines, a bitmap image or no imagery at all. In addition to the line or bitmap imagery, gadgets may include a series of text strings.

Hand drawn Gadgets

Bitmap or custom images are used as imagery for a gadget by setting the GFLG_GADGIMAGE flag in the Flags field of the Gadget structure. An Image structure must be set up to manage the bitmap data. The address of the Image structure is placed into the gadget's GadgetRender field. The bitmap image will be positioned relative to the gadget's select box. For more information about creating Intuition images, see Intuition Images, Line Drawing, and Text. For a listing of the Gadget structure and all its flags see the Gadget Structure section.

Line drawn Gadgets

Gadget imagery can also be created by specifying a series of lines to be drawn. These lines can go around or through the select box of the gadget, and can be drawn using any color pen and draw mode. Multiple groups of lines may be specified, each with its own pen and draw mode.

The Border structure is used to describe the lines to be drawn. The Border structure is incorporated into the gadget by clearing the GFLG_GADGIMAGE flag in the gadget's Flags field. The address of the Border structure is placed into the gadget's GadgetRender field. The border imagery will be positioned relative to the gadget's select box. For more information about creating a Border structure, see Intuition Images, Line Drawing, and Text.

Gadget Text

Gadgets may include text information in the form of a linked list of IntuiText structures. A pointer to the first IntuiText structure in the list is placed in the Gadget structure's GadgetText field. The text is positioned relative to the top left corner of the gadget’s select box. For more information on IntuiText, see Intuition Images, Line Drawing, and Text.

Gadgets without Imagery

Gadgets can be created without any defining imagery. This type of gadget may be used where mouse information is required but graphical definition of the gadget is not, or where the existing graphics sufficiently define the gadget that no additional imagery is required. A gadget with no imagery may be created by clearing the GFLG_GADGIMAGE flag in the gadget's Flags field, and by setting the gadget's GadgetRender and GadgetText fields to NULL.

The text display of a word processor is a case where mouse information is required without any additional graphics. If a large gadget is placed over the text display, gadget and mouse event messages may be received at the IDCMP (Window.UserPort) when the mouse select button is either pressed or released. The mouse information is used to position the pointer in the text, or to allow the user to mark blocks of text. The drag bar of a window is another example of a gadget where existing imagery defines the gadget such that additional graphics are not required.

Gadget Selection

The user operates a gadget by pressing the select button while the mouse pointer is within the gadget's select box. Intuition provides two ways of notifying your program about the user operating a gadget. If your application needs immediate notification when the gadget is chosen, set the GACT_IMMEDIATE flag in the gadget's Activation field. Intuition will send an IDCMP_GADGETDOWN message to the window's UserPort when it detects the mouse select button being pressed on the gadget.

If the application needs notification when the gadget is released, i.e., when the user releases the mouse select button, set the GACT_RELVERIFY (for "release verify") flag in the gadget's Activation field. For boolean gadgets, Intuition will send an IDCMP_GADGETUP message to the window's UserPort when the mouse select button is released over a GACT_RELVERIFY gadget. The program will only receive the IDCMP_GADGETUP message if the user still has the pointer positioned over the select box of the gadget when the mouse select button is released.

If the user moves the mouse out of the gadget's select box before releasing the mouse button an IDCMP_MOUSEBUTTONS event will be sent with a code of SELECTUP. This indicates the user’s desire to not proceed with the action. Boolean gadgets that are GACT_RELVERIFY allow the user a chance to cancel a selection by rolling the mouse off of the gadget before releasing the select button.

String gadgets have a slightly different behavior, in that they remain active after the mouse button has been released. The gadget remains active until Return or Enter is pressed, the user tabs to the next or previous gadget, another window becomes active or the user chooses another object with the mouse. An IDCMP_GADGETUP message is only sent for GACT_RELVERIFY string gadgets if the user ends the gadget interaction through the Return, Enter or (if activated) one of the tab keys.

GACT_RELVERIFY proportional gadgets send IDCMP_GADGETUP events even if the mouse button is released when the pointer is not positioned over the select box of the gadget.

Gadgets can specify both the GACT_IMMEDIATE and GACT_RELVERIFY activation types, in which case, the program will receive both IDCMP_GADGETDOWN and IDCMP_GADGETUP messages.

Gadget Size and Position

The position and dimensions of the gadget's select box are defined in the Gadget structure. The LeftEdge, TopEdge, Width and Height values can be absolute numbers or values relative to the size of the window. When using absolute numbers, the values are set once, when the gadget is created. When using relative numbers, the size and position of the select box are adjusted dynamically every time the window size changes.

The gadget image is positioned relative to the select box so when the select box moves the whole gadget moves. The size of the gadget image, however, is not usually affected by changes in the select box size (proportional gadgets are the exception). To create a gadget image that changes size when the select box and window change size, you have to handle gadget rendering yourself or use a BOOPSI gadget.

Select Box Position

To specify relative position or size for the gadget’s select box, set or more of the flags GFLG_RELRIGHT, GFLG_RELBOTTOM, GFLG_RELWIDTH or GFLG_RELHEIGHT in the Flags field of the Gadget structure. When using GFLG_RELxxx flags, the gadget size or position is recomputed each time the window is sized.

Positioning the Select Box
With GFLG_RELxxx gadgets, all of the imagery must be contained within the gadget's select box. This allows Intuition to erase the gadget's imagery when the window is sized. Intuition must be able to erase the gadget's imagery since the gadget's position or size will change as the window size changes. If the old one were not removed, imagery from both sizes/positions would be visible.

If a GFLG_RELxxx gadget's imagery must extend outside of its select box, position another GFLG_RELxxx gadget with a larger select box such that all of the first gadget's imagery is within the second gadget's select box. This "shadow" gadget is only used to clear the first gadget's imagery and, as such, it should not have imagery nor should it generate any messages. It should also be positioned later in the gadget list than the first gadget so that its select box does not interfere with the first gadget.

The left-right position of the select box is defined by the variable LeftEdge, which is an offset from either the left or right edge of the display element. The offset method is determined by the GFLG_RELRIGHT flag. For the LeftEdge variable, positive values move toward the right and negative values move toward the left of the containing display element. If GFLG_RELRIGHT is cleared, LeftEdge is an offset (usually a positive value) from the left edge of the display element.

If GFLG_RELRIGHT is set, LeftEdge is an offset (usually a negative value) from the right edge of the display element. When this is set, the left-right position of the select box in the window is recomputed each time the window is sized. The gadget will automatically move with the left border as the window is sized.

The top-bottom position of the select box is defined by the variable TopEdge, which is an offset from either the top or bottom edge of the display element (window or requester). The offset method is determined by the GFLG_RELBOTTOM flag. For the TopEdge variable, positive values move toward the bottom and negative values move toward the top of the containing display element.

If GFLG_RELBOTTOM is cleared, TopEdge is an offset (usually a positive value) from the top of the display element. If GFLG_RELBOTTOM is set, TopEdge is an offset (usually a negative value) from the bottom of the display element. When this is set, the position of the select box is recomputed each time the window is sized. The gadget will automatically move with the bottom border as the window is sized.

Select Box Dimension

The height and width of the gadget select box can be absolute or they can be relative to the height and width of the display element in which the gadget resides.

Set the gadget's GFLG_RELWIDTH flag to make the gadget's width relative to the width of the window. When this flag is set, the Width value is added to the current window width to determine the width of the gadget select box. The Width value is usually negative in this case, making the width of the gadget smaller than the width of the window. If GFLG_RELWIDTH is not set, Width will specify the actual width of the select box.

The actual width of the box will be recomputed each time the window is sized. Setting GFLG_RELWIDTH and a gadget width of zero will create a gadget that is always as wide as the window, regardless of how the window is sized.

The GFLG_RELHEIGHT flag has the same effect on the height of the gadget select box. If the flag is set, the height of the select box will be relative to the height of the window, and the actual height will be recomputed each time the window is sized. If the flag is not set, the value will specify the actual height of the select box.

Here are a few examples of gadgets that take advantage of the special relativity modes of the select box. Consider the Intuition window sizing gadget. The LeftEdge and TopEdge of this gadget are both defined relative to the right and bottom edges of the window. No matter how the window is sized, the gadget always appears in the lower right corner.

For the window drag gadget, the LeftEdge and TopEdge are always absolute in relation to the top left corner of the window. Height of this gadget is always an absolute quantity. Width of the gadget, however, is defined to be zero. When Width is combined with the effect of the GFLG_RELWIDTH flag, the drag gadget is always as wide as the window.

For a program with several requesters, each of which has an "OK" gadget in the lower left corner and a "Cancel" gadget in the lower right corner, two gadgets may be designed that will appear in the correct position regardless of the size of the requester. Design the "OK" and "Cancel" gadgets such that they are relative to the lower left and lower right corners of the requester. Regardless of the size of the requesters, these gadgets will appear in the correct position relative to these corners. Note that these gadgets may only be used in one window or requester at a time.

Positioning Gadgets in Window Borders

Gadgets may be placed in the borders of a window. To do this, set one or more of the border flags in the Gadget structure and position the gadget in the window border. Setting these flags also tells Intuition to adjust the size of the window's borders to accommodate the gadget.

Borders are adjusted only when the window is opened. Although the application can add and remove gadgets with AddGList() and RemoveGList() after the window is opened, Intuition does not readjust the borders.

A gadget may be placed into two borders by setting multiple border flags. If a gadget is to be placed in two borders, it only makes sense to put the gadget into adjoining borders. Setting both side border flags or both the top and bottom border flags for a particular gadget, will create a window that is all border.

See the SuperBitMap example, "lines.c", in Intuition Windows for an example of creating proportional gadgets that are positioned within a window's borders.

There are circumstances where the border size will not adjust properly so that the gadget has the correct visual appearance. One way to correct this problem is to place a "hidden" gadget into the border, which forces the border to the correct size. Such a gadget would have no imagery and would not cause any IDCMP messages to be sent on mouse button activity. The gadget should be placed at the end of the gadget list of the window, so that it does not cover up any other border gadgets.

Sometimes the sizing gadget can be used to adjust the width of the borders, as in the case of proportional gadgets in the right or bottom border. The proportional gadget will only increase the width of the border by enough so that the select box of the gadget fits within the border, no space is reserved between the gadget and the inner edge of the window. By placing the size gadget in both borders (using the window flags WFLG_SIZEBRIGHT and WFLG_SIZEBBOTTOM), the prop gadget sizes can be adjusted so that there is an even margin on all sides. This technique is used in the "lines.c" example mentioned above.

Size Gadget in Various Window Border Combinations

The border flags GACT_RIGHTBORDER, GACT_LEFTBORDER, GACT_TOPBORDER and GACT_BOTTOMBORDER which are set in the Activation field of the Gadget structure declare that the gadget will be positioned in the border. Gadgets which are declared to be in the border are automatically refreshed by Intuition whenever the window borders need to be redrawn. This prevents the gadget imagery from being obliterated.

Intuition attempts to identify gadgets that are substantially in the border but do not have the appropriate border flags set. Such gadgets are marked for the same refresh treatment as explicit border gadgets. Applications should not rely on this behavior, but should instead declare their border gadgets properly.

Gadgets that are not declared to be in the border, and whose dimensions are 1*1 or smaller are never marked by Intuition as being effectively in the border. This is because some applications tuck a small non-selectable gadget (of size 0*0 or 1*1) into the window border, and attach imagery for the window to that gadget. The application does this to get automatic refresh of that imagery, since Intuition refreshes gadget imagery when window damage occurs.

Intuition attempts to locate gadgets within the border that do not have the appropriate flags set. This may cause gadgets to appear in the border when the application has not set any of the border flags. Applications should not rely on this behavior, nor should they place non-border gadgets fully or partially within the window's borders.

Gadget Highlighting

In general, the appearance of an active or selected gadget changes to inform the user the gadget state has changed. A highlighting method is specified by setting one of the highlighting flags in the Gadget structure's Flags field.

Intuition supports three methods of activation or selection highlighting:

  • Highlighting by color complementing (GFLG_GADGHCOMP)

  • Highlighting by drawing a box (GFLG_GADGHBOX)

  • Highlighting by an alternate image or border (GFLG_GADGHIMAGE)

  • No highlighting (GFLG_GADGHNONE)

One of the highlighting types or GFLG_GADGHNONE must be specified for each gadget.

Highlighting by Color Complementing

Highlighting may be accomplished by complementing all of the colors in the gadget’s select box. In this context, complementing means the complement of the binary number used to represent a particular color register. For example, if the color in color register 2 is used (binary 10) in a specific pixel of the gadget, the complemented value of that pixel will be the color in color register 1 (binary 01).

To use this highlighting method, set the GFLG_GADGHCOMP flag.

Only the select box of the gadget is complemented; any portion of the text, image, or border which is outside of the select box is not disturbed. See Intuition Images, Line Drawing, and Text for more information about complementing and about color in general.

Highlighting by Drawing a Box

To highlight by drawing a simple border around the gadget's select box, set the GFLG_GADGHBOX bit in the Flags field.

Highlighting with an Alternate Image or Alternate Border

An alternate image may be supplied as highlighting for gadgets that use image rendering, similarly an alternate border may be supplied for gadgets that use border rendering. When the gadget is active or selected, the alternate image or border is displayed in place of the default image or border. For this highlighting method, set the SelectRender field of the Gadget structure to point to the Image structure or Border structure for the alternate display.

Specify that highlighting is to be done with alternate imagery by setting the GFLG_GADGHIMAGE flag in the Flags field of the Gadget structure. When using GFLG_GADGHIMAGE, remember to set the GFLG_GADGIMAGE flag for images, clear it for borders.

When using alternate images and borders for highlighting, gadgets rendered with images must highlight with another image and gadgets rendered with borders must highlight with another border. For information about how to create an Image or Border structure, see Intuition Images, Line Drawing, and Text.

Gadget Refreshing

Gadget imagery is redrawn by Intuition at appropriate times, e.g., when the user operates the gadget. The imagery can also be updated under application control.

Gadget Refreshing by Intuition

Intuition will refresh a gadget whenever an operation has damaged the layer of the window or requester to which it is attached. Because of this, the typical application does not need to call RefreshGList() as a part of its IDCMP_REFRESHWINDOW event handling.

Intuition's refreshing of the gadgets of a damaged layer is done through the layer's damage list. This means that rendering is clipped or limited to the layer's damage region-that part of the window or requester that needs refreshing.

Intuition directly calls the Layers library functions BeginUpdate() and EndUpdate(), so that rendering is restricted to the proper area. Applications should not directly call these functions under Intuition, instead, use the BeginRefresh() and EndRefresh() calls. Calls to RefreshGList() or RefreshGadgets() between BeginRefresh() and EndRefresh() are not permitted. Never add or remove gadgets between the BeginRefresh() and EndRefresh() calls.

For more information on BeginRefresh() and EndRefresh(), see Intuition Windows and the SDK.

Gadgets which are positioned using GFLG_RELBOTTOM or GFLG_RELRIGHT, or sized using GFLG_RELWIDTH or GFLG_RELHEIGHT pose a problem for this scheme. When the window is sized, the images for these gadgets must change, even though they are not necessarily in the damage region. Therefore, Intuition must add the original and new visual regions for such relative gadgets to the damage region before refreshing the gadgets. The result of this is that applications should ensure that any gadgets with relative position or size do not have Border, Image or IntuiText imagery that extends beyond their select boxes.

Gadget Refreshing by the Program

The AddGList() function adds gadgets to Intuition's internal lists but do not display their imagery. Subsequently calls to RefreshGList() must be made to draw the gadgets into the window or requester.

Programs may use RefreshGList() to update the display after making changes to their gadgets. The supported changes include (not an exhaustive list): changing the GFLG_SELECTED flag for boolean gadgets to implement mutually exclusive gadgets, changing the GadgetText of a gadget to change its label, changing the GFLG_DISABLED flag, and changing the contents of the StringInfo structure Buffer of a string gadget. When making changes to a gadget, be sure to remove the gadget from the system with RemoveGList() before altering it. Remember to add the gadget back and refresh its imagery.

Boolean gadgets rendered with borders, instead of images, or highlighted with surrounding boxes (GFLG_GADGHBOX) are handled very simply by Intuition, and complicated transitions done by the program can get the rendering out of phase. Applications should avoid modifying the imagery and refreshing gadgets that may be highlighted due to selection by the user. Such operations may leave pixels highlighted when the gadget is no longer selected. The problems with such transitions can often be avoided by providing imagery, either image or border, that covers all pixels in the select box. For GFLG_GADGHIMAGE gadgets, the select imagery should cover all pixels covered in the normal imagery.

Updating a Gadget's Imagery

The RefreshGList() function was designed to draw gadgets from scratch, and assumes that the underlying area is blank. This function cannot be used blindly to update gadget imagery. The typical problem that arises is that the application cannot change a gadget from selected to unselected state (or from disabled to enabled state) and have the imagery appear correct. However, with a little care, the desired results can be obtained.

Depending on the imagery you select for your gadget, the rendering of one state may not completely overwrite the rendering of a previous one. For example, consider a button which consists of a complement-highlighted boolean gadget, whose imagery is a surrounding Border and whose label is an IntuiText. Attempting to visually unselect such a gadget by clearing its GFLG_SELECTED flag and refreshing it will leave incorrect imagery because RefreshGList() just redraws the border and text, and never knows to erase the field area around the text and inside the gadget. That area will remain complemented from before.

One solution is to use a gadget whose imagery is certain to overwrite any imagery left over from a different state. Disabling a gadget or highlighting it with complement mode affects the imagery in the entire select box. To overwrite this successfully, the gadget's imagery (GadgetRender) should be an Image structure which fully covers the select box. Such a gadget may be highlighted with color complementing (GFLG_GADGHCOMP), or with an alternate image (GFLG_GADGHIMAGE) for its SelectRender. Or, for a gadget which will never be disabled but needs to be deselected programmatically, you may also use a Border structure for its GadgetRender, and an identically-shaped (but differently colored) Border for its SelectRender.

The other technique is to pre-clear the underlying area before re-rendering the gadget. To do this, remove the gadget, erase the rectangle of the gadget's select area, change the GFLG_SELECTED or the GFLG_DISABLED flag, add the gadget back, and refresh it.

If the gadget has a relative size and/or position (i.e., if of the GFLG_RELxxx flags are used), then the application will need to compute the rectangle of the gadget's select area based on the window's current width and/or height. Since the window size is involved in the calculation, it is important that the window not change size between the call to RemoveGList() and the call to RectFill(). To ensure this, the application should set IDCMP_SIZEVERIFY so that Intuition will first notify you before beginning a sizing operation. (Note that applications using any of the IDCMP verify events such as IDCMP_SIZEVERIFY should not delay long in processing such events, since that holds up the user, and also Intuition may give up and stop waiting for you).

Gadget Refresh Function

Use the RefreshGList() function to refresh one or more gadgets in a window or requester.

VOID RefreshGList( struct Gadget *gadgets, struct Window *window,
                   struct Requester *requester, LONG numGad );

This function redraws no more than numGad gadgets, starting with the specified gadget, in a window or requester. The application should refresh any gadgets after adding them. The function should also be used after the application has modified the imagery of the gadgets to display the new imagery.

Gadget Enabling and Disabling

A gadget may be disabled so that it cannot be chosen by the user. When a gadget is disabled, its image is ghosted. A ghosted gadget is overlaid with a pattern of dots, thereby making the imagery less distinct. The dots are drawn into the select box of the gadget and any imagery that extends outside of the select box is not affected by the ghosting.

The application may initialize whether a gadget is disabled by setting the GFLG_DISABLED flag in the Gadget structure's Flags field before a gadget is submitted to Intuition. Clear this flag to create an enabled gadget.

After a gadget is submitted to Intuition for display, its current enable state may be changed by calling OnGadget() or OffGadget(). If the gadget is in a requester, the requester must currently be displayed when calling these functions.

VOID OnGadget ( struct Gadget *gadget, struct Window *window, struct Requester *requester );
VOID OffGadget( struct Gadget *gadget, struct Window *window, struct Requester *requester );

Depending on what sort of imagery you choose for your gadget, OnGadget() may not be smart enough to correct the gadget's displayed imagery. See the section on "Updating a Gadget's Imagery" for more details.

Multiple gadgets may be enabled or disabled by calling OnGadget() or OffGadget() for each gadget, or by removing the gadgets with RemoveGList(), setting or clearing the GFLG_DISABLED flag on each, replacing the gadgets with AddGList(), and refreshing with RefreshGList().

Gadget Pointer Movements

If the GACT_FOLLOWMOUSE flag is set for a gadget, the application will receive mouse movement broadcasts as long as the gadget is active. This section covers the behavior of proportional, boolean and string gadgets, although there are major caveats in some cases:

Unlike IDCMP_GADGETUP and IDCMP_GADGETDOWN IntuiMessages, the IAddress field of an IDMP_MOUSEMOVE IntuiMessage does not point to the gadget. The application must track the active gadget (this information is readily obtained from the IDCMP_GADGETDOWN message) instead of using the IAddress field.

Right Wrong
imsg = IIntuition->GetMsg(win->UserPort);

class = imsg->Class;
code = imsg->Code;
/* GOOD */
iaddress = imsg->IAddress;
IIntuition->ReplyMsg(imsg);

imsg = IIntuition->GetMsg(win->UserPort);

class = imsg->Class;
code = imsg->Code;
/* ILLEGAL */
gadid = ((struct Gadget *)imsg->IAddress)->GadgetID;
IIntuition->ReplyMsg(imsg);

Using the code in the left column, it is acceptable to get the address of a gadget with gadid=((struct Gadget *)iaddress)->GadgetID but only after you have checked to make sure the message is an IDCMP_GADGETUP or IDCMP_GADGETDOWN.

Boolean gadgets only receive mouse messages if both GACT_RELVERIFY and GACT_FOLLOWMOUSE are set. Those cases described below with GACT_RELVERIFY cleared do not apply to boolean gadgets.

In general, IDCMP_MOUSEMOVE messages are sent when the mouse changes position while the gadget is active. Boolean and proportional gadgets are active while the mouse button is held down, thus mouse move messages will be received when the user "drags" with the mouse. String gadgets are active until terminated by keyboard entry or another object becomes active (generally by user clicking the other object). GACT_FOLLOWMOUSE string gadgets will generate mouse moves the entire time they are active, not just when the mouse button is held.

The broadcasts received differ according to the gadget's flag settings. If using the GACT_IMMEDIATE and GACT_RELVERIFY activation flags, the program gets a gadget down message, receives mouse reports (IDCMP_MOUSEMOVE) as the mouse moves, and receives a gadget up message when the mouse button is released. For boolean gadgets, the mouse button must be released while the pointer is over the gadget. If the button is not released over the boolean gadget, an IDCMP_MOUSEBUTTONS message with the SELECTUP qualifier will be sent.

If only using the GACT_IMMEDIATE activation flag, the program gets a gadget down message and receives mouse reports as the mouse moves. The mouse reports will stop when the user releases the mouse select button. This case does not apply to boolean gadgets as GACT_RELVERIFY must be set for boolean gadgets to receive mouse messages.

If only using the GACT_RELVERIFY activation flag, the program gets mouse reports followed by an up event for a gadget. For boolean gadgets, the IDCMP_GADGETUP event will only be received if the button was released while the pointer was over the gadget. If the button is not released over the boolean gadget, a IDCMP_MOUSEBUTTONS message with the SELECTUP qualifier will be received if the program is receiving these events.

If neither the GACT_IMMEDIATE nor the GACT_RELVERIFY activation flags are set, the program will only receive mouse reports. This case does not apply to boolean gadgets as GACT_RELVERIFY must be set for boolean gadgets to receive mouse messages.

Gadget Help

Window-based applications can elect to receive a type of IDCMP message called IDCMP_GADGETHELP when the user positions the pointer over one of the window's gadgets. The pointer is over the gadget if the pointer is within the gadget's bounding box (which defaults to the gadget's hit box).

Using the intuition.library function HelpControl(), an application can turn Gadget Help on and off for a window:

VOID HelpControl(struct Window *my_win, ULONG help_flags);

Currently, the only flag defined for the help_flags field is HC_GADGETHELP (from <intuition/intuition.h>). If the HC_GADGETHELP bit is set, HelpControl() turns on help for my_win, otherwise HelpControl() turns off gadget help for the window.

When gadget help is on for the active window, Intuition sends IDCMP_GADGETHELP messages to the window's IDCMP port. Each time the user moves the pointer from one gadget to another, Intuition sends an IDCMP_GADGETHELP message about the new gadget. Intuition also sends an IDCMP_GADGETHELP message when the user positions the pointer over a gadgetless portion of the window, and when the user moves the pointer outside of the window. An application can find out what caused the IDCMP_GADGETHELP message by first examining the IntuiMessage's IAddress field. If IAddress is NULL, the pointer is outside of the window. If IAddress is the window address, the pointer is inside of the window, but not over any gadget. If IAddress is some other value, the user positioned the pointer over one of the window's gadgets and IAddress is the address of that gadget.

To discern between the different system gadgets (window drag bar, window close gadget, etc.) an application has to check the GadgetType field of the gadget:

sysgtype = ((struct Gadget *)imsg->IAddress)->GadgetType & GTYP_SYSTYPEMASK;

The constant GTYP_SYSTYPEMASK (defined in <intuition/intuition.h>) corresponds to the bits of the GadgetType field used for the system gadget type. There are several possible values for sysgtype (defined in <intuition/intuition.h>).

If sysgtype is zero, IAddress is the address of an application's gadget.

Not all gadget's will trigger an IDCMP_GADGETHELP event. Intuition will send gadget help events when the pointer is over a gadget with an extended Gadget structure (struct ExtGadget from <intuition/intuition.h>) and a set GMORE_GADGETHELP flag (from the ExtGadget.MoreFlags field).

To set or clear this flag for a BOOPSI gadget, an application can use the GA_GadgetHelp attribute. Setting GA_GadgetHelp to TRUE sets the flags and setting it to FALSE clears the flag. Only the OM_SET method applies to this gadgetclass attribute.

Gadget Bounding Boxes

All gadgets have a select (or hit) box. This box is the area of the window that the user can click in to select the gadget. The select box limits certain gadgets because the gadget's imagery could lie outside of the gadget's hit box. For example, the hit box for a string gadget is the area that text appears when the user types into the gadget (see below). Many string gadgets have a border and a label, which the programmer sets using the Gadget structure's GadgetRender and GadgetText fields. The border and label imagery appears outside of the hit box.

String Gadget without Bounding Box

The major disadvantage of a gadget's imagery being external to its hit box has to do with relative gadgets (these are sometimes referred to as GREL gadgets). Intuition positions one of these gadgets relative to the edge's of the gadget's window. When the window changes dimensions, Intuition repositions the gadget within the window. The gadget can also make its size relative to the window's dimensions.

When Intuition resizes a window, it remembers which portions of the window's display sustained visual damage. When Intuition refreshes the visual state of the window, it only redisplays the parts of the window that sustained visual damage. When Intuition resizes a window that has a GREL gadget, Intuition erases the old gadget by erasing the hit box of the gadget and remembers that area as a region it will have to refresh. Intuition also figures out where the the new hit box will be and remembers that area as a region Intuition will have to refresh. Because Intuition will not erase or redraw any imagery that falls outside of the GREL gadget's hit box, Intuition will ignore any part of the gadget's label or border that is outside the hit box.

To remedy this situation, Intuition also adds a bounding box to gadgets. If a gadget has a bounding box, Intuition uses the bounding box in place of the hit box when figuring out what areas to refresh. With a bounding box, a gadget can extend its hit area to encompass all of its imagery.

The bounding box feature is not specific to BOOPSI gadgets. Any Intuition gadget can have one. If the gadget doesn't supply a bounding box, Intuition will use the gadget's normal hit box as the bounding box, which yields the same result as previous versions of the OS.

Adding the bounding box feature to Intuition gadgets required extending the Gadget structure. The ExtGadget structure is a superset of the old Gadget structure (from <intuition/intuition.h>):

struct ExtGadget
{
    /* The first fields match struct Gadget exactly */
    struct ExtGadget *NextGadget; /* Matches struct Gadget */
    WORD LeftEdge, TopEdge;       /* Matches struct Gadget */
    WORD Width, Height;           /* Matches struct Gadget */
    UWORD Flags;                  /* Matches struct Gadget */
    APTR SpecialInfo;             /* Matches struct Gadget */
    UWORD GadgetID;               /* Matches struct Gadget */
    APTR UserData;                /* Matches struct Gadget */
 
    /* These fields only exist under V39 and only if GFLG_EXTENDED is set */
    ULONG MoreFlags;
    WORD BoundsLeftEdge;        /* Bounding extent for gadget, valid */
    WORD BoundsTopEdge;         /* only if the GMORE_BOUNDS bit in   */
                                /*  the MoreFlags field is set.  The */
    WORD BoundsWidth;           /* GFLG_RELxxx flags affect these    */
    WORD BoundsHeight;          /* coordinates as well.              */
};


Intuition discerns a Gadget from an ExtGadget by testing the Flags field. If the GFLG_EXTENDED bit is set, the Gadget structure is really an ExtGadget structure. Intuition will use the bounding box only if the GMORE_BOUNDS bit in the ExtGadget.MoreFlags field is set.

Gadgetclass supports an attribute called GA_Bounds that sets up a BOOPSI gadget's bounding box. It expects a pointer to an IBox structure (from <intuition/intuition.h>) in the ti_Data field, which gadgetclass copies into the bounding box fields in the ExtGadget structure.

Gadget Structure

Here is the specification for the Gadget structure defined in <intuition/intuition.h>. You create an instance of this structure for each gadget you place in a window or requester:

struct Gadget
    {
    struct Gadget *NextGadget;
    WORD LeftEdge, TopEdge;
    WORD Width, Height;
    UWORD Flags;
    UWORD Activation;
    UWORD GadgetType;
    APTR GadgetRender;
    APTR SelectRender;
    struct IntuiText *GadgetText;
    LONG MutualExclude;
    APTR SpecialInfo;
    UWORD GadgetID;
    APTR UserData;
    };
NextGadget
Applications may create lists of gadgets that may be added to a window or requester with a single instruction. NextGadget is a pointer to the next gadget in the list. The last gadget in the list should have a NextGadget value of NULL.
When gadgets are added or removed, Intuition will modify the appropriate NextGadget fields to maintain a correctly linked list of gadgets for that window or requester. However, removing one or more gadgets does not reset the last removed gadget’s NextGadget field to NULL.
LeftEdge, TopEdge, Width, Height
These variables describe the location and dimensions of the select box of the gadget. Both location and dimensions can be either absolute values or else relative to the edges and size of the window or requester that contains the gadget.
LeftEdge and TopEdge are relative to one of the corners of the display element, according to how GFLG_RELRIGHT and GFLG_RELBOTTOM are set in the Flags variable (see below).
Width and Height are either absolute dimensions or a negative increment to the width abd height of a requester or a window, according to to how the GFLG_RELWIDTH and GFLG_RELHEIGHT flags are set (see below).
Flags
The Flags field is shared by the program and Intuition. See the section below on "Gadget Flags" for a complete description of all the flag bits.
Activation
This field is used for information about some gadget attributes. See the "Gadget Activation Flags" section below for a description of the various flags.
GadgetType
This field contains information about gadget type and in what sort of display element the gadget is to be displayed. One of the following flags must be set to specify the type:
GTYP_BOOLGADGET Boolean gadget type.
GTYP_STRGADGET String gadget type. For an integer gadget, also set the GACT_LONGINT flag. See the "Gadget Activation Flags" section below.
GTYP_PROPGADGET Proportional gadget type.
GTYP_CUSTOMGADGET Normally not set by the application. Used by custom BOOPSI gadget types, discussed in BOOPSI.
The following gadget types may be set in addition to one of the above types. None of the following types are required:
GTYP_GZZGADGET If the gadget is placed in a GimmeZeroZero window, setting this flag will place the gadget in the border layer, out of the inner window. If this flag is not set, the gadget will go into the inner window. Do not set this bit if this gadget is not placed in a GimmeZeroZero window.
GTYP_REQGADGET Set this bit if this gadget is placed in a requester.
GadgetRender
A pointer to the Image or Border structure containing the graphics imagery of this gadget. If this field is set to NULL, no rendering will be done.
If the graphics of this gadget are implemented with an Image structure, this field should contain a pointer to that structure and the GFLG_GADGIMAGE flag must be set. If a Border structure is used, this field should contain a pointer to the Border structure, and the GFLG_GADGIMAGE bit must be cleared.
SelectRender
If the application does not use an alternate image for highlighting, set this field to NULL. Otherwise, if the flag GFLG_GADGHIMAGE is set, this field must contain a pointer to an Image or Border structure. The GFLG_GADGIMAGE flag determines the type of the rendering. Provide a pointer to an IntuiText structure to include a text component to the gadget. Multiple IntuiText structures may be chained. Set this field to NULL if the gadget has no associated text.
GadgetText
Provide a pointer to an IntuiText structure to include a text component to the gadget. Multiple IntuiText structures may be chained. Set this field to NULL if the gadget has no associated text.
The offsets in the IntuiText structure are relative to the top left of the gadget's select box.
MutualExclude
This field is currently ignored by Intuition, but is reserved. Do not store information here. Starting with V36, if the GadgetType is GTYP_CUSTOMGADGET this field is used to point to a Hook for the custom gadget.
SpecialInfo
SpecialInfo contains a pointer to an extension structure which contains the special information needed by the gadget.
If this is a proportional gadget, this variable must contain a pointer to an instance of a PropInfo data structure. If this is a string or integer gadget, this variable must contain a pointer to an instance of a StringInfo data structure. If this is a boolean gadget with GACT_BOOLEXTEND activation, this variable must contain a pointer to an instance of a BoolInfo data structure. Otherwise, this variable is ignored.
GadgetID
This variable is for application use and may contain any value. It is often used to identify the specific gadget within an event processing loop. This variable is ignored by Intuition.
UserData
This variable is for application use and may contain any value. It is often used as a pointer to a data block specific to the application or gadget. This variable is ignored by Intuition.

Gadget Flags

The following are the flags that can be set in the Flags variable of the Gadget structure. There are four highlighting methods to choose from. These determine how the gadget imagery will be changed when the gadget is selected. One of these four flags must be set.

GFLG_GADGHNONE
Set this flag for no highlighting.
GFLG_GADGHCOMP
This flag chooses highlighting by complementing all of the bits contained within the gadget's select box.
GFLG_GADGHBOX
This flag chooses highlighting by drawing a complemented box around the gadget's select box.
GFLG_GADGHIMAGE
Set this flag to indicate highlighting with an alternate image.

In addition to the highlighting flags, these other values may be set in the Flags field of the Gadget structure.

GFLG_GADGIMAGE
If the gadget has a graphic, and it is implemented with an Image structure, set this bit. If the graphic is implemented with a Border structure, make sure this bit is clear. This bit is also used by SelectRender to determine the rendering type.
GFLG_RELBOTTOM
Set this flag if the gadget's TopEdge variable describes an offset relative to the bottom of the display element (window or requester) containing it. A GFLG_RELBOTTOM gadget moves automatically as its window is made taller or shorter. Clear this flag if TopEdge is relative to the top of the display element. If GFLG_RELBOTTOM is set, TopEdge should contain a negative value, which will position it up from the bottom of the display element.
GFLG_RELRIGHT
Set this flag if the gadget's LeftEdge variable describes an offset relative to the right edge of the display element containing it. A GFLG_RELRIGHT gadget moves automatically as its window is made wider or narrower. Clear this flag if LeftEdge is relative to the left edge of the display element. If GFLG_RELRIGHT is set, LeftEdge should contain a negative value, which will position the gadget left of the right edge of the display element.
GFLG_RELWIDTH
Set this flag for "relative gadget width." If this flag is set, the width of the gadget's select box changes automatically whenever the width of its window changes. When using GFLG_RELWIDTH, set the gadget's Width to a negative value. This value will be added to the width of the gadget's display element (window or requester) to determine the actual width of the gadget's select box.
GFLG_RELHEIGHT
Set this flag for "relative gadget height." If this flag is set, the height of the gadget's select box changes automatically whenever the height of its window changes. When using GFLG_RELHEIGHT, set the gadget's Height to a negative value. This value will be added to the height of the gadget's display element (window or requester) to determine the actual height of the gadget's select box.
GFLG_SELECTED
Use this flag to preset the on/off selected state for a toggle-select boolean gadget (see the discussion of the GACT_TOGGLESELCT flag below). If the flag is set, the gadget is initially selected and is highlighted. If the flag is clear, the gadget starts off in the unselected state. To change the selection state of one or more gadgets, change their GFLG_SELECTED bits as appropriate, add them back and refresh them. However, see the section on "Updating a Gadget's Imagery" for important details.
GFLG_DISABLED
If this flag is set, this gadget is disabled. To enable or disable a gadget after the gadget has been added to the system, call the routines OnGadget() and OffGadget(). The GFLG_DISABLED flag can be programmatically altered in much the same way as GFLG_SELECTED above. See the section on "Updating a Gadget's Imagery" for important details.
GFLG_STRINGEXTEND
The StringInfo Extension field points to a valid StringExtend structure. Use of this structure is described later in the "String Gadget Type" section. This flag is ignored prior to V37, see GACT_STRINGEXTEND for the same functionality under V36. Note that GACT_STRINGEXTEND is not ignored prior to V36 and should only be set in V36 or later systems.
GFLG_TABCYCLE
This string participates in cycling activation with the tab (or shifted tab) key. If this flag is set, the tab keys will de-activate this gadget as if the Return or Enter keys had been pressed, sending an IDCMP_GADGETUP message to the application, then the next string gadget with GFLG_TABCYCLE set will be activated. Shifted tab activates the previous gadget.

Gadget Activation Flags

These flags may be set in the Activation field of the Gadget structure.

GACT_TOGGLESELECT
This flag applies only to boolean gadgets, and tells Intuition that this is to be a toggle-select gadget, not a hit-select one. Preset the selection state with the gadget flag GFLG_SELECTED (see above). The program may check if the gadget is in the selected state by examining the GFLG_SELECTED flag at any time.
GACT_IMMEDIATE
If this bit is set, the program will be sent an IDCMP_GADGETDOWN message when the gadget is first picked. The message will be sent when the user presses the mouse select button.
GACT_RELVERIFY
This is short for "release verify." If this bit is set, the program will be sent an IDCMP_GADGETUP message when the gadget is deactivated. IDCMP_GADGETUP will be sent for boolean gadgets when the user releases the mouse select button while the pointer is over the select box, for proportional gadgets whenever the user releases the mouse select button (regardless of the pointer position), and for string and integer gadgets when the user completes the text entry by pressing return or tabbing to the next gadget (where supported).
For boolean gadgets, if the user releases the mouse button while the pointer is outside of the gadget's select box IDCMP_GADGETUP will not be generated. Instead, the program will receive an IDCMP_MOUSEBUTTONS event with the SELECTUP code set. For string gadgets, if the user deactivates the gadget by clicking elsewhere, it may not be possible to detect.
GACT_ENDGADGET
This flag pertains only to gadgets attached to requesters. If a gadget with the GACT_ENDGADGET flag set is chosen by the user the requester will be terminated as if the application had called the EndRequest() function.
See Intuition Requesters for more information about requester gadget considerations.
GACT_FOLLOWMOUSE
As long as a gadget that has this flag set is active, the program will receive mouse position messages for each change of mouse position. For GTYP_BOOLGADGET gadgets, GACT_RELVERIFY must also be set for the program to receive mouse events.

The following flags are used to place application gadgets into a specified window border. Intuition will adjust the size of a window's borders appropriately provided these gadgets are set up with a call to OpenWindow(), OpenWindowTags() or OpenWindowTagList(). Intuition knows to refresh gadgets marked with these flags when the window border is changed, e.g., when the window is activated. For GimmeZeroZero windows, the GTYP_GZZGADGET flag must also be set for border gadgets.

GACT_RIGHTBORDER
If this flag is set, the gadget is placed in the right border of the window and the width and position of this gadget are used in deriving the width of the window's right border.
GACT_LEFTBORDER
If this flag is set, the gadget is placed in the left border of the window and the width and position of this gadget are used in deriving the width of the window's left border.
GACT_TOPBORDER
If this flag is set, the gadget is placed in the top border of the window and the height and position of this gadget are used in deriving the height of the window's top border.
GACT_BOTTOMBORDER
If this flag is set, the gadget is placed in the bottom border of the window and the height and position of this gadget are used in deriving the height of the window's bottom border.

The following flags apply only to string gadgets:

GACT_STRINGCENTER
If this flag is set, the text in a string gadget is centered within the select box.
GACT_STRINGRIGHT
If this flag is set, the text in a string gadget is right justified within the select box.
GACT_STRINGLEFT
This "flag" has a value of zero. By default, the text in a string gadget is left justified within the select box.
GACT_LONGINT
If this flag is set, the user can construct a 32-bit signed integer value in a normal string gadget. The input buffer of the string gadget must be initialized with an ASCII representation of the starting integer value.
GACT_ALTKEYMAP
These flags may be set in the Activation field of the Gadget structure. A pointer to the keymap must be placed in the StringInfo structure variable AltKeyMap.
GACT_BOOLEXTEND
This flag applies only to boolean gadgets. If this flag is set, then the boolean gadget has a BoolInfo structure associated with it. A pointer to the BoolInfo structure must be placed in the SpecialInfo field of the Gadget structure.
GACT_STRINGEXTEND
This is an obsolete flag originally defined in V36. It applies only to string gadgets and indicates that StringInfo.Extension points to a valid StringExtend structure. Although this flag works, it is not ignored prior to V36 as it should be in order to be backward compatible. This flag is replaced by GFLG_STRINGEXTEND in V37. GFLG_STRINGEXTEND performs the same function and is properly ignored on systems prior to V36.

Gadget Types

The following is a list of the most primitive gadget types available through Intuition. All of these types have been superseded by BOOPSI. This information is being provided for historical reference only.

Boolean Gadget Type

Proportional Gadget Type

String Gadget Type

Custom Gadgets

Intuition also supports custom gadgets, where the application can supply to Intuition its own code to manage gadgets. This allows the creation of gadgets with behavior quite different from standard boolean, proportional, or string gadgets. For example, it would be possible to create a dial gadget, where the user could rotate the knob of a gadget. The code for a custom gadget needs to respond to various commands and requests from Intuition, such as "is this pixel in your hit-area?", "please go active" and "please go inactive".

Intuition has an object-oriented creation and delegation method called BOOPSI, that allows custom gadgets to be easily created, deleted, specialized from existing classes of custom gadget, and so on. See BOOPSI for details.

Function Reference

The following are brief descriptions of the Intuition functions that relate to the use of Intuition gadgets. See the SDK for details on each function call.

Function Description
AddGadget() Add a gadget to an open window or requester.
AddGList() Add some gadgets to an open window or requester.
RemoveGadget() Remove a gadget from an open window or requester.
RemoveGList() Remove some gadgets from an open window or requester.
RefreshGadgets() Refresh all gadgets for the window or requester.
RefreshGList() Refresh some gadgets from the window or requester.
ModifyProp() Change the values of an open proportional gadget.
NewModifyProp() Optimized version of ModifyProp().
OnGadget() Enable an open gadget.
OffGadget() Disable an open gadget.
ActivateGadget() Activate an open string gadget.
SetEditHook() Change the global edit hook for string gadgets.