// iigs/uiBuilder.h - declarative UI scaffolding for desktop demos. // // Replaces hand-rolled ">> Menu \N3\r--Item\N250*Xx\r.\r" strings, // NewWindowParm zero-then-init boilerplate, AlertTemplate/ItemTemplate // blocks, and the cmd-ID -> handler switch. Each demo previously // duplicated ~150 lines of this boilerplate; the uiBuilder surface // folds it to ~30 lines. // // Three sub-surfaces: // 1. uiBuilderMenu() - builds an in-memory Menu Manager byte // stream from a UiMenuT spec, ready to hand // to NewMenu(). // 2. uiBuilderWindow() - fills a NewWindowParm with sensible defaults // + caller overrides + a UiCtlT array of // controls. Wraps NewWindow + NewControl2. // 3. uiBuilderAlert() - assembles AlertTemplate + ItemTemplate[] // from a small spec, runs Alert/StopAlert/... // // Plus a single onCmd dispatcher (extends IigsEventCallbacksT) that // looks up the menu-pick itemID in a (cmdId,handler) table. // // ORCA control.h proc constants (simpleProc/checkProc/scrollProc/ // growProc) are ABSTRACT 32-bit codes - NOT bank-E1 ROM addresses; // the CtlMgr maps them internally. Our cButton/cCheckBox/... mirror // those abstract values byte-for-byte. #ifndef IIGS_UI_BUILDER_H #define IIGS_UI_BUILDER_H #ifdef __cplusplus extern "C" { #endif #include #include "iigs/eventLoop.h" // --------------------------------------------------------------------------- // Menu builder // --------------------------------------------------------------------------- // Per-item flags (bitmask). Mirrors the Menu Manager mini-format // suffix letters: D=disabled, V=checked-visible, X=xor (hilite-only), // I=icon, S=item-has-style. Most demos only need MI_DISABLED and // MI_CHECKED. #define MI_DISABLED 0x0001 // item starts disabled (D) #define MI_CHECKED 0x0002 // item starts with checkmark (V) #define MI_XOR 0x0004 // item hilites via XOR (X) #define MI_DIVIDER 0x0008 // render this item as a 1-pixel divider line // Per-menu flags. #define MN_APPLE 0x0001 // this is the Apple menu (>>@); icon goes in title #define MN_ALL_DISABLED 0x0002 typedef struct { uint16_t cmdId; // unique id returned by MenuKey/MenuSelect; // also the value passed to onCmd(). // Use values >= 256 to avoid collision // with Apple menu's CDA range. const char *title; // C string ("Quit"). Builder copies // it into the byte stream verbatim. // NULL for divider items. char keyEquiv; // command-key shortcut letter (0 = none). // Upper- and lower-case forms are // emitted as the ORCA *Xx pair. uint16_t flags; // MI_* bitmask. } UiMenuItemT; typedef struct { uint16_t menuId; // Menu Manager menu ID (matches \N###). const char *title; // C string ("File"). Apple menu uses // an icon when MN_APPLE is set; // the title text is then unused. uint16_t flags; // MN_* bitmask. uint16_t numItems; const UiMenuItemT *items; } UiMenuT; // Assemble a single menu's byte stream into `outBuf`. Returns the // number of bytes written (excluding the NUL terminator some builders // expect). The output is the exact format NewMenu() expects: a // pascal-style mini-program with `>>`/`>>@` header, `--Name\N###...` // lines per item, and a final `.\r` terminator. // // outBufSize should be at least 32 + sum(strlen(item.title)+16) bytes. // The builder bails (returns 0) if it would overflow. uint16_t uiBuilderMenuBytes(const UiMenuT *spec, char *outBuf, uint16_t outBufSize); // Install a menu spec via NewMenu()+InsertMenu(). Allocates a // temporary buffer on the static heap below. Returns the MenuHandle // from NewMenu (or NULL on overflow). Pass `beforeMenuId=0` to insert // at the end of the menu bar (Menu Manager convention). void *uiBuilderInstallMenu(const UiMenuT *spec, uint16_t beforeMenuId); // Convenience: install N menus in order (left to right), then call // FixAppleMenu + FixMenuBar + DrawMenuBar. The Apple menu (if // MN_APPLE-flagged) is detected and its ID passed to FixAppleMenu. void uiBuilderInstallMenuBar(const UiMenuT *menus, uint16_t numMenus); // --------------------------------------------------------------------------- // Window builder // --------------------------------------------------------------------------- // Frame-bits convenience. Same values ORCA's window.h uses. #define UW_TITLE 0x0001 #define UW_CLOSE 0x4000 #define UW_VIS 0x0020 #define UW_MOVE 0x0080 #define UW_GROW 0x0400 #define UW_ZOOM 0x0100 #define UW_PAGE 0x0008 #define UW_INFO 0x0004 #define UW_STD_DOC (UW_TITLE | UW_CLOSE | UW_VIS | UW_MOVE) #define UW_STD_DOC_GZ (UW_STD_DOC | UW_GROW | UW_ZOOM) typedef struct { int16_t v1, h1, v2, h2; } UiRectT; typedef struct { const char *title; // C string title (NULL for untitled) uint16_t frameBits; // UW_* bitmask UiRectT position; // window screen position int16_t maxHeight; int16_t maxWidth; uint32_t refCon; void *contentDefProc; // NULL = default } UiWindowT; // Open a window from the spec. Title is converted into the Menu // Manager's pascal-counted form in a builder-managed buffer. Returns // the WindowPtr from NewWindow, or NULL on failure. void *uiBuilderOpenWindow(const UiWindowT *spec); // --------------------------------------------------------------------------- // Alert builder // --------------------------------------------------------------------------- #define UA_NORMAL 0 #define UA_STOP 1 #define UA_NOTE 2 #define UA_CAUTION 3 // Show a simple message-and-OK alert. `msg` is a C string; the // builder converts it to pascal-counted form in a scratch buffer. // Returns the item-ID picked by the user (1 for OK). uint16_t uiBuilderAlert(uint16_t kind, const char *msg); // --------------------------------------------------------------------------- // onCmd dispatch // --------------------------------------------------------------------------- typedef struct { uint16_t cmdId; void (*handler)(uint16_t cmdId); } UiCmdHandlerT; // Drop-in onMenu callback that looks up itemId in a (cmdId, handler) // table. Wire it into IigsEventCallbacksT.onMenu via: // // static void myOnMenu(uint16_t menuId, uint16_t itemId) { // uiBuilderDispatch(itemId, gCmdTable, gCmdTableLen); // } // // The handler receives the cmdId (which equals itemId here, by // convention). void uiBuilderDispatch(uint16_t cmdId, const UiCmdHandlerT *table, uint16_t tableLen); #ifdef __cplusplus } #endif #endif // IIGS_UI_BUILDER_H