Files
DocumentServer-v-9.2.0/sdkjs/word/Editor/annotations/custom-text-annotator/range-marks.js
Yajbir Singh f1b860b25c
Some checks failed
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

462 lines
12 KiB
JavaScript

/*
* (c) Copyright Ascensio System SIA 2010-2025
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
"use strict";
(function(window)
{
/**
* Class for handling a collection of custom annotation range marks
* @param {AscWord.Document} logicDocument
* @constructor
*/
function CustomMarks(logicDocument)
{
this.logicDocument = logicDocument;
this.runs = {}; // runId -> markId
this.paragraphs = {}; // paraId -> handlerId -> rangeId -> {start, end}
}
CustomMarks.prototype.add = function(mark)
{
let rangeId = mark.getRangeId();
let runId = mark.getRun().GetId();
let paraId = mark.getParagraph().GetId();
let handlerId = mark.getHandlerId();
if (!this.runs[runId])
this.runs[runId] = {};
this.runs[runId][mark.getId()] = mark;
if (!this.paragraphs[paraId])
this.paragraphs[paraId] = {};
if (!this.paragraphs[paraId][handlerId])
this.paragraphs[paraId][handlerId] = {};
if (!this.paragraphs[paraId][handlerId][rangeId])
this.paragraphs[paraId][handlerId][rangeId] = {start : null, end : null};
if (mark.isStart())
this.paragraphs[paraId][handlerId][rangeId].start = mark;
else
this.paragraphs[paraId][handlerId][rangeId].end = mark;
};
CustomMarks.prototype.clear = function(paragraph, handlerId)
{
let paraId = paragraph.GetId();
if (!this.paragraphs[paraId] || !this.paragraphs[paraId][handlerId])
return;
for (let rangeId in this.paragraphs[paraId][handlerId])
{
this.removeMarkFromRun(this.paragraphs[paraId][handlerId][rangeId].start);
this.removeMarkFromRun(this.paragraphs[paraId][handlerId][rangeId].end);
}
delete this.paragraphs[paraId][handlerId];
};
CustomMarks.prototype.removeMarkFromRun = function(mark)
{
if (!mark)
return;
let runId = mark.getRun().GetId();
if (!this.runs[runId])
return;
if (this.runs[runId] && this.runs[runId][mark.getId()])
delete this.runs[runId][mark.getId()];
};
/**
* @param {AscWord.Paragraph} paragraph
* @param {AscWord.CParagraphContentPos} paraContentPos
* @returns {[]}
*/
CustomMarks.prototype.getStartedMarks = function(paragraph, paraContentPos)
{
let paraId = paragraph.GetId();
if (!this.paragraphs[paraId])
return [];
let marks = this.paragraphs[paraId];
let result = [];
for (let handlerId in marks)
{
for (let rangeId in marks[handlerId])
{
let startMark = marks[handlerId][rangeId].start;
let endMark = marks[handlerId][rangeId].end;
if (!startMark || !endMark)
continue;
let startPos = startMark.getParaPos();
let endPos = endMark.getParaPos();
if (!startPos || !endPos)
continue;
if (paraContentPos.Compare(startPos) > 0 && paraContentPos.Compare(endPos) < 0)
result.push(startMark);
}
}
return result;
};
/**
* @param {AscWord.Paragraph} paragraph
* @param {AscWord.CParagraphContentPos} paraContentPos
* @returns {[]}
*/
CustomMarks.prototype.getMarksByPos = function(paragraph, paraContentPos)
{
let paraId = paragraph.GetId();
if (!this.paragraphs[paraId])
return [];
let marks = this.paragraphs[paraId];
let result = [];
for (let handlerId in marks)
{
for (let rangeId in marks[handlerId])
{
let startMark = marks[handlerId][rangeId].start;
let endMark = marks[handlerId][rangeId].end;
if (!startMark || !endMark)
continue;
let startPos = startMark.getParaPos();
let endPos = endMark.getParaPos();
if (!startPos || !endPos)
continue;
if (paraContentPos.Compare(startPos) >= 0 && paraContentPos.Compare(endPos) <= 0)
result.push(startMark);
}
}
return result;
};
CustomMarks.prototype.selectRange = function(paraId, handlerId, rangeId)
{
let paragraph = AscCommon.g_oTableId.GetById(paraId);
if (!this.paragraphs[paraId]
|| !this.paragraphs[paraId][handlerId]
|| !this.paragraphs[paraId][handlerId][rangeId])
return;
let start = this.paragraphs[paraId][handlerId][rangeId].start;
let end = this.paragraphs[paraId][handlerId][rangeId].end;
let startPos = start.getParaPos();
let endPos = end.getParaPos();
this.logicDocument.RemoveSelection();
paragraph.SetSelectionUse(true);
paragraph.SetSelectionContentPos(startPos, endPos, false);
paragraph.SetThisElementCurrent();
this.logicDocument.UpdateSelection();
this.logicDocument.UpdateInterface();
this.logicDocument.UpdateTracks();
};
CustomMarks.prototype.removeRange = function(paraId, handlerId, rangeId)
{
let paragraph = AscCommon.g_oTableId.GetById(paraId);
if (!this.paragraphs[paraId]
|| !this.paragraphs[paraId][handlerId]
|| !this.paragraphs[paraId][handlerId][rangeId])
return;
this.removeMarkFromRun(this.paragraphs[paraId][handlerId][rangeId].start);
this.removeMarkFromRun(this.paragraphs[paraId][handlerId][rangeId].end);
delete this.paragraphs[paraId][handlerId][rangeId];
this._checkEmptyParaHandler(paraId, handlerId);
this._checkEmptyPara(paraId);
if (paragraph)
paragraph.ReDraw();
};
CustomMarks.prototype.removeAllRanges = function(paraId, handlerId)
{
let paragraph = AscCommon.g_oTableId.GetById(paraId);
if (!this.paragraphs[paraId]
|| !this.paragraphs[paraId][handlerId]
|| !this.paragraphs[paraId][handlerId])
return;
for (let rangeId in this.paragraphs[paraId][handlerId])
{
this.removeMarkFromRun(this.paragraphs[paraId][handlerId][rangeId].start);
this.removeMarkFromRun(this.paragraphs[paraId][handlerId][rangeId].end);
}
delete this.paragraphs[paraId][handlerId];
this._checkEmptyPara(paraId);
if (paragraph)
paragraph.ReDraw();
};
CustomMarks.prototype.removeAllMarks = function(handlerId)
{
for (let paraId in this.paragraphs)
{
this.removeAllRanges(paraId, handlerId);
}
};
CustomMarks.prototype.flatRunMarks = function(runId)
{
if (!this.runs[runId])
return null;
let result = [];
this.forEachInRun(runId, function(mark){
result.push(mark);
});
result.sort(function(a, b){
let aPos = a.getPos();
let bPos = b.getPos();
if (aPos === bPos && a.isStart() !== b.isStart())
return a.isStart() ? -1 : 1;
return aPos - bPos;
});
return result;
};
CustomMarks.prototype.onAddToRun = function(runId, pos, count)
{
this.forEachInRun(runId, function(mark){
mark.onAdd(pos, count);
});
};
CustomMarks.prototype.onRemoveFromRun = function(runId, pos, count)
{
this.forEachInRun(runId, function(mark){
mark.onRemove(pos, count);
});
};
CustomMarks.prototype.onSplitRun = function(runId, pos, nextRunId)
{
let _t = this;
let nextRun = AscCommon.g_oTableId.GetById(nextRunId);
this.forEachInRun(runId, function(mark){
mark.onSplit(pos, nextRun);
if (mark.getRun().GetId() === nextRunId)
{
if (_t.runs[runId])
delete _t.runs[runId][mark.getId()];
if (!_t.runs[nextRunId])
_t.runs[nextRunId] = {};
_t.runs[nextRunId][mark.getId()] = mark;
}
});
};
CustomMarks.prototype.onConcatRun = function(runId, runLen, nextRunId)
{
let _t = this;
let prevRun = AscCommon.g_oTableId.GetById(runId);
this.forEachInRun(nextRunId, function(mark){
mark.onConcat(runLen, prevRun);
if (_t.runs[nextRunId])
delete _t.runs[nextRunId][mark.getId()];
if (!_t.runs[runId])
_t.runs[runId] = {};
_t.runs[runId][mark.getId()] = mark;
});
delete this.runs[nextRunId];
};
CustomMarks.prototype.forEachInRun = function(runId, f)
{
for (let id in this.runs[runId])
{
f.call(this, this.runs[runId][id]);
}
};
CustomMarks.prototype._checkEmptyParaHandler = function(paraId, handlerId)
{
if (!this.paragraphs[paraId] || !this.paragraphs[paraId][handlerId])
return;
for (let rangeId in this.paragraphs[paraId][handlerId])
{
return;
}
delete this.paragraphs[paraId][handlerId];
};
CustomMarks.prototype._checkEmptyPara = function(paraId)
{
if (!this.paragraphs[paraId])
return;
for (let handlerId in this.paragraphs[paraId])
{
return;
}
delete this.paragraphs[paraId];
};
let idCounter = 0;
function getNextId()
{
return ++idCounter;
}
/**
* @param run {AscWord.Run}
* @param pos {number}
* @param paragraph {AscWord.Paragraph}
* @param handlerId {string}
* @param rangeId {string}
* @constructor
*/
function CustomMark(run, pos, paragraph, handlerId, rangeId)
{
this.id = getNextId();
this.run = run;
this.paragraph = paragraph;
this.pos = pos;
this.handlerId = handlerId;
this.rangeId = rangeId;
}
CustomMark.prototype.getId = function()
{
return this.id;
};
CustomMark.prototype.getRangeId = function()
{
return this.rangeId;
};
CustomMark.prototype.getHandlerId = function()
{
return this.handlerId;
};
CustomMark.prototype.isStart = function()
{
return true;
};
CustomMark.prototype.onAdd = function(pos, count)
{
if (this.pos >= pos)
this.pos += count;
};
CustomMark.prototype.onRemove = function(pos, count)
{
if (this.pos > pos + count)
this.pos -= count;
else if (this.pos > pos)
this.pos = Math.max(0, pos);
};
CustomMark.prototype.onSplit = function(pos, nextRun)
{
if (this.pos < pos)
return;
this.pos -= pos;
this.run = nextRun;
};
CustomMark.prototype.onConcat = function(pos, prevRun)
{
this.pos += pos;
this.run = prevRun;
};
CustomMark.prototype.getPos = function()
{
return this.pos;
};
CustomMark.prototype.getRun = function()
{
return this.run;
};
CustomMark.prototype.getParagraph = function()
{
return this.run ? this.run.GetParagraph() : null;
};
CustomMark.prototype.getParaPos = function()
{
let paragraph = this.getParagraph();
let paraPos = paragraph ? paragraph.GetPosByElement(this.run) : null;
if (!paraPos)
return new AscWord.CParagraphContentPos();
paraPos.Update(this.pos, paraPos.GetDepth() + 1);
return paraPos;
};
/**
* Метка начала промежутка
* @constructor
*/
function CustomMarkStart()
{
CustomMark.apply(this, arguments);
}
CustomMarkStart.prototype = Object.create(CustomMark.prototype);
CustomMarkStart.prototype.constructor = CustomMarkStart;
CustomMarkStart.prototype.isStart = function()
{
return true;
};
/**
* Метка окончания промежутка
* @constructor
*/
/**
* Метка начала промежутка
* @constructor
*/
function CustomMarkEnd()
{
CustomMark.apply(this, arguments);
}
CustomMarkEnd.prototype = Object.create(CustomMark.prototype);
CustomMarkEnd.prototype.constructor = CustomMarkEnd;
CustomMarkEnd.prototype.isStart = function()
{
return false;
};
//--------------------------------------------------------export----------------------------------------------------
AscWord.CustomMarks = CustomMarks;
AscWord.CustomMarkStart = CustomMarkStart;
AscWord.CustomMarkEnd = CustomMarkEnd;
})(window);