Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions docs/syntax/data-binding.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,97 @@ Explanation of complex bindings:
Note: The `lv_obj-` prefix can be omitted. For example, you can simply
write `bind_state_if_gt` instead.

### Choosing the right attribute

`bind_flag_*` and `bind_state_*` look almost identical but expect a different attribute and a different set of values:

- `bind_flag_*` toggles a widget **flag** — use the `flag` attribute.
- `bind_state_*` toggles a widget **state** — use the `state` attribute.

```xml
<!-- Set the "hidden" flag while subject_mode != 1 -->
<lv_obj bind_flag_if_not_eq="subject_mode" flag="hidden" ref_value="1"/>
Comment thread
kisvegabor marked this conversation as resolved.
Outdated

<!-- Enter the "checked" state while subject_lamp == 2 -->
<lv_button bind_state_if_eq="subject_lamp" state="checked" ref_value="2"/>
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
Outdated
Comment thread
kisvegabor marked this conversation as resolved.
Outdated
```

### Valid state values

These match LVGL's `LV_STATE_*` constants. The same names are used as style selectors and in `bind_state_*` bindings.

| Value | Meaning |
|---|---|
| `default` | Widget is in its base state |
| `checked` | Widget is toggled on (e.g. a checkable button) |
| `focused` | Widget has focus from any input device |
| `focus_key` | Widget has focus from a keypad/encoder |
| `edited` | Widget is being edited (e.g. encoder edit mode) |
| `hovered` | Pointer is over the widget |
| `pressed` | Widget is currently pressed |
| `scrolled` | Widget is being scrolled |
| `disabled` | Widget rejects input |

### Valid flag values

The most commonly bound `LV_OBJ_FLAG_*` flags, exposed by the same names without the prefix:

| Value | Effect when set |
|---|---|
| `hidden` | Widget is not drawn and ignores input |
| `clickable` | Widget can be pressed/clicked |
| `checkable` | Click toggles the `checked` state |
| `scrollable` | Widget can be scrolled |
| `scroll_on_focus` | Parent scrolls so the focused child is visible |
| `floating` | Excluded from the parent's layout |
| `ignore_layout` | Ignored by the parent's layout |

For the full list of states and flags see LVGL's [Object basics](https://lvgl.io/docs/open/intro/basics) and [Style states](https://lvgl.io/docs/open/main-modules/style#states) reference.

## Selection groups via a shared subject

A common pattern is to express "exactly one of these widgets is active" with a single integer subject and one `ref_value` per option. Combining `subject_set_int_event` (writes the subject on click) with `bind_state_if_eq` (reads it to drive the `checked` state) produces a runtime-driven radio group with no application code.

```xml
<!-- globals.xml -->
<subjects>
<int name="subject_lamp" value="0"/>
</subjects>
```

```xml
<!-- lamp_cell.xml — one cell instantiated per option -->
<component>
<api>
<prop name="label" type="string" default="Lamp"/>
<prop name="ref_value" type="int" default="0"/>
</api>

<view extends="lv_obj" width="content" height="content" flex_flow="column">
<lv_label text="$label"/>

<lv_button style_bg_color-checked="0xed7d31">
<lv_image src="img_lightbulb"/>

<!-- Read: this button is checked iff subject_lamp == ref_value -->
<bind_state_if_eq subject="subject_lamp" state="checked" ref_value="$ref_value"/>

<!-- Write: clicking this button stores ref_value in subject_lamp -->
<subject_set_int_event subject="subject_lamp" trigger="clicked" value="$ref_value"/>
</lv_button>
</view>
</component>
```

```xml
<!-- screen — each cell carries a unique ref_value -->
<lamp_cell label="Lamp 1" ref_value="0"/>
<lamp_cell label="Lamp 2" ref_value="1"/>
<lamp_cell label="Lamp 3" ref_value="2"/>
```

