Skip to content

Commit

Permalink
feat(range-selector): support selection control
Browse files Browse the repository at this point in the history
  • Loading branch information
Gggpound committed Sep 29, 2024
1 parent 36e13ab commit ca9acc0
Show file tree
Hide file tree
Showing 12 changed files with 307 additions and 164 deletions.
17 changes: 15 additions & 2 deletions packages/sheets-formula/src/controllers/prompt.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ import type {
} from '@univerjs/sheets';

import type { EditorBridgeService, SelectionShape } from '@univerjs/sheets-ui';
import { isRangeSelector } from '../../src/views/range-selector/utils/isRangeSelector';
import { SelectEditorFormulaOperation } from '../commands/operations/editor-formula.operation';
import { HelpFunctionOperation } from '../commands/operations/help-function.operation';
import { ReferenceAbsoluteOperation } from '../commands/operations/reference-absolute.operation';
Expand Down Expand Up @@ -258,7 +259,10 @@ export class PromptController extends Disposable {
if (params?.unitId == null) {
return;
}

// ToDo: range
if (isRangeSelector(params.unitId)) {
return;
}
const editor = this._editorService.getEditor(params.unitId);
if (!editor
|| editor.onlyInputContent()
Expand Down Expand Up @@ -305,6 +309,10 @@ export class PromptController extends Disposable {
return;
}

if (isRangeSelector(unitId)) {
return;
}

if (this._listenInputCache.has(unitId)) {
return;
}
Expand Down Expand Up @@ -376,6 +384,9 @@ export class PromptController extends Disposable {

const editorId = documentDataModel.getUnitId();

if (isRangeSelector(editorId)) {
return;
}
if (!this._editorService.isEditor(editorId) || this._previousEditorUnitId === editorId) {
return;
}
Expand Down Expand Up @@ -1551,7 +1562,9 @@ export class PromptController extends Disposable {
const nodeIndex = Number(id);

const currentNode = this._formulaPromptService.getCurrentSequenceNodeByIndex(nodeIndex);

if (!currentNode) {
return;
}
let refType: IAbsoluteRefTypeForRange = { startAbsoluteRefType: AbsoluteRefType.NONE };
if (typeof currentNode !== 'string') {
const token = (currentNode as ISequenceNode).token;
Expand Down
2 changes: 2 additions & 0 deletions packages/sheets-formula/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export { FORMULA_PROMPT_ACTIVATED } from './services/prompt.service';
export { RegisterOtherFormulaService } from './services/register-other-formula.service';
export type { IFormulaInfo, IOtherFormulaResult } from './services/formula-common';
export { RangeSelector } from './views/range-selector/index';
export { RefSelectionsRenderService } from './services/render-services/ref-selections.render-service';
export { isRangeSelector } from './views/range-selector/utils/isRangeSelector';

// #region - all commands

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { ScrollTimerType, SHEET_VIEWPORT_KEY, Vector2 } from '@univerjs/engine-r
import { convertSelectionDataToRange, getNormalSelectionStyle, IRefSelectionsService, SelectionMoveType } from '@univerjs/sheets';
import { attachSelectionWithCoord, BaseSelectionRenderService, checkInHeaderRanges, getAllSelection, getCoordByOffset, getSheetObject, SheetSkeletonManagerService } from '@univerjs/sheets-ui';
import { IShortcutService } from '@univerjs/ui';
import { merge } from 'rxjs';
import type { IDisposable, Nullable, Workbook } from '@univerjs/core';
import type { IMouseEvent, IPointerEvent, IRenderContext, IRenderModule, Viewport } from '@univerjs/engine-render';
import type { ISelectionStyle, ISelectionWithCoordAndStyle, ISelectionWithStyle, SheetsSelectionsService, WorkbookSelections } from '@univerjs/sheets';
Expand Down Expand Up @@ -187,7 +188,7 @@ export class RefSelectionsRenderService extends BaseSelectionRenderService imple
// Changing the selection area through the 8 control points of the ref selection will not trigger this subscriber.

// beforeSelectionMoveEnd$ & selectionMoveEnd$ would triggered when change skeleton(change sheet).
this.disposeWithMe(this._workbookSelections.selectionMoveEnd$.subscribe((selectionsWithStyles) => {
this.disposeWithMe(merge(this._workbookSelections.selectionMoveEnd$, this._workbookSelections.selectionSet$).subscribe((selectionsWithStyles) => {
this._reset();

// The selections' style would be colorful here. PromptController would change the color of selections later.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
* limitations under the License.
*/

import { ColorKit, IUniverInstanceService, Rectangle, ThemeService, useDependency } from '@univerjs/core';
import { ColorKit, IUniverInstanceService, ThemeService, useDependency } from '@univerjs/core';
import { IEditorService } from '@univerjs/docs-ui';
import { deserializeRangeWithSheet, sequenceNodeType } from '@univerjs/engine-formula';
import { getPrimaryForRange, setEndForRange } from '@univerjs/sheets';
import { IDescriptionService } from '@univerjs/sheets-formula';
import { IMarkSelectionService } from '@univerjs/sheets-ui';
import { IRenderManagerService } from '@univerjs/engine-render';
import { IRefSelectionsService, setEndForRange } from '@univerjs/sheets';
import { IDescriptionService, RefSelectionsRenderService } from '@univerjs/sheets-formula';
import { attachRangeWithCoord, SheetSkeletonManagerService } from '@univerjs/sheets-ui';
import { useEffect, useMemo, useState } from 'react';
import type { ITextRun, Workbook } from '@univerjs/core';
import type { ISequenceNode } from '@univerjs/engine-formula';
Expand All @@ -40,7 +41,11 @@ interface IRefSelection {
export function useSheetHighlight(isNeed: boolean, unitId: string, subUnitId: string, refSelections: IRefSelection[]) {
const univerInstanceService = useDependency(IUniverInstanceService);
const themeService = useDependency(ThemeService);
const markSelectionService = useDependency(IMarkSelectionService);
const refSelectionsService = useDependency(IRefSelectionsService);
const renderManagerService = useDependency(IRenderManagerService);
const render = renderManagerService.getRenderById(unitId);
const refSelectionsRenderService = render?.with(RefSelectionsRenderService);
const sheetSkeletonManagerService = render?.with(SheetSkeletonManagerService);

const [ranges, rangesSet] = useState<ISelectionWithStyle[]>([]);

Expand Down Expand Up @@ -73,38 +78,39 @@ export function useSheetHighlight(isNeed: boolean, unitId: string, subUnitId: st

const range = setEndForRange(rawRange, worksheet.getRowCount(), worksheet.getColumnCount());

const primary = getPrimaryForRange(range, worksheet);

if (
!Rectangle.equals(primary, range) &&
range.startRow === range.endRow &&
range.startColumn === range.endColumn
) {
range.startRow = primary.startRow;
range.endRow = primary.endRow;
range.startColumn = primary.startColumn;
range.endColumn = primary.endColumn;
}

selectionWithStyle.push({
range,
primary,
primary: undefined,
style: getFormulaRefSelectionStyle(themeService, themeColor, refIndex.toString()),
});
}
rangesSet(selectionWithStyle);
}, [unitId, subUnitId, refSelections, isNeed]);

useEffect(() => {
if (isNeed) {
const ids = ranges.map((range) => markSelectionService.addShape(range));
return () => {
ids.forEach((id) => {
id && markSelectionService.removeShape(id);
const skeleton = sheetSkeletonManagerService?.getCurrentSkeleton();
if (isNeed && skeleton) {
const allControls = refSelectionsRenderService?.getSelectionControls() || [];
if (allControls.length === ranges.length) {
allControls.forEach((control, index) => {
const range = ranges[index];
control.updateRange(attachRangeWithCoord(skeleton, range.range));
control.updateStyle(range.style!);
});
};
} else {
refSelectionsService.setSelections(ranges);
}
}
}, [ranges, isNeed]);
}, [ranges, isNeed, sheetSkeletonManagerService]);

useEffect(() => {
return () => {
refSelectionsService.clearCurrentSelections();
const controls = refSelectionsRenderService?.getSelectionControls() || [];
controls.forEach((c) => c.dispose());
controls.length = 0;
};
}, []);
}

export function useDocHight(editorId: string, sequenceNodes: (string | ISequenceNode)[]) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@
* limitations under the License.
*/

import { debounce } from '@univerjs/core';
import { DocSkeletonManagerService } from '@univerjs/docs';
import { useEffect } from 'react';
import type { Editor } from '@univerjs/docs-ui';
import { type Editor, VIEWPORT_KEY } from '@univerjs/docs-ui';
import { ScrollBar } from '@univerjs/engine-render';
import { useEffect, useMemo } from 'react';
import type { Nullable } from '@univerjs/core';

export const useResize = (editor?: Editor) => {
const resize = () => {
Expand All @@ -35,15 +38,65 @@ export const useResize = (editor?: Editor) => {
}
};

const checkScrollBar = useMemo(() => {
return debounce(() => {
if (!editor) {
return;
}
const docSkeletonManagerService = editor.render.with(DocSkeletonManagerService);
const skeleton = docSkeletonManagerService.getSkeleton();
const { scene, mainComponent } = editor.render;
const viewportMain = scene.getViewport(VIEWPORT_KEY.VIEW_MAIN);
const { actualWidth } = skeleton.getActualSize();
const { width, height } = editor.getBoundingClientRect();
let scrollBar = viewportMain?.getScrollBar() as Nullable<ScrollBar>;
const contentWidth = Math.max(actualWidth, width);

const contentHeight = height;

scene.transformByState({
width: contentWidth,
height: contentHeight,
});

mainComponent?.resize(contentWidth, contentHeight);

if (actualWidth > width) {
if (scrollBar == null) {
viewportMain && new ScrollBar(viewportMain, { barSize: 8, enableVertical: false });
} else {
viewportMain?.resetCanvasSizeAndUpdateScroll();
}
} else {
scrollBar = null;
viewportMain?.scrollToBarPos({ x: 0, y: 0 });
viewportMain?.getScrollBar()?.dispose();
}
}, 30);
}, [editor]);

useEffect(() => {
if (editor) {
const time = setTimeout(() => {
resize();
checkScrollBar();
}, 500);
return () => {
clearTimeout(time);
};
}
}, [editor]);
return resize;

useEffect(() => {
if (editor) {
const d = editor.input$.subscribe(() => {
checkScrollBar();
});
return () => {
d.unsubscribe();
};
}
}, [editor]);

return { resize, checkScrollBar };
};
Loading

0 comments on commit ca9acc0

Please sign in to comment.