Open codecat opened 11 months ago
True, it should be possible to have recursive datastructure. We would need that for recursive sub-menus ( https://github.com/slint-ui/slint/issues/38 ) and maybe treeview kind.
This should be made possible:
struct Foo {
children: [Foo],
}
But also
struct Foo {
children: [{ id: string, node: Foo }]
}
But unfortunately this is not possible:
struct Bar { id: string, node: Foo }
struct Foo { children: [Bar] }
Because there is no concept of forward declaration.
Also: this is currently valid code:
struct Foo { xxx: int }
struct Foo { children: [Foo] }
And changing this to take another meaning of Foo would be a breaking change. Although I guess no-one would do that. We could make this a warning a few version before.
Just to add a voice to this issue, I've spent the past few weeks assessing slint and creating sample controls and apps. I think this is a really good framework.
I also think that this feature (the ability for a struct to self-reference/express a tree) is a make-or-break feature for this framework. If there were some kind of parallel to a Turing-completeness test for a UI framework, tree expression would be a part of the test.
Personally, I cannot build apps without this. The types of apps I build depend too much on logic-generated and recusrive visual elements. Even something as simple as creating a rich text control cannot be reasonably done without this feature.
I've never contributed to a project like slint before, but I would be happy to do so if it would get this feature rolling. I think this framework deserves it!
Depending what you're trying to do, a tree can be represented as a flatten list. (For example to build a treeview, like in cargo-ui ), or use id-like things to get the value in native code.
For example, in Slint
struct MenuItem {
text: string,
icon: image,
id: int, // could also be a string.
}
global MenuLogic {
// Given a menu's id, fetch the children for that submenu
pure callback fetch-children(int) -> [MenuItem];
}
And then the tree is held in native code and there you can have tree structure, without the need to declare a tree structure in Slint.
What is really your usecase for this feature?
@ogoffart Thanks for your response!
I actually tried exactly what you describe. What you've posted is a good way to use logic to dictate UI in slint.
The shortcoming of your example is in turning it from a flat list into a tree. I'll simplify this example for brevity:
struct MenuData {
text: string,
id: int, // could also be a string.
children: [int],
}
global MenuLogic {
// Given a menu's id, fetch the children for that submenu
pure callback fetch-children(int) -> [MenuData];
}
export component MenuItem {
in-out property <MenuData> data;
in property <int> indent: 0;
VerticalLayout {
Text {
text: data.text;
x: 10px * indent;
}
for child in data.children: MenuItem {
data: MenuLogic.fetch-children(child);
indent: root.indent + 1;
}
}
}
The above produces a compile error: unknown type MenuItem. It's the MenuItem
referenced in the for loop. That is what we need to work before slint can be used for complex UI development. That feature is needed for trees, nested menus, rich text editing and a host of other use cases.
This is not possible (which makes perfect sense):
But I think this should be possible, as it would allow us to create tree structures: