mirror of
https://github.com/groldsf/obsidian_check_plugin.git
synced 2026-07-22 05:37:48 +00:00
init state
This commit is contained in:
parent
b0d58d6447
commit
a7f33e676d
15 changed files with 617 additions and 10 deletions
20
package-lock.json
generated
20
package-lock.json
generated
|
|
@ -2741,16 +2741,6 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/diff-sequences": {
|
||||
"version": "29.6.3",
|
||||
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
|
||||
|
|
@ -5673,6 +5663,16 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/ts-node/node_modules/diff": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
||||
|
|
|
|||
37
src/core/CheckboxUtils2.ts
Normal file
37
src/core/CheckboxUtils2.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import { CheckboxState, CheckboxSyncPluginSettings } from "src/types";
|
||||
import { ICheckboxUtils } from "./interface/ICheckboxUtils";
|
||||
import { ContextFactory } from "./model/ContextFactory";
|
||||
import { PropagateStateToChildrenProcess } from "./process/PropagateStateToChildrenProcess";
|
||||
import { PropagateStateToParentProcess } from "./process/PropagateStateToParentProcess";
|
||||
|
||||
export interface CheckboxLineInfo {
|
||||
indent: number;
|
||||
marker: string;
|
||||
checkChar?: string;
|
||||
checkboxCharPosition?: number;
|
||||
checkboxState: CheckboxState;
|
||||
isChecked?: boolean | undefined;
|
||||
listItemText?: string;
|
||||
}
|
||||
|
||||
export class CheckboxUtils2 implements ICheckboxUtils {
|
||||
private settings: Readonly<CheckboxSyncPluginSettings>;
|
||||
private propagateStateToChildrenProcces: PropagateStateToChildrenProcess;
|
||||
private propagateStateToParentProcces: PropagateStateToParentProcess;
|
||||
|
||||
constructor(settings: Readonly<CheckboxSyncPluginSettings>) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
syncText(text: string, textBefore: string | undefined): string {
|
||||
if (text === textBefore) {
|
||||
return text;
|
||||
}
|
||||
const context = ContextFactory.createContext(text, textBefore, this.settings);
|
||||
|
||||
this.propagateStateToChildrenProcces.process(context);
|
||||
this.propagateStateToParentProcces.process(context);
|
||||
|
||||
return context.getResultText();
|
||||
}
|
||||
}
|
||||
5
src/core/interface/CheckboxProcess.ts
Normal file
5
src/core/interface/CheckboxProcess.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import { Context } from "../model/Context";
|
||||
|
||||
export interface CheckboxProcess {
|
||||
process(context: Context): void;
|
||||
}
|
||||
3
src/core/interface/ICheckboxUtils.ts
Normal file
3
src/core/interface/ICheckboxUtils.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export interface ICheckboxUtils {
|
||||
syncText(text: string, textBefore: string | undefined): string;
|
||||
}
|
||||
75
src/core/model/Context.ts
Normal file
75
src/core/model/Context.ts
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
import { CheckboxSyncPluginSettings } from "src/types";
|
||||
import { View } from "./View";
|
||||
import { Line } from "./Line";
|
||||
import { ContextFactory } from "./ContextFactory";
|
||||
|
||||
export class Context {
|
||||
|
||||
private settings: Readonly<CheckboxSyncPluginSettings>;
|
||||
|
||||
private text: string;
|
||||
private textLines?: string[];
|
||||
|
||||
private textBeforeChange?: string;
|
||||
private textBeforeChangeLines?: string[];
|
||||
|
||||
private lines?: Line[];
|
||||
private view?: View;
|
||||
|
||||
constructor(text: string, textBeforeChange: string | undefined, settings: Readonly<CheckboxSyncPluginSettings>) {
|
||||
this.text = text;
|
||||
this.textBeforeChange = textBeforeChange;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
getSettings(): Readonly<CheckboxSyncPluginSettings> {
|
||||
return this.settings;
|
||||
}
|
||||
|
||||
textBeforeChangeIsPresent(): boolean {
|
||||
if (this.textBeforeChange) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
getText() {
|
||||
return this.text;
|
||||
}
|
||||
|
||||
getTextLines() {
|
||||
if (!this.textLines) {
|
||||
this.textLines = this.getText().split("\n");
|
||||
}
|
||||
return this.textLines;
|
||||
}
|
||||
|
||||
getTextBeforeChange() {
|
||||
return this.textBeforeChange;
|
||||
}
|
||||
|
||||
getTextBeforeChangeLines() {
|
||||
if (!this.textBeforeChangeLines) {
|
||||
this.textBeforeChangeLines = this.textBeforeChange?.split("\n");
|
||||
}
|
||||
return this.textBeforeChangeLines;
|
||||
}
|
||||
|
||||
getLines() {
|
||||
if (!this.lines) {
|
||||
this.lines = ContextFactory.createLines(this);
|
||||
}
|
||||
return this.lines;
|
||||
}
|
||||
|
||||
getView(): View {
|
||||
if (!this.view) {
|
||||
this.view = ContextFactory.createView(this);
|
||||
}
|
||||
return this.view;
|
||||
}
|
||||
|
||||
getResultText(): string {
|
||||
return this.getView().toResultText();
|
||||
}
|
||||
}
|
||||
121
src/core/model/ContextFactory.ts
Normal file
121
src/core/model/ContextFactory.ts
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
import { CheckboxSyncPluginSettings } from "src/types";
|
||||
import { Context } from "./Context";
|
||||
import { TreeNode } from "./TreeNode";
|
||||
import { Line } from "./Line";
|
||||
import { View } from "./View";
|
||||
|
||||
export class ContextFactory {
|
||||
|
||||
private constructor() {
|
||||
}
|
||||
|
||||
public static createContext(text: string, textBefore: string | undefined, settings: Readonly<CheckboxSyncPluginSettings>): Context {
|
||||
return new Context(text, textBefore, settings);
|
||||
}
|
||||
|
||||
static createLines(context: Context): Line[] {
|
||||
const settings = context.getSettings();
|
||||
const textLines = context.getTextLines();
|
||||
const lines = this.createLinesFromTextLines(context.getTextLines(), settings);
|
||||
if (context.textBeforeChangeIsPresent()) {
|
||||
const textBeforeLines = context.getTextBeforeChangeLines()!;
|
||||
if (textLines.length === textBeforeLines.length) {
|
||||
const diffIndex = this.findSingleDiffLineIndex(textLines, textBeforeLines);
|
||||
if (diffIndex) {
|
||||
const oldLine = new Line(textBeforeLines[diffIndex], settings);
|
||||
const actualLine = lines[diffIndex];
|
||||
|
||||
// если новая и старая строка чекбокс
|
||||
// если текст остался старым
|
||||
// если изменилось состояние чекбокса
|
||||
if (oldLine.isCheckbox() &&
|
||||
actualLine.isCheckbox() &&
|
||||
oldLine.getText() === actualLine.getText() &&
|
||||
oldLine.getState() !== actualLine.getState()
|
||||
) {
|
||||
actualLine.setChange(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
static createView(context: Context) {
|
||||
const settings = context.getSettings();
|
||||
|
||||
const lines = context.getLines();
|
||||
|
||||
// построить дерево
|
||||
const treeNodes = this.createNodesFromLines(lines);
|
||||
|
||||
// проверить ноды на modify
|
||||
let isModify = false;
|
||||
for (const treeNode of treeNodes) {
|
||||
isModify = isModify || treeNode.isModify();
|
||||
}
|
||||
|
||||
return new View(treeNodes, isModify);
|
||||
}
|
||||
|
||||
private static createNodesFromLines(textLines: Line[]): TreeNode[] {
|
||||
const nodes: TreeNode[] = [];
|
||||
const stack: TreeNode[] = [];
|
||||
for (let index = 0; index < textLines.length; index++) {
|
||||
const line = textLines[index];
|
||||
const node = new TreeNode(line);
|
||||
|
||||
// найти родителя
|
||||
let parent = undefined;
|
||||
while (stack.length > 0) {
|
||||
const previousNode = stack[stack.length - 1];
|
||||
const previousLine = previousNode.getLine();
|
||||
if (previousLine.getIndent() < line.getIndent()) {
|
||||
parent = previousNode;
|
||||
break;
|
||||
} else {
|
||||
stack.pop();
|
||||
}
|
||||
}
|
||||
// добавить родителю, если есть
|
||||
parent?.addChildren(node);
|
||||
|
||||
nodes.push(node);
|
||||
stack.push(node);
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// создаёт Line[] из текста
|
||||
private static createLinesFromTextLines(textLines: string[], settings: Readonly<CheckboxSyncPluginSettings>): Line[] {
|
||||
return textLines.map(line => {
|
||||
return new Line(line, settings);
|
||||
});
|
||||
}
|
||||
|
||||
private static findSingleDiffLineIndex(lines1: string[], lines2: string[]): number | undefined {
|
||||
const diffLines = this.findDifferentLineIndexes(lines1, lines2);
|
||||
if (diffLines.length == 1) {
|
||||
return diffLines[0];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private static findDifferentLineIndexes(lines1: string[], lines2: string[]): number[] {
|
||||
if (lines1.length !== lines2.length) {
|
||||
throw new Error("the length of the lines must be equal");
|
||||
}
|
||||
|
||||
const length = lines1.length;
|
||||
const result: number[] = [];
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (lines1[i] !== lines2[i]) {
|
||||
result.push(i);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
8
src/core/model/Line.ts
Normal file
8
src/core/model/Line.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
export interface Line {
|
||||
getIndent(): number;
|
||||
|
||||
getText(): string;
|
||||
|
||||
toResultText(): string;
|
||||
|
||||
}
|
||||
59
src/core/model/TreeNode.ts
Normal file
59
src/core/model/TreeNode.ts
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
import { Line } from "./Line";
|
||||
|
||||
export class TreeNode {
|
||||
private parent?: TreeNode;
|
||||
private childrens: TreeNode[];
|
||||
|
||||
private line: Line;
|
||||
private modify = false;
|
||||
|
||||
constructor(line: Line) {
|
||||
this.line = line;
|
||||
if (line.isChange()) {
|
||||
this.modify = true;
|
||||
}
|
||||
}
|
||||
|
||||
getLine(): Line {
|
||||
return this.line;
|
||||
}
|
||||
|
||||
isModify(): boolean {
|
||||
return this.modify;
|
||||
}
|
||||
|
||||
private setParent(parent: TreeNode) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
getParent(): TreeNode | undefined {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
addChildren(children: TreeNode) {
|
||||
this.childrens.push(children);
|
||||
children.setParent(this);
|
||||
|
||||
this.modify = this.modify || children.isModify();
|
||||
}
|
||||
|
||||
hasChildren(): boolean {
|
||||
return this.childrens.length > 0;
|
||||
}
|
||||
|
||||
getChildrenNodes(): TreeNode[] {
|
||||
return [...this.childrens];
|
||||
}
|
||||
|
||||
toResultText(): string {
|
||||
const parts: string[] = [];
|
||||
|
||||
parts.push(this.line.toResultText());
|
||||
|
||||
for (const children of this.childrens) {
|
||||
parts.push(children.toResultText());
|
||||
}
|
||||
|
||||
return parts.join("\n");
|
||||
}
|
||||
}
|
||||
27
src/core/model/View.ts
Normal file
27
src/core/model/View.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { TreeNode } from "./TreeNode";
|
||||
|
||||
export class View {
|
||||
private treeNodes: TreeNode[];
|
||||
private modify: boolean;
|
||||
|
||||
constructor(treeNodes: TreeNode[], isModify: boolean) {
|
||||
this.treeNodes = treeNodes;
|
||||
this.modify = isModify;
|
||||
}
|
||||
|
||||
isModify() {
|
||||
return this.modify;
|
||||
}
|
||||
|
||||
getTreeNodes(): TreeNode[] {
|
||||
return this.treeNodes;
|
||||
}
|
||||
|
||||
toResultText(): string {
|
||||
const parts: string[] = [];
|
||||
for (const treeNode of this.treeNodes) {
|
||||
parts.push(treeNode.toResultText());
|
||||
}
|
||||
return parts.join("\n");
|
||||
}
|
||||
}
|
||||
29
src/core/model/line/AbstractLine.ts
Normal file
29
src/core/model/line/AbstractLine.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import { Line } from "../Line";
|
||||
|
||||
export abstract class AbstractLine implements Line {
|
||||
|
||||
// длина отступа
|
||||
protected indent: number;
|
||||
// текст после чекбокса
|
||||
protected listText: string;
|
||||
|
||||
constructor(indent:number, lineText: string){
|
||||
this.indent = indent;
|
||||
this.listText = lineText;
|
||||
|
||||
}
|
||||
|
||||
getIndent(): number {
|
||||
return this.indent;
|
||||
}
|
||||
|
||||
getText(): string {
|
||||
return this.listText;
|
||||
}
|
||||
|
||||
setText(lineText: string){
|
||||
this.listText = lineText;
|
||||
}
|
||||
|
||||
abstract toResultText(): string;
|
||||
}
|
||||
84
src/core/model/line/CheckboxLine.ts
Normal file
84
src/core/model/line/CheckboxLine.ts
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
import { CheckboxState, CheckboxSyncPluginSettings } from "src/types";
|
||||
import { AbstractLine } from "./AbstractLine";
|
||||
|
||||
export class CheckboxLine extends AbstractLine {
|
||||
|
||||
// символы перед чекбоксом
|
||||
private marker: string;
|
||||
// символ в чекбоксе
|
||||
private checkChar: string;
|
||||
// позиция символа чекбокса в исходной строке
|
||||
private checkboxCharPosition: number;
|
||||
// интерпретация символа чекбокса(или его отсутствия)
|
||||
private checkboxState: CheckboxState;
|
||||
// интерпретация состояния чекбокса(или его отсутствия)
|
||||
// private isChecked?: boolean | undefined;
|
||||
|
||||
|
||||
private hasChange = false;
|
||||
|
||||
protected settings: Readonly<CheckboxSyncPluginSettings>;
|
||||
|
||||
constructor(indent: number, marker: string, checkChar: string, lineText: string, settings: Readonly<CheckboxSyncPluginSettings>) {
|
||||
super(indent, lineText);
|
||||
this.marker = marker;
|
||||
this.checkChar = checkChar;
|
||||
this.settings = settings;
|
||||
|
||||
this.checkboxCharPosition = ;
|
||||
this.checkboxState = ;
|
||||
throw new Error("Constructor not implemented.");
|
||||
}
|
||||
|
||||
isChange(): boolean {
|
||||
return this.hasChange;
|
||||
}
|
||||
|
||||
setChange(hasChange: boolean) {
|
||||
this.hasChange = hasChange;
|
||||
}
|
||||
|
||||
|
||||
|
||||
isCheckbox(): boolean {
|
||||
return this.checkboxState !== CheckboxState.NoCheckbox;
|
||||
}
|
||||
|
||||
setState(state: CheckboxState): void {
|
||||
// обновить checkboxState
|
||||
this.checkboxState = state;
|
||||
// обновить checkChar
|
||||
switch (state) {
|
||||
case CheckboxState.Checked:
|
||||
this.checkChar = this.settings.checkedSymbols.length > 0 ? this.settings.checkedSymbols[0] : 'x'; // 'x' как дефолт
|
||||
break;
|
||||
case CheckboxState.Unchecked:
|
||||
this.checkChar = this.settings.uncheckedSymbols.length > 0 ? this.settings.uncheckedSymbols[0] : ' '; // ' ' как дефолт
|
||||
break;
|
||||
case CheckboxState.Ignore:
|
||||
if (this.settings.ignoreSymbols.length > 0) {
|
||||
this.checkChar = this.settings.ignoreSymbols[0];
|
||||
} else {
|
||||
throw new Error("Not found ignore char.");
|
||||
}
|
||||
break;
|
||||
case CheckboxState.NoCheckbox:
|
||||
this.checkChar = undefined;
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unexpected value for parameter [state] = ${state}.`);
|
||||
}
|
||||
}
|
||||
|
||||
setStateIfNotEquals(newState: CheckboxState) {
|
||||
if (newState !== this.checkboxState) {
|
||||
this.setState(newState);
|
||||
}
|
||||
}
|
||||
|
||||
getState(): CheckboxState {
|
||||
return this.checkboxState;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
27
src/core/model/line/ListLine.ts
Normal file
27
src/core/model/line/ListLine.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { AbstractLine } from "./AbstractLine";
|
||||
|
||||
export class ListLine extends AbstractLine {
|
||||
|
||||
// символы перед текстом
|
||||
private marker: string;
|
||||
|
||||
constructor(indent: number, marker: string, listText: string) {
|
||||
super(indent, listText);
|
||||
this.marker = marker;
|
||||
}
|
||||
|
||||
getMarker(): string {
|
||||
return this.marker;
|
||||
}
|
||||
|
||||
setMarker(marker: string) {
|
||||
this.marker = marker;
|
||||
}
|
||||
|
||||
toResultText(): string {
|
||||
const spaces = ' '.repeat(this.indent);
|
||||
|
||||
const resultText = spaces + this.marker + " " + this.listText;
|
||||
return resultText;
|
||||
}
|
||||
}
|
||||
9
src/core/model/line/TextLine.ts
Normal file
9
src/core/model/line/TextLine.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { AbstractLine } from "./AbstractLine";
|
||||
|
||||
export class TextLine extends AbstractLine {
|
||||
toResultText(): string {
|
||||
const spaces = ' '.repeat(this.indent);
|
||||
const resultText = spaces + this.listText;
|
||||
return resultText;
|
||||
}
|
||||
}
|
||||
66
src/core/process/PropagateStateToChildrenProcess.ts
Normal file
66
src/core/process/PropagateStateToChildrenProcess.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import { CheckboxState } from "src/types";
|
||||
import { CheckboxProcess } from "../interface/CheckboxProcess";
|
||||
import { Context } from "../model/Context";
|
||||
import { TreeNode } from "../model/TreeNode";
|
||||
|
||||
export class PropagateStateToChildrenProcess implements CheckboxProcess {
|
||||
|
||||
process(context: Context): void {
|
||||
if (!context.getSettings().enableAutomaticChildState) {
|
||||
return;
|
||||
}
|
||||
if (!context.textBeforeChangeIsPresent()) {
|
||||
return;
|
||||
}
|
||||
// получить представление текста
|
||||
const view = context.getView();
|
||||
|
||||
if (!view.isModify()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nodes = view.getTreeNodes();
|
||||
for (const node of nodes) {
|
||||
this.propageteStateToChildrenFromChangeLineNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
// находит изменённую Line, если она существует и вызывает от неё propagateStateToChildren
|
||||
propageteStateToChildrenFromChangeLineNode(node: TreeNode) {
|
||||
if (!node.isModify()) {
|
||||
return;
|
||||
}
|
||||
const line = node.getLine();
|
||||
// если line изменён
|
||||
if (line.isChange()) {
|
||||
// значит мы нашли нужную ноду
|
||||
this.propagateStateToChildren(node);
|
||||
} else {
|
||||
// иначе ищем вглубь среди детей
|
||||
const childrens = node.getChildrenNodes();
|
||||
for (const children of childrens) {
|
||||
this.propageteStateToChildrenFromChangeLineNode(children);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
propagateStateToChildren(modifiedNode: TreeNode) {
|
||||
const state = modifiedNode.getLine().getState();
|
||||
if (state === CheckboxState.Ignore || state === CheckboxState.NoCheckbox) {
|
||||
console.warn(`propagateStateToChildren ${state.toString()}`);
|
||||
return;
|
||||
}
|
||||
this.propagateToChildren(modifiedNode, state);
|
||||
}
|
||||
|
||||
propagateToChildren(node: TreeNode, state: CheckboxState) {
|
||||
const line = node.getLine();
|
||||
if (line.isCheckbox()) {
|
||||
line.setStateIfNotEquals(state);
|
||||
}
|
||||
for (const childrenNode of node.getChildrenNodes()) {
|
||||
this.propagateToChildren(childrenNode, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
57
src/core/process/PropagateStateToParentProcess.ts
Normal file
57
src/core/process/PropagateStateToParentProcess.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import { CheckboxState } from "src/types";
|
||||
import { CheckboxProcess } from "../interface/CheckboxProcess";
|
||||
import { Context } from "../model/Context";
|
||||
import { TreeNode } from "../model/TreeNode";
|
||||
|
||||
export class PropagateStateToParentProcess implements CheckboxProcess {
|
||||
|
||||
process(context: Context): void {
|
||||
if (!context.getSettings().enableAutomaticParentState) {
|
||||
return;
|
||||
}
|
||||
// получить представление текста
|
||||
const view = context.getView();
|
||||
|
||||
|
||||
const nodes = view.getTreeNodes();
|
||||
|
||||
for (const node of nodes) {
|
||||
this.propagateStateFromChildrens(node);
|
||||
}
|
||||
}
|
||||
|
||||
// возврат значения нужен для того, чтобы правильно обрабатывать случаи с "не чекбоксам", чтобы они передавали значения детей
|
||||
propagateStateFromChildrens(node: TreeNode): CheckboxState {
|
||||
const line = node.getLine();
|
||||
|
||||
if (!node.hasChildren()) {
|
||||
return line.getState();
|
||||
}
|
||||
|
||||
let resultIfHasRelevantChildren = CheckboxState.Checked;
|
||||
let hasRelevantChildren = false;
|
||||
for (const childrenNode of node.getChildrenNodes()) {
|
||||
const childrenState = this.propagateStateFromChildrens(childrenNode);
|
||||
|
||||
if (childrenState === CheckboxState.Checked || childrenState === CheckboxState.Unchecked) {
|
||||
hasRelevantChildren = true;
|
||||
}
|
||||
|
||||
if (childrenState === CheckboxState.Unchecked) {
|
||||
resultIfHasRelevantChildren = CheckboxState.Unchecked;
|
||||
}
|
||||
}
|
||||
// делаем эту проверку только после обработки детей
|
||||
if (line.getState() == CheckboxState.Ignore) {
|
||||
return line.getState();
|
||||
}
|
||||
// проверка для нод, все дети которых не релевантны
|
||||
if (!hasRelevantChildren) {
|
||||
return line.getState();
|
||||
}
|
||||
|
||||
line.setStateIfNotEquals(resultIfHasRelevantChildren);
|
||||
|
||||
return resultIfHasRelevantChildren;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue