diff --git a/packages/docs-ui/src/services/selection/convert-text-range.ts b/packages/docs-ui/src/services/selection/convert-text-range.ts index e910940b2d3c..a4d413e9f2fd 100644 --- a/packages/docs-ui/src/services/selection/convert-text-range.ts +++ b/packages/docs-ui/src/services/selection/convert-text-range.ts @@ -14,9 +14,9 @@ * limitations under the License. */ -import { DocumentSkeletonPageType, getPageFromPath, GlyphType, Liquid } from '@univerjs/engine-render'; import type { IPosition, ITextRange, Nullable } from '@univerjs/core'; import type { DocumentSkeleton, IDocumentOffsetConfig, IDocumentSkeletonColumn, IDocumentSkeletonDivide, IDocumentSkeletonGlyph, IDocumentSkeletonLine, IDocumentSkeletonPage, IDocumentSkeletonRow, IDocumentSkeletonSection, INodePosition, IPoint } from '@univerjs/engine-render'; +import { DocumentSkeletonPageType, getPageFromPath, GlyphType, Liquid } from '@univerjs/engine-render'; export enum NodePositionStateType { NORMAL, diff --git a/packages/docs-ui/src/services/selection/rect-range.ts b/packages/docs-ui/src/services/selection/rect-range.ts index 14f985c1c570..896a8b023875 100644 --- a/packages/docs-ui/src/services/selection/rect-range.ts +++ b/packages/docs-ui/src/services/selection/rect-range.ts @@ -14,12 +14,12 @@ * limitations under the License. */ +import type { Documents, DocumentSkeleton, INodePosition, IPoint, ITextSelectionStyle, ThinScene } from '@univerjs/engine-render'; +import type { IDocRange } from './range-interface'; import { COLORS, DOC_RANGE_TYPE, type Nullable, RANGE_DIRECTION, Rectangle, Tools } from '@univerjs/core'; import { getColor, NORMAL_TEXT_SELECTION_PLUGIN_STYLE, RegularPolygon } from '@univerjs/engine-render'; -import type { Documents, DocumentSkeleton, INodePosition, IPoint, ITextSelectionStyle, ThinScene } from '@univerjs/engine-render'; import { compareNodePositionInTable, NodePositionConvertToRectRange } from './convert-rect-range'; import { TEXT_RANGE_LAYER_INDEX } from './text-range'; -import type { IDocRange } from './range-interface'; const RECT_RANGE_KEY_PREFIX = '__DocTableRectRange__'; const ID_LENGTH = 6; diff --git a/packages/docs-ui/src/services/selection/selection-utils.ts b/packages/docs-ui/src/services/selection/selection-utils.ts index ba355de959d7..be876566a348 100644 --- a/packages/docs-ui/src/services/selection/selection-utils.ts +++ b/packages/docs-ui/src/services/selection/selection-utils.ts @@ -30,13 +30,13 @@ * limitations under the License. */ +import type { Documents, DocumentSkeleton, Engine, IDocumentSkeletonGlyph, INodePosition, IRectRangeWithStyle, ITextRangeWithStyle, ITextSelectionStyle, Scene } from '@univerjs/engine-render'; +import type { IDocRange } from './range-interface'; import { type Nullable, RANGE_DIRECTION, Tools } from '@univerjs/core'; import { getOffsetRectForDom } from '@univerjs/engine-render'; -import type { Documents, DocumentSkeleton, Engine, IDocumentSkeletonGlyph, INodePosition, IRectRangeWithStyle, ITextRangeWithStyle, ITextSelectionStyle, Scene } from '@univerjs/engine-render'; import { isInSameTableCell, isValidRectRange } from './convert-rect-range'; import { convertPositionsToRectRanges, RectRange } from './rect-range'; import { TextRange } from './text-range'; -import type { IDocRange } from './range-interface'; interface IDocRangeList { textRanges: TextRange[]; diff --git a/packages/engine-render/src/components/docs/doc-component.ts b/packages/engine-render/src/components/docs/doc-component.ts index 365c210d65a5..dd23d3c631cf 100644 --- a/packages/engine-render/src/components/docs/doc-component.ts +++ b/packages/engine-render/src/components/docs/doc-component.ts @@ -14,14 +14,14 @@ * limitations under the License. */ -import { RENDER_CLASS_TYPE } from '../../basics/const'; import type { IDocumentSkeletonGlyph, IDocumentSkeletonLine, IDocumentSkeletonPage } from '../../basics/i-document-skeleton-cached'; -import { PageLayoutType } from '../../basics/i-document-skeleton-cached'; import type { IBoundRectNoAngle, IViewportInfo } from '../../basics/vector2'; import type { UniverRenderingContext } from '../../context'; -import { RenderComponent } from '../component'; import type { DOCS_EXTENSION_TYPE } from './doc-extension'; import type { DocumentSkeleton } from './layout/doc-skeleton'; +import { RENDER_CLASS_TYPE } from '../../basics/const'; +import { PageLayoutType } from '../../basics/i-document-skeleton-cached'; +import { RenderComponent } from '../component'; export interface IPageMarginLayout { pageMarginLeft: number; diff --git a/packages/engine-render/src/components/docs/layout/doc-skeleton.ts b/packages/engine-render/src/components/docs/layout/doc-skeleton.ts index 932eec7511b7..fbd6a198b268 100644 --- a/packages/engine-render/src/components/docs/layout/doc-skeleton.ts +++ b/packages/engine-render/src/components/docs/layout/doc-skeleton.ts @@ -511,10 +511,11 @@ export class DocumentSkeleton extends Skeleton { const { pages, skeHeaders, skeFooters } = skeletonData; const editArea = this.findEditAreaByCoord(coord, pageLayoutType, pageMarginLeft, pageMarginTop).editArea; + const pageLength = pages.length; this._findLiquid.reset(); if (restrictions == null) { - for (let pi = 0, len = pages.length; pi < len; pi++) { + for (let pi = 0; pi < pageLength; pi++) { const page = pages[pi]; const { headerId, footerId, pageWidth } = page; @@ -532,7 +533,8 @@ export class DocumentSkeleton extends Skeleton { pi, cache, x, - y + y, + pageLength ); } @@ -547,7 +549,8 @@ export class DocumentSkeleton extends Skeleton { pi, cache, x, - y + y, + pageLength ); } } else { @@ -560,7 +563,8 @@ export class DocumentSkeleton extends Skeleton { pi, cache, x, - y + y, + pageLength ); } @@ -575,7 +579,7 @@ export class DocumentSkeleton extends Skeleton { let exactMatch = null; if (strict === false) { - for (let pi = 0, len = pages.length; pi < len; pi++) { + for (let pi = 0; pi < pageLength; pi++) { const page = pages[pi]; const { headerId, footerId, pageWidth } = page; @@ -591,7 +595,8 @@ export class DocumentSkeleton extends Skeleton { pi, cache, x, - y + y, + pageLength ); } @@ -606,7 +611,8 @@ export class DocumentSkeleton extends Skeleton { pi, cache, x, - y + y, + pageLength ); } } else { @@ -619,7 +625,8 @@ export class DocumentSkeleton extends Skeleton { pi, cache, x, - y + y, + pageLength ); } @@ -630,7 +637,7 @@ export class DocumentSkeleton extends Skeleton { this._translatePage(page, pageLayoutType, pageMarginLeft, pageMarginTop); } } else { - for (let pi = 0, len = pages.length; pi < len; pi++) { + for (let pi = 0; pi < pageLength; pi++) { const page = pages[pi]; if (segmentId) { @@ -651,7 +658,8 @@ export class DocumentSkeleton extends Skeleton { segmentPage, cache, x, - y + y, + pageLength ); } } else { @@ -664,7 +672,8 @@ export class DocumentSkeleton extends Skeleton { pi, cache, x, - y + y, + pageLength ); } @@ -689,6 +698,7 @@ export class DocumentSkeleton extends Skeleton { cache: INearestCache, x: number, y: number, + pageLength: number, nestLevel: number = 0 // eslint-disable-next-line ts/no-explicit-any ): any { @@ -700,11 +710,30 @@ export class DocumentSkeleton extends Skeleton { const pageTop = this._findLiquid.y + (pageType === DocumentSkeletonPageType.FOOTER ? page.pageHeight - segmentPage.pageHeight : 0); const pageBottom = pageTop + segmentPage.pageHeight; - const pointInPage = x >= pageLeft + let pointInPage = x >= pageLeft && x <= pageRight && y >= pageTop && y <= pageBottom; + // Handle the outmost page. + if (nestLevel === 0 && pageType === DocumentSkeletonPageType.BODY) { + const isFirstPage = pi === 0; + const isLastPage = pi === pageLength - 1; + // TODO: Use page margin top as page gap now, need to consider the page gap in the future. + const halfMarginTop = page.originMarginTop / 2; + + // It's the only page, point always in page. + if (isFirstPage && isLastPage) { + pointInPage = true; + } else if (isFirstPage) { + pointInPage = y <= pageBottom + halfMarginTop; + } else if (isLastPage) { + pointInPage = y >= pageTop - halfMarginTop; + } else { + pointInPage = y >= pageTop - halfMarginTop && y <= pageBottom + halfMarginTop; + } + } + switch (pageType) { case DocumentSkeletonPageType.HEADER: { this._findLiquid.translatePagePadding({ @@ -877,6 +906,7 @@ export class DocumentSkeleton extends Skeleton { cache, x, y, + pageLength, nestLevel + 1 );