When the user taps a cell, `subject_lamp` is written to that cell's `ref_value`; every other cell's `bind_state_if_eq` re-evaluates and drops out of the `checked` state automatically. The same subject can also be set from C (`lv_subject_set_int(&subject_lamp, …)`) to drive the selection from application code.

## Subject Related Events

Besides binding properties to subjects, it's also possible to add
Expand Down
16 changes: 15 additions & 1 deletion docs/syntax/fonts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ Right now the 3 Font engines are supported:
2. `<tiny_ttf>` - Parse the TTF files and render the bitmaps at runtime in the required size. Works on MCUs too.
3. `<freetype>` - Also renders from TTF files but it's design for MPUs

### Path Resolution

All `src_path` values are **relative to the project root** — the folder that contains `project.xml` and `globals.xml`. So `src_path="fonts/Montserrat-Regular.ttf"` refers to `<project_root>/fonts/Montserrat-Regular.ttf` on disk.

When you export C code and load fonts as files (`as_file="true"`), the runtime needs to know where those files actually live on the target. This is handled by the path you pass to the project's init function:

```c
my_ui_init("A:my_ui/v2.3/assets");
```

The init function concatenates this base with each `src_path`, so `src_path="fonts/Montserrat-Regular.ttf"` resolves at runtime to `"A:my_ui/v2.3/assets/fonts/Montserrat-Regular.ttf"`. Fonts compiled as **data** (`as_file="false"`) are embedded in the firmware and ignore this path entirely.

