// ideDesigner.h -- DVX BASIC form designer // // Design-time data model and design surface for visual form editing. // Controls are stored as pure data (not live widgets) and rendered // onto a Canvas widget. The designer reads and writes .frm files. #ifndef IDE_DESIGNER_H #define IDE_DESIGNER_H #include "dvxApp.h" #include "dvxWgt.h" #include "canvas/canvas.h" #include "stb_ds_wrap.h" #include #include // ============================================================ // Limits // ============================================================ #define DSGN_MAX_NAME 32 #define DSGN_MAX_TEXT 256 #define DSGN_MAX_PROPS 32 #define DSGN_GRID_SIZE 8 #define DSGN_HANDLE_SIZE 6 // ============================================================ // Design-time property (stored as key=value strings) // ============================================================ typedef struct { char name[DSGN_MAX_NAME]; char value[DSGN_MAX_TEXT]; } DsgnPropT; // ============================================================ // Design-time menu item (flat array with level for tree structure) // ============================================================ typedef struct { char caption[DSGN_MAX_TEXT]; // "&File", "-" for separator char name[DSGN_MAX_NAME]; // "mnuFile" int32_t level; // 0 = top-level menu, 1 = item, 2+ = submenu bool checked; bool enabled; // default true } DsgnMenuItemT; // ============================================================ // Design-time control // ============================================================ typedef struct { char name[DSGN_MAX_NAME]; char typeName[DSGN_MAX_NAME]; char parentName[DSGN_MAX_NAME]; // empty = top-level (child of form) int32_t index; // control array index (-1 = not in array) int32_t left; int32_t top; int32_t width; int32_t height; int32_t maxWidth; // 0 = no cap (stretch to fill) int32_t maxHeight; // 0 = no cap (stretch to fill) int32_t weight; // layout weight (0 = fixed size, >0 = share extra space) DsgnPropT props[DSGN_MAX_PROPS]; int32_t propCount; WidgetT *widget; // live widget (created at design time for WYSIWYG) } DsgnControlT; // ============================================================ // Design-time form // ============================================================ typedef struct { char name[DSGN_MAX_NAME]; char caption[DSGN_MAX_TEXT]; int32_t width; int32_t height; int32_t left; // initial X position (0 = default) int32_t top; // initial Y position (0 = default) char layout[DSGN_MAX_NAME]; // "VBox" or "HBox" (contentBox type) bool centered; // true = center on screen, false = use left/top bool autoSize; // true = dvxFitWindow, false = use width/height bool resizable; // true = user can resize at runtime DsgnControlT *controls; // stb_ds dynamic array DsgnMenuItemT *menuItems; // stb_ds dynamic array (NULL if no menus) bool dirty; WidgetT *contentBox; // VBox parent for live widgets char *code; // BASIC code section (malloc'd, after End block) } DsgnFormT; // ============================================================ // Active tool // ============================================================ // // Empty string = pointer (select/move) mode. // Non-empty = basName of the widget type to place. #define DSGN_TOOL_NONE "" // pointer mode // ============================================================ // Grab handle IDs // ============================================================ typedef enum { HANDLE_NONE = -1, HANDLE_E = 0, // resize width HANDLE_S, // resize height HANDLE_SE, // resize both HANDLE_COUNT = 3 } DsgnHandleE; // ============================================================ // Interaction mode // ============================================================ typedef enum { DSGN_IDLE, DSGN_REORDERING, // dragging control up/down in the VBox DSGN_RESIZING } DsgnModeE; // ============================================================ // Designer state // ============================================================ typedef struct { DsgnFormT *form; int32_t selectedIdx; // -1 = form itself selected char activeTool[DSGN_MAX_NAME]; // "" = pointer, else basName to place DsgnModeE mode; DsgnHandleE activeHandle; int32_t dragStartY; // mouse Y at drag start (for reorder) int32_t dragOrigWidth; // widget size at resize start int32_t dragOrigHeight; int32_t dragStartX; // mouse X at resize start WindowT *formWin; AppContextT *ctx; const char *projectDir; // project directory (for resolving relative paths) } DsgnStateT; // ============================================================ // API // ============================================================ // Initialize designer state. void dsgnInit(DsgnStateT *ds, AppContextT *ctx); // Set the canvas overlay widget (for grab handles). void dsgnSetCanvas(DsgnStateT *ds, WidgetT *canvas); // Create live widgets for all controls in the form. // Call after dsgnLoadFrm or dsgnNewForm, with the form window's contentBox. void dsgnCreateWidgets(DsgnStateT *ds, WidgetT *contentBox); // Load a .frm file into the designer. bool dsgnLoadFrm(DsgnStateT *ds, const char *source, int32_t sourceLen); // Save the designer form to .frm text format. // Returns the number of bytes written (excluding null), or -1 on error. int32_t dsgnSaveFrm(const DsgnStateT *ds, char *buf, int32_t bufSize); // Create a new blank form. void dsgnNewForm(DsgnStateT *ds, const char *name); // Repaint the design surface. void dsgnPaint(DsgnStateT *ds); // Draw selection handles over the painted window surface. void dsgnPaintOverlay(DsgnStateT *ds, int32_t winX, int32_t winY); // Handle mouse click on the design surface. void dsgnOnMouse(DsgnStateT *ds, int32_t x, int32_t y, bool drag); // Handle key press in design view. void dsgnOnKey(DsgnStateT *ds, int32_t key); // Get the name of the selected control (or form name if nothing selected). const char *dsgnSelectedName(const DsgnStateT *ds); // Get the default event name for a control type. const char *dsgnDefaultEvent(const char *typeName); // Auto-generate a unique control name for the given type. void dsgnAutoName(const DsgnStateT *ds, const char *typeName, char *buf, int32_t bufSize); // Check if a control type is a container (can hold children). bool dsgnIsContainer(const char *typeName); // Free designer resources. void dsgnFree(DsgnStateT *ds); // Create a live design-time widget for a given VB type name. WidgetT *dsgnCreateDesignWidget(const char *vbTypeName, WidgetT *parent); // Build a display-only menu bar on a window from the form's menuItems. // Used in the form designer to preview the menu layout. void dsgnBuildPreviewMenuBar(WindowT *win, const DsgnFormT *form); // ============================================================ // Code rename support (implemented in ideMain.c) // ============================================================ // // Rename all references to a form or control in project .bas files. // Replaces OldName. -> NewName. and OldName_ -> NewName_ (case-insensitive, // word-boundary aware). Also handles FormName.ControlName. patterns. void ideRenameInCode(const char *oldName, const char *newName); #endif // IDE_DESIGNER_H