Intuition Gadgets — Classic Gadgets (Section 3.4)¶
This article synthesises Section 3.4 ("Gadgets") of Amiga C for Advanced Programmers by Bleek, Jennrich, Schulz (Abacus / Data Becker, ~1991). Section 3.4 is one of the longest in Chapter 3 (~50 pages, PDF pages 187–238) and covers the classic Intuition gadget model: struct Gadget, the gadget chain, the four built-in gadget kinds (boolean, string, integer, proportional), custom gadget rendering, and the high-level GadTools toolkit.
Editorial note: page numbers in this article refer to the PDF page index in the raw OCR source. Important: this article covers classic Intuition gadgets (pre-BOOPSI), not the modern BOOPSI gadget class system. For BOOPSI, see
graphics/v39-aa-graphics-features.mdand the autodocs forgadgetclass.
What a gadget is (page 187)¶
A gadget is a sub-region of a window that detects and reacts to user input. Compared to a window (which gets events for clicks anywhere on its surface), a gadget is a focused area with:
- A specific kind (boolean button, text field, slider, etc.)
- A specific region (top-left corner + width/height)
- A specific IDCMP event it emits (
IDCMP_GADGETUP,IDCMP_GADGETDOWN) - A specific way to render itself (Intuition-managed via flags, or application-managed via custom rendering)
Gadgets appear in two places:
- Title bar (system gadgets: close, size, depth, zoom, iconify)
- Window body (the application's gadgets: OK buttons, scroll bars, sliders, custom controls)
The book's editor uses gadgets heavily: OK buttons in requesters, scroll bars for the editing area, sliders for jump-to-line.
The classic Gadget structure (page 188)¶
struct Gadget {
struct Gadget *NextGadget; /* chain to the next gadget */
WORD LeftEdge, TopEdge; /* position relative to window origin */
WORD Width, Height; /* size */
UWORD Flags; /* GADGH_*, GACT_* */
UWORD Activation; /* GADGIMMEDIATE | GADGFOLLOW | RELVERIFY */
UWORD GadgetType;
APTR GadgetRender; /* Image or IntuiText */
APTR SelectRender; /* selected-state render */
struct IBox *GadgetText; /* optional text */
LONG MutualExclude; /* mutual-exclusion mask */
UWORD SpecialInfo; /* kind-specific data */
UWORD GadgetID; /* application-defined ID */
APTR UserData; /* application data */
};
For most applications, only a few fields are interesting:
Flags— visual/interaction flagsActivation— when/how the gadget respondsGadgetType— which built-in kindSelectRender— what to draw when activeGadgetID— your tag for finding the gadget after aGadgetUpevent
The book walks through each field in detail (page 188-200).
The four built-in gadget kinds¶
The book's section 3.4 is organised around these kinds:
Boolean gadgets (page ~200)¶
A simple on/off button:
struct NewGadget ng_bool = {
40, 60, 80, 14, /* x, y, w, h */
"OK", /* label */
&myButtonImage, /* unselected image */
&myButtonSelectImage, /* selected image */
0, /* placement */
1, /* gadget ID */
NULL /* userdata */
};
struct Gadget *ok_g = (struct Gadget *)CreateGadgetA(
GADGETBUTTON_KIND, /* kind */
&ng_bool,
NULL /* tag list */
);
CreateGadgetA() (added in OS 2.0) is the modern way to create classic gadgets from a NewGadget template.
IDCMP_GADGETUP arrives when the user releases the mouse button on the gadget.
String gadgets (page ~210)¶
A text input field:
struct Gadget *str_g = CreateGadgetA(
STRING_KIND,
&ng_string,
NULL
);
AddGadget(window, str_g);
RefreshGadgets(str_g, window);
String gadgets have a buffer (typically 64 bytes), a maximum-length, and a workbench-like cursor. IDCMP_GADGETUP arrives when the user presses Enter.
Integer gadgets (page ~220)¶
A numeric input field with up/down arrows:
struct Gadget *int_g = CreateGadgetA(
INTEGER_KIND,
&ng_integer,
NULL
);
IDCMP_GADGETUP arrives when the user clicks the arrows or presses Enter.
Proportional gadgets (page ~230)¶
A slider/scrubber:
struct Gadget *prop_g = CreateGadgetA(
PROPGADGET_KIND,
&ng_prop,
NULL
);
The prop gadget reports its body and pot position via the standard gadget fields. IDCMP_GADGETUP arrives when the user releases the mouse.
Activation and flags (page ~205)¶
Activation¶
| Flag | Effect |
|---|---|
GACT_IMMEDIATE |
Fire IDCMP_GADGETDOWN on press, IDCMP_GADGETUP on release (button-like) |
GACT_RELVERIFY |
Fire IDCMP_GADGETUP only if the user releases on the gadget |
GACT_FOLLOW |
Continuously fire IDCMP_GADGETUP while the user holds (slider-like) |
RELVERIFY is the safe default for most buttons: prevents accidentally clicking through a dialog if the user drags out.
Flags¶
| Flag | Effect |
|---|---|
GADGH_COMP |
Complement (XOR) render when selected |
GADGH_NONE |
No render selected appearance |
GADGH_IMAGE |
Use the SelectRender image when selected |
GADGH_TEXT |
Use the SelectRender IntuiText when selected |
GADGH_BOXES |
Draw a box outline when selected |
GADGH_RBUTTON |
Render like a Workbench radio button |
GADGH_CBOX |
Render like a checkbox |
GFLG_SELECTED |
The gadget starts in the selected state |
GFLG_TABCYCLE |
Tab key moves focus to next gadget |
GFLG_TABSTOP |
Gadget is a tab-stop |
MutualExclude (page ~207)¶
The MutualExclude field is a bitmask of gadget IDs. If two gadgets share a bit, activating one deactivates the other. Classic pattern for radio-button groups:
ng_radio1.MutualExclude = (1 << GADGET_ID_RADIO2) | (1 << GADGET_ID_RADIO3);
ng_radio2.MutualExclude = (1 << GADGET_ID_RADIO1) | (1 << GADGET_ID_RADIO3);
ng_radio3.MutualExclude = (1 << GADGET_ID_RADIO1) | (1 << GADGET_ID_RADIO2);
Gadget IDs 1-15 form the mutual-exclusion bits (a 16-bit mask).
Adding gadgets to a window (page ~190)¶
Classic gadgets must be added to the window's gadget chain:
AddGadget(window, &ng_bool.Gadget, 0); /* legacy form, OS 1.x */
/* or: */
AddGadget(window, ok_g, 0); /* modern form, OS 2.0+ */
RefreshGadgets(ok_g, window); /* redraw */
RefreshGadgets() causes intuition.library to redraw the gadget using its current image/flag settings.
To remove:
RemoveGadget(window, ok_g);
Custom gadgets (page ~240)¶
When none of the four built-in kinds fit, write your own:
static struct Image my_button_image = {
0, 0,
80, 14,
2, /* depth (2 bitplanes = 4 colours) */
&my_button_data, /* pixel data */
4, 0, /* pick me first colour */
NULL /* next image */
};
struct Gadget *my_gadget = (struct Gadget *)CreateGadgetA(
CUSTOM_KIND,
&ng_my,
NULL
);
Custom gadgets don't have a built-in render. The application must:
- Draw the gadget in its window's refresh event
- Provide a hit-test region (via the image or its bounding box)
- Handle the IDCMP_GADGETUP / DOWN events it emits
The book covers several custom-gadget examples for the editor: the scroll-bar, the cursor-position bar, the line-jumper.
The high-level GadTools toolkit (page ~245)¶
The book briefly introduces GadTools, which provides higher-level gadget kinds than the four built-ins:
- ListView
- Scroller (replaces manual proportional-gadget logic)
- TextDisplay
- Cycle (radio buttons as a single gadget)
- Integer, String, Boolean (with cleaner creation)
- CheckBox, MutuallyExclusive
- Slider (numeric slider with continuous update)
- GetFile, GetFont, GetScreen, GetColor (file/dialog gadget host)
The book only briefly introduces
GadToolsbecause it came with OS 2.0; the editor uses classic gadgets throughout Chapter 3. The fullGadToolscoverage is ingadtools/gadtools-library-reference.mdandlibrary-reference/gadtools-library.md(21 functions).
What's NOT in section 3.4¶
- BOOPSI gadget classes (the modern OO-style gadget system). These came later with OS 3.0 and replaced classic gadgets for new code. See the autodocs for
gadgetclassin the OS 3.5+ NDK. - ReAction (the BOOPSI library that ships with OS 3.5+). See
gadtools/reaction-gui-toolkit.md. - MUI (third-party gadget toolkit by Stefan Stuntz). See
gui/mui-toolkit.md. - Layout (GadTools' automatic positioning). The book pre-dates Layout; manually calculating gadget positions is what the editor examples show.
Modern migration notes¶
If you're writing new code today:
| Use this | Instead of this | Why |
|---|---|---|
OpenWindowTagList() |
OpenWindow() with NewWindow |
Modern API |
Layout for positioning |
Manual pixel positions | Easier to maintain |
| BOOPSI gadget classes | Classic gadgets | OO-style, customisable |
GadTools for built-in kinds |
Classic kinds | Saner API |
WindowUserData() |
Global state | Window-attached state |
IExec->Wait() |
WaitPort() |
Multi-source waiting |
But the fundamentals the book describes (Activation, MutualExclude, GADGH flags, refresh handling) all still apply.
Sources¶
- Bleek, Jennrich, Schulz, Amiga C for Advanced Programmers, Abacus / Data Becker, ~1991, Chapter 3 section 3.4 (pages ~140–180 of the printed book; PDF pages 187–238 of the scanned source).
- Full OCR text:
raw/c-programming/amiga-c-for-advanced-programmers.md. - Cross-references:
gadtools/gadtools-library-reference.md,library-reference/gadtools-library.md,graphics/v39-aa-graphics-features.md(BOOPSI in OS 3.x),gadtools/reaction-gui-toolkit.md.
The classic gadget model covered in the book is still applicable for compatibility code; new development should use BOOPSI or ReAction instead.