1176 lines
32 KiB
JavaScript
1176 lines
32 KiB
JavaScript
/*
|
||
* (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";
|
||
|
||
/**
|
||
* Класс представляющий нумерацию параграфов в документах
|
||
* @param {AscWord.CNumbering} oNumbering - ссылка на главный объект нумерации в документах
|
||
* @param {string} sAbstractNumId - идентификатор абстрактной нумерации
|
||
* @constructor
|
||
*/
|
||
function CNum(oNumbering, sAbstractNumId)
|
||
{
|
||
this.Id = AscCommon.g_oIdCounter.Get_NewId();
|
||
|
||
this.Lock = new AscCommon.CLock();
|
||
if (!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.AbstractNumId = sAbstractNumId ? sAbstractNumId : null;
|
||
this.LvlOverride = [];
|
||
this.Numbering = oNumbering;
|
||
|
||
// Добавляем данный класс в таблицу Id (обязательно в конце конструктора)
|
||
AscCommon.g_oTableId.Add(this, this.Id);
|
||
}
|
||
CNum.prototype.Get_Id = function()
|
||
{
|
||
return this.Id;
|
||
};
|
||
/**
|
||
* Идентификатор данного объекта
|
||
* @returns {string}
|
||
*/
|
||
CNum.prototype.GetId = function()
|
||
{
|
||
return this.Id;
|
||
};
|
||
/**
|
||
* Создаем копию данной нумерации
|
||
* @returns {CNum}
|
||
*/
|
||
CNum.prototype.Copy = function()
|
||
{
|
||
var oNum = this.Numbering.CreateNum();
|
||
|
||
var oNewAbstractNum = this.Numbering.GetAbstractNum(oNum.AbstractNumId);
|
||
var oAbstractNum = this.Numbering.GetAbstractNum(this.AbstractNumId);
|
||
|
||
if (oAbstractNum && oNewAbstractNum)
|
||
oNewAbstractNum.Copy(oAbstractNum);
|
||
|
||
for (var nLvl = 0; nLvl < 9; ++nLvl)
|
||
{
|
||
if (this.LvlOverride[nLvl] && this.LvlOverride[nLvl].NumberingLvl)
|
||
oNum.SetLvlOverride(this.LvlOverride[nLvl].GetLvl().Copy(), nLvl, this.LvlOverride[nLvl].GetStartOverride());
|
||
}
|
||
|
||
return oNum;
|
||
};
|
||
/**
|
||
* Получаем заданный уровень
|
||
* @param nLvl {number} 0..8
|
||
* @returns {CNumberingLvl}
|
||
*/
|
||
CNum.prototype.GetLvl = function(nLvl)
|
||
{
|
||
if (this.private_HaveLvlOverride(nLvl))
|
||
return this.LvlOverride[nLvl].GetLvl();
|
||
|
||
var oAbstractNum = this.Numbering.GetAbstractNum(this.AbstractNumId);
|
||
if (!oAbstractNum)
|
||
return new CNumberingLvl();
|
||
|
||
return oAbstractNum.GetLvl(nLvl);
|
||
};
|
||
/**
|
||
* Создаем многоуровневый список с заданным пресетом
|
||
* @param nType {c_oAscMultiLevelNumbering}
|
||
*/
|
||
CNum.prototype.CreateDefault = function(nType)
|
||
{
|
||
var oAbstractNum = this.Numbering.GetAbstractNum(this.AbstractNumId);
|
||
if (!oAbstractNum)
|
||
return;
|
||
|
||
oAbstractNum.CreateDefault(nType);
|
||
this.ClearAllLvlOverride();
|
||
};
|
||
/**
|
||
* Задаем новый уровень нумерации
|
||
* @param oNumberingLvl {CNumberingLvl}
|
||
* @param nLvl {number} 0..8
|
||
*/
|
||
CNum.prototype.SetLvl = function(oNumberingLvl, nLvl)
|
||
{
|
||
if ("number" !== typeof(nLvl) || nLvl < 0 || nLvl >= 9)
|
||
return;
|
||
|
||
if (this.private_HaveLvlOverride(nLvl))
|
||
{
|
||
this.SetLvlOverride(oNumberingLvl, nLvl);
|
||
}
|
||
else
|
||
{
|
||
var oAbstractNum = this.Numbering.GetAbstractNum(this.AbstractNumId);
|
||
if (!oAbstractNum)
|
||
return;
|
||
|
||
oAbstractNum.SetLvl(nLvl, oNumberingLvl);
|
||
}
|
||
};
|
||
/**
|
||
* Заполняем настройки уровня из интерфейсного класса
|
||
* @param oAscNumberingLvl {CAscNumberingLvl}
|
||
* @param nLvl {number} 0..8
|
||
*/
|
||
CNum.prototype.SetAscLvl = function(oAscNumberingLvl, nLvl)
|
||
{
|
||
var oNumberingLvl = new CNumberingLvl();
|
||
oNumberingLvl.FillFromAscNumberingLvl(oAscNumberingLvl);
|
||
this.SetLvl(oNumberingLvl, nLvl);
|
||
};
|
||
/**
|
||
* Делаем заданный уровень заданного пресета
|
||
* @param nLvl {number} 0..8
|
||
* @param nType {c_oAscNumberingLevel}
|
||
* @param [sText=undefined] Используется для типа c_oAscNumberingLevel.Bullet
|
||
* @param [oTextPr=undefined] {CTextPr} Используется для типа c_oAscNumberingLevel.Bullet
|
||
*/
|
||
CNum.prototype.SetLvlByType = function(nLvl, nType, sText, oTextPr)
|
||
{
|
||
if ("number" !== typeof(nLvl) || nLvl < 0 || nLvl >= 9)
|
||
return;
|
||
|
||
if (this.private_HaveLvlOverride(nLvl))
|
||
{
|
||
var oNumberingLvl = new CNumberingLvl();
|
||
oNumberingLvl.SetByType(nType, nLvl, sText, oTextPr);
|
||
|
||
this.SetLvlOverride(oNumberingLvl, nLvl);
|
||
}
|
||
else
|
||
{
|
||
var oAbstractNum = this.Numbering.GetAbstractNum(this.AbstractNumId);
|
||
if (!oAbstractNum)
|
||
return;
|
||
|
||
oAbstractNum.SetLvlByType(nLvl, nType, sText, oTextPr);
|
||
}
|
||
};
|
||
/**
|
||
* Заполняем уровень по заданному формату
|
||
* @param nLvl {number} 0..8
|
||
* @param nType
|
||
* @param sFormatText
|
||
* @param nAlign
|
||
*/
|
||
CNum.prototype.SetLvlByFormat = function(nLvl, nType, sFormatText, nAlign)
|
||
{
|
||
if ("number" !== typeof(nLvl) || nLvl < 0 || nLvl >= 9)
|
||
return;
|
||
|
||
if (this.private_HaveLvlOverride(nLvl))
|
||
{
|
||
var oNumberingLvl = new CNumberingLvl();
|
||
oNumberingLvl.SetByFormat(nLvl, nType, sFormatText, nAlign);
|
||
|
||
this.SetLvlOverride(oNumberingLvl, nLvl);
|
||
}
|
||
else
|
||
{
|
||
var oAbstractNum = this.Numbering.GetAbstractNum(this.AbstractNumId);
|
||
if (!oAbstractNum)
|
||
return;
|
||
|
||
oAbstractNum.SetLvlByFormat(nLvl, nType, sFormatText, nAlign);
|
||
}
|
||
};
|
||
/**
|
||
* Выставляем является ли данный уровень сквозным или каждый раз перестартовывать нумерацию
|
||
* @param nLvl {number} 0..8
|
||
* @param isRestart {boolean}
|
||
*/
|
||
CNum.prototype.SetLvlRestart = function(nLvl, isRestart)
|
||
{
|
||
if ("number" !== typeof(nLvl) || nLvl < 0 || nLvl >= 9)
|
||
return;
|
||
|
||
if (this.private_HaveLvlOverride(nLvl))
|
||
{
|
||
var oNumberingLvl = this.LvlOverride[nLvl].GetLvl();
|
||
var oNewNumberingLvl = oNumberingLvl.Copy();
|
||
oNewNumberingLvl.Restart = (isRestart ? -1 : 0);
|
||
this.SetLvlOverride(oNewNumberingLvl, nLvl);
|
||
}
|
||
else
|
||
{
|
||
var oAbstractNum = this.Numbering.GetAbstractNum(this.AbstractNumId);
|
||
if (!oAbstractNum)
|
||
return;
|
||
|
||
oAbstractNum.SetLvlRestart(nLvl, isRestart);
|
||
}
|
||
};
|
||
/**
|
||
* Задаем начальное значения для данного уровня
|
||
* @param nLvl {number} 0..8
|
||
* @param nStart {number}
|
||
*/
|
||
CNum.prototype.SetLvlStart = function(nLvl, nStart)
|
||
{
|
||
if ("number" !== typeof(nLvl) || nLvl < 0 || nLvl >= 9)
|
||
return;
|
||
|
||
if (this.private_HaveLvlOverride(nLvl))
|
||
{
|
||
var oNumberingLvl = this.LvlOverride[nLvl].GetLvl();
|
||
var oNewNumberingLvl = oNumberingLvl.Copy();
|
||
oNewNumberingLvl.Start = nStart;
|
||
this.SetLvlOverride(oNewNumberingLvl, nLvl);
|
||
}
|
||
else
|
||
{
|
||
var oAbstractNum = this.Numbering.GetAbstractNum(this.AbstractNumId);
|
||
if (!oAbstractNum)
|
||
return;
|
||
|
||
oAbstractNum.SetLvlStart(nLvl, nStart);
|
||
}
|
||
};
|
||
/**
|
||
* Связываем данную нумерацию с заголовками
|
||
* @param styles {CStyles}
|
||
*/
|
||
CNum.prototype.LinkWithHeadings = function(styles)
|
||
{
|
||
for (let iLvl = 0; iLvl <= 8; ++iLvl)
|
||
{
|
||
this.LinkWithStyle(iLvl, styles.GetDefaultHeading(iLvl), styles);
|
||
}
|
||
};
|
||
/**
|
||
* Связываем заданный уровень с заданным стилем
|
||
* @param {number} iLvl 0..8
|
||
* @param {string} styleId
|
||
* @param {AscWord.CStyles} styleManager
|
||
*/
|
||
CNum.prototype.LinkWithStyle = function(iLvl, styleId, styleManager)
|
||
{
|
||
if ("number" !== typeof(iLvl) || iLvl < 0 || iLvl >= 9)
|
||
return;
|
||
|
||
let numLvl = this.GetLvl(iLvl);
|
||
let pStyle = numLvl.GetPStyle();
|
||
if (pStyle && styleManager.Get(pStyle))
|
||
{
|
||
let oldStyle = styleManager.Get(pStyle);
|
||
oldStyle.SetNumPr(null);
|
||
}
|
||
|
||
let style = styleManager.Get(styleId);
|
||
if (!style)
|
||
return;
|
||
|
||
style.SetNumPr(this.GetId(), iLvl);
|
||
|
||
if (this.private_HaveLvlOverride(iLvl))
|
||
{
|
||
var oNumberingLvl = this.LvlOverride[iLvl].GetLvl();
|
||
var oNewNumberingLvl = oNumberingLvl.Copy();
|
||
oNewNumberingLvl.SetPStyle(styleId);
|
||
this.SetLvlOverride(oNewNumberingLvl, iLvl);
|
||
}
|
||
else
|
||
{
|
||
var oAbstractNum = this.Numbering.GetAbstractNum(this.AbstractNumId);
|
||
if (!oAbstractNum)
|
||
return;
|
||
|
||
oAbstractNum.SetLvlPStyle(iLvl, styleId);
|
||
}
|
||
};
|
||
/**
|
||
* Выставляем тип разделителя между табом и последующим текстом
|
||
* @param nLvl {number} 0..8
|
||
* @param nSuff {number}
|
||
*/
|
||
CNum.prototype.SetLvlSuff = function(nLvl, nSuff)
|
||
{
|
||
if ("number" !== typeof(nLvl) || nLvl < 0 || nLvl >= 9)
|
||
return;
|
||
|
||
if (this.private_HaveLvlOverride(nLvl))
|
||
{
|
||
var oNumberingLvl = this.LvlOverride[nLvl].GetLvl();
|
||
var oNewNumberingLvl = oNumberingLvl.Copy();
|
||
oNewNumberingLvl.Suff = nSuff;
|
||
this.SetLvlOverride(oNewNumberingLvl, nLvl);
|
||
}
|
||
else
|
||
{
|
||
var oAbstractNum = this.Numbering.GetAbstractNum(this.AbstractNumId);
|
||
if (!oAbstractNum)
|
||
return;
|
||
|
||
oAbstractNum.SetLvlSuff(nLvl, nSuff);
|
||
}
|
||
};
|
||
/**
|
||
* Устанавливаем новый уровень
|
||
* @param oNumberingLvl {CNumberingLvl}
|
||
* @param nLvl {number} 0..8
|
||
* @param [nStartOverride=-1]
|
||
*/
|
||
CNum.prototype.SetLvlOverride = function(oNumberingLvl, nLvl, nStartOverride)
|
||
{
|
||
if (nLvl < 0 || nLvl > 8)
|
||
return;
|
||
|
||
if (!oNumberingLvl && !this.LvlOverride[nLvl] && (-1 === nStartOverride || undefined == nStartOverride))
|
||
return;
|
||
|
||
var oLvlOverrideOld = this.LvlOverride[nLvl];
|
||
var oLvlOverrideNew = new CLvlOverride(oNumberingLvl, nLvl, nStartOverride);
|
||
|
||
AscCommon.History.Add(new CChangesNumLvlOverrideChange(this, oLvlOverrideOld, oLvlOverrideNew, nLvl));
|
||
|
||
this.LvlOverride[nLvl] = oLvlOverrideNew;
|
||
this.RecalculateRelatedParagraphs(nLvl);
|
||
};
|
||
/**
|
||
* Удаляем все записи о перекрывании уровней
|
||
*/
|
||
CNum.prototype.ClearAllLvlOverride = function()
|
||
{
|
||
for (var nLvl = 0; nLvl < 9; ++nLvl)
|
||
{
|
||
this.SetLvlOverride(undefined, nLvl);
|
||
}
|
||
};
|
||
/**
|
||
* Изменяем базовую нумерацию
|
||
* @param sId {string}
|
||
*/
|
||
CNum.prototype.SetAbstractNumId = function(sId)
|
||
{
|
||
if (sId !== this.AbstractNumId)
|
||
{
|
||
AscCommon.History.Add(new CChangesNumAbstractNum(this, this.AbstractNumId, sId));
|
||
this.AbstractNumId = sId;
|
||
this.RecalculateRelatedParagraphs(-1);
|
||
}
|
||
};
|
||
/**
|
||
* Сообщаем, что параграфы связанные с заданным уровнем нужно пересчитать
|
||
* @param nLvl {number} 0..8 - заданный уровен, если -1 то для всех уровней
|
||
*/
|
||
CNum.prototype.RecalculateRelatedParagraphs = function(nLvl)
|
||
{
|
||
if (nLvl < 0 || nLvl > 8)
|
||
nLvl = undefined;
|
||
|
||
let logicDocument = editor.WordControl.m_oLogicDocument;
|
||
if (!logicDocument || !logicDocument.IsDocumentEditor())
|
||
return;
|
||
|
||
let styleManager = logicDocument.GetStyles();
|
||
if (undefined !== nLvl)
|
||
{
|
||
let lvl = this.GetLvl(nLvl);
|
||
let style = styleManager.Get(lvl.GetPStyle());
|
||
if (style)
|
||
logicDocument.Add_ChangedStyle(style.GetId());
|
||
}
|
||
else
|
||
{
|
||
for (let iLvl = 0; iLvl <= 8; ++iLvl)
|
||
{
|
||
let lvl = this.GetLvl(iLvl);
|
||
let style = styleManager.Get(lvl.GetPStyle());
|
||
if (style)
|
||
logicDocument.Add_ChangedStyle(style.GetId());
|
||
}
|
||
}
|
||
|
||
logicDocument.GetNumberingCollection().CheckNum(this.Id, nLvl);
|
||
|
||
var arrParagraphs = logicDocument.GetAllParagraphsByNumbering({NumId : this.Id, Lvl : nLvl});
|
||
for (var nIndex = 0, nCount = arrParagraphs.length; nIndex < nCount; ++nIndex)
|
||
{
|
||
arrParagraphs[nIndex].RecalcCompiledPr();
|
||
}
|
||
};
|
||
/**
|
||
* Применяем новые тектовые настройки к данной нумерации на заданном уровне
|
||
* @param nLvl {number} 0..8
|
||
* @param oTextPr {CTextPr}
|
||
*/
|
||
CNum.prototype.ApplyTextPr = function(nLvl, oTextPr)
|
||
{
|
||
if (nLvl < 0 || nLvl > 8)
|
||
return;
|
||
|
||
if (this.private_HaveLvlOverride(nLvl))
|
||
{
|
||
var oNumberingLvl = this.LvlOverride[nLvl].GetLvl();
|
||
var oNewNumberingLvl = oNumberingLvl.Copy();
|
||
oNewNumberingLvl.TextPr.Merge(oTextPr);
|
||
this.SetLvlOverride(oNewNumberingLvl, nLvl);
|
||
}
|
||
else
|
||
{
|
||
var oAbstractNum = this.Numbering.GetAbstractNum(this.AbstractNumId);
|
||
if (!oAbstractNum)
|
||
return;
|
||
|
||
oAbstractNum.ApplyTextPr(nLvl, oTextPr);
|
||
}
|
||
};
|
||
/**
|
||
* Сдвигаем все уровни на заданное значение (оно задается для нулевого уровня)
|
||
* @param nLeftNew {number}
|
||
*/
|
||
CNum.prototype.ShiftLeftInd = function(nLeftNew)
|
||
{
|
||
var oFirstLevel = this.GetLvl(0);
|
||
var nLeftOld = oFirstLevel.ParaPr.Ind.Left ? oFirstLevel.ParaPr.Ind.Left : 0;
|
||
|
||
for (var nLvl = 0; nLvl < 9; ++nLvl)
|
||
{
|
||
var oLvlOld = this.GetLvl(nLvl);
|
||
var oLvlNew = this.GetLvl(nLvl).Copy();
|
||
|
||
oLvlNew.ParaPr.Ind.Left = oLvlOld.ParaPr.Ind.Left ? oLvlOld.ParaPr.Ind.Left - nLeftOld + nLeftNew : nLeftNew - nLeftOld;
|
||
|
||
this.SetLvl(oLvlNew, nLvl);
|
||
}
|
||
};
|
||
/**
|
||
* Получаем Id NumStyleLink
|
||
* @returns {null | string}
|
||
*/
|
||
CNum.prototype.GetNumStyleLink = function()
|
||
{
|
||
var oAbstractNum = this.Numbering.GetAbstractNum(this.AbstractNumId);
|
||
if (!oAbstractNum)
|
||
return null;
|
||
|
||
return oAbstractNum.GetNumStyleLink();
|
||
};
|
||
/**
|
||
* Получаем Id StyleLink
|
||
* @returns {null | string}
|
||
*/
|
||
CNum.prototype.GetStyleLink = function()
|
||
{
|
||
var oAbstractNum = this.Numbering.GetAbstractNum(this.AbstractNumId);
|
||
if (!oAbstractNum)
|
||
return null;
|
||
|
||
return oAbstractNum.GetStyleLink();
|
||
};
|
||
/**
|
||
* Получаем уровень списка по заданном стилю
|
||
* @param sStyleId {string}
|
||
* @returns {number}
|
||
*/
|
||
CNum.prototype.GetLvlByStyle = function(sStyleId)
|
||
{
|
||
for (var nLvl = 0; nLvl < 9; ++nLvl)
|
||
{
|
||
var oLvl = this.GetLvl(nLvl);
|
||
if (oLvl && sStyleId === oLvl.GetPStyle())
|
||
return nLvl;
|
||
}
|
||
|
||
return -1;
|
||
};
|
||
/**
|
||
* Получаем нумерованное значение для заданного уровня с учетом заданого сдвига и формата данного уровня
|
||
* @param nLvl {number} 0..8
|
||
* @param nNumShift {number}
|
||
* @param [isForceArabic=false] {boolean}
|
||
* @param oLangForTextNumbering {AscCommonWord.CLang}
|
||
*/
|
||
CNum.prototype.private_GetNumberedLvlText = function(nLvl, nNumShift, isForceArabic, oLangForTextNumbering)
|
||
{
|
||
var nFormat = this.GetLvl(nLvl).GetFormat();
|
||
if (true === isForceArabic
|
||
&& nFormat !== Asc.c_oAscNumberingFormat.Decimal
|
||
&& nFormat !== Asc.c_oAscNumberingFormat.DecimalZero)
|
||
nFormat = Asc.c_oAscNumberingFormat.Decimal;
|
||
|
||
return AscCommon.IntToNumberFormat(nNumShift, nFormat, {lang: oLangForTextNumbering});
|
||
};
|
||
/**
|
||
* Функция отрисовки заданного уровня нумерации в заданной позиции
|
||
* @param nX
|
||
* @param nY
|
||
* @param oContext
|
||
* @param nLvl
|
||
* @param oNumInfo
|
||
* @param oNumTextPr
|
||
* @param oTheme
|
||
* @param isRtl {boolean}
|
||
*/
|
||
CNum.prototype.Draw = function(nX, nY, oContext, nLvl, oNumInfo, oNumTextPr, oTheme, isRtl)
|
||
{
|
||
var oLvl = this.GetLvl(nLvl);
|
||
var arrText = oLvl.GetLvlText();
|
||
var dKoef = oNumTextPr.VertAlign !== AscCommon.vertalign_Baseline ? AscCommon.vaKSize : 1;
|
||
|
||
oContext.SetTextPr(oNumTextPr, oTheme);
|
||
g_oTextMeasurer.SetTextPr(oNumTextPr, oTheme);
|
||
|
||
let numDraw = new AscWord.NumBidiDraw();
|
||
numDraw.begin(nX, nY, oContext, g_oTextMeasurer, oNumTextPr, isRtl);
|
||
|
||
for (let i = 0, count = arrText.length; i < count; ++i)
|
||
{
|
||
let element = arrText[i];
|
||
if (numbering_lvltext_Text === element.Type)
|
||
{
|
||
let strValue = element.Value;
|
||
let codePoint = strValue.charCodeAt(0);
|
||
let curCoef = dKoef;
|
||
|
||
let info;
|
||
if ((info = this.ApplyTextPrToCodePoint(codePoint, oNumTextPr)))
|
||
{
|
||
curCoef *= info.FontCoef;
|
||
codePoint = info.CodePoint;
|
||
strValue = String.fromCodePoint(codePoint);
|
||
}
|
||
|
||
numDraw.addTextString(strValue, curCoef);
|
||
}
|
||
else if (numbering_lvltext_Num === element.Type)
|
||
{
|
||
var langForTextNumbering = oNumTextPr.Lang;
|
||
|
||
var nCurLvl = element.Value;
|
||
var T = "";
|
||
|
||
if (nCurLvl < oNumInfo.length)
|
||
T = this.private_GetNumberedLvlText(nCurLvl, oNumInfo[nCurLvl], oLvl.IsLegalStyle() && nCurLvl < nLvl, langForTextNumbering);
|
||
|
||
numDraw.addTextString(T, dKoef);
|
||
}
|
||
}
|
||
|
||
numDraw.end();
|
||
};
|
||
/**
|
||
* Функция пересчета заданного уровня нумерации
|
||
* @param oContext
|
||
* @param nLvl
|
||
* @param oNumInfo
|
||
* @param oNumTextPr
|
||
* @param oTheme
|
||
* @returns {{Width : number, Ascent : number}}
|
||
*/
|
||
CNum.prototype.Measure = function(oContext, nLvl, oNumInfo, oNumTextPr, oTheme)
|
||
{
|
||
var nX = 0;
|
||
|
||
var oLvl = this.GetLvl(nLvl);
|
||
var arrText = oLvl.GetLvlText();
|
||
var dKoef = oNumTextPr.VertAlign !== AscCommon.vertalign_Baseline ? AscCommon.vaKSize : 1;
|
||
|
||
oContext.SetTextPr(oNumTextPr, oTheme);
|
||
oContext.SetFontSlot(AscWord.fontslot_ASCII, dKoef);
|
||
var nAscent = oContext.GetAscender();
|
||
|
||
for (var nTextIndex = 0, nTextLen = arrText.length; nTextIndex < nTextLen; ++nTextIndex)
|
||
{
|
||
switch (arrText[nTextIndex].Type)
|
||
{
|
||
case numbering_lvltext_Text:
|
||
{
|
||
let strValue = arrText[nTextIndex].Value;
|
||
let codePoint = strValue.getUnicodeIterator().value();
|
||
let curCoef = dKoef;
|
||
|
||
let info;
|
||
if ((info = this.ApplyTextPrToCodePoint(codePoint, oNumTextPr)))
|
||
{
|
||
curCoef *= info.FontCoef;
|
||
codePoint = info.CodePoint;
|
||
strValue = String.fromCodePoint(codePoint);
|
||
}
|
||
|
||
var FontSlot = AscWord.GetFontSlotByTextPr(codePoint, oNumTextPr);
|
||
|
||
oContext.SetFontSlot(FontSlot, curCoef);
|
||
nX += oContext.MeasureCode(codePoint).Width;
|
||
|
||
break;
|
||
}
|
||
case numbering_lvltext_Num:
|
||
{
|
||
oContext.SetFontSlot(AscWord.fontslot_ASCII, dKoef);
|
||
var nCurLvl = arrText[nTextIndex].Value;
|
||
var sLangForTextNumbering = oNumTextPr.Lang;
|
||
var T = "";
|
||
|
||
if (nCurLvl < oNumInfo.length)
|
||
T = this.private_GetNumberedLvlText(nCurLvl, oNumInfo[nCurLvl], oLvl.IsLegalStyle() && nCurLvl < nLvl, sLangForTextNumbering);
|
||
|
||
for (var iter = T.getUnicodeIterator(); iter.check(); iter.next())
|
||
{
|
||
var CharCode = iter.value();
|
||
nX += oContext.MeasureCode(CharCode).Width;
|
||
}
|
||
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
return {
|
||
Width : nX,
|
||
Ascent : nAscent
|
||
};
|
||
};
|
||
/**
|
||
* Составляем список всех используемых символов
|
||
* @param oFontCharMap
|
||
* @param nLvl {number} 0..8
|
||
* @param oNumInfo
|
||
* @param oNumTextPr {CTextPr}
|
||
*/
|
||
CNum.prototype.CreateFontCharMap = function(oFontCharMap, nLvl, oNumInfo, oNumTextPr)
|
||
{
|
||
oFontCharMap.StartFont(oNumTextPr.FontFamily.Name, oNumTextPr.Bold, oNumTextPr.Italic, oNumTextPr.FontSize);
|
||
|
||
var arrText = this.GetLvl(nLvl).GetLvlText();
|
||
for (var nIndex = 0, nCount = arrText.length; nIndex < nCount; ++nIndex)
|
||
{
|
||
switch (arrText[nIndex].Type)
|
||
{
|
||
case numbering_lvltext_Text:
|
||
{
|
||
oFontCharMap.AddChar(arrText[nIndex].Value);
|
||
break;
|
||
}
|
||
case numbering_lvltext_Num:
|
||
{
|
||
var nCurLvl = arrText[nIndex].Value;
|
||
|
||
var T = "";
|
||
if (nCurLvl < oNumInfo.length)
|
||
T = this.private_GetNumberedLvlText(nCurLvl, oNumInfo[nCurLvl]);
|
||
|
||
for (var Index2 = 0; Index2 < T.length; Index2++)
|
||
{
|
||
var Char = T.charAt(Index2);
|
||
oFontCharMap.AddChar(Char);
|
||
}
|
||
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
};
|
||
/**
|
||
* Получаем список всех используемых шрифтов
|
||
* @param arrAllFonts {array}
|
||
*/
|
||
CNum.prototype.GetAllFontNames = function(arrAllFonts)
|
||
{
|
||
for (var nLvl = 0; nLvl < 9; ++nLvl)
|
||
{
|
||
var oLvl = this.GetLvl(nLvl);
|
||
|
||
if (oLvl)
|
||
oLvl.GetTextPr().GetAllFontNames(arrAllFonts);
|
||
}
|
||
};
|
||
/**
|
||
* Получаем текст нумерации для заданного уровня
|
||
* @param nLvl {number} 0..8
|
||
* @param oNumInfo
|
||
* @param bWithoutLastLvlText {?boolean}
|
||
* @param [oLang] {AscCommonWord.CLang}
|
||
* @returns {string}
|
||
*/
|
||
CNum.prototype.GetText = function(nLvl, oNumInfo, bWithoutLastLvlText, oLang)
|
||
{
|
||
var oLvl = this.GetLvl(nLvl);
|
||
var arrText = oLvl.GetLvlText();
|
||
|
||
var sResult = "";
|
||
for (var Index = 0; Index < arrText.length; Index++)
|
||
{
|
||
switch (arrText[Index].Type)
|
||
{
|
||
case numbering_lvltext_Text:
|
||
{
|
||
if(bWithoutLastLvlText && Index === arrText.length - 1)
|
||
{
|
||
break;
|
||
}
|
||
sResult += arrText[Index].Value;
|
||
break;
|
||
}
|
||
case numbering_lvltext_Num:
|
||
{
|
||
var nCurLvl = arrText[Index].Value;
|
||
if (nCurLvl < oNumInfo.length)
|
||
sResult += this.private_GetNumberedLvlText(nCurLvl, oNumInfo[nCurLvl], oLvl.IsLegalStyle(), oLang);
|
||
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
return sResult;
|
||
};
|
||
/**
|
||
* Обрабатываем окончание загрузки изменений
|
||
* @param oData
|
||
*/
|
||
CNum.prototype.Process_EndLoad = function(oData)
|
||
{
|
||
if (undefined !== oData.Lvl)
|
||
this.RecalculateRelatedParagraphs(oData.Lvl);
|
||
};
|
||
/**
|
||
* Проверяем есть ли у нас LvlOverride с перезаписанным уровнем
|
||
* @param nLvl {number} 0..8
|
||
* @returns {boolean}
|
||
*/
|
||
CNum.prototype.private_HaveLvlOverride = function(nLvl)
|
||
{
|
||
return !!(this.LvlOverride[nLvl] && this.LvlOverride[nLvl].GetLvl());
|
||
};
|
||
/**
|
||
* Получаем связанную абстрактную нумерацию
|
||
* @returns {CAbstractNum}
|
||
*/
|
||
CNum.prototype.GetAbstractNum = function()
|
||
{
|
||
return this.Numbering.GetAbstractNum(this.AbstractNumId);
|
||
};
|
||
/**
|
||
* Получаем идентификатор связанной абстрактной нумерации
|
||
* @returns {string}
|
||
*/
|
||
CNum.prototype.GetAbstractNumId = function()
|
||
{
|
||
let abstractNum = this.GetAbstractNum();
|
||
return abstractNum ? abstractNum.GetId() : this.AbstractNumId;
|
||
};
|
||
/**
|
||
* Получаем параметр StartOverride для заданного уровня
|
||
* @param nLvl {number} 0..8
|
||
* @returns {number} возвращаем -1, если данный параметр не задан
|
||
*/
|
||
CNum.prototype.GetStartOverride = function(nLvl)
|
||
{
|
||
var oLvlOverride = this.LvlOverride[nLvl];
|
||
if (!oLvlOverride)
|
||
return -1;
|
||
|
||
return oLvlOverride.GetStartOverride();
|
||
};
|
||
/**
|
||
* Проверяем есть ли у данной нумерации уровни с текстом, зависящим от других уровней
|
||
* @returns {boolean}
|
||
*/
|
||
CNum.prototype.IsHaveRelatedLvlText = function()
|
||
{
|
||
for (var nLvl = 0; nLvl < 9; ++nLvl)
|
||
{
|
||
var oLvl = this.GetLvl(nLvl);
|
||
var arrLvlText = oLvl.GetLvlText();
|
||
for (var nIndex = 0, nCount = arrLvlText.length; nIndex < nCount; ++nIndex)
|
||
{
|
||
var oLvlText = arrLvlText[nIndex];
|
||
if (numbering_lvltext_Num === oLvlText.Type && nLvl !== oLvlText.Value)
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
};
|
||
/**
|
||
* Выставляем текстовые настройки для заданного уровня
|
||
* @param nLvl {number} 0..8
|
||
* @param oTextPr {CTextPr}
|
||
*/
|
||
CNum.prototype.SetTextPr = function(nLvl, oTextPr)
|
||
{
|
||
if (nLvl < 0 || nLvl > 8)
|
||
return;
|
||
|
||
if (this.private_HaveLvlOverride(nLvl))
|
||
{
|
||
var oNumberingLvl = this.LvlOverride[nLvl].GetLvl();
|
||
var oNewNumberingLvl = oNumberingLvl.Copy();
|
||
oNewNumberingLvl.TextPr = oTextPr;
|
||
this.SetLvlOverride(oNewNumberingLvl, nLvl);
|
||
}
|
||
else
|
||
{
|
||
var oAbstractNum = this.Numbering.GetAbstractNum(this.AbstractNumId);
|
||
if (!oAbstractNum)
|
||
return;
|
||
|
||
oAbstractNum.SetTextPr(nLvl, oTextPr);
|
||
}
|
||
};
|
||
/**
|
||
* Выставляем настройки параграфа для заданного уровня
|
||
* @param nLvl {number} 0..8
|
||
* @param oParaPr {CParaPr}
|
||
*/
|
||
CNum.prototype.SetParaPr = function(nLvl, oParaPr)
|
||
{
|
||
if (nLvl < 0 || nLvl > 8)
|
||
return;
|
||
|
||
if (this.private_HaveLvlOverride(nLvl))
|
||
{
|
||
var oNumberingLvl = this.LvlOverride[nLvl].GetLvl();
|
||
var oNewNumberingLvl = oNumberingLvl.Copy();
|
||
oNewNumberingLvl.ParaPr = oParaPr;
|
||
this.SetLvlOverride(oNewNumberingLvl, nLvl);
|
||
}
|
||
else
|
||
{
|
||
var oAbstractNum = this.Numbering.GetAbstractNum(this.AbstractNumId);
|
||
if (!oAbstractNum)
|
||
return;
|
||
|
||
oAbstractNum.SetParaPr(nLvl, oParaPr);
|
||
}
|
||
};
|
||
/**
|
||
* Заполняем специальный класс для общения с интерфейсом
|
||
* @param oAscNum {CAscNumbering}
|
||
*/
|
||
CNum.prototype.FillToAscNum = function(oAscNum)
|
||
{
|
||
oAscNum.NumId = this.GetId();
|
||
for (var nLvl = 0; nLvl < 9; ++nLvl)
|
||
{
|
||
var oLvl = this.GetLvl(nLvl);
|
||
oLvl.FillToAscNumberingLvl(oAscNum.get_Lvl(nLvl));
|
||
}
|
||
};
|
||
/**
|
||
* Заполняем настройки нумерации из интерфейсного класса
|
||
* @param oAscNum {CAscNumbering}
|
||
*/
|
||
CNum.prototype.FillFromAscNum = function(oAscNum)
|
||
{
|
||
for (var nLvl = 0; nLvl < 9; ++nLvl)
|
||
{
|
||
var oLvl = new CNumberingLvl();
|
||
var oAscLvl = oAscNum.get_Lvl(nLvl);
|
||
oLvl.FillFromAscNumberingLvl(oAscLvl);
|
||
this.SetLvl(oLvl, nLvl);
|
||
}
|
||
};
|
||
/**
|
||
* Проверяем похожи ли две заданные нумерации
|
||
* @param oNum {CNum}
|
||
* @returns {boolean}
|
||
*/
|
||
CNum.prototype.IsSimilar = function(oNum)
|
||
{
|
||
if (!oNum)
|
||
return false;
|
||
|
||
for (var nLvl = 0; nLvl < 9; ++nLvl)
|
||
{
|
||
var oLvl = this.GetLvl(nLvl);
|
||
if (!oLvl.IsSimilar(oNum.GetLvl(nLvl)))
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
};
|
||
/**
|
||
* Проверяем, одинаковы ли две заданные нумерации
|
||
* @param oNum {CNum}
|
||
* @returns {boolean}
|
||
*/
|
||
CNum.prototype.IsEqual = function(oNum)
|
||
{
|
||
if (!oNum)
|
||
return false;
|
||
|
||
for (var nLvl = 0; nLvl < 9; ++nLvl)
|
||
{
|
||
var oLvl = this.GetLvl(nLvl);
|
||
if (!oLvl.IsEqual(oNum.GetLvl(nLvl)))
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
};
|
||
//----------------------------------------------------------------------------------------------------------------------
|
||
// Undo/Redo функции
|
||
//----------------------------------------------------------------------------------------------------------------------
|
||
CNum.prototype.Refresh_RecalcData = function(Data)
|
||
{
|
||
};
|
||
CNum.prototype.Document_Is_SelectionLocked = function(nCheckType)
|
||
{
|
||
return this.IsSelectionLocked(nCheckType);
|
||
};
|
||
CNum.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;
|
||
}
|
||
}
|
||
|
||
var oAbstractNum = this.Numbering.GetAbstractNum(this.AbstractNumId);
|
||
if (oAbstractNum)
|
||
oAbstractNum.IsSelectionLocked(nCheckType);
|
||
};
|
||
//----------------------------------------------------------------------------------------------------------------------
|
||
// Функции для работы с совместным редактирования
|
||
//----------------------------------------------------------------------------------------------------------------------
|
||
CNum.prototype.Write_ToBinary2 = function(oWriter)
|
||
{
|
||
oWriter.WriteLong(AscDFH.historyitem_type_Num);
|
||
|
||
// String : Id
|
||
// String : AbstractNumId
|
||
// Variable[9 Lvl] : LvlOverride
|
||
|
||
oWriter.WriteString2(this.Id);
|
||
oWriter.WriteString2(this.AbstractNumId);
|
||
|
||
for (var nLvl = 0; nLvl < 9; ++nLvl)
|
||
{
|
||
if (this.LvlOverride[nLvl])
|
||
{
|
||
oWriter.WriteBool(true);
|
||
this.LvlOverride[nLvl].WriteToBinary(oWriter);
|
||
}
|
||
else
|
||
{
|
||
oWriter.WriteBool(false);
|
||
}
|
||
}
|
||
};
|
||
CNum.prototype.Read_FromBinary2 = function(oReader)
|
||
{
|
||
// String : Id
|
||
// String : AbstractNumId
|
||
// Variable[9 Lvl] : LvlOverride
|
||
|
||
this.Id = oReader.GetString2();
|
||
this.AbstractNumId = oReader.GetString2();
|
||
|
||
for (var nLvl = 0; nLvl < 9; ++nLvl)
|
||
{
|
||
if (oReader.GetBool())
|
||
{
|
||
this.LvlOverride[nLvl] = new CLvlOverride();
|
||
this.LvlOverride[nLvl].ReadFromBinary();
|
||
}
|
||
}
|
||
|
||
// TODO: Нужно перенести в сам класс нумерации
|
||
if (!this.Numbering)
|
||
this.Numbering = editor.WordControl.m_oLogicDocument.GetNumbering();
|
||
|
||
this.Numbering.AddNum(this);
|
||
};
|
||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// Private area
|
||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
CNum.prototype.ApplyTextPrToCodePoint = function(codePoint, textPr)
|
||
{
|
||
if (!textPr || (!textPr.Caps && !textPr.SmallCaps))
|
||
return null;
|
||
|
||
let resultCodePoint = (String.fromCharCode(codePoint).toUpperCase()).charCodeAt(0);
|
||
if (resultCodePoint === codePoint)
|
||
return null;
|
||
|
||
return {
|
||
CodePoint : resultCodePoint,
|
||
FontCoef : !textPr.Caps ? smallcaps_Koef : 1,
|
||
};
|
||
};
|
||
|
||
|
||
/**
|
||
* Класс реализующий замену уровня в нумерации CNum
|
||
* @param oNumberingLvl {CNumberingLvl}
|
||
* @param nLvl {number} 0..8
|
||
* @param [nStartOverride=-1] {number}
|
||
* @constructor
|
||
*/
|
||
function CLvlOverride(oNumberingLvl, nLvl, nStartOverride)
|
||
{
|
||
this.NumberingLvl = oNumberingLvl;
|
||
this.Lvl = nLvl;
|
||
this.StartOverride = undefined !== nStartOverride ? nStartOverride : -1;
|
||
}
|
||
CLvlOverride.prototype.GetLvl = function()
|
||
{
|
||
return this.NumberingLvl;
|
||
};
|
||
CLvlOverride.prototype.GetStartOverride = function()
|
||
{
|
||
return this.StartOverride;
|
||
};
|
||
CLvlOverride.prototype.WriteToBinary = function(oWriter)
|
||
{
|
||
// Long : Lvl
|
||
// Long : StartOverride
|
||
// bool : isUndefined NumberingLvl
|
||
// false -> CNumberingLvl : NumberingLvl
|
||
|
||
oWriter.WriteLong(this.Lvl);
|
||
oWriter.WriteLong(this.StartOverride);
|
||
|
||
if (this.NumberingLvl)
|
||
{
|
||
oWriter.WriteBool(false);
|
||
this.NumberingLvl.WriteToBinary(oWriter);
|
||
}
|
||
else
|
||
{
|
||
oWriter.WriteBool(true);
|
||
}
|
||
};
|
||
CLvlOverride.prototype.ReadFromBinary = function(oReader)
|
||
{
|
||
// Long : Lvl
|
||
// Long : StartOverride
|
||
// bool : isUndefined NumberingLvl
|
||
// false -> CNumberingLvl : NumberingLvl
|
||
|
||
this.Lvl = oReader.GetLong();
|
||
this.StartOverride = oReader.GetLong();
|
||
this.NumberingLvl = undefined;
|
||
|
||
if (!oReader.GetBool())
|
||
{
|
||
this.NumberingLvl = new CNumberingLvl();
|
||
this.NumberingLvl.ReadFromBinary(oReader);
|
||
}
|
||
};
|
||
|
||
(function(){
|
||
|
||
/**
|
||
* Class for rendering num
|
||
* @constructor
|
||
*/
|
||
function NumBidiDraw()
|
||
{
|
||
this.bidiFlow = new AscWord.BidiFlow(this);
|
||
|
||
this.x = 0;
|
||
this.y = 0;
|
||
|
||
this.graphics = null;
|
||
this.measurer = null;
|
||
this.textPr = null;
|
||
}
|
||
|
||
NumBidiDraw.prototype.begin = function(x, y, graphics, measurer, textPr, isRtl)
|
||
{
|
||
this.x = x;
|
||
this.y = y;
|
||
|
||
this.graphics = graphics;
|
||
this.measurer = measurer;
|
||
this.textPr = textPr;
|
||
|
||
this.bidiFlow.begin(isRtl);
|
||
};
|
||
NumBidiDraw.prototype.addTextString = function(text, fontCoeff)
|
||
{
|
||
for (let iter = text.getUnicodeIterator(); iter.check(); iter.next())
|
||
{
|
||
this.addCodePoint(iter.value(), fontCoeff);
|
||
}
|
||
};
|
||
NumBidiDraw.prototype.addCodePoint = function(codePoint, fontCoeff)
|
||
{
|
||
this.bidiFlow.add([codePoint, fontCoeff], AscBidi.getType(codePoint));
|
||
};
|
||
NumBidiDraw.prototype.end = function()
|
||
{
|
||
this.bidiFlow.end();
|
||
};
|
||
NumBidiDraw.prototype.handleBidiFlow = function(data, direction)
|
||
{
|
||
let codePoint = data[0];
|
||
let fontCoeff = data[1];
|
||
|
||
if (AscBidi.DIRECTION.R === direction && AscBidi.isPairedBracket(codePoint))
|
||
codePoint = AscBidi.getPairedBracket(codePoint);
|
||
|
||
let fontSlot = AscWord.GetFontSlotByTextPr(codePoint, this.textPr);
|
||
|
||
this.graphics.SetFontSlot(fontSlot, fontCoeff);
|
||
this.graphics.FillTextCode(this.x, this.y, codePoint);
|
||
|
||
this.measurer.SetFontSlot(fontSlot, fontCoeff);
|
||
this.x += this.measurer.MeasureCode(codePoint).Width;
|
||
};
|
||
|
||
//--------------------------------------------------------export----------------------------------------------------
|
||
AscWord.NumBidiDraw = NumBidiDraw;
|
||
})();
|
||
|
||
//--------------------------------------------------------export--------------------------------------------------------
|
||
window['AscCommonWord'] = window['AscCommonWord'] || {};
|
||
window['AscCommonWord'].CNum = CNum;
|
||
|
||
window['AscWord'] = window['AscWord'] || {};
|
||
window['AscWord'].CNum = CNum;
|
||
|