/* * (c) Copyright Ascensio System SIA 2010-2024 * * 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"; // Import var g_oTextMeasurer = AscCommon.g_oTextMeasurer; var History = AscCommon.History; /** * Класс реализующий w:abstractNum * @constructor */ function CAbstractNum() { this.Id = AscCommon.g_oIdCounter.Get_NewId(); this.Lock = new AscCommon.CLock(); if (false === AscCommon.g_oIdCounter.m_bLoad) { this.Lock.Set_Type(AscCommon.c_oAscLockTypes.kLockTypeMine, false); if (typeof AscCommon.CollaborativeEditing !== "undefined") AscCommon.CollaborativeEditing.Add_Unlock2(this); } this.Numbering = null; // Link to the main class this.NumStyleLink = undefined; this.StyleLink = undefined; this.nsid = undefined; this.Lvl = []; for (var nLvl = 0; nLvl < 9; ++nLvl) { this.Lvl[nLvl] = new CNumberingLvl(); } this.MultiLvlType = Asc.c_oAbstractNumMultiLvlTypes.MultiLevel; // Добавляем данный класс в таблицу Id (обязательно в конце конструктора) AscCommon.g_oTableId.Add(this, this.Id); } CAbstractNum.prototype.Get_Id = function() { return this.Id; }; CAbstractNum.prototype.GetId = function() { return this.Id; }; CAbstractNum.prototype.SetParent = function(parent) { this.Numbering = parent; }; CAbstractNum.prototype.Copy = function(oAbstractNum) { this.SetStyleLink(oAbstractNum.StyleLink); this.SetNumStyleLink(oAbstractNum.NumStyleLink); for (var nLvl = 0; nLvl < 9; ++nLvl) { var oLvlNew = oAbstractNum.Lvl[nLvl].Copy(); var oLvlOld = this.Lvl[nLvl]; History.Add(new AscDFH.CChangesAbstractNumLvlChange(this, oLvlOld, oLvlNew, nLvl)); this.Lvl[nLvl] = oLvlNew; } }; CAbstractNum.prototype.SetStyleLink = function(sValue) { if (sValue !== this.StyleLink) { History.Add(new AscDFH.CChangesAbstractNumStyleLink(this, this.StyleLink, sValue)); this.StyleLink = sValue; } }; CAbstractNum.prototype.GetStyleLink = function() { return this.StyleLink; }; CAbstractNum.prototype.SetNumStyleLink = function(sValue) { if (sValue !== this.NumStyleLink) { History.Add(new AscDFH.CChangesAbstractNumNumStyleLink(this, this.NumStyleLink, sValue)); this.NumStyleLink = sValue; } }; CAbstractNum.prototype.GetNumStyleLink = function() { return this.NumStyleLink; }; CAbstractNum.prototype.SetNsid = function(nsid) { if (this.nsid === nsid) return false; AscCommon.History.Add(new AscDFH.CChangesAbstractNumNsid(this, this.nsid, nsid)); this.nsid = nsid; }; CAbstractNum.prototype.GetNsid = function() { return this.nsid; }; CAbstractNum.prototype.RecalculateRelatedParagraphs = function(nLvl) { if (nLvl < 0 || nLvl > 8) nLvl = undefined; let logicDocument = editor.WordControl.m_oLogicDocument; if (!logicDocument || !logicDocument.IsDocumentEditor()) return; let numberingManager = logicDocument.GetNumbering(); numberingManager.GetAllNumsByAbstractNum(this).forEach(function(num) { num.RecalculateRelatedParagraphs(nLvl); }); }; CAbstractNum.prototype.GetMultiLvlType = function() { return this.MultiLvlType; }; CAbstractNum.prototype.SetMultiLvlType = function(nMultiLvlType) { this.MultiLvlType = nMultiLvlType; }; /** * Получаем заданный уровень * @param nLvl {number} * @returns {CNumberingLvl} */ CAbstractNum.prototype.GetLvl = function(nLvl) { if (!this.Lvl[nLvl]) return this.Lvl[0]; return this.Lvl[nLvl]; }; /** * Задаем уровень * @param nLvl {number} * @param oLvlNew {CNumberingLvl} */ CAbstractNum.prototype.SetLvl = function(nLvl, oLvlNew) { if ("number" != typeof(nLvl) || nLvl < 0 || nLvl >= 9) return; var oLvlOld = this.Lvl[nLvl]; this.Lvl[nLvl] = oLvlNew; History.Add(new AscDFH.CChangesAbstractNumLvlChange(this, oLvlOld, oLvlNew, nLvl)); this.RecalculateRelatedParagraphs(nLvl); }; /** * Создаем многоуровневый список с заданным пресетом * @param nType {c_oAscMultiLevelNumbering} */ CAbstractNum.prototype.CreateDefault = function(nType) { for (var nLvl = 0; nLvl < 9; ++nLvl) { let lvlOld = this.Lvl[nLvl].Copy(); this.Lvl[nLvl].InitDefault(nLvl, nType); History.Add(new AscDFH.CChangesAbstractNumLvlChange(this, lvlOld, this.Lvl[nLvl].Copy(), nLvl)); this.RecalculateRelatedParagraphs(nLvl); } }; /** * Делаем заданный уровень заданного пресета * @param nLvl {number} 0..8 * @param nType {c_oAscNumberingLevel} * @param [sText=undefined] Используется для типа c_oAscNumberingLevel.Bullet * @param [oTextPr=undefined] {CTextPr} Используется для типа c_oAscNumberingLevel.Bullet */ CAbstractNum.prototype.SetLvlByType = function(nLvl, nType, sText, oTextPr) { if ("number" !== typeof(nLvl) || nLvl < 0 || nLvl >= 9) return; var oLvlOld = this.Lvl[nLvl].Copy(); this.Lvl[nLvl].SetByType(nType, nLvl, sText, oTextPr); History.Add(new AscDFH.CChangesAbstractNumLvlChange(this, oLvlOld, this.Lvl[nLvl].Copy(), nLvl)); this.RecalculateRelatedParagraphs(nLvl); }; /** * Заполняем уровень по заданному формату * @param nLvl {number} 0..8 * @param nType * @param sFormatText * @param nAlign */ CAbstractNum.prototype.SetLvlByFormat = function(nLvl, nType, sFormatText, nAlign) { if ("number" !== typeof(nLvl) || nLvl < 0 || nLvl >= 9) return; var oLvlOld = this.Lvl[nLvl].Copy(); this.Lvl[nLvl].SetByFormat(nLvl, nType, sFormatText, nAlign); History.Add(new AscDFH.CChangesAbstractNumLvlChange(this, oLvlOld, this.Lvl[nLvl].Copy(), nLvl)); this.RecalculateRelatedParagraphs(nLvl); }; /** * Связываем заданный уровень с заданным стилем * @param iLvl {number} 0..8 * @param styleId {string} */ CAbstractNum.prototype.SetLvlPStyle = function(iLvl, styleId) { if ("number" !== typeof(iLvl) || iLvl < 0 || iLvl >= 9) return; var oLvlOld = this.Lvl[iLvl].Copy(); this.Lvl[iLvl].SetPStyle(styleId); History.Add(new AscDFH.CChangesAbstractNumLvlChange(this, oLvlOld, this.Lvl[iLvl].Copy(), iLvl)); }; /** * Выставляем является ли данный уровень сквозным или каждый раз перестартовывать нумерацию * @param nLvl {number} 0..8 * @param isRestart {boolean} */ CAbstractNum.prototype.SetLvlRestart = function(nLvl, isRestart) { if ("number" !== typeof(nLvl) || nLvl < 0 || nLvl >= 9) return; var oLvlOld = this.Lvl[nLvl].Copy(); this.Lvl[nLvl].Restart = (isRestart ? -1 : 0); History.Add(new AscDFH.CChangesAbstractNumLvlChange(this, oLvlOld, this.Lvl[nLvl].Copy(), nLvl)); }; /** * Задаем начальное значения для данного уровня * @param nLvl {number} 0..8 * @param nStart {number} */ CAbstractNum.prototype.SetLvlStart = function(nLvl, nStart) { if ("number" !== typeof(nLvl) || nLvl < 0 || nLvl >= 9) return; var oLvlOld = this.Lvl[nLvl].Copy(); this.Lvl[nLvl].Start = nStart; History.Add(new AscDFH.CChangesAbstractNumLvlChange(this, oLvlOld, this.Lvl[nLvl].Copy(), nLvl)); }; /** * Получаем начальное значение для заданного уровня * @param nLvl {number} 0..8 * @returns {number} */ CAbstractNum.prototype.GetLvlStart = function(nLvl) { if ("number" !== typeof(nLvl) || nLvl < 0 || nLvl >= 9) return 1; return this.Lvl[nLvl].Start; }; /** * Выставляем тип разделителя между табом и последующим текстом * @param nLvl {number} 0..8 * @param nSuff {number} */ CAbstractNum.prototype.SetLvlSuff = function(nLvl, nSuff) { if ("number" !== typeof(nLvl) || nLvl < 0 || nLvl >= 9) return; var oLvlOld = this.Lvl[nLvl].Copy(); this.Lvl[nLvl].Suff = nSuff; History.Add(new AscDFH.CChangesAbstractNumLvlChange(this, oLvlOld, this.Lvl[nLvl].Copy(), nLvl)); }; /** * Применяем новые тектовые настройки к данной нумерации на заданном уровне * @param nLvl {number} 0..8 * @param oTextPr {CTextPr} */ CAbstractNum.prototype.ApplyTextPr = function(nLvl, oTextPr) { var oTextPrOld = this.Lvl[nLvl].TextPr.Copy(); this.Lvl[nLvl].TextPr.Merge(oTextPr); History.Add(new AscDFH.CChangesAbstractNumTextPrChange(this, oTextPrOld, this.Lvl[nLvl].TextPr.Copy(), nLvl)); }; /** * Выставляем текстовые настройки для заданного уровня * @param nLvl {number} 0..8 * @param oTextPr {CTextPr} */ CAbstractNum.prototype.SetTextPr = function(nLvl, oTextPr) { History.Add(new AscDFH.CChangesAbstractNumTextPrChange(this, this.Lvl[nLvl].TextPr, oTextPr.Copy(), nLvl)); this.Lvl[nLvl].TextPr = oTextPr; }; /** * Выставляем настройки параграфа для заданного уровня * @param nLvl {number} 0..8 * @param oParaPr {CParaPr} */ CAbstractNum.prototype.SetParaPr = function(nLvl, oParaPr) { History.Add(new AscDFH.CChangesAbstractNumParaPrChange(this, this.Lvl[nLvl].ParaPr, oParaPr.Copy(), nLvl)); this.Lvl[nLvl].ParaPr = oParaPr; }; //---------------------------------------------------------------------------------------------------------------------- // Undo/Redo функции //---------------------------------------------------------------------------------------------------------------------- CAbstractNum.prototype.Refresh_RecalcData = function(Data) { var oHistory = History; if (!oHistory) return; if (!oHistory.AddChangedNumberingToRecalculateData(this.Get_Id(), Data.Index, this)) return; var oLogicDocument = editor.WordControl.m_oLogicDocument; if (!oLogicDocument) return; var oNumbering = oLogicDocument.GetNumbering(); var arrNumPr = []; for (var sId in oNumbering.Num) { var oNum = oNumbering.Num[sId]; if (this.Id === oNum.GetAbstractNumId()) { arrNumPr.push(new AscWord.NumPr(oNum.GetId(), Data.Index)); } } var arrAllParagraphs = oLogicDocument.GetAllParagraphsByNumbering(arrNumPr); for (var nIndex = 0, nCount = arrAllParagraphs.length; nIndex < nCount; ++nIndex) { arrAllParagraphs[nIndex].Refresh_RecalcData({Type : AscDFH.historyitem_Paragraph_Numbering}); } }; CAbstractNum.prototype.Document_Is_SelectionLocked = function(nCheckType) { return this.IsSelectionLocked(nCheckType); }; CAbstractNum.prototype.IsSelectionLocked = function(nCheckType) { switch (nCheckType) { case AscCommon.changestype_Paragraph_Content: case AscCommon.changestype_Paragraph_Properties: case AscCommon.changestype_Paragraph_AddText: case AscCommon.changestype_Paragraph_TextProperties: case AscCommon.changestype_ContentControl_Add: { this.Lock.Check(this.Get_Id()); break; } case AscCommon.changestype_Document_Content: case AscCommon.changestype_Document_Content_Add: case AscCommon.changestype_Image_Properties: { AscCommon.CollaborativeEditing.Add_CheckLock(true); break; } } }; //---------------------------------------------------------------------------------------------------------------------- // Функции для работы с совместным редактирования //---------------------------------------------------------------------------------------------------------------------- CAbstractNum.prototype.Write_ToBinary2 = function(Writer) { Writer.WriteLong(AscDFH.historyitem_type_AbstractNum); // String : Id // String : StyleLink // String : NumStyleLink // Variable[9 Lvl] : 9 уровней // Long : nsid Writer.WriteString2(this.Id); Writer.WriteString2(this.StyleLink ? this.StyleLink : ""); Writer.WriteString2(this.NumStyleLink ? this.NumStyleLink : ""); for (var nLvl = 0; nLvl < 9; ++nLvl) this.Lvl[nLvl].WriteToBinary(Writer); Writer.WriteLong(this.nsid ? this.nsid : 0); }; CAbstractNum.prototype.Read_FromBinary2 = function(Reader) { // String : Id // String : StyleLink // String : NumStyleLink // Variable[9 Lvl] : 9 уровней this.Id = Reader.GetString2(); this.StyleLink = Reader.GetString2(); this.NumStyleLink = Reader.GetString2(); if ("" === this.StyleLink) this.StyleLink = undefined; if ("" === this.NumStyleLink) this.NumStyleLink = undefined; for (var nLvl = 0; nLvl < 9; ++nLvl) { this.Lvl[nLvl] = new CNumberingLvl(); this.Lvl[nLvl].ReadFromBinary(Reader); } this.nsid = Reader.GetLong(); if (0 === this.nsid) this.nsid = undefined; // Если мы создали нумерацию с nsid, который уже был занят, то далее мы его меняем на не занятый // Тут при добавлении уже тоже должен быть занят этот nsid // TODO: Нужно перенести в сам класс нумерации // Добавим данный список в нумерацию let numbering = editor.WordControl.m_oLogicDocument.Get_Numbering(); numbering._AddAbstractNum(this, this.GetId()); }; CAbstractNum.prototype.Process_EndLoad = function(Data) { var iLvl = Data.iLvl; if (undefined !== iLvl) { // Пересчитываем стили у все параграфов с данной нумерацией this.Recalc_CompiledPr(iLvl); } }; CAbstractNum.prototype.Recalc_CompiledPr = function(nLvl) { // Ищем все параграфы, который используют данную нумерацию и проставляем у них, то что их стиль // нужно перекомпилировать. this.RecalculateRelatedParagraphs(nLvl); }; CAbstractNum.prototype.isEqual = function(abstractNum) { var lvlUsuallyAdd = this.Lvl; var lvlNew = abstractNum.Lvl; for (var lvl = 0; lvl < lvlUsuallyAdd.length; lvl++) { var LvlTextEqual = null; var ParaPrEqual = null; var TextPrEqual = null; if (lvlUsuallyAdd[lvl].Format == lvlNew[lvl].Format && lvlUsuallyAdd[lvl].Jc == lvlNew[lvl].Jc && lvlUsuallyAdd[lvl].PStyle == lvlNew[lvl].PStyle && lvlUsuallyAdd[lvl].Restart == lvlNew[lvl].Restart && lvlUsuallyAdd[lvl].Start == lvlNew[lvl].Start && lvlUsuallyAdd[lvl].Suff == lvlNew[lvl].Suff) { LvlTextEqual = this._isEqualLvlText(lvlUsuallyAdd[lvl].LvlText, lvlNew[lvl].LvlText); ParaPrEqual = lvlUsuallyAdd[lvl].ParaPr.isEqual(lvlUsuallyAdd[lvl].ParaPr, lvlNew[lvl].ParaPr); TextPrEqual = lvlUsuallyAdd[lvl].TextPr.isEqual(lvlUsuallyAdd[lvl].TextPr, lvlNew[lvl].TextPr); } if (!LvlTextEqual || !ParaPrEqual || !TextPrEqual) return false; } return true; }; CAbstractNum.prototype._isEqualLvlText = function(LvlTextOld, LvlTextNew) { if (LvlTextOld.length !== LvlTextNew.length) return false; for (var LvlText = 0; LvlText < LvlTextOld.length; LvlText++) { if (LvlTextOld[LvlText].Type != LvlTextNew[LvlText].Type || LvlTextOld[LvlText].Value != LvlTextNew[LvlText].Value) return false; } return true; }; //--------------------------------------------------------export-------------------------------------------------------- window['AscWord'] = window['AscWord'] || {}; window['AscWord'].CAbstractNum = CAbstractNum;