Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reference-counted AreaHandlers for interactive canvas scenarios #118

Open
shankuniyogi opened this issue Apr 23, 2022 · 1 comment
Open

Comments

@shankuniyogi
Copy link

I'm using this library to implement widgets for a STEM toolkit I'm building. It's perfect, super simple, and has just what I need. Thank you!

Some of my components require both custom painting and interaction, but when I started to use Area and AreaHandler, I ran into some limitations. The AreaHandler object passed into Area::new is boxed, and there's no way to access that object from a reference to an Area, so its state can't be changed after the area is created.

let meter = Box::new(Meter { value: 100.0 });
let area = Area::new(&ui, meter);
// Can't change it anymore!
meter = 50.0;

In my fork, I've modified area.rs to also support reference-counted handlers (Rc<RefCell<dyn AreaHandler>>).

let meter = Rc::new(RefCell:new(Meter { value: 100.0 }));
let area = Area::new(&ui, meter.clone());
// Can change this any time.
meter.borrow_mut().value = 50.0;
area.queue_redraw_all(&ui);

The change still supports boxed handlers, and requires no changes to existing code - the existing canvas example runs perfectly - but I've also created a new example that shows how to build an interactive canvas with a ref-counted handler. The handler also implements a changed event that can be hooked by the application. In effect, someone could use this technique to build simple controls on top of an Area.

Would you be interested in a PR to add this change? I'd be happy to do the work to get it PR-ready.

Thanks again for this project!

@duffrecords
Copy link

Here's an idea for anyone in need of an immediate workaround. What I do is create a Tokio watch channel and pass the receiver half of the channel as a parameter in the new Area. Then I can update it through the sender half at any time. I spawn any tasks that need to run independently of the UI and then run a main loop that repeatedly evaluates a Tokio select macro. It has a branch for receiving state from each spawned task and a default branch that sleeps asynchronously for a few milliseconds and sends these updates to the Area before calling queue_redraw_all().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants