|
use std::collections::HashSet; |
|
use std::cell::RefCell; |
|
use std::rc::Rc; |
|
|
|
struct WidgetRef(Rc<RefCell<Box<Widget>>>); |
|
|
|
impl WidgetRef { |
|
fn new(inner: Rc<RefCell<Box<Widget>>>) -> Self { |
|
WidgetRef(inner) |
|
} |
|
|
|
fn pointer_usize(&self) -> usize { |
|
&(*(&self.0).borrow()) as *const _ as usize |
|
} |
|
} |
|
|
|
impl std::cmp::PartialEq for WidgetRef { |
|
fn eq(&self, other: &Self) -> bool { |
|
self.pointer_usize() == other.pointer_usize() |
|
} |
|
} |
|
|
|
impl std::cmp::Eq for WidgetRef {} |
|
|
|
impl std::hash::Hash for WidgetRef { |
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { |
|
self.pointer_usize().hash(state); |
|
} |
|
} |
|
|
|
impl std::ops::Deref for WidgetRef { |
|
type Target = Rc<RefCell<Box<Widget>>>; |
|
fn deref(&self) -> &Self::Target { |
|
&self.0 |
|
} |
|
} |
|
|
|
trait Widget { |
|
fn update(&mut self); |
|
fn draw(&self); |
|
} |
|
|
|
struct Button; |
|
struct TextBox; |
|
|
|
impl Widget for Button { |
|
fn update(&mut self) { |
|
println!("Updating button"); |
|
} |
|
|
|
fn draw(&self) { |
|
println!("Drawing button"); |
|
} |
|
} |
|
|
|
impl Widget for TextBox { |
|
fn update(&mut self) { |
|
println!("Updating textbox"); |
|
} |
|
|
|
fn draw(&self) { |
|
println!("Drawing textbox"); |
|
} |
|
} |
|
|
|
fn main() { |
|
let button = Rc::new(RefCell::new(Box::new(Button) as Box<Widget>)); |
|
let text_box = Rc::new(RefCell::new(Box::new(TextBox) as Box<Widget>)); |
|
|
|
let mut widgets = HashSet::new(); |
|
widgets.insert(WidgetRef::new(button.clone())); |
|
widgets.insert(WidgetRef::new(text_box.clone())); |
|
|
|
for mut w in widgets.iter().map(|w| w.borrow_mut()) { |
|
w.update(); |
|
w.draw(); |
|
} |
|
|
|
widgets.remove(&WidgetRef::new(button.clone())); |
|
println!("------------"); |
|
|
|
for mut w in widgets.iter().map(|w| w.borrow_mut()) { |
|
w.update(); |
|
w.draw(); |
|
} |
|
} |