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.sheetview.active_sheet().unwrap(); let sheet = lock.read().unwrap(); if sheet.id() != luaref.id() { return Ok(()); } let (width, height) = (sheet.width(), sheet.height()); if state.sheetview.selection_anchor.is_some() { state.sheetview.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 { if let Some(ud) = value.as_userdata() { ud.take() } else { Err(LuaError::runtime("failed to parse sheet")) } } }