1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#![deny(warnings)]
use ultron::editor;
use ultron::editor::Editor;
use ultron::sauron::jss::jss;
use ultron::sauron::prelude::*;
use ultron::sauron::wasm_bindgen::JsCast;
use ultron::sauron::Window;

#[derive(Debug, Clone)]
pub enum Msg {
    WindowScrolled((i32, i32)),
    EditorMsg(editor::Msg),
    Keydown(web_sys::KeyboardEvent),
    Mouseup(i32, i32),
    Mousedown(i32, i32),
    Mousemove(i32, i32),
    NoOp,
}

pub struct App {
    editor: Editor<Msg>,
}

impl App {
    pub fn new() -> Self {
        let content = include_str!("../test_data/hello.rs");
        //let content = include_str!("../test_data/svgbob.md");
        App {
            editor: Editor::from_str(&content, "rust"),
        }
    }
}

impl Application<Msg> for App {
    fn init(&mut self) -> Cmd<Self, Msg> {
        Window::add_event_listeners(vec![
            on_scroll(Msg::WindowScrolled),
            //on_mousemove(|me| Msg::Mousemove(me.client_x(), me.client_y())),
            //on_mousedown(|me| Msg::Mousedown(me.client_x(), me.client_y())),
            on_mouseup(|me| Msg::Mouseup(me.client_x(), me.client_y())),
            on("keydown", |event| {
                let event = event.as_web().expect("must be a web event");
                let ke: KeyboardEvent = event
                    .clone()
                    .dyn_into()
                    .expect("unable to cast to keyboard event");
                if ke.key() == "Tab" {
                    event.prevent_default();
                    event.stop_propagation();
                    Msg::Keydown(ke.clone());
                }
                Msg::NoOp
            }),
        ])
    }
    fn style(&self) -> String {
        let lib_css = jss! {
            ".app": {
                display: "flex",
                flex: "none",
                width: percent(100),
                height: percent(100),
            },
        };

        [lib_css, self.editor.style()].join("\n")
    }
    fn view(&self) -> Node<Msg> {
        div(
            vec![class("app")],
            vec![self.editor.view().map_msg(Msg::EditorMsg)],
        )
    }

    fn update(&mut self, msg: Msg) -> Cmd<Self, Msg> {
        match msg {
            Msg::WindowScrolled((scroll_top, scroll_left)) => {
                log::trace!("scrolled: {},{}", scroll_top, scroll_left);
                self.editor.update(editor::Msg::WindowScrolled((
                    scroll_top,
                    scroll_left,
                )));
                Cmd::none()
            }
            Msg::EditorMsg(emsg) => {
                let effects = self.editor.update(emsg);
                Cmd::from(effects.localize(Msg::EditorMsg))
            }
            Msg::Mouseup(client_x, client_y) => {
                self.editor.update(editor::Msg::Mouseup(client_x, client_y));
                Cmd::none().measure()
            }
            Msg::Mousedown(client_x, client_y) => {
                let effects = self
                    .editor
                    .update(editor::Msg::Mousedown(client_x, client_y));
                Cmd::from(effects.localize(Msg::EditorMsg)).measure()
            }
            Msg::Mousemove(client_x, client_y) => {
                self.editor
                    .update(editor::Msg::Mousemove(client_x, client_y));
                Cmd::none().no_render()
            }
            Msg::Keydown(ke) => {
                self.editor.update(editor::Msg::Keydown(ke));
                Cmd::none().measure()
            }
            Msg::NoOp => Cmd::none().no_render(),
        }
    }

    fn measurements(&self, measurements: Measurements) -> Cmd<Self, Msg> {
        Cmd::new(move |program| {
            program.dispatch(Msg::EditorMsg(editor::Msg::SetMeasurement(
                measurements.clone(),
            )))
        })
        .no_render()
    }
}

#[cfg(target_arch = "wasm32")]
#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;

#[cfg(target_arch = "wasm32")]
#[wasm_bindgen(start)]
pub fn main() {
    console_log::init_with_level(log::Level::Trace).unwrap();
    console_error_panic_hook::set_once();
    log::trace!("starting ultron..");
    Program::mount_to_body(App::new());
}