Skip to content

$WIDGET

A specialized type for GUI components and interactive elements in Grapa applications.

Overview

$WIDGET is a data type designed for creating and managing graphical user interface components. It provides a structured way to define UI elements with properties, behaviors, and hierarchical relationships.

Basic Operations

Creation

/* Create basic widget */
button = {name:"button", type:"click", label:"Click Me"};

/* Create widget with properties */
input = {name:"input", type:"text", placeholder:"Enter text", value:""};

/* Create widget with children */
container = {name:"container", type:"div", children:[button, input]};

Addition Operations (+=)

widget = {name:"form", type:"form"};

/* Add widget with name and value */
widget += ("button", "Submit");           /* Add button widget */

/* Add widget at specific position */
widget += ("input", "text", widget[0]);   /* Add input before button */

/* Add widget with complex properties */
widget += ("label", {text:"Name:", for:"name"}, widget[1]);

Concatenation Operations (++=)

form1 = {name:"login", type:"form"};
form2 = {name:"register", type:"form"};

/* Extend widget with another widget */
form1 ++= form2;                          /* Combine form widgets */

Widget Properties

Common Properties

widget = {
    name: "my_widget",           /* Unique identifier */
    type: "button",              /* Widget type */
    label: "Click Me",           /* Display text */
    value: "default",            /* Current value */
    enabled: true,               /* Interaction state */
    visible: true,               /* Visibility state */
    style: {                     /* Styling properties */
        color: "blue",
        size: "large",
        position: "center"
    },
    events: {                    /* Event handlers */
        click: op(){/* handler */},
        change: op(){/* handler */}
    }
};

Widget Types

/* Button widgets */
button = {name:"btn", type:"button", label:"Click"};

/* Input widgets */
text_input = {name:"input", type:"text", placeholder:"Enter text"};
number_input = {name:"num", type:"number", min:0, max:100};
checkbox = {name:"check", type:"checkbox", checked:false};

/* Container widgets */
div = {name:"container", type:"div", children:[]};
form = {name:"form", type:"form", method:"POST"};
table = {name:"table", type:"table", rows:3, cols:2};

/* Display widgets */
label = {name:"label", type:"label", text:"Display text"};
image = {name:"img", type:"image", src:"path/to/image.png"};

Widget Hierarchy

Parent-Child Relationships

/* Create hierarchical widget structure */
form = {name:"main_form", type:"form"};

/* Add child widgets */
form += ("name_input", "text", {placeholder:"Enter name"});
form += ("email_input", "text", {placeholder:"Enter email"});
form += ("submit_btn", "button", {label:"Submit"});

/* Access child widgets */
name_field = form.children[0];
email_field = form.children[1];
submit_button = form.children[2];

Widget Navigation

widget = {name:"container", type:"div"};

/* Find widget by name */
button = widget.find("submit_button");

/* Find widget by type */
buttons = widget.find_all("button");

/* Get parent widget */
parent = widget.parent;

/* Get sibling widgets */
siblings = widget.siblings;

Event Handling

Event Definition

widget = {
    name: "interactive_button",
    type: "button",
    label: "Click Me",
    events: {
        click: op(event){
            "Button clicked!".echo();
            event.target.value = "Clicked";
        },
        mouseover: op(event){
            event.target.style.color = "red";
        },
        mouseout: op(event){
            event.target.style.color = "black";
        }
    }
};

Dynamic Event Binding

widget = {name:"button", type:"button", label:"Click"};

/* Bind event dynamically */
widget.bind("click", op(event){
    "Dynamic click handler".echo();
});

/* Unbind event */
widget.unbind("click");

Widget Styling

Style Properties

widget = {
    name: "styled_widget",
    type: "button",
    label: "Styled Button",
    style: {
        /* Layout */
        width: "200px",
        height: "50px",
        margin: "10px",
        padding: "5px",

        /* Appearance */
        background: "#007bff",
        color: "white",
        border: "1px solid #0056b3",
        borderRadius: "5px",

        /* Typography */
        fontSize: "16px",
        fontWeight: "bold",
        textAlign: "center",

        /* Position */
        position: "relative",
        top: "0px",
        left: "0px"
    }
};

Dynamic Styling

widget = {name:"dynamic", type:"button", label:"Dynamic"};

/* Change style properties */
widget.style.background = "red";
widget.style.color = "white";

/* Apply style class */
widget.add_class("highlighted");
widget.remove_class("highlighted");
widget.toggle_class("active");

Widget Validation

Validation Rules

input = {
    name: "email_input",
    type: "text",
    placeholder: "Enter email",
    validation: {
        required: true,
        pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
        message: "Please enter a valid email address",
        validate: op(value){
            return value.contains("@") && value.contains(".");
        }
    }
};

Validation Methods

widget = {name:"input", type:"text"};

/* Check if widget is valid */
is_valid = widget.validate();

/* Get validation errors */
errors = widget.get_errors();

/* Clear validation state */
widget.clear_validation();

Advanced Features

Widget Templates

/* Create reusable widget template */
button_template = {
    type: "button",
    style: {
        background: "#007bff",
        color: "white",
        padding: "10px 20px",
        border: "none",
        borderRadius: "5px"
    }
};

/* Use template to create widgets */
primary_btn = button_template.copy();
primary_btn.name = "primary";
primary_btn.label = "Primary Action";

secondary_btn = button_template.copy();
secondary_btn.name = "secondary";
secondary_btn.label = "Secondary Action";
secondary_btn.style.background = "#6c757d";

Widget Composition

/* Create complex widget from simpler ones */
form_widget = {
    name: "user_form",
    type: "form",
    children: [
        {name:"name_label", type:"label", text:"Name:"},
        {name:"name_input", type:"text", placeholder:"Enter name"},
        {name:"email_label", type:"label", text:"Email:"},
        {name:"email_input", type:"text", placeholder:"Enter email"},
        {name:"submit_btn", type:"button", label:"Submit"}
    ]
};

Widget Serialization

widget = {name:"my_widget", type:"button", label:"Click"};

/* Convert widget to JSON */
json_data = widget.to_json();

/* Create widget from JSON */
new_widget = widget.from_json(json_data);

/* Export widget configuration */
config = widget.export_config();

/* Import widget configuration */
widget.import_config(config);

Performance Considerations

  • Lazy Rendering: Widgets are rendered only when needed
  • Event Delegation: Efficient event handling for large widget trees
  • Memory Management: Automatic cleanup of unused widgets
  • Batch Updates: Multiple property changes are batched for performance

Integration with Other Types

Widget Arrays

/* Create array of widgets */
buttons = [
    {name:"btn1", type:"button", label:"Button 1"},
    {name:"btn2", type:"button", label:"Button 2"},
    {name:"btn3", type:"button", label:"Button 3"}
];

/* Process widgets */
buttons.map(op(widget){
    widget.style.background = "blue";
});

Widget Lists

/* Create list of widgets */
widget_list = {
    header: {name:"header", type:"header", text:"Application"},
    sidebar: {name:"sidebar", type:"nav", items:["Home", "About", "Contact"]},
    content: {name:"content", type:"main", children:[]},
    footer: {name:"footer", type:"footer", text:"Copyright 2024"}
};

See also