226 lines
8.7 KiB
C
226 lines
8.7 KiB
C
// 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 <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
// ============================================================
|
|
// Limits
|
|
// ============================================================
|
|
|
|
#define DSGN_MAX_NAME 32
|
|
#define DSGN_MAX_TEXT 256
|
|
#define DSGN_MAX_PROPS 32
|
|
#define DSGN_MAX_FRM_NESTING 16
|
|
#define DSGN_GRID_SIZE 8
|
|
#define DSGN_HANDLE_SIZE 6
|
|
#define DSGN_MENU_ID_BASE 20000 // base ID for designer preview menu items
|
|
|
|
// ============================================================
|
|
// 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 radioCheck; // true = radio bullet instead of checkmark
|
|
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 array of heap-allocated pointers
|
|
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);
|
|
|
|
// Create a layout container (VBox/HBox/WrapBox) from a layout name string.
|
|
// For VBox, reuses the root directly. For HBox/WrapBox, creates a child.
|
|
WidgetT *dsgnCreateContentBox(WidgetT *root, const char *layout);
|
|
|
|
// Create and configure a window from form properties.
|
|
// Shared by the designer and runtime to ensure consistent behavior.
|
|
// Creates the window, widget root, and layout container (VBox/HBox/WrapBox).
|
|
// Applies sizing (autoSize or explicit) and positioning (centered or explicit).
|
|
// On success, sets *outRoot and *outContentBox and returns the window.
|
|
// On failure, returns NULL.
|
|
WindowT *dsgnCreateFormWindow(AppContextT *ctx, const char *title, const char *layout, bool resizable, bool centered, bool autoSize, int32_t width, int32_t height, int32_t left, int32_t top, WidgetT **outRoot, WidgetT **outContentBox);
|
|
|
|
// ============================================================
|
|
// 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
|