slint
slint copied to clipboard
Introduce a project configuration file
We identified that having a project file that's understood by the tooling around Slint would have several benefits to support larger scale projects by centralising settings in a well-defined location.
This issue proposes to introduce slint.project.json as a configuration file
File Format
The file format shall be JSON with the extension of supporting comments.
Location
The file shall be read by the Slint compiler, the preview tool as well as by the LSP implementation. When loading a .slint file in order to compile the entry component as instructed, the tools shall look in the directory of the .slint file and in the directory hierarchy upwards for a slint.project.json file. In the case of the slint::slint! macro in the Rust integration, the starting point for the lookup shall be the CARGO_MANIFEST_DIR.
Purpose
Initially the file shall allow configuring the following settings:
- The default style to be used.
- A list of include search paths for .slint files.
- A list of file paths to custom fonts to load (replaces
import "foo.ttf"syntax) - The version of Slint the .slint files are intended to be compatible with.
- The license of Slint selected by the user.
This could also be extended in the future to allow defining an entry point, so that tools like the preview tool could be pointed to a slint.project.json file.
Priority
Some of these settings are also configurable through different means, such as the style with the SLINT_STYLE environment variable. The order of priority shall be from lowest to highest priority:
- Environment variables
slint.project.jsonvalue- API / Command line option
Schema
A schema shall be provided, which allows for the validation of the project settings file and code completion in IDEs
The proposed initial schema is:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://slint.dev/slint.project.schema.json",
"title": "Slint Project Settings",
"description": "Various configurable settings when using Slint with .slint files",
"type": "object",
"properties": {
"style": {
"description": "The style to use when loading and rendering the UI",
"type": "string"
},
"includes": {
"description": "A list of include search paths, relative to the slint.project.json file",
"type": "array",
"items": {
"type": "string",
}
},
"fonts": {
"description": "A list of file paths to font files, relative to the slint.project.json file",
"type": "array",
"items": {
"type": "string",
}
},
"version": {
"description": "The Slint version number the project files are intended to be compatible with",
"type": "string",
}
}
}
Other things that the project file could contains:
- Some target information that could be overriden for specific targets
- screen size
- pixel format (relevant for MCU)
- scale factor
- which unicode coverage for each font / size to embedded as pixmap
Additional features that could be configured are per-image properties, such as whether an image should be compressed (png, etc.) or be stored raw (as texture).
I'd like to have license information and a pointer to the root components of all slint UIs so that people do not need to search for those in between all the source code.
I am thinking along the lines of what Cargo does: One file per "project" to define the settings needed for each UI and an optional "workspace" to combine several UI files.
I was also thinking to use toml, so we optionally piggy-back on Cargo.toml. If there is a slint-project.toml file, then we use that. If not, we parse Cargo.toml and extract our settings from there.
Per-UI I am suggesting this set of settings for a start, all in a [slint.package] section:
versionof slint (with a fallback to get that from Cargo.toml dependencies).licenseof slint (fallback to the license in Cargo.toml if we can trivially match it)library_path,include_pathandstyle
This will then be shared for all UIs created in the project.
We also need a way to define sub-UIs in a project. I would again follow cargo here and go for just scanning the ui folder following the same rules (and overwrites) as Cargo does for examples and such:
[[slint.ui]]
path = "ui/main.slint`
library_path = [ { name = "@something", path = "./something" } ]
[[slint.ui]]
path = "foo/bar.slint"
style = "fluent-dark"
For the workspace file I'd suggest to start with the Cargo.toml layout, so that we do not need to keep a very similar list of child projects in two locations. We expect either a slint-project.toml or a Cargo.toml file with a [slint.package] section in the workspace.members folders or we ignore the folder in slint.
If the project is not Cargo based, we can set up a hierarchy of slint-project.toml files manually.
If you do put config in the Cargo.toml, it should go under (workspace|package).metadata.slint: https://doc.rust-lang.org/cargo/reference/manifest.html#the-metadata-table
@wetheredge: Very good point :-)