mod custom {
use flemish::props::*;
use flemish::utils;
use flemish::vdom::VirtualDom;
use flemish::vnode::{VNode, VNodeType, View};
use flemish::widgets::{IsWidget, WidgetUnion};
use fltk::{prelude::*, *};
use std::any::TypeId;
use std::cell::RefCell;
use std::marker::PhantomData;
use std::rc::Rc;
#[derive(Clone)]
struct MyFrameImpl {
f: frame::Frame,
label: Rc<RefCell<String>>,
angle: Rc<RefCell<f64>>,
}
impl MyFrameImpl {
pub fn new(x: i32, y: i32, w: i32, h: i32) -> Self {
let mut f = frame::Frame::new(x, y, w, h, None);
f.set_frame(enums::FrameType::FlatBox);
let label = Rc::new(RefCell::new(String::new()));
let label_rc = label.clone();
let angle = Rc::new(RefCell::new(0.0));
let angle_rc = angle.clone();
f.draw(move |f| {
draw::set_draw_color(enums::Color::Black);
draw::set_font(enums::Font::Courier, 18);
draw::draw_text_angled(
(*angle_rc.borrow() * 360.0) as i32,
&label_rc.borrow(),
(f.x() + f.w()) / 2,
(f.y() + f.h()) / 2,
);
});
Self { f, label, angle }
}
pub fn set_label(&mut self, l: &str) {
*self.label.borrow_mut() = l.to_string();
}
pub fn set_angle(&mut self, l: f64) {
*self.angle.borrow_mut() = l;
}
}
impl IsWidget for MyFrameImpl {
fn as_widget(&self) -> fltk::widget::Widget {
unsafe { self.f.into_widget() }
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
}
#[derive(Clone)]
pub struct MyFrame<Message> {
node_id: usize,
typ: VNodeType,
wprops: WidgetProps,
label: String,
angle: f64,
phantom: PhantomData<Message>,
}
impl<Message: 'static> MyFrame<Message> {
pub fn new(label: &str, angle: f64) -> Self {
Self {
node_id: 0,
typ: VNodeType::Other(TypeId::of::<Self>()),
wprops: WidgetProps::default(),
label: label.to_string(),
angle,
phantom: PhantomData,
}
}
}
impl<Message: Clone + 'static + Send + Sync> VNode<Message> for MyFrame<Message> {
fn node_id(&self) -> usize {
self.node_id
}
fn set_node_id(&mut self, id: usize) {
self.node_id = id;
}
fn typ(&self) -> &VNodeType {
&self.typ
}
fn wprops(&mut self) -> &mut WidgetProps {
&mut self.wprops
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
fn gprops(&mut self) -> Option<&mut GroupProps<Message>> {
None
}
fn mount(&self, dom: &VirtualDom<Message>) {
let mut f = MyFrameImpl::new(0, 0, 0, 0);
set_wprops(&mut f.f, &self.wprops);
f.set_label(&self.label);
f.set_angle(self.angle);
dom.widget_map
.borrow_mut()
.insert(self.node_id, WidgetUnion::Other(Rc::new(f)));
}
fn patch(&mut self, old: &mut View<Message>, dom: &VirtualDom<Message>) {
if self.typ != *old.typ() {
utils::subtree::replace_subtree(old, self, dom);
return;
}
let mut widget = {
let mut map = dom.widget_map.borrow_mut();
map.get_mut(&old.node_id()).cloned()
};
if let Some(WidgetUnion::Other(ref mut f)) = widget {
update_wprops(&mut f.as_widget(), old.wprops(), &self.wprops);
let old: &MyFrame<Message> = old.as_any().downcast_ref().unwrap();
let mut f = f.as_any().downcast_ref::<MyFrameImpl>().unwrap().clone();
if self.label != old.label {
f.set_label(&self.label);
}
if self.angle != old.angle {
f.set_angle(self.angle);
}
}
}
}
}
use flemish::{view::*, Settings, Subscription};
pub fn main() {
flemish::application("app", Custom::update, Custom::view)
.settings(Settings {
size: (300, 100),
resizable: true,
..Default::default()
})
.subscription(Custom::subscription)
.run();
}
#[derive(Default)]
struct Custom {
angle: f64,
}
impl Custom {
fn update(&mut self, message: i32) {
self.angle -= message as f64 / 360.0;
}
fn view(&self) -> View<i32> {
custom::MyFrame::new("Label", self.angle).view()
}
fn subscription(&self) -> Subscription<i32> {
Subscription::every(std::time::Duration::from_millis(30)).map(|_| 10)
}
}