192 lines
7 KiB
C
192 lines
7 KiB
C
// 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 <stdint.h>
|
|
|
|
#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
|