logisheets_controller 0.7.0

the core of LogiSheets
Documentation
mod delete_line;
mod input;
mod insert_line;
mod utils;
use std::collections::HashSet;

use delete_line::delete_line;
use input::input;
use insert_line::insert_line;
use logisheets_base::{errors::BasicError, Cube, CubeId};

use crate::{edit_action::EditPayload, Error};

use super::{ctx::CubeExecCtx, manager::CubeManager};

#[derive(Debug, Clone)]
pub struct CubeExecutor {
    pub manager: CubeManager,
    pub dirty_cubes: HashSet<CubeId>,
    pub removed_cubes: HashSet<CubeId>,
}

impl CubeExecutor {
    pub fn new(manager: CubeManager) -> Self {
        CubeExecutor {
            manager,
            dirty_cubes: HashSet::new(),
            removed_cubes: HashSet::new(),
        }
    }

    pub fn execute<C: CubeExecCtx>(
        self,
        ctx: &C,
        payload: EditPayload,
    ) -> Result<CubeExecutor, Error> {
        match payload {
            EditPayload::CellInput(cell_input) => {
                let sheet_idx = cell_input.sheet_idx;
                let sheet_id = ctx
                    .fetch_sheet_id_by_index(sheet_idx)
                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
                Ok(input(self, sheet_id, cell_input.row, cell_input.col, ctx))
            }
            EditPayload::CellClear(cell_clear) => {
                let sheet_idx = cell_clear.sheet_idx;
                let sheet_id = ctx
                    .fetch_sheet_id_by_index(sheet_idx)
                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
                Ok(input(self, sheet_id, cell_clear.row, cell_clear.col, ctx))
            }
            EditPayload::InsertCols(insert_cols) => {
                let sheet_idx = insert_cols.sheet_idx;
                let sheet_id = ctx
                    .fetch_sheet_id_by_index(sheet_idx)
                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
                Ok(insert_line(
                    self,
                    sheet_id,
                    false,
                    insert_cols.start,
                    insert_cols.count as u32,
                    ctx,
                ))
            }
            EditPayload::DeleteCols(delete_cols) => {
                let sheet_idx = delete_cols.sheet_idx;
                let sheet_id = ctx
                    .fetch_sheet_id_by_index(sheet_idx)
                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
                Ok(delete_line(
                    self,
                    sheet_id,
                    false,
                    delete_cols.start,
                    delete_cols.count as u32,
                    ctx,
                ))
            }
            EditPayload::InsertRows(insert_rows) => {
                let sheet_idx = insert_rows.sheet_idx;
                let sheet_id = ctx
                    .fetch_sheet_id_by_index(sheet_idx)
                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
                Ok(insert_line(
                    self,
                    sheet_id,
                    true,
                    insert_rows.start,
                    insert_rows.count as u32,
                    ctx,
                ))
            }
            EditPayload::DeleteRows(delete_rows) => {
                let sheet_idx = delete_rows.sheet_idx;
                let sheet_id = ctx
                    .fetch_sheet_id_by_index(sheet_idx)
                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
                Ok(delete_line(
                    self,
                    sheet_id,
                    true,
                    delete_rows.start,
                    delete_rows.count as u32,
                    ctx,
                ))
            }
            _ => Ok(self),
        }
    }

    pub fn cube_update<F>(self, func: &mut F) -> Self
    where
        F: FnMut(&Cube, &CubeId) -> CubeUpdateType,
    {
        let mut dirty_cubes = self.dirty_cubes;
        let removed_cubes = self.removed_cubes;
        let new_manager = self.manager.clone();
        self.manager
            .cube_to_id
            .iter()
            .for_each(|(c, id)| match func(c, id) {
                CubeUpdateType::Dirty => {
                    dirty_cubes.insert(*id);
                }
                CubeUpdateType::None => {}
            });
        CubeExecutor {
            manager: new_manager,
            dirty_cubes,
            removed_cubes,
        }
    }
}

pub enum CubeUpdateType {
    None,
    Dirty,
}