flemish 0.7.0

An Elmish architecture for fltk-rs
Documentation
use crate::id::next_id;
use crate::image::Image;
use crate::props::*;
use crate::vdom::VirtualDom;
use fltk::enums;
use std::any::Any;

#[derive(Clone, Debug, PartialEq)]
pub enum VNodeType {
    Column,
    Row,
    Button,
    Frame,
    Input,
    MenuBar,
    RadioButton,
    ToggleButton,
    RoundButton,
    CheckButton,
    LightButton,
    RepeatButton,
    RadioLightButton,
    RadioRoundButton,
    ReturnButton,
    ShortcutButton,
    Group,
    Pack,
    HorPack,
    Tabs,
    Scroll,
    Tile,
    Wizard,
    ColorChooser,
    Window,
    Grid,
    TextDisplay,
    TextEditor,
    IntInput,
    FloatInput,
    MultilineInput,
    SecretInput,
    FileInput,
    Output,
    MultilineOutput,
    Choice,
    SysMenuBar,
    MenuButton,
    Slider,
    NiceSlider,
    ValueSlider,
    Dial,
    LineDial,
    Counter,
    Scrollbar,
    HorScrollbar,
    Roller,
    Adjuster,
    ValueInput,
    ValueOutput,
    FillSlider,
    FillDial,
    HorSlider,
    HorFillSlider,
    HorNiceSlider,
    HorValueSlider,
    Browser,
    SelectBrowser,
    HoldBrowser,
    MultiBrowser,
    FileBrowser,
    CheckBrowser,
    Spinner,
    Clock,
    Chart,
    Progress,
    InputChoice,
    HelpView,
    Table,
    TableRow,
    SmartTable,
    Tree,
    Other(std::any::TypeId),
}

pub trait HasProps<Message> {
    fn label(self, label: &str) -> Self;
    fn fixed(self, sz: i32) -> Self;
    fn color(self, col: enums::Color) -> Self;
    fn boxtype(self, boxtype: enums::FrameType) -> Self;
    fn selection_color(self, v: enums::Color) -> Self;
    fn label_color(self, v: enums::Color) -> Self;
    fn label_font(self, v: enums::Font) -> Self;
    fn label_size(self, v: i32) -> Self;
    fn tooltip(self, v: &str) -> Self;
    fn align(self, v: enums::Align) -> Self;
    fn when(self, v: enums::CallbackTrigger) -> Self;
    fn visible(self, v: bool) -> Self;
    fn deactivate(self, v: bool) -> Self;
    fn x(self, x: i32) -> Self;
    fn y(self, x: i32) -> Self;
    fn w(self, x: i32) -> Self;
    fn h(self, x: i32) -> Self;
    fn image(self, i: Option<Image>) -> Self;
    fn deimage(self, i: Option<Image>) -> Self;
}

impl<Message: 'static, W: VNode<Message>> HasProps<Message> for W {
    fn label(mut self, label: &str) -> Self {
        self.wprops().label = Some(label.to_string());
        self
    }
    fn fixed(mut self, sz: i32) -> Self {
        self.wprops().fixed = Some(sz);
        self
    }
    fn color(mut self, col: enums::Color) -> Self {
        self.wprops().color = Some(col);
        self
    }
    fn boxtype(mut self, boxtype: enums::FrameType) -> Self {
        self.wprops().boxtype = Some(boxtype);
        self
    }
    fn selection_color(mut self, v: enums::Color) -> Self {
        self.wprops().selection_color = Some(v);
        self
    }
    fn label_color(mut self, v: enums::Color) -> Self {
        self.wprops().label_color = Some(v);
        self
    }
    fn label_font(mut self, v: enums::Font) -> Self {
        self.wprops().label_font = Some(v);
        self
    }
    fn label_size(mut self, v: i32) -> Self {
        self.wprops().label_size = Some(v);
        self
    }
    fn tooltip(mut self, v: &str) -> Self {
        self.wprops().tooltip = Some(v.to_string());
        self
    }
    fn align(mut self, v: enums::Align) -> Self {
        self.wprops().align = Some(v);
        self
    }
    fn when(mut self, v: enums::CallbackTrigger) -> Self {
        self.wprops().when = Some(v);
        self
    }
    fn visible(mut self, v: bool) -> Self {
        self.wprops().visible = Some(v);
        self
    }
    fn deactivate(mut self, v: bool) -> Self {
        self.wprops().deactivate = Some(v);
        self
    }
    fn x(mut self, x: i32) -> Self {
        self.wprops().x = Some(x);
        self
    }
    fn y(mut self, x: i32) -> Self {
        self.wprops().y = Some(x);
        self
    }
    fn w(mut self, x: i32) -> Self {
        self.wprops().w = Some(x);
        self
    }
    fn h(mut self, x: i32) -> Self {
        self.wprops().h = Some(x);
        self
    }
    fn image(mut self, i: Option<Image>) -> Self {
        self.wprops().image = i;
        self
    }
    fn deimage(mut self, i: Option<Image>) -> Self {
        self.wprops().deimage = i;
        self
    }
}

pub type View<Message> = Box<dyn VNode<Message>>;

pub trait VNode<Message: 'static>: Any + dyn_clone::DynClone {
    fn node_id(&self) -> usize;
    fn set_node_id(&mut self, id: usize);
    fn typ(&self) -> &VNodeType;
    fn wprops(&mut self) -> &mut WidgetProps;
    fn as_any(&self) -> &dyn Any;
    fn as_any_mut(&mut self) -> &mut dyn Any;
    fn gprops(&mut self) -> Option<&mut GroupProps<Message>>;
    fn mount(&self, dom: &VirtualDom<Message>);
    fn patch(&mut self, old: &mut View<Message>, dom: &VirtualDom<Message>);
    fn view(self) -> View<Message>
    where
        Self: Sized,
    {
        Box::new(self)
    }
    fn assign_ids_topdown(&mut self) {
        self.set_node_id(next_id());

        if let Some(gprops) = self.gprops().as_mut() {
            for child in &mut gprops.children {
                child.assign_ids_topdown()
            }
        }
    }
}

impl<Message> std::clone::Clone for View<Message> {
    fn clone(&self) -> Self {
        dyn_clone::clone_box(&**self)
    }
}