orbtk
orbtk copied to clipboard
Option property values
Hi,
for an application that i'm making i need to store inside a widget an Option<T> value. I also need to set it from another widget that have a different name, so i set it using (&str,entity) "formula". Apart from the macro parsing error that come from when using "<" and ">" characters (that can be easily bypassed with type OptionT = Option<T>;, when setting the value, the compiler complain about missing implementation of IntoPropertySource for the type:
error[E0277]: the trait bound `(&str, dces::entity::Entity): orbtk_api::properties::IntoPropertySource<std::option::Option<inventory_page::item_widget::Item>>` is not satisfied
--> src/inventory_page/inventory.rs:64:47
|
64 | let display = ItemDisplay::new().item(("selected",equipment)).build(ctx);
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `orbtk_api::properties::IntoPropertySource<std::option::Option<inventory_page::item_widget::Item>>` is not implemented for `(&str, dces::entity::Entity)`
|
= help: the following implementations were found:
<(&str, &str) as orbtk_api::properties::IntoPropertySource<orbtk_api::properties::layout::scroll_viewer_mode::ScrollViewerMode>>
<(&str, dces::entity::Entity) as orbtk_api::properties::IntoPropertySource<bool>>
<(&str, dces::entity::Entity) as orbtk_api::properties::IntoPropertySource<f32>>
<(&str, dces::entity::Entity) as orbtk_api::properties::IntoPropertySource<f64>>
and 62 others
(yeah, from the code you could guess that it is a D&D-like application :-D)
Maybe there is not implementation for Option< T > (if i'm not wrong it's not possible to implement a trait for a foreign type). I don't know if i miss something. If it is not yet implemented as feature, a solution to this problem could be using the property system itself: every property is internally implemented as an Option< T >, so maybe a solution could be allowing the user to unset a property, basically adding to WidgetContainer a function like:
pub fn unset(&mut self, key: &str)
At this point there is no more need to have the ability to use Option< T > inside a widget since it is already implemented at the core. If i want to set None i only need to unset the property.
Thanks for the attention, Have a nice day
Ah D&D 😄. If you are ready and want to show it to others I'm interested in seeing what you are doing 😉.
I workaround for the Option type is to to use an alias type type MyType = Option<bool>; this should work. But I think the macro need to extended to support also complex types.
About your unset suggestion I have to think.
Thank you
About your unset suggestion I have to think.
Obviously it is a forcing and I would prefer to use another method. I'm still trying to undestand what cause that error.
If you are ready and want to show it to others I'm interested in seeing what you are doing
Sure, it's not a secret, simply i'm developing part by part and i will put all together at the end, so for now there is nothing concrete. Also i have to find first a way draw figures in a battlefield-like space. Initially i thought about using canvas to do this, but maybe i could make a widget using absolute layout and move the figures setting "bounds" property. In this way i could use the event system itself to catch the inputs instead of doing it myself (with the canvas solution). For example i could use ImageWidget to represent characters, obstacles and area effect (maybe?) and for the map itself i can simply set the map image as background (the movement of character is free, it is not based on squares. I said D&D-like to give an idea, but the core game is very different :wink:).
Hi,
i think i have found what cause that error: basically every IntoPropertySource implementations are generated by into_property_source!(type) macro and it will implement all the needed IntoPropertySource for the passed type.
Now, generally is possible to pass to Context and widget! macro any type, including Option<T> without problems. Errors come out when trying to use it where IntoPropertySource is required. There is an implementation for every primitive type, but not when wrapped into Option (there is no IntoPropertySource<Option<bool>> for example), since it is not possible to implement trait for foreign types. So when, during template function, when passing something like
MyWidget::new()
.my_option_bool_field(("other_field_name",other_entity_id))
.build()
the compiler will complain that the implementation IntoPropertySource<Optioninto_property_source! macro
impl IntoPropertySource<$type> for (String, Entity) {
fn into_source(self) -> PropertySource<$type> {
PropertySource::KeySource(self.0, self.1)
}
}
impl IntoPropertySource<$type> for (&str, Entity) {
fn into_source(self) -> PropertySource<$type> {
PropertySource::KeySource(self.0.to_string(), self.1)
}
}
with a generic implementation (outside of the macro):
impl<T: Component + Debug> IntoPropertySource<T> for (String, Entity) {
fn into_source(self) -> PropertySource<T> {
PropertySource::KeySource(self.0, self.1)
}
}
impl<T: Component + Debug> IntoPropertySource<T> for (&str, Entity) {
fn into_source(self) -> PropertySource<T> {
PropertySource::KeySource(self.0.to_string(), self.1)
}
}
In this way the generic implementation will provide IntoPropertySource for basically every type T, including foreign types like Option (probably using Vec bring the same errors and this generic implementation should also fix this).
Just to be clear, normally Option and other wrappers works when setting and getting values from Context and widget! macro generated structures without errors. The problem is when using (String, Entity) and (&str, Entity) to get shared value (like the example before). If you need i could provide an example that trigger this edge case.
Thanks for the attention, Have a nice day
Hi,
i've been testing the fix on the previous post for a while and seems to work correctly and don't cause issues on widgets. I have also noticed that, for the same reason of the Option< T >, the trait IntoPropertySource< T > is not implemented for tuples. The fix will also implement the trait for tuples since it works on generic T, that could be anything from Vec<T> to (u32,f64).
If you want i can send a PR so you can see what is exaclty changed, so you can also test this solution and then decide if merge or not. I can also attach some example that show situations that normally throw errors that this correction fix.
Thanks for the attention, Have a good day
Any update on this? I have a similar issue.
Unfortunately not yet, I have some other task to do before.