See [Using Exported C Code](../integration/using-exported-c-code#initialization-and-setup) for the full init flow.

### As Data

The Editor can convert the TTF files to C array that can be compiled into the firmware. To use the fonts as C array set `as_file="false"`.
Expand Down Expand Up @@ -49,7 +63,7 @@ For example:
```xml
<globals>
<fonts>
<bin as_file="true" name="medium" src="path/to/file.ttf" range="0x20-0x7f" symbols="°" size="24"/>
<bin as_file="true" name="medium" src_path="path/to/file.ttf" range="0x20-0x7f" symbols="°" size="24"/>

<tiny_ttf as_file="true" name="big" src_path="path/to/file.ttf" range="0x20-0x7f" size="48"/>
</fonts>
Expand Down
16 changes: 15 additions & 1 deletion docs/syntax/images.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,21 @@ names.
## Registering Images


In order to use images in the Editor add your PNG images in the `images` folder of your project, and list them in an `<images>` block in `globals.xml`. Note that only PNG files are supported at this moment.
In order to use images in the Editor add your PNG images in the `images` folder of your project, and list them in an `<images>` block in `globals.xml`. Note that only PNG files are supported at this moment.

### Path Resolution

All `src_path` values are **relative to the project root** — the folder that contains `project.xml` and `globals.xml`. So `src_path="images/logo.png"` refers to `<project_root>/images/logo.png` on disk.

When you export C code and load images as files (`<file>` entries), the runtime needs to know where those files actually live on the target. This is handled by the path you pass to the project's init function:

```c
my_ui_init("A:my_ui/v2.3/assets");
```

The init function concatenates this base with each `src_path`, so `src_path="images/logo.png"` resolves at runtime to `"A:my_ui/v2.3/assets/images/logo.png"`. Images registered as **data** (`<data>` entries) are compiled into the firmware and ignore this path entirely.

See [Using Exported C Code](../integration/using-exported-c-code#initialization-and-setup) for the full init flow.

### As Data

Expand Down
8 changes: 8 additions & 0 deletions docs/syntax/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ This section covers everything from basic building blocks to advanced styling an
>
Explore XML syntax rules, element structure, attributes, and best practices for writing clean UI definitions.
</Card>

<Card
icon={<Settings />}
href="./project"
title="Project File"
>
Configure `project.xml` with the LVGL version, exported project name, and display targets used to preview screens.
</Card>
</Cards>

## UI Elements
Expand Down
3 changes: 2 additions & 1 deletion docs/syntax/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"---Understanding XML---",
"introduction",
"overview",

"project",

"---UI Elements---",
"components",
"widgets",
Expand Down
11 changes: 11 additions & 0 deletions docs/syntax/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ In XML files, fonts, images, styles, and other assets are referenced by name, no
<style name="red" bg_color="0xff0000"/>
```

The same names can also be used as `<prop>` types so a Component can accept an asset as a parameter. The values are resolved against items registered in `globals.xml`:

| Type | Looks up | Example |
|---|---|---|
| **image** | An image registered under `<images>` | `<prop name="src" type="image" default="img_power"/>` |
| **font** | A font registered under `<fonts>` | `<prop name="title_font" type="font" default="montserrat_22"/>` |
| **subject** | A subject registered under `<subjects>` | `<prop name="subject" type="subject" default="subject_dimmer1"/>` |
| **style** | A style defined in `<styles>` or `globals.xml` | `<prop name="extra_style" type="style"/>` |

These props are typically forwarded into a child element with the `$` prefix, e.g. `<lv_image src="$src"/>` or `<lv_slider bind_value="$subject"/>`.

**Automatic binding** occurs for:
- Styles, fonts, images, animations
- Gradients and other visual components
Expand Down
64 changes: 64 additions & 0 deletions docs/syntax/project.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
title: Project File
description: Configure your LVGL Pro project with project.xml — set the LVGL version, exported code name, and the display targets used to preview screens.
---

`project.xml` is the top-level configuration file of an LVGL Pro project. It is read by the Editor, by the CLI, and by the runtime XML loader to learn the target LVGL version, the exported code's name, and the display configurations used to render screens in the preview.

`project.xml` lives next to `globals.xml` at the root of the project folder.

## Recommended Project Layout

LVGL Pro doesn't enforce a folder structure, but the Editor, the tutorials, and the example projects all follow the same convention. Sticking to it keeps `src_path` references short and makes generated code predictable.

```
my_project/
├── project.xml ← target/display configuration (this file)
├── globals.xml ← shared fonts, images, subjects, consts, styles
├── translations.xml ← optional, multi-language strings
├── fonts/ ← .ttf / .bin source files referenced by globals.xml
├── images/ ← .png assets referenced by globals.xml
├── widgets/ ← custom <widget> XMLs (one file per widget)
├── components/ ← reusable <component> XMLs (one file per component)
└── screens/ ← <screen> XMLs (one file per screen)
```

The three XML files (`project.xml`, `globals.xml`, `translations.xml`) sit at the project root; the five sub-folders hold everything else. Any of the sub-folders can be omitted if the project doesn't use that category.

## Minimal Example

The simplest valid project file just declares the LVGL version:

```xml
<project lvgl_version="9.5.0">
</project>
```

This is enough for the Editor to load the project, but no preview targets are defined — screens fall back to a default preview size.

## Defining Display Targets

To preview Screens at the resolution(s) of the real hardware, declare one or more `<target>` elements inside `<targets>`. Each target contains a `<display>` describing the screen size.

```xml
<project lvgl_version="9.5.0">
<targets>
<target name="dashboard_large">
<display width="800" height="480"/>
</target>
<target name="controller_small">
<display width="480" height="320"/>
</target>
</targets>
</project>
```

When a Screen is open in the Editor, the Preview panel shows one entry per `<target>`. This is also how the Editor knows how to size a Screen's `<view>` when `width="100%"` or `height="100%"` is used at the screen root.

All Screens see all targets — there is no per-screen targeting.

## Relation to Other Files

- **`globals.xml`** — Defines project-wide fonts, images, subjects, constants, and shared styles. See [Introduction](./introduction#shared-resources-with-globalsxml).
- **Screens** — Use the targets declared here to choose a preview resolution. See [Screens](./screens#preview).
- **Code export** — The `name` attribute controls the exported project name and init function. See [Using Exported C Code](../integration/using-exported-c-code).
Loading