Skip to content

Commit

Permalink
fix: scrollbar
Browse files Browse the repository at this point in the history
  • Loading branch information
ImJeremyHe committed Jan 2, 2025
1 parent 92f74e7 commit c12a35c
Show file tree
Hide file tree
Showing 18 changed files with 235 additions and 79 deletions.
20 changes: 9 additions & 11 deletions crates/buildtools/src/generate.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
fn main() {
use gents::FileGroup;
use logisheets_controller::controller::display::CellPosition;
use logisheets_controller::controller::display::DisplayWindowWithStartPoint;
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;
use gents::FileGroup;
use logisheets_controller::controller::display::{
CellPosition, DisplayResponse, DisplaySheetRequest, DisplayWindowRequest,
DisplayWindowWithStartPoint, SheetInfo,
};
use logisheets_controller::edit_action::{ActionEffect, AsyncFuncResult, EditAction};
use logisheets_controller::{CellInfo, ErrorMessage, SheetDimension};

fn main() {
let path = "packages/web/src/bindings";
let mut file_group = FileGroup::new();
file_group.add::<DisplaySheetRequest>();
Expand All @@ -21,6 +18,7 @@ fn main() {
file_group.add::<SheetInfo>();
file_group.add::<ActionEffect>();
file_group.add::<AsyncFuncResult>();
file_group.add::<SheetDimension>();

file_group.add::<CellInfo>();
file_group.add::<ErrorMessage>();
Expand Down
12 changes: 12 additions & 0 deletions crates/controller/src/api/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,15 @@ pub struct CellInfo {
pub style: Style,
pub block_id: Option<BlockId>,
}

#[cfg_attr(
feature = "gents",
gents_derives::gents_header(file_name = "sheet_dimension.ts")
)]
#[derive(Debug, Clone)]
pub struct SheetDimension {
pub max_row: usize,
pub max_col: usize,
pub height: f64,
pub width: f64,
}
57 changes: 37 additions & 20 deletions crates/controller/src/api/worksheet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use logisheets_base::{BlockId, CellId, ColId, RowId, SheetId};
use logisheets_parser::unparse;

use super::workbook::CellPositionerDefault;
use super::SheetDimension;

// Use a cache to record the coordinate
pub struct Worksheet<'a> {
Expand Down Expand Up @@ -473,35 +474,51 @@ impl<'a> Worksheet<'a> {
}

/// Get the dimension of the sheet.
pub fn get_sheet_dimension(&self) -> (usize, usize) {
pub fn get_sheet_dimension(&self) -> Result<SheetDimension> {
let sheet_container = self
.controller
.status
.container
.get_sheet_container(self.sheet_id);
if sheet_container.is_none() {
return (0, 0);
return Ok(SheetDimension {
max_row: 0,
max_col: 0,
height: 0.,
width: 0.,
});
}
let sheet_container = sheet_container.unwrap();
sheet_container
.cells
.clone()
.iter()
.fold((0, 0), |(r, c), (id, _)| {
let cell_idx = self
.controller
.status
.navigator
.fetch_cell_idx(&self.sheet_id, id);
match cell_idx {
Ok((row, col)) => {
let r = if r > row { r } else { row };
let c = if c > col { c } else { col };
(r, c)
let (max_row, max_col) =
sheet_container
.cells
.clone()
.iter()
.fold((0, 0), |(r, c), (id, _)| {
let cell_idx = self
.controller
.status
.navigator
.fetch_cell_idx(&self.sheet_id, id);
match cell_idx {
Ok((row, col)) => {
let r = if r > row { r } else { row };
let c = if c > col { c } else { col };
(r, c)
}
Err(_) => (r, c),
}
Err(_) => (r, c),
}
})
});
let CellPosition {
y: start_row,
x: start_col,
} = self.get_cell_position(max_row, max_col)?;
Ok(SheetDimension {
max_row,
max_col,
height: start_row,
width: start_col,
})
}

pub fn get_row_info(&self, row: usize) -> Option<RowInfo> {
Expand Down
14 changes: 14 additions & 0 deletions crates/wasms/server/src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,20 @@ pub fn get_cell_position(id: usize, sheet_idx: usize, row: usize, col: usize) ->
serde_wasm_bindgen::to_value(&result).unwrap()
}

#[wasm_bindgen]
pub fn get_sheet_dimension(id: usize, sheet_idx: usize) -> JsValue {
init();
let manager = MANAGER.get();
let result = manager
.get_workbook(&id)
.unwrap()
.get_sheet_by_idx(sheet_idx)
.unwrap()
.get_sheet_dimension();
handle_result!(result);
serde_wasm_bindgen::to_value(&result).unwrap()
}

#[wasm_bindgen]
/// logisheets_controller::DisplayResponse
pub fn get_patches(id: usize, sheet_idx: u32, version: u32) -> JsValue {
Expand Down
8 changes: 7 additions & 1 deletion packages/web/src/api/worksheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
get_display_window_within_cell,
get_cell_position,
get_all_fully_covered_blocks,
get_sheet_dimension,
} from '../../wasm'
import {
BlockInfo,
Expand All @@ -22,8 +23,9 @@ import {
RowInfo,
Style,
Value,
CellInfo,
SheetDimension,
} from '../bindings'
import {CellInfo} from '../bindings/cell_info'
import {Cell} from './cell'
import {isErrorMessage, Result} from './utils'

Expand All @@ -33,6 +35,10 @@ export class Worksheet {
this._sheetIdx = idx
}

public getSheetDimension(): Result<SheetDimension> {
return get_sheet_dimension(this._id, this._sheetIdx)
}

public getDisplayWindow(
startRow: number,
endRow: number,
Expand Down
1 change: 1 addition & 0 deletions packages/web/src/bindings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export * from './set_visible'
export * from './sheet_blocks'
export * from './sheet_col_info'
export * from './sheet_comments'
export * from './sheet_dimension'
export * from './sheet_info'
export * from './sheet_merge_cells'
export * from './sheet_names'
Expand Down
8 changes: 8 additions & 0 deletions packages/web/src/bindings/sheet_dimension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// DO NOT EDIT. CODE GENERATED BY gents.

export interface SheetDimension {
maxRow: number
maxCol: number
height: number
width: number
}
1 change: 1 addition & 0 deletions packages/web/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export type {
SheetBlocks,
SheetColInfo,
SheetComments,
SheetDimension,
SheetInfo,
SheetMergeCells,
SheetNames,
Expand Down
1 change: 1 addition & 0 deletions src/components/canvas/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ const Internal: FC<CanvasProps> = observer((props: CanvasProps) => {
lastScrollTime = now
store.setAnchor(store.anchorX, store.anchorY + e.deltaY)
store.render.render()
store.scrollbar.update('y')
store.scroll()
}

Expand Down
2 changes: 2 additions & 0 deletions src/components/canvas/store/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ export class Render {
)
this.render()
this._jumpToCellInCurrentView(row, col)
this.store.scrollbar.update('x')
this.store.scrollbar.update('y')
})
}

Expand Down
67 changes: 56 additions & 11 deletions src/components/canvas/store/scrollbar.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {action, makeObservable, observable} from 'mobx'
import {CanvasStore} from './store'
import {ScrollbarAttr, ScrollbarType} from '@/components/scrollbar'
import type {ScrollbarAttr, ScrollbarType} from '@/components/scrollbar'
import {CANVAS_OFFSET} from '@/core/data2'
import {isErrorMessage} from 'logisheets-web'
import {ptToPx, widthToPx} from '@/core'

export class ScrollBar {
constructor(public readonly store: CanvasStore) {
Expand All @@ -16,25 +18,65 @@ export class ScrollBar {

@action
init() {
this.store.dataSvc
.getSheetDimension(this.store.currSheetIdx)
.then((v) => {
if (isErrorMessage(v)) {
throw Error(
`failed to get sheet dimension: ${this.store.currSheetIdx}`
)
}

this._init(ptToPx(v.height), widthToPx(v.width))
})
}

@action
_init(dimensionHeight: number, dimensionWidth: number) {
const {offsetHeight: height, offsetWidth: width} =
this.store.render.canvas
const h = Math.max(dimensionHeight, height + CANVAS_OFFSET)
const w = Math.max(dimensionWidth, width + CANVAS_OFFSET)
this.xScrollbar.scrollTop = this.store.anchorX
this.xScrollbar.scrollHeight = w
this.xScrollbar.offsetHeight = width
this.xScrollbar.scrollHeight = width + CANVAS_OFFSET
this.yScrollbar.scrollTop = this.store.anchorY
this.yScrollbar.scrollHeight = h
this.yScrollbar.offsetHeight = height
this.yScrollbar.scrollHeight = height + CANVAS_OFFSET

this._appropriateHeight = h
this._appropriateWidth = w
}

@action
onResize() {
const {offsetHeight: canvasHeight, offsetWidth: canvasWidth} =
this.store.render.canvas
const scrollWidth = canvasWidth + CANVAS_OFFSET
const scrollHeight = +canvasHeight + CANVAS_OFFSET
this.init()
}

this.xScrollbar.offsetHeight = canvasWidth
this.xScrollbar.scrollHeight = scrollWidth
this.yScrollbar.offsetHeight = canvasHeight
this.yScrollbar.scrollHeight = scrollHeight
/**
* Make sure this happens after the anchor X or Y is updated.
*/
@action
update(type: ScrollbarType) {
const {offsetHeight: height, offsetWidth: width} =
this.store.render.canvas
if (type === 'x') {
this.xScrollbar.scrollTop = this.store.anchorX
const viewLength = this.store.anchorX + width
if (this.store.anchorX + width > this.xScrollbar.scrollHeight) {
this.xScrollbar.scrollHeight = this.store.anchorX + width
} else if (viewLength < this._appropriateWidth) {
this.xScrollbar.scrollHeight = this._appropriateWidth
}
} else {
this.yScrollbar.scrollTop = this.store.anchorY
const viewLength = this.store.anchorY + height
if (viewLength > this.yScrollbar.scrollHeight) {
this.yScrollbar.scrollHeight = viewLength + CANVAS_OFFSET
} else if (viewLength < this._appropriateHeight) {
this.yScrollbar.scrollHeight = this._appropriateHeight
}
}
}

@action
Expand All @@ -46,4 +88,7 @@ export class ScrollBar {
}
this.store.render.render()
}

private _appropriateHeight: number = 0
private _appropriateWidth: number = 0
}
14 changes: 7 additions & 7 deletions src/components/scrollbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export * from './scroll_event'
export type ScrollbarType = 'x' | 'y'
export interface ScrollbarAttr {
offsetHeight?: number
scrollHeight?: number
scrollHeight: number
scrollTop?: number
minThumbLength?: number
direction: ScrollbarType
Expand Down Expand Up @@ -48,29 +48,29 @@ export const ScrollbarComponent: FC<ScrollbarProps> = ({
* The difference between clientHeight, offsetHeight, scrollHeight, offsetTop, and scrollTop
* https://www.programmersought.com/article/76801676023/
*/
const scrollRadio =
const scrollRatio =
scrollHeight === 0 ? 0 : scrollTop / scrollHeight
const thumbRadio =
const thumbRatio =
scrollHeight === 0 ? 0 : offsetHeight / scrollHeight
const containerStyle = getComputedStyle(thumbContainer)
const newThumbStyle: CSSProperties = {}
if (xScrollbar()) {
const containerLength = parseFloat(containerStyle.width)
const thumbWidth = containerLength * thumbRadio
const thumbWidth = containerLength * thumbRatio
const thumbLength = Math.max(thumbWidth, minThumbLength)
newThumbStyle.width =
thumbLength === containerLength ? 0 : toPx(thumbLength)
const left = scrollRadio * containerLength
const left = scrollRatio * containerLength
if (left + thumbLength > containerLength) {
newThumbStyle.right = 0
} else newThumbStyle.left = toPx(left)
} else {
const containerLength = parseFloat(containerStyle.height)
const thumbHeight = thumbContainer.offsetHeight * thumbRadio
const thumbHeight = thumbContainer.offsetHeight * thumbRatio
const thumbLength = Math.max(thumbHeight, minThumbLength)
newThumbStyle.height =
thumbLength === containerLength ? 0 : toPx(thumbLength)
const top = scrollRadio * containerLength
const top = scrollRatio * containerLength
if (top + thumbLength > containerLength) {
newThumbStyle.bottom = 0
} else newThumbStyle.top = toPx(top)
Expand Down
1 change: 0 additions & 1 deletion src/components/sheets-tab/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ export const SheetsTabComponent: FC<SheetTabProps> = ({
const onTabChange = (key: string) => {
const i = sheets.findIndex((s) => s === key)
activeSheet$(i)
DATA_SERVICE.setCurrentSheetIdx(i)
}

const add = () => {
Expand Down
Loading

0 comments on commit c12a35c

Please sign in to comment.