/* * (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"; (function(window) { /** * Класс представляющий нумерацию в документе * @constructor */ function CNumbering() { this.AbstractNum = {}; // all abstract nums this.Num = {}; this.AbstractNumByNsid = {}; } /** * Копируем все нумерации и абстрактные нумерации. Возвращаем новые объекты с мапом из старых Id в новые * @param oNumbering {CNumbering} * @returns {{AbstractNum: {}, AbstractMap: {}, Num: {}, NumMap: {}}} */ CNumbering.prototype.CopyAllNums = function(oNumbering) { if (!oNumbering) oNumbering = this; var oAbstractMap = {}; var oNumMap = {}; var oNewAbstractNums = {}; var oNewNums = {} for (var sOldId in this.AbstractNum) { var oOldAbstractNum = this.AbstractNum[sOldId]; var oNewAbstractNum = new CAbstractNum(); var sNewId = oNewAbstractNum.GetId(); oNewAbstractNum.Copy(oOldAbstractNum); oNewAbstractNums[sNewId] = oNewAbstractNum; oAbstractMap[sOldId] = sNewId; } for (var sOldId in this.Num) { var oOldNum = this.Num[sOldId]; var oNewNum = new CNum(oNumbering, oAbstractMap[oOldNum.AbstractNumId]); for (var nLvl = 0; nLvl < 9; ++nLvl) { if (oOldNum.LvlOverride[nLvl] && oOldNum.LvlOverride[nLvl].NumberingLvl) oNewNum.SetLvlOverride(oOldNum.LvlOverride[nLvl].GetLvl().Copy(), nLvl, oOldNum.LvlOverride[nLvl].GetStartOverride()); } var sNewId = oNewNum.GetId(); oNewNums[sNewId] = oNewNum; oNumMap[sOldId] = sNewId; } return { AbstractNum : oNewAbstractNums, AbstractMap : oAbstractMap, Num : oNewNums, NumMap : oNumMap }; }; /** * Удаляем все нумерации */ CNumbering.prototype.Clear = function() { this.AbstractNum = {}; this.Num = {}; this.AbstractNumByNsid = {}; }; /** * Добавляем к текущим абстрактным нумерациям новые * @param {AscWord.CAbstractNum[]} abstractNums */ CNumbering.prototype.AppendAbstractNums = function(abstractNums) { for (let numId in abstractNums) { if (undefined === this.AbstractNum[numId]) this._AddAbstractNum(abstractNums[numId], numId); } }; /** * Добавляем к текущим нумерациям новые * @param oNums */ CNumbering.prototype.AppendNums = function(oNums) { for (var sId in oNums) { if (undefined === this.Num[sId]) this.Num[sId] = oNums[sId]; } }; /** * Создаем новую абстрактную нумерацию * @returns {AscWord.CAbstractNum} */ CNumbering.prototype.CreateAbstractNum = function() { let abstractNum = this._CreateAbstractNumWithUniqueNsid(); this._AddAbstractNum(abstractNum, abstractNum.GetId()); return abstractNum; }; /** * Добавляем абстрактную нумерацию * @param abstractNum {CAbstractNum} * @returns {string} идентификатор нумерации */ CNumbering.prototype.AddAbstractNum = function(abstractNum) { if (!(abstractNum instanceof CAbstractNum)) return; let numId = abstractNum.GetId(); this._AddAbstractNum(abstractNum, numId); return numId; }; /** * Добавляем абстрактную нумерацию * @param oNum {CNum} * @returns {string} идентификатор нумерации */ CNumbering.prototype.AddNum = function(oNum) { if (!(oNum instanceof CNum)) return; var sNumId = oNum.GetId(); this.Num[sNumId] = oNum; return sNumId; }; /** * Доступ к абстрактной нумерации по Id * @param sId * @returns {CAbstractNum} */ CNumbering.prototype.GetAbstractNum = function(sId) { let abstractNum = this.AbstractNum[sId]; let nsid = abstractNum ? abstractNum.GetNsid() : null; if (nsid && this.AbstractNumByNsid[nsid]) abstractNum = this.AbstractNumByNsid[nsid]; if (!abstractNum) return null; if (abstractNum.GetNumStyleLink()) { var oStyles = editor.WordControl.m_oLogicDocument.GetStyles(); var oNumStyle = oStyles.Get(abstractNum.GetNumStyleLink()); if (oNumStyle && oNumStyle.ParaPr.NumPr && undefined !== oNumStyle.ParaPr.NumPr.NumId) { var oStyleNum = this.GetNum(oNumStyle.ParaPr.NumPr.NumId); if (!oStyleNum) return null; return oStyleNum.GetAbstractNum(); } } return abstractNum; }; /** * Создаем новую нумерацию * @returns {CNum} */ CNumbering.prototype.CreateNum = function() { let abstractNum = this._CreateAbstractNumWithUniqueNsid(); this._AddAbstractNum(abstractNum, abstractNum.GetId()); var oNum = new CNum(this, abstractNum.GetId()); this.Num[oNum.GetId()] = oNum; return oNum; }; /** * @param sId * @returns {CNum} */ CNumbering.prototype.GetNum = function(sId) { if (this.Num[sId]) return this.Num[sId]; return null; }; /** * Получаем настройки параграфа для заданного уровня заданной нумерации * @param sNumId {string} * @param nLvl {number} 0..8 * @returns {CParaPr} */ CNumbering.prototype.GetParaPr = function(sNumId, nLvl) { var oNum = this.GetNum(sNumId); if (oNum) return oNum.GetLvl(nLvl).GetParaPr(); return new CParaPr(); }; /** * Получаем формат заданного уровня заданной нумерации * @param sNumId * @param nLvl * @returns {Asc.c_oAscNumberingFormat} */ CNumbering.prototype.GetNumFormat = function(sNumId, nLvl) { var oNum = this.GetNum(sNumId); if (!oNum) return Asc.c_oAscNumberingFormat.Bullet; var oLvl = oNum.GetLvl(nLvl); if (!oLvl) return Asc.c_oAscNumberingFormat.Bullet; return oLvl.Format; }; /** * Проверяем по типам Numbered и Bullet * @param numId {string} * @param iLvl {number} * @param format {Asc.c_oAscNumberingFormat} * @returns {boolean} */ CNumbering.prototype.CheckFormat = function(numId, iLvl, format) { let numFormat = this.GetNumFormat(numId, iLvl); return !!((AscWord.IsBulletedNumbering(format) && AscWord.IsBulletedNumbering(numFormat)) || (AscWord.IsNumberedNumbering(format) && AscWord.IsNumberedNumbering(numFormat))); }; CNumbering.prototype.Draw = function(sNumId, nLvl, nX, nY, oContext, oNumInfo, oTextPr, oTheme, isRtl) { var oNum = this.GetNum(sNumId); return oNum.Draw(nX, nY, oContext, nLvl, oNumInfo, oTextPr, oTheme, isRtl); }; CNumbering.prototype.Measure = function(sNumId, nLvl, oContext, oNumInfo, oTextPr, oTheme) { var oNum = this.GetNum(sNumId); return oNum.Measure(oContext, nLvl, oNumInfo, oTextPr, oTheme); }; /** * Получаем список всех символов используемых в заданном уровне заданной нумерации * @param oFontCharMap * @param oNumTextPr * @param oNumPr * @param oNumInfo */ CNumbering.prototype.CreateFontCharMap = function(oFontCharMap, oNumTextPr, oNumPr, oNumInfo) { var oNum = this.GetNum(oNumPr.NumId); oNum.CreateFontCharMap(oFontCharMap, oNumPr.Lvl, oNumInfo, oNumTextPr); }; /** * Получаем список всех используемых шрифтов * @param arrAllFonts {array} */ CNumbering.prototype.GetAllFontNames = function(arrAllFonts) { for (var sNumId in this.Num) { var oNum = this.GetNum(sNumId); oNum.GetAllFontNames(arrAllFonts); } arrAllFonts["Symbol"] = true; arrAllFonts["Courier New"] = true; arrAllFonts["Wingdings"] = true; }; /** * Получаем текст нумерации для заданного уровня * @param sNumId {string} * @param nLvl {number} 0..8 * @param oNumInfo * @param bWithoutLastLvlText {?boolean} * @param [oLang] {AscCommonWord.CLang} * @returns {string} */ CNumbering.prototype.GetText = function(sNumId, nLvl, oNumInfo, bWithoutLastLvlText, oLang) { var oNum = this.GetNum(sNumId); return oNum.GetText(nLvl, oNumInfo, bWithoutLastLvlText, oLang); }; /** * Проверяем, есть ли обьекты на которые можно ссылаться * @returns {boolean} */ CNumbering.prototype.IsEmpty = function() { return 0 === Object.keys(this.Num).length; }; /** * Получаем список идентификаторов всех нумераций, который основаны на заданной абстрактной * @param abstractNum {AscWord.CAbstractNum} * @returns {AscWord.CNum[]} */ CNumbering.prototype.GetAllNumsByAbstractNum = function(abstractNum) { if (!abstractNum) return []; let abstractNumId = abstractNum.GetId(); let result = []; for (let numId in this.Num) { let num = this.Num[numId]; if (abstractNumId === num.GetAbstractNumId()) result.push(num); } return result; }; CNumbering.prototype._AddAbstractNum = function(abstractNum, numId) { this.AbstractNum[numId] = abstractNum; abstractNum.SetParent(this); let nsid = abstractNum.GetNsid(); if (nsid && !this.AbstractNumByNsid[nsid]) this.AbstractNumByNsid[nsid] = abstractNum; }; CNumbering.prototype._CreateAbstractNumWithUniqueNsid = function() { let abstractNum = new AscWord.CAbstractNum(); let nsid = abstractNum.GetNsid(); // TODO: Need to create a general scheme for obtaining DurableId with check of existing ones let attempts = 100; while (!nsid || (this.AbstractNumByNsid[nsid] && attempts >= 0)) { nsid = AscCommon.CreateDurableId(); attempts -= 1; } if (nsid !== abstractNum.GetNsid()) abstractNum.SetNsid(nsid); return abstractNum; }; //---------------------------------------------------------export--------------------------------------------------- window["AscWord"].CNumbering = CNumbering; window["AscWord"].DEFAULT_NUMBERING = new CNumbering(); })(window);