summaryrefslogtreecommitdiff
path: root/src/sheet/luaref.rs
blob: 1a2fd5ff5e973150a0dd79e6b759be8f77b054fe (plain)
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
use crate::state::GlobalState;

use super::{
    map::LuaMap,
    register::{Register, SheetId},
};
use mlua::prelude::*;

pub struct SheetLuaRef {
    id: SheetId,
}

impl SheetLuaRef {
    pub fn new(id: SheetId) -> Self {
        Self { id }
    }

    pub fn id(&self) -> SheetId {
        self.id
    }
}

impl LuaUserData for SheetLuaRef {
    fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
        fields.add_field_method_get("width", |_, luaref| {
            Ok(Register::get(luaref.id).unwrap().read().unwrap().width())
        });

        fields.add_field_method_get("height", |_, luaref| {
            Ok(Register::get(luaref.id).unwrap().read().unwrap().height())
        });
    }

    fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
        methods.add_method_mut("cell", |lua, luaref, (row, column): (usize, usize)| {
            if let Some(rw) = Register::get(luaref.id) {
                let sheet = rw.read().unwrap();
                Ok(sheet.get_ref(row, column).into_lua(lua).unwrap())
            } else {
                Ok(LuaValue::Nil)
            }
        });

        methods.add_method_mut("map", |_, luaref, func: LuaFunction| {
            let range: Vec<_> = {
                let state = GlobalState::instance();
                let lock = state.view.active_sheet().unwrap();
                let sheet = lock.read().unwrap();

                if sheet.id() != luaref.id() {
                    return Ok(());
                }

                let (width, height) = (sheet.width(), sheet.height());

                if state.view.selection_anchor.is_some() {
                    state.view.selection()
                } else {
                    let mut cells = Vec::new();
                    for row in 0..height {
                        for column in 0..width {
                            cells.push((row, column));
                        }
                    }
                    cells
                }
            };

            Register::get(luaref.id).unwrap().lua_map(func, range)
        })
    }
}

impl<'lua> FromLua<'lua> for SheetLuaRef {
    fn from_lua(value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult<Self> {
        if let Some(ud) = value.as_userdata() {
            ud.take()
        } else {
            Err(LuaError::runtime("failed to parse sheet"))
        }
    }
}