feat: copy style information when wrapping #384
This commit is contained in:
@@ -29,6 +29,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
IAppendElementListOption,
|
IAppendElementListOption,
|
||||||
IDrawImagePayload,
|
IDrawImagePayload,
|
||||||
|
IDrawOption,
|
||||||
IForceUpdateOption,
|
IForceUpdateOption,
|
||||||
IGetImageOption,
|
IGetImageOption,
|
||||||
IGetValueOption,
|
IGetValueOption,
|
||||||
@@ -271,16 +272,32 @@ export class CommandAdapt {
|
|||||||
this.draw.isReadonly() || this.control.isDisabledControl()
|
this.draw.isReadonly() || this.control.isDisabledControl()
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelectionElementList()
|
const selection = this.range.getSelectionElementList()
|
||||||
if (!selection) return
|
// 选区设置或设置换行处样式
|
||||||
selection.forEach(el => {
|
let renderOption: IDrawOption = {}
|
||||||
el.font = ''
|
let changeElementList: IElement[] = []
|
||||||
el.color = ''
|
if (selection?.length) {
|
||||||
el.bold = false
|
changeElementList = selection
|
||||||
el.italic = false
|
renderOption = { isSetCursor: false }
|
||||||
el.underline = false
|
} else {
|
||||||
el.strikeout = false
|
const { endIndex } = this.range.getRange()
|
||||||
|
const elementList = this.draw.getElementList()
|
||||||
|
const enterElement = elementList[endIndex]
|
||||||
|
if (enterElement?.value === ZERO) {
|
||||||
|
changeElementList.push(enterElement)
|
||||||
|
renderOption = { curIndex: endIndex }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!changeElementList.length) return
|
||||||
|
changeElementList.forEach(el => {
|
||||||
|
delete el.size
|
||||||
|
delete el.font
|
||||||
|
delete el.color
|
||||||
|
delete el.bold
|
||||||
|
delete el.italic
|
||||||
|
delete el.underline
|
||||||
|
delete el.strikeout
|
||||||
})
|
})
|
||||||
this.draw.render({ isSetCursor: false })
|
this.draw.render(renderOption)
|
||||||
}
|
}
|
||||||
|
|
||||||
public font(payload: string) {
|
public font(payload: string) {
|
||||||
@@ -288,11 +305,20 @@ export class CommandAdapt {
|
|||||||
this.draw.isReadonly() || this.control.isDisabledControl()
|
this.draw.isReadonly() || this.control.isDisabledControl()
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelectionElementList()
|
const selection = this.range.getSelectionElementList()
|
||||||
if (!selection) return
|
if (selection?.length) {
|
||||||
selection.forEach(el => {
|
selection.forEach(el => {
|
||||||
el.font = payload
|
el.font = payload
|
||||||
})
|
})
|
||||||
this.draw.render({ isSetCursor: false })
|
this.draw.render({ isSetCursor: false })
|
||||||
|
} else {
|
||||||
|
const { endIndex } = this.range.getRange()
|
||||||
|
const elementList = this.draw.getElementList()
|
||||||
|
const enterElement = elementList[endIndex]
|
||||||
|
if (enterElement?.value === ZERO) {
|
||||||
|
enterElement.font = payload
|
||||||
|
this.draw.render({ curIndex: endIndex, isCompute: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public size(payload: number) {
|
public size(payload: number) {
|
||||||
@@ -301,10 +327,25 @@ export class CommandAdapt {
|
|||||||
const isDisabled =
|
const isDisabled =
|
||||||
this.draw.isReadonly() || this.control.isDisabledControl()
|
this.draw.isReadonly() || this.control.isDisabledControl()
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
|
// 选区设置或设置换行处样式
|
||||||
|
let renderOption: IDrawOption = {}
|
||||||
|
let changeElementList: IElement[] = []
|
||||||
const selection = this.range.getTextLikeSelectionElementList()
|
const selection = this.range.getTextLikeSelectionElementList()
|
||||||
if (!selection || !selection.length) return
|
if (selection?.length) {
|
||||||
|
changeElementList = selection
|
||||||
|
renderOption = { isSetCursor: false }
|
||||||
|
} else {
|
||||||
|
const { endIndex } = this.range.getRange()
|
||||||
|
const elementList = this.draw.getElementList()
|
||||||
|
const enterElement = elementList[endIndex]
|
||||||
|
if (enterElement?.value === ZERO) {
|
||||||
|
changeElementList.push(enterElement)
|
||||||
|
renderOption = { curIndex: endIndex }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!changeElementList.length) return
|
||||||
let isExistUpdate = false
|
let isExistUpdate = false
|
||||||
selection.forEach(el => {
|
changeElementList.forEach(el => {
|
||||||
if (
|
if (
|
||||||
(!el.size && payload === defaultSize) ||
|
(!el.size && payload === defaultSize) ||
|
||||||
(el.size && el.size === payload)
|
(el.size && el.size === payload)
|
||||||
@@ -315,7 +356,7 @@ export class CommandAdapt {
|
|||||||
isExistUpdate = true
|
isExistUpdate = true
|
||||||
})
|
})
|
||||||
if (isExistUpdate) {
|
if (isExistUpdate) {
|
||||||
this.draw.render({ isSetCursor: false })
|
this.draw.render(renderOption)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,10 +365,25 @@ export class CommandAdapt {
|
|||||||
this.draw.isReadonly() || this.control.isDisabledControl()
|
this.draw.isReadonly() || this.control.isDisabledControl()
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getTextLikeSelectionElementList()
|
const selection = this.range.getTextLikeSelectionElementList()
|
||||||
if (!selection || !selection.length) return
|
// 选区设置或设置换行处样式
|
||||||
|
let renderOption: IDrawOption = {}
|
||||||
|
let changeElementList: IElement[] = []
|
||||||
|
if (selection?.length) {
|
||||||
|
changeElementList = selection
|
||||||
|
renderOption = { isSetCursor: false }
|
||||||
|
} else {
|
||||||
|
const { endIndex } = this.range.getRange()
|
||||||
|
const elementList = this.draw.getElementList()
|
||||||
|
const enterElement = elementList[endIndex]
|
||||||
|
if (enterElement?.value === ZERO) {
|
||||||
|
changeElementList.push(enterElement)
|
||||||
|
renderOption = { curIndex: endIndex }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!changeElementList.length) return
|
||||||
const { defaultSize, maxSize } = this.options
|
const { defaultSize, maxSize } = this.options
|
||||||
let isExistUpdate = false
|
let isExistUpdate = false
|
||||||
selection.forEach(el => {
|
changeElementList.forEach(el => {
|
||||||
if (!el.size) {
|
if (!el.size) {
|
||||||
el.size = defaultSize
|
el.size = defaultSize
|
||||||
}
|
}
|
||||||
@@ -340,7 +396,7 @@ export class CommandAdapt {
|
|||||||
isExistUpdate = true
|
isExistUpdate = true
|
||||||
})
|
})
|
||||||
if (isExistUpdate) {
|
if (isExistUpdate) {
|
||||||
this.draw.render({ isSetCursor: false })
|
this.draw.render(renderOption)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,10 +405,25 @@ export class CommandAdapt {
|
|||||||
this.draw.isReadonly() || this.control.isDisabledControl()
|
this.draw.isReadonly() || this.control.isDisabledControl()
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getTextLikeSelectionElementList()
|
const selection = this.range.getTextLikeSelectionElementList()
|
||||||
if (!selection || !selection.length) return
|
// 选区设置或设置换行处样式
|
||||||
|
let renderOption: IDrawOption = {}
|
||||||
|
let changeElementList: IElement[] = []
|
||||||
|
if (selection?.length) {
|
||||||
|
changeElementList = selection
|
||||||
|
renderOption = { isSetCursor: false }
|
||||||
|
} else {
|
||||||
|
const { endIndex } = this.range.getRange()
|
||||||
|
const elementList = this.draw.getElementList()
|
||||||
|
const enterElement = elementList[endIndex]
|
||||||
|
if (enterElement?.value === ZERO) {
|
||||||
|
changeElementList.push(enterElement)
|
||||||
|
renderOption = { curIndex: endIndex }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!changeElementList.length) return
|
||||||
const { defaultSize, minSize } = this.options
|
const { defaultSize, minSize } = this.options
|
||||||
let isExistUpdate = false
|
let isExistUpdate = false
|
||||||
selection.forEach(el => {
|
changeElementList.forEach(el => {
|
||||||
if (!el.size) {
|
if (!el.size) {
|
||||||
el.size = defaultSize
|
el.size = defaultSize
|
||||||
}
|
}
|
||||||
@@ -365,7 +436,7 @@ export class CommandAdapt {
|
|||||||
isExistUpdate = true
|
isExistUpdate = true
|
||||||
})
|
})
|
||||||
if (isExistUpdate) {
|
if (isExistUpdate) {
|
||||||
this.draw.render({ isSetCursor: false })
|
this.draw.render(renderOption)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,12 +445,21 @@ export class CommandAdapt {
|
|||||||
this.draw.isReadonly() || this.control.isDisabledControl()
|
this.draw.isReadonly() || this.control.isDisabledControl()
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelectionElementList()
|
const selection = this.range.getSelectionElementList()
|
||||||
if (!selection) return
|
if (selection?.length) {
|
||||||
const noBoldIndex = selection.findIndex(s => !s.bold)
|
const noBoldIndex = selection.findIndex(s => !s.bold)
|
||||||
selection.forEach(el => {
|
selection.forEach(el => {
|
||||||
el.bold = !!~noBoldIndex
|
el.bold = !!~noBoldIndex
|
||||||
})
|
})
|
||||||
this.draw.render({ isSetCursor: false })
|
this.draw.render({ isSetCursor: false })
|
||||||
|
} else {
|
||||||
|
const { endIndex } = this.range.getRange()
|
||||||
|
const elementList = this.draw.getElementList()
|
||||||
|
const enterElement = elementList[endIndex]
|
||||||
|
if (enterElement?.value === ZERO) {
|
||||||
|
enterElement.bold = !enterElement.bold
|
||||||
|
this.draw.render({ curIndex: endIndex, isCompute: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public italic() {
|
public italic() {
|
||||||
@@ -387,12 +467,21 @@ export class CommandAdapt {
|
|||||||
this.draw.isReadonly() || this.control.isDisabledControl()
|
this.draw.isReadonly() || this.control.isDisabledControl()
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelectionElementList()
|
const selection = this.range.getSelectionElementList()
|
||||||
if (!selection) return
|
if (selection?.length) {
|
||||||
const noItalicIndex = selection.findIndex(s => !s.italic)
|
const noItalicIndex = selection.findIndex(s => !s.italic)
|
||||||
selection.forEach(el => {
|
selection.forEach(el => {
|
||||||
el.italic = !!~noItalicIndex
|
el.italic = !!~noItalicIndex
|
||||||
})
|
})
|
||||||
this.draw.render({ isSetCursor: false })
|
this.draw.render({ isSetCursor: false })
|
||||||
|
} else {
|
||||||
|
const { endIndex } = this.range.getRange()
|
||||||
|
const elementList = this.draw.getElementList()
|
||||||
|
const enterElement = elementList[endIndex]
|
||||||
|
if (enterElement?.value === ZERO) {
|
||||||
|
enterElement.italic = !enterElement.italic
|
||||||
|
this.draw.render({ curIndex: endIndex, isCompute: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public underline() {
|
public underline() {
|
||||||
@@ -400,15 +489,24 @@ export class CommandAdapt {
|
|||||||
this.draw.isReadonly() || this.control.isDisabledControl()
|
this.draw.isReadonly() || this.control.isDisabledControl()
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelectionElementList()
|
const selection = this.range.getSelectionElementList()
|
||||||
if (!selection) return
|
if (selection?.length) {
|
||||||
const noUnderlineIndex = selection.findIndex(s => !s.underline)
|
const noUnderlineIndex = selection.findIndex(s => !s.underline)
|
||||||
selection.forEach(el => {
|
selection.forEach(el => {
|
||||||
el.underline = !!~noUnderlineIndex
|
el.underline = !!~noUnderlineIndex
|
||||||
})
|
})
|
||||||
this.draw.render({
|
this.draw.render({
|
||||||
isSetCursor: false,
|
isSetCursor: false,
|
||||||
isCompute: false
|
isCompute: false
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
const { endIndex } = this.range.getRange()
|
||||||
|
const elementList = this.draw.getElementList()
|
||||||
|
const enterElement = elementList[endIndex]
|
||||||
|
if (enterElement?.value === ZERO) {
|
||||||
|
enterElement.underline = !enterElement.underline
|
||||||
|
this.draw.render({ curIndex: endIndex, isCompute: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public strikeout() {
|
public strikeout() {
|
||||||
@@ -416,15 +514,24 @@ export class CommandAdapt {
|
|||||||
this.draw.isReadonly() || this.control.isDisabledControl()
|
this.draw.isReadonly() || this.control.isDisabledControl()
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelectionElementList()
|
const selection = this.range.getSelectionElementList()
|
||||||
if (!selection) return
|
if (selection?.length) {
|
||||||
const noStrikeoutIndex = selection.findIndex(s => !s.strikeout)
|
const noStrikeoutIndex = selection.findIndex(s => !s.strikeout)
|
||||||
selection.forEach(el => {
|
selection.forEach(el => {
|
||||||
el.strikeout = !!~noStrikeoutIndex
|
el.strikeout = !!~noStrikeoutIndex
|
||||||
})
|
})
|
||||||
this.draw.render({
|
this.draw.render({
|
||||||
isSetCursor: false,
|
isSetCursor: false,
|
||||||
isCompute: false
|
isCompute: false
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
const { endIndex } = this.range.getRange()
|
||||||
|
const elementList = this.draw.getElementList()
|
||||||
|
const enterElement = elementList[endIndex]
|
||||||
|
if (enterElement?.value === ZERO) {
|
||||||
|
enterElement.strikeout = !enterElement.strikeout
|
||||||
|
this.draw.render({ curIndex: endIndex, isCompute: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public superscript() {
|
public superscript() {
|
||||||
@@ -492,14 +599,23 @@ export class CommandAdapt {
|
|||||||
this.draw.isReadonly() || this.control.isDisabledControl()
|
this.draw.isReadonly() || this.control.isDisabledControl()
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelectionElementList()
|
const selection = this.range.getSelectionElementList()
|
||||||
if (!selection) return
|
if (selection?.length) {
|
||||||
selection.forEach(el => {
|
selection.forEach(el => {
|
||||||
el.color = payload
|
el.color = payload
|
||||||
})
|
})
|
||||||
this.draw.render({
|
this.draw.render({
|
||||||
isSetCursor: false,
|
isSetCursor: false,
|
||||||
isCompute: false
|
isCompute: false
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
const { endIndex } = this.range.getRange()
|
||||||
|
const elementList = this.draw.getElementList()
|
||||||
|
const enterElement = elementList[endIndex]
|
||||||
|
if (enterElement?.value === ZERO) {
|
||||||
|
enterElement.color = payload
|
||||||
|
this.draw.render({ curIndex: endIndex, isCompute: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public highlight(payload: string) {
|
public highlight(payload: string) {
|
||||||
@@ -507,14 +623,23 @@ export class CommandAdapt {
|
|||||||
this.draw.isReadonly() || this.control.isDisabledControl()
|
this.draw.isReadonly() || this.control.isDisabledControl()
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelectionElementList()
|
const selection = this.range.getSelectionElementList()
|
||||||
if (!selection) return
|
if (selection?.length) {
|
||||||
selection.forEach(el => {
|
selection.forEach(el => {
|
||||||
el.highlight = payload
|
el.highlight = payload
|
||||||
})
|
})
|
||||||
this.draw.render({
|
this.draw.render({
|
||||||
isSetCursor: false,
|
isSetCursor: false,
|
||||||
isCompute: false
|
isCompute: false
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
const { endIndex } = this.range.getRange()
|
||||||
|
const elementList = this.draw.getElementList()
|
||||||
|
const enterElement = elementList[endIndex]
|
||||||
|
if (enterElement?.value === ZERO) {
|
||||||
|
enterElement.highlight = payload
|
||||||
|
this.draw.render({ curIndex: endIndex, isCompute: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public title(payload: TitleLevel | null) {
|
public title(payload: TitleLevel | null) {
|
||||||
|
|||||||
@@ -1327,7 +1327,7 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
metrics.boundingBoxAscent =
|
metrics.boundingBoxAscent =
|
||||||
(element.value === ZERO
|
(element.value === ZERO
|
||||||
? defaultSize
|
? element.size || defaultSize
|
||||||
: fontMetrics.actualBoundingBoxAscent) * scale
|
: fontMetrics.actualBoundingBoxAscent) * scale
|
||||||
metrics.boundingBoxDescent =
|
metrics.boundingBoxDescent =
|
||||||
fontMetrics.actualBoundingBoxDescent * scale
|
fontMetrics.actualBoundingBoxDescent * scale
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ export function input(data: string, host: CanvasEvent) {
|
|||||||
}
|
}
|
||||||
const nextElement = elementList[endIndex + 1]
|
const nextElement = elementList[endIndex + 1]
|
||||||
if (
|
if (
|
||||||
|
!copyElement.type ||
|
||||||
copyElement.type === TEXT ||
|
copyElement.type === TEXT ||
|
||||||
(!copyElement.type && copyElement.value !== ZERO) ||
|
|
||||||
(copyElement.type === HYPERLINK && nextElement?.type === HYPERLINK) ||
|
(copyElement.type === HYPERLINK && nextElement?.type === HYPERLINK) ||
|
||||||
(copyElement.type === DATE && nextElement?.type === DATE) ||
|
(copyElement.type === DATE && nextElement?.type === DATE) ||
|
||||||
(copyElement.type === SUBSCRIPT && nextElement?.type === SUBSCRIPT) ||
|
(copyElement.type === SUBSCRIPT && nextElement?.type === SUBSCRIPT) ||
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import { ZERO } from '../../../../dataset/constant/Common'
|
import { ZERO } from '../../../../dataset/constant/Common'
|
||||||
|
import { EDITOR_ELEMENT_STYLE_ATTR } from '../../../../dataset/constant/Element'
|
||||||
import { IElement } from '../../../../interface/Element'
|
import { IElement } from '../../../../interface/Element'
|
||||||
import { formatElementContext } from '../../../../utils/element'
|
import {
|
||||||
|
formatElementContext,
|
||||||
|
getAnchorElement
|
||||||
|
} from '../../../../utils/element'
|
||||||
import { CanvasEvent } from '../../CanvasEvent'
|
import { CanvasEvent } from '../../CanvasEvent'
|
||||||
|
|
||||||
export function enter(evt: KeyboardEvent, host: CanvasEvent) {
|
export function enter(evt: KeyboardEvent, host: CanvasEvent) {
|
||||||
@@ -40,6 +44,16 @@ export function enter(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
) {
|
) {
|
||||||
formatElementContext(elementList, [enterText], startIndex)
|
formatElementContext(elementList, [enterText], startIndex)
|
||||||
}
|
}
|
||||||
|
// 复制样式属性
|
||||||
|
const copyElement = getAnchorElement(elementList, endIndex)
|
||||||
|
if (copyElement) {
|
||||||
|
EDITOR_ELEMENT_STYLE_ATTR.forEach(attr => {
|
||||||
|
const value = copyElement[attr] as never
|
||||||
|
if (value !== undefined) {
|
||||||
|
enterText[attr] = value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
// 控件或文档插入换行元素
|
// 控件或文档插入换行元素
|
||||||
const activeControl = control.getActiveControl()
|
const activeControl = control.getActiveControl()
|
||||||
let curIndex: number
|
let curIndex: number
|
||||||
|
|||||||
Reference in New Issue
Block a user