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).map(|s| s.width())) }); fields.add_field_method_get("height", |_, luaref| { Ok(Register::get(luaref.id).map(|s| s.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(sheet) = Register::get(luaref.id) { Ok(sheet.get_ref(row, column).into_lua(lua).unwrap()) } else { Ok(LuaValue::Nil) } }); methods.add_method_mut("map", |_, luaref, func: LuaFunction| { if let Some(sheet) = Register::get(luaref.id) { let range: Vec<_> = { let state = GlobalState::get(); let sheet = state.view.active_sheet().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 } }; sheet.lua_map(func, range) } else { Err(mlua::Error::runtime("unvalid sheet")) } }) } } 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")) } } }