Skip to content

Commit fbdd5f6

Browse files
committed
feat: style settings when range is collapsed #870
1 parent 6bed83b commit fbdd5f6

File tree

5 files changed

+165
-18
lines changed

5 files changed

+165
-18
lines changed

src/editor/core/command/CommandAdapt.ts

Lines changed: 116 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -351,13 +351,23 @@ export class CommandAdapt {
351351
})
352352
this.draw.render({ isSetCursor: false })
353353
} else {
354+
let isSubmitHistory = true
354355
const { endIndex } = this.range.getRange()
355356
const elementList = this.draw.getElementList()
356357
const enterElement = elementList[endIndex]
357358
if (enterElement?.value === ZERO) {
358359
enterElement.font = payload
359-
this.draw.render({ curIndex: endIndex, isCompute: false })
360+
} else {
361+
this.range.setDefaultStyle({
362+
font: payload
363+
})
364+
isSubmitHistory = false
360365
}
366+
this.draw.render({
367+
isSubmitHistory,
368+
curIndex: endIndex,
369+
isCompute: false
370+
})
361371
}
362372
}
363373

@@ -380,6 +390,15 @@ export class CommandAdapt {
380390
if (enterElement?.value === ZERO) {
381391
changeElementList.push(enterElement)
382392
renderOption = { curIndex: endIndex }
393+
} else {
394+
this.range.setDefaultStyle({
395+
size: payload
396+
})
397+
this.draw.render({
398+
curIndex: endIndex,
399+
isCompute: false,
400+
isSubmitHistory: false
401+
})
383402
}
384403
}
385404
if (!changeElementList.length) return
@@ -402,6 +421,7 @@ export class CommandAdapt {
402421
public sizeAdd() {
403422
const isDisabled = this.draw.isReadonly() || this.draw.isDisabled()
404423
if (isDisabled) return
424+
const { defaultSize, maxSize } = this.options
405425
const selection = this.range.getTextLikeSelectionElementList()
406426
// 选区设置或设置换行处样式
407427
let renderOption: IDrawOption = {}
@@ -416,10 +436,20 @@ export class CommandAdapt {
416436
if (enterElement?.value === ZERO) {
417437
changeElementList.push(enterElement)
418438
renderOption = { curIndex: endIndex }
439+
} else {
440+
const style = this.range.getDefaultStyle()
441+
const anchorSize = style?.size || enterElement.size || defaultSize
442+
this.range.setDefaultStyle({
443+
size: anchorSize + 2 > maxSize ? maxSize : anchorSize + 2
444+
})
445+
this.draw.render({
446+
curIndex: endIndex,
447+
isCompute: false,
448+
isSubmitHistory: false
449+
})
419450
}
420451
}
421452
if (!changeElementList.length) return
422-
const { defaultSize, maxSize } = this.options
423453
let isExistUpdate = false
424454
changeElementList.forEach(el => {
425455
if (!el.size) {
@@ -441,6 +471,7 @@ export class CommandAdapt {
441471
public sizeMinus() {
442472
const isDisabled = this.draw.isReadonly() || this.draw.isDisabled()
443473
if (isDisabled) return
474+
const { defaultSize, minSize } = this.options
444475
const selection = this.range.getTextLikeSelectionElementList()
445476
// 选区设置或设置换行处样式
446477
let renderOption: IDrawOption = {}
@@ -455,10 +486,20 @@ export class CommandAdapt {
455486
if (enterElement?.value === ZERO) {
456487
changeElementList.push(enterElement)
457488
renderOption = { curIndex: endIndex }
489+
} else {
490+
const style = this.range.getDefaultStyle()
491+
const anchorSize = style?.size || enterElement.size || defaultSize
492+
this.range.setDefaultStyle({
493+
size: anchorSize - 2 < minSize ? minSize : anchorSize - 2
494+
})
495+
this.draw.render({
496+
curIndex: endIndex,
497+
isCompute: false,
498+
isSubmitHistory: false
499+
})
458500
}
459501
}
460502
if (!changeElementList.length) return
461-
const { defaultSize, minSize } = this.options
462503
let isExistUpdate = false
463504
changeElementList.forEach(el => {
464505
if (!el.size) {
@@ -488,13 +529,23 @@ export class CommandAdapt {
488529
})
489530
this.draw.render({ isSetCursor: false })
490531
} else {
532+
let isSubmitHistory = true
491533
const { endIndex } = this.range.getRange()
492534
const elementList = this.draw.getElementList()
493535
const enterElement = elementList[endIndex]
494536
if (enterElement?.value === ZERO) {
495537
enterElement.bold = !enterElement.bold
496-
this.draw.render({ curIndex: endIndex, isCompute: false })
538+
} else {
539+
this.range.setDefaultStyle({
540+
bold: enterElement.bold ? false : !this.range.getDefaultStyle()?.bold
541+
})
542+
isSubmitHistory = false
497543
}
544+
this.draw.render({
545+
isSubmitHistory,
546+
curIndex: endIndex,
547+
isCompute: false
548+
})
498549
}
499550
}
500551

@@ -509,13 +560,25 @@ export class CommandAdapt {
509560
})
510561
this.draw.render({ isSetCursor: false })
511562
} else {
563+
let isSubmitHistory = true
512564
const { endIndex } = this.range.getRange()
513565
const elementList = this.draw.getElementList()
514566
const enterElement = elementList[endIndex]
515567
if (enterElement?.value === ZERO) {
516568
enterElement.italic = !enterElement.italic
517-
this.draw.render({ curIndex: endIndex, isCompute: false })
569+
} else {
570+
this.range.setDefaultStyle({
571+
italic: enterElement.italic
572+
? false
573+
: !this.range.getDefaultStyle()?.italic
574+
})
575+
isSubmitHistory = false
518576
}
577+
this.draw.render({
578+
isSubmitHistory,
579+
curIndex: endIndex,
580+
isCompute: false
581+
})
519582
}
520583
}
521584

@@ -547,13 +610,25 @@ export class CommandAdapt {
547610
isCompute: false
548611
})
549612
} else {
613+
let isSubmitHistory = true
550614
const { endIndex } = this.range.getRange()
551615
const elementList = this.draw.getElementList()
552616
const enterElement = elementList[endIndex]
553617
if (enterElement?.value === ZERO) {
554618
enterElement.underline = !enterElement.underline
555-
this.draw.render({ curIndex: endIndex, isCompute: false })
619+
} else {
620+
this.range.setDefaultStyle({
621+
underline: enterElement?.underline
622+
? false
623+
: !this.range.getDefaultStyle()?.underline
624+
})
625+
isSubmitHistory = false
556626
}
627+
this.draw.render({
628+
isSubmitHistory,
629+
curIndex: endIndex,
630+
isCompute: false
631+
})
557632
}
558633
}
559634

@@ -571,13 +646,25 @@ export class CommandAdapt {
571646
isCompute: false
572647
})
573648
} else {
649+
let isSubmitHistory = true
574650
const { endIndex } = this.range.getRange()
575651
const elementList = this.draw.getElementList()
576652
const enterElement = elementList[endIndex]
577653
if (enterElement?.value === ZERO) {
578654
enterElement.strikeout = !enterElement.strikeout
579-
this.draw.render({ curIndex: endIndex, isCompute: false })
655+
} else {
656+
this.range.setDefaultStyle({
657+
strikeout: enterElement.strikeout
658+
? false
659+
: !this.range.getDefaultStyle()?.strikeout
660+
})
661+
isSubmitHistory = false
580662
}
663+
this.draw.render({
664+
isSubmitHistory,
665+
curIndex: endIndex,
666+
isCompute: false
667+
})
581668
}
582669
}
583670

@@ -656,6 +743,7 @@ export class CommandAdapt {
656743
isCompute: false
657744
})
658745
} else {
746+
let isSubmitHistory = true
659747
const { endIndex } = this.range.getRange()
660748
const elementList = this.draw.getElementList()
661749
const enterElement = elementList[endIndex]
@@ -665,8 +753,17 @@ export class CommandAdapt {
665753
} else {
666754
delete enterElement.color
667755
}
668-
this.draw.render({ curIndex: endIndex, isCompute: false })
756+
} else {
757+
this.range.setDefaultStyle({
758+
color: payload || undefined
759+
})
760+
isSubmitHistory = false
669761
}
762+
this.draw.render({
763+
isSubmitHistory,
764+
curIndex: endIndex,
765+
isCompute: false
766+
})
670767
}
671768
}
672769

@@ -687,6 +784,7 @@ export class CommandAdapt {
687784
isCompute: false
688785
})
689786
} else {
787+
let isSubmitHistory = true
690788
const { endIndex } = this.range.getRange()
691789
const elementList = this.draw.getElementList()
692790
const enterElement = elementList[endIndex]
@@ -696,8 +794,17 @@ export class CommandAdapt {
696794
} else {
697795
delete enterElement.highlight
698796
}
699-
this.draw.render({ curIndex: endIndex, isCompute: false })
797+
} else {
798+
this.range.setDefaultStyle({
799+
highlight: payload || undefined
800+
})
801+
isSubmitHistory = false
700802
}
803+
this.draw.render({
804+
isSubmitHistory,
805+
curIndex: endIndex,
806+
isCompute: false
807+
})
701808
}
702809
}
703810

src/editor/core/event/handlers/input.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { EDITOR_ELEMENT_COPY_ATTR } from '../../../dataset/constant/Element'
33
import { ElementType } from '../../../dataset/enum/Element'
44
import { IElement } from '../../../interface/Element'
55
import { splitText } from '../../../utils'
6-
import { formatElementContext, getAnchorElement } from '../../../utils/element'
6+
import { formatElementContext } from '../../../utils/element'
77
import { CanvasEvent } from '../CanvasEvent'
88

99
export function input(data: string, host: CanvasEvent) {
@@ -28,7 +28,7 @@ export function input(data: string, host: CanvasEvent) {
2828
const { startIndex, endIndex } = rangeManager.getRange()
2929
// 格式化元素
3030
const elementList = draw.getElementList()
31-
const copyElement = getAnchorElement(elementList, endIndex)
31+
const copyElement = rangeManager.getRangeAnchorStyle(elementList, endIndex)
3232
if (!copyElement) return
3333
const isDesignMode = draw.isDesignMode()
3434
const inputData: IElement[] = splitText(text).map(value => {

src/editor/core/event/handlers/keydown/enter.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@ import {
77
import { ControlComponent } from '../../../../dataset/enum/Control'
88
import { IElement } from '../../../../interface/Element'
99
import { omitObject } from '../../../../utils'
10-
import {
11-
formatElementContext,
12-
getAnchorElement
13-
} from '../../../../utils/element'
10+
import { formatElementContext } from '../../../../utils/element'
1411
import { CanvasEvent } from '../../CanvasEvent'
1512

1613
export function enter(evt: KeyboardEvent, host: CanvasEvent) {
@@ -61,7 +58,7 @@ export function enter(evt: KeyboardEvent, host: CanvasEvent) {
6158
)
6259
) {
6360
// 复制样式属性
64-
const copyElement = getAnchorElement(elementList, endIndex)
61+
const copyElement = rangeManager.getRangeAnchorStyle(elementList, endIndex)
6562
if (copyElement) {
6663
const copyAttr = [...EDITOR_ROW_ATTR]
6764
// 不复制控件后缀样式

src/editor/core/range/RangeManager.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { EventBusMap } from '../../interface/EventBus'
1010
import { IRangeStyle } from '../../interface/Listener'
1111
import {
1212
IRange,
13+
IRangeElementStyle,
1314
IRangeParagraphInfo,
1415
RangeRowArray,
1516
RangeRowMap
@@ -29,6 +30,7 @@ export class RangeManager {
2930
private eventBus: EventBus<EventBusMap>
3031
private position: Position
3132
private historyManager: HistoryManager
33+
private defaultStyle: IRangeElementStyle | null
3234

3335
constructor(draw: Draw) {
3436
this.draw = draw
@@ -41,6 +43,7 @@ export class RangeManager {
4143
startIndex: -1,
4244
endIndex: -1
4345
}
46+
this.defaultStyle = null
4447
}
4548

4649
public getRange(): IRange {
@@ -51,6 +54,33 @@ export class RangeManager {
5154
this.setRange(-1, -1)
5255
}
5356

57+
public setDefaultStyle(style: IRangeElementStyle | null) {
58+
if (!style) {
59+
this.defaultStyle = null
60+
} else {
61+
this.defaultStyle = {
62+
...this.defaultStyle,
63+
...style
64+
}
65+
}
66+
}
67+
68+
public getDefaultStyle(): IRangeElementStyle | null {
69+
return this.defaultStyle
70+
}
71+
72+
public getRangeAnchorStyle(
73+
elementList: IElement[],
74+
anchorIndex: number
75+
): IElement | null {
76+
const anchorElement = getAnchorElement(elementList, anchorIndex)
77+
if (!anchorElement) return null
78+
return {
79+
...anchorElement,
80+
...this.defaultStyle
81+
}
82+
}
83+
5484
public getIsCollapsed(): boolean {
5585
const { startIndex, endIndex } = this.range
5686
return startIndex === endIndex
@@ -373,6 +403,7 @@ export class RangeManager {
373403
startTrIndex ||
374404
endTrIndex
375405
)
406+
this.setDefaultStyle(null)
376407
this.range.zone = this.draw.getZone().getZone()
377408
// 激活控件
378409
const control = this.draw.getControl()
@@ -417,7 +448,7 @@ export class RangeManager {
417448
const index = ~endIndex ? endIndex : 0
418449
// 行首以第一个非换行符元素定位
419450
const elementList = this.draw.getElementList()
420-
curElement = getAnchorElement(elementList, index)
451+
curElement = this.getRangeAnchorStyle(elementList, index)
421452
}
422453
if (!curElement) return
423454
// 选取元素列表

src/editor/interface/Range.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { EditorZone } from '../dataset/enum/Editor'
2-
import { IElement, IElementFillRect } from './Element'
2+
import { IElement, IElementFillRect, IElementStyle } from './Element'
33

44
export interface IRange {
55
startIndex: number
@@ -41,3 +41,15 @@ export interface IRangeParagraphInfo {
4141
elementList: IElement[]
4242
startIndex: number
4343
}
44+
45+
export type IRangeElementStyle = Pick<
46+
IElementStyle,
47+
| 'bold'
48+
| 'color'
49+
| 'highlight'
50+
| 'font'
51+
| 'size'
52+
| 'italic'
53+
| 'underline'
54+
| 'strikeout'
55+
>

0 commit comments

Comments
 (0)