Compare commits
4 Commits
7bafb04a34
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 7b54aaf3c4 | |||
| 17c436d944 | |||
| a592318a6f | |||
| 796bc41752 |
@@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
ActiveData, Event, EventCtx, EventFn, EventIdCtx, EventLike, HasEvents, IdLike, LayerId,
|
ActiveData, Event, EventCtx, EventFn, EventIdCtx, EventLike, HasEvents, IdLike, LayerId,
|
||||||
WeakWidget, Widget, WidgetEventFn, WidgetId,
|
WeakWidget, WidgetEventFn, WidgetId,
|
||||||
util::{HashMap, HashSet, TypeMap},
|
util::{HashMap, HashSet, TypeMap},
|
||||||
};
|
};
|
||||||
use std::{any::TypeId, rc::Rc};
|
use std::{any::TypeId, rc::Rc};
|
||||||
@@ -24,15 +24,16 @@ impl<Rsc: HasEvents + 'static> EventManager<Rsc> {
|
|||||||
self.types.type_or_default()
|
self.types.type_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register<W: Widget + ?Sized, E: EventLike>(
|
pub fn register<I: IdLike + 'static, E: EventLike>(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: WeakWidget<W>,
|
id: I,
|
||||||
event: E,
|
event: E,
|
||||||
f: impl for<'a> WidgetEventFn<Rsc, <E::Event as Event>::Data<'a>, W>,
|
f: impl for<'a> WidgetEventFn<Rsc, <E::Event as Event>::Data<'a>, I::Widget>,
|
||||||
) {
|
) {
|
||||||
|
let i = id.id();
|
||||||
self.get_type::<E>().register(id, event, f);
|
self.get_type::<E>().register(id, event, f);
|
||||||
self.widget_to_types
|
self.widget_to_types
|
||||||
.entry(id.id())
|
.entry(i)
|
||||||
.or_default()
|
.or_default()
|
||||||
.insert(Self::type_key::<E>());
|
.insert(Self::type_key::<E>());
|
||||||
}
|
}
|
||||||
@@ -112,11 +113,11 @@ impl<Rsc: HasEvents, E: Event> Default for TypeEventManager<Rsc, E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<Rsc: HasEvents + 'static, E: Event> TypeEventManager<Rsc, E> {
|
impl<Rsc: HasEvents + 'static, E: Event> TypeEventManager<Rsc, E> {
|
||||||
fn register<W: Widget + ?Sized>(
|
fn register<I: IdLike + 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
widget: WeakWidget<W>,
|
widget: I,
|
||||||
event: impl EventLike<Event = E>,
|
event: impl EventLike<Event = E>,
|
||||||
f: impl for<'a> WidgetEventFn<Rsc, E::Data<'a>, W>,
|
f: impl for<'a> WidgetEventFn<Rsc, E::Data<'a>, I::Widget>,
|
||||||
) {
|
) {
|
||||||
let event = event.into_event();
|
let event = event.into_event();
|
||||||
self.map.entry(widget.id()).or_default().push((
|
self.map.entry(widget.id()).or_default().push((
|
||||||
@@ -124,7 +125,7 @@ impl<Rsc: HasEvents + 'static, E: Event> TypeEventManager<Rsc, E> {
|
|||||||
Rc::new(move |ctx, rsc| {
|
Rc::new(move |ctx, rsc| {
|
||||||
f(
|
f(
|
||||||
EventIdCtx {
|
EventIdCtx {
|
||||||
widget,
|
widget: WeakWidget::new(widget.id()),
|
||||||
state: ctx.state,
|
state: ctx.state,
|
||||||
data: ctx.data,
|
data: ctx.data,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::marker::Unsize;
|
use std::marker::Unsize;
|
||||||
|
|
||||||
use crate::{Widget, WeakWidget};
|
use crate::{IdLike, WeakWidget, Widget};
|
||||||
|
|
||||||
pub trait WidgetView {
|
pub trait WidgetView {
|
||||||
type Widget: Widget + ?Sized + Unsize<dyn Widget>;
|
type Widget: Widget + ?Sized + Unsize<dyn Widget>;
|
||||||
@@ -14,3 +14,11 @@ pub trait HasWidget {
|
|||||||
impl<W: Widget + Unsize<dyn Widget> + ?Sized> HasWidget for WeakWidget<W> {
|
impl<W: Widget + Unsize<dyn Widget> + ?Sized> HasWidget for WeakWidget<W> {
|
||||||
type Widget = W;
|
type Widget = W;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<WV: WidgetView> IdLike for WV {
|
||||||
|
type Widget = WV::Widget;
|
||||||
|
|
||||||
|
fn id(&self) -> super::WidgetId {
|
||||||
|
self.root().id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ My experimental attempt at a rust ui library (also my first ui library).
|
|||||||
|
|
||||||
It's currently designed around using retained data structures (widgets), rather than diffing generated trees from data like xilem or iced. This is an experiment and I'm not sure if it's a good idea or not.
|
It's currently designed around using retained data structures (widgets), rather than diffing generated trees from data like xilem or iced. This is an experiment and I'm not sure if it's a good idea or not.
|
||||||
|
|
||||||
There's a `main.rs` that runs a testing window, so you can just `cargo run` to see it working.
|
Examples are in `examples`, eg. `cargo run --example tabs`.
|
||||||
|
|
||||||
Goals, in general order:
|
Goals, in general order:
|
||||||
1. does what I want it to (text, images, video, animations)
|
1. does what I want it to (text, images, video, animations)
|
||||||
2. very easy to use ignoring ergonomic ref counting
|
2. very easy to use ignoring ergonomic ref counting
|
||||||
3. reasonably fast / efficient (a lot faster than electron, save battery life)
|
3. reasonably fast / efficient (a lot faster than electron, save battery life, try to beat iced and xilem)
|
||||||
|
|
||||||
## dev details
|
## dev details
|
||||||
|
|
||||||
|
|||||||
@@ -143,6 +143,7 @@ impl<State> UiRsc for DefaultRsc<State> {
|
|||||||
|
|
||||||
fn on_remove(&mut self, id: WidgetId) {
|
fn on_remove(&mut self, id: WidgetId) {
|
||||||
self.events.remove(id);
|
self.events.remove(id);
|
||||||
|
self.state.remove(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
use iris_core::{WidgetId, util::HashMap};
|
use iris_core::{
|
||||||
|
WidgetId,
|
||||||
|
util::{HashMap, HashSet},
|
||||||
|
};
|
||||||
use std::{
|
use std::{
|
||||||
any::{Any, TypeId},
|
any::{Any, TypeId},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
@@ -13,6 +16,7 @@ struct Key {
|
|||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct WidgetState {
|
pub struct WidgetState {
|
||||||
|
widgets: HashMap<WidgetId, HashSet<(TypeId, usize)>>,
|
||||||
counts: HashMap<(WidgetId, TypeId), usize>,
|
counts: HashMap<(WidgetId, TypeId), usize>,
|
||||||
map: HashMap<Key, Box<dyn Any>>,
|
map: HashMap<Key, Box<dyn Any>>,
|
||||||
}
|
}
|
||||||
@@ -24,16 +28,20 @@ impl WidgetState {
|
|||||||
pub fn add<T: 'static>(&mut self, id: WidgetId, data: T) -> WeakState<T> {
|
pub fn add<T: 'static>(&mut self, id: WidgetId, data: T) -> WeakState<T> {
|
||||||
let ty = TypeId::of::<T>();
|
let ty = TypeId::of::<T>();
|
||||||
let count = self.counts.entry((id, ty)).or_default();
|
let count = self.counts.entry((id, ty)).or_default();
|
||||||
let key = Key { ty, i: *count, id };
|
let i = *count;
|
||||||
|
let key = Key { ty, i, id };
|
||||||
self.map.insert(key, Box::new(data));
|
self.map.insert(key, Box::new(data));
|
||||||
|
self.widgets.entry(id).or_default().insert((ty, i));
|
||||||
*count += 1;
|
*count += 1;
|
||||||
WeakState {
|
WeakState {
|
||||||
key,
|
key,
|
||||||
_pd: PhantomData,
|
_pd: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn remove<T>(&mut self, state: WeakState<T>) {
|
pub fn remove(&mut self, id: WidgetId) {
|
||||||
self.map.remove(&state.key);
|
for &(ty, i) in self.widgets.get(&id).into_iter().flatten() {
|
||||||
|
self.map.remove(&Key { id, ty, i });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn get<T: 'static>(&self, state: WeakState<T>) -> &T {
|
pub fn get<T: 'static>(&self, state: WeakState<T>) -> &T {
|
||||||
self.map.get(&state.key).unwrap().downcast_ref().unwrap()
|
self.map.get(&state.key).unwrap().downcast_ref().unwrap()
|
||||||
|
|||||||
@@ -57,6 +57,13 @@ widget_trait! {
|
|||||||
|
|
||||||
pub trait HasTasks: Sized + HasState + HasEvents {
|
pub trait HasTasks: Sized + HasState + HasEvents {
|
||||||
fn tasks_mut(&mut self) -> &mut Tasks<Self>;
|
fn tasks_mut(&mut self) -> &mut Tasks<Self>;
|
||||||
|
|
||||||
|
fn spawn_task<F: AsyncFnOnce(TaskCtx<Self>) + 'static + std::marker::Send>(&mut self, task: F)
|
||||||
|
where
|
||||||
|
F::CallOnceFuture: Send,
|
||||||
|
{
|
||||||
|
self.tasks_mut().spawn(task);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait AsyncWidgetEventFn<Rsc: HasEvents, W: ?Sized>:
|
pub trait AsyncWidgetEventFn<Rsc: HasEvents, W: ?Sized>:
|
||||||
|
|||||||
Reference in New Issue
Block a user