Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
ImJeremyHe committed Dec 7, 2024
1 parent 50473b7 commit 6fd959e
Show file tree
Hide file tree
Showing 31 changed files with 829 additions and 262 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"src/bindings/**/*",
"crates/wasms/**/*",
"packages/**/bindings/**/*",
"packages/**/dist/**/*",
"packages/**/wasm/**/*"
],
"rules": {
Expand Down
9 changes: 7 additions & 2 deletions crates/buildtools/src/generate.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
fn main() {
use gents::FileGroup;
use logisheets_controller::controller::display::CellPosition;
use logisheets_controller::controller::display::DisplayWindowWithStartPoint;
use logisheets_controller::controller::display::{DisplayRequest, DisplayResponse, SheetInfo};
use logisheets_controller::controller::display::{
DisplayResponse, DisplaySheetRequest, DisplayWindowRequest, SheetInfo,
};
use logisheets_controller::edit_action::AsyncFuncResult;
use logisheets_controller::edit_action::{ActionEffect, EditAction};
use logisheets_controller::CellInfo;
use logisheets_controller::ErrorMessage;

let path = "packages/web/src/bindings";
let mut file_group = FileGroup::new();
file_group.add::<DisplayRequest>();
file_group.add::<DisplaySheetRequest>();
file_group.add::<DisplayWindowRequest>();
file_group.add::<DisplayResponse>();
file_group.add::<CellPosition>();
file_group.add::<DisplayWindowWithStartPoint>();
file_group.add::<EditAction>();
file_group.add::<SheetInfo>();
Expand Down
186 changes: 186 additions & 0 deletions crates/controller/src/api/cell_positioner.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
use itertools::Itertools;

use super::worksheet::Worksheet;
use crate::errors::Result;

#[derive(Debug, Clone)]
pub struct CellPositioner<const INTERVAL: usize> {
cache_height: Vec<(usize, f64)>,
cache_width: Vec<(usize, f64)>,
}

impl<const INTERVAL: usize> CellPositioner<INTERVAL> {
pub fn new() -> Self {
CellPositioner {
cache_height: vec![],
cache_width: vec![],
}
}

pub fn clear(&mut self) {
self.cache_height = vec![];
self.cache_width = vec![];
}

pub fn get_row_start_y(&mut self, row: usize, ws: &Worksheet) -> Result<f64> {
let (mut curr, mut result) = self.find_closest_cache_height(row);
if curr == row {
return Ok(result);
}
let reverse = curr > row;

while curr != row {
if ws.is_row_hidden(row) {
curr = advance(reverse, curr);
continue;
}
let h = ws.get_row_height(curr)?;
result += h;
self.add_cache(true, curr, result);
}
Ok(result)
}

pub fn get_col_start_x(&mut self, col: usize, ws: &Worksheet) -> Result<f64> {
let (mut curr, mut result) = self.find_closest_cache_width(col);
if curr == col {
return Ok(result);
}
let reverse = curr > col;

while curr != col {
if ws.is_col_hidden(col) {
curr = advance(reverse, curr);
continue;
}
let h = ws.get_row_height(curr)?;
result += h;
self.add_cache(true, curr, result);
}
Ok(result)
}

pub fn get_nearest_row_before_given_y(
&mut self,
y: f64,
ws: &Worksheet,
) -> Result<(usize, f64)> {
let (mut curr_idx, mut curr_h) = self.find_closest_cache_before_y(y);
let mut h = 0.;
while curr_h < y {
if ws.is_row_hidden(curr_idx) {
curr_idx += 1;
continue;
}
h = ws.get_row_height(curr_idx)?;
curr_idx += 1;
curr_h += h;
self.add_cache(true, curr_idx, curr_h);
}

return Ok((curr_idx - 1, curr_h - h));
}

pub fn get_nearest_col_before_given_x(
&mut self,
x: f64,
ws: &Worksheet,
) -> Result<(usize, f64)> {
let (mut curr_idx, mut curr_w) = self.find_closest_cache_before_x(x);
let mut w = 0.;
while curr_w < x {
if ws.is_row_hidden(curr_idx) {
curr_idx += 1;
continue;
}
w = ws.get_row_height(curr_idx)?;
curr_idx += 1;
curr_w += w;
self.add_cache(false, curr_idx, curr_w);
}

return Ok((curr_idx - 1, curr_w - w));
}

fn find_closest_cache_before_x(&self, x: f64) -> (usize, f64) {
if self.cache_width.is_empty() {
return (0, 0.);
}

let r = self.cache_width.iter().find_position(|(_, v)| *v > x);
if let Some((idx, _)) = r {
self.cache_width.get(idx - 1).unwrap().clone()
} else {
self.cache_width.last().unwrap().clone()
}
}

fn find_closest_cache_before_y(&self, y: f64) -> (usize, f64) {
if self.cache_height.is_empty() {
return (0, 0.);
}

let r = self.cache_height.iter().find_position(|(_, v)| *v > y);
if let Some((idx, _)) = r {
self.cache_height.get(idx - 1).unwrap().clone()
} else {
self.cache_height.last().unwrap().clone()
}
}

fn find_closest_cache_width(&self, col: usize) -> (usize, f64) {
if self.cache_width.is_empty() {
return (0, 0.);
}

for (c, x) in self.cache_width.iter() {
if c.abs_diff(col) <= INTERVAL / 2 {
return (*c, *x);
}
}
let result = self.cache_width.last().unwrap();
*result
}

fn find_closest_cache_height(&self, row: usize) -> (usize, f64) {
if self.cache_height.is_empty() {
return (0, 0.);
}

for (r, y) in self.cache_height.iter() {
if r.abs_diff(row) <= usize::from(INTERVAL / 2) {
return (*r, *y);
}
}
let result = self.cache_height.last().unwrap();
*result
}

fn add_cache(&mut self, height: bool, k: usize, v: f64) -> bool {
let cache = if height {
&mut self.cache_height
} else {
&mut self.cache_width
};
if cache.is_empty() {
cache.push((k, v));
return true;
}

let last = cache.last().unwrap();
if k - last.0 >= INTERVAL {
cache.push((k, v));
return true;
}
return false;
}
}

#[inline]
fn advance(reverse: bool, curr: usize) -> usize {
if reverse {
curr - 1
} else {
curr + 1
}
}
1 change: 1 addition & 0 deletions crates/controller/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub use crate::{
errors::{Error, ErrorMessage, Result},
Comment, MergeCell, Style, Value,
};
mod cell_positioner;
mod types;
mod workbook;
mod worksheet;
Expand Down
50 changes: 39 additions & 11 deletions crates/controller/src/api/workbook.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use super::worksheet::Worksheet;
use std::collections::HashMap;

use super::{cell_positioner::CellPositioner, worksheet::Worksheet};
use crate::{
controller::display::{DisplayRequest, DisplayResponse, SheetInfo},
controller::display::{DisplayResponse, DisplaySheetRequest, SheetInfo},
edit_action::{ActionEffect, StatusCode},
lock::{locked_write, new_locked, Locked},
Controller,
};
use crate::{
Expand All @@ -11,16 +14,21 @@ use crate::{
use logisheets_base::{
async_func::{AsyncCalcResult, Task},
errors::BasicError,
SheetId,
};

pub(crate) type CellPositionerDefault = CellPositioner<1000>;

pub struct Workbook {
controller: Controller,
cell_positioners: Locked<HashMap<SheetId, Locked<CellPositionerDefault>>>,
}

impl Default for Workbook {
fn default() -> Self {
Self {
controller: Default::default(),
cell_positioners: new_locked(HashMap::new()),
}
}
}
Expand All @@ -30,6 +38,7 @@ impl Workbook {
pub fn new() -> Self {
Workbook {
controller: Default::default(),
cell_positioners: new_locked(HashMap::new()),
}
}

Expand All @@ -41,7 +50,10 @@ impl Workbook {
/// Create a workbook from a .xlsx file.
pub fn from_file(buf: &[u8], book_name: String) -> Result<Self> {
let controller = Controller::from_file(book_name, buf)?;
Ok(Workbook { controller })
Ok(Workbook {
controller,
cell_positioners: new_locked(HashMap::new()),
})
}

#[inline]
Expand All @@ -60,8 +72,8 @@ impl Workbook {
}

#[inline]
pub fn get_display_response(&self, req: DisplayRequest) -> DisplayResponse {
self.controller.get_display_response(req)
pub fn get_display_sheet_response(&self, req: DisplaySheetRequest) -> Result<DisplayResponse> {
self.controller.get_display_sheet_response(req)
}

#[inline]
Expand All @@ -85,14 +97,29 @@ impl Workbook {
self.controller.get_all_sheet_info()
}

#[inline]
pub fn get_cell_positioner(&self, sheet: SheetId) -> Locked<CellPositionerDefault> {
let mut cell_positioners = locked_write(&self.cell_positioners);
let entry = cell_positioners
.entry(sheet)
.or_insert_with(|| new_locked(CellPositionerDefault::new()));

entry.clone()
}

pub fn get_sheet_by_name(&self, name: &str) -> Result<Worksheet> {
match self.controller.get_sheet_id_by_name(name) {
Some(sheet_id) => Ok(Worksheet {
sheet_id,
controller: &self.controller,
}),
None => Err(BasicError::SheetNameNotFound(name.to_string()).into()),
let id = self.controller.get_sheet_id_by_name(name);
if id.is_none() {
return Err(BasicError::SheetNameNotFound(name.to_string()).into());
}
let sheet_id = id.unwrap();
let positioner = self.get_cell_positioner(sheet_id);
let c = &self.controller;
Ok(Worksheet {
sheet_id,
controller: c,
positioner,
})
}

pub fn get_sheet_idx_by_name(&self, name: &str) -> Result<usize> {
Expand All @@ -113,6 +140,7 @@ impl Workbook {
Some(sheet_id) => Ok(Worksheet {
sheet_id,
controller: &self.controller,
positioner: self.get_cell_positioner(sheet_id),
}),
None => Err(Error::UnavailableSheetIdx(idx)),
}
Expand Down
Loading

0 comments on commit 6fd959e

Please sign in to comment.