/* * (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"; // TODO: При расчете таблиц есть один баг, который надо будет поправить в будущем: // при разбиении строки на страницы возможен вариант, когда у каких-то ячеек // убирается содержимое на первой странице, а у каких-то - нет. В данном случае // надо для всех ячеек содержимое переносить на новую страницу(как в Word). // TODO: Несовсем правильно(всмысле не как в Word) обрабатывается верхнее поле ячеек: // особенно это проявляется в таблицах с ненулевым расстоянием между ячейками. // TODO: Оказалось, что параметр "не отрывать от следующего" влияет и на таблицы, если // после параграфа с таким параметром идет таблица. (см. MSFT_FY11Q3_10Q.docx стр. 3) // TODO: Поскольку, расстояния до/после параграфа для первого и последнего параграфов // в ячейке зависит от следующей и предыдущей ячеек, надо включать их в пересчет // TODO: Расчет таблицы происходит по строкам, причем строки расчитываются независимо друг от // друга, вплоть до того, что разные строки могут быть внутри разных рамок, и тогда // эти строки нужно считать отдельными таблицами // Import var align_Left = AscCommon.align_Left; var CMouseMoveData = AscCommon.CMouseMoveData; var g_oTableId = AscCommon.g_oTableId; var linerule_AtLeast = Asc.linerule_AtLeast; var c_oAscError = Asc.c_oAscError; var c_oAscHAnchor = Asc.c_oAscHAnchor; var c_oAscXAlign = Asc.c_oAscXAlign; var c_oAscYAlign = Asc.c_oAscYAlign; var c_oAscVAnchor = Asc.c_oAscVAnchor; var c_oAscCellTextDirection = Asc.c_oAscCellTextDirection; var c_oAscRevisionsChangeType = Asc.c_oAscRevisionsChangeType; var table_Selection_Cell = 0x00; // Селектим целыми ячейками var table_Selection_Text = 0x01; // Селектим текст внутри текущей ячейки var table_Selection_Common = 0x00; var table_Selection_Border = 0x01; var table_Selection_Border_InnerTable = 0x02; var table_Selection_Rows = 0x03; // Селектим по строкам var table_Selection_Columns = 0x04; // Селектим по колонкам var table_Selection_Cells = 0x05; // Селектим только по ячейкам var type_Table = 0x0002; /** * Класс CTable * @constructor * @extends {CDocumentContentElementBase} */ function CTable(DrawingDocument, Parent, Inline, Rows, Cols, TableGrid, bPresentation) { CDocumentContentElementBase.call(this, Parent); this.Markup = new AscCommon.CTableMarkup(this); this.Inline = Inline; this.Lock = new AscCommon.CLock(); // TODO: Когда у g_oIdCounter будет тоже проверка на TurnOff заменить здесь // Когда пользователь сидит 1, мы не лочим параграф на добавлении, т.к. лок не отсылается на сервер в такой // ситуации, а лочим при любом первом действии с параграфом if (false === AscCommon.g_oIdCounter.m_bLoad && true === AscCommon.History.Is_On() && AscCommon.CollaborativeEditing && !AscCommon.CollaborativeEditing.Is_SingleUser()) { this.Lock.Set_Type(AscCommon.c_oAscLockTypes.kLockTypeMine, false); AscCommon.CollaborativeEditing.Add_Unlock2(this); } this.DrawingDocument = DrawingDocument ? DrawingDocument : null; this.LogicDocument = null; if (Parent && Parent.GetLogicDocument) this.LogicDocument = Parent.GetLogicDocument(); else if (this.DrawingDocument) this.LogicDocument = this.DrawingDocument.m_oLogicDocument; this.CompiledPr = { Pr : null, // Скомпилированный (окончательный стиль) NeedRecalc : true // Нужно ли пересчитать скомпилированный стиль }; this.Pr = new CTablePr(); this.Pr.TableW = new CTableMeasurement(tblwidth_Auto, 0); this.bPresentation = bPresentation === true; // TODO: TableLook и TableStyle нужно перемесить в TablePr this.TableStyle = (undefined !== this.DrawingDocument && null !== this.DrawingDocument && this.DrawingDocument.m_oLogicDocument && this.DrawingDocument.m_oLogicDocument.Styles ? this.DrawingDocument.m_oLogicDocument.Styles.Get_Default_TableGrid() : null); this.TableLook = new AscCommon.CTableLook(false, false, false, false, false, false); this.TableLook.SetDefault(); this.TableSumGrid = []; // данный массив будет заполнен после private_RecalculateGrid this.TableGrid = TableGrid ? TableGrid : []; this.TableGridCalc = this.private_CopyTableGrid(); this.CalculatedPageFields = {X : 0, Y : 0, XLimit : 0, YLimit : 0}; this.CalculatedMinWidth = -1; this.CalculatedPctWidth = -1; this.CalculatedTableW = -1; this.CalculatedX = null; this.CalculatedXLimit = null; this.TableWidthRange = 0; this.RecalcInfo = new CTableRecalcInfo(); this.Rows = Rows; this.Cols = Cols; // Массив строк this.Content = []; for ( var Index = 0; Index < Rows; Index++ ) { this.Content[Index] = new CTableRow( this, Cols, TableGrid ); } this.Internal_ReIndexing(0); // Информация о строках (расположение, высота и остальные метрики) this.RowsInfo = []; this.TableRowsBottom = []; this.HeaderInfo = { HeaderRecalculate : false, // В данный момент идет пересчет самих заголовков Count : 0, // Количество строк, входящих в заголовок H : 0, // Суммарная высота, занимаемая заголовком PageIndex : 0, // Страница, на которой лежит исходный заголовок (либо 0, либо 1) Pages : [] }; this.Selection = { Start : false, Use : false, StartPos : { Pos : {Row : 0, Cell : 0}, X : 0, Y : 0, PageIndex : 0, MouseEvent : {ClickCount : 1, Type : AscCommon.g_mouse_event_type_down, CtrlKey : false} }, EndPos : { Pos : {Row : 0, Cell : 0}, X : 0, Y : 0, PageIndex : 0, MouseEvent : {ClickCount : 1, Type : AscCommon.g_mouse_event_type_down, CtrlKey : false} }, Type : table_Selection_Text, Data : null, Type2 : table_Selection_Common, Data2 : null, CurRow : 0 // Специальный параметр, используемый для стрелок вправо/влево }; // this.X_origin - точка, которую нам задали как начальную для рисования таблицы // this.X - фактическая начальная точка для рисования и обсчета таблицы this.X_origin = 0; this.AllowOverlap = true; // Позиция по горизонтали this.PositionH = { RelativeFrom : c_oAscHAnchor.Page, // Относительно чего вычисляем координаты Align : true, // true : В поле Value лежит тип прилегания, false - в поле Value лежит точное значени Value : c_oAscXAlign.Center // }; this.PositionH_Old = undefined; // Позиция по горизонтали this.PositionV = { RelativeFrom : c_oAscVAnchor.Page, // Относительно чего вычисляем координаты Align : true, // true : В поле Value лежит тип прилегания, false - в поле Value лежит точное значени Value : c_oAscYAlign.Center // }; this.PositionV_Old = undefined; // Расстояние до окружающего текста this.Distance = { T : 0, B : 0, L : 0, R : 0 }; this.AnchorPosition = new CTableAnchorPosition(); this.Pages = []; this.Pages[0] = new CTablePage(0, 0, 0, 0, 0, 0); this.MaxTopBorder = []; this.MaxBotBorder = []; this.MaxBotMargin = []; // Выставляем текущую ячейку if ( this.Content.length > 0 ) this.CurCell = this.Content[0].Get_Cell( 0 ); else this.CurCell = null; this.TurnOffRecalc = false; this.ApplyToAll = false; // Специальный параметр, используемый в ячейках таблицы. // True, если ячейка попадает в выделение по ячейкам. this.m_oContentChanges = new AscCommon.CContentChanges(); // список изменений(добавление/удаление элементов) // Добавляем данный класс в таблицу Id (обязательно в конце конструктора) AscCommon.g_oTableId.Add(this, this.Id); this.updateTrackRevisions(); } CTable.prototype = Object.create(CDocumentContentElementBase.prototype); CTable.prototype.constructor = CTable; CTable.prototype.GetType = function() { return type_Table; }; //---------------------------------------------------------------------------------------------------------------------- // Общие функции //---------------------------------------------------------------------------------------------------------------------- CTable.prototype.Get_Theme = function() { if (!this.Parent) return null; return this.Parent.Get_Theme(); }; CTable.prototype.Get_ColorMap = function() { if (!this.Parent) return null; return this.Parent.Get_ColorMap(); }; CTable.prototype.Get_Props = function() { var TablePr = this.Get_CompiledPr(false).TablePr; var Pr = {}; if (tblwidth_Auto === TablePr.TableW.Type || (tblwidth_Mm === TablePr.TableW.Type && TablePr.TableW.W < 0.001)) Pr.TableWidth = null; else if (tblwidth_Mm === TablePr.TableW.Type) Pr.TableWidth = TablePr.TableW.W; else// if (tblwidth_Pct === TablePr.TableW.Type) Pr.TableWidth = -TablePr.TableW.W; Pr.AllowOverlap = this.AllowOverlap; // Пока у нас во всей таблицы одинаковый Spacing Pr.TableSpacing = this.Content[0].Get_CellSpacing(); Pr.TableDefaultMargins = { Left : TablePr.TableCellMar.Left.W, Right : TablePr.TableCellMar.Right.W, Top : TablePr.TableCellMar.Top.W, Bottom : TablePr.TableCellMar.Bottom.W }; if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { Pr.CellSelect = true; var CellMargins = null; var CellMarginFlag = false; var Border_left = null; var Border_right = null; var Border_top = null; var Border_bottom = null; var Border_insideH = null; var Border_insideV = null; var CellShd = null; var CellWidth = undefined; var CellWidthStart = undefined; var Prev_row = -1; var bFirstRow = true; var VAlign = null; var TextDirection = null; var NoWrap = null; var nRowHeight = null; for (var Index = 0; Index < this.Selection.Data.length; Index++) { var Pos = this.Selection.Data[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_borders = Cell.Get_Borders(); var Cell_margins = Cell.GetMargins(); var Cell_shd = Cell.Get_Shd(); var Cell_w = Cell.Get_W(); if (0 === Index) { VAlign = Cell.Get_VAlign(); TextDirection = Cell.Get_TextDirection(); NoWrap = Cell.GetNoWrap(); } else { if (VAlign !== Cell.Get_VAlign()) VAlign = null; if (TextDirection !== Cell.Get_TextDirection()) TextDirection = null; if (NoWrap !== Cell.GetNoWrap()) NoWrap = null; } if (0 === Index) { CellShd = Cell_shd; } else { if (null != CellShd && ( CellShd.Value != Cell_shd.Value || CellShd.Color.r != Cell_shd.Color.r || CellShd.Color.g != Cell_shd.Color.g || CellShd.Color.b != Cell_shd.Color.b )) CellShd = null; } var _CellWidth; if (tblwidth_Auto === Cell_w.Type) _CellWidth = null; else if (tblwidth_Mm === Cell_w.Type) _CellWidth = Cell_w.W; else// if (tblwidth_Pct === Cell_w.Type) _CellWidth = -Cell_w.W; if (0 === Index) { CellWidthStart = _CellWidth; } else { if ((tblwidth_Auto === Cell_w.Type && null !== CellWidth) || (undefined === CellWidth || null === CellWidth || Math.abs(CellWidth - _CellWidth) > 0.001)) CellWidth = undefined; } // Крайняя левая ли данная ячейка в выделении? if (0 === Index || this.Selection.Data[Index - 1].Row != Pos.Row) { if (null === Border_left) Border_left = Cell_borders.Left; else Border_left = this.Internal_CompareBorders2(Border_left, Cell_borders.Left); } else { if (null === Border_insideV) Border_insideV = Cell_borders.Left; else Border_insideV = this.Internal_CompareBorders2(Border_insideV, Cell_borders.Left); } // Крайняя правая ли данная ячейка в выделении? if (this.Selection.Data.length - 1 === Index || this.Selection.Data[Index + 1].Row != Pos.Row) { if (null === Border_right) Border_right = Cell_borders.Right; else Border_right = this.Internal_CompareBorders2(Border_right, Cell_borders.Right); } else { if (null === Border_insideV) Border_insideV = Cell_borders.Right; else Border_insideV = this.Internal_CompareBorders2(Border_insideV, Cell_borders.Right); } if (Prev_row != Pos.Row) { if (-1 != Prev_row) bFirstRow = false; if (false === bFirstRow) { if (null === Border_insideH) { Border_insideH = Border_bottom; Border_insideH = this.Internal_CompareBorders2(Border_insideH, Cell_borders.Top); } else { Border_insideH = this.Internal_CompareBorders2(Border_insideH, Border_bottom); Border_insideH = this.Internal_CompareBorders2(Border_insideH, Cell_borders.Top); } } else { if (null === Border_top) Border_top = Cell_borders.Top; } Border_bottom = Cell_borders.Bottom; Prev_row = Pos.Row; } else { if (false === bFirstRow) { if (null === Border_insideH) Border_insideH = Cell_borders.Top; else Border_insideH = this.Internal_CompareBorders2(Border_insideH, Cell_borders.Top); } else { if (null === Border_top) Border_top = Cell_borders.Top; else Border_top = this.Internal_CompareBorders2(Border_top, Cell_borders.Top); } Border_bottom = this.Internal_CompareBorders2(Border_bottom, Cell_borders.Bottom); } if (true != Cell.Is_TableMargins()) { if (null === CellMargins) { CellMargins = Common_CopyObj(Cell_margins); } else { if (CellMargins.Left.W != Cell_margins.Left.W) CellMargins.Left.W = null; if (CellMargins.Right.W != Cell_margins.Right.W) CellMargins.Right.W = null; if (CellMargins.Top.W != Cell_margins.Top.W) CellMargins.Top.W = null; if (CellMargins.Bottom.W != Cell_margins.Bottom.W) CellMargins.Bottom.W = null; } } else { CellMarginFlag = true; } var nCurRowHeight; var oRowH = Row.GetHeight(); if (oRowH.IsAuto()) { var oRow = Row; var nCurRow = oRow.GetIndex(); var nRowSummaryH = 0; // Проверка на случай непересчитанной таблицы if (this.RowsInfo[nCurRow]) { for (var nCurPage in this.RowsInfo[nCurRow].H) nRowSummaryH += this.RowsInfo[nCurRow].H[nCurPage]; if (null !== Pr.TableSpacing) nRowSummaryH += Pr.TableSpacing; else if (this.RowsInfo[nCurRow].TopDy[0]) nRowSummaryH -= this.RowsInfo[nCurRow].TopDy[0]; nRowSummaryH -= oRow.GetTopMargin() + oRow.GetBottomMargin(); } nCurRowHeight = nRowSummaryH; } else { nCurRowHeight = oRowH.GetValue(); } if (null === nRowHeight) nRowHeight = nCurRowHeight; else if (undefined !== nRowHeight && Math.abs(nRowHeight - nCurRowHeight) > 0.001) nRowHeight = undefined; } Pr.CellsVAlign = VAlign; Pr.CellsTextDirection = TextDirection; Pr.CellsNoWrap = NoWrap; if (undefined === CellWidth) { Pr.CellsWidth = CellWidthStart; Pr.CellsWidthNotEqual = true; } else { Pr.CellsWidth = CellWidthStart; Pr.CellsWidthNotEqual = false; } Pr.RowHeight = nRowHeight; Pr.CellBorders = { Left : Border_left.Copy(), Right : Border_right.Copy(), Top : Border_top.Copy(), Bottom : Border_bottom.Copy(), InsideH : null === Border_insideH ? null : Border_insideH.Copy(), InsideV : null === Border_insideV ? null : Border_insideV.Copy() }; if (null === CellShd) Pr.CellsBackground = null; else Pr.CellsBackground = CellShd.Copy(); if (null === CellMargins) { Pr.CellMargins = { Flag : 0 }; } else { var Flag = 2; if (true === CellMarginFlag) Flag = 1; Pr.CellMargins = { Left : CellMargins.Left.W, Right : CellMargins.Right.W, Top : CellMargins.Top.W, Bottom : CellMargins.Bottom.W, Flag : Flag }; } } else { Pr.CellSelect = false; var Cell = this.CurCell; var CellMargins = Cell.GetMargins(true); var CellBorders = Cell.Get_Borders(); var CellShd = Cell.Get_Shd(); var CellW = Cell.Get_W(); if (true === Cell.Is_TableMargins()) { Pr.CellMargins = { Flag : 0 }; } else { Pr.CellMargins = { Left : CellMargins.Left.W, Right : CellMargins.Right.W, Top : CellMargins.Top.W, Bottom : CellMargins.Bottom.W, Flag : 2 }; } Pr.CellsVAlign = Cell.Get_VAlign(); Pr.CellsTextDirection = Cell.Get_TextDirection(); Pr.CellsNoWrap = Cell.GetNoWrap(); Pr.CellsBackground = CellShd.Copy(); if (tblwidth_Auto === CellW.Type) Pr.CellsWidth = null; else if (tblwidth_Mm === CellW.Type) Pr.CellsWidth = CellW.W; else// if (tblwidth_Pct === CellW.Type) Pr.CellsWidth = -CellW.W; Pr.CellsWidthNotEqual = false; var Spacing = this.Content[0].Get_CellSpacing(); var Border_left = null; var Border_right = null; var Border_top = null; var Border_bottom = null; var Border_insideH = null; var Border_insideV = null; var CellShd = null; for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Row = this.Content[CurRow]; var Cells_Count = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < Cells_Count; CurCell++) { var Cell = Row.Get_Cell(CurCell); var Cell_borders = Cell.Get_Borders(); var Cell_shd = Cell.Get_Shd(); var oCellW = Cell.GetW(); if (0 === CurCell && Cells_Count) { CellShd = Cell_shd; } else { if (null != CellShd && ( CellShd.Value != Cell_shd.Value || CellShd.Color.r != Cell_shd.Color.r || CellShd.Color.g != Cell_shd.Color.g || CellShd.Color.b != Cell_shd.Color.b )) CellShd = null; } // Крайняя левая ли данная ячейка в выделении? if (0 === CurCell) { if (null === Border_left) Border_left = Cell_borders.Left; else Border_left = this.Internal_CompareBorders2(Border_left, Cell_borders.Left); } else { if (null === Border_insideV) Border_insideV = Cell_borders.Left; else Border_insideV = this.Internal_CompareBorders2(Border_insideV, Cell_borders.Left); } // Крайняя правая ли данная ячейка в выделении? if (Cells_Count - 1 === CurCell) { if (null === Border_right) Border_right = Cell_borders.Right; else Border_right = this.Internal_CompareBorders2(Border_right, Cell_borders.Right); } else { if (null === Border_insideV) Border_insideV = Cell_borders.Right; else Border_insideV = this.Internal_CompareBorders2(Border_insideV, Cell_borders.Right); } if (0 === CurCell) { if (0 != CurRow) { if (null === Border_insideH) { Border_insideH = Border_bottom; Border_insideH = this.Internal_CompareBorders2(Border_insideH, Cell_borders.Top); } else { Border_insideH = this.Internal_CompareBorders2(Border_insideH, Border_bottom); Border_insideH = this.Internal_CompareBorders2(Border_insideH, Cell_borders.Top); } } else { if (null === Border_top) Border_top = Cell_borders.Top; } Border_bottom = Cell_borders.Bottom; } else { if (0 != CurRow) { if (null === Border_insideH) Border_insideH = Cell_borders.Top; else Border_insideH = this.Internal_CompareBorders2(Border_insideH, Cell_borders.Top); } else { if (null === Border_top) Border_top = Cell_borders.Top; else Border_top = this.Internal_CompareBorders2(Border_top, Cell_borders.Top); } Border_bottom = this.Internal_CompareBorders2(Border_bottom, Cell_borders.Bottom); } } } Pr.CellBorders = { Left : Border_left.Copy(), Right : Border_right.Copy(), Top : Border_top.Copy(), Bottom : Border_bottom.Copy(), InsideH : null === Border_insideH ? null : Border_insideH.Copy(), InsideV : null === Border_insideV ? null : Border_insideV.Copy() }; var oRowH = this.CurCell.Row.GetHeight(); if (oRowH.IsAuto()) { var oRow = this.CurCell.GetRow(); var nCurRow = oRow.GetIndex(); var nRowSummaryH = 0; if (this.RowsInfo[nCurRow]) { for (var nCurPage in this.RowsInfo[nCurRow].H) nRowSummaryH += this.RowsInfo[nCurRow].H[nCurPage]; if (null !== Pr.TableSpacing) nRowSummaryH += Pr.TableSpacing; else if (this.RowsInfo[nCurRow].TopDy[0]) nRowSummaryH -= this.RowsInfo[nCurRow].TopDy[0]; nRowSummaryH -= oRow.GetTopMargin() + oRow.GetBottomMargin(); } Pr.RowHeight = nRowSummaryH; } else { Pr.RowHeight = oRowH.GetValue(); } } var arrSelectedCells = this.GetSelectionArray(); var oCells = {}; for (var nIndex = 0, nCount = arrSelectedCells.length; nIndex < nCount; ++nIndex) { var nCurCell = arrSelectedCells[nIndex].Cell; if (!oCells[nCurCell]) oCells[nCurCell] = 1; } var nColumnWidth = null; var arrRowsInfo = this.private_GetRowsInfo(); for (var nCurRow = 0, nCount = arrRowsInfo.length; nCurRow < nCount; ++nCurRow) { var nAdd = -1 === arrRowsInfo[nCurRow][0].Type ? 1 : 0; for (var nCurCell in oCells) { var _nCurCell = nCurCell | 0; if (arrRowsInfo[nCurRow][_nCurCell + nAdd]) { if (null === nColumnWidth) { nColumnWidth = arrRowsInfo[nCurRow][_nCurCell + nAdd].W; } else if (Math.abs(nColumnWidth - arrRowsInfo[nCurRow][_nCurCell + nAdd].W) > 0.001) { nColumnWidth = undefined; break; } } } if (undefined === nColumnWidth) break; } Pr.ColumnWidth = nColumnWidth; switch (Pr.CellsVAlign) { case vertalignjc_Top : Pr.CellsVAlign = c_oAscVertAlignJc.Top; break; case vertalignjc_Bottom : Pr.CellsVAlign = c_oAscVertAlignJc.Bottom; break; case vertalignjc_Center : Pr.CellsVAlign = c_oAscVertAlignJc.Center; break; default : Pr.CellsVAlign = null; break; } switch (Pr.CellsTextDirection) { case textdirection_LRTB : Pr.CellsTextDirection = c_oAscCellTextDirection.LRTB; break; case textdirection_TBRL : Pr.CellsTextDirection = c_oAscCellTextDirection.TBRL; break; case textdirection_BTLR : Pr.CellsTextDirection = c_oAscCellTextDirection.BTLR; break; default : Pr.CellsTextDirection = null; break; } var oSelectionRowsRange = this.GetSelectedRowsRange(); var nRowsInHeader = this.GetRowsCountInHeader(); if (oSelectionRowsRange.Start > nRowsInHeader) Pr.RowsInHeader = null; else if (oSelectionRowsRange.End < nRowsInHeader) Pr.RowsInHeader = true; else Pr.RowsInHeader = false; if (true === this.Is_Inline()) { Pr.TableAlignment = ( align_Left === TablePr.Jc ? 0 : ( AscCommon.align_Center === TablePr.Jc ? 1 : 2 ) ); Pr.TableIndent = TablePr.TableInd; Pr.TableWrappingStyle = AscCommon.c_oAscWrapStyle.Inline; Pr.Position = { X : this.X, Y : this.Y }; Pr.TablePaddings = { Top : 0, Bottom : 0, Left : 3.2, Right : 3.2 }; } else { var LD_PageFields = this.LogicDocument.Get_PageFields(this.GetAbsoluteStartPage(), this.Parent && this.Parent.IsHdrFtr()); Pr.TableAlignment = 0; // align_Left Pr.TableIndent = this.X_origin - LD_PageFields.X; Pr.TableWrappingStyle = AscCommon.c_oAscWrapStyle.Flow; Pr.PositionH = {}; Pr.PositionH.RelativeFrom = this.PositionH.RelativeFrom; Pr.PositionH.UseAlign = this.PositionH.Align; Pr.PositionH.Align = ( true === Pr.PositionH.UseAlign ? this.PositionH.Value : undefined ); Pr.PositionH.Value = ( true === Pr.PositionH.UseAlign ? 0 : this.PositionH.Value ); Pr.PositionV = {}; Pr.PositionV.RelativeFrom = this.PositionV.RelativeFrom; Pr.PositionV.UseAlign = this.PositionV.Align; Pr.PositionV.Align = ( true === Pr.PositionV.UseAlign ? this.PositionV.Value : undefined ); Pr.PositionV.Value = ( true === Pr.PositionV.UseAlign ? 0 : this.PositionV.Value ); Pr.Position = { X : this.Parent.X, Y : this.Parent.Y }; Pr.TablePaddings = { Left : this.Distance.L, Right : this.Distance.R, Top : this.Distance.T, Bottom : this.Distance.B }; } Pr.Internal_Position = this.AnchorPosition; Pr.TableBorders = Common_CopyObj(TablePr.TableBorders); Pr.TableBackground = TablePr.Shd.Copy(); Pr.TableStyle = this.TableStyle; Pr.TableLook = this.TableLook; if (true === this.Parent.Is_DrawingShape()) Pr.CanBeFlow = false; else Pr.CanBeFlow = true; Pr.Locked = this.Lock.Is_Locked(); if (true === this.Parent.IsInTable()) Pr.TableLayout = undefined; else Pr.TableLayout = (TablePr.TableLayout === tbllayout_AutoFit ? c_oAscTableLayout.AutoFit : c_oAscTableLayout.Fixed ); if (!this.bPresentation) { this.DrawingDocument.CheckTableStyles(this.TableLook); } Pr.PercentFullWidth = this.private_RecalculatePercentWidth(); Pr.TableDescription = this.Get_TableDescription(); Pr.TableCaption = this.Get_TableCaption(); return Pr; }; CTable.prototype.Set_Props = function(Props) { var TablePr = this.Get_CompiledPr(false).TablePr; var bApplyToInnerTable = false; if (true != this.Selection.Use || ( true === this.Selection.Use && table_Selection_Text === this.Selection.Type )) { bApplyToInnerTable = this.CurCell.Content.SetTableProps(Props); } if (true === bApplyToInnerTable) return true; var bRecalc_All = false; var bRedraw = false; // TableStyle (стиль таблицы) if (undefined !== Props.TableStyle) { this.Set_TableStyle(Props.TableStyle); bRecalc_All = true; } // TableLook if (Props.TableLook) { var NewLook = new AscCommon.CTableLook(Props.TableLook.FirstCol, Props.TableLook.FirstRow, Props.TableLook.LastCol, Props.TableLook.LastRow, Props.TableLook.BandHor, Props.TableLook.BandVer); this.Set_TableLook(NewLook); bRecalc_All = true; } // AllowOverlap if (undefined != Props.AllowOverlap) { this.Set_AllowOverlap(Props.AllowOverlap); bRecalc_All = true; } // RowsInHeader if (undefined !== Props.RowsInHeader && null !== Props.RowsInHeader) { var oSelectionRowsRange = this.GetSelectedRowsRange(); var nRowsInHeader = this.GetRowsCountInHeader(); if (oSelectionRowsRange.Start <= nRowsInHeader) { for (var nCurRow = oSelectionRowsRange.Start, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { if (nCurRow <= oSelectionRowsRange.End) this.Content[nCurRow].SetHeader(Props.RowsInHeader ? true : false); else this.Content[nCurRow].SetHeader(false); } } } // TableSpacing (расстояние между ячейками) if ("undefined" != typeof(Props.TableSpacing)) { var NeedChange = false; for (var Index = 0; Index < this.Content.length; Index++) { if (Props.TableSpacing != this.Content[Index].Get_CellSpacing()) { NeedChange = true; break; } } if (true === NeedChange) { var OldSpacing = this.Content[0].Get_CellSpacing(); var Diff = Props.TableSpacing - ( null === OldSpacing ? 0 : OldSpacing ); for (var Index = 0; Index < this.Content.length; Index++) this.Content[Index].Set_CellSpacing(Props.TableSpacing); bRecalc_All = true; // При изменении Spacing мы должны изменить сетку таблицы var GridKoeff = []; var ColsCount = this.TableGridCalc.length; for (var Index = 0; Index < ColsCount; Index++) GridKoeff.push(1); for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Row = this.Content[CurRow]; var GridBefore = Row.Get_Before().GridBefore; var GridAfter = Row.Get_After().GridAfter; GridKoeff[Math.min(GridBefore, GridKoeff.length - 1)] = 1.5; GridKoeff[Math.max(GridKoeff.length - 1 - GridAfter, 0)] = 1.5; } var arrNewGrid = []; for (var Index = 0; Index < ColsCount; Index++) { arrNewGrid[Index] = this.TableGridCalc[Index] + GridKoeff[Index] * Diff; } this.SetTableGrid(arrNewGrid); } } // Определим, есть ли у таблицы Spacing, уже с учетом новых настроек var bSpacing = null === this.Content[0].Get_CellSpacing() ? false : true; // TableDefaultMargins (отступы в ячейках по умолчанию) if ("undefined" != typeof(Props.TableDefaultMargins)) { var UsingDefaultMar = false; for (var Index = 0; Index < this.Content.length; Index++) { var Row = this.Content[Index]; var CellsCount = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var Cell = Row.Get_Cell(CurCell); if (null === Cell.Pr.TableCellMar) { UsingDefaultMar = true; break; } } } var NeedChange = false; var TDM = Props.TableDefaultMargins; var Left_new = ( "undefined" != typeof(TDM.Left) ? ( null != TDM.Left ? TDM.Left : TablePr.TableCellMar.Left.W ) : TablePr.TableCellMar.Left.W ); var Right_new = ( "undefined" != typeof(TDM.Right) ? ( null != TDM.Right ? TDM.Right : TablePr.TableCellMar.Right.W ) : TablePr.TableCellMar.Right.W ); var Top_new = ( "undefined" != typeof(TDM.Top) ? ( null != TDM.Top ? TDM.Top : TablePr.TableCellMar.Top.W ) : TablePr.TableCellMar.Top.W ); var Bottom_new = ( "undefined" != typeof(TDM.Bottom) ? ( null != TDM.Bottom ? TDM.Bottom : TablePr.TableCellMar.Bottom.W ) : TablePr.TableCellMar.Bottom.W ); if (Left_new != TablePr.TableCellMar.Left.W || Right_new != TablePr.TableCellMar.Right.W || Top_new != TablePr.TableCellMar.Top.W || Bottom_new != TablePr.TableCellMar.Bottom.W) NeedChange = true; if (true === NeedChange) { this.Set_TableCellMar(Left_new, Top_new, Right_new, Bottom_new); if (true === UsingDefaultMar) { bRecalc_All = true; } } } // CellMargins (отступы в ячейках) if ("undefined" != typeof(Props.CellMargins) && null != Props.CellMargins) { var NeedChange = false; switch (Props.CellMargins.Flag) { case 0: { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { for (var Index = 0; Index < this.Selection.Data.length; Index++) { var Pos = this.Selection.Data[Index]; var Cell = this.Content[Pos.Row].Get_Cell(Pos.Cell); if (null != Cell.Pr.TableCellMar) { Cell.Set_Margins(null); NeedChange = true; } } } else { var Cell = this.CurCell; if (null != Cell.Pr.TableCellMar) { Cell.Set_Margins(null); NeedChange = true; } } break; } case 1: { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { for (var Index = 0; Index < this.Selection.Data.length; Index++) { var Pos = this.Selection.Data[Index]; var Cell = this.Content[Pos.Row].Get_Cell(Pos.Cell); // Ячейки, у которых маргины дефелтовые, мы не трогаем if (true != Cell.Is_TableMargins()) { if (null != Props.CellMargins.Left) Cell.Set_Margins({W : Props.CellMargins.Left, Type : tblwidth_Mm}, 3); if (null != Props.CellMargins.Right) Cell.Set_Margins({W : Props.CellMargins.Right, Type : tblwidth_Mm}, 1); if (null != Props.CellMargins.Top) Cell.Set_Margins({W : Props.CellMargins.Top, Type : tblwidth_Mm}, 0); if (null != Props.CellMargins.Bottom) Cell.Set_Margins({W : Props.CellMargins.Bottom, Type : tblwidth_Mm}, 2); NeedChange = true; } } } else { // Сюда вообще не должны заходить, но на всякий случай реализуем. var Cell = this.CurCell; if (true != Cell.Is_TableMargins()) { if (null != Props.CellMargins.Left) Cell.Set_Margins({W : Props.CellMargins.Left, Type : tblwidth_Mm}, 3); if (null != Props.CellMargins.Right) Cell.Set_Margins({W : Props.CellMargins.Right, Type : tblwidth_Mm}, 1); if (null != Props.CellMargins.Top) Cell.Set_Margins({W : Props.CellMargins.Top, Type : tblwidth_Mm}, 0); if (null != Props.CellMargins.Bottom) Cell.Set_Margins({W : Props.CellMargins.Bottom, Type : tblwidth_Mm}, 2); } else { if (null != Props.CellMargins.Left) Cell.Set_Margins({W : Props.CellMargins.Left, Type : tblwidth_Mm}, 3); else Cell.Set_Margins({W : TablePr.TableCellMar.Left.W, Type : tblwidth_Mm}, 3); if (null != Props.CellMargins.Right) Cell.Set_Margins({W : Props.CellMargins.Right, Type : tblwidth_Mm}, 1); else Cell.Set_Margins({W : TablePr.TableCellMar.Right.W, Type : tblwidth_Mm}, 1); if (null != Props.CellMargins.Top) Cell.Set_Margins({W : Props.CellMargins.Top, Type : tblwidth_Mm}, 0); else Cell.Set_Margins({W : TablePr.TableCellMar.Top.W, Type : tblwidth_Mm}, 0); if (null != Props.CellMargins.Bottom) Cell.Set_Margins({W : Props.CellMargins.Bottom, Type : tblwidth_Mm}, 2); else Cell.Set_Margins({W : TablePr.TableCellMar.Bottom.W, Type : tblwidth_Mm}, 2); } NeedChange = true; } break; } case 2: { NeedChange = true; if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { for (var Index = 0; Index < this.Selection.Data.length; Index++) { var Pos = this.Selection.Data[Index]; var Cell = this.Content[Pos.Row].Get_Cell(Pos.Cell); // Ячейки, у которых маргины дефелтовые, мы не трогаем if (true != Cell.Is_TableMargins()) { if (null != Props.CellMargins.Left) Cell.Set_Margins({W : Props.CellMargins.Left, Type : tblwidth_Mm}, 3); if (null != Props.CellMargins.Right) Cell.Set_Margins({W : Props.CellMargins.Right, Type : tblwidth_Mm}, 1); if (null != Props.CellMargins.Top) Cell.Set_Margins({W : Props.CellMargins.Top, Type : tblwidth_Mm}, 0); if (null != Props.CellMargins.Bottom) Cell.Set_Margins({W : Props.CellMargins.Bottom, Type : tblwidth_Mm}, 2); } else { if (null != Props.CellMargins.Left) Cell.Set_Margins({W : Props.CellMargins.Left, Type : tblwidth_Mm}, 3); else Cell.Set_Margins({W : TablePr.TableCellMar.Left.W, Type : tblwidth_Mm}, 3); if (null != Props.CellMargins.Right) Cell.Set_Margins({W : Props.CellMargins.Right, Type : tblwidth_Mm}, 1); else Cell.Set_Margins({W : TablePr.TableCellMar.Right.W, Type : tblwidth_Mm}, 1); if (null != Props.CellMargins.Top) Cell.Set_Margins({W : Props.CellMargins.Top, Type : tblwidth_Mm}, 0); else Cell.Set_Margins({W : TablePr.TableCellMar.Top.W, Type : tblwidth_Mm}, 0); if (null != Props.CellMargins.Bottom) Cell.Set_Margins({W : Props.CellMargins.Bottom, Type : tblwidth_Mm}, 2); else Cell.Set_Margins({W : TablePr.TableCellMar.Bottom.W, Type : tblwidth_Mm}, 2); } } } else { var Cell = this.CurCell; if (true != Cell.Is_TableMargins()) { if (null != Props.CellMargins.Left) Cell.Set_Margins({W : Props.CellMargins.Left, Type : tblwidth_Mm}, 3); if (null != Props.CellMargins.Right) Cell.Set_Margins({W : Props.CellMargins.Right, Type : tblwidth_Mm}, 1); if (null != Props.CellMargins.Top) Cell.Set_Margins({W : Props.CellMargins.Top, Type : tblwidth_Mm}, 0); if (null != Props.CellMargins.Bottom) Cell.Set_Margins({W : Props.CellMargins.Bottom, Type : tblwidth_Mm}, 2); } else { if (null != Props.CellMargins.Left) Cell.Set_Margins({W : Props.CellMargins.Left, Type : tblwidth_Mm}, 3); else Cell.Set_Margins({W : TablePr.TableCellMar.Left.W, Type : tblwidth_Mm}, 3); if (null != Props.CellMargins.Right) Cell.Set_Margins({W : Props.CellMargins.Right, Type : tblwidth_Mm}, 1); else Cell.Set_Margins({W : TablePr.TableCellMar.Right.W, Type : tblwidth_Mm}, 1); if (null != Props.CellMargins.Top) Cell.Set_Margins({W : Props.CellMargins.Top, Type : tblwidth_Mm}, 0); else Cell.Set_Margins({W : TablePr.TableCellMar.Top.W, Type : tblwidth_Mm}, 0); if (null != Props.CellMargins.Bottom) Cell.Set_Margins({W : Props.CellMargins.Bottom, Type : tblwidth_Mm}, 2); else Cell.Set_Margins({W : TablePr.TableCellMar.Bottom.W, Type : tblwidth_Mm}, 2); } NeedChange = true; } break; } } if (true === NeedChange) bRecalc_All = true; } // TableWidth (ширина таблицы) if (undefined !== Props.TableWidth) { if (null === Props.TableWidth) { if (tblwidth_Auto != TablePr.TableW.Type) { this.Set_TableW(tblwidth_Auto, 0); bRecalc_All = true; } } else if (Props.TableWidth > -0.001) { this.Set_TableW(tblwidth_Mm, Props.TableWidth); bRecalc_All = true; } else { this.Set_TableW(tblwidth_Pct, Math.abs(Props.TableWidth)); bRecalc_All = true; } } // TableLayout if (undefined != Props.TableLayout) { this.SetTableLayout(( Props.TableLayout === c_oAscTableLayout.AutoFit ? tbllayout_AutoFit : tbllayout_Fixed )); bRecalc_All = true; } // TableWrappingStyle if (undefined != Props.TableWrappingStyle) { // При изменении flow на inline или наоборот, пересчет таблицы будет запущен позже if (0 === Props.TableWrappingStyle && true != this.Inline) { this.Set_Inline(true); bRecalc_All = true; } else if (1 === Props.TableWrappingStyle && false != this.Inline) { this.Set_Inline(false); if (undefined === Props.PositionH) this.Set_PositionH(c_oAscHAnchor.Page, false, this.AnchorPosition.Calculate_X_Value(c_oAscHAnchor.Page)); if (undefined === Props.PositionV) { // Сдвигаемся на 1 twips вниз, чтобы не было пересечения с предыдущей строкой var ValueY = AscCommon.CorrectMMToTwips(this.AnchorPosition.Calculate_Y_Value(c_oAscVAnchor.Page)) + AscCommon.TwipsToMM(1); this.Set_PositionV(c_oAscVAnchor.Page, false, ValueY); } if (undefined === Props.TablePaddings) this.Set_Distance(3.2, 0, 3.2, 0); this.Set_TableInd(0); bRecalc_All = true; } } var _Jc = TablePr.Jc; // Запоминаем, чтобы не пересчитывать стиль // TableAlignment (прилегание таблицы) if ("undefined" != typeof(Props.TableAlignment) && true === this.Is_Inline()) { var NewJc = ( 0 === Props.TableAlignment ? align_Left : ( 1 === Props.TableAlignment ? AscCommon.align_Center : AscCommon.align_Right ) ); if (TablePr.Jc != NewJc) { _Jc = NewJc; this.Set_TableAlign(NewJc); bRecalc_All = true; } } // TableIndent (отступ слева) if ("undefined" != typeof(Props.TableIndent) && true === this.Is_Inline() && align_Left === _Jc) { if (Props.TableIndent != TablePr.TableInd) { this.Set_TableInd(Props.TableIndent); bRecalc_All = true; } } // Position if (undefined != Props.Position) { this.PositionH.RelativeFrom = c_oAscHAnchor.Page; this.PositionH.Align = true; this.PositionV.RelativeFrom = c_oAscVAnchor.Page; this.PositionH.Align = true; this.PositionH.Value = c_oAscXAlign.Center; this.PositionV.Value = c_oAscYAlign.Center; //this.PositionH.Value = ( "undefined" != typeof(Props.Position.X) ? ( null != Props.Position.X ? // Props.Position.X : this.X ) : this.X ); this.PositionV.Value = ( "undefined" != // typeof(Props.Position.Y) ? ( null != Props.Position.Y ? Props.Position.Y : this.Y ) : this.Y ); bRecalc_All = true; } if (undefined != Props.PositionH) { this.Set_PositionH(Props.PositionH.RelativeFrom, Props.PositionH.UseAlign, (true === Props.PositionH.UseAlign) ? Props.PositionH.Align : Props.PositionH.Value); } if (undefined != Props.PositionV) { this.Set_PositionV(Props.PositionV.RelativeFrom, Props.PositionV.UseAlign, (true === Props.PositionV.UseAlign) ? Props.PositionV.Align : Props.PositionV.Value); } // TablePaddings if (undefined != Props.TablePaddings) { var TP = Props.TablePaddings; var CurPaddings = this.Distance; var NewPaggings_left = ( undefined != TP.Left ? ( null != TP.Left ? TP.Left : CurPaddings.L ) : CurPaddings.L ); var NewPaggings_right = ( undefined != TP.Right ? ( null != TP.Right ? TP.Right : CurPaddings.R ) : CurPaddings.R ); var NewPaggings_top = ( undefined != TP.Top ? ( null != TP.Top ? TP.Top : CurPaddings.T ) : CurPaddings.T ); var NewPaggings_bottom = ( undefined != TP.Bottom ? ( null != TP.Bottom ? TP.Bottom : CurPaddings.B ) : CurPaddings.B ); if (Math.abs(CurPaddings.L - NewPaggings_left) > 0.001 || Math.abs(CurPaddings.R - NewPaggings_right) > 0.001 || Math.abs(CurPaddings.T - NewPaggings_top) > 0.001 || Math.abs(CurPaddings.B - NewPaggings_bottom) > 0.001) { this.Set_Distance(NewPaggings_left, NewPaggings_top, NewPaggings_right, NewPaggings_bottom); bRecalc_All = true; } } // TableBorders(границы таблицы) if ("undefined" != typeof(Props.TableBorders) && null != Props.TableBorders) { if (false === this.Internal_CheckNullBorder(Props.TableBorders.Top) && false === this.Internal_CompareBorders3(Props.TableBorders.Top, TablePr.TableBorders.Top)) { this.Set_TableBorder_Top(Props.TableBorders.Top); bRecalc_All = true; if (true != bSpacing) { var Row = this.Content[0]; for (var CurCell = 0; CurCell < Row.Get_CellsCount(); CurCell++) { var Cell = Row.Get_Cell(CurCell); Cell.Set_Border(null, 0); } } } if (false === this.Internal_CheckNullBorder(Props.TableBorders.Bottom) && false === this.Internal_CompareBorders3(Props.TableBorders.Bottom, TablePr.TableBorders.Bottom)) { this.Set_TableBorder_Bottom(Props.TableBorders.Bottom); bRecalc_All = true; if (true != bSpacing) { var Row = this.Content[this.Content.length - 1]; for (var CurCell = 0; CurCell < Row.Get_CellsCount(); CurCell++) { var Cell = Row.Get_Cell(CurCell); Cell.Set_Border(null, 2); } } } if (false === this.Internal_CheckNullBorder(Props.TableBorders.Left) && false === this.Internal_CompareBorders3(Props.TableBorders.Left, TablePr.TableBorders.Left)) { this.Set_TableBorder_Left(Props.TableBorders.Left); bRecalc_All = true; if (true != bSpacing) { for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Cell = this.Content[CurRow].Get_Cell(0); Cell.Set_Border(null, 3); } } } if (false === this.Internal_CheckNullBorder(Props.TableBorders.Right) && false === this.Internal_CompareBorders3(Props.TableBorders.Right, TablePr.TableBorders.Right)) { this.Set_TableBorder_Right(Props.TableBorders.Right); bRecalc_All = true; if (true != bSpacing) { for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Cell = this.Content[CurRow].Get_Cell(this.Content[CurRow].Get_CellsCount() - 1); Cell.Set_Border(null, 1); } } } if (false === this.Internal_CheckNullBorder(Props.TableBorders.InsideH) && false === this.Internal_CompareBorders3(Props.TableBorders.InsideH, TablePr.TableBorders.InsideH)) { this.Set_TableBorder_InsideH(Props.TableBorders.InsideH); bRecalc_All = true; for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Row = this.Content[CurRow]; var Cells_Count = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < Cells_Count; CurCell++) { var Cell = Row.Get_Cell(CurCell); if ((0 === CurRow && true === bSpacing) || 0 != CurRow) Cell.Set_Border(null, 0); if (( this.Content.length - 1 === CurRow && true === bSpacing ) || this.Content.length - 1 != CurRow) Cell.Set_Border(null, 2); } } } if (false === this.Internal_CheckNullBorder(Props.TableBorders.InsideV) && false === this.Internal_CompareBorders3(Props.TableBorders.InsideV, TablePr.TableBorders.InsideV)) { this.Set_TableBorder_InsideV(Props.TableBorders.InsideV); bRecalc_All = true; for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Row = this.Content[CurRow]; var Cells_Count = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < Cells_Count; CurCell++) { var Cell = Row.Get_Cell(CurCell); if ((0 === CurCell && true === bSpacing) || 0 != CurCell) Cell.Set_Border(null, 3); if (( Cells_Count - 1 === CurCell && true === bSpacing ) || Cells_Count - 1 != CurCell) Cell.Set_Border(null, 1); } } } } // CellBorders (границы ячеек) if ("undefined" != typeof(Props.CellBorders) && null != Props.CellBorders) { var Cells_array = null; // Переделаем идеальный вариант, на новый if (true === bSpacing) { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { Cells_array = []; for (var Index = 0, Count = this.Selection.Data.length; Index < Count; Index++) { var RowIndex = this.Selection.Data[Index].Row; var CellIndex = this.Selection.Data[Index].Cell; var StartGridCol = this.Content[RowIndex].Get_CellInfo(CellIndex).StartGridCol; var GridSpan = this.Content[RowIndex].Get_Cell(CellIndex).Get_GridSpan(); var TempCells_array = this.private_GetCellsPosArrayByCellsArray(this.private_GetMergedCells(RowIndex, StartGridCol, GridSpan)); Cells_array = Cells_array.concat(TempCells_array); } } else if (false === Props.CellSelect) { Cells_array = []; for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Row = this.Content[CurRow]; var Cells_count = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < Cells_count; CurCell++) { var Cell = Row.Get_Cell(CurCell); if (vmerge_Continue === Cell.GetVMerge()) continue; var StartGridCol = this.Content[CurRow].Get_CellInfo(CurCell).StartGridCol; var GridSpan = this.Content[CurRow].Get_Cell(CurCell).Get_GridSpan(); var TempCells_array = this.private_GetCellsPosArrayByCellsArray(this.private_GetMergedCells(CurRow, StartGridCol, GridSpan)); Cells_array = Cells_array.concat(TempCells_array); } } } else { var RowIndex = this.CurCell.Row.Index; var CellIndex = this.CurCell.Index; var StartGridCol = this.Content[RowIndex].Get_CellInfo(CellIndex).StartGridCol; var GridSpan = this.Content[RowIndex].Get_Cell(CellIndex).Get_GridSpan(); Cells_array = this.private_GetCellsPosArrayByCellsArray(this.private_GetMergedCells(RowIndex, StartGridCol, GridSpan)); } } else { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { Cells_array = []; for (var Index = 0, Count = this.Selection.Data.length; Index < Count; Index++) { var RowIndex = this.Selection.Data[Index].Row; var CellIndex = this.Selection.Data[Index].Cell; var StartGridCol = this.Content[RowIndex].Get_CellInfo(CellIndex).StartGridCol; var GridSpan = this.Content[RowIndex].Get_Cell(CellIndex).Get_GridSpan(); var TempCells_array = this.private_GetCellsPosArrayByCellsArray(this.private_GetMergedCells(RowIndex, StartGridCol, GridSpan)); Cells_array = Cells_array.concat(TempCells_array); } } else { var RowIndex = this.CurCell.Row.Index; var CellIndex = this.CurCell.Index; var StartGridCol = this.Content[RowIndex].Get_CellInfo(CellIndex).StartGridCol; var GridSpan = this.Content[RowIndex].Get_Cell(CellIndex).Get_GridSpan(); Cells_array = this.private_GetCellsPosArrayByCellsArray(this.private_GetMergedCells(RowIndex, StartGridCol, GridSpan)); } } //if ( true === this.Selection.Use && table_Selection_Cell === this.Selection.Type ) // Cells_array = this.Selection.Data; //else //{ // // TODO: Если данная ячейка имеет вертикальное объединение, тогда нам надо добавить // // все ячейки в него попадающие // Cells_array = [ { Row : this.CurCell.Row.Index, Cell : this.CurCell.Index } ]; //} var Pos_first = Cells_array[0]; var Pos_last = Cells_array[Cells_array.length - 1]; var Row_first = Pos_first.Row; var Row_last = Pos_last.Row; var bBorder_top = ( false === this.Internal_CheckNullBorder(Props.CellBorders.Top) ? true : false ); var bBorder_bottom = ( false === this.Internal_CheckNullBorder(Props.CellBorders.Bottom) ? true : false ); var bBorder_left = ( false === this.Internal_CheckNullBorder(Props.CellBorders.Left) ? true : false ); var bBorder_right = ( false === this.Internal_CheckNullBorder(Props.CellBorders.Right) ? true : false ); var bBorder_insideh = ( false === this.Internal_CheckNullBorder(Props.CellBorders.InsideH) ? true : false ); var bBorder_insidev = ( false === this.Internal_CheckNullBorder(Props.CellBorders.InsideV) ? true : false ); if (true != bSpacing) { // Узначем GridCol начала и конца первой и последней строк var Grid_row_first_start = 0, Grid_row_first_end = 0, Grid_row_last_start = 0, Grid_row_last_end = 0; var Pos = {Row : 0, Cell : 0}; var CurRow = Row_first; var Index = 0; Grid_row_first_start = this.Content[Pos_first.Row].Get_CellInfo(Pos_first.Cell).StartGridCol; while (Index < Cells_array.length) { Pos = Cells_array[Index]; if (Pos.Row != Row_first) break; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); Grid_row_first_end = Row.Get_CellInfo(Pos.Cell).StartGridCol + Cell.Get_GridSpan() - 1; Index++; } Index = 0; while (Index < Cells_array.length) { Pos = Cells_array[Index]; if (Pos.Row === Row_last) break; Index++; } Grid_row_last_start = this.Content[Pos.Row].Get_CellInfo(Pos.Cell).StartGridCol; Grid_row_last_end = this.Content[Pos_last.Row].Get_CellInfo(Pos_last.Cell).StartGridCol + this.Content[Pos_last.Row].Get_Cell(Pos_last.Cell).Get_GridSpan() - 1; if (Row_first > 0 && true === bBorder_top) { var Cell_start = 0, Cell_end = 0; var bStart = false; var bEnd = false; var Row = this.Content[Row_first - 1]; for (var CurCell = 0; CurCell < Row.Get_CellsCount(); CurCell++) { var StartGridCol = Row.Get_CellInfo(CurCell).StartGridCol; var EndGridCol = StartGridCol + Row.Get_Cell(CurCell).Get_GridSpan() - 1; if (false === bStart) { if (StartGridCol < Grid_row_first_start) continue; else if (StartGridCol > Grid_row_first_start) break; else //if ( StartGridCol === Grid_row_first_start ) { Cell_start = CurCell; bStart = true; if (EndGridCol < Grid_row_first_end) continue; else if (EndGridCol > Grid_row_first_end) break; else { Cell_end = CurCell; bEnd = true; break; } } } if (false === bEnd) { if (EndGridCol < Grid_row_first_end) continue; else if (EndGridCol > Grid_row_first_end) break; else //if ( EndGridCol === Grid_row_first_end ) { Cell_end = CurCell; bEnd = true; break; } } } if (true === bStart && true === bEnd) { for (var CurCell = Cell_start; CurCell <= Cell_end; CurCell++) { var Cell = Row.Get_Cell(CurCell); Cell.Set_Border(Props.CellBorders.Top, 2); } bRecalc_All = true; } } if (Row_last < this.Content.length - 1 && true === bBorder_bottom) { var Cell_start = 0, Cell_end = 0; var bStart = false; var bEnd = false; var Row = this.Content[Row_last + 1]; for (var CurCell = 0; CurCell < Row.Get_CellsCount(); CurCell++) { var StartGridCol = Row.Get_CellInfo(CurCell).StartGridCol; var EndGridCol = StartGridCol + Row.Get_Cell(CurCell).Get_GridSpan() - 1; if (false === bStart) { if (StartGridCol < Grid_row_last_start) continue; else if (StartGridCol > Grid_row_last_start) break; else //if ( StartGridCol === Grid_row_last_start ) { Cell_start = CurCell; bStart = true; if (EndGridCol < Grid_row_last_end) continue; else if (EndGridCol > Grid_row_last_end) break; else { Cell_end = CurCell; bEnd = true; break; } } } if (false === bEnd) { if (EndGridCol < Grid_row_last_end) continue; else if (EndGridCol > Grid_row_last_end) break; else //if ( EndGridCol === Grid_row_last_end ) { Cell_end = CurCell; bEnd = true; break; } } } if (true === bStart && true === bEnd) { for (var CurCell = Cell_start; CurCell <= Cell_end; CurCell++) { var Cell = Row.Get_Cell(CurCell); Cell.Set_Border(Props.CellBorders.Bottom, 0); } bRecalc_All = true; } } } var PrevRow = Row_first; var Cell_start = Pos_first.Cell, Cell_end = Pos_first.Cell; for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; Row = this.Content[Pos.Row]; Cell = Row.Get_Cell(Pos.Cell); if (PrevRow != Pos.Row) { var Row_temp = this.Content[PrevRow]; if (true != bSpacing && Cell_start > 0 && true === bBorder_left) { Row_temp.Get_Cell(Cell_start - 1).Set_Border(Props.CellBorders.Left, 1); bRecalc_All = true; } if (true != bSpacing && Cell_end < Row_temp.Get_CellsCount() - 1 && true === bBorder_right) { Row_temp.Get_Cell(Cell_end + 1).Set_Border(Props.CellBorders.Right, 3); bRecalc_All = true; } for (var CurCell = Cell_start; CurCell <= Cell_end; CurCell++) { var Cell_temp = Row_temp.Get_Cell(CurCell); if (Row_first === PrevRow && true === bBorder_top) { Cell_temp.Set_Border(Props.CellBorders.Top, 0); bRecalc_All = true; } else if (Row_first != PrevRow && true === bBorder_insideh) { Cell_temp.Set_Border(Props.CellBorders.InsideH, 0); bRecalc_All = true; } if (Row_last === PrevRow && true === bBorder_bottom) { Cell_temp.Set_Border(Props.CellBorders.Bottom, 2); bRecalc_All = true; } else if (Row_last != PrevRow && true === bBorder_insideh) { Cell_temp.Set_Border(Props.CellBorders.InsideH, 2); bRecalc_All = true; } if (CurCell === Cell_start && true === bBorder_left) { Cell_temp.Set_Border(Props.CellBorders.Left, 3); bRecalc_All = true; } else if (CurCell != Cell_start && true === bBorder_insidev) { Cell_temp.Set_Border(Props.CellBorders.InsideV, 3); bRecalc_All = true; } if (CurCell === Cell_end && true === bBorder_right) { Cell_temp.Set_Border(Props.CellBorders.Right, 1); bRecalc_All = true; } else if (CurCell != Cell_end && true === bBorder_insidev) { Cell_temp.Set_Border(Props.CellBorders.InsideV, 1); bRecalc_All = true; } } Cell_start = Pos.Cell; Cell_end = Pos.Cell; PrevRow = Pos.Row; } else Cell_end = Pos.Cell; if (Cells_array.length - 1 === Index) { var Row_temp = this.Content[PrevRow]; if (true != bSpacing && Cell_start > 0 && true === bBorder_left) { Row_temp.Get_Cell(Cell_start - 1).Set_Border(Props.CellBorders.Left, 1); bRecalc_All = true; } if (true != bSpacing && Cell_end < Row_temp.Get_CellsCount() - 1 && true === bBorder_right) { Row_temp.Get_Cell(Cell_end + 1).Set_Border(Props.CellBorders.Right, 3); bRecalc_All = true; } for (var CurCell = Cell_start; CurCell <= Cell_end; CurCell++) { var Cell_temp = Row_temp.Get_Cell(CurCell); if (Row_first === Pos.Row && true === bBorder_top) { Cell_temp.Set_Border(Props.CellBorders.Top, 0); bRecalc_All = true; } else if (Row_first != Pos.Row && true === bBorder_insideh) { Cell_temp.Set_Border(Props.CellBorders.InsideH, 0); bRecalc_All = true; } if (Row_last === Pos.Row && true === bBorder_bottom) { Cell_temp.Set_Border(Props.CellBorders.Bottom, 2); bRecalc_All = true; } else if (Row_last != Pos.Row && true === bBorder_insideh) { Cell_temp.Set_Border(Props.CellBorders.InsideH, 2); bRecalc_All = true; } if (CurCell === Cell_start && true === bBorder_left) { Cell_temp.Set_Border(Props.CellBorders.Left, 3); bRecalc_All = true; } else if (CurCell != Cell_start && true === bBorder_insidev) { Cell_temp.Set_Border(Props.CellBorders.InsideV, 3); bRecalc_All = true; } if (CurCell === Cell_end && true === bBorder_right) { Cell_temp.Set_Border(Props.CellBorders.Right, 1); bRecalc_All = true; } else if (CurCell != Cell_end && true === bBorder_insidev) { Cell_temp.Set_Border(Props.CellBorders.InsideV, 1); bRecalc_All = true; } } } } } // TableBackground (заливка таблицы) if (undefined !== Props.TableBackground) { if (Props.TableBackground.Value != TablePr.Shd.Value || Props.TableBackground.Color.r != TablePr.Shd.Color.r || Props.TableBackground.Color.g != TablePr.Shd.Color.g || Props.TableBackground.Color.b != TablePr.Shd.Color.b) { this.Set_TableShd(Props.TableBackground.Value, Props.TableBackground.Color.r, Props.TableBackground.Color.g, Props.TableBackground.Color.b); for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); oCell.Set_Shd({ Value : Props.TableBackground.Value, Color : { r : Props.TableBackground.Color.r, g : Props.TableBackground.Color.g, b : Props.TableBackground.Color.b, Auto : false }, Fill : { r : Props.TableBackground.Color.r, g : Props.TableBackground.Color.g, b : Props.TableBackground.Color.b, Auto : false } }); } } } } // CellsBackground (заливка ячеек) if ("undefined" != typeof(Props.CellsBackground) && null != Props.CellsBackground) { if (false === Props.CellSelect && true === bSpacing) { for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Row = this.Content[CurRow]; for (var CurCell = 0; CurCell < Row.Get_CellsCount(); CurCell++) { var oUnifill = Props.CellsBackground.Unifill; var Cell = Row.Get_Cell(CurCell); var NewShd = { Value : Props.CellsBackground.Value, Color : { r : Props.CellsBackground.Color.r, g : Props.CellsBackground.Color.g, b : Props.CellsBackground.Color.b, Auto : false }, Fill : { r : Props.CellsBackground.Color.r, g : Props.CellsBackground.Color.g, b : Props.CellsBackground.Color.b, Auto : false }, Unifill : oUnifill ? oUnifill.createDuplicate() : undefined, ThemeFill : oUnifill ? oUnifill.createDuplicate() : undefined }; Cell.Set_Shd(NewShd); bRedraw = true; } } } else if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { for (var Index = 0; Index < this.Selection.Data.length; Index++) { var Pos = this.Selection.Data[Index]; var Cell = this.Content[Pos.Row].Get_Cell(Pos.Cell); var Cell_shd = Cell.Get_Shd(); if (Props.CellsBackground.Value != Cell_shd.Value || Props.CellsBackground.Color.r != Cell_shd.Color.r || Props.CellsBackground.Color.g != Cell_shd.Color.g || Props.CellsBackground.Color.b != Cell_shd.Color.b || !AscFormat.CompareUnifillBool(Props.CellsBackground.Unifill, Cell_shd.Unifill)) { var oUnifill = Props.CellsBackground.Unifill; var NewShd = { Value : Props.CellsBackground.Value, Color : { r : Props.CellsBackground.Color.r, g : Props.CellsBackground.Color.g, b : Props.CellsBackground.Color.b, Auto : false }, Fill : { r : Props.CellsBackground.Color.r, g : Props.CellsBackground.Color.g, b : Props.CellsBackground.Color.b, Auto : false }, Unifill : oUnifill ? oUnifill.createDuplicate() : undefined, ThemeFill : oUnifill ? oUnifill.createDuplicate() : undefined }; Cell.Set_Shd(NewShd); bRedraw = true; } } } else { var Cell = this.CurCell; var Cell_shd = Cell.Get_Shd(); if (Props.CellsBackground.Value != Cell_shd.Value || Props.CellsBackground.Color.r != Cell_shd.Color.r || Props.CellsBackground.Color.g != Cell_shd.Color.g || Props.CellsBackground.Color.b != Cell_shd.Color.b || !AscFormat.CompareUnifillBool(Props.CellsBackground.Unifill, Cell_shd.Unifill)) { var oUnifill = Props.CellsBackground.Unifill; var NewShd = { Value : Props.CellsBackground.Value, Color : { r : Props.CellsBackground.Color.r, g : Props.CellsBackground.Color.g, b : Props.CellsBackground.Color.b, Auto : false }, Fill : { r : Props.CellsBackground.Color.r, g : Props.CellsBackground.Color.g, b : Props.CellsBackground.Color.b, Auto : false }, Unifill : oUnifill ? oUnifill.createDuplicate() : undefined, ThemeFill : oUnifill ? oUnifill.createDuplicate() : undefined }; Cell.Set_Shd(NewShd); bRedraw = true; } } } // CellsVAlign (вертикальное выравнивание ячеек) if (undefined != Props.CellsVAlign && null != Props.CellsVAlign) { if (this.Selection.Use === true && table_Selection_Cell === this.Selection.Type) { var Count = this.Selection.Data.length; for (var Index = 0; Index < Count; Index++) { var Pos = this.Selection.Data[Index]; var Cell = this.Content[Pos.Row].Get_Cell(Pos.Cell); Cell.Set_VAlign(Props.CellsVAlign); } } else { this.CurCell.Set_VAlign(Props.CellsVAlign); } bRecalc_All = true; } // CellsTextDirection if (undefined !== Props.CellsTextDirection && null !== Props.CellsTextDirection) { var TextDirection = undefined; switch (Props.CellsTextDirection) { case c_oAscCellTextDirection.LRTB: TextDirection = textdirection_LRTB; break; case c_oAscCellTextDirection.TBRL: TextDirection = textdirection_TBRL; break; case c_oAscCellTextDirection.BTLR: TextDirection = textdirection_BTLR; break; } if (undefined !== TextDirection) { if (this.Selection.Use === true && table_Selection_Cell === this.Selection.Type) { var Count = this.Selection.Data.length; for (var Index = 0; Index < Count; ++Index) { var Pos = this.Selection.Data[Index]; var Cell = this.Content[Pos.Row].Get_Cell(Pos.Cell); Cell.Set_TextDirectionFromApi(TextDirection); } } else { this.CurCell.Set_TextDirectionFromApi(TextDirection); } } } // CellsNoWrap if (undefined !== Props.CellsNoWrap && null !== Props.CellsNoWrap) { if (this.Selection.Use === true && table_Selection_Cell === this.Selection.Type) { var Count = this.Selection.Data.length; for (var Index = 0; Index < Count; ++Index) { var Pos = this.Selection.Data[Index]; var Cell = this.Content[Pos.Row].Get_Cell(Pos.Cell); Cell.SetNoWrap(Props.CellsNoWrap); } } else { this.CurCell.SetNoWrap(Props.CellsNoWrap); } } // CellsWidth if (undefined !== Props.CellsWidth) { var CellsWidth = Props.CellsWidth; if (null !== CellsWidth && Math.abs(CellsWidth) < 0.001) CellsWidth = null; if (this.Selection.Use === true && table_Selection_Cell === this.Selection.Type) { var Count = this.Selection.Data.length; for (var Index = 0; Index < Count; ++Index) { var Pos = this.Selection.Data[Index]; var Cell = this.Content[Pos.Row].Get_Cell(Pos.Cell); if (null === CellsWidth) Cell.Set_W(new CTableMeasurement(tblwidth_Auto, 0)); else if (CellsWidth > -0.001) Cell.Set_W(new CTableMeasurement(tblwidth_Mm, CellsWidth)); else Cell.Set_W(new CTableMeasurement(tblwidth_Pct, Math.abs(CellsWidth))); } } else { if (null === CellsWidth) this.CurCell.Set_W(new CTableMeasurement(tblwidth_Auto, 0)); else if (CellsWidth > -0.001) this.CurCell.Set_W(new CTableMeasurement(tblwidth_Mm, CellsWidth)); else this.CurCell.Set_W(new CTableMeasurement(tblwidth_Pct, Math.abs(CellsWidth))); } } // TableDescription if (undefined !== Props.TableDescription && null !== Props.TableDescription) { this.Set_TableDescription(Props.TableDescription); } // TableCaption if (undefined !== Props.TableCaption && null !== Props.TableCaption) { this.Set_TableCaption(Props.TableCaption); } if (undefined !== Props.RowHeight) this.SetRowHeight(Props.RowHeight); if (undefined !== Props.ColumnWidth) this.SetColumnWidth(Props.ColumnWidth); return true; }; CTable.prototype.Get_Styles = function(Lvl) { if (this.Parent) return this.Parent.Get_Styles(Lvl); return null; }; CTable.prototype.Get_TextBackGroundColor = function() { // Сначала проверим заливку данной таблицы, если ее нет, тогда спрашиваем у родительского класса var Shd = this.Get_Shd(); if (Shd && !Shd.IsNil()) return Shd.GetSimpleColor(this.Get_Theme(), this.Get_ColorMap()); return this.Parent.Get_TextBackGroundColor(); }; CTable.prototype.Get_Numbering = function() { if (this.Parent) return this.Parent.Get_Numbering(); return null; }; CTable.prototype.Get_PageBounds = function(CurPage) { return this.Pages[CurPage].Bounds; }; CTable.prototype.GetPageBounds = function(nCurPage) { return this.Get_PageBounds(nCurPage); }; CTable.prototype.getRowBounds = function(iRow, relPage) { let page = this.Pages[relPage]; let rowInfo = this.RowsInfo[iRow]; if (!this.IsRecalculated() || undefined === page || undefined === rowInfo || undefined === rowInfo.Y[relPage]) return new CDocumentBounds(0, 0, 0, 0); // Возвращаем границы, по которым реально происходит отрисовка let leftCorrection = this.GetTableOffsetCorrection(); return new CDocumentBounds( rowInfo.X0 + page.X_origin + leftCorrection, rowInfo.Y[relPage], rowInfo.X1 + page.X_origin + leftCorrection, rowInfo.Y[relPage] + rowInfo.H[relPage] ); }; CTable.prototype.getRowPageRange = function(iRow) { let rowInfo = this.RowsInfo[iRow]; if (!this.IsRecalculate() || undefined === rowInfo) return [0, 0]; return [rowInfo.StartPage, rowInfo.StartPage + rowInfo.Pages - 1]; }; CTable.prototype.GetContentBounds = function(CurPage) { return this.Get_PageBounds(CurPage); }; /** * @param pageIndex * @returns {?CTablePage} */ CTable.prototype.GetPage = function(pageIndex) { return this.Pages[pageIndex]; }; CTable.prototype.Get_PagesCount = function() { return this.Pages.length; }; CTable.prototype.GetAllDrawingObjects = function(DrawingObjs) { if (undefined === DrawingObjs) DrawingObjs = []; var Rows_Count = this.Content.length; for (var CurRow = 0; CurRow < Rows_Count; CurRow++) { var Row = this.Content[CurRow]; var Cells_Count = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < Cells_Count; CurCell++) { var Cell = Row.Get_Cell(CurCell); Cell.Content.GetAllDrawingObjects(DrawingObjs); } } return DrawingObjs; }; CTable.prototype.GetAllComments = function(AllComments) { if (undefined === AllComments) AllComments = []; var Rows_Count = this.Content.length; for (var CurRow = 0; CurRow < Rows_Count; CurRow++) { var Row = this.Content[CurRow]; var Cells_Count = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < Cells_Count; CurCell++) { var Cell = Row.Get_Cell(CurCell); Cell.Content.GetAllComments(AllComments); } } return AllComments; }; CTable.prototype.GetAllMaths = function(AllMaths) { if (undefined === AllMaths) AllMaths = []; var Rows_Count = this.Content.length; for (var CurRow = 0; CurRow < Rows_Count; CurRow++) { var Row = this.Content[CurRow]; var Cells_Count = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < Cells_Count; CurCell++) { var Cell = Row.Get_Cell(CurCell); Cell.Content.GetAllMaths(AllMaths); } } return AllMaths; }; CTable.prototype.GetAllFloatElements = function(FloatObjs) { if (undefined === FloatObjs) FloatObjs = []; var Rows_Count = this.Content.length; for (var CurRow = 0; CurRow < Rows_Count; CurRow++) { var Row = this.Content[CurRow]; var Cells_Count = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < Cells_Count; CurCell++) { var Cell = Row.Get_Cell(CurCell); Cell.Content.GetAllFloatElements(FloatObjs); } } return FloatObjs; }; CTable.prototype.GetAllFields = function(isSelection, arrFields) { if (!arrFields) arrFields = []; if (isSelection) { if (this.IsCellSelection()) { var arrCellsArray = this.GetSelectionArray(); for (var nPos = 0, nCount = arrCellsArray.length; nPos < nCount; ++nPos) { var oCellPos = arrCellsArray[nPos]; var oCurCell = this.GetRow(oCellPos.Row).GetCell(oCellPos.Cell); var oCellContent = oCurCell.GetContent(); oCellContent.SelectAll(); oCellContent.GetAllFields(true, arrFields); oCellContent.RemoveSelection(); } } else { this.CurCell.Content.GetAllFields(isSelection, arrFields); } } else { for (let iRow = 0, rowCount = this.GetRowsCount(); iRow < rowCount; ++iRow) { let row = this.GetRow(iRow); for (let iCell = 0, cellCount = row.GetCellsCount(); iCell < cellCount; ++iCell) { row.GetCell(iCell).GetContent().GetAllFields(false, arrFields); } } } return arrFields; }; CTable.prototype.IsTableCellSelection = function() { if (this.IsInnerTable()) return this.CurCell.GetContent().IsTableCellSelection(); return this.IsCellSelection(); }; CTable.prototype.GetAllSeqFieldsByType = function(sType, aFields) { var aRows = this.Content; for(var i = 0; i < aRows.length; ++i) { var aCells = aRows[i].Content; for(var j = 0; j < aCells.length; ++j) { var oCell = aCells[j]; oCell.Content.GetAllSeqFieldsByType(sType, aFields); } } }; CTable.prototype.FindParagraph = function (fCondition, bBackward, nStartIdx) { var nSearchStartIdx, nIdx, oResult; if(bBackward) { if(nStartIdx !== null) { nSearchStartIdx = Math.min(nStartIdx, this.Content.length - 1); } else { nSearchStartIdx = this.Content.length - 1; } for(nIdx = nSearchStartIdx; nIdx >= 0; --nIdx) { oResult = this.Content[nIdx].FindParagraph(fCondition, bBackward, null); if(oResult) { return oResult } } } else { if(nStartIdx !== null) { nSearchStartIdx = Math.max(nStartIdx, 0); } else { nSearchStartIdx = 0; } for(nIdx = nSearchStartIdx; nIdx < this.Content.length; ++nIdx) { oResult = this.Content[nIdx].FindParagraph(fCondition, bBackward, null); if(oResult) { return oResult } } } return null; }; CTable.prototype.FindParaWithStyle = function (sStyleId, bBackward, nStartIdx) { let fCondition = function (oParagraph) { return oParagraph.GetParagraphStyle() === sStyleId; }; return this.FindParagraph(fCondition, bBackward, nStartIdx); }; CTable.prototype.FindParaWithOutlineLvl = function (nOutlineLvl, bBackward, nStartIdx) { let fCondition = function (oParagraph) { return oParagraph.GetOutlineLvl() === nOutlineLvl; }; return this.FindParagraph(fCondition, bBackward, nStartIdx); }; /** * Данная функция запрашивает новую позицию для содержимого у ячейки, разбивающейся на несколько страниц */ CTable.prototype.GetCellPageContentFrame = function(CurPage, RowIndex, CellIndex) { var Row = this.Content[RowIndex]; var Cell = Row.Get_Cell(CellIndex); var CellMar = Cell.GetMargins(); var CellInfo = Row.Get_CellInfo(CellIndex); var VMerge_count = this.Internal_GetVertMergeCount(RowIndex, CellInfo.StartGridCol, Cell.Get_GridSpan()); // Возможно первая ячейка, для которой мы рассчитваем перенос на следующую страницу // имеет вертикальное объединение. Поэтому строка, по которой идет перенос не RowIndex, // а последняя строка в объединении. RowIndex = RowIndex + VMerge_count - 1; Row = this.Content[RowIndex]; let contentFrame = this.GetPageContentFrame(CurPage); // На момент обращения к данной функции, у всех ячеек всех строк до текущей (включительно) должны быть // просчитаны верхние границы. И также должен быть просчитан заголовок на данной странице, если он есть. var bHeader = false; var Y = contentFrame.Y; if (true !== this.HeaderInfo.HeaderRecalculate && -1 != this.HeaderInfo.PageIndex && this.HeaderInfo.Count > 0 && CurPage > this.HeaderInfo.PageIndex && true === this.HeaderInfo.Pages[CurPage].Draw) { Y = this.HeaderInfo.Pages[CurPage].RowsInfo[this.HeaderInfo.Count - 1].TableRowsBottom; bHeader = true; } var CellSpacing = Row.Get_CellSpacing(); if (null != CellSpacing) { var Table_Border_Top = this.Get_Borders().Top; if (border_Single === Table_Border_Top.Value) Y += Table_Border_Top.Size; if (true === bHeader || 0 === CurPage || ( 1 === CurPage && true != this.RowsInfo[0].FirstPage )) Y += CellSpacing; else Y += CellSpacing / 2; } // Далее вычислим маскимальную ширину верхней границы всех ячеек в данной // строке, учитывая ячейки, учавствующие в вертикальном объединении. var MaxTopBorder = this.private_GetMaxTopBorderWidth(RowIndex, bHeader); contentFrame.X = this.Pages[CurPage].X; Y += MaxTopBorder; // Учтем верхнее поле ячейки Y += CellMar.Top.W; var YLimit = contentFrame.YLimit; YLimit -= this.Pages[CurPage].FootnotesH; // TODO: Здесь надо учитывать нижнюю границу ячейки и вычесть ее ширину из YLimit return {X : contentFrame.X + CellInfo.X_content_start, XLimit : contentFrame.X + CellInfo.X_content_end, Y : Y, YLimit : YLimit, MaxTopBorder : MaxTopBorder }; }; CTable.prototype.Get_MaxTopBorder = function(RowIndex) { // Вычислим маскимальную ширину верхней границы всех ячеек в данной // строке, учитывая ячейки, учавствующие в вертикальном объединении. var Row = this.Content[RowIndex]; var MaxTopBorder = 0; var CellsCount = Row.Get_CellsCount(); var TableBorders = this.Get_Borders(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var Cell = Row.Get_Cell(CurCell); var VMerge = Cell.GetVMerge(); if (vmerge_Continue === VMerge) Cell = this.Internal_Get_StartMergedCell(RowIndex, Row.Get_CellInfo(CurCell).StartGridCol, Cell.Get_GridSpan()); var BorderInfo_Top = Cell.GetBorderInfo().Top; if (null === BorderInfo_Top) continue; for (var Index = 0; Index < BorderInfo_Top.length; Index++) { var CurBorder = BorderInfo_Top[Index]; var ResultBorder = this.private_ResolveBordersConflict(CurBorder, TableBorders.Top, false, true); if (border_Single === ResultBorder.Value && MaxTopBorder < ResultBorder.Size) MaxTopBorder = ResultBorder.Size; } } return MaxTopBorder; }; /** * Вычисляем небольшое смещение по X, необходимое для совместимости с Word разных версий */ CTable.prototype.GetTableOffsetCorrection = function() { var X = 0; if (!this.Parent || true === this.Parent.IsTableCellContent() || this.bPresentation || !this.LogicDocument || !this.LogicDocument.GetCompatibilityMode || this.LogicDocument.GetCompatibilityMode() >= AscCommon.document_compatibility_mode_Word15) return 0; var Row = this.Content[0]; var Cell = Row.Get_Cell(0); var Margins = Cell.GetMargins(); var CellSpacing = Row.Get_CellSpacing(); if (null != CellSpacing) { var TableBorder_Left = this.Get_Borders().Left; if (border_None != TableBorder_Left.Value) X += TableBorder_Left.Size / 2; X += CellSpacing; var CellBorder_Left = Cell.Get_Borders().Left; if (border_None != CellBorder_Left.Value) X += CellBorder_Left.Size; X += Margins.Left.W; } else { var TableBorder_Left = this.Get_Borders().Left; var CellBorder_Left = Cell.Get_Borders().Left; var Result_Border = this.private_ResolveBordersConflict(TableBorder_Left, CellBorder_Left, true, false); if (border_None != Result_Border.Value) X += Math.max(Result_Border.Size / 2, Margins.Left.W); else X += Margins.Left.W; } return -X; }; CTable.prototype.GetRightTableOffsetCorrection = function() { var X = 0; if (!this.Parent || true === this.Parent.IsTableCellContent() || this.bPresentation || !this.LogicDocument || !this.LogicDocument.GetCompatibilityMode || this.LogicDocument.GetCompatibilityMode() >= AscCommon.document_compatibility_mode_Word15) return 0; var Row = this.Content[0]; var Cell = Row.Get_Cell(Row.Get_CellsCount() - 1); var Margins = Cell.GetMargins(); var CellSpacing = Row.Get_CellSpacing(); if (null != CellSpacing) { var TableBorder_Right = this.Get_Borders().Right; if (border_None != TableBorder_Right.Value) X += TableBorder_Right.Size / 2; X += CellSpacing; var CellBorder_Right = Cell.Get_Borders().Right; if (border_None != CellBorder_Right.Value) X += CellBorder_Right.Size; X += Margins.Right.W; } else { var TableBorder_Right = this.Get_Borders().Right; var CellBorder_Right = Cell.Get_Borders().Right; var Result_Border = this.private_ResolveBordersConflict(TableBorder_Right, CellBorder_Right, true, false); if (border_None != Result_Border.Value) X += Math.max(Result_Border.Size / 2, Margins.Right.W); else X += Margins.Right.W; } return X; }; /** * Получаем первый параграф первой ячейки. (Нужно, например, для контроля ContextualSpacing) */ CTable.prototype.Get_FirstParagraph = function() { if (this.Content.length <= 0 || this.Content[0].Content.length <= 0) return null; return this.Content[0].Content[0].Content.Get_FirstParagraph(); }; CTable.prototype.GetAllParagraphs = function(Props, ParaArray) { if (!ParaArray) ParaArray = []; var Count = this.Content.length; for (var CurRow = 0; CurRow < Count; CurRow++) { var Row = this.Content[CurRow]; var Cells_Count = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < Cells_Count; CurCell++) { var Cell = Row.Get_Cell(CurCell); Cell.Content.GetAllParagraphs(Props, ParaArray); } } return ParaArray; }; CTable.prototype.GetAllTables = function(oProps, tables) { if (!tables) tables = []; tables.push(this); this.GetNestedTables(tables); return tables; }; CTable.prototype.GetNestedTables = function(tables) { if (!tables) tables = []; for (let iRow = 0, rowCount = this.GetRowsCount(); iRow < rowCount; ++iRow) { let row = this.GetRow(iRow); for (let iCell = 0, cellCount = row.GetCellsCount(); iCell < cellCount; ++iCell) { row.GetCell(iCell).GetContent().GetAllTables(undefined, tables); } } return tables; }; CTable.prototype.GetEndInfo = function() { var RowsCount = this.Content.length; if (RowsCount > 0) return this.Content[RowsCount - 1].GetEndInfo(); return null; }; CTable.prototype.GetPrevElementEndInfo = function(RowIndex) { if (-1 === RowIndex || !this.Parent || !this.Content[RowIndex]) return null; if (0 === RowIndex) return this.Parent.GetPrevElementEndInfo(this); else return this.Content[RowIndex - 1].GetEndInfo(); }; //---------------------------------------------------------------------------------------------------------------------- // Функции к которым идет обращение из родительского класса //---------------------------------------------------------------------------------------------------------------------- CTable.prototype.Copy = function(Parent, DrawingDocument, oPr) { var TableGrid = this.private_CopyTableGrid(); var Table = new CTable(this.DrawingDocument, Parent, this.Inline, 0, 0, TableGrid, this.bPresentation); Table.Set_Distance(this.Distance.L, this.Distance.T, this.Distance.R, this.Distance.B); Table.Set_PositionH(this.PositionH.RelativeFrom, this.PositionH.Align, this.PositionH.Value); Table.Set_PositionV(this.PositionV.RelativeFrom, this.PositionV.Align, this.PositionV.Value); // Копируем настройки var sStyle = this.TableStyle; if(oPr && oPr.Comparison) { sStyle = oPr.Comparison.copyStyleById(sStyle); } Table.Set_TableStyle(sStyle); Table.Set_TableLook(this.TableLook.Copy()); Table.SetPr(this.Pr.Copy()); Table.Rows = this.Rows; Table.Cols = this.Cols; // Копируем строки var Rows = this.Content.length; var Index; for (Index = 0; Index < Rows; Index++) { Table.Content[Index] = this.Content[Index].Copy(Table, oPr); Table.Content[Index].Recalc_CompiledPr(); AscCommon.History.Add(new CChangesTableAddRow(Table, Index, [Table.Content[Index]])); } Table.Internal_ReIndexing(0); Table.private_UpdateTableGrid(); Table.Recalc_CompiledPr(); if (Table.Content.length > 0 && Table.Content[0].Get_CellsCount() > 0) Table.CurCell = Table.Content[0].Get_Cell(0); return Table; }; CTable.prototype.Shift = function(CurPage, Dx, Dy) { this.Pages[CurPage].Shift(Dx, Dy); if (0 === CurPage) { this.X_origin += Dx; this.X += Dx; this.Y += Dy; this.XLimit += Dx; this.YLimit += Dy; } var StartRow = this.Pages[CurPage].FirstRow; var LastRow = this.Pages[CurPage].LastRow; for (var CurRow = StartRow; CurRow <= LastRow; CurRow++) { var Row = this.Content[CurRow]; var CellsCount = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var Cell = Row.Get_Cell(CurCell); var CellPageIndex = CurPage - Cell.Content.GetRelativeStartPage(); if (vmerge_Restart === Cell.GetVMerge()) { Cell.ShiftCell(CellPageIndex, Dx, Dy); } } this.RowsInfo[CurRow].Y[CurPage] += Dy; this.TableRowsBottom[CurRow][CurPage] += Dy; } if (!this.bPresentation && !this.IsInline() && this.GetLogicDocument()) { var oLogicDocument = this.GetLogicDocument(); var oDrawingObjects = oLogicDocument.GetDrawingObjects(); oDrawingObjects.updateFloatTable(new CFlowTable(this, this.PageNum + CurPage)); } }; CTable.prototype.IsMoveWithTextVertically = function() { var oVertRelative = this.GetPositionV().RelativeFrom; return (Asc.c_oAscVAnchor.Text === oVertRelative); }; CTable.prototype.UpdateEndInfo = function() { for (var RowIndex = 0, RowsCount = this.Content.length; RowIndex < RowsCount; RowIndex++) { var Row = this.Content[RowIndex]; for (var CellIndex = 0, CellsCount = Row.Get_CellsCount(); CellIndex < CellsCount; CellIndex++) { var Cell = Row.Get_Cell(CellIndex); Cell.Content.UpdateEndInfo(); } } }; CTable.prototype.Internal_UpdateFlowPosition = function(X, Y) { this.X_origin = X; var Dx = this.GetTableOffsetCorrection(); this.X = X + Dx; this.Y = Y; this.Set_PositionH(c_oAscHAnchor.Page, false, this.X_origin); this.Set_PositionV(c_oAscVAnchor.Page, false, this.Y); }; CTable.prototype.Move = function(X, Y, PageNum, NearestPos) { let logicDocument = this.GetLogicDocument(); if (!logicDocument || !logicDocument.IsDocumentEditor()) return; this.Document_SetThisElementCurrent(false); this.MoveCursorToStartPos(); let isCancelMove = false; var oTargetTable = this; if (true != this.Is_Inline()) { if (false === logicDocument.Document_Is_SelectionLocked(AscCommon.changestype_Table_Properties, null, true)) { logicDocument.StartAction(AscDFH.historydescription_Document_MoveFlowTable); // Переносим привязку (если получается, что заносим таблицу саму в себя, тогда привязку не меняем) var NewDocContent = NearestPos.Paragraph.Parent; var OldDocContent = this.Parent; var oPageLimits; if (true != NewDocContent.CheckTableCoincidence(this)) { var OldIndex = this.Index; var NewIndex = NearestPos.Paragraph.Index; // Проверим можем ли мы добавить таблицу перед параграфом так, чтобы таблица осталась на данной странице if (PageNum > NearestPos.Paragraph.GetAbsoluteStartPage()) { if (NearestPos.Paragraph.Pages.length > 2) { // Параграф начинается до заданной страницы и заканчивается после. Нам нужно разделить его на // 2 параграфа в заданной точке. var NewParagraph = new AscWord.Paragraph(); NearestPos.Paragraph.Split(NewParagraph, NearestPos.ContentPos); NewDocContent.Internal_Content_Add(NewIndex + 1, NewParagraph); // Если все происходило в одном классе-документе, тогда проверяем индексы if (NewDocContent === OldDocContent && NewIndex + 1 <= OldIndex) OldIndex++; NewIndex++; } else { // Вставляем таблицу после найденного параграфа. Если параграф последний, тогда // в конец добавляем новый пустой параграф NewIndex++; if (NewIndex >= NewDocContent.Content.length - 1) NewDocContent.Internal_Content_Add(NewDocContent.Content.length, new AscWord.Paragraph()); } } oTargetTable = AscCommon.CollaborativeEditing.Is_SingleUser() ? this : this.Copy(NewDocContent); if (NewDocContent !== OldDocContent) { OldDocContent.Internal_Content_Remove(OldIndex, 1); NewDocContent.Internal_Content_Add(NewIndex, oTargetTable); oTargetTable.Parent = NewDocContent; } else if (NewIndex !== OldIndex && OldIndex + 1 !== NewIndex) { if (NewIndex > OldIndex) { OldDocContent.Internal_Content_Remove(OldIndex, 1); NewDocContent.Internal_Content_Add(NewIndex - 1, oTargetTable); } else { OldDocContent.Internal_Content_Remove(OldIndex, 1); NewDocContent.Internal_Content_Add(NewIndex, oTargetTable); } } oPageLimits = NewDocContent.Get_PageLimits(NearestPos.Paragraph.GetRelativePage(NearestPos.Internal.Page)) } else { oPageLimits = OldDocContent.Get_PageLimits(this.GetRelativePage(0)) } // Обновляем координаты // Здесь мы должны для первого рассчета оставить привязку относительно страницы, а после рассчета // изменить привязку на старую, при этом пересчитав координаты так, чтобы картинка не изменила // своего положения. oTargetTable.PositionH_Old = { RelativeFrom : oTargetTable.PositionH.RelativeFrom, Align : oTargetTable.PositionH.Align, Value : oTargetTable.PositionH.Value }; oTargetTable.PositionV_Old = { RelativeFrom : oTargetTable.PositionV.RelativeFrom, Align : oTargetTable.PositionV.Align, Value : oTargetTable.PositionV.Value }; oTargetTable.PositionH.RelativeFrom = c_oAscHAnchor.Page; oTargetTable.PositionH.Align = false; oTargetTable.PositionH.Value = X - oPageLimits.X; oTargetTable.PositionV.RelativeFrom = c_oAscVAnchor.Page; oTargetTable.PositionV.Align = false; oTargetTable.PositionV.Value = Y - oPageLimits.Y; oTargetTable.PageNum = PageNum; var nTableInd = oTargetTable.Get_TableInd(); if (Math.abs(nTableInd) > 0.001) oTargetTable.Set_TableInd(0); this.LogicDocument.Recalculate(true); oTargetTable.StartTrackTable(); // Если так случилось, что после пересчета позиции не пересчитались, тогда нам нужно оставить привязку к // странице, чтобы таблица правильна расположилась. Такое происходит, если перемещать таблицу больше, // чем на 3 страницы и до пересчета успевает пройти сохранение. if (undefined !== oTargetTable.PositionH_Old) { // Восстанови старые значения, чтобы в историю изменений все нормально записалось oTargetTable.PositionH.RelativeFrom = oTargetTable.PositionH_Old.RelativeFrom; oTargetTable.PositionH.Align = oTargetTable.PositionH_Old.Align; oTargetTable.PositionH.Value = oTargetTable.PositionH_Old.Value; oTargetTable.Set_PositionH(c_oAscHAnchor.Page, false, X); oTargetTable.PositionH_Old = undefined; } if (undefined !== oTargetTable.PositionV_Old) { // Восстанови старые значения, чтобы в историю изменений все нормально записалось oTargetTable.PositionV.RelativeFrom = oTargetTable.PositionV_Old.RelativeFrom; oTargetTable.PositionV.Align = oTargetTable.PositionV_Old.Align; oTargetTable.PositionV.Value = oTargetTable.PositionV_Old.Value; oTargetTable.Set_PositionV(c_oAscVAnchor.Page, false, Y); oTargetTable.PositionV_Old = undefined; } logicDocument.FinalizeAction(); } } else { // Проверяем, можно ли двигать данную таблицу if (false === logicDocument.Document_Is_SelectionLocked(AscCommon.changestype_Table_Properties, { Type : AscCommon.changestype_2_InlineObjectMove, PageNum : PageNum, X : X, Y : Y }, true)) { logicDocument.StartAction(AscDFH.historydescription_Document_MoveInlineTable); var NewDocContent = NearestPos.Paragraph.Parent; var OldDocContent = this.Parent; if (true != NewDocContent.CheckTableCoincidence(this)) { var TarParagraph = NearestPos.Paragraph; var ParaContentPos = NearestPos.ContentPos; var OldIndex = this.Index; var NewIndex = NearestPos.Paragraph.Index; // Если позиция в начале параграфа, тогда добавляем таблицу до параграфа, если в конце, тогда // после параграфа, в противном случае разделяем параграф. if (true === TarParagraph.IsCursorAtEnd(ParaContentPos)) { NewIndex++; } else if (true != TarParagraph.IsCursorAtBegin(ParaContentPos)) { var NewParagraph = new AscWord.Paragraph(); NearestPos.Paragraph.Split(NewParagraph, NearestPos.ContentPos); NewDocContent.Internal_Content_Add(NewIndex + 1, NewParagraph); // Если все происходило в одном классе-документе, тогда проверяем индексы if (NewDocContent === OldDocContent && NewIndex + 1 <= OldIndex) OldIndex++; NewIndex++; } oTargetTable = AscCommon.CollaborativeEditing.Is_SingleUser() ? this : this.Copy(NewDocContent); if (NewDocContent !== OldDocContent) { // Сначала добавляем таблицу в новый класс NewDocContent.Internal_Content_Add(NewIndex, oTargetTable); // Удаляем таблицу из родительского класса OldDocContent.Internal_Content_Remove(OldIndex, 1); oTargetTable.Parent = NewDocContent; } else { if (NearestPos.Paragraph.Index > this.Index) { NewDocContent.Internal_Content_Add(NewIndex, oTargetTable); OldDocContent.Internal_Content_Remove(OldIndex, 1); } else { OldDocContent.Internal_Content_Remove(OldIndex, 1); NewDocContent.Internal_Content_Add(NewIndex, oTargetTable); } } if (!oTargetTable.IsUseInDocument()) { isCancelMove = true; logicDocument.CancelAction(); oTargetTable = this; } logicDocument.Recalculate(); } oTargetTable.StartTrackTable(); logicDocument.FinalizeAction(); } } logicDocument.RemoveSelection(); if (isCancelMove) oTargetTable.SelectAll(); else oTargetTable.MoveCursorToStartPos(); oTargetTable.Document_SetThisElementCurrent(true); logicDocument.UpdateSelection(); }; CTable.prototype.Reset = function(X, Y, XLimit, YLimit, PageNum, ColumnNum, ColumnsCount, sectionIndex, sectPr) { this.X_origin = X; this.X = X; this.Y = Y + 0.001; // Погрешность для Flow-таблиц this.XLimit = XLimit; this.YLimit = YLimit; this.PageNum = PageNum; this.ColumnNum = ColumnNum ? ColumnNum : 0; this.ColumnsCount = ColumnsCount ? ColumnsCount : 1; this.SectionNum = sectionIndex ? sectionIndex : 0; this.private_CheckYLimitForFlowTableInHdrFtr(); this.private_CalculateTableWidthRange(); this.private_CheckRangeOnReset(); this.ResetSection(X, Y, XLimit, YLimit, PageNum, sectionIndex, sectPr); }; CTable.prototype.private_CalculateTableWidthRange = function() { if (this.ColumnsCount > 1) { var oSectPr = this.Get_SectPr(); this.TableWidthRange = oSectPr.GetMinColumnWidth(); } else { this.TableWidthRange = this.XLimit - this.X; } }; CTable.prototype.private_CheckRangeOnReset = function() { let X = this.X; let XLimit = this.XLimit; let compatibilityMode = this.LogicDocument && this.LogicDocument.GetCompatibilityMode ? this.LogicDocument.GetCompatibilityMode() : AscCommon.document_compatibility_mode_Current; if (this.LogicDocument && this.LogicDocument.IsDocumentEditor() && this.IsInline() && this.Parent && this.Parent.CheckRange && compatibilityMode <= AscCommon.document_compatibility_mode_Word14) { var arrRanges = this.Parent.CheckRange(X, this.Y, XLimit, this.Y + 0.001, this.Y, this.Y + 0.001, X, XLimit, this.GetRelativePage(0)); if (arrRanges.length > 0) { for (var nRangeIndex = 0, nRangesCount = arrRanges.length; nRangeIndex < nRangesCount; ++nRangeIndex) { if (arrRanges[nRangeIndex].X0 < this.X + 3.2 && arrRanges[nRangeIndex].X1 > X) X = arrRanges[nRangeIndex].X1 + 0.001; if (arrRanges[nRangeIndex].X1 > this.XLimit - 3.2 && arrRanges[nRangeIndex].X0 < XLimit) XLimit = arrRanges[nRangeIndex].X0 - 0.001; } } } this.X = X; this.XLimit = XLimit; }; CTable.prototype.private_CheckYLimitForFlowTableInHdrFtr = function() { // Здесь мы проверяем специальный случай, когда данная таблица находится в колонтитуле, она плавающая, и // привязана к странице или к полю по вертикали, у такой таблицы мы считаем, что нет нижней границы // Можно добавить условие, что это только в режиме совместимости Word14 и ниже, но с 15-ой версии у всего колонтитула // нижняя граница не задана let logicDocument = this.GetLogicDocument(); if (!logicDocument || !logicDocument.IsDocumentEditor() || this.IsInline() || this.IsMoveWithTextVertically() || !this.Parent || !this.Parent.IsHdrFtr() || this.IsInnerTable()) return; this.YLimit = AscWord.MAX_MM_VALUE; }; CTable.prototype.Recalculate = function() { // Пересчитываем сетку колонок this.private_RecalculateGrid(); this.Internal_Recalculate_1(); }; CTable.prototype.Reset_RecalculateCache = function() { this.RecalcInfo.Reset(true); var RowsCount = this.Content.length; for (var RowIndex = 0; RowIndex < RowsCount; RowIndex++) { var Row = this.Content[RowIndex]; var CellsCount = Row.Get_CellsCount(); for (var CellIndex = 0; CellIndex < CellsCount; CellIndex++) { var Cell = Row.Get_Cell(CellIndex); Cell.Content.Reset_RecalculateCache(); } } }; CTable.prototype.RecalculateCurPos = function(bUpdateX, bUpdateY, isUpdateTarget) { if (this.CurCell) return this.CurCell.Content_RecalculateCurPos(bUpdateX, bUpdateY, isUpdateTarget); return null; }; CTable.prototype.RecalculateMinMaxContentWidth = function(isRotated) { this.private_RecalculateGrid(); if (true === isRotated) { var arrMinContent = [], arrMaxContent = []; var nRowsCount = this.GetRowsCount(); for (var nCurRow = 0; nCurRow < nRowsCount; ++nCurRow) { arrMinContent[nCurRow] = 0; arrMaxContent[nCurRow] = 0; } for (var nCurRow = 0; nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); var oCellMinMax = oCell.RecalculateMinMaxContentWidth(false, this.CalculatedPctWidth); var nCellMin = oCellMinMax.ContentMin; var nCellMax = oCellMinMax.Max; if (arrMinContent[nCurRow] < nCellMin) arrMinContent[nCurRow] = nCellMin; if (arrMaxContent[nCurRow] < nCellMax) arrMaxContent[nCurRow] = nCellMax; } var oRowH = oRow.GetHeight(); if (Asc.linerule_Exact === oRowH.HRule || (linerule_AtLeast === oRowH.HRule && arrMinContent[nCurRow] < oRowH.Value)) arrMinContent[nCurRow] = oRowH.Value; if (Asc.linerule_Exact === oRowH.HRule || (linerule_AtLeast === oRowH.HRule && arrMaxContent[nCurRow] < oRowH.Value)) arrMaxContent[nCurRow] = oRowH.Value; } var nMin = 0; var nMax = 0; for (var nCurRow = 0; nCurRow < nRowsCount; ++nCurRow) { nMin += arrMinContent[nCurRow]; nMax += arrMaxContent[nCurRow]; } return {Min : nMin, Max : nMax}; } else { var arrMinMargin = [], arrMinContent = [], arrMaxContent = [], arrPreferred = [], // 0 - ориентируемся на содержимое ячеек, > 0 - ориентируемся только на ширину ячеек записанную в свойствах arrMinNoPref = []; // минимальное значение контента, только без учета предпочитаемы ширин var nColsCount = this.TableGridCalc.length; for (var nCurCol = 0; nCurCol < nColsCount; ++nCurCol) { arrMinMargin[nCurCol] = 0; arrMinContent[nCurCol] = 0; arrMaxContent[nCurCol] = 0; arrPreferred[nCurCol] = 0; arrMinNoPref[nCurCol] = 0; } this.private_RecalculateGridMinContent(this.CalculatedPctWidth, arrMinMargin, arrMinContent, arrMaxContent, arrPreferred, arrMinNoPref); var nMin = 0; var nMax = 0; for (var nCurCol = 0; nCurCol < nColsCount; ++nCurCol) { nMin += arrMinNoPref[nCurCol]; nMax += arrMaxContent[nCurCol]; } var oTableW = this.GetTableW(); if (oTableW) { var nValue = oTableW.GetValue(); if (oTableW.IsMM()) { if (nMin < nValue) nMin = nValue; if (nMax < nValue) nMax = nValue; } else if (oTableW.IsPercent()) { var nPercentWidth = this.private_RecalculatePercentWidth(); var mmValue = nValue / 100 * nPercentWidth; if (nMin < mmValue) nMin = mmValue; if (nMax < mmValue) nMax = mmValue; } } return {Min : nMin, Max : nMax}; } }; CTable.prototype.RecalculateAllTables = function() { this.private_RecalculateGrid(); this.private_RecalculateBorders(); var RowsCount = this.Content.length; for (var CurRow = 0; CurRow < RowsCount; CurRow++) { var Row = this.Content[CurRow]; var CellsCount = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var Cell = Row.Get_Cell(CurCell); Cell.Content.RecalculateAllTables(); } } }; CTable.prototype.GetLastRangeVisibleBounds = function() { var CurPage = this.Pages.length - 1; var Page = this.Pages[CurPage]; var CurRow = this.Content.length - 1; var Row = this.Content[CurRow]; // Ищем границы по горизонтали для последней ячейки var CurCell = Row.Get_CellsCount() - 1; var Cell = Row.Get_Cell(CurCell); var CellInfo = Row.Get_CellInfo(CurCell); var CellMar = Cell.GetMargins(); var X_start = Page.X + CellInfo.X_cell_start; var X_end = Page.X + CellInfo.X_cell_end; var Cell_PageRel = CurPage - Cell.Content.GetRelativeStartPage(); // Не все ячейки могут иметь страницу с номером Cell_PageRel, но хотя бы одна такая должна быть (иначе переноса // на новую страницу не было бы) var CellsCount = Row.Get_CellsCount(); for (CurCell = 0; CurCell < CellsCount; CurCell++) { Cell = Row.Get_Cell(CurCell); if (Cell_PageRel <= Cell.PagesCount - 1) break; } if (CurCell >= CellsCount) return {X : X_start, Y : 0, W : X_end - X_start, H : 0, BaseLine : 0, XLimit : Page.XLimit}; var Bounds = Cell.Content_Get_PageBounds(Cell_PageRel); var Y_offset = Cell.Temp.Y_VAlign_offset[Cell_PageRel]; var Y = 0; var H = 0; if (0 != Cell_PageRel) { // мы должны определить ряд, на котором случился перенос на новую страницу var TempRowIndex = this.Pages[CurPage].FirstRow; Y = this.RowsInfo[TempRowIndex].Y[CurPage] + this.RowsInfo[TempRowIndex].TopDy[CurPage] + CellMar.Top.W + Y_offset; H = this.RowsInfo[TempRowIndex].H[CurPage]; } else { Y = this.RowsInfo[CurRow].Y[CurPage] + this.RowsInfo[CurRow].TopDy[CurPage] + CellMar.Top.W + Y_offset; H = this.RowsInfo[CurRow].H[CurPage]; } return {X : X_start, Y : Y, W : X_end - X_start, H : H, BaseLine : H, XLimit : Page.XLimit}; }; CTable.prototype.FindNextFillingForm = function(isNext, isCurrent, isStart) { var nCurRow = this.Selection.Use === true ? this.Selection.StartPos.Pos.Row : this.CurCell.Row.Index; var nCurCell = this.Selection.Use === true ? this.Selection.StartPos.Pos.Cell : this.CurCell.Index; var nStartRow = 0, nStartCell = 0, nEndRow = 0, nEndCell = 0; if (isCurrent) { if (isStart) { nStartRow = nCurRow; nStartCell = nCurCell; nEndRow = isNext ? this.GetRowsCount() - 1 : 0; nEndCell = isNext ? this.GetRow(nEndRow).GetCellsCount() - 1 : 0; } else { nStartRow = isNext ? 0 : this.GetRowsCount() - 1; nStartCell = isNext ? 0 : this.GetRow(nStartRow).GetCellsCount() - 1; nEndRow = nCurRow; nEndCell = nCurCell; } } else { if (isNext) { nStartRow = 0; nStartCell = 0; nEndRow = this.GetRowsCount() - 1; nEndCell = this.GetRow(nEndRow).GetCellsCount() - 1; } else { nStartRow = this.GetRowsCount() - 1; nStartCell = this.GetRow(nStartRow).GetCellsCount() - 1; nEndRow = 0; nEndCell = 0; } } if (isNext) { for (var nRowIndex = nStartRow; nRowIndex <= nEndRow; ++nRowIndex) { var _nStartCell = nRowIndex === nStartRow ? nStartCell : 0; var _nEndCell = nRowIndex === nEndRow ? nEndCell : this.GetRow(nRowIndex).GetCellsCount() - 1; for (var nCellIndex = _nStartCell; nCellIndex <= _nEndCell; ++nCellIndex) { var oCell = this.GetRow(nRowIndex).GetCell(nCellIndex); var oRes = oCell.GetContent().FindNextFillingForm(true, isCurrent && nCellIndex === nCurCell && nRowIndex === nCurRow ? true : false, isStart); if (oRes) return oRes; } } } else { for (var nRowIndex = nStartRow; nRowIndex >= nEndRow; --nRowIndex) { var _nStartCell = nRowIndex === nStartRow ? nStartCell : this.GetRow(nRowIndex).GetCellsCount() - 1; var _nEndCell = nRowIndex === nEndRow ? nEndCell : 0; for (var nCellIndex = _nStartCell; nCellIndex >= _nEndCell; --nCellIndex) { var oCell = this.GetRow(nRowIndex).GetCell(nCellIndex); var oRes = oCell.GetContent().FindNextFillingForm(false, isCurrent && nCellIndex === nCurCell && nRowIndex === nCurRow ? true : false, isStart); if (oRes) return oRes; } } } return null; }; CTable.prototype.Get_NearestPos = function(CurPage, X, Y, bAnchor, Drawing) { var Pos = this.private_GetCellByXY(X, Y, CurPage); var Cell = this.Content[Pos.Row].Get_Cell(Pos.Cell); return Cell.Content_Get_NearestPos(CurPage - Cell.Content.GetRelativeStartPage(), X, Y, bAnchor, Drawing); }; CTable.prototype.Get_ParentTextTransform = function() { if (this.Parent) return this.Parent.Get_ParentTextTransform(); return null; }; /** * Проверяем начинается ли текущий параграф с новой страницы. */ CTable.prototype.IsStartFromNewPage = function() { if ((this.Pages.length > 1 && true === this.IsEmptyPage(0)) || (null === this.Get_DocumentPrev() && true === this.Parent.Is_TopDocument())) return true; return false; }; CTable.prototype.IsContentOnFirstPage = function() { if (this.Pages.length >= 1 && true === this.RowsInfo[0].FirstPage && this.Pages[0].LastRow >= this.Pages[0].FirstRow) return true; return false; }; CTable.prototype.IsTableBorder = function(X, Y, CurPage) { if (true === this.DrawingDocument.IsMobileVersion()) return null; CurPage = Math.max(0, Math.min(this.Pages.length - 1, CurPage)); if (true === this.IsEmptyPage(CurPage)) return null; var Result = this.private_CheckHitInBorder(X, Y, CurPage); if (Result.Border != -1) { return this; } else { var Cell = this.Content[Result.Pos.Row].Get_Cell(Result.Pos.Cell); return Cell.Content_Is_TableBorder(X, Y, CurPage - Cell.Content.GetRelativeStartPage()); } }; CTable.prototype.IsInText = function(X, Y, CurPage) { if (CurPage < 0 || CurPage >= this.Pages.length) CurPage = 0; var Result = this.private_CheckHitInBorder(X, Y, CurPage); if (Result.Border != -1) { return null; } else { var Cell = this.Content[Result.Pos.Row].Get_Cell(Result.Pos.Cell); return Cell.Content_Is_InText(X, Y, CurPage - Cell.Content.GetRelativeStartPage()); } }; CTable.prototype.IsInDrawing = function(X, Y, CurPage) { if (CurPage < 0 || CurPage >= this.Pages.length) CurPage = 0; var Result = this.private_CheckHitInBorder(X, Y, CurPage); if (Result.Border != -1) { return null; } else { var Cell = this.Content[Result.Pos.Row].Get_Cell(Result.Pos.Cell); return Cell.Content_Is_InDrawing(X, Y, CurPage - Cell.Content.GetRelativeStartPage()); } }; CTable.prototype.IsInnerTable = function() { if (this.Content.length <= 0) return false; if (false === this.Selection.Use || ( true === this.Selection.Use && table_Selection_Text === this.Selection.Type )) return this.CurCell.Content.Is_CurrentElementTable(); return false; }; CTable.prototype.IsUseInDocument = function(Id) { if (undefined !== Id && null !== Id) { let isFound = false; for (let nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { if (Id === this.GetRow(nCurRow).GetId()) { isFound = true; break; } } if (!isFound) return false; } if (-1 === this.GetIndex()) return false; return this.Parent.IsUseInDocument(); }; CTable.prototype.GetAbsoluteCurrentPage = function() { if (this.IsCellSelection()) { // Проходимся по всей последней выделенной строке и находим текущую страницу с наибольшим значением // Если мы будет брать текущую страницу просто у последней ячейки выделения, тогда нужно переделать функцию // CDocument.GetCurPage var nCurPage = 0; var nRow = this.Selection.EndPos.Pos.Row; if (this.RowsInfo[nRow]) nCurPage = this.RowsInfo[nRow].StartPage + this.RowsInfo[nRow].Pages - 1; return this.GetAbsolutePage(nCurPage); } else { return this.CurCell.Content.GetAbsoluteCurrentPage(); } }; CTable.prototype.GetRelativeCurrentPage = function() { if (true === this.Selection.Use) return 0; return this.CurCell.Content.GetAbsoluteCurrentPage() - this.GetAbsoluteStartPage(); }; CTable.prototype.UpdateCursorType = function(X, Y, CurPage) { if (CurPage < 0 || CurPage >= this.Pages.length) CurPage = 0; if (true === this.Lock.Is_Locked()) { var _X = this.Pages[CurPage].Bounds.Left; var _Y = this.Pages[CurPage].Bounds.Top; var MMData = new CMouseMoveData(); var Coords = this.DrawingDocument.ConvertCoordsToCursorWR(_X, _Y, this.GetAbsolutePage(CurPage)); MMData.X_abs = Coords.X - 5; MMData.Y_abs = Coords.Y - 5; MMData.Type = Asc.c_oAscMouseMoveDataTypes.LockedObject; MMData.UserId = this.Lock.Get_UserId(); MMData.HaveChanges = this.Lock.Have_Changes(); MMData.LockedObjectType = c_oAscMouseMoveLockedObjectType.Common; editor.sync_MouseMoveCallback(MMData); } if (true === this.Selection.Start || table_Selection_Border === this.Selection.Type2 || table_Selection_Border_InnerTable === this.Selection.Type2) return; if (this.LogicDocument && this.LogicDocument.IsShowTableAdjustments && this.LogicDocument.IsShowTableAdjustments()) { // Случай, когда у нас уже есть трэк вложенной таблицы и курсор выходит во внешнюю. Чтобы трэк сразу не пропадал, // пока курсор находится в области табличного трэка для вложенной таблицы. if (true !== this.DrawingDocument.IsCursorInTableCur(X, Y, this.GetAbsolutePage(CurPage), true) && true === this.Check_EmptyPages(CurPage - 1) && true !== this.IsEmptyPage(CurPage)) { this.private_StartTrackTable(CurPage); } var oHitInfo = this.private_CheckHitInBorder(X, Y, CurPage); if (true === oHitInfo.RowSelection) { return this.DrawingDocument.SetCursorType(AscCommon.Cursors.SelectTableRow, new CMouseMoveData()); } else if (true === oHitInfo.ColumnSelection) { return this.DrawingDocument.SetCursorType(AscCommon.Cursors.SelectTableColumn, new CMouseMoveData()); } else if (true === oHitInfo.CellSelection) { return this.DrawingDocument.SetCursorType(AscCommon.Cursors.SelectTableCell, new CMouseMoveData()); } else if (-1 !== oHitInfo.Border) { var Transform = this.Get_ParentTextTransform(); if (null !== Transform) { var dX = Math.abs(Transform.TransformPointX(0, 0) - Transform.TransformPointX(0, 1)); var dY = Math.abs(Transform.TransformPointY(0, 0) - Transform.TransformPointY(0, 1)); if (Math.abs(dY) > Math.abs(dX)) { switch (oHitInfo.Border) { case 0: case 2: return this.DrawingDocument.SetCursorType("row-resize", new CMouseMoveData()); case 1: case 3: return this.DrawingDocument.SetCursorType("col-resize", new CMouseMoveData()); } } else { switch (oHitInfo.Border) { case 0: case 2: return this.DrawingDocument.SetCursorType("col-resize", new CMouseMoveData()); case 1: case 3: return this.DrawingDocument.SetCursorType("row-resize", new CMouseMoveData()); } } } else { switch (oHitInfo.Border) { case 0: case 2: return this.DrawingDocument.SetCursorType("row-resize", new CMouseMoveData()); case 1: case 3: return this.DrawingDocument.SetCursorType("col-resize", new CMouseMoveData()); } } } } var oCellPos = this.private_GetCellByXY(X, Y, CurPage); var oCell = this.GetRow(oCellPos.Row).GetCell(oCellPos.Cell); oCell.Content_UpdateCursorType(X, Y, CurPage - oCell.Content.GetRelativeStartPage()); var oLogicDocument = this.GetLogicDocument(); if (oLogicDocument && oLogicDocument.GetApi && oLogicDocument.IsDocumentEditor() && !oLogicDocument.IsSimpleMarkupInReview() && this.IsCellSelection()) { var oTrackManager = oLogicDocument.GetTrackRevisionsManager(); var oCurChange = oTrackManager.GetCurrentChange(); if (oCurChange && this === oTrackManager.GetCurrentChangeElement()) { var arrSelection = this.GetSelectionArray(); for (var nIndex = 0, nCount = arrSelection.length; nIndex < nCount; ++nIndex) { if (arrSelection[nIndex].Cell === oCellPos.Cell && arrSelection[nIndex].Row === oCellPos.Row) { var oMMData = new AscCommon.CMouseMoveData(); var oCoords = this.DrawingDocument.ConvertCoordsToCursorWR(X, Y, this.GetAbsolutePage(CurPage), this.Get_ParentTextTransform()); oMMData.X_abs = oCoords.X; oMMData.Y_abs = oCoords.Y; oMMData.Type = Asc.c_oAscMouseMoveDataTypes.Review; oMMData.ReviewChange = oCurChange; oLogicDocument.GetApi().sync_MouseMoveCallback(oMMData); break; } } } } }; CTable.prototype.StartTrackTable = function() { var CurPage = 0; while (CurPage < this.Pages.length) { if (true != this.IsEmptyPage(CurPage)) break; CurPage++; } this.private_StartTrackTable(CurPage); }; CTable.prototype.CollectDocumentStatistics = function(Stats) { for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Row = this.Content[CurRow]; var CellsCount = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { Row.Get_Cell(CurCell).Content.CollectDocumentStatistics(Stats); } } }; CTable.prototype.Document_CreateFontMap = function(FontMap) { for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Row = this.Content[CurRow]; var CellsCount = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { Row.Get_Cell(CurCell).Content_Document_CreateFontMap(FontMap); } } }; CTable.prototype.Document_CreateFontCharMap = function(FontCharMap) { for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Row = this.Content[CurRow]; var CellsCount = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { Row.Get_Cell(CurCell).Content.Document_CreateFontCharMap(0x00B7); } } }; CTable.prototype.Document_Get_AllFontNames = function(AllFonts) { for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Row = this.Content[CurRow]; var CellsCount = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { Row.Get_Cell(CurCell).Content.Document_Get_AllFontNames(AllFonts); } } }; CTable.prototype.Document_UpdateInterfaceState = function() { if (!this.IsCellSelection()) { this.CurCell.Content.Document_UpdateInterfaceState(); } else { var oParaPr = this.GetCalculatedParaPr(); if (oParaPr) { oParaPr.CanAddTable = false; editor.UpdateParagraphProp(oParaPr); } var oTextPr = this.GetCalculatedTextPr(); if (oTextPr) { var theme = this.Get_Theme(); if (theme && theme.themeElements && theme.themeElements.fontScheme) oTextPr.ReplaceThemeFonts(theme.themeElements.fontScheme); editor.UpdateTextPr(oTextPr); } } }; CTable.prototype.CollectSelectedReviewChanges = function(oTrackManager) { var oLogicDocument = this.GetLogicDocument(); if (!oLogicDocument || this.bPresentation && !oLogicDocument.GetTrackRevisionsManager) return; var arrSelection = this.GetSelectionArray(false); if (!arrSelection.length) return; var nFirstRow = arrSelection[0].Row; if (!this.RowsInfo[nFirstRow] || !this.RowsInfo[nFirstRow].Y[this.RowsInfo[nFirstRow].StartPage]) return; var nCurPage = this.RowsInfo[nFirstRow].StartPage; var nPageAbs = this.GetAbsolutePage(nCurPage); var dY = this.RowsInfo[nFirstRow].Y[nCurPage]; var dX = oLogicDocument.Get_PageLimits(nPageAbs).XLimit; var arrChanges = oTrackManager.GetElementChanges(this.GetId()); var isCellSelection = this.IsCellSelection(); var isSelection = this.IsSelectionUse(); for (var nChangeIndex = 0, nChangesCount = arrChanges.length; nChangeIndex < nChangesCount; ++nChangeIndex) { var oChange = arrChanges[nChangeIndex]; var isAddChange = false; if (oChange.IsTableRowChange() && (!isSelection || isCellSelection)) { for (var nSelectionPos = 0, nSelectionLength = arrSelection.length; nSelectionPos < nSelectionLength; ++nSelectionPos) { var nCurRow = arrSelection[nSelectionPos].Row; if (nCurRow >= oChange.GetStartPos() && nCurRow <= oChange.GetEndPos()) { isAddChange = true; break; } } } else if (oChange.IsTablePrChange() && (!isSelection || this.IsSelectedAll())) { isAddChange = true; } if (isAddChange) { oChange.SetInternalPos(dX, dY, nPageAbs); oTrackManager.AddSelectedChange(oChange); } } for (var nPos = 0, nCount = arrSelection.length; nPos < nCount; ++nPos) { var oCell = this.GetRow(arrSelection[nPos].Row).GetCell(arrSelection[nPos].Cell); oCell.GetContent().CollectSelectedReviewChanges(oTrackManager); } }; CTable.prototype.Document_UpdateRulersState = function(CurPage) { if (CurPage < 0 || CurPage >= this.Pages.length) CurPage = 0; if (true == this.Selection.Use && table_Selection_Cell == this.Selection.Type) { this.private_UpdateTableMarkup(this.Selection.EndPos.Pos.Row, this.Selection.EndPos.Pos.Cell, CurPage); } else { this.private_UpdateTableMarkup(this.CurCell.Row.Index, this.CurCell.Index, CurPage); this.CurCell.Content.Document_UpdateRulersState(CurPage - this.CurCell.Content.GetRelativeStartPage()); } }; CTable.prototype.Document_SetThisElementCurrent = function(bUpdateStates) { this.Parent.Update_ContentIndexing(); this.Parent.Set_CurrentElement(this.Index, bUpdateStates); }; CTable.prototype.Can_CopyCut = function() { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) return true; else return this.CurCell.Content.Can_CopyCut(); }; CTable.prototype.Set_Inline = function(Value) { AscCommon.History.Add(new CChangesTableInline(this, this.Inline, Value)); this.Inline = Value; }; CTable.prototype.Is_Inline = function() { if (this.Parent && true === this.Parent.Is_DrawingShape()) return true; return this.Inline; }; CTable.prototype.IsInline = function() { return this.Is_Inline(); }; CTable.prototype.SetInline = function(isInline) { return this.Set_Inline(isInline); }; /** * Берем настройки рамки для всей таблицы * @returns {?CFramePr} */ CTable.prototype.GetFramePr = function() { // Word разные строки может записывать в разные ракми, для этого нужно сильно менять логику пересчета, поэтому мы // пока будем основываться по последней строке var nRowsCount = this.GetRowsCount(); if (nRowsCount <= 0) return null; var oRow = this.GetRow(nRowsCount - 1); if (oRow.GetCellsCount() <= 0) return null; var oCell = oRow.GetCell(0); return oCell.GetContent().GetFirstParagraph().GetFramePr(); }; CTable.prototype.SetCalculatedFrame = function(oFrame) { for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { oRow.GetCell(nCurCell).GetContent().SetCalculatedFrame(oFrame); } } }; /** * Функция, которую нужно вызвать перед удалением данного элемента */ CTable.prototype.PreDelete = function() { if (this.isPreventedPreDelete()) return; this.DrawingDocument.EndTrackTable(this, false); var RowsCount = this.Content.length; for (var CurRow = 0; CurRow < RowsCount; CurRow++) { var Row = this.Content[CurRow]; Row.PreDelete(); } this.RemoveSelection(); }; CTable.prototype.RemoveInnerTable = function() { this.CurCell.Content.RemoveTable(); }; CTable.prototype.SelectTable = function(Type) { if (true === this.IsInnerTable()) { this.CurCell.Content.SelectTable(Type); if (true === this.CurCell.Content.IsSelectionUse()) { this.Selection.Use = true; this.Selection.Start = false; this.Selection.Type = table_Selection_Text; this.Selection.Type2 = table_Selection_Common; this.Selection.Data2 = null; this.private_SetSelectionData(null); } return; } var NewSelectionData = []; switch (Type) { case c_oAscTableSelectionType.Table : { for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Row = this.Content[CurRow]; var Cells_Count = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < Cells_Count; CurCell++) { var Cell = Row.Get_Cell(CurCell); var Vmerge = Cell.GetVMerge(); if (vmerge_Continue === Vmerge) continue; NewSelectionData.push({Row : CurRow, Cell : CurCell}); } } break; } case c_oAscTableSelectionType.Row : { var Rows_to_select = []; if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { var Row_prev = -1; for (var Index = 0; Index < this.Selection.Data.length; Index++) { var Pos = this.Selection.Data[Index]; if (-1 === Row_prev || Row_prev != Pos.Row) { Rows_to_select.push(Pos.Row); Row_prev = Pos.Row; } } } else { Rows_to_select.push(this.CurCell.Row.Index); } for (var Index = 0; Index < Rows_to_select.length; Index++) { var Row = this.Content[Rows_to_select[Index]]; var Cells_Count = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < Cells_Count; CurCell++) { var Cell = Row.Get_Cell(CurCell); var Vmerge = Cell.GetVMerge(); if (vmerge_Continue === Vmerge) continue; NewSelectionData.push({Cell : CurCell, Row : Rows_to_select[Index]}); } } break; } case c_oAscTableSelectionType.Column: { var nGridStart = -1; var nGridEnd = -1; if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type && this.Selection.Data.length > 0) { var oStartPos = this.Selection.Data[0]; var oEndPos = this.Selection.Data[this.Selection.Data.length - 1]; var oStartRow = this.GetRow(oStartPos.Row); var oEndRow = this.GetRow(oEndPos.Row) nGridStart = oStartRow.GetCellInfo(oStartPos.Cell).StartGridCol; nGridEnd = oEndRow.GetCellInfo(oEndPos.Cell).StartGridCol + oEndRow.GetCell(oEndPos.Cell).GetGridSpan() - 1; } else { nGridStart = this.CurCell.GetRow().GetCellInfo(this.CurCell.GetIndex()).StartGridCol; nGridEnd = nGridStart + this.CurCell.GetGridSpan() - 1; } this.private_GetColumnByGridRange(nGridStart, nGridEnd, NewSelectionData); break; } case c_oAscTableSelectionType.Cell : default : { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) NewSelectionData = this.Selection.Data; else NewSelectionData.push({Row : this.CurCell.Row.Index, Cell : this.CurCell.Index}); break; } } this.Selection.Use = true; this.Selection.Start = false; this.Selection.Type = table_Selection_Cell; this.Selection.Type2 = table_Selection_Common; this.Selection.Data2 = null; this.private_SetSelectionData(NewSelectionData); this.Selection.StartPos.Pos = {Row : NewSelectionData[0].Row, Cell : NewSelectionData[0].Cell}; this.Selection.EndPos.Pos = { Row : NewSelectionData[NewSelectionData.length - 1].Row, Cell : NewSelectionData[NewSelectionData.length - 1].Cell }; }; CTable.prototype.CanSplitTableCells = function() { if (true === this.IsInnerTable()) return this.CurCell.Content.CanSplitTableCells(); // Разделение ячейки работает, только если выделена ровно одна ячейка. if (!( false === this.Selection.Use || ( true === this.Selection.Use && ( table_Selection_Text === this.Selection.Type || ( table_Selection_Cell === this.Selection.Type && 1 === this.Selection.Data.length ) ) ) )) return false; return true; }; CTable.prototype.CanMergeTableCells = function() { if (true === this.IsInnerTable()) return this.CurCell.Content.CanMergeTableCells(); if (true != this.Selection.Use || table_Selection_Cell != this.Selection.Type || this.Selection.Data.length <= 1) return false; return this.Internal_CheckMerge().bCanMerge; }; /** * Выставляем селект по заданным строкам таблицы * @param nStartRow {number} * @param nEndRow {number} */ CTable.prototype.SelectRows = function(nStartRow, nEndRow) { var nRowsCount = this.GetRowsCount(); if (nRowsCount <= 0) return; nStartRow = Math.max(0, Math.min(nStartRow, nRowsCount - 1)); nEndRow = Math.max(0, Math.min(nEndRow, nRowsCount - 1), nStartRow); var arrSelectionData = []; for (var nCurRow = nStartRow; nCurRow <= nEndRow; ++nCurRow) { for (var nCurCell = 0, nCellsCount = this.GetRow(nCurRow).GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { arrSelectionData.push({ Cell : nCurCell, Row : nCurRow }); } } this.Selection.Use = true; this.Selection.Start = false; this.Selection.Type = table_Selection_Cell; this.Selection.Type2 = table_Selection_Common; this.Selection.Data2 = null; this.private_SetSelectionData(arrSelectionData); this.Selection.StartPos.Pos = { Row : arrSelectionData[0].Row, Cell : arrSelectionData[0].Cell }; this.Selection.EndPos.Pos = { Row : arrSelectionData[arrSelectionData.length - 1].Row, Cell : arrSelectionData[arrSelectionData.length - 1].Cell }; }; CTable.prototype.GetCurCell = function() { return this.CurCell; }; //---------------------------------------------------------------------------------------------------------------------- // Undo/Redo функции //---------------------------------------------------------------------------------------------------------------------- CTable.prototype.GetSelectionState = function() { var TableState = {}; TableState.Selection = { Start : this.Selection.Start, Use : this.Selection.Use, StartPos : { Pos : {Row : this.Selection.StartPos.Pos.Row, Cell : this.Selection.StartPos.Pos.Cell}, X : this.Selection.StartPos.X, Y : this.Selection.StartPos.Y, PageIndex : this.Selection.StartPos.PageIndex, MouseEvent : { // TODO : Если в MouseEvent будет использоваться что-то кроме ClickCount, Type и CtrlKey, добавить // здесь ClickCount : this.Selection.StartPos.MouseEvent.ClickCount, Type : this.Selection.StartPos.MouseEvent.Type, CtrlKey : this.Selection.StartPos.MouseEvent.CtrlKey } }, EndPos : { Pos : {Row : this.Selection.EndPos.Pos.Row, Cell : this.Selection.EndPos.Pos.Cell}, X : this.Selection.EndPos.X, Y : this.Selection.EndPos.Y, PageIndex : this.Selection.EndPos.PageIndex, MouseEvent : { // TODO : Если в MouseEvent будет использоваться что-то кроме ClickCount, Type и CtrlKey, добавить // здесь ClickCount : this.Selection.EndPos.MouseEvent.ClickCount, Type : this.Selection.EndPos.MouseEvent.Type, CtrlKey : this.Selection.EndPos.MouseEvent.CtrlKey } }, Type : this.Selection.Type, Data : null, Type2 : table_Selection_Common, Data2 : null, CurRow : this.Selection.CurRow }; TableState.Selection.Data = []; if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { for (var Index = 0; Index < this.Selection.Data.length; Index++) TableState.Selection.Data[Index] = { Row : this.Selection.Data[Index].Row, Cell : this.Selection.Data[Index].Cell }; } TableState.CurCell = {Row : this.CurCell.Row.Index, Cell : this.CurCell.Index}; var State = this.CurCell.Content.GetSelectionState(); State.push(TableState); return State; }; CTable.prototype.SetSelectionState = function(State, StateIndex) { if (State.length <= 0) return; var TableState = State[StateIndex]; this.Selection = { Start : TableState.Selection.Start, Use : TableState.Selection.Use, StartPos : { Pos : { Row : TableState.Selection.StartPos.Pos.Row, Cell : TableState.Selection.StartPos.Pos.Cell }, X : TableState.Selection.StartPos.X, Y : TableState.Selection.StartPos.Y, PageIndex : TableState.Selection.StartPos.PageIndex, MouseEvent : { // TODO : Если в MouseEvent будет использоваться что-то кроме ClickCount, Type и CtrlKey, добавить // здесь ClickCount : TableState.Selection.StartPos.MouseEvent.ClickCount, Type : TableState.Selection.StartPos.MouseEvent.Type, CtrlKey : TableState.Selection.StartPos.MouseEvent.CtrlKey } }, EndPos : { Pos : {Row : TableState.Selection.EndPos.Pos.Row, Cell : TableState.Selection.EndPos.Pos.Cell}, X : TableState.Selection.EndPos.X, Y : TableState.Selection.EndPos.Y, PageIndex : TableState.Selection.EndPos.PageIndex, MouseEvent : { // TODO : Если в MouseEvent будет использоваться что-то кроме ClickCount, Type и CtrlKey, добавить // здесь ClickCount : TableState.Selection.EndPos.MouseEvent.ClickCount, Type : TableState.Selection.EndPos.MouseEvent.Type, CtrlKey : TableState.Selection.EndPos.MouseEvent.CtrlKey } }, Type : TableState.Selection.Type, Data : null, Type2 : table_Selection_Common, Data2 : null, CurRow : TableState.Selection.CurRow }; var arrSelectionData = []; if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { for (var Index = 0; Index < TableState.Selection.Data.length; Index++) arrSelectionData[Index] = { Row : TableState.Selection.Data[Index].Row, Cell : TableState.Selection.Data[Index].Cell }; } this.private_SetSelectionData(arrSelectionData); this.CurCell = this.Content[TableState.CurCell.Row].Get_Cell(TableState.CurCell.Cell); this.CurCell.Content.SetSelectionState(State, StateIndex - 1); }; CTable.prototype.Get_ParentObject_or_DocumentPos = function() { return this.Parent.Get_ParentObject_or_DocumentPos(this.Index); }; CTable.prototype.Refresh_RecalcData = function(Data) { var Type = Data.Type; var bNeedRecalc = false; var nRowIndex = 0; switch (Type) { case AscDFH.historyitem_Table_TableShd: { break; } case AscDFH.historyitem_Table_TableW: case AscDFH.historyitem_Table_TableLayout: case AscDFH.historyitem_Table_TableCellMar: case AscDFH.historyitem_Table_TableAlign: case AscDFH.historyitem_Table_TableInd: case AscDFH.historyitem_Table_TableBorder_Left: case AscDFH.historyitem_Table_TableBorder_Right: case AscDFH.historyitem_Table_TableBorder_Top: case AscDFH.historyitem_Table_TableBorder_Bottom: case AscDFH.historyitem_Table_TableBorder_InsideH: case AscDFH.historyitem_Table_TableBorder_InsideV: case AscDFH.historyitem_Table_Inline: case AscDFH.historyitem_Table_AllowOverlap: case AscDFH.historyitem_Table_PositionH: case AscDFH.historyitem_Table_PositionV: case AscDFH.historyitem_Table_Distance: case AscDFH.historyitem_Table_TableStyleColBandSize: case AscDFH.historyitem_Table_TableStyleRowBandSize: case AscDFH.historyitem_Table_Pr: { bNeedRecalc = true; break; } case AscDFH.historyitem_Table_AddRow: case AscDFH.historyitem_Table_RemoveRow: { bNeedRecalc = true; nRowIndex = Data.Pos; break; } case AscDFH.historyitem_Table_TableGrid: { bNeedRecalc = true; break; } case AscDFH.historyitem_Table_TableStyle: case AscDFH.historyitem_Table_TableLook: { var Count = this.Content.length; for (var CurRow = 0; CurRow < Count; CurRow++) { var Row = this.Content[CurRow]; var Cells_Count = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < Cells_Count; CurCell++) { var Cell = Row.Get_Cell(CurCell); Cell.Recalc_CompiledPr(); } Row.Recalc_CompiledPr(); } this.Recalc_CompiledPr(); bNeedRecalc = true; break; } } this.RecalcInfo.Recalc_AllCells(); this.RecalcInfo.RecalcBorders(); if (true === bNeedRecalc) { AscCommon.History.Add_RecalcTableGrid(this.Get_Id()); this.Refresh_RecalcData2(nRowIndex, 0); } }; CTable.prototype.Refresh_RecalcData2 = function(nRowIndex, nCurPage) { // Если Index < 0, значит данный элемент еще не был добавлен в родительский класс if (this.Index >= 0) { if (Math.min(nRowIndex, this.RowsInfo.length - 1) < 0) this.Parent.Refresh_RecalcData2(this.Index, this.GetRelativePage(0)); else this.Parent.Refresh_RecalcData2(this.Index, this.GetRelativePage(nCurPage)); } }; //---------------------------------------------------------------------------------------------------------------------- // Функции для работы с совместным редактирования //---------------------------------------------------------------------------------------------------------------------- CTable.prototype.Write_ToBinary2 = function(Writer) { Writer.WriteLong(AscDFH.historyitem_type_Table); // Long : type_Table // String : Id самой таблицы // String : Id стиля (если стока пустая, то null) // Bool : Inline // Long : количество элементов в TableGrid // Array of doubles : массив TableGrid // Double : X_origin // Double : X // Double : Y // Double : XLimit // Double : YLimit // Variable : свойства таблицы (TablePr) // Long : количество строк // Array of Strings : массив Id строк Writer.WriteLong(type_Table); Writer.WriteString2(this.Id); Writer.WriteString2(null === this.TableStyle ? "" : this.TableStyle); Writer.WriteBool(this.Inline); var GridCount = this.TableGrid.length; Writer.WriteLong(GridCount); for (var Index = 0; Index < GridCount; Index++) Writer.WriteDouble(this.TableGrid[Index]); Writer.WriteDouble(this.X_origin); Writer.WriteDouble(this.X); Writer.WriteDouble(this.Y); Writer.WriteDouble(this.XLimit); Writer.WriteDouble(this.YLimit); this.Pr.Write_ToBinary(Writer); var RowsCount = this.Content.length; Writer.WriteLong(RowsCount); for (var Index = 0; Index < RowsCount; Index++) Writer.WriteString2(this.Content[Index].Get_Id()); Writer.WriteBool(this.bPresentation); }; CTable.prototype.Read_FromBinary2 = function(Reader) { // Long : type_Table // String : Id самой таблицы // String : Id стиля (если стока пустая, то null) // Bool : Inline // Long : количество элементов в TableGrid // Array of doubles : массив TableGrid // Double : X_origin // Double : X // Double : Y // Double : XLimit // Double : YLimit // Variable : свойства таблицы (TablePr) // Long : количество строк // Array of Strings : массив Id строк this.Prev = null; this.Next = null; Reader.GetLong(); this.Id = Reader.GetString2(); var TableStyleId = Reader.GetString2(); this.TableStyle = ( TableStyleId === "" ? null : TableStyleId ); this.Inline = Reader.GetBool(); var GridCount = Reader.GetLong(); this.TableGrid = []; for (var Index = 0; Index < GridCount; Index++) this.TableGrid.push(Reader.GetDouble()); this.X_origin = Reader.GetDouble(); this.X = Reader.GetDouble(); this.Y = Reader.GetDouble(); this.XLimit = Reader.GetDouble(); this.YLimit = Reader.GetDouble(); this.Pr = new CTablePr(); this.Pr.Read_FromBinary(Reader); this.Recalc_CompiledPr(); var Count = Reader.GetLong(); this.Content = []; for (var Index = 0; Index < Count; Index++) { var Row = g_oTableId.Get_ById(Reader.GetString2()); this.Content.push(Row); } this.bPresentation = Reader.GetBool(); this.Internal_ReIndexing(); var DrawingDocument = editor.WordControl.m_oDrawingDocument; if (undefined !== DrawingDocument && null !== DrawingDocument) { this.DrawingDocument = DrawingDocument; this.LogicDocument = this.DrawingDocument.m_oLogicDocument; } if (this.GetRowsCount() > 0 && this.GetRow(0).GetCellsCount() > 0) this.CurCell = this.GetRow(0).GetCell(0); else this.CurCell = null; }; CTable.prototype.Get_SelectionState2 = function() { var TableState = {}; TableState.Id = this.Get_Id(); TableState.CellId = ( null !== this.CurCell ? this.CurCell.Get_Id() : null ); TableState.Data = ( null !== this.CurCell ? this.CurCell.Content.Get_SelectionState2() : null ); return TableState; }; CTable.prototype.Set_SelectionState2 = function(TableState) { var CellId = TableState.CellId; var CurCell = null; var Pos = {Cell : 0, Row : 0}; var RowsCount = this.Content.length; for (var RowIndex = 0; RowIndex < RowsCount; RowIndex++) { var Row = this.Content[RowIndex]; var CellsCount = Row.Get_CellsCount(); for (var CellIndex = 0; CellIndex < CellsCount; CellIndex++) { var Cell = Row.Get_Cell(CellIndex); if (Cell.Get_Id() === CellId) { CurCell = Cell; Pos.Cell = CellIndex; Pos.Row = RowIndex; break; } } if (null !== CurCell) break; } if (null == CurCell) { this.MoveCursorToStartPos(false); } else { this.CurCell = CurCell; this.Selection.Start = false; this.Selection.Use = false; this.Selection.StartPos.Pos = {Row : Pos.Row, Cell : Pos.Cell}; this.Selection.EndPos.Pos = {Row : Pos.Row, Cell : Pos.Cell}; this.Selection.Type = table_Selection_Common; this.Selection.Type2 = table_Selection_Common; this.Selection.Data2 = null; this.Selection.CurRow = 0; this.private_SetSelectionData(null); this.CurCell.Content.Set_SelectionState2(TableState.Data); } }; //---------------------------------------------------------------------------------------------------------------------- // Функции для работы с гиперссылками //---------------------------------------------------------------------------------------------------------------------- CTable.prototype.AddHyperlink = function(HyperProps) { // Выделения по ячейкам быть не должно return this.CurCell.Content.AddHyperlink(HyperProps); }; CTable.prototype.ModifyHyperlink = function(HyperProps) { if (false === this.Selection.Use || (true === this.Selection.Use && table_Selection_Text === this.Selection.Type)) this.CurCell.Content.ModifyHyperlink(HyperProps); return false; }; CTable.prototype.RemoveHyperlink = function() { if (false === this.Selection.Use || (true === this.Selection.Use && table_Selection_Text === this.Selection.Type)) this.CurCell.Content.RemoveHyperlink(); }; CTable.prototype.CanAddHyperlink = function(bCheckInHyperlink) { if (false === this.Selection.Use || (true === this.Selection.Use && table_Selection_Text === this.Selection.Type)) return this.CurCell.Content.CanAddHyperlink(bCheckInHyperlink); return false; }; CTable.prototype.IsCursorInHyperlink = function(bCheckEnd) { if (false === this.Selection.Use || (true === this.Selection.Use && table_Selection_Text === this.Selection.Type)) return this.CurCell.Content.IsCursorInHyperlink(bCheckEnd); return null; }; //---------------------------------------------------------------------------------------------------------------------- // Функции для работы с комментариями //---------------------------------------------------------------------------------------------------------------------- CTable.prototype.AddComment = function(Comment, bStart, bEnd) { if (true === this.ApplyToAll) { var RowsCount = this.Content.length; var CellsCount = this.Content[RowsCount - 1].Get_CellsCount(); if (true === bStart && true === bEnd && RowsCount <= 1 && CellsCount <= 1) { var Cell_Content = this.Content[0].Get_Cell(0).Content; Cell_Content.SetApplyToAll(true); Cell_Content.AddComment(Comment, true, true); Cell_Content.SetApplyToAll(false); } else { if (true === bStart) { var Cell_Content = this.Content[0].Get_Cell(0).Content; Cell_Content.SetApplyToAll(true); Cell_Content.AddComment(Comment, true, false); Cell_Content.SetApplyToAll(false); } if (true === bEnd) { var Cell_Content = this.Content[RowsCount - 1].Get_Cell(CellsCount - 1).Content; Cell_Content.SetApplyToAll(true); Cell_Content.AddComment(Comment, false, true); Cell_Content.SetApplyToAll(false); } // TODO: Пока нам приходится пересчитывать ячейки после добавления комментариев. Как только // избавимся от этого, то надо будет переделать здесь. var RowsCount = this.Content.length; for (var RowIndex = 0; RowIndex < RowsCount; RowIndex++) { var Row = this.Content[RowIndex]; var CellsCount = Row.Get_CellsCount(); for (var CellIndex = 0; CellIndex < CellsCount; CellIndex++) { var Cell = Row.Get_Cell(CellIndex); this.RecalcInfo.Add_Cell(Cell); } } } } else { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { if (true === bStart && true === bEnd && this.Selection.Data.length <= 1) { var Pos = this.Selection.Data[0]; var Cell_Content = this.Content[Pos.Row].Get_Cell(Pos.Cell).Content; Cell_Content.SetApplyToAll(true); Cell_Content.AddComment(Comment, true, true); Cell_Content.SetApplyToAll(false); } else { var StartPos = null, EndPos = null; if (true === bStart) { StartPos = this.Selection.Data[0]; var Cell_Content = this.Content[StartPos.Row].Get_Cell(StartPos.Cell).Content; Cell_Content.SetApplyToAll(true); Cell_Content.AddComment(Comment, true, false); Cell_Content.SetApplyToAll(false); } if (true === bEnd) { EndPos = this.Selection.Data[this.Selection.Data.length - 1]; var Cell_Content = this.Content[EndPos.Row].Get_Cell(EndPos.Cell).Content; Cell_Content.SetApplyToAll(true); Cell_Content.AddComment(Comment, false, true); Cell_Content.SetApplyToAll(false); } // TODO: Пока нам приходится пересчитывать ячейки после добавления комментариев. Как только // избавимся от этого, то надо будет переделать здесь. var StartRow = 0, EndRow = -1, StartCell = 0, EndCell = -1; if (null !== StartPos && null !== EndPos) { StartRow = StartPos.Row; EndRow = EndPos.Row; StartCell = StartPos.Cell; EndCell = EndPos.Cell; } else if (null !== StartPos) { StartRow = StartPos.Row; StartCell = StartPos.Cell; EndRow = this.Content.length - 1; EndCell = this.Content[EndRow].Get_CellsCount() - 1; } else if (null !== EndPos) { StartRow = 0; StartCell = 0; EndRow = EndPos.Row; EndCell = EndPos.Cell; } for (var RowIndex = StartRow; RowIndex <= EndRow; RowIndex++) { var Row = this.Content[RowIndex]; var _StartCell = ( RowIndex === StartRow ? StartCell : 0 ); var _EndCell = ( RowIndex === EndRow ? EndCell : Row.Get_CellsCount() - 1 ); for (var CellIndex = _StartCell; CellIndex <= _EndCell; CellIndex++) { var Cell = Row.Get_Cell(CellIndex); this.RecalcInfo.Add_Cell(Cell); } } } } else { this.CurCell.Content.AddComment(Comment, bStart, bEnd); } } }; CTable.prototype.CanAddComment = function() { if (true === this.ApplyToAll) { if (this.Content.length > 1 || this.Content[0].Get_CellsCount() > 1) return true; this.Content[0].Get_Cell(0).Content.SetApplyToAll(true); var Result = this.Content[0].Get_Cell(0).Content.CanAddComment(); this.Content[0].Get_Cell(0).Content.SetApplyToAll(false); return Result; } else { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { if (this.Selection.Data.length > 1) { return true; } else { var oPos = this.Selection.Data[0]; var oCell = this.GetRow(oPos.Row).GetCell(oPos.Cell); var oCellContent = oCell.GetContent(); oCellContent.SetApplyToAll(true); var isCanAdd = oCellContent.CanAddComment(); oCellContent.SetApplyToAll(false); return isCanAdd; } } else { return this.CurCell.Content.CanAddComment(); } } }; CTable.prototype.Can_IncreaseParagraphLevel = function(bIncrease) { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { if (this.Selection.Data.length > 0) { var Data = this.Selection.Data; for (var i = 0; i < Data.length; ++i) { var Pos = Data[i]; var Cell_Content = this.Content[Pos.Row].Get_Cell(Pos.Cell).Content; if (Cell_Content) { Cell_Content.SetApplyToAll(true); var bCan = Cell_Content.Can_IncreaseParagraphLevel(bIncrease); Cell_Content.SetApplyToAll(false); if (!bCan) { return false; } } } return true; } else { return false; } } else { this.CurCell.Content.Can_IncreaseParagraphLevel(bIncrease); } }; CTable.prototype.GetSelectionBounds = function(isForceCellSelection) { var isUseSelection = this.IsCellSelection(); var arrCells = (isUseSelection ? this.GetSelectionArray() : (isForceCellSelection ? [this.CurCell] : null)); if (arrCells) { var arrCells = this.GetSelectionArray(); var StartPos = arrCells[0]; var EndPos = arrCells[arrCells.length - 1]; var Row = this.Content[StartPos.Row]; var Cell = Row.Get_Cell(StartPos.Cell); var X0 = Cell.Metrics.X_cell_start; var X1 = Cell.Metrics.X_cell_end; if (!this.RowsInfo[StartPos.Row] || !this.RowsInfo[EndPos.Row] || !this.Pages[this.RowsInfo[StartPos.Row].StartPage]) { return { Start : {X : 0, Y : 0, W : 0, H : 0, Page : 0}, End : {X : 0, Y : 0, W : 0, H : 0, Page : 0}, Direction : 1 }; } var CurPage = this.RowsInfo[StartPos.Row].StartPage; var Y = this.RowsInfo[StartPos.Row].Y[CurPage]; var H = this.RowsInfo[StartPos.Row].H[CurPage]; var TableX = this.Pages[CurPage].X + this.RowsInfo[StartPos.Row].X0; var BeginRect = {X : TableX + X0, Y : Y, W : X1 - X0, H : H, Page : CurPage + this.GetAbsoluteStartPage()}; Row = this.Content[EndPos.Row]; Cell = Row.Get_Cell(EndPos.Cell); X0 = Cell.Metrics.X_cell_start; X1 = Cell.Metrics.X_cell_end; CurPage = this.RowsInfo[EndPos.Row].StartPage + this.RowsInfo[EndPos.Row].Pages - 1; Y = this.RowsInfo[EndPos.Row].Y[CurPage]; H = this.RowsInfo[EndPos.Row].H[CurPage]; var Direction = 1; if (this.Selection.StartPos.Pos.Row < this.Selection.EndPos.Pos.Row || (this.Selection.StartPos.Pos.Row === this.Selection.EndPos.Pos.Row && this.Selection.StartPos.Pos.Cell <= this.Selection.EndPos.Pos.Cell)) Direction = 1; else Direction = -1; var EndRect = {X : TableX + X0, Y : Y, W : X1 - X0, H : H, Page : CurPage + this.GetAbsoluteStartPage()}; return {Start : BeginRect, End : EndRect, Direction : Direction}; } else { return this.CurCell.Content.GetSelectionBounds(); } }; CTable.prototype.GetSelectionAnchorPos = function() { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); var Pos = Cells_array[0]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var X0 = Cell.Metrics.X_cell_start; var X1 = Cell.Metrics.X_cell_end; var Y = this.RowsInfo[Pos.Row].Y[this.RowsInfo[Pos.Row].StartPage]; var Page = this.RowsInfo[Pos.Row].StartPage + this.GetAbsoluteStartPage(); return {X0 : X0, X1 : X1, Y : Y, Page : Page}; } else { return this.CurCell.Content.GetSelectionAnchorPos(); } }; //---------------------------------------------------------------------------------------------------------------------- // Работаем с текущей позицией и селектом таблицы //---------------------------------------------------------------------------------------------------------------------- CTable.prototype.MoveCursorToXY = function(X, Y, bLine, bDontChangeRealPos, CurPage) { var oPos = this.private_GetCellByXY(X, Y, CurPage); var oRow = this.GetRow(oPos.Row); var oCell = oRow.GetCell(oPos.Cell); this.Selection.Type = table_Selection_Text; this.Selection.Type2 = table_Selection_Common; this.Selection.StartPos.Pos = {Row : oPos.Row, Cell : oPos.Cell}; this.Selection.EndPos.Pos = {Row : oPos.Row, Cell : oPos.Cell}; this.Selection.CurRow = oPos.Row; // Устанавливаем найденную ячейку текущей и перемещаемся в контент ячейки по координатам X,Y this.CurCell = oCell; this.CurCell.Content_MoveCursorToXY(X, Y, false, true, CurPage - this.CurCell.Content.GetRelativeStartPage()); }; CTable.prototype.Selection_SetStart = function(X, Y, CurPage, MouseEvent) { if (CurPage < 0 || CurPage >= this.Pages.length) CurPage = 0; var Page = this.Pages[CurPage]; var oHitInfo = this.private_CheckHitInBorder(X, Y, CurPage); var Pos = oHitInfo.Pos; if (oHitInfo.ColumnSelection || oHitInfo.RowSelection || oHitInfo.CellSelection) { this.RemoveSelection(); this.CurCell = this.Content[Pos.Row].Get_Cell(Pos.Cell); this.CurCell.Content_Selection_SetStart(X, Y, CurPage - this.CurCell.Content.GetRelativeStartPage(), MouseEvent); this.Selection.Use = true; this.Selection.Start = true; this.Selection.Type = table_Selection_Cell; this.Selection.Type2 = table_Selection_Cells; this.Selection.Data2 = null; this.Selection.StartPos.Pos = Pos; this.Selection.StartPos.X = X; this.Selection.StartPos.Y = Y; this.Selection.StartPos.PageIndex = CurPage; this.Selection.StartPos.MouseEvent = { // TODO : Если в MouseEvent будет использоваться что-то кроме ClickCount, Type и CtrlKey, добавить // здесь ClickCount : MouseEvent.ClickCount, Type : MouseEvent.Type, CtrlKey : MouseEvent.CtrlKey }; var oEndPos = { Row : Pos.Row, Cell : Pos.Cell }; if (oHitInfo.RowSelection) { oEndPos.Cell = this.GetRow(Pos.Row).GetCellsCount() - 1; this.Selection.Type2 = table_Selection_Rows; } else if (oHitInfo.ColumnSelection) { var oRow = this.GetRow(Pos.Row); var nEndRow = this.GetRowsCount() - 1; var nEndCell = this.private_GetCellIndexByStartGridCol(nEndRow, oRow.GetCellInfo(Pos.Cell).StartGridCol, true); if (-1 !== nEndCell) { oEndPos.Row = nEndRow; oEndPos.Cell = nEndCell; this.Selection.Type2 = table_Selection_Columns; } } this.Selection.EndPos.Pos = oEndPos; this.Selection.EndPos.X = X; this.Selection.EndPos.Y = Y; this.Selection.EndPos.PageIndex = CurPage; this.Selection.EndPos.MouseEvent = { // TODO : Если в MouseEvent будет использоваться что-то кроме ClickCount, Type и CtrlKey, добавить // здесь ClickCount : MouseEvent.ClickCount, Type : MouseEvent.Type, CtrlKey : MouseEvent.CtrlKey }; this.Selection.Type = table_Selection_Cell; this.private_UpdateSelectedCellsArray(); } else if (-1 === oHitInfo.Border) { var bInnerTableBorder = ( null != this.IsTableBorder(X, Y, CurPage) ? true : false ); if (true === bInnerTableBorder) { // Значит двигается граница внутренней таблицы, мы не должны отменять селект var Cell = this.Content[Pos.Row].Get_Cell(Pos.Cell); Cell.Content_Selection_SetStart(X, Y, CurPage - Cell.Content.GetRelativeStartPage(), MouseEvent); this.Selection.Type2 = table_Selection_Border_InnerTable; this.Selection.Data2 = Cell; } else { this.RemoveSelection(); this.CurCell = this.Content[Pos.Row].Get_Cell(Pos.Cell); this.CurCell.Content_Selection_SetStart(X, Y, CurPage - this.CurCell.Content.GetRelativeStartPage(), MouseEvent); this.Selection.Use = true; this.Selection.Start = true; this.Selection.Type = table_Selection_Text; this.Selection.Type2 = table_Selection_Common; this.Selection.Data2 = null; this.Selection.StartPos.Pos = Pos; this.Selection.StartPos.X = X; this.Selection.StartPos.Y = Y; this.Selection.StartPos.PageIndex = CurPage; this.Selection.StartPos.MouseEvent = { // TODO : Если в MouseEvent будет использоваться что-то кроме ClickCount, Type и CtrlKey, добавить // здесь ClickCount : MouseEvent.ClickCount, Type : MouseEvent.Type, CtrlKey : MouseEvent.CtrlKey }; } } else { this.private_UpdateTableMarkup(Pos.Row, Pos.Cell, CurPage); this.Selection.Type2 = table_Selection_Border; this.Selection.Data2 = {}; this.Selection.Data2.PageNum = CurPage; var Row = this.Content[Pos.Row]; var _X = X; var _Y = Y; if (0 === oHitInfo.Border || 2 === oHitInfo.Border) { var PageH = this.LogicDocument.Get_PageLimits(this.GetAbsoluteStartPage()).YLimit; var Y_min = 0; var Y_max = PageH; this.Selection.Data2.bCol = false; var Row_start = this.Pages[CurPage].FirstRow; var Row_end = this.Pages[CurPage].LastRow; if (0 === oHitInfo.Border) this.Selection.Data2.Index = Pos.Row - Row_start; else this.Selection.Data2.Index = oHitInfo.Row - Row_start + 1; if (0 != this.Selection.Data2.Index) { var TempRow = this.Selection.Data2.Index + Row_start - 1; Y_min = this.RowsInfo[TempRow].Y[CurPage]; } // Подправим Y, чтобы первоначально точно по границе проходила линия if (this.Selection.Data2.Index !== Row_end - Row_start + 1) _Y = this.RowsInfo[this.Selection.Data2.Index + Row_start].Y[CurPage]; else _Y = this.RowsInfo[this.Selection.Data2.Index + Row_start - 1].Y[CurPage] + this.RowsInfo[this.Selection.Data2.Index + Row_start - 1].H[CurPage]; this.Selection.Data2.Min = Y_min; this.Selection.Data2.Max = Y_max; this.Selection.Data2.Pos = { Row : Pos.Row, Cell : Pos.Cell }; if (null != this.Selection.Data2.Min) _Y = Math.max(_Y, this.Selection.Data2.Min); if (null != this.Selection.Data2.Max) _Y = Math.min(_Y, this.Selection.Data2.Max); } else { var CellsCount = Row.Get_CellsCount(); var CellSpacing = ( null === Row.Get_CellSpacing() ? 0 : Row.Get_CellSpacing() ); var X_min = null; var X_max = null; this.Selection.Data2.bCol = true; if (3 === oHitInfo.Border) this.Selection.Data2.Index = Pos.Cell; else this.Selection.Data2.Index = Pos.Cell + 1; if (0 != this.Selection.Data2.Index) { var Margins = Row.Get_Cell(this.Selection.Data2.Index - 1).GetMargins(); if (0 != this.Selection.Data2.Index - 1 && this.Selection.Data2.Index != CellsCount) X_min = Page.X + Row.Get_CellInfo(this.Selection.Data2.Index - 1).X_grid_start + Margins.Left.W + Margins.Right.W + CellSpacing; else X_min = Page.X + Row.Get_CellInfo(this.Selection.Data2.Index - 1).X_grid_start + Margins.Left.W + Margins.Right.W + 1.5 * CellSpacing; } if (CellsCount != this.Selection.Data2.Index) { var Margins = Row.Get_Cell(this.Selection.Data2.Index).GetMargins(); if (CellsCount - 1 != this.Selection.Data2.Index) X_max = Page.X + Row.Get_CellInfo(this.Selection.Data2.Index).X_grid_end - (Margins.Left.W + Margins.Right.W + CellSpacing); else X_max = Page.X + Row.Get_CellInfo(this.Selection.Data2.Index).X_grid_end - (Margins.Left.W + Margins.Right.W + 1.5 * CellSpacing); } // Подправим значение по X, чтобы первоначально точно по границе проходила линия if (CellsCount != this.Selection.Data2.Index) _X = Page.X + Row.Get_CellInfo(this.Selection.Data2.Index).X_grid_start; else _X = Page.X + Row.Get_CellInfo(this.Selection.Data2.Index - 1).X_grid_end; this.Selection.Data2.Min = X_min; this.Selection.Data2.Max = X_max; this.Selection.Data2.Pos = { Row : Pos.Row, Cell : Pos.Cell }; if (null != this.Selection.Data2.Min) _X = Math.max(_X, this.Selection.Data2.Min); if (null != this.Selection.Data2.Max) _X = Math.min(_X, this.Selection.Data2.Max); } this.Selection.Data2.X = _X; this.Selection.Data2.Y = _Y; this.Selection.Data2.StartCX = _X; // Начальная позиция скорректированная относительно положения границы this.Selection.Data2.StartCY = _Y; this.Selection.Data2.StartX = X; // Начальная позиция нажатия мыши (без корректировки) this.Selection.Data2.StartY = Y; this.Selection.Data2.Start = true; this.DrawingDocument.LockCursorTypeCur(); } }; CTable.prototype.Selection_SetEnd = function(X, Y, CurPage, MouseEvent) { let LogicDocument = this.GetLogicDocument(); var TablePr = this.Get_CompiledPr(false).TablePr; if (CurPage < 0 || CurPage >= this.Pages.length) CurPage = 0; var Page = this.Pages[CurPage]; if (this.Selection.Type2 === table_Selection_Border) { if (!LogicDocument || true !== LogicDocument.CanEdit() || this.Selection.Data2.PageNum != CurPage) return; var _X = X; var _Y = Y; // Проверяем, случайное нажатие на границу. (т.е. случайное однократное нажатие или с малым смещением) if (true !== this.Selection.Data2.Start || Math.abs(X - this.Selection.Data2.StartX) > 0.05 || Math.abs(Y - this.Selection.Data2.StartY) > 0.05) { _X = this.DrawingDocument.CorrectRulerPosition(X); _Y = this.DrawingDocument.CorrectRulerPosition(Y); this.Selection.Data2.Start = false; } else { _X = this.Selection.Data2.X; _Y = this.Selection.Data2.Y; } if (true === this.Selection.Data2.bCol) _X = this.private_UpdateTableRulerOnBorderMove(_X); else _Y = this.private_UpdateTableRulerOnBorderMove(_Y); this.Selection.Data2.X = _X; this.Selection.Data2.Y = _Y; if (MouseEvent.Type === AscCommon.g_mouse_event_type_up) { // Обрабатываем случай, когда граница не изменила своего первоначального положения if (Math.abs(_X - this.Selection.Data2.StartCX) < 0.001 && Math.abs(_Y - this.Selection.Data2.StartCY) < 0.001) { this.Selection.Type2 = table_Selection_Common; this.Selection.Data2 = null; return; } if (false === LogicDocument.Document_Is_SelectionLocked(AscCommon.changestype_None, { Type : AscCommon.changestype_2_Element_and_Type, Element : this, CheckType : AscCommon.changestype_Table_Properties })) { LogicDocument.StartAction(AscDFH.historydescription_Document_MoveTableBorder); if (true === this.Selection.Data2.bCol) { // Найдем колонку в TableGrid, с которой мы работаем var Index = this.Selection.Data2.Index; var CurRow = this.Selection.Data2.Pos.Row; var Row = this.Content[CurRow]; var Col = 0; // границ на 1 больше, чем самих ячеек в строке if (Index === this.Markup.Cols.length) Col = Row.Get_CellInfo(Index - 1).StartGridCol + Row.Get_Cell(Index - 1).Get_GridSpan(); else Col = Row.Get_CellInfo(Index).StartGridCol; var Dx = _X - (Page.X + this.TableSumGrid[Col - 1]); // Строим новую секту для таблицы var Rows_info = []; // Если граница, которую мы двигаем не попадает в селект, тогда работает, как будто селекта и нет var bBorderInSelection = false; if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type && this.Selection.Data.length > 0 && !this.bPresentation) { var CellsFlag = []; for (CurRow = 0; CurRow < this.Content.length; CurRow++) { CellsFlag[CurRow] = []; Row = this.Content[CurRow]; var CellsCount = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { CellsFlag[CurRow][CurCell] = 0; } } var CurSelectedCell = this.Selection.Data[0]; var CurSelectedIndex = 0; for (CurRow = 0; CurRow < this.Content.length; CurRow++) { Row = this.Content[CurRow]; var CellsCount = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { if (CurSelectedCell.Cell === CurCell && CurSelectedCell.Row === CurRow) { CellsFlag[CurRow][CurCell] = 1; var StartGridCol = Row.Get_CellInfo(CurCell).StartGridCol; var GridSpan = Row.Get_Cell(CurCell).Get_GridSpan(); var VMergeCount = this.Internal_GetVertMergeCount(CurRow, StartGridCol, GridSpan); if (CurRow === this.Selection.Data2.Pos.Row && Col >= StartGridCol && Col <= StartGridCol + GridSpan) bBorderInSelection = true; for (var TempIndex = 1; TempIndex < VMergeCount; TempIndex++) { var TempCell = this.private_GetCellIndexByStartGridCol(CurRow + TempIndex, StartGridCol); if (-1 != TempCell) { CellsFlag[CurRow + TempIndex][TempCell] = 1; if (CurRow + TempIndex === this.Selection.Data2.Pos.Row && Col >= StartGridCol && Col <= StartGridCol + GridSpan) bBorderInSelection = true; } } if (CurSelectedIndex < this.Selection.Data.length - 1) CurSelectedCell = this.Selection.Data[++CurSelectedIndex]; else CurSelectedCell = {Row : -1, Cell : -1}; } } } } var OldTableInd = TablePr.TableInd; var NewTableInd = TablePr.TableInd; if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type && true === bBorderInSelection && !this.bPresentation) { var BeforeFlag = false; var BeforeSpace2 = null; if (0 === Col) { BeforeSpace2 = _X - Page.X; if (BeforeSpace2 < 0) { Page.X += BeforeSpace2; if (true === this.Is_Inline()) NewTableInd = NewTableInd + BeforeSpace2; else this.Internal_UpdateFlowPosition(Page.X, Page.Y); } } var BeforeSpace = null; if (0 === Index && 0 != Col && _X < Page.X) { BeforeSpace = Page.X - _X; Page.X -= BeforeSpace; if (true === this.Is_Inline()) NewTableInd = NewTableInd - BeforeSpace; else this.Internal_UpdateFlowPosition(Page.X, Page.Y); } for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { Rows_info[nCurRow] = []; oRow = this.GetRow(nCurRow); var oBeforeInfo = oRow.GetBefore(); var WBefore = 0; if (null === BeforeSpace2) { if (oBeforeInfo.Grid > 0 && Col === oBeforeInfo.Grid && 1 === CellsFlag[nCurRow][0]) { WBefore = this.TableSumGrid[oBeforeInfo.Grid - 1] + Dx; } else { if (null != BeforeSpace) WBefore = this.TableSumGrid[oBeforeInfo.Grid - 1] + BeforeSpace; else WBefore = this.TableSumGrid[oBeforeInfo.Grid - 1]; } } else { if (BeforeSpace2 > 0) { if (0 === oBeforeInfo.Grid && 1 === CellsFlag[nCurRow][0]) WBefore = BeforeSpace2; else if (0 != oBeforeInfo.Grid) WBefore = this.TableSumGrid[oBeforeInfo.Grid - 1]; } else { if (0 === oBeforeInfo.Grid && 1 != CellsFlag[nCurRow][0]) WBefore = -BeforeSpace2; else if (0 != oBeforeInfo.Grid) WBefore = -BeforeSpace2 + this.TableSumGrid[oBeforeInfo.Grid - 1]; } } if (WBefore > 0.001) Rows_info[nCurRow].push({W : WBefore, Type : -1, GridSpan : 1}); var TempDx = Dx; var isFindLeft = true, isFindRight = false; for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); var oCellMargins = oCell.GetMargins(); var nCellGridStart = oRow.GetCellInfo(nCurCell).StartGridCol; var nCellGridEnd = nCellGridStart + oCell.GetGridSpan() - 1; var nCellW = 0; if (isFindLeft) { if (nCellGridStart === Col && 1 === CellsFlag[nCurRow][nCurCell]) { isFindLeft = false; isFindRight = false; nCellW = this.TableSumGrid[nCellGridEnd] - this.TableSumGrid[Col - 1] - Dx; } else { if (((nCellGridEnd + 1 < Col && (this.TableSumGrid[Col - 1] - this.TableSumGrid[nCellGridEnd]) < 0.635) || (nCellGridEnd + 1 === Col) || (nCellGridEnd + 1 > Col && (this.TableSumGrid[nCellGridEnd] - this.TableSumGrid[Col - 1]) < 0.635)) && (1 === CellsFlag[nCurRow][nCurCell] || (nCurCell + 1 < nCellsCount && 1 === CellsFlag[nCurRow][nCurCell + 1]))) { isFindLeft = false; nCellW = this.TableSumGrid[Col - 1] - this.TableSumGrid[nCellGridStart - 1] + Dx; } if (isFindLeft) nCellW = this.TableSumGrid[nCellGridEnd] - this.TableSumGrid[nCellGridStart - 1]; var _nCellW = Math.max(1, Math.max(nCellW, oCellMargins.Left.W + oCellMargins.Right.W)); if (!isFindLeft) { TempDx = _nCellW - (this.TableSumGrid[Col - 1] - this.TableSumGrid[nCellGridStart - 1]); isFindRight = true; } } } else if (isFindRight) { isFindRight = false; nCellW = this.TableSumGrid[nCellGridEnd] - this.TableSumGrid[Col - 1] - TempDx; } else { nCellW = this.TableSumGrid[nCellGridEnd] - this.TableSumGrid[nCellGridStart - 1]; } nCellW = Math.max(1, Math.max(nCellW, oCellMargins.Left.W + oCellMargins.Right.W)); Rows_info[nCurRow].push({W : nCellW, Type : 0, GridSpan : 1}); } } // Возможно, что во всех рядах RowsInfo в начале есть запись BeforeGrid var MinBefore = 0; for (CurRow = 0; CurRow < this.Content.length; CurRow++) { if (-1 != Rows_info[CurRow][0].Type) { MinBefore = 0; break; } if (0 === MinBefore || MinBefore > Rows_info[CurRow][0].W) MinBefore = Rows_info[CurRow][0].W; } if (0 != MinBefore) { for (CurRow = 0; CurRow < this.Content.length; CurRow++) { if (Math.abs(MinBefore - Rows_info[CurRow][0].W) < 0.001) Rows_info[CurRow].splice(0, 1); else // if ( MinBefore < Rows_info[CurRow][0].W ) Rows_info[CurRow][0].W -= MinBefore; } Page.X += MinBefore; if (true === this.Is_Inline()) NewTableInd = NewTableInd + MinBefore; else this.Internal_UpdateFlowPosition(Page.X, Page.Y); } } else { var BeforeFlag = false; var BeforeSpace2 = null; if (0 === Col) { BeforeSpace2 = Page.X - _X; if (-BeforeSpace2 > this.TableSumGrid[0]) { BeforeFlag = true; Page.X += this.TableSumGrid[0]; } else Page.X += Dx; if (true === this.Is_Inline()) { if (-BeforeSpace2 > this.TableSumGrid[0]) NewTableInd = NewTableInd + this.TableSumGrid[0]; else NewTableInd = NewTableInd + Dx; } else this.Internal_UpdateFlowPosition(Page.X, Page.Y); } var BeforeSpace = null; if (0 === Index && 0 != Col && _X < Page.X) { BeforeSpace = Page.X - _X; Page.X -= BeforeSpace; if (true === this.Is_Inline()) NewTableInd = NewTableInd - BeforeSpace; else this.Internal_UpdateFlowPosition(Page.X, Page.Y); } for (nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { Rows_info[nCurRow] = []; oRow = this.GetRow(nCurRow); var oBeforeInfo = oRow.GetBefore(); var WBefore = 0; if (oBeforeInfo.Grid > 0 && Col === oBeforeInfo.Grid) { WBefore = this.TableSumGrid[oBeforeInfo.Grid - 1] + Dx; } else { if (null != BeforeSpace) WBefore = this.TableSumGrid[oBeforeInfo.Grid - 1] + BeforeSpace; else WBefore = this.TableSumGrid[oBeforeInfo.Grid - 1]; if (null != BeforeSpace2) { if (oBeforeInfo.Grid > 0) { if (true === BeforeFlag) WBefore = this.TableSumGrid[oBeforeInfo.Grid - 1] - this.TableSumGrid[0]; else WBefore = this.TableSumGrid[oBeforeInfo.Grid - 1] + BeforeSpace2; } else if (0 === oBeforeInfo.Grid && true === BeforeFlag) { WBefore = ( -BeforeSpace2 ) - this.TableSumGrid[0]; } } } if (WBefore > 0.001) Rows_info[nCurRow].push({W : WBefore, Type : -1, GridSpan : 1}); var TempDx = Dx; var isFindLeft = true, isFindRight = false; for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); var oCellMargins = oCell.GetMargins(); var nCellGridStart = oRow.GetCellInfo(nCurCell).StartGridCol; var nCellGridEnd = nCellGridStart + oCell.GetGridSpan() - 1; var nCellW = 0; if (isFindLeft) { if (nCellGridStart === Col) { isFindLeft = false; isFindRight = false; nCellW = this.TableSumGrid[nCellGridEnd] - this.TableSumGrid[Col - 1] - Dx; } else { if ((nCellGridEnd + 1 < Col && (this.TableSumGrid[Col - 1] - this.TableSumGrid[nCellGridEnd]) < 0.635) || (nCellGridEnd + 1 === Col) || (nCellGridEnd + 1 > Col && (this.TableSumGrid[nCellGridEnd] - this.TableSumGrid[Col - 1]) < 0.635)) { isFindLeft = false; nCellW = this.TableSumGrid[Col - 1] - this.TableSumGrid[nCellGridStart - 1] + Dx; } if (isFindLeft) nCellW = this.TableSumGrid[nCellGridEnd] - this.TableSumGrid[nCellGridStart - 1]; var _nCellW = Math.max(1, Math.max(nCellW, oCellMargins.Left.W + oCellMargins.Right.W)); if (!isFindLeft) { TempDx = _nCellW - (this.TableSumGrid[Col - 1] - this.TableSumGrid[nCellGridStart - 1]); isFindRight = true; } } } else if (isFindRight) { isFindRight = false; nCellW = this.TableSumGrid[nCellGridEnd] - this.TableSumGrid[Col - 1] - TempDx; } else { nCellW = this.TableSumGrid[nCellGridEnd] - this.TableSumGrid[nCellGridStart - 1]; } nCellW = Math.max(1, Math.max(nCellW, oCellMargins.Left.W + oCellMargins.Right.W)); Rows_info[nCurRow].push({W : nCellW, Type : 0, GridSpan : 1}); } } } if (Math.abs(NewTableInd - OldTableInd) > 0.001) this.Set_TableInd(NewTableInd); var oTablePr = this.Get_CompiledPr(false).TablePr; if (tbllayout_AutoFit === oTablePr.TableLayout) this.SetTableLayout(tbllayout_Fixed); this.Internal_CreateNewGrid(Rows_info); if (undefined !== oTablePr.TableW && tblwidth_Auto !== oTablePr.TableW.Type) { var nTableW = 0; for (var nCurCol = 0, nColsCount = this.TableGrid.length; nCurCol < nColsCount; ++nCurCol) nTableW += this.TableGrid[nCurCol]; if (tblwidth_Pct === oTablePr.TableW.Type) { var nPctWidth = this.private_RecalculatePercentWidth(); if (nPctWidth < 0.01) this.Set_TableW(tblwidth_Auto, 0); else this.Set_TableW(tblwidth_Pct, nTableW / nPctWidth * 100); } else { this.Set_TableW(tblwidth_Mm, nTableW); } } this.private_RecalculateGrid(); } else { var RowIndex = this.Pages[this.Selection.Data2.PageNum].FirstRow + this.Selection.Data2.Index; if (0 === RowIndex) { if (true === this.Is_Inline()) { // Ничего не делаем } else { var Dy = _Y - this.Markup.Rows[0].Y; Page.Y += Dy; this.Internal_UpdateFlowPosition(Page.X, Page.Y); //var NewH = this.Markup.Rows[0].H + Dy; //this.Content[0].Set_Height( NewH, Asc.linerule_AtLeast ); } } else { if (this.Selection.Data2.PageNum > 0 && 0 === this.Selection.Data2.Index) { // Ничего не делаем } else { var _Y_old = this.Markup.Rows[this.Selection.Data2.Index - 1].Y + this.Markup.Rows[this.Selection.Data2.Index - 1].H; var Dy = _Y - _Y_old; var NewH = this.Markup.Rows[this.Selection.Data2.Index - 1].H + Dy; let row = this.GetRow(RowIndex - 1); let hRule = row.GetHeight().HRule; if (Asc.linerule_Auto === hRule) hRule = Asc.linerule_AtLeast; row.SetHeight(NewH, hRule); } } } LogicDocument.Recalculate(); LogicDocument.FinalizeAction(); } this.Selection.Type2 = table_Selection_Common; this.Selection.Data2 = null; } return; } else if (table_Selection_Border_InnerTable === this.Selection.Type2) { var Cell = this.Selection.Data2; Cell.Content_Selection_SetEnd(X, Y, CurPage - Cell.Content.GetRelativeStartPage(), MouseEvent); if (MouseEvent.Type === AscCommon.g_mouse_event_type_up) { this.Selection.Type2 = table_Selection_Common; this.Selection.Data2 = null; } return; } var oTempPos = this.private_GetCellByXY(X, Y, CurPage); var Pos = { Row : oTempPos.Row, Cell : oTempPos.Cell }; if (table_Selection_Rows === this.Selection.Type2) { Pos.Cell = this.GetRow(Pos.Row).GetCellsCount() - 1; } else if (table_Selection_Columns === this.Selection.Type2) { var oRow = this.GetRow(oTempPos.Row); var nEndRow = this.GetRowsCount() - 1; var nEndCell = this.private_GetCellIndexByStartGridCol(nEndRow, oRow.GetCellInfo(oTempPos.Cell).StartGridCol, true); if (-1 !== nEndCell) { Pos.Row = nEndRow; Pos.Cell = nEndCell; } } this.Content[Pos.Row].Get_Cell(Pos.Cell).Content_SetCurPosXY(X, Y); this.Selection.EndPos.Pos = Pos; this.Selection.EndPos.X = X; this.Selection.EndPos.Y = Y; this.Selection.EndPos.PageIndex = CurPage; this.Selection.EndPos.MouseEvent = MouseEvent; this.Selection.CurRow = Pos.Row; // При селекте внутри ячейки мы селектим содержимое ячейки if (table_Selection_Common === this.Selection.Type2 && (this.Parent.IsSelectedSingleElement() || (LogicDocument && LogicDocument.IsDocumentEditor() && LogicDocument.IsNumberingSelection())) && this.Selection.StartPos.Pos.Row === this.Selection.EndPos.Pos.Row && this.Selection.StartPos.Pos.Cell === this.Selection.EndPos.Pos.Cell) { this.private_SetSelectionData(null); this.CurCell.Content_Selection_SetStart(this.Selection.StartPos.X, this.Selection.StartPos.Y, this.Selection.StartPos.PageIndex - this.CurCell.Content.GetRelativeStartPage(), this.Selection.StartPos.MouseEvent); this.Selection.Type = table_Selection_Text; this.CurCell.Content_Selection_SetEnd(X, Y, CurPage - this.CurCell.Content.GetRelativeStartPage(), MouseEvent); if (AscCommon.g_mouse_event_type_up == MouseEvent.Type) this.Selection.Start = false; if (false === this.CurCell.Content.Selection.Use) { this.Selection.Use = false; this.Selection.Start = false; this.MoveCursorToXY(X, Y, false, false, CurPage); return; } } else { if (AscCommon.g_mouse_event_type_up === MouseEvent.Type) { this.Selection.Start = false; this.CurCell = this.Content[Pos.Row].Get_Cell(Pos.Cell); if (table_Selection_Cells === this.Selection.Type2 && this.Selection.StartPos.Pos.Cell === this.Selection.EndPos.Pos.Cell && this.Selection.StartPos.Pos.Row === this.Selection.EndPos.Pos.Row && MouseEvent.ClickCount > 1 && 0 === MouseEvent.ClickCount % 2) { this.Selection.StartPos.Pos.Cell = 0; this.Selection.EndPos.Pos.Cell = this.GetRow(this.Selection.StartPos.Pos.Row).GetCellsCount() - 1; } } this.Selection.Type = table_Selection_Cell; this.private_UpdateSelectedCellsArray(table_Selection_Rows === this.Selection.Type2 ? true : false); } }; CTable.prototype.Selection_Stop = function() { if (true != this.Selection.Use) return; this.Selection.Start = false; var Cell = this.Content[this.Selection.StartPos.Pos.Row].Get_Cell(this.Selection.StartPos.Pos.Cell); Cell.Content_Selection_Stop(); }; CTable.prototype.DrawSelectionOnPage = function(CurPage, clipInfo) { if (false === this.Selection.Use) return; if (CurPage < 0 || CurPage >= this.Pages.length) return; var Page = this.Pages[CurPage]; var PageAbs = this.GetAbsolutePage(CurPage); switch (this.Selection.Type) { case table_Selection_Cell: { for (var Index = 0; Index < this.Selection.Data.length; ++Index) { var Pos = this.Selection.Data[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var CellInfo = Row.Get_CellInfo(Pos.Cell); var CellMar = Cell.GetMargins(); var X_start = (0 === Pos.Cell ? Page.X + CellInfo.X_content_start : Page.X + CellInfo.X_cell_start); var X_end = Page.X + CellInfo.X_cell_end; var Cell_Pages = Cell.Content_Get_PagesCount(); var Cell_PageRel = CurPage - Cell.Content.GetRelativeStartPage(); if (Cell_PageRel < 0 || Cell_PageRel >= Cell_Pages) continue; var Bounds = Cell.Content_Get_PageBounds(Cell_PageRel); var Y_offset = Cell.Temp.Y_VAlign_offset[Cell_PageRel]; var RowIndex = 0 != Cell_PageRel ? this.Pages[CurPage].FirstRow : Pos.Row; if (true === Cell.IsVerticalText()) { var X_start = Page.X + CellInfo.X_cell_start; var TextDirection = Cell.Get_TextDirection(); var MergeCount = this.private_GetVertMergeCountOnPage(CurPage, RowIndex, CellInfo.StartGridCol, Cell.Get_GridSpan()); if (MergeCount <= 0) continue; var LastRow = Math.min(RowIndex + MergeCount - 1, this.Pages[CurPage].LastRow); var Y_start = this.RowsInfo[RowIndex].Y[CurPage] + this.RowsInfo[RowIndex].TopDy[CurPage] + CellMar.Top.W; var Y_end = this.TableRowsBottom[LastRow][CurPage] - CellMar.Bottom.W; if (TextDirection === textdirection_BTLR) { var SelectionW = Math.min(X_end - X_start - CellMar.Left.W, Bounds.Bottom - Bounds.Top); this.DrawingDocument.AddPageSelection(PageAbs, X_start + CellMar.Left.W + Y_offset, Y_start, SelectionW, Y_end - Y_start); } else if (TextDirection === textdirection_TBRL) { var SelectionW = Math.min(X_end - X_start - CellMar.Right.W, Bounds.Bottom - Bounds.Top); this.DrawingDocument.AddPageSelection(PageAbs, X_end - CellMar.Right.W - Y_offset - SelectionW, Y_start, SelectionW, Y_end - Y_start); } } else { let rectY = this.RowsInfo[RowIndex].Y[CurPage] + this.RowsInfo[RowIndex].TopDy[CurPage] + CellMar.Top.W + Y_offset; let rectH = Bounds.Bottom - Bounds.Top; if (Cell.Temp && Cell.Temp.UseClip && undefined !== Cell.Temp.ClipTop && undefined !== Cell.Temp.ClipBottom) { rectY = Math.max(rectY, Cell.Temp.ClipTop); rectH = Math.min(rectH, Math.max(0, Cell.Temp.ClipBottom - rectY)); } this.DrawingDocument.AddPageSelection(PageAbs, X_start, rectY, X_end - X_start, rectH); } } break; } case table_Selection_Text: { var Cell = this.Content[this.Selection.StartPos.Pos.Row].Get_Cell(this.Selection.StartPos.Pos.Cell); var Cell_PageRel = CurPage - Cell.Content.GetRelativeStartPage(); Cell.Content_DrawSelectionOnPage(Cell_PageRel, clipInfo); break; } } }; CTable.prototype.RemoveSelection = function() { if (false === this.Selection.Use) return; let arrCells = this.GetSelectionArray(true); for (let nIndex = 0, nCount = arrCells.length; nIndex < nCount; ++nIndex) { let oPos = arrCells[nIndex]; let oRow = this.GetRow(oPos.Row); if (!oRow) continue; let oCell = oRow.GetCell(oPos.Cell); if (oCell) oCell.GetContent().RemoveSelection(); } this.CurCell = null; if (this.GetRowsCount() > 0) { let oRow = this.GetRow(this.Selection.EndPos.Pos.Row); if (!oRow) this.CurCell = this.GetRow(0).GetCell(0); else this.CurCell = oRow.GetCellsCount() > this.Selection.EndPos.Pos.Cell ? oRow.GetCell(this.Selection.EndPos.Pos.Cell) : oRow.GetCell(0); } this.Selection.Use = false; this.Selection.Start = false; this.private_SetSelectionData(null); this.Selection.StartPos.Pos = {Row : 0, Cell : 0}; this.Selection.EndPos.Pos = {Row : 0, Cell : 0}; this.Markup.Internal.RowIndex = 0; this.Markup.Internal.CellIndex = 0; this.Markup.Internal.PageNum = 0; }; CTable.prototype.CheckPosInSelection = function(X, Y, CurPage, NearPos) { if (undefined != NearPos) { if ((true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) || true === this.ApplyToAll) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var CurPos = Cells_array[Index]; var CurCell = this.Content[CurPos.Row].Get_Cell(CurPos.Cell); var CellContent = CurCell.Content; CellContent.SetApplyToAll(true); if (true === CellContent.CheckPosInSelection(0, 0, 0, NearPos)) { CellContent.SetApplyToAll(false); return true; } CellContent.SetApplyToAll(false); } } else return this.CurCell.Content_CheckPosInSelection(0, 0, 0, NearPos); return false; } else { if (CurPage < 0 || CurPage >= this.Pages.length) return false; var oHitInfo = this.private_CheckHitInBorder(X, Y, CurPage); if (oHitInfo.CellSelection || oHitInfo.RowSelection || oHitInfo.ColumnSelection) return false; var CellPos = this.private_GetCellByXY(X, Y, CurPage); if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { for (var Index = 0; Index < this.Selection.Data.length; Index++) { var CurPos = this.Selection.Data[Index]; if (CurPos.Cell === CellPos.Cell && CurPos.Row === CellPos.Row) return true; } return false; } else if (CellPos.Cell === this.CurCell.Index && CellPos.Row === this.CurCell.Row.Index) return this.CurCell.Content_CheckPosInSelection(X, Y, CurPage - this.CurCell.Content.GetRelativeStartPage(), undefined); return false; } }; CTable.prototype.IsSelectionEmpty = function(bCheckHidden) { if (true === this.Selection.Use) { if (table_Selection_Cell === this.Selection.Type) return false; else return this.CurCell.Content.IsSelectionEmpty(bCheckHidden); } return true; }; CTable.prototype.SelectAll = function(nDirection) { this.Selection.Use = true; this.Selection.Start = false; this.Selection.Type = table_Selection_Cell; this.Selection.Type2 = table_Selection_Common; this.Selection.Data2 = null; if (nDirection && nDirection < 0) { this.Selection.EndPos.Pos = { Row : 0, Cell : 0 }; this.Selection.EndPos.PageIndex = 0; this.Selection.StartPos.Pos = { Row : this.Content.length - 1, Cell : this.Content[this.Content.length - 1].Get_CellsCount() - 1 }; this.Selection.StartPos.PageIndex = this.Pages.length - 1; } else { this.Selection.StartPos.Pos = { Row : 0, Cell : 0 }; this.Selection.StartPos.PageIndex = 0; this.Selection.EndPos.Pos = { Row : this.Content.length - 1, Cell : this.Content[this.Content.length - 1].Get_CellsCount() - 1 }; this.Selection.EndPos.PageIndex = this.Pages.length - 1; } this.private_UpdateSelectedCellsArray(); }; /** * В данной функции проверяется идет ли выделение таблицы до конца таблицы. */ CTable.prototype.IsSelectionToEnd = function() { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); var Len = Cells_array.length; if (Len < 1) return false; var Pos = Cells_array[Len - 1]; if (Pos.Row !== this.Content.length - 1 || Pos.Cell !== this.Content[Pos.Row].Get_CellsCount() - 1) return false; return true; } else return false; }; CTable.prototype.SetSelectionUse = function(isUse) { if (true === isUse) this.Selection.Use = true; else this.RemoveSelection(); }; CTable.prototype.SetSelectionToBeginEnd = function(isSelectionStart, isElementStart) { var Pos; if (false === isElementStart) { var Row = this.Content.length - 1; var Cell = this.Content[Row].Get_CellsCount() - 1; Pos = {Row : Row, Cell : Cell}; } else { Pos = {Row : 0, Cell : 0}; } if (isSelectionStart) this.Selection.StartPos.Pos = Pos; else this.Selection.EndPos.Pos = Pos; this.private_UpdateSelectedCellsArray(); }; CTable.prototype.MoveCursorToStartPos = function(AddToSelect) { if (true === AddToSelect) { var StartRow = ( true === this.Selection.Use ? this.Selection.StartPos.Pos.Row : this.CurCell.Row.Index ); var EndRow = 0; this.Selection.Use = true; this.Selection.Start = false; this.Selection.Type = table_Selection_Cell; this.Selection.Type2 = table_Selection_Common; this.Selection.StartPos.Pos = {Row : StartRow, Cell : this.Content[StartRow].Get_CellsCount() - 1}; this.Selection.EndPos.Pos = {Row : EndRow, Cell : 0}; this.Selection.CurRow = EndRow; this.private_UpdateSelectedCellsArray(); } else { this.CurCell = this.Content[0].Get_Cell(0); this.Selection.Use = false; this.Selection.Start = false; this.Selection.StartPos.Pos = {Row : 0, Cell : 0}; this.Selection.EndPos.Pos = {Row : 0, Cell : 0}; this.Selection.CurRow = 0; this.CurCell.Content_MoveCursorToStartPos(); } }; CTable.prototype.MoveCursorToEndPos = function(AddToSelect) { if (true === AddToSelect) { var StartRow = ( true === this.Selection.Use ? this.Selection.StartPos.Pos.Row : this.CurCell.Row.Index ); var EndRow = this.Content.length - 1; this.Selection.Use = true; this.Selection.Start = false; this.Selection.Type = table_Selection_Cell; this.Selection.Type2 = table_Selection_Common; this.Selection.StartPos.Pos = {Row : StartRow, Cell : 0}; this.Selection.EndPos.Pos = {Row : EndRow, Cell : this.Content[EndRow].Get_CellsCount() - 1}; this.Selection.CurRow = EndRow; this.private_UpdateSelectedCellsArray(); } else { var Row = this.Content[this.Content.length - 1]; this.CurCell = Row.Get_Cell(Row.Get_CellsCount() - 1); this.Selection.Use = false; this.Selection.Start = false; this.Selection.StartPos.Pos = {Row : Row.Index, Cell : this.CurCell.Index}; this.Selection.EndPos.Pos = {Row : Row.Index, Cell : this.CurCell.Index}; this.Selection.CurRow = Row.Index; this.CurCell.Content_MoveCursorToEndPos(); } }; CTable.prototype.IsCursorAtBegin = function(bOnlyPara) { if (false === this.Selection.Use || ( true === this.Selection.Use && table_Selection_Text === this.Selection.Type )) { if (0 === this.CurCell.Index && 0 === this.CurCell.Row.Index) { return this.CurCell.Content.IsCursorAtBegin(bOnlyPara); } } return false; }; CTable.prototype.IsCursorAtEnd = function() { if ((false === this.Selection.Use || (true === this.Selection.Use && table_Selection_Text === this.Selection.Type)) && this.CurCell.Row.Index === this.GetRowsCount() - 1) return this.CurCell.Content.IsCursorAtEnd(); return false; }; //---------------------------------------------------------------------------------------------------------------------- // Работаем с содержимым таблицы //---------------------------------------------------------------------------------------------------------------------- CTable.prototype.AddNewParagraph = function() { this.CurCell.Content.AddNewParagraph(); }; CTable.prototype.AddInlineImage = function(W, H, Img, GraphicObject, bFlow) { this.Selection.Use = true; this.Selection.Type = table_Selection_Text; this.CurCell.Content.AddInlineImage(W, H, Img, GraphicObject, bFlow); }; CTable.prototype.AddImages = function(aImages) { this.Selection.Use = true; this.Selection.Type = table_Selection_Text; this.CurCell.Content.AddImages(aImages); }; CTable.prototype.AddSignatureLine = function(oSignatureDrawing) { this.Selection.Use = true; this.Selection.Type = table_Selection_Text; this.CurCell.Content.AddSignatureLine(oSignatureDrawing); }; CTable.prototype.AddOleObject = function(W, H, nWidthPix, nHeightPix, Img, Data, sApplicationId, bSelect, arrImagesForAddToHistory) { this.Selection.Use = true; this.Selection.Type = table_Selection_Text; return this.CurCell.Content.AddOleObject(W, H, nWidthPix, nHeightPix, Img, Data, sApplicationId, bSelect, arrImagesForAddToHistory); }; CTable.prototype.AddTextArt = function(nStyle) { this.Selection.Use = true; this.Selection.Type = table_Selection_Text; this.CurCell.Content.AddTextArt(nStyle); }; CTable.prototype.AddInlineTable = function(nCols, nRows, nMode) { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) return null; return this.CurCell.Content.AddInlineTable(nCols, nRows, nMode); }; CTable.prototype.Add = function(ParaItem, bRecalculate) { this.AddToParagraph(ParaItem, bRecalculate); }; CTable.prototype.AddToParagraph = function(ParaItem, bRecalculate) { if (para_TextPr === ParaItem.Type && this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.AddToParagraph(ParaItem, bRecalculate); Cell_Content.SetApplyToAll(false); } // Если в TextPr только HighLight, тогда не надо ничего пересчитывать, только перерисовываем if (true === ParaItem.Value.Check_NeedRecalc()) { if (Cells_array[0].Row - 1 >= 0) this.Internal_RecalculateFrom(Cells_array[0].Row - 1, 0, true, true); else { this.Internal_Recalculate_1(); } } else { this.Parent.OnContentReDraw(this.GetAbsolutePage(0), this.GetAbsolutePage(this.Pages.length - 1)); } } else { this.CurCell.Content.AddToParagraph(ParaItem, bRecalculate); } }; CTable.prototype.ClearParagraphFormatting = function(isClearParaPr, isClearTextPr) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.ClearParagraphFormatting(isClearParaPr, isClearTextPr); Cell_Content.SetApplyToAll(false); } } else { this.CurCell.Content.ClearParagraphFormatting(isClearParaPr, isClearTextPr); } }; CTable.prototype.PasteFormatting = function(oData) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.PasteFormatting(oData); Cell_Content.SetApplyToAll(false); } } else { this.CurCell.Content.PasteFormatting(oData); } }; CTable.prototype.Remove = function(Count, bOnlyText, bRemoveOnlySelection, bOnTextAdd, isWord) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); if (true === bOnTextAdd && Cells_array.length > 0) { // Снимаем выделением со всех ячеек, кроме первой, попавшей в выделение var Pos = Cells_array[0]; var Cell = this.Content[Pos.Row].Get_Cell(Pos.Cell); Cell.Content.SelectAll(); Cell.Content.Remove(Count, bOnlyText, bRemoveOnlySelection, true, false); this.RemoveSelection(); this.CurCell = Cell; this.Document_SetThisElementCurrent(true); } else { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.Remove(Count, bOnlyText, bRemoveOnlySelection, false, false); Cell_Content.SetApplyToAll(false); } // Снимаем выделение var Pos = Cells_array[0]; var Cell = this.Content[Pos.Row].Get_Cell(Pos.Cell); this.CurCell = Cell; this.Selection.Use = false; this.Selection.Start = false; this.Selection.StartPos.Pos = {Row : Cell.Row.Index, Cell : Cell.Index}; this.Selection.EndPos.Pos = {Row : Cell.Row.Index, Cell : Cell.Index}; } } else { this.CurCell.Content.Remove(Count, bOnlyText, bRemoveOnlySelection, bOnTextAdd, isWord); if (false === this.CurCell.Content.IsSelectionUse()) { var Cell = this.CurCell; this.Selection.Use = false; this.Selection.Start = false; this.Selection.StartPos.Pos = {Row : Cell.Row.Index, Cell : Cell.Index}; this.Selection.EndPos.Pos = {Row : Cell.Row.Index, Cell : Cell.Index}; } } }; CTable.prototype.GetCursorPosXY = function() { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { if (this.Selection.Data.length < 0) return {X : 0, Y : 0}; var Pos = this.Selection.Data[0]; var Cell = this.Content[Pos.Row].Get_Cell(Pos.Cell); var Para = Cell.Content.Get_FirstParagraph(); return {X : Para.X, Y : Para.Y} } else return this.CurCell.Content.GetCursorPosXY(); }; CTable.prototype.MoveCursorLeft = function(AddToSelect, Word) { if (true === this.Selection.Use && this.Selection.Type === table_Selection_Cell) { if (true === AddToSelect) { var StartPos = this.Selection.StartPos.Pos; var EndPos = this.Selection.EndPos.Pos; if (StartPos.Cell == EndPos.Cell && StartPos.Row == EndPos.Row && this.Parent.IsSelectedSingleElement()) { // Если была выделена одна ячейка, тогда мы убираем выделение по ячейкам this.Selection.Type = table_Selection_Text; return true; } else { // Если текущая ячейка - первая в первой строке и данная таблица - первый элемент, тогда мы ничего не // делаем if (0 == EndPos.Cell && 0 == EndPos.Row && ( null === this.Get_DocumentPrev() && true === this.Parent.Is_TopDocument() )) return false; // Если текущая ячейка - первая в первой строке (и таблица не первый элемент документа), // тогда мы выделаяем первую строку var bRet = true; if (0 == EndPos.Cell && 0 == EndPos.Row || ( !this.Parent.IsSelectedSingleElement() && 0 == EndPos.Row && 0 == StartPos.Row )) { this.Selection.EndPos.Pos = {Cell : 0, Row : 0}; bRet = false; } else if (EndPos.Cell > 0 && this.Parent.IsSelectedSingleElement()) this.Selection.EndPos.Pos = {Cell : EndPos.Cell - 1, Row : EndPos.Row}; else this.Selection.EndPos.Pos = {Cell : 0, Row : EndPos.Row - 1}; var bForceSelectByLines = false; if (false === bRet && true == this.Is_Inline()) bForceSelectByLines = true; this.private_UpdateSelectedCellsArray(bForceSelectByLines); return bRet; } } else { // Перемещаем курсор в начало первой выделенной ячейки this.Selection.Use = false; var Pos = this.Selection.Data[0]; this.CurCell = this.Content[Pos.Row].Get_Cell(Pos.Cell); this.CurCell.Content_MoveCursorToStartPos(); return true; } } else { if (false === this.CurCell.Content.MoveCursorLeft(AddToSelect, Word)) { if (false === AddToSelect) { var nCurCell = this.CurCell.GetIndex(); var nCurRow = this.CurCell.GetRow().GetIndex(); if (0 !== nCurCell || 0 !== nCurRow) { while (true) { if (nCurCell > 0) { nCurCell--; } else if (nCurRow > 0) { nCurRow--; nCurCell = this.GetRow(nCurRow).GetCellsCount() - 1; } else { this.CurCell = this.GetRow(0).GetCell(0); break; } var oTempCell = this.GetRow(nCurRow).GetCell(nCurCell); if (vmerge_Restart !== oTempCell.GetVMerge()) continue; this.RemoveSelection(); this.CurCell = oTempCell; break; } this.CurCell.Content.MoveCursorToEndPos(); } else { return false; } } else { // Если текущая ячейка - первая в первой строке и данная таблица - первый элемент, тогда мы ничего не // делаем if (0 == this.CurCell.Index && 0 == this.CurCell.Row.Index && ( null === this.Get_DocumentPrev() && true === this.Parent.Is_TopDocument() )) return false; this.Selection.Use = true; this.Selection.Type = table_Selection_Cell; // Если текущая ячейка - первая в первой строке (и таблица не первый элемент документа), // тогда мы выделаяем первую строку var bRet = true; this.Selection.StartPos.Pos = {Cell : this.CurCell.Index, Row : this.CurCell.Row.Index}; if (0 == this.CurCell.Index && 0 == this.CurCell.Row.Index) { this.Selection.EndPos.Pos = {Cell : this.CurCell.Row.Get_CellsCount() - 1, Row : 0}; bRet = false; } else if (this.CurCell.Index > 0) this.Selection.EndPos.Pos = {Cell : this.CurCell.Index - 1, Row : this.CurCell.Row.Index}; else this.Selection.EndPos.Pos = {Cell : 0, Row : this.CurCell.Row.Index - 1}; this.private_UpdateSelectedCellsArray(); return bRet; } } else { if (true === AddToSelect) { this.Selection.Use = true; this.Selection.Type = table_Selection_Text; this.Selection.StartPos.Pos = {Cell : this.CurCell.Index, Row : this.CurCell.Row.Index}; this.Selection.EndPos.Pos = {Cell : this.CurCell.Index, Row : this.CurCell.Row.Index}; } return true; } } }; CTable.prototype.MoveCursorLeftWithSelectionFromEnd = function(Word) { if (true === this.IsSelectionUse()) this.RemoveSelection(); if (this.Content.length <= 0) return; var LastRow = this.Content[this.Content.length - 1]; // Нам нужно выделить последний ряд таблицы this.Selection.Use = true; this.Selection.Type = table_Selection_Cell; this.Selection.StartPos.Pos = { Row : LastRow.Index, Cell : LastRow.Get_CellsCount() - 1 }; this.Selection.EndPos.Pos = { Row : LastRow.Index, Cell : 0 }; this.CurCell = LastRow.Get_Cell(0); var arrSelectionData = []; for (var CellIndex = 0; CellIndex < LastRow.Get_CellsCount(); CellIndex++) { arrSelectionData.push({Cell : CellIndex, Row : LastRow.Index}); } this.private_SetSelectionData(arrSelectionData); }; CTable.prototype.MoveCursorRight = function(AddToSelect, Word, FromPaste) { if (true === this.Selection.Use && this.Selection.Type === table_Selection_Cell) { if (true === AddToSelect) { var StartPos = this.Selection.StartPos.Pos; var EndPos = this.Selection.EndPos.Pos; if (StartPos.Cell == EndPos.Cell && StartPos.Row == EndPos.Row && this.Parent.IsSelectedSingleElement()) { // Если была выделена одна ячейка, тогда мы убираем выделение по ячейкам this.Selection.Type = table_Selection_Text; return true; } else { // Если текущая ячейка - последняя в последней строке, тогда мы выделаяем последнюю строку var oLastRow = this.GetRow(this.GetRowsCount() - 1); var oEndRow = this.GetRow(EndPos.Row); var bRet = true; if (EndPos.Cell < oEndRow.GetCellsCount() - 1 && this.Parent.IsSelectedSingleElement()) { this.Selection.EndPos.Pos = { Cell : EndPos.Cell + 1, Row : EndPos.Row }; } else if (this.GetRowsCount() - 1 <= EndPos.Row) { this.Selection.EndPos.Pos = { Cell : oLastRow.GetCellsCount() - 1, Row : oLastRow.Index }; bRet = false; } else { this.Selection.EndPos.Pos = { Cell : this.GetRow(EndPos.Row + 1).GetCellsCount() - 1, Row : EndPos.Row + 1 }; } var bForceSelectByLines = false; if (false === bRet && true == this.Is_Inline()) bForceSelectByLines = true; this.private_UpdateSelectedCellsArray(bForceSelectByLines); return bRet; } } else { // Перемещаем курсор в конец последней выделенной ячейки this.Selection.Use = false; var Pos = this.Selection.Data[this.Selection.Data.length - 1]; this.CurCell = this.Content[Pos.Row].Get_Cell(Pos.Cell); this.CurCell.Content_MoveCursorToEndPos(); return true; } } else { if (false === this.CurCell.Content.MoveCursorRight(AddToSelect, Word, FromPaste)) { if (false === AddToSelect) { var nCurCell = this.CurCell.GetIndex(); var nCurRow = this.CurCell.GetRow().GetIndex(); var nCellsCount = this.GetRow(nCurRow).GetCellsCount(); var nRowsCount = this.GetRowsCount(); if (this.Content.length - 1 > nCurRow || nCellsCount - 1 > nCurCell) { while (true) { if (nCurCell < nCellsCount - 1) { nCurCell++; } else if (nCurRow < nRowsCount - 1) { nCurRow++; nCurCell = 0; nCellsCount = this.GetRow(nCurRow).GetCellsCount(); } else { var oLastRow = this.GetRow(this.GetRowsCount() - 1); this.CurCell = oLastRow.GetCell(oLastRow.GetCellsCount() - 1); break; } var oTempCell = this.GetRow(nCurRow).GetCell(nCurCell); if (vmerge_Restart !== oTempCell.GetVMerge()) continue; this.RemoveSelection(); this.CurCell = oTempCell; break; } this.CurCell.Content.MoveCursorToStartPos(); } else { return false; } } else { this.Selection.Use = true; this.Selection.Type = table_Selection_Cell; // Если текущая ячейка - последняя в последней строке, тогда мы выделаяем последнюю строку var oLastRow = this.GetRow(this.GetRowsCount() - 1); var oCurRow = this.CurCell.Row; this.Selection.StartPos.Pos = { Cell : this.CurCell.Index, Row : this.CurCell.Row.Index }; var bRet = true; if (this.CurCell.Index < oCurRow.Get_CellsCount() - 1) { this.Selection.EndPos.Pos = { Cell : this.CurCell.Index + 1, Row : this.CurCell.Row.Index }; } else if (this.CurCell.Row.Index >= this.GetRowsCount() - 1) { this.Selection.EndPos.Pos = { Cell : oLastRow.GetCellsCount() - 1, Row : oLastRow.Index }; bRet = false; } else { this.Selection.EndPos.Pos = { Cell : this.GetRow(this.CurCell.Row.Index + 1).GetCellsCount() - 1, Row : this.CurCell.Row.Index + 1 }; } var bForceSelectByLines = false; if (false === bRet && true == this.Is_Inline()) bForceSelectByLines = true; this.private_UpdateSelectedCellsArray(bForceSelectByLines); return bRet; } } else { if (true === AddToSelect) { this.Selection.Use = true; this.Selection.Type = table_Selection_Text; this.Selection.StartPos.Pos = {Cell : this.CurCell.Index, Row : this.CurCell.Row.Index}; this.Selection.EndPos.Pos = {Cell : this.CurCell.Index, Row : this.CurCell.Row.Index}; } return true; } } }; CTable.prototype.MoveCursorRightWithSelectionFromStart = function(Word) { if (true === this.IsSelectionUse()) this.RemoveSelection(); if (this.Content.length <= 0) return; var FirstRow = this.Content[0]; // Нам нужно выделить первый ряд таблицы this.Selection.Use = true; this.Selection.Type = table_Selection_Cell; this.Selection.StartPos.Pos = { Row : 0, Cell : 0 }; this.Selection.EndPos.Pos = { Row : 0, Cell : FirstRow.Get_CellsCount() - 1 }; this.CurCell = FirstRow.Get_Cell(FirstRow.Get_CellsCount() - 1); var arrSelectionData = []; for (var CellIndex = 0; CellIndex < FirstRow.Get_CellsCount(); CellIndex++) { arrSelectionData.push({Cell : CellIndex, Row : 0}); } this.private_SetSelectionData(arrSelectionData); }; CTable.prototype.MoveCursorUp = function(AddToSelect) { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { if (true === AddToSelect) { var bRetValue = true; var EndPos = this.Selection.EndPos.Pos; if (0 === EndPos.Row) { bRetValue = false; } else { var EndCell = this.Content[EndPos.Row].Get_Cell(EndPos.Cell); var X = EndCell.Content_GetCurPosXY().X; var Y = EndCell.Content_GetCurPosXY().Y; var PrevRow = this.Content[EndPos.Row - 1]; var Cell = null; for (var CurCell = 0; CurCell < PrevRow.Get_CellsCount(); CurCell++) { Cell = PrevRow.Get_Cell(CurCell); var CellInfo = PrevRow.Get_CellInfo(CurCell); if (X <= CellInfo.X_grid_end) break; } if (null === Cell) return true; Cell.Content_SetCurPosXY(X, Y); this.CurCell = Cell; this.Selection.EndPos.Pos = {Cell : Cell.Index, Row : Cell.Row.Index}; } var bForceSelectByLines = false; if (false === bRetValue && true === this.Is_Inline()) bForceSelectByLines = true; this.private_UpdateSelectedCellsArray(bForceSelectByLines); return bRetValue; } else { if (this.Selection.Data.length < 0) return true; var Pos = this.Selection.Data[0]; var Cell = this.Content[Pos.Row].Get_Cell(Pos.Cell); var Para = Cell.Content.Get_FirstParagraph(); var X = Para.X; var Y = Para.Y; this.Selection.Use = false; if (0 === Pos.Row) { this.CurCell = Cell; this.CurCell.Content.MoveCursorToStartPos(); this.CurCell.Content_SetCurPosXY(X, Y); return false; } else { var PrevRow = this.Content[Pos.Row - 1]; var PrevCell = null; for (var CurCell = 0; CurCell < PrevRow.Get_CellsCount(); CurCell++) { PrevCell = PrevRow.Get_Cell(CurCell); var CellInfo = PrevRow.Get_CellInfo(CurCell); if (X <= CellInfo.X_grid_end) break; } if (null === PrevCell) return true; PrevCell.Content_MoveCursorUpToLastRow(X, Y, false); this.CurCell = PrevCell; return true; } } } else { if (false === this.CurCell.Content.MoveCursorUp(AddToSelect)) { // Ничего не делаем, если это "плавающая" таблица или первый элемент документа if (0 === this.CurCell.Row.Index && (false === this.Is_Inline() || ( null === this.Get_DocumentPrev() && true === this.Parent.Is_TopDocument() ))) return true; if (true === AddToSelect) { this.Selection.Use = true; this.Selection.Type = table_Selection_Cell; this.Selection.StartPos.Pos = {Row : this.CurCell.Row.Index, Cell : this.CurCell.Index}; var bRetValue = true; if (0 === this.CurCell.Row.Index) { this.Selection.EndPos.Pos = {Row : 0, Cell : 0}; bRetValue = false; } else { var X = this.CurCell.Content_GetCurPosXY().X; var Y = this.CurCell.Content_GetCurPosXY().Y; var PrevRow = this.Content[this.CurCell.Row.Index - 1]; var Cell = null; for (var CurCell = 0; CurCell < PrevRow.Get_CellsCount(); CurCell++) { Cell = PrevRow.Get_Cell(CurCell); var CellInfo = PrevRow.Get_CellInfo(CurCell); if (X <= CellInfo.X_grid_end) break; } if (null === Cell) return true; Cell.Content_SetCurPosXY(X, Y); this.CurCell = Cell; this.Selection.EndPos.Pos = {Cell : Cell.Index, Row : Cell.Row.Index}; } var bForceSelectByLines = false; if (false === bRetValue && true === this.Is_Inline()) bForceSelectByLines = true; this.private_UpdateSelectedCellsArray(bForceSelectByLines); return bRetValue; } else { if (0 === this.CurCell.Row.Index) return false; else { var X = this.CurCell.Content_GetCurPosXY().X; var Y = this.CurCell.Content_GetCurPosXY().Y; var PrevRow = this.Content[this.CurCell.Row.Index - 1]; var Cell = null; for (var CurCell = 0; CurCell < PrevRow.Get_CellsCount(); CurCell++) { Cell = PrevRow.Get_Cell(CurCell); var CellInfo = PrevRow.Get_CellInfo(CurCell); if (!CellInfo) { Cell = null; break; } if (X <= CellInfo.X_grid_end) break; } if (null === Cell) return true; Cell = this.GetStartMergedCell(Cell.Index, Cell.Row.Index); if (!Cell) return true; Cell.Content_MoveCursorUpToLastRow(X, Y, false); this.CurCell = Cell; this.Selection.EndPos.Pos = {Cell : Cell.Index, Row : Cell.Row.Index}; this.Selection.CurRow = Cell.Row.Index; return true; } } } else { if (true === AddToSelect) { this.Selection.Use = true; this.Selection.Type = table_Selection_Text; this.Selection.StartPos.Pos = {Cell : this.CurCell.Index, Row : this.CurCell.Row.Index}; this.Selection.EndPos.Pos = {Cell : this.CurCell.Index, Row : this.CurCell.Row.Index}; } return true; } } }; CTable.prototype.MoveCursorDown = function(AddToSelect) { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { if (true === AddToSelect) { var bRetValue = true; var EndPos = this.Selection.EndPos.Pos; if (this.Content.length - 1 === EndPos.Row) { bRetValue = false; } else { var EndCell = this.Content[EndPos.Row].Get_Cell(EndPos.Cell); var X = EndCell.Content_GetCurPosXY().X; var Y = EndCell.Content_GetCurPosXY().Y; var NextRow = this.Content[EndPos.Row + 1]; var Cell = null; for (var CurCell = 0; CurCell < NextRow.Get_CellsCount(); CurCell++) { Cell = NextRow.Get_Cell(CurCell); var CellInfo = NextRow.Get_CellInfo(CurCell); if (X <= CellInfo.X_grid_end) break; } if (null === Cell) return true; Cell.Content_SetCurPosXY(X, Y); this.CurCell = Cell; this.Selection.EndPos.Pos = {Cell : Cell.Index, Row : Cell.Row.Index}; } var bForceSelectByLines = false; if (false === bRetValue && true === this.Is_Inline()) bForceSelectByLines = true; this.private_UpdateSelectedCellsArray(bForceSelectByLines); return bRetValue; } else { if (this.Selection.Data.length < 0) return true; var Pos = this.Selection.Data[this.Selection.Data.length - 1]; var Cell = this.Content[Pos.Row].Get_Cell(Pos.Cell); var Para = Cell.Content.Get_FirstParagraph(); var X = Para.X; var Y = Para.Y; this.Selection.Use = false; if (this.Content.length - 1 === Pos.Row) { this.CurCell = Cell; this.CurCell.Content.MoveCursorToStartPos(); this.CurCell.Content_SetCurPosXY(X, Y); return false; } else { var NextRow = this.Content[Pos.Row + 1]; var NextCell = null; for (var CurCell = 0; CurCell < NextRow.Get_CellsCount(); CurCell++) { NextCell = NextRow.Get_Cell(CurCell); var CellInfo = NextRow.Get_CellInfo(CurCell); if (X <= CellInfo.X_grid_end) break; } if (null === NextCell) return true; NextCell.Content_MoveCursorDownToFirstRow(X, Y, false); this.CurCell = NextCell; return true; } } } else { if (false === this.CurCell.Content.MoveCursorDown(AddToSelect)) { if (true === AddToSelect) { this.Selection.Use = true; this.Selection.Type = table_Selection_Cell; this.Selection.StartPos.Pos = {Row : this.CurCell.Row.Index, Cell : this.CurCell.Index}; var bRetValue = true; if (this.Content.length - 1 === this.CurCell.Row.Index) { this.Selection.EndPos.Pos = { Row : this.Content.length - 1, Cell : this.Content[this.Content.length - 1].Get_CellsCount() - 1 }; bRetValue = false; } else { var X = this.CurCell.Content_GetCurPosXY().X; var Y = this.CurCell.Content_GetCurPosXY().Y; var NextRow = this.Content[this.CurCell.Row.Index + 1]; var Cell = null; for (var CurCell = 0; CurCell < NextRow.Get_CellsCount(); CurCell++) { Cell = NextRow.Get_Cell(CurCell); var CellInfo = NextRow.Get_CellInfo(CurCell); if (X <= CellInfo.X_grid_end) break; } if (null === Cell) return true; Cell.Content_SetCurPosXY(X, Y); this.CurCell = Cell; this.Selection.EndPos.Pos = {Cell : Cell.Index, Row : Cell.Row.Index}; } var bForceSelectByLines = false; if (false === bRetValue && true === this.Is_Inline()) bForceSelectByLines = true; this.private_UpdateSelectedCellsArray(bForceSelectByLines); return bRetValue; } else { var VMerge_count = this.Internal_GetVertMergeCount(this.CurCell.Row.Index, this.CurCell.Row.Get_CellInfo(this.CurCell.Index).StartGridCol, this.CurCell.Get_GridSpan()); if (this.Content.length - 1 === this.CurCell.Row.Index + VMerge_count - 1) return false; else { var X = this.CurCell.Content_GetCurPosXY().X; var Y = this.CurCell.Content_GetCurPosXY().Y; var NextRow = this.Content[this.CurCell.Row.Index + VMerge_count]; var Cell = null; for (var CurCell = 0; CurCell < NextRow.Get_CellsCount(); CurCell++) { Cell = NextRow.Get_Cell(CurCell); var CellInfo = NextRow.Get_CellInfo(CurCell); if (X <= CellInfo.X_grid_end) break; } if (null === Cell) return true; Cell.Content_MoveCursorDownToFirstRow(X, Y, false); this.CurCell = Cell; this.Selection.EndPos.Pos = {Cell : Cell.Index, Row : Cell.Row.Index}; this.Selection.CurRow = Cell.Row.Index; return true; } } } else { if (true === AddToSelect) { this.Selection.Use = true; this.Selection.Type = table_Selection_Text; this.Selection.StartPos.Pos = {Cell : this.CurCell.Index, Row : this.CurCell.Row.Index}; this.Selection.EndPos.Pos = {Cell : this.CurCell.Index, Row : this.CurCell.Row.Index}; } return true; } } }; CTable.prototype.MoveCursorToEndOfLine = function(AddToSelect) { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) return this.MoveCursorRight(AddToSelect, false); else { var bRetValue = this.CurCell.Content.MoveCursorToEndOfLine(AddToSelect); if (true === this.CurCell.Content.IsSelectionUse()) { this.Selection.Use = true; this.Selection.Type = table_Selection_Text; this.Selection.StartPos.Pos = {Cell : this.CurCell.Index, Row : this.CurCell.Row.Index}; this.Selection.EndPos.Pos = {Cell : this.CurCell.Index, Row : this.CurCell.Row.Index}; } else { this.Selection.Use = false; } return bRetValue; } }; CTable.prototype.MoveCursorToStartOfLine = function(AddToSelect) { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) return this.MoveCursorLeft(AddToSelect, false); else { var bRetValue = this.CurCell.Content.MoveCursorToStartOfLine(AddToSelect); if (true === this.CurCell.Content.IsSelectionUse()) { this.Selection.Use = true; this.Selection.Type = table_Selection_Text; this.Selection.StartPos.Pos = {Cell : this.CurCell.Index, Row : this.CurCell.Row.Index}; this.Selection.EndPos.Pos = {Cell : this.CurCell.Index, Row : this.CurCell.Row.Index}; } else { this.Selection.Use = false; } return bRetValue; } }; CTable.prototype.MoveCursorUpToLastRow = function(X, Y, AddToSelect) { if (true === AddToSelect) { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { var Row = this.Content[this.Content.length - 1]; var Cell = null; for (var CurCell = 0; CurCell < Row.Get_CellsCount(); CurCell++) { Cell = Row.Get_Cell(CurCell); var CellInfo = Row.Get_CellInfo(CurCell); if (X <= CellInfo.X_grid_end) break; } if (null === Cell) return true; Cell.Content_SetCurPosXY(X, Y); this.CurCell = Cell; this.Selection.EndPos.Pos = {Cell : Cell.Index, Row : Cell.Row.Index}; this.private_UpdateSelectedCellsArray(); } else { this.Selection.Use = true; this.Selection.Type = table_Selection_Cell; this.Selection.StartPos.Pos = { Row : this.Content.length - 1, Cell : this.Content[this.Content.length - 1].Get_CellsCount() - 1 }; this.Selection.EndPos.Pos = {Row : this.Content.length - 1, Cell : 0}; this.private_UpdateSelectedCellsArray(); // У последней ячейки у первого параграфа, мы выставим RealX, RealY var Cell = this.Content[this.Content.length - 1].Get_Cell(0); Cell.Content_SetCurPosXY(X, Y); } } else { this.RemoveSelection(); var Row = this.Content[this.Content.length - 1]; var Cell = null; for (var CurCell = 0; CurCell < Row.Get_CellsCount(); CurCell++) { Cell = Row.Get_Cell(CurCell); var CellInfo = Row.Get_CellInfo(CurCell); if (!CellInfo) { Cell = null; break; } if (X <= CellInfo.X_grid_end) break; } if (!Cell) return; Cell = this.GetStartMergedCell(Cell.Index, Cell.Row.Index); if (!Cell) return; Cell.Content_MoveCursorUpToLastRow(X, Y, false); this.Selection.CurRow = Cell.Row.Index; this.CurCell = Cell; } }; CTable.prototype.MoveCursorDownToFirstRow = function(X, Y, AddToSelect) { if (true === AddToSelect) { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { var Row = this.Content[0]; var Cell = null; for (var CurCell = 0; CurCell < Row.Get_CellsCount(); CurCell++) { Cell = Row.Get_Cell(CurCell); var CellInfo = Row.Get_CellInfo(CurCell); if (X <= CellInfo.X_grid_end) break; } if (null === Cell) return true; Cell.Content_SetCurPosXY(X, Y); this.CurCell = Cell; this.Selection.EndPos.Pos = {Cell : Cell.Index, Row : Cell.Row.Index}; this.private_UpdateSelectedCellsArray(); } else { this.Selection.Use = true; this.Selection.Type = table_Selection_Cell; this.Selection.StartPos.Pos = {Row : 0, Cell : 0}; this.Selection.EndPos.Pos = {Row : 0, Cell : this.Content[0].Get_CellsCount() - 1}; this.private_UpdateSelectedCellsArray(); // У последней ячейки у первого параграфа, мы выставим RealX, RealY var Cell = this.Content[0].Get_Cell(0); Cell.Content_SetCurPosXY(X, Y); } } else { this.RemoveSelection(); var Row = this.Content[0]; var Cell = null; for (var CurCell = 0; CurCell < Row.Get_CellsCount(); CurCell++) { Cell = Row.Get_Cell(CurCell); var CellInfo = Row.Get_CellInfo(CurCell); if (X <= CellInfo.X_grid_end) break; } if (null === Cell) return; Cell.Content_MoveCursorDownToFirstRow(X, Y, false); this.Selection.CurRow = Cell.Row.Index; this.CurCell = Cell; } }; CTable.prototype.MoveCursorToCell = function(bNext) { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { var Pos = this.Selection.Data[0]; this.Selection.Type = table_Selection_Text; this.CurCell = this.Content[Pos.Row].Get_Cell(Pos.Cell); this.CurCell.Content.SelectAll(); } else { var oLogicDocument = this.GetLogicDocument(); if (!oLogicDocument) return; if (true === this.IsInnerTable()) return this.CurCell.Content.MoveCursorToCell(bNext); var CurCell = this.CurCell; var Pos_c = this.CurCell.Index; var Pos_r = this.CurCell.Row.Index; var Pos = { Cell : Pos_c, Row : Pos_r }; var oCheckAutoCorrectPara = null; if (!this.IsSelectionUse()) { oCheckAutoCorrectPara = this.CurCell.GetContent().GetCurrentParagraph(); if (oCheckAutoCorrectPara && !oCheckAutoCorrectPara.IsCursorAtEnd()) oCheckAutoCorrectPara = null; } if (true === bNext) { var TempCell = this.Internal_Get_NextCell(Pos); while (null != TempCell && vmerge_Restart !== TempCell.GetVMerge()) TempCell = this.Internal_Get_NextCell(Pos); if (null != TempCell) CurCell = TempCell; else { if (!oLogicDocument.IsSelectionLocked(AscCommon.changestype_None, { Type : AscCommon.changestype_2_Element_and_Type, Element : this, CheckType : AscCommon.changestype_Table_Properties })) { this.LogicDocument.StartAction(AscDFH.historydescription_Document_TableAddNewRowByTab); this.AddTableRow(false); if (oCheckAutoCorrectPara) { var oParaEndRun = oCheckAutoCorrectPara.GetParaEndRun(); if (oParaEndRun) oParaEndRun.ProcessAutoCorrectOnParaEnd(1); oCheckAutoCorrectPara = null; } if(this.Parent && this.Parent.checkExtentsByDocContent) { this.Parent.checkExtentsByDocContent(); } this.LogicDocument.Recalculate(); this.LogicDocument.FinalizeAction(); } else { return; } var TempCell = this.Internal_Get_NextCell(Pos); while (null != TempCell && vmerge_Restart !== TempCell.GetVMerge()) TempCell = this.Internal_Get_NextCell(Pos); if (null != TempCell) CurCell = TempCell; } } else { var TempCell = this.Internal_Get_PrevCell(Pos); while (null != TempCell && vmerge_Restart !== TempCell.GetVMerge()) TempCell = this.Internal_Get_PrevCell(Pos); if (null != TempCell) CurCell = TempCell; } if (oCheckAutoCorrectPara) { var oParaEndRun = oCheckAutoCorrectPara.GetParaEndRun(); if (oParaEndRun) oParaEndRun.ProcessAutoCorrectOnParaEnd(0); oCheckAutoCorrectPara = null; } // Т.к. мы собираемся выставить селект заново, то предварительно очистим текущий селект oLogicDocument.RemoveSelection(); this.CurCell = CurCell; this.CurCell.Content.SelectAll(); if (true === this.CurCell.Content.IsSelectionEmpty(false)) { this.CurCell.Content.MoveCursorToStartPos(); this.Selection.Use = false; this.Selection.Type = table_Selection_Text; this.Selection.CurRow = CurCell.Row.Index; } else { this.Selection.Use = true; this.Selection.Type = table_Selection_Text; this.Selection.StartPos.Pos = {Row : CurCell.Row.Index, Cell : CurCell.Index}; this.Selection.EndPos.Pos = {Row : CurCell.Row.Index, Cell : CurCell.Index}; this.Selection.CurRow = CurCell.Row.Index; } this.Document_SetThisElementCurrent(true); } }; CTable.prototype.GetCurPosXY = function() { var Cell = null; if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) Cell = this.Content[this.Selection.EndPos.Pos.Row].Get_Cell(this.Selection.EndPos.Pos.Cell); else Cell = this.CurCell; return Cell.Content_GetCurPosXY(); }; CTable.prototype.IsSelectionUse = function() { if ((true == this.Selection.Use && table_Selection_Cell == this.Selection.Type) || table_Selection_Border == this.Selection.Type2 || table_Selection_Border_InnerTable == this.Selection.Type2) return true; else if (true == this.Selection.Use) return this.CurCell.Content.IsSelectionUse(); return false; }; CTable.prototype.IsTextSelectionUse = function() { if ((true == this.Selection.Use && table_Selection_Cell == this.Selection.Type) || table_Selection_Border == this.Selection.Type2 || table_Selection_Border_InnerTable == this.Selection.Type2) return true; else if (true == this.Selection.Use) return this.CurCell.Content.IsTextSelectionUse(); return false; }; CTable.prototype.GetSelectedText = function(bClearText, oPr) { if (true === bClearText && ( (true == this.Selection.Use && table_Selection_Text == this.Selection.Type) || false === this.Selection.Use )) { return this.CurCell.Content.GetSelectedText(true, oPr); } else if (false === bClearText) { if (this.IsCellSelection()) { var arrSelectedCells = this.GetSelectionArray(); var sResultText = ""; for (var nIndex = 0, nCount = arrSelectedCells.length; nIndex < nCount; ++nIndex) { var oPos = arrSelectedCells[nIndex]; var oCell = this.GetRow(oPos.Row).GetCell(oPos.Cell); var oCellContent = oCell.GetContent(); oCellContent.SetApplyToAll(true); sResultText += oCellContent.GetSelectedText(false, oPr); oCellContent.SetApplyToAll(false); } return sResultText; } else { return this.CurCell.Content.GetSelectedText(false, oPr); } } return null; }; CTable.prototype.GetText = function(pr) { let sResultText = ""; for (let nRow = 0, nRows = this.GetRowsCount(); nRow < nRows; ++nRow) { let oRow = this.GetRow(nRow); for (let nCell = 0, nCells = oRow.GetCellsCount(); nCell < nCells; ++nCell) { let oCell = oRow.GetCell(nCell); let oContent = oCell.GetContent(); sResultText += oContent.GetText(pr); } } return sResultText; }; CTable.prototype.GetSelectedElementsInfo = function(Info) { Info.SetTable(); if (false === this.Selection.Use || (true === this.Selection.Use && table_Selection_Text === this.Selection.Type)) { this.CurCell.Content.GetSelectedElementsInfo(Info); } else if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type && this.Selection.StartPos.Pos.Row === this.Selection.EndPos.Pos.Row && this.Selection.StartPos.Pos.Cell === this.Selection.EndPos.Pos.Cell) { var Row = this.Get_Row(this.Selection.StartPos.Pos.Row); if (!Row) return; var Cell = Row.Get_Cell(this.Selection.StartPos.Pos.Cell); if (!Cell) return; Info.SetSingleCell(Cell); } }; CTable.prototype.GetSelectedContent = function(SelectedContent) { if (true !== this.Selection.Use) return; if (table_Selection_Cell === this.Selection.Type || true === this.ApplyToAll) { // Сначала проверим выделена ли таблица целиком, если да, тогда просто копируем ее. if (true === this.ApplyToAll) { SelectedContent.Add(new AscCommonWord.CSelectedElement(this.Copy(this.Parent), true)); return; } var bAllSelected = true; var SelectedCount = this.Selection.Data.length; // Собираем информацию по строкам var RowsInfoArray = []; var RowsCount = this.Content.length; for (var CurRow = 0; CurRow < RowsCount; CurRow++) { var Row = this.Content[CurRow]; var CellsCount = Row.Get_CellsCount(); var CellsInfoArray = []; var bSelectedRow = false; CellsInfoArray.push({GridSpan : Row.Get_Before().GridBefore, Cell : null, Selected : false}); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var Cell = Row.Get_Cell(CurCell); var GridSpan = Cell.Get_GridSpan(); var VMerge = Cell.GetVMerge(); var bSelected = false; if (VMerge === vmerge_Restart) { // Ищем текущую ячейку среди выделенных for (var Index = 0; Index < SelectedCount; Index++) { var TempPos = this.Selection.Data[Index]; if (CurCell === TempPos.Cell && CurRow === TempPos.Row) { bSelected = true; break; } else if (CurRow < TempPos.Row) break; } } else { // Данная ячейка попала в вертикальное объединение, находим ячейку, с которой это объединение // началось и проверяем была ли она выделена (эту ячейку мы уже проверяли, т.к. она находится // выше). var StartMergedCell = this.GetStartMergedCell(CurCell, CurRow); if (StartMergedCell) bSelected = RowsInfoArray[StartMergedCell.Row.Index].CellsInfoArray[StartMergedCell.Index + 1].Selected; } if (false === bSelected) bAllSelected = false; else bSelectedRow = true; CellsInfoArray.push({GridSpan : GridSpan, Cell : Cell, Selected : bSelected}); } CellsInfoArray.push({GridSpan : Row.Get_After().GridAfter, Cell : null, Selected : false}); RowsInfoArray.push({CellsInfoArray : CellsInfoArray, Selected : bSelectedRow}); } if (true === bAllSelected) { SelectedContent.Add(new AscCommonWord.CSelectedElement(this.Copy(this.Parent), true)); return; } var TableGrid = this.Internal_Copy_Grid(this.TableGridCalc); // Посчитаем сколько слева и справа пустых спанов var MinBefore = -1; var MinAfter = -1; for (var CurRow = 0; CurRow < RowsCount; CurRow++) { var CellsInfoArray = RowsInfoArray[CurRow].CellsInfoArray; if (true !== RowsInfoArray[CurRow].Selected) continue; var bBefore = true; var BeforeGrid = 0, AfterGrid = 0; var CellsInfoCount = CellsInfoArray.length; for (var CellIndex = 0, CurCell = 0; CellIndex < CellsInfoCount; CellIndex++) { var CellInfo = CellsInfoArray[CellIndex]; if (true === CellInfo.Selected) { bBefore = false; } else if (true === bBefore) { BeforeGrid += CellInfo.GridSpan; } else { AfterGrid += CellInfo.GridSpan; } } if (MinBefore > BeforeGrid || -1 === MinBefore) MinBefore = BeforeGrid; if (MinAfter > AfterGrid || -1 === MinAfter) MinAfter = AfterGrid; } for (var CurRow = 0; CurRow < RowsCount; CurRow++) { var CellsInfoArray = RowsInfoArray[CurRow].CellsInfoArray; if (true === RowsInfoArray[CurRow].Selected) { CellsInfoArray[0].GridSpan -= MinBefore; CellsInfoArray[CellsInfoArray.length - 1].GridSpan -= MinAfter; } } if (MinAfter > 0) TableGrid.splice(TableGrid.length - MinAfter, MinAfter); // TableGrid.length - (MinAfter - 1) - 1 if (MinBefore > 0) TableGrid.splice(0, MinBefore); // Формируем новую таблицу, по выделенно части. var Table = new CTable(this.DrawingDocument, this.Parent, this.Inline, 0, 0, TableGrid, this.bPresentation); // Копируем настройки Table.Set_TableStyle(this.TableStyle); Table.Set_TableLook(this.TableLook.Copy()); Table.Set_PositionH(this.PositionH.RelativeFrom, this.PositionH.Align, this.PositionH.Value); Table.Set_PositionV(this.PositionV.RelativeFrom, this.PositionV.Align, this.PositionV.Value); Table.Set_Distance(this.Distance.L, this.Distance.T, this.Distance.R, this.Distance.B); Table.SetPr(this.Pr.Copy()); // Копируем строки for (var CurRow = 0, CurRow2 = 0; CurRow < RowsCount; CurRow++) { var RowInfo = RowsInfoArray[CurRow]; if (true !== RowInfo.Selected) continue; var CellsInfoArray = RowInfo.CellsInfoArray; var Row = new CTableRow(Table, 0); // Копируем настройки строки Row.Set_Pr(this.Content[CurRow].Pr.Copy()); var bMergedRow = true; var bBefore = true; var BeforeGrid = 0, AfterGrid = 0; var CellsInfoCount = CellsInfoArray.length; for (var CellIndex = 0, CurCell = 0; CellIndex < CellsInfoCount; CellIndex++) { var CellInfo = CellsInfoArray[CellIndex]; if (true === CellInfo.Selected) { bBefore = false; // Добавляем ячейку Row.Content[CurCell] = CellInfo.Cell.Copy(Row); AscCommon.History.Add(new CChangesTableRowAddCell(Row, CurCell, [Row.Content[CurCell]])); Row.private_UpdateTableGrid(); CurCell++; var VMerge = CellInfo.Cell.GetVMerge(); if (VMerge === vmerge_Restart) bMergedRow = false; } else if (true === bBefore) { BeforeGrid += CellInfo.GridSpan; } else { AfterGrid += CellInfo.GridSpan; } } // Строку, составленную полностью из вертикально объединенных ячеек не добавляем if (true === bMergedRow) continue; Row.Set_Before(BeforeGrid); Row.Set_After(AfterGrid); Row.Internal_ReIndexing(); // Добавляем строку в новую таблицу Table.Content[CurRow2] = Row; AscCommon.History.Add(new CChangesTableAddRow(Table, CurRow2, [Table.Content[CurRow2]])); CurRow2++; } Table.Internal_ReIndexing(0); Table.private_UpdateTableGrid(); if (Table.Content.length > 0 && Table.Content[0].Get_CellsCount() > 0) Table.CurCell = Table.Content[0].Get_Cell(0); SelectedContent.Add(new AscCommonWord.CSelectedElement(Table, false)); } else { this.CurCell.Content.GetSelectedContent(SelectedContent); } }; CTable.prototype.SetParagraphPrOnAdd = function(oPara) { this.SetApplyToAll(true); var oParaPr = oPara.GetDirectParaPr().Copy(); oParaPr.Ind = new CParaInd(); this.SetParagraphPr(oParaPr); var oTextPr = oPara.Get_TextPr(); this.AddToParagraph(new ParaTextPr(oTextPr)); this.SetApplyToAll(false); }; CTable.prototype.SetParagraphAlign = function(Align) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.SetParagraphAlign(Align); Cell_Content.SetApplyToAll(false); } } else { return this.CurCell.Content.SetParagraphAlign(Align); } }; CTable.prototype.SetParagraphDefaultTabSize = function(TabSize) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.SetParagraphDefaultTabSize(TabSize); Cell_Content.SetApplyToAll(false); } } else { return this.CurCell.Content.SetParagraphDefaultTabSize(TabSize); } }; CTable.prototype.SetParagraphSpacing = function(Spacing) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.SetParagraphSpacing(Spacing); Cell_Content.SetApplyToAll(false); } } else { return this.CurCell.Content.SetParagraphSpacing(Spacing); } }; CTable.prototype.SetParagraphIndent = function(Ind) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.SetParagraphIndent(Ind); Cell_Content.SetApplyToAll(false); } } else { return this.CurCell.Content.SetParagraphIndent(Ind); } }; CTable.prototype.Set_ParagraphPresentationNumbering = function(NumInfo) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.Set_ParagraphPresentationNumbering(NumInfo); Cell_Content.SetApplyToAll(false); } if (Cells_array[0].Row - 1 >= 0) this.Internal_RecalculateFrom(Cells_array[0].Row - 1, 0, true, true); else { this.Internal_Recalculate_1(); } } else return this.CurCell.Content.Set_ParagraphPresentationNumbering(NumInfo); }; CTable.prototype.Increase_ParagraphLevel = function(bIncrease) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.Increase_ParagraphLevel(bIncrease); Cell_Content.SetApplyToAll(false); } if (Cells_array[0].Row - 1 >= 0) this.Internal_RecalculateFrom(Cells_array[0].Row - 1, 0, true, true); else { this.Internal_Recalculate_1(); } } else return this.CurCell.Content.Increase_ParagraphLevel(bIncrease); }; CTable.prototype.SetParagraphShd = function(Shd) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.SetParagraphShd(Shd); Cell_Content.SetApplyToAll(false); } } else { return this.CurCell.Content.SetParagraphShd(Shd); } }; CTable.prototype.SetParagraphStyle = function(Name) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.SetParagraphStyle(Name); Cell_Content.SetApplyToAll(false); } } else { return this.CurCell.Content.SetParagraphStyle(Name); } }; CTable.prototype.SetParagraphTabs = function(Tabs) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.SetParagraphTabs(Tabs); Cell_Content.SetApplyToAll(false); } } else { return this.CurCell.Content.SetParagraphTabs(Tabs); } }; CTable.prototype.SetParagraphContextualSpacing = function(Value) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.SetParagraphContextualSpacing(Value); Cell_Content.SetApplyToAll(false); } } else { return this.CurCell.Content.SetParagraphContextualSpacing(Value); } }; CTable.prototype.SetParagraphPageBreakBefore = function(Value) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.SetParagraphPageBreakBefore(Value); Cell_Content.SetApplyToAll(false); } } else { return this.CurCell.Content.SetParagraphPageBreakBefore(Value); } }; CTable.prototype.SetParagraphKeepLines = function(Value) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.SetParagraphKeepLines(Value); Cell_Content.SetApplyToAll(false); } } else { return this.CurCell.Content.SetParagraphKeepLines(Value); } }; CTable.prototype.SetParagraphKeepNext = function(Value) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.SetParagraphKeepNext(Value); Cell_Content.SetApplyToAll(false); } } else { return this.CurCell.Content.SetParagraphKeepNext(Value); } }; CTable.prototype.SetParagraphWidowControl = function(Value) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.SetParagraphWidowControl(Value); Cell_Content.SetApplyToAll(false); } } else { return this.CurCell.Content.SetParagraphWidowControl(Value); } }; CTable.prototype.SetParagraphBorders = function(Borders) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.SetParagraphBorders(Borders); Cell_Content.SetApplyToAll(false); } } else { return this.CurCell.Content.SetParagraphBorders(Borders); } }; CTable.prototype.SetParagraphFramePr = function(FramePr, bDelete) { if (true !== this.ApplyToAll && (true !== this.Selection.Use || table_Selection_Cell !== this.Selection.Type)) { this.CurCell.Content.SetParagraphFramePr(FramePr, bDelete); } }; CTable.prototype.SetParagraphPr = function(oParaPr) { if (this.IsCellSelection()) { var arrSelectedCells = this.GetSelectionArray(); for (var nIndex = 0, nCount = arrSelectedCells.length; nIndex < nCount; ++nIndex) { var oPos = arrSelectedCells[nIndex]; var oRow = this.GetRow(oPos.Row); if (!oRow) continue; var oCell = oRow.GetCell(oPos.Cell); if (!oCell) continue; var oCellContent = oCell.GetContent(); oCellContent.SetApplyToAll(true); oCellContent.SetParagraphPr(oParaPr); oCellContent.SetApplyToAll(false); } } else { this.CurCell.GetContent().SetParagraphPr(oParaPr); } }; CTable.prototype.SetParagraphBidi = function(bidi) { if (this.IsCellSelection()) { let selectionArray = this.GetSelectionArray(); for (let i = 0; i < selectionArray.length; ++i) { let row = this.GetRow([selectionArray[i].Row]); let cell = row.GetCell(selectionArray[i].Cell); let docContent = cell.GetContent(); docContent.SetApplyToAll(true); docContent.SetParagraphBidi(bidi); docContent.SetApplyToAll(false); } } else { return this.CurCell.Content.SetParagraphBidi(bidi); } }; CTable.prototype.IncreaseDecreaseFontSize = function(bIncrease) { if (this.IsCellSelection()) { var Cells_array = this.GetSelectionArray(); for (var Index = 0; Index < Cells_array.length; Index++) { var Pos = Cells_array[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var Cell_Content = Cell.Content; Cell_Content.SetApplyToAll(true); Cell.Content.IncreaseDecreaseFontSize(bIncrease); Cell_Content.SetApplyToAll(false); } } else { return this.CurCell.Content.IncreaseDecreaseFontSize(bIncrease); } }; CTable.prototype.IncreaseDecreaseIndent = function(bIncrease) { if (this.IsCellSelection()) { var TablePr = this.Get_CompiledPr(false).TablePr; var LeftIndOld = TablePr.TableInd; if (undefined === LeftIndOld || null === LeftIndOld) { LeftIndOld = 0; } else if (LeftIndOld < 0) { this.Set_TableInd(0); return; } var LeftIndNew = 0; if (true === bIncrease) { if (LeftIndOld >= 0) { LeftIndOld = 12.5 * parseInt(10 * LeftIndOld / 125); LeftIndNew = ( (LeftIndOld - (10 * LeftIndOld) % 125 / 10) / 12.5 + 1) * 12.5; } if (LeftIndNew < 0) LeftIndNew = 12.5; } else { var TempValue = (125 - (10 * LeftIndOld) % 125); TempValue = ( 125 === TempValue ? 0 : TempValue ); LeftIndNew = Math.max(( (LeftIndOld + TempValue / 10) / 12.5 - 1 ) * 12.5, 0); } this.Set_TableInd(LeftIndNew); } else { this.CurCell.Content.IncreaseDecreaseIndent(bIncrease); } }; CTable.prototype.GetCalculatedParaPr = function() { if (true === this.ApplyToAll) { var Row = this.Content[0]; var Cell = Row.Get_Cell(0); Cell.Content.SetApplyToAll(true); var Result_ParaPr = Cell.Content.GetCalculatedParaPr(); Cell.Content.SetApplyToAll(false); for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { Row = this.Content[CurRow]; var CellsCount = Row.Get_CellsCount(); var StartCell = ( CurRow === 0 ? 1 : 0 ); for (var CurCell = StartCell; CurCell < CellsCount; CurCell++) { Cell = Row.Get_Cell(CurCell); Cell.Content.SetApplyToAll(true); var CurPr = Cell.Content.GetCalculatedParaPr(); Cell.Content.SetApplyToAll(false); Result_ParaPr = Result_ParaPr.Compare(CurPr); } } return Result_ParaPr; } if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { var Pos = this.Selection.Data[0]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); Cell.Content.SetApplyToAll(true); var Result_ParaPr = Cell.Content.GetCalculatedParaPr(); Cell.Content.SetApplyToAll(false); for (var Index = 1; Index < this.Selection.Data.length; Index++) { Pos = this.Selection.Data[Index]; Row = this.Content[Pos.Row]; Cell = Row.Get_Cell(Pos.Cell); Cell.Content.SetApplyToAll(true); var CurPr = Cell.Content.GetCalculatedParaPr(); Cell.Content.SetApplyToAll(false); Result_ParaPr = Result_ParaPr.Compare(CurPr); } return Result_ParaPr; } return this.CurCell.Content.GetCalculatedParaPr(); }; CTable.prototype.GetCalculatedTextPr = function() { if (true === this.ApplyToAll) { var Row = this.Content[0]; var Cell = Row.Get_Cell(0); Cell.Content.SetApplyToAll(true); var Result_TextPr = Cell.Content.GetCalculatedTextPr(true); Cell.Content.SetApplyToAll(false); for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { Row = this.Content[CurRow]; var CellsCount = Row.Get_CellsCount(); var StartCell = ( CurRow === 0 ? 1 : 0 ); for (var CurCell = StartCell; CurCell < CellsCount; CurCell++) { Cell = Row.Get_Cell(CurCell); Cell.Content.SetApplyToAll(true); var CurPr = Cell.Content.GetCalculatedTextPr(true); Cell.Content.SetApplyToAll(false); Result_TextPr = Result_TextPr.Compare(CurPr); } } return Result_TextPr; } if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { var Pos = this.Selection.Data[0]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); Cell.Content.SetApplyToAll(true); var Result_TextPr = Cell.Content.GetCalculatedTextPr(true); Cell.Content.SetApplyToAll(false); for (var Index = 1; Index < this.Selection.Data.length; Index++) { Pos = this.Selection.Data[Index]; Row = this.Content[Pos.Row]; Cell = Row.Get_Cell(Pos.Cell); Cell.Content.SetApplyToAll(true); var CurPr = Cell.Content.GetCalculatedTextPr(true); Cell.Content.SetApplyToAll(false); Result_TextPr = Result_TextPr.Compare(CurPr); } return Result_TextPr; } return this.CurCell.Content.GetCalculatedTextPr(true); }; CTable.prototype.GetDirectTextPr = function() { if (true === this.ApplyToAll) { var Row = this.Content[0]; var Cell = Row.Get_Cell(0); Cell.Content.SetApplyToAll(true); var Result_TextPr = Cell.Content.GetDirectTextPr(); Cell.Content.SetApplyToAll(false); return Result_TextPr; } if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { var Pos = this.Selection.Data[0]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); Cell.Content.SetApplyToAll(true); var Result_TextPr = Cell.Content.GetDirectTextPr(); Cell.Content.SetApplyToAll(false); return Result_TextPr; } return this.CurCell.Content.GetDirectTextPr(); }; CTable.prototype.GetDirectParaPr = function() { if (true === this.ApplyToAll) { var Row = this.Content[0]; var Cell = Row.Get_Cell(0); Cell.Content.SetApplyToAll(true); var Result_TextPr = Cell.Content.GetDirectParaPr(); Cell.Content.SetApplyToAll(false); return Result_TextPr; } if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { var Pos = this.Selection.Data[0]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); Cell.Content.SetApplyToAll(true); var Result_TextPr = Cell.Content.GetDirectParaPr(); Cell.Content.SetApplyToAll(false); return Result_TextPr; } return this.CurCell.Content.GetDirectParaPr(); }; CTable.prototype.GetCurrentParagraph = function(bIgnoreSelection, arrSelectedParagraphs, oPr) { if (!bIgnoreSelection && oPr && oPr.ReturnSelectedTable && this.IsCellSelection()) return this; if (arrSelectedParagraphs) { var arrSelectionArray = this.GetSelectionArray(); for (var nIndex = 0, nCount = arrSelectionArray.length; nIndex < nCount; ++nIndex) { var nCurCell = arrSelectionArray[nIndex].Cell; var nCurRow = arrSelectionArray[nIndex].Row; var oCellContent = this.GetRow(nCurRow).GetCell(nCurCell).GetContent(); if (true === this.ApplyToAll || (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type)) { oCellContent.SetApplyToAll(true); oCellContent.GetCurrentParagraph(false, arrSelectedParagraphs, oPr); oCellContent.SetApplyToAll(false); } else { oCellContent.GetCurrentParagraph(false, arrSelectedParagraphs, oPr); } } return arrSelectedParagraphs; } else if (true === bIgnoreSelection) { if (this.CurCell) return this.CurCell.Content.GetCurrentParagraph(bIgnoreSelection, null, oPr); else return null; } else { let selectionArray = this.GetSelectionArray(); if (selectionArray.length <= 0) return null; let pos = 0; if (true !== bIgnoreSelection && oPr) { if (oPr.FirstInSelection) pos = 0; else if (oPr.LastInSelection) pos = selectionArray.length - 1; } var nCurCell = selectionArray[pos].Cell; var nCurRow = selectionArray[pos].Row; var oCellContent = this.GetRow(nCurRow).GetCell(nCurCell).GetContent(); if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { oCellContent.SetApplyToAll(true); var oRes = oCellContent.GetCurrentParagraph(bIgnoreSelection, null, oPr); oCellContent.SetApplyToAll(false); return oRes; } else { return oCellContent.GetCurrentParagraph(bIgnoreSelection, null, oPr); } } return null; }; CTable.prototype.GetCurrentTablesStack = function(arrTables) { if (!arrTables) arrTables = []; arrTables.push(this); if (true !== this.Selection.Use || table_Selection_Text === this.Selection.Type) return this.CurCell.GetContent().GetCurrentTablesStack(arrTables); return arrTables; }; CTable.prototype.SetImageProps = function(Props) { if ((true === this.Selection.Use && table_Selection_Text === this.Selection.Type) || false === this.Selection.Use) { return this.CurCell.Content.SetImageProps(Props); } }; //---------------------------------------------------------------------------------------------------------------------- // Работаем со стилем таблицы //---------------------------------------------------------------------------------------------------------------------- /** * Сообщаем таблице, что ей надо будет пересчитать скомпилированный стиль * (Такое может случится, если у данной таблицы задан стиль, * который меняется каким-то внешним образом) * */ CTable.prototype.Recalc_CompiledPr = function() { this.CompiledPr.NeedRecalc = true; this.RecalcInfo.RecalcBorders(); }; CTable.prototype.Recalc_CompiledPr2 = function() { this.Recalc_CompiledPr(); var RowsCount = this.Content.length; for (var CurRow = 0; CurRow < RowsCount; CurRow++) { var Row = this.Content[CurRow]; Row.Recalc_CompiledPr(); var CellsCount = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var Cell = Row.Get_Cell(CurCell); Cell.Recalc_CompiledPr(); } } }; /** * Формируем конечные свойства параграфа на основе стиля и прямых настроек. */ CTable.prototype.Get_CompiledPr = function(bCopy) { let forceCompile = false; if (true === AscCommon.g_oIdCounter.m_bLoad || true === AscCommon.g_oIdCounter.m_bRead) { let logicDocument = this.GetLogicDocument(); if (logicDocument && logicDocument.IsDocumentEditor() && logicDocument.CompileStyleOnLoad) forceCompile = true; } if (true === this.CompiledPr.NeedRecalc) { if ((!forceCompile && (true === AscCommon.g_oIdCounter.m_bLoad || true === AscCommon.g_oIdCounter.m_bRead)) || !this.Parent) { this.CompiledPr.Pr = { TextPr : g_oDocumentDefaultTextPr, ParaPr : g_oDocumentDefaultParaPr, TablePr : g_oDocumentDefaultTablePr, TableRowPr : g_oDocumentDefaultTableRowPr, TableCellPr : g_oDocumentDefaultTableCellPr, TableFirstCol : g_oDocumentDefaultTableStylePr, TableFirstRow : g_oDocumentDefaultTableStylePr, TableLastCol : g_oDocumentDefaultTableStylePr, TableLastRow : g_oDocumentDefaultTableStylePr, TableBand1Horz : g_oDocumentDefaultTableStylePr, TableBand1Vert : g_oDocumentDefaultTableStylePr, TableBand2Horz : g_oDocumentDefaultTableStylePr, TableBand2Vert : g_oDocumentDefaultTableStylePr, TableTLCell : g_oDocumentDefaultTableStylePr, TableTRCell : g_oDocumentDefaultTableStylePr, TableBLCell : g_oDocumentDefaultTableStylePr, TableBRCell : g_oDocumentDefaultTableStylePr, TableWholeTable : g_oDocumentDefaultTableStylePr }; this.CompiledPr.NeedRecalc = true; } else { this.CompiledPr.Pr = this.Internal_Compile_Pr(); this.CompiledPr.NeedRecalc = forceCompile; } } if (false === bCopy) return this.CompiledPr.Pr; else { var Pr = {}; Pr.TextPr = this.CompiledPr.Pr.TextPr.Copy(); Pr.ParaPr = this.CompiledPr.Pr.ParaPr.Copy(); Pr.TablePr = this.CompiledPr.Pr.TablePr.Copy(); Pr.TableRowPr = this.CompiledPr.Pr.TableRowPr.Copy(); Pr.TableCellPr = this.CompiledPr.Pr.TableCellPr.Copy(); Pr.TableFirstCol = this.CompiledPr.Pr.TableFirstCol.Copy(); Pr.TableFirstRow = this.CompiledPr.Pr.TableFirstRow.Copy(); Pr.TableLastCol = this.CompiledPr.Pr.TableLastCol.Copy(); Pr.TableLastRow = this.CompiledPr.Pr.TableLastRow.Copy(); Pr.TableBand1Horz = this.CompiledPr.Pr.TableBand1Horz.Copy(); Pr.TableBand1Vert = this.CompiledPr.Pr.TableBand1Vert.Copy(); Pr.TableBand2Horz = this.CompiledPr.Pr.TableBand2Horz.Copy(); Pr.TableBand2Vert = this.CompiledPr.Pr.TableBand2Vert.Copy(); Pr.TableTLCell = this.CompiledPr.Pr.TableTLCell.Copy(); Pr.TableTRCell = this.CompiledPr.Pr.TableTRCell.Copy(); Pr.TableBLCell = this.CompiledPr.Pr.TableBLCell.Copy(); Pr.TableBRCell = this.CompiledPr.Pr.TableBRCell.Copy(); Pr.TableWholeTable = this.CompiledPr.Pr.TableWholeTable.Copy(); return Pr; // Отдаем копию объекта, чтобы никто не поменял извне настройки стиля } }; CTable.prototype.Get_Style = function() { if ("undefined" != typeof(this.TableStyle)) return this.TableStyle; return null; }; CTable.prototype.Set_Style = function(Id) { this.Style_Remove(); if (null === Id) return; // Если стиль является стилем по умолчанию для таблицы, тогда не надо его записывать. if (Id != this.Get_Styles().Get_Default_Table()) this.TableStyle = Id; // Надо пересчитать конечный стиль this.CompiledPr.NeedRecalc = true; }; CTable.prototype.Remove_Style = function() { if ("undefined" != typeof(this.TableStyle)) delete this.TableStyle; // Надо пересчитать конечный стиль this.CompiledPr.NeedRecalc = true; }; /** * Формируем конечные свойства таблицы на основе стиля и прямых настроек. */ CTable.prototype.Internal_Compile_Pr = function() { var Styles = this.Get_Styles(); var StyleId = this.Get_Style(); // Считываем свойства для текущего стиля var Pr = Styles.Get_Pr(StyleId, styletype_Table); if (this.bPresentation) { this.Check_PresentationPr(Pr); } // Копируем прямые настройки параграфа. Pr.TablePr.Merge(this.Pr); let logicDocument = this.GetLogicDocument(); if (logicDocument && logicDocument.IsDocumentEditor()) Pr.TablePr.TableInd = logicDocument.Layout.calculateIndent(Pr.TablePr.TableInd, this); return Pr; }; CTable.prototype.Check_PresentationPr = function(Pr) { var Theme = this.Get_Theme(); Pr.TablePr.Check_PresentationPr(Theme); Pr.TextPr.Check_PresentationPr(Theme); Pr.TableCellPr.Check_PresentationPr(Theme); Pr.TableFirstCol.Check_PresentationPr(Theme); Pr.TableFirstRow.Check_PresentationPr(Theme); Pr.TableLastCol.Check_PresentationPr(Theme); Pr.TableLastRow.Check_PresentationPr(Theme); Pr.TableBand1Horz.Check_PresentationPr(Theme); Pr.TableBand1Vert.Check_PresentationPr(Theme); Pr.TableBand2Horz.Check_PresentationPr(Theme); Pr.TableBand2Vert.Check_PresentationPr(Theme); Pr.TableTLCell.Check_PresentationPr(Theme); Pr.TableTRCell.Check_PresentationPr(Theme); Pr.TableBLCell.Check_PresentationPr(Theme); Pr.TableBRCell.Check_PresentationPr(Theme); }; //---------------------------------------------------------------------------------------------------------------------- // Устанавливаем прямые настройки таблицы //---------------------------------------------------------------------------------------------------------------------- CTable.prototype.Clear_DirectFormatting = function(bClearMerge) { // Очищаем все прямые настройки таблицы, всех ее строк и всех ее ячеек this.Set_TableStyleRowBandSize(undefined); this.Set_TableStyleColBandSize(undefined); this.Set_TableAlign(undefined); this.Set_TableShd(undefined); this.Set_TableBorder_Bottom(undefined); this.Set_TableBorder_Left(undefined); this.Set_TableBorder_Right(undefined); this.Set_TableBorder_Top(undefined); this.Set_TableBorder_InsideV(undefined); this.Set_TableBorder_InsideH(undefined); this.Set_TableCellMar(undefined, undefined, undefined, undefined); this.Set_TableInd(undefined); if (false !== bClearMerge) this.Set_TableW(undefined, undefined); var Count = this.Content.length; for (var Index = 0; Index < Count; Index++) { this.Content[Index].Clear_DirectFormatting(bClearMerge); } }; CTable.prototype.Set_Pr = function(TablePr) { var isHavePrChange = this.HavePrChange(); this.private_AddPrChange(); AscCommon.History.Add(new CChangesTablePr(this, this.Pr, TablePr)); this.Pr = TablePr; this.Recalc_CompiledPr2(); this.private_UpdateTableGrid(); if (isHavePrChange || this.HavePrChange()) this.updateTrackRevisions(); }; CTable.prototype.SetPr = function(oTablePr) { this.Set_Pr(oTablePr); }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // TODO: Заменять вызовы Set_TableStyle функции на SetTableStyle и доп обработку, если нужно // Set_TableStyle2 нужно убрать вообще //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CTable.prototype.Set_TableStyle = function(StyleId, bNoClearFormatting) { // Здесь мы не проверяем изменился ли стиль, потому что при выставлении стиля нужно сбрасывать // прямые настройки, даже если мы выставляем тот же самый стиль. AscCommon.History.Add(new CChangesTableTableStyle(this, this.TableStyle, StyleId)); this.TableStyle = StyleId; // Очищаем все прямое форматирование таблицы if (!(bNoClearFormatting === true)) { this.Clear_DirectFormatting(false); } this.Recalc_CompiledPr2(); }; CTable.prototype.Set_TableStyle2 = function(StyleId) { this.SetTableStyle(StyleId); }; CTable.prototype.SetTableStyle = function(styleId) { if (this.TableStyle === styleId) return; AscCommon.History.Add(new CChangesTableTableStyle(this, this.TableStyle, styleId)); this.TableStyle = styleId; this.Recalc_CompiledPr2(); }; CTable.prototype.Get_TableStyle = function() { return this.TableStyle; }; CTable.prototype.GetTableStyle = function() { return this.Get_TableStyle(); }; CTable.prototype.Set_TableLook = function(TableLook) { AscCommon.History.Add(new CChangesTableTableLook(this, this.TableLook, TableLook)); this.TableLook = TableLook; this.Recalc_CompiledPr2(); }; CTable.prototype.Get_TableLook = function() { return this.TableLook; }; CTable.prototype.setAllowOverlap = function(isAllow) { this.Set_AllowOverlap(isAllow); }; CTable.prototype.Set_AllowOverlap = function(AllowOverlap) { AscCommon.History.Add(new CChangesTableAllowOverlap(this, this.AllowOverlap, AllowOverlap)); this.AllowOverlap = AllowOverlap; }; CTable.prototype.Get_AllowOverlap = function() { return this.AllowOverlap; }; CTable.prototype.Set_PositionH = function(RelativeFrom, Align, Value) { AscCommon.History.Add(new CChangesTablePositionH(this, { RelativeFrom : this.PositionH.RelativeFrom, Align : this.PositionH.Align, Value : this.PositionH.Value }, { RelativeFrom : RelativeFrom, Align : Align, Value : Value })); this.PositionH.RelativeFrom = RelativeFrom; this.PositionH.Align = Align; this.PositionH.Value = Value; }; CTable.prototype.SetPositionH = function(relativeFrom, align, value) { return this.Set_PositionH(relativeFrom, align, value); }; CTable.prototype.GetPositionH = function() { return this.PositionH; }; CTable.prototype.Get_PositionHValueInTwips = function() { var res; if(this.PositionH && null !== this.PositionH.Value && undefined !== this.PositionH.Value) { res = Math.round(AscCommonWord.g_dKoef_mm_to_twips * this.PositionH.Value); //0 is a special value(left align) if (0 === res) { res = 1; } } return res; }; CTable.prototype.Set_PositionV = function(RelativeFrom, Align, Value) { AscCommon.History.Add(new CChangesTablePositionV(this, { RelativeFrom : this.PositionV.RelativeFrom, Align : this.PositionV.Align, Value : this.PositionV.Value }, { RelativeFrom : RelativeFrom, Align : Align, Value : Value })); this.PositionV.RelativeFrom = RelativeFrom; this.PositionV.Align = Align; this.PositionV.Value = Value; }; CTable.prototype.SetPositionV = function(relativeFrom, align, value) { return this.Set_PositionV(relativeFrom, align, value); }; CTable.prototype.GetPositionV = function() { return this.PositionV; }; CTable.prototype.Get_PositionVValueInTwips = function() { var res; if(this.PositionV && null !== this.PositionV.Value && undefined !== this.PositionV.Value) { res = Math.round(AscCommonWord.g_dKoef_mm_to_twips * this.PositionV.Value); //0 is a special value(c_oAscVAnchor.Text) if (0 === res) { res = 1; } } return res; }; CTable.prototype.Set_Distance = function(L, T, R, B) { if (null === L || undefined === L) L = this.Distance.L; if (null === T || undefined === T) T = this.Distance.T; if (null === R || undefined === R) R = this.Distance.R; if (null === B || undefined === B) B = this.Distance.B; AscCommon.History.Add(new CChangesTableDistance(this, { Left : this.Distance.L, Top : this.Distance.T, Right : this.Distance.R, Bottom : this.Distance.B }, { Left : L, Top : T, Right : R, Bottom : B })); this.Distance.L = L; this.Distance.R = R; this.Distance.T = T; this.Distance.B = B; }; CTable.prototype.Set_TableStyleRowBandSize = function(Value) { if (this.Pr.TableStyleRowBandSize === Value) return; this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableStyleRowBandSize(this, this.Pr.TableStyleRowBandSize, Value)); this.Pr.TableStyleRowBandSize = Value; this.Recalc_CompiledPr(); }; CTable.prototype.Get_TableStyleRowBandSize = function() { var Pr = this.Get_CompiledPr(false).TablePr; return Pr.TableStyleRowBandSize; }; CTable.prototype.Set_TableStyleColBandSize = function(Value) { if (this.Pr.TableStyleColBandSize === Value) return; this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableStyleColBandSize(this, this.Pr.TableStyleColBandSize, Value)); this.Pr.TableStyleColBandSize = Value; this.Recalc_CompiledPr(); }; CTable.prototype.Get_TableStyleColBandSize = function() { var Pr = this.Get_CompiledPr(false).TablePr; return Pr.TableStyleColBandSize; }; CTable.prototype.Get_ShapeStyleForPara = function() { return this.Parent ? this.Parent.Get_ShapeStyleForPara() : null; }; CTable.prototype.Set_TableW = function(Type, W) { if (undefined === Type) { if (undefined === this.Pr.TableW) return; this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableW(this, this.Pr.TableW, undefined)); this.Pr.TableW = undefined; this.Recalc_CompiledPr(); this.private_UpdateTableGrid(); } else if (undefined === this.Pr.TableW) { this.private_AddPrChange(); var TableW = new CTableMeasurement(Type, W); AscCommon.History.Add(new CChangesTableTableW(this, undefined, TableW)); this.Pr.TableW = TableW; this.Recalc_CompiledPr(); this.private_UpdateTableGrid(); } else if (Type != this.Pr.TableW.Type || Math.abs(this.Pr.TableW.W - W) > 0.001) { this.private_AddPrChange(); var TableW = new CTableMeasurement(Type, W); AscCommon.History.Add(new CChangesTableTableW(this, this.Pr.TableW, TableW)); this.Pr.TableW = TableW; this.Recalc_CompiledPr(); this.private_UpdateTableGrid(); } }; CTable.prototype.Get_TableW = function() { var Pr = this.Get_CompiledPr(false).TablePr; return Pr.TableW; }; /** * Задаем предпочитаемую ширину таблицы * @param nType * @param nW */ CTable.prototype.SetTableW = function(nType, nW) { this.Set_TableW(nType, nW); }; /** * Получаем предпочитаемую ширину таблицы * @returns {CTableMeasurement} */ CTable.prototype.GetTableW = function() { return this.Get_TableW(); }; CTable.prototype.SetTableLayout = function(Value) { if (this.Pr.TableLayout === Value) return; this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableLayout(this, this.Pr.TableLayout, Value)); this.Pr.TableLayout = Value; this.Recalc_CompiledPr(); }; CTable.prototype.GetTableLayout = function() { var Pr = this.Get_CompiledPr(false).TablePr; return Pr.TableLayout; }; CTable.prototype.Set_TableCellMar = function(Left, Top, Right, Bottom) { var old_Left = ( undefined === this.Pr.TableCellMar.Left ? undefined : this.Pr.TableCellMar.Left ); var old_Right = ( undefined === this.Pr.TableCellMar.Right ? undefined : this.Pr.TableCellMar.Right ); var old_Top = ( undefined === this.Pr.TableCellMar.Top ? undefined : this.Pr.TableCellMar.Top ); var old_Bottom = ( undefined === this.Pr.TableCellMar.Bottom ? undefined : this.Pr.TableCellMar.Bottom ); var new_Left = ( undefined === Left ? undefined : new CTableMeasurement(tblwidth_Mm, Left) ); var new_Right = ( undefined === Right ? undefined : new CTableMeasurement(tblwidth_Mm, Right) ); var new_Top = ( undefined === Top ? undefined : new CTableMeasurement(tblwidth_Mm, Top) ); var new_Bottom = ( undefined === Bottom ? undefined : new CTableMeasurement(tblwidth_Mm, Bottom) ); this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableCellMar(this, { Left : old_Left, Right : old_Right, Top : old_Top, Bottom : old_Bottom }, { Left : new_Left, Right : new_Right, Top : new_Top, Bottom : new_Bottom }) ); this.Pr.TableCellMar.Left = new_Left; this.Pr.TableCellMar.Right = new_Right; this.Pr.TableCellMar.Top = new_Top; this.Pr.TableCellMar.Bottom = new_Bottom; this.Recalc_CompiledPr(); this.private_UpdateTableGrid(); }; CTable.prototype.Get_TableCellMar = function() { var Pr = this.Get_CompiledPr(false).TablePr; return Pr.TableCellMar; }; CTable.prototype.Set_TableAlign = function(Align) { if (undefined === Align) { if (undefined === this.Pr.Jc) return; this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableAlign(this, this.Pr.Jc, undefined)); this.Pr.Jc = undefined; this.Recalc_CompiledPr(); } else if (undefined === this.Pr.Jc) { this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableAlign(this, undefined, Align)); this.Pr.Jc = Align; this.Recalc_CompiledPr(); } else if (Align != this.Pr.Jc) { this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableAlign(this, this.Pr.Jc, Align)); this.Pr.Jc = Align; this.Recalc_CompiledPr(); } }; CTable.prototype.Get_TableAlign = function() { var Pr = this.Get_CompiledPr(false).TablePr; return Pr.Jc; }; CTable.prototype.Set_TableInd = function(Ind) { if (undefined === Ind) { if (undefined === this.Pr.TableInd) return; this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableInd(this, this.Pr.TableInd, undefined)); this.Pr.TableInd = undefined; this.Recalc_CompiledPr(); } else if (undefined === this.Pr.TableInd) { this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableInd(this, undefined, Ind)); this.Pr.TableInd = Ind; this.Recalc_CompiledPr(); } else if (Math.abs(this.Pr.TableInd - Ind) > 0.001) { this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableInd(this, this.Pr.TableInd, Ind)); this.Pr.TableInd = Ind; this.Recalc_CompiledPr(); } }; CTable.prototype.Get_TableInd = function() { var Pr = this.Get_CompiledPr(false).TablePr; return Pr.TableInd; }; CTable.prototype.Set_TableBorder_Left = function(Border) { if (undefined === this.Pr.TableBorders.Left && undefined === Border) return; var _Border = Border; if (undefined !== _Border) { _Border = new CDocumentBorder(); _Border.Set_FromObject(Border); } this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableBorderLeft(this, this.Pr.TableBorders.Left, _Border)); this.Pr.TableBorders.Left = _Border; this.Recalc_CompiledPr(); }; CTable.prototype.Set_TableBorder_Right = function(Border) { if (undefined === this.Pr.TableBorders.Right && undefined === Border) return; var _Border = Border; if (undefined !== _Border) { _Border = new CDocumentBorder(); _Border.Set_FromObject(Border); } this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableBorderRight(this, this.Pr.TableBorders.Right, _Border)); this.Pr.TableBorders.Right = _Border; this.Recalc_CompiledPr(); }; CTable.prototype.Set_TableBorder_Top = function(Border) { if (undefined === this.Pr.TableBorders.Top && undefined === Border) return; var _Border = Border; if (undefined !== _Border) { _Border = new CDocumentBorder(); _Border.Set_FromObject(Border); } this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableBorderTop(this, this.Pr.TableBorders.Top, _Border)); this.Pr.TableBorders.Top = _Border; this.Recalc_CompiledPr(); }; CTable.prototype.Set_TableBorder_Bottom = function(Border) { if (undefined === this.Pr.TableBorders.Bottom && undefined === Border) return; var _Border = Border; if (undefined !== _Border) { _Border = new CDocumentBorder(); _Border.Set_FromObject(Border); } this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableBorderBottom(this, this.Pr.TableBorders.Bottom, _Border)); this.Pr.TableBorders.Bottom = _Border; this.Recalc_CompiledPr(); }; CTable.prototype.Set_TableBorder_InsideH = function(Border) { if (undefined === this.Pr.TableBorders.InsideH && undefined === Border) return; var _Border = Border; if (undefined !== _Border) { _Border = new CDocumentBorder(); _Border.Set_FromObject(Border); } this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableBorderInsideH(this, this.Pr.TableBorders.InsideH, _Border)); this.Pr.TableBorders.InsideH = _Border; this.Recalc_CompiledPr(); }; CTable.prototype.Set_TableBorder_InsideV = function(Border) { if (undefined === this.Pr.TableBorders.InsideV && undefined === Border) return; var _Border = Border; if (undefined !== _Border) { _Border = new CDocumentBorder(); _Border.Set_FromObject(Border); } this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableBorderInsideV(this, this.Pr.TableBorders.InsideV, _Border)); this.Pr.TableBorders.InsideV = _Border; this.Recalc_CompiledPr(); }; CTable.prototype.Get_TableBorders = function() { var Pr = this.Get_CompiledPr(false).TablePr; return Pr.TableBorders; }; CTable.prototype.GetTopTableBorder = function() { return this.Get_CompiledPr(false).TablePr.TableBorders.Top; }; CTable.prototype.GetBottomTableBorder = function() { return this.Get_CompiledPr(false).TablePr.TableBorders.Bottom; }; CTable.prototype.Set_TableShd = function(Value, r, g, b) { if (undefined === Value && undefined === this.Pr.Shd) return; var _Shd = undefined; if (undefined !== Value) { _Shd = new CDocumentShd(); _Shd.Value = Value; _Shd.Color = new CDocumentColor(r, g, b); _Shd.Fill = new CDocumentColor(r, g, b); } this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableShd(this, this.Pr.Shd, _Shd)); this.Pr.Shd = _Shd; this.Recalc_CompiledPr(); }; CTable.prototype.Get_Shd = function() { var Pr = this.Get_CompiledPr(false).TablePr; return Pr.Shd; }; CTable.prototype.Get_Borders = function() { return this.Get_TableBorders(); }; CTable.prototype.Set_TableDescription = function(sDescription) { this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableDescription(this, this.Pr.TableDescription, sDescription)); this.Pr.TableDescription = sDescription; this.Recalc_CompiledPr(); }; CTable.prototype.Get_TableDescription = function() { var Pr = this.Get_CompiledPr(false).TablePr; return Pr.TableDescription; }; CTable.prototype.Set_TableCaption = function(sCaption) { this.private_AddPrChange(); AscCommon.History.Add(new CChangesTableTableCaption(this, this.Pr.TableCaption, sCaption)); this.Pr.TableCaption = sCaption; this.Recalc_CompiledPr(); }; CTable.prototype.Get_TableCaption = function() { var Pr = this.Get_CompiledPr(false).TablePr; return Pr.TableCaption; }; //---------------------------------------------------------------------------------------------------------------------- // Работаем с сеткой таблицы //---------------------------------------------------------------------------------------------------------------------- CTable.prototype.Split = function() { // Пока данная функция используется только при добавлении секции. В этом случае мы делим таблицу на 2 части по // текущей строке. Если текущая строка первая, тогда не делим таблицу. var CurRow = this.CurCell.Row.Index; if (0 === CurRow) return null; var NewTable = new CTable(this.DrawingDocument, this.Parent, this.Inline, 0, 0, this.private_CopyTableGrid()); var Len = this.Content.length; for (var RowIndex = CurRow; RowIndex < Len; RowIndex++) { NewTable.private_AddRow(RowIndex - CurRow, 0, false, this.Content[CurRow]); this.private_RemoveRow(CurRow); } NewTable.ReIndexing(0); this.ReIndexing(0); NewTable.SetPr(this.Pr.Copy()); NewTable.Set_TableStyle2(this.TableStyle); NewTable.Set_TableLook(this.TableLook.Copy()); // Сбросим селект и текущую позицию в таблицах this.MoveCursorToStartPos(false); NewTable.MoveCursorToStartPos(false); return NewTable; }; CTable.prototype.Internal_CheckMerge = function() { var bCanMerge = true; var Grid_start = -1; var Grid_end = -1; var RowsInfo = []; var nRowMin = -1; var nRowMax = -1; for (var Index = 0; Index < this.Selection.Data.length; Index++) { var Pos = this.Selection.Data[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.GetCell(Pos.Cell); var CellInfo = Row.GetCellInfo(Pos.Cell); var StartGridCol = CellInfo.StartGridCol; var EndGridCol = StartGridCol + Cell.GetGridSpan() - 1; var VMergeCount = this.Internal_GetVertMergeCount(Pos.Row, CellInfo.StartGridCol, Cell.GetGridSpan()); for (var RowIndex = Pos.Row; RowIndex <= Pos.Row + VMergeCount - 1; RowIndex++) { if ("undefined" === typeof(RowsInfo[RowIndex])) { RowsInfo[RowIndex] = { Grid_start : StartGridCol, Grid_end : EndGridCol }; if (-1 === nRowMax || RowIndex > nRowMax) nRowMax = RowIndex; if (-1 === nRowMin || RowIndex < nRowMin) nRowMin = RowIndex; } else { if (StartGridCol < RowsInfo[RowIndex].Grid_start) RowsInfo[RowIndex].Grid_start = StartGridCol; if (EndGridCol > RowsInfo[RowIndex].Grid_end) RowsInfo[RowIndex].Grid_end = EndGridCol; } } } // Проверим, что селект строк идет без пропусков for (var nRowIndex = nRowMin; nRowIndex <= nRowMax; ++nRowIndex) { if (!RowsInfo[nRowIndex]) { bCanMerge = false; break; } } for (var Index in RowsInfo) { if (-1 === Grid_start) Grid_start = RowsInfo[Index].Grid_start; else if (Grid_start != RowsInfo[Index].Grid_start) { bCanMerge = false; break; } if (-1 === Grid_end) Grid_end = RowsInfo[Index].Grid_end; else if (Grid_end != RowsInfo[Index].Grid_end) { bCanMerge = false; break; } } if (true === bCanMerge) { // Далее, мы должны убедиться, что у выеделенных ячеек верхние и нижние поля также // ровные (т.е. без выступов). // Для этого для каждой колонки, попавшей в отрезок [Grid_start, Grid_end] находим // верхнюю и нижнюю ячейку и смотрим на верхнюю и нижнюю строки данных ячеек, // соответственно var TopRow = -1; var BotRow = -1; for (var GridIndex = Grid_start; GridIndex <= Grid_end; GridIndex++) { var Pos_top = null; var Pos_bot = null; for (var Index = 0; Index < this.Selection.Data.length; Index++) { var Pos = this.Selection.Data[Index]; var Row = this.Content[Pos.Row]; var Cell = Row.Get_Cell(Pos.Cell); var StartGridCol = Row.Get_CellInfo(Pos.Cell).StartGridCol; var EndGridCol = StartGridCol + Cell.Get_GridSpan() - 1; if (GridIndex >= StartGridCol && GridIndex <= EndGridCol) { if (null === Pos_top || Pos_top.Row > Pos.Row) Pos_top = Pos; if (null === Pos_bot || Pos_bot.Row < Pos.Row) Pos_bot = Pos; } } if (null === Pos_top || null === Pos_bot) { bCanMerge = false; break; } if (-1 === TopRow) TopRow = Pos_top.Row; else if (TopRow != Pos_top.Row) { bCanMerge = false; break; } var Row = this.Content[Pos_bot.Row]; var Cell = Row.Get_Cell(Pos_bot.Cell); var VMergeCount = this.Internal_GetVertMergeCount(Pos_bot.Row, Row.Get_CellInfo(Pos_bot.Cell).StartGridCol, Cell.Get_GridSpan()); var CurBotRow = Pos_bot.Row + VMergeCount - 1; if (-1 === BotRow) BotRow = CurBotRow; else if (BotRow != CurBotRow) { bCanMerge = false; break; } } // Объединенные ячейки образуют прямоугольник, но возможно в нем есть вырезы, // т.е. выделение такое, что в него попала строка с GridBefore или GridAfter > 0 if (true === bCanMerge) { for (var RowIndex = TopRow; RowIndex <= BotRow; RowIndex++) { var Row = this.Content[RowIndex]; var Grid_before = Row.Get_Before().GridBefore; var Grid_after = Row.Get_After().GridAfter; if (Grid_after <= 0 && Grid_before <= 0) continue; if (Grid_start < Grid_before) { bCanMerge = false; break; } var Cell = Row.Get_Cell(Row.Get_CellsCount() - 1); var Row_grid_end = Cell.Get_GridSpan() - 1 + Row.Get_CellInfo(Row.Get_CellsCount() - 1).StartGridCol; if (Grid_end > Row_grid_end) { bCanMerge = false; break; } } } } return {Grid_start : Grid_start, Grid_end : Grid_end, RowsInfo : RowsInfo, bCanMerge : bCanMerge}; }; /** * Объединяем выделенные ячейки таблицы. * @param isClearMerge - используем или нет рассчетные данные (true - не используем, false - default value) */ CTable.prototype.MergeTableCells = function(isClearMerge) { var bApplyToInnerTable = false; if (false === this.Selection.Use || ( true === this.Selection.Use && table_Selection_Text === this.Selection.Type )) bApplyToInnerTable = this.CurCell.Content.MergeTableCells(); if (true === bApplyToInnerTable) return false; if (true !== this.Selection.Use || table_Selection_Cell !== this.Selection.Type || this.Selection.Data.length <= 1) return false; // В массиве this.Selection.Data идет список ячеек по строкам (без разрывов) // Перед объединением мы должны проверить совпадают ли начальная и конечная колонки // в сетке TableGrid для каждого ряда. var Temp = this.Internal_CheckMerge(); var bCanMerge = Temp.bCanMerge; var Grid_start = Temp.Grid_start; var Grid_end = Temp.Grid_end; var RowsInfo = Temp.RowsInfo; if (false === bCanMerge) return false; var oLogicDocument = this.GetLogicDocument(); if (oLogicDocument && !oLogicDocument.IsDocumentEditor()) oLogicDocument = undefined; // Объединяем содержимое всех ячеек в левую верхнюю ячейку. (Все выделенные // ячейки идут у нас последовательно, начиная с левой верхней), и объединяем // сами ячейки. var Pos_tl = this.Selection.Data[0]; var Cell_tl = this.GetRow(Pos_tl.Row).GetCell(Pos_tl.Cell); // Добавляем содержимое данной ячейки к содержимому левой верхней ячейки // Комментарии сохраняем, т.к. метка начала комментария при этом перенесится только еще в более раннюю // позицию, поэтому нарушения логики быть не должно // TODO: Возможно стоить обновление позиций комментариев запихнуть внутрь CDocumentContent.AddContent var isRemoveComments = null; if (oLogicDocument) { isRemoveComments = oLogicDocument.RemoveCommentsOnPreDelete; oLogicDocument.RemoveCommentsOnPreDelete = false; } var oMainCellContent = Cell_tl.GetContent(); var arrMovedComments = []; for (var nIndex = 1; nIndex < this.Selection.Data.length; ++nIndex) { var oPos = this.Selection.Data[nIndex]; var oCellContent = this.GetRow(oPos.Row).GetCell(oPos.Cell).GetContent(); oCellContent.GetAllComments(arrMovedComments); oMainCellContent.AddContent(oCellContent.Content); oCellContent.ClearContent(); } if (oLogicDocument) { var oCommentsManager = oLogicDocument.GetCommentsManager(); for (var nIndex = 0, nCount = arrMovedComments.length; nIndex < nCount; ++nIndex) { var oCommentMark = arrMovedComments[nIndex].Comment; var oComment = oCommentsManager.GetById(oCommentMark.GetCommentId()); if (oComment) oComment.UpdatePosition(); } oLogicDocument.RemoveCommentsOnPreDelete = isRemoveComments; } if (true !== isClearMerge) { // Выставим ширину результируещей ячейки var SumW = 0; for (var CurGridCol = Grid_start; CurGridCol <= Grid_end; CurGridCol++) { SumW += this.TableGridCalc[CurGridCol]; } Cell_tl.Set_W(new CTableMeasurement(tblwidth_Mm, SumW)); } // Теперь нам надо удалить лишние ячейки и добавить ячейки с // вертикальным объединением. for (var RowIndex in RowsInfo) { var Row = this.Content[RowIndex]; for (var CellIndex = 0; CellIndex < Row.Get_CellsCount(); CellIndex++) { var Cell_grid_start = Row.Get_CellInfo(CellIndex).StartGridCol; if (Grid_start === Cell_grid_start) { if (RowIndex != Pos_tl.Row) { var Cell = Row.Get_Cell(CellIndex); Cell.Set_GridSpan(Grid_end - Grid_start + 1); Cell.SetVMerge(vmerge_Continue); } else { Cell_tl.Set_GridSpan(Grid_end - Grid_start + 1); } } else if (Cell_grid_start > Grid_start && Cell_grid_start <= Grid_end) { Row.Remove_Cell(CellIndex); CellIndex--; } else if (Cell_grid_start > Grid_end) break; } } // Удаляем лишние строки this.CorrectTableRows(true !== isClearMerge ? true : false); for (var PageNum = 0; PageNum < this.Pages.length - 1; PageNum++) { if (Pos_tl.Row <= this.Pages[PageNum + 1].FirstRow) break; } // Выделяем полученную ячейку this.Selection.Use = true; this.Selection.StartPos.Pos = Pos_tl; this.Selection.EndPos.Pos = Pos_tl; this.Selection.Type = table_Selection_Cell; this.private_SetSelectionData([Pos_tl]); this.CurCell = Cell_tl; this.CurCell.GetContent().SelectAll(); return true; }; /** * Разделяем текущую ячейку * @param Cols {number} * @param Rows {number} * @param [isFailureEvents=true] {boolean} * @returns {boolean} */ CTable.prototype.SplitTableCells = function(Cols, Rows, isFailureEvents) { var bApplyToInnerTable = false; if (false === this.Selection.Use || ( true === this.Selection.Use && table_Selection_Text === this.Selection.Type )) bApplyToInnerTable = this.CurCell.Content.SplitTableCells(Cols, Rows); if (true === bApplyToInnerTable) return true; // Разделение ячейки работает, только если выделена ровно одна ячейка. if (!( false === this.Selection.Use || ( true === this.Selection.Use && ( table_Selection_Text === this.Selection.Type || ( table_Selection_Cell === this.Selection.Type && 1 === this.Selection.Data.length ) ) ) )) return false; var Cell_pos = null; var Cell = null; if (false === this.Selection.Use || ( true === this.Selection.Use && table_Selection_Text === this.Selection.Type )) { Cell = this.CurCell; Cell_pos = { Cell : Cell.Index, Row : Cell.Row.Index }; } else { Cell_pos = this.Selection.Data[0]; Cell = this.GetRow(Cell_pos.Row).GetCell(Cell_pos.Cell); } var Row = this.Content[Cell_pos.Row]; var Grid_start = Row.Get_CellInfo(Cell_pos.Cell).StartGridCol; var Grid_span = Cell.Get_GridSpan(); var VMerge_count = this.Internal_GetVertMergeCount(Cell_pos.Row, Grid_start, Grid_span); // Если данная ячейка имеет вертикальное объединение, тогда по вертикали мы // ее разбиваем максимально на VMerge_count частей, если значение Rows превышает // заданное максимально допустимое значение или Rows не является делителем // числа VMerge_count - выдаем ошибку. // Если данная ячейка не учавствует в вертикальном объединении, тогда мы спокойно // можем делить ячейку на любое количество строк. if (VMerge_count > 1) { if (Rows > VMerge_count) { if (false !== isFailureEvents) { // Сообщение об ошибке : "Value Rows must be between 1 and " + VMerge_count var ErrData = new AscCommon.CErrorData(); ErrData.put_Value(VMerge_count); editor.sendEvent("asc_onError", c_oAscError.ID.SplitCellMaxRows, c_oAscError.Level.NoCritical, ErrData); } return false; } else if (0 != VMerge_count % Rows) { if (false !== isFailureEvents) { // Сообщение об ошибке : "Value must be a divisor of the number " + VMerge_count var ErrData = new AscCommon.CErrorData(); ErrData.put_Value(VMerge_count); editor.sendEvent("asc_onError", c_oAscError.ID.SplitCellRowsDivider, c_oAscError.Level.NoCritical, ErrData); } return false; } } // Сделаем оценку макимального количества колонок if (this.IsRecalculated()) { var Sum_before = this.TableSumGrid[Grid_start - 1]; var Sum_with = this.TableSumGrid[Grid_start + Grid_span - 1]; var Span_width = Sum_with - Sum_before; var Grid_width = Span_width / Cols; var CellSpacing = Row.Get_CellSpacing(); var CellMar = Cell.GetMargins(); var MinW = CellSpacing + CellMar.Right.W + CellMar.Left.W; if (Grid_width < MinW) { if (false !== isFailureEvents) { var MaxCols = Math.floor(Span_width / MinW); // Сообщение об ошибке : "Value Cols must be a between 1 and " + MaxCols var ErrData = new AscCommon.CErrorData(); ErrData.put_Value(MaxCols); editor.sendEvent("asc_onError", c_oAscError.ID.SplitCellMaxCols, c_oAscError.Level.NoCritical, ErrData); } return false; } } var Cells = []; var Cells_pos = []; var Rows_ = []; if (Rows <= 1) { for (var Index = 0; Index < VMerge_count; Index++) { var TempRow = this.Content[Cell_pos.Row + Index]; Rows_[Index] = TempRow; Cells[Index] = null; Cells_pos[Index] = null; // Ищем ячейку, начинающуюся с Grid_start var CellsCount = TempRow.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var StartGridCol = TempRow.Get_CellInfo(CurCell).StartGridCol; if (StartGridCol === Grid_start) { Cells[Index] = TempRow.Get_Cell(CurCell); Cells_pos[Index] = {Row : Cell_pos.Row + Index, Cell : CurCell}; } } } } else { if (VMerge_count > 1) { var New_VMerge_Count = VMerge_count / Rows; for (var Index = 0; Index < VMerge_count; Index++) { var TempRow = this.Content[Cell_pos.Row + Index]; Rows_[Index] = TempRow; Cells[Index] = null; Cells_pos[Index] = null; // Ищем ячейку, начинающуюся с Grid_start var CellsCount = TempRow.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var StartGridCol = TempRow.Get_CellInfo(CurCell).StartGridCol; if (StartGridCol === Grid_start) { var TempCell = TempRow.Get_Cell(CurCell); Cells[Index] = TempCell; Cells_pos[Index] = {Row : Cell_pos.Row + Index, Cell : CurCell}; if (0 === Index % New_VMerge_Count) TempCell.SetVMerge(vmerge_Restart); else TempCell.SetVMerge(vmerge_Continue); } } } } else { // Делаем разбиение по вертикали // Нам нужно добавить несколько точных копий текущей строки, только все ячейки, // кроме текущей, должны быть объединены по вертикали. Rows_[0] = Row; Cells[0] = Cell; Cells_pos[0] = Cell_pos; var CellsCount = Row.Get_CellsCount(); for (var Index = 1; Index < Rows; Index++) { var NewRow = this.private_AddRow(Cell_pos.Row + Index, CellsCount); NewRow.Copy_Pr(Row.Pr); Rows_[Index] = NewRow; Cells[Index] = null; Cells_pos[Index] = null; // Копируем настройки всех ячеек исходной строки в новую строку for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var New_Cell = NewRow.Get_Cell(CurCell); var Old_Cell = Row.Get_Cell(CurCell); New_Cell.Copy_Pr(Old_Cell.Pr); New_Cell.CopyParaPrAndTextPr(Old_Cell); if (CurCell === Cell_pos.Cell) { Cells[Index] = New_Cell; Cells_pos[Index] = {Row : Cell_pos.Row + Index, Cell : CurCell}; } else { New_Cell.SetVMerge(vmerge_Continue); } } } } } // Сделаем разбиение по горизонтали if (Cols > 1) { // Найдем позиции новых колонок в сетке var Sum_before = this.TableSumGrid[Grid_start - 1]; var Sum_with = this.TableSumGrid[Grid_start + Grid_span - 1]; var Span_width = Sum_with - Sum_before; var Grid_width = Span_width / Cols; // Данный массив содержит информацию о том сколько новых колонок // было добавлено после i-ой колонки var Grid_Info = []; for (var Index = 0; Index < this.TableGridCalc.length; Index++) Grid_Info[Index] = 0; // Массив содержит информацию о том сколько промежутков будет в // новых ячейках var Grid_Info_new = []; for (var Index = 0; Index < Cols; Index++) Grid_Info_new[Index] = 1; var Grid_Info_start = []; for (var Index = 0; Index < this.TableGridCalc.length; Index++) Grid_Info_start[Index] = this.TableGridCalc[Index]; var NewCol_Index = 0; var CurWidth = Sum_before + Grid_width; for (var Grid_index = Grid_start; Grid_index < Grid_start + Grid_span; Grid_index++) { var bNewCol = true; // Если мы попали в уже имеющуюся границу не добавляем новую точку if (Math.abs(CurWidth - this.TableSumGrid[Grid_index]) < 0.001) { NewCol_Index++; CurWidth += Grid_width; bNewCol = false; continue; } while (CurWidth < this.TableSumGrid[Grid_index]) { if (0 === Grid_Info[Grid_index]) Grid_Info_start[Grid_index] = CurWidth - this.TableSumGrid[Grid_index - 1]; Grid_Info[Grid_index] += 1; NewCol_Index++; CurWidth += Grid_width; // Если мы попали в уже имеющуюся границу не добавляем новую точку if (Math.abs(CurWidth - this.TableSumGrid[Grid_index]) < 0.001) { NewCol_Index++; CurWidth += Grid_width; bNewCol = false; break; } } if (true === bNewCol) Grid_Info_new[NewCol_Index] += 1; } // Добавим в данной строке (Cols - 1) ячеек, с теми же настроками, // что и исходной. Значение GridSpan мы берем из массива Grid_Info_new var oCellW = Cell.GetW().Copy(); if (!oCellW.IsAuto()) oCellW.SetValue(oCellW.GetValue() / Cols); for (var Index2 = 0; Index2 < Rows_.length; Index2++) { if (null != Cells[Index2] && null != Cells_pos[Index2]) { var TempRow = Rows_[Index2]; var TempCell = Cells[Index2]; var TempCell_pos = Cells_pos[Index2]; TempCell.SetGridSpan(Grid_Info_new[0]); TempCell.SetW(oCellW.Copy()); for (var Index = 1; Index < Cols; Index++) { var NewCell = TempRow.Add_Cell(TempCell_pos.Cell + Index, TempRow, null, false); NewCell.Copy_Pr(TempCell.Pr); NewCell.SetGridSpan(Grid_Info_new[Index]); NewCell.SetW(oCellW.Copy()); NewCell.CopyParaPrAndTextPr(TempCell); } } } var OldTableGridLen = this.TableGridCalc.length; var arrNewGrid = this.private_CopyTableGrid(); // Добавим новые колонки в TableGrid // начинаем с конца, чтобы не пересчитывать номера for (var Index = OldTableGridLen - 1; Index >= 0; Index--) { var Summary = this.TableGridCalc[Index]; if (Grid_Info[Index] > 0) { arrNewGrid[Index] = Grid_Info_start[Index]; Summary -= Grid_Info_start[Index] - Grid_width; for (var NewIndex = 0; NewIndex < Grid_Info[Index]; NewIndex++) { Summary -= Grid_width; if (NewIndex != Grid_Info[Index] - 1) arrNewGrid.splice(Index + NewIndex + 1, 0, Grid_width); else arrNewGrid.splice(Index + NewIndex + 1, 0, Summary); } } } this.SetTableGrid(arrNewGrid); // Проходим по всем строкам и изменяем у ячеек GridSpan, в // соответствии со значениями массива Grid_Info for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { if (CurRow >= Cells_pos[0].Row && CurRow <= Cells_pos[Cells_pos.length - 1].Row) continue; var TempRow = this.Content[CurRow]; var GridBefore = TempRow.Get_Before().GridBefore; var GridAfter = TempRow.Get_After().GridAfter; if (GridBefore > 0) { var SummaryGridSpan = GridBefore; for (var CurGrid = 0; CurGrid < GridBefore; CurGrid++) SummaryGridSpan += Grid_Info[CurGrid]; TempRow.Set_Before(SummaryGridSpan); } var LastGrid = 0; for (var CurCell = 0; CurCell < TempRow.Get_CellsCount(); CurCell++) { var TempCell = TempRow.Get_Cell(CurCell); var TempGridSpan = TempCell.Get_GridSpan(); var TempStartGrid = TempRow.Get_CellInfo(CurCell).StartGridCol; var SummaryGridSpan = TempGridSpan; LastGrid = TempStartGrid + TempGridSpan; for (var CurGrid = TempStartGrid; CurGrid < TempStartGrid + TempGridSpan; CurGrid++) SummaryGridSpan += Grid_Info[CurGrid]; TempCell.Set_GridSpan(SummaryGridSpan); } if (GridAfter > 0) { var SummaryGridSpan = GridAfter; for (var CurGrid = LastGrid; CurGrid < OldTableGridLen; CurGrid++) SummaryGridSpan += Grid_Info[CurGrid]; TempRow.Set_After(SummaryGridSpan); } } } this.ReIndexing(); this.Recalc_CompiledPr2(); this.private_RecalculateGrid(); this.Internal_Recalculate_1(); return true; }; /** * Добавление строки. * @param bBefore - true - до(сверху) первой выделенной строки, false - после(снизу) последней выделенной строки. * @param {number} [nCount=undefined] форсированное количество добавляемых строк * @param {boolean} [isCheckInnerTable=true] Выполнять ли данную функцию для внутренней таблицы */ CTable.prototype.AddTableRow = function(bBefore, nCount, isCheckInnerTable) { if ("undefined" === typeof(bBefore)) bBefore = true; var bApplyToInnerTable = false; if (false !== isCheckInnerTable && (false === this.Selection.Use || (true === this.Selection.Use && table_Selection_Text === this.Selection.Type))) bApplyToInnerTable = this.CurCell.Content.AddTableRow(bBefore); if (true === bApplyToInnerTable) return; var Cells_pos = []; // Количество, вставляемых строк зависит от того сколько содержится // строк в выделении. Если вставляем до, тогда копируем верхнюю строку // выделения, а если после, тогда последнюю. var Count = 1; var RowId = 0; if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { Cells_pos = this.Selection.Data; var Prev_row = -1; Count = 0; for (var Index = 0; Index < this.Selection.Data.length; Index++) { if (Prev_row != this.Selection.Data[Index].Row) { Count++; Prev_row = this.Selection.Data[Index].Row; } } } else { Cells_pos[0] = {Row : this.CurCell.Row.Index, Cell : this.CurCell.Index}; Count = 1; } if (null !== nCount && undefined !== nCount && nCount > 0) Count = nCount; if (Cells_pos.length <= 0) return; if (true === bBefore) RowId = Cells_pos[0].Row; else RowId = Cells_pos[Cells_pos.length - 1].Row; var Row = this.Content[RowId]; var CellsCount = Row.Get_CellsCount(); // Сначала пробежимся по строке, которую мы будем копировать, и получим // всю необходимую информацию. var Cells_info = []; for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var Cell = Row.GetCell(CurCell); var Cell_info = Row.Get_CellInfo(CurCell); var Cell_grid_start = Cell_info.StartGridCol; var Cell_grid_span = Cell.Get_GridSpan(); var VMerge_count_before = this.Internal_GetVertMergeCountUp(RowId, Cell_grid_start, Cell_grid_span); var VMerge_count_after = this.Internal_GetVertMergeCount(RowId, Cell_grid_start, Cell_grid_span); Cells_info[CurCell] = { VMerge_count_before : VMerge_count_before, VMerge_count_after : VMerge_count_after }; } // TODO: Пока делаем одинаковый CellSpacing var CellSpacing = this.Content[0].Get_CellSpacing(); for (var Index = 0; Index < Count; Index++) { var New_Row = null; if (true === bBefore) New_Row = this.private_AddRow(RowId, CellsCount, true); else New_Row = this.private_AddRow(RowId + 1, CellsCount, true); New_Row.Copy_Pr(Row.Pr); New_Row.Set_CellSpacing(CellSpacing); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var New_Cell = New_Row.Get_Cell(CurCell); var Old_Cell = Row.Get_Cell(CurCell); New_Cell.Copy_Pr(Old_Cell.Pr); New_Cell.CopyParaPrAndTextPr(Old_Cell); if (true === bBefore) { if (Cells_info[CurCell].VMerge_count_before > 1) New_Cell.SetVMerge(vmerge_Continue); else New_Cell.SetVMerge(vmerge_Restart); } else { if (Cells_info[CurCell].VMerge_count_after > 1) New_Cell.SetVMerge(vmerge_Continue); else New_Cell.SetVMerge(vmerge_Restart); } } } // Выделим новые строки this.Selection.Use = true; this.Selection.Use = true; this.Selection.Type = table_Selection_Cell; var StartRow = ( true === bBefore ? RowId : RowId + 1 ); this.Selection.StartPos.Pos = { Row : StartRow, Cell : 0 }; this.Selection.EndPos.Pos = { Row : StartRow + Count - 1, Cell : this.Content[StartRow + Count - 1].GetCellsCount() - 1 }; var arrSelectionData = []; for (var Index = 0; Index < Count; Index++) { var Row = this.Content[StartRow + Index]; var CellsCount = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var Cell = Row.Get_Cell(CurCell); if (vmerge_Continue === Cell.GetVMerge()) continue; arrSelectionData.push({Row : StartRow + Index, Cell : CurCell}); } } this.private_SetSelectionData(arrSelectionData); this.Recalc_CompiledPr2(); }; /** * Удаление строки либо по номеру Ind, либо по выделению Selection, либо по текущей ячейке. */ CTable.prototype.RemoveTableRow = function(Ind) { var bApplyToInnerTable = false; if (false === this.Selection.Use || ( true === this.Selection.Use && table_Selection_Text === this.Selection.Type )) bApplyToInnerTable = this.CurCell.Content.RemoveTableRow(Ind); if (true === bApplyToInnerTable) return true; var Rows_to_delete = []; if ("undefined" === typeof(Ind) || null === Ind) { if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { var Counter = 0; var PrevRow = -1; for (var Index = 0; Index < this.Selection.Data.length; Index++) { var CurPos = this.Selection.Data[Index]; if (CurPos.Row != PrevRow) Rows_to_delete[Counter++] = CurPos.Row; PrevRow = CurPos.Row; } } else Rows_to_delete[0] = this.CurCell.Row.Index; } else Rows_to_delete[0] = Ind; if (Rows_to_delete.length <= 0) return true; // Строки мы удаляем либо по 1, либо непрервным блоком. При удалении мы // смотрим на следующую строку после удаляемого блока и проверяем, если // какая-либо из ячеек данной строки учавствует в вертикальном объединении, // тогда проверяем где оно началось. Если начало объединения выше // строк, тогда ничего не делаем, в противном случае начинаем вертикальное // объединение с текущей ячейки. var FirstRow_to_delete = Rows_to_delete[0]; var CurRow = Rows_to_delete[Rows_to_delete.length - 1] + 1; if (CurRow < this.Content.length) { var Row = this.Content[CurRow]; var CellsCount = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var Cell = Row.Get_Cell(CurCell); var VMerge = Cell.GetVMerge(); if (vmerge_Continue != VMerge) continue; // Данная ячейка продолжает вертикальное объединение ячеек // Найдем строку, с которой начинается данное объединение. var VMerge_count = this.Internal_GetVertMergeCountUp(CurRow, Row.Get_CellInfo(CurCell).StartGridCol, Cell.Get_GridSpan()); if (CurRow - ( VMerge_count - 1 ) >= FirstRow_to_delete) Cell.SetVMerge(vmerge_Restart); } } this.RemoveSelection(); var oLogicDocument = this.LogicDocument; var isTrackRevisions = oLogicDocument ? oLogicDocument.IsTrackRevisions() : false; if (isTrackRevisions) { for (var nIndex = Rows_to_delete.length - 1; nIndex >= 0; --nIndex) { var oRow = this.GetRow(Rows_to_delete[nIndex]); var nRowReviewType = oRow.GetReviewType(); var oRowReviewInfo = oRow.GetReviewInfo(); if (reviewtype_Add === nRowReviewType && oRowReviewInfo.IsCurrentUser()) { this.private_RemoveRow(Rows_to_delete[nIndex]); } else { for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCellContent = oRow.GetCell(nCurCell).GetContent(); oCellContent.SelectAll(); oCellContent.Remove(); oCellContent.RemoveSelection(); } oRow.SetReviewType(reviewtype_Remove); } } } else { for (var Index = Rows_to_delete.length - 1; Index >= 0; Index--) { this.private_RemoveRow(Rows_to_delete[Index]); } } // При удалении последней строки, надо сообщить об этом родительскому классу if (this.Content.length <= 0) return false; this.Recalc_CompiledPr2(); // Перемещаем курсор в начало следующей строки, либо в следующий параграф let curRow = Rows_to_delete[0]; if (curRow >= this.Content.length) { let nextPara = this.GetNextParagraph(); if (nextPara) { nextPara.MoveCursorToStartPos(); nextPara.Document_SetThisElementCurrent(true); return; } curRow = this.Content.length - 1; } this.CurCell = this.GetRow(curRow).GetCell(0); this.CurCell.Content.MoveCursorToStartPos(); this.Document_SetThisElementCurrent(true); return true; }; /** * Специальная функция для удаления строк таблицы, когда выделены одновременно параграф и таблица */ CTable.prototype.Row_Remove2 = function() { if (!this.IsCellSelection()) return true; let arrRowsToDelete = []; for (let nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) arrRowsToDelete[nCurRow] = 0; let arrSelection = this.GetSelectionArray(false); for (let nIndex = 0, nCount = arrSelection.length; nIndex < nCount; ++nIndex) { let iRow = arrSelection[nIndex].Row; arrRowsToDelete[iRow]++; } this.RemoveSelection(); for (let nCurRow = this.GetRowsCount() - 1; nCurRow >= 0; --nCurRow) { if (arrRowsToDelete[nCurRow]) this.private_RemoveRow(nCurRow); } this.CorrectTableRows(false); if (!this.GetRowsCount()) return false; // Проверяем текущую ячейку if (this.CurCell.Row.Index >= this.Content.length) this.CurCell = this.GetRow(this.GetRowsCount() - 1).GetCell(0); return true; }; /** * Удаление колонки либо по выделению Selection, либо по текущей ячейке * * ВАЖНО: * Данная функция больше не должна использоваться. Удаление колонки должно теперь осуществляться через * выделение колонки, с помощью функции SelectTable(c_oAscTableSelectionType.Column), и последующим удалением ячеек, * с помощью функции RemoveTableCells * */ CTable.prototype.RemoveTableColumn = function() { var bApplyToInnerTable = false; if (false === this.Selection.Use || ( true === this.Selection.Use && table_Selection_Text === this.Selection.Type )) bApplyToInnerTable = this.CurCell.Content.RemoveTableColumn(); if (true === bApplyToInnerTable) return true; // Найдем правую и левую границы выделенных ячеек. var Cells_pos = []; if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) Cells_pos = this.Selection.Data; else Cells_pos[0] = {Row : this.CurCell.Row.Index, Cell : this.CurCell.Index}; if (Cells_pos.length <= 0) return; var Grid_start = -1; var Grid_end = -1; for (var Index = 0; Index < Cells_pos.length; Index++) { var Row = this.Content[Cells_pos[Index].Row]; var Cell = Row.Get_Cell(Cells_pos[Index].Cell); var Cur_Grid_start = Row.Get_CellInfo(Cells_pos[Index].Cell).StartGridCol; var Cur_Grid_end = Cur_Grid_start + Cell.Get_GridSpan() - 1; if (-1 === Grid_start || ( -1 !== Grid_start && Grid_start > Cur_Grid_start )) Grid_start = Cur_Grid_start; if (-1 === Grid_end || ( -1 !== Grid_end && Grid_end < Cur_Grid_end )) Grid_end = Cur_Grid_end; } // Пробегаемся по всем строкам и смотрим, если у какой либо ячейки // есть пересечение с отрезком [Grid_start, Grid_end], тогда удаляем // данную ячейку. var Delete_info = []; var Rows_info = []; for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { Delete_info[CurRow] = []; Rows_info[CurRow] = []; var Row = this.Content[CurRow]; var Before_Info = Row.Get_Before(); if (Before_Info.GridBefore > 0) Rows_info[CurRow].push({W : this.TableSumGrid[Before_Info.GridBefore - 1], Type : -1, GridSpan : 1}); var CellsCount = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var Cell = Row.Get_Cell(CurCell); var Cur_Grid_start = Row.Get_CellInfo(CurCell).StartGridCol; var Cur_Grid_end = Cur_Grid_start + Cell.Get_GridSpan() - 1; if (Cur_Grid_start <= Grid_end && Cur_Grid_end >= Grid_start) { Delete_info[CurRow].push(CurCell); } else { var W = this.TableSumGrid[Cur_Grid_end] - this.TableSumGrid[Cur_Grid_start - 1]; Rows_info[CurRow].push({W : W, Type : 0, GridSpan : 1}); } } } // Удалим все ячейки for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Row = this.Content[CurRow]; for (var Index = Delete_info[CurRow].length - 1; Index >= 0; Index--) { var CurCell = Delete_info[CurRow][Index]; Row.Remove_Cell(CurCell); } } // При удалении колонки возможен случай, когда удаляется строка целиком for (var CurRow = this.Content.length - 1; CurRow >= 0; CurRow--) { // Строка удалена целиком, если в RowsInfo нет ни одной записи // о ячейках (т.е. с типом равным 0) var bRemove = true; for (var Index = 0; Index < Rows_info[CurRow].length; Index++) { if (0 === Rows_info[CurRow][Index].Type) { bRemove = false; break; } } if (true === bRemove) { this.private_RemoveRow(CurRow); Rows_info.splice(CurRow, 1); } } // Возвращаем курсор if(!this.bPresentation) { this.DrawingDocument.TargetStart(); this.DrawingDocument.TargetShow(); this.DrawingDocument.SelectEnabled(false); } // При удалении последней строки, надо сообщить об этом родительскому классу if (this.Content.length <= 0) return false; // TODO: При удалении колонки надо запоминать информацию о вертикально // объединенных ячейках, и в новой сетке объединять ячейки только // если они были объединены изначально. Сейчас если ячейка была // объединена с какой-либо ячейков, то она может после удаления колонки // объединиться с совсем другой ячейкой. this.Internal_CreateNewGrid(Rows_info); // Пробегаемся по всем ячейкам и смотрим на их вертикальное объединение, было ли оно нарушено this.private_CorrectVerticalMerge(); // Возможен случай, когда у нас остались строки, полностью состоящие из объединенных вертикально ячеек for (var CurRow = this.Content.length - 1; CurRow >= 0; CurRow--) { var bRemove = true; var Row = this.Content[CurRow]; var CellsCount = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var Cell = Row.Get_Cell(CurCell); if (vmerge_Continue !== Cell.GetVMerge()) { bRemove = false; break; } } if (true === bRemove) { this.private_RemoveRow(CurRow); } } // Перемещаем курсор в начало следующей колонки var CurRow = 0; var Row = this.Content[CurRow]; var CellsCount = Row.Get_CellsCount(); var CurCell = Delete_info[0][0] === undefined ? CellsCount - 1 : Math.min(Delete_info[0][0], CellsCount - 1); this.CurCell = Row.Get_Cell(CurCell); this.CurCell.Content.MoveCursorToStartPos(); var PageNum = 0; this.Markup.Internal.RowIndex = CurRow; this.Markup.Internal.CellIndex = CurCell; this.Markup.Internal.PageNum = PageNum; this.Selection.Use = false; this.Selection.Start = false; this.Selection.StartPos.Pos = {Row : CurRow, Cell : CurCell}; this.Selection.EndPos.Pos = {Row : CurRow, Cell : CurCell}; this.Selection.CurRow = CurRow; this.private_RecalculateGrid(); this.Internal_Recalculate_1(); return true; }; /** * Добавление колонки. * @param bBefore - true - до(слева) первой выделенной колонки, false - после(справа) последней выделенной колонки. * @param {number} [nCount=undefined] форсированное количество добавляемых колонок */ CTable.prototype.AddTableColumn = function(bBefore, nCount) { if ("undefined" === typeof(bBefore)) bBefore = true; var bApplyToInnerTable = false; if (false === this.Selection.Use || ( true === this.Selection.Use && table_Selection_Text === this.Selection.Type )) bApplyToInnerTable = this.CurCell.Content.AddTableColumn(bBefore); if (true === bApplyToInnerTable) return; var Cells_pos = []; // Количество, вставляемых столбцов зависит от того сколько содержится // ячеек в первой строке выделения. Ширина берется у первой ячейки, если // bBefore = true, и у последней, если bBefore = false. var Count = 1; var Width = 0; if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { Cells_pos = this.Selection.Data; var Prev_row = -1; Count = 0; for (var Index = 0; Index < this.Selection.Data.length; Index++) { if (-1 != Prev_row) { if (Prev_row === this.Selection.Data[Index].Row) Count++; else break; } else { Count++; Prev_row = this.Selection.Data[Index].Row; } } } else { Cells_pos[0] = {Row : this.CurCell.Row.Index, Cell : this.CurCell.Index}; Count = 1; } if (null !== nCount && undefined !== nCount && nCount > 0) Count = nCount; if (Cells_pos.length <= 0) return; if (true === bBefore) { // Вычислим ширину первой ячейки var FirstCell_Grid_start = this.Content[Cells_pos[0].Row].Get_CellInfo(Cells_pos[0].Cell).StartGridCol; var FirstCell_Grid_end = FirstCell_Grid_start + this.Content[Cells_pos[0].Row].Get_Cell(Cells_pos[0].Cell).Get_GridSpan() - 1; Width = this.TableSumGrid[FirstCell_Grid_end] - this.TableSumGrid[FirstCell_Grid_start - 1]; } else { // Вычислим ширину последней ячейки var LastPos = Cells_pos.length - 1; var LastCell_Grid_start = this.Content[Cells_pos[LastPos].Row].Get_CellInfo(Cells_pos[LastPos].Cell).StartGridCol; var LastCell_Grid_end = LastCell_Grid_start + this.Content[Cells_pos[LastPos].Row].Get_Cell(Cells_pos[LastPos].Cell).Get_GridSpan() - 1; Width = this.TableSumGrid[LastCell_Grid_end] - this.TableSumGrid[LastCell_Grid_start - 1]; } var Rows_info = []; var Add_info = []; if (true === bBefore) { // Ищем левую границу выделенных ячеек var Grid_start = -1; for (var Index = 0; Index < Cells_pos.length; Index++) { var Row = this.Content[Cells_pos[Index].Row]; var Cell = Row.Get_Cell(Cells_pos[Index].Cell); var Cur_Grid_start = Row.Get_CellInfo(Cells_pos[Index].Cell).StartGridCol; if (-1 === Grid_start || ( -1 != Grid_start && Grid_start > Cur_Grid_start )) Grid_start = Cur_Grid_start; } for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Row = this.Content[CurRow]; Rows_info[CurRow] = []; Add_info[CurRow] = 0; var Before_Info = Row.Get_Before(); if (Before_Info.GridBefore > 0) Rows_info[CurRow].push({W : this.TableSumGrid[Before_Info.GridBefore - 1], Type : -1, GridSpan : 1}); var CellsCount = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var Cell = Row.Get_Cell(CurCell); var Cur_Grid_start = Row.Get_CellInfo(CurCell).StartGridCol; var Cur_Grid_end = Cur_Grid_start + Cell.Get_GridSpan() - 1; if (Cur_Grid_start <= Grid_start) Add_info[CurRow] = CurCell; var W = this.TableSumGrid[Cur_Grid_end] - this.TableSumGrid[Cur_Grid_start - 1]; Rows_info[CurRow].push({W : W, Type : 0, GridSpan : 1}); } var After_Info = Row.Get_After(); if (After_Info.GridAfter > 0) { if (Row.Get_CellInfo(CellsCount - 1).StartGridCol + Row.Get_Cell(CellsCount - 1).Get_GridSpan() <= Grid_start) Add_info[CurRow] = CellsCount; } } // Теперь нам надо добавить ячейки в найденные позиции, и в те же позиции // добавить элементы в массиве Rows_info for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Row = this.Content[CurRow]; var bBefore2 = false; if (Rows_info.length > 0 && Rows_info[CurRow][0].Type === -1) bBefore2 = true; for (var Index = 0; Index < Count; Index++) { var NewCell = Row.Add_Cell(Add_info[CurRow], Row, null, false); // Скопируем свойства следующуй ячейки в данной строке, а если мы добавляем в конец, то предыдущей var NextCell = ( Add_info[CurRow] >= Row.Get_CellsCount() - 1 ? Row.Get_Cell(Add_info[CurRow] - 1) : Row.Get_Cell(Add_info[CurRow] + 1) ); NewCell.Copy_Pr(NextCell.Pr, true); // Скопируем текстовые настройки var FirstPara = NextCell.Content.Get_FirstParagraph(); var TextPr = FirstPara.GetFirstRunPr(); NewCell.Content.SetApplyToAll(true); // Добавляем стиль во все параграфы var PStyleId = FirstPara.Style_Get(); if (undefined !== PStyleId && null !== this.LogicDocument) { var Styles = this.LogicDocument.Get_Styles(); NewCell.Content.SetParagraphStyle(Styles.Get_Name(PStyleId)); } NewCell.Content.AddToParagraph(new ParaTextPr(TextPr)); NewCell.Content.SetApplyToAll(false); if (false === bBefore2) Rows_info[CurRow].splice(Add_info[CurRow], 0, {W : Width, Type : 0, GridSpan : 1}); else Rows_info[CurRow].splice(Add_info[CurRow] + 1, 0, {W : Width, Type : 0, GridSpan : 1}); } } } else { // Ищем правую границу выделенных ячеек var Grid_end = -1; for (var Index = 0; Index < Cells_pos.length; Index++) { var Row = this.Content[Cells_pos[Index].Row]; var Cell = Row.Get_Cell(Cells_pos[Index].Cell); var Cur_Grid_start = Row.Get_CellInfo(Cells_pos[Index].Cell).StartGridCol; var Cur_Grid_end = Cur_Grid_start + Cell.Get_GridSpan() - 1; if (-1 === Grid_end || ( -1 != Grid_end && Grid_end < Cur_Grid_end )) Grid_end = Cur_Grid_end; } for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Row = this.Content[CurRow]; Rows_info[CurRow] = []; Add_info[CurRow] = -1; var Before_Info = Row.Get_Before(); if (Before_Info.GridBefore > 0) Rows_info[CurRow].push({W : this.TableSumGrid[Before_Info.GridBefore - 1], Type : -1, GridSpan : 1}); var CellsCount = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var Cell = Row.Get_Cell(CurCell); var Cur_Grid_start = Row.Get_CellInfo(CurCell).StartGridCol; var Cur_Grid_end = Cur_Grid_start + Cell.Get_GridSpan() - 1; if (Cur_Grid_end <= Grid_end) Add_info[CurRow] = CurCell; var W = this.TableSumGrid[Cur_Grid_end] - this.TableSumGrid[Cur_Grid_start - 1]; Rows_info[CurRow].push({W : W, Type : 0, GridSpan : 1}); } } // Теперь нам надо добавить ячейки в найденные позиции, и в те же позиции // добавить элементы в массиве Rows_info for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Row = this.Content[CurRow]; var bBefore2 = false; if (Rows_info.length > 0 && Rows_info[CurRow][0].Type === -1) bBefore2 = true; for (var Index = 0; Index < Count; Index++) { var NewCell = Row.Add_Cell(Add_info[CurRow] + 1, Row, null, false); // Скопируем свойства следующуй ячейки в данной строке, а если мы добавляем в конец, то предыдущей var NextCell = ( Add_info[CurRow] + 1 >= Row.Get_CellsCount() - 1 ? Row.Get_Cell(Add_info[CurRow]) : Row.Get_Cell(Add_info[CurRow] + 2) ); NewCell.Copy_Pr(NextCell.Pr, true); // Скопируем текстовые настройки var FirstPara = NextCell.Content.Get_FirstParagraph(); var TextPr = FirstPara.GetFirstRunPr(); NewCell.Content.SetApplyToAll(true); // Добавляем стиль во все параграфы var PStyleId = FirstPara.Style_Get(); if (undefined !== PStyleId && null !== this.LogicDocument) { var Styles = this.LogicDocument.Get_Styles(); NewCell.Content.SetParagraphStyle(Styles.Get_Name(PStyleId)); } NewCell.Content.AddToParagraph(new ParaTextPr(TextPr)); NewCell.Content.SetApplyToAll(false); if (false === bBefore2) Rows_info[CurRow].splice(Add_info[CurRow] + 1, 0, {W : Width, Type : 0, GridSpan : 1}); else Rows_info[CurRow].splice(Add_info[CurRow] + 2, 0, {W : Width, Type : 0, GridSpan : 1}); } } } this.Internal_CreateNewGrid(Rows_info); // Выделим добавленные ячейки this.Selection.Use = true; this.Selection.Type = table_Selection_Cell; let selectionData = []; for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var StartCell = ( true === bBefore ? Add_info[CurRow] : Add_info[CurRow] + 1 ); for (var Index = 0; Index < Count; Index++) { selectionData.push({Row : CurRow, Cell : StartCell + Index}); } } if (selectionData.length) { this.private_SetSelectionData(selectionData); let startPos = selectionData[0]; let endPos = selectionData[selectionData.length - 1]; this.Selection.StartPos.Pos = {Row : startPos.Row, Cell : startPos.Cell}; this.Selection.EndPos.Pos = {Row : endPos.Row, Cell : endPos.Cell}; } else { this.RemoveSelection(); } this.private_RecalculateGrid(); }; CTable.prototype.DrawTableCells = function(X1, Y1, X2, Y2, CurPageStart, CurPageEnd, drawMode) { this.RemoveSelection(); // сбрасываем выделение // Приводим к координатам таблицы X1 = X1 - this.Pages[CurPageStart].X; X2 = X2 - this.Pages[CurPageStart].X; if (Y1 < 0) Y1 = 0; if (Y2 < 0) Y2 = 0; // Если рисуем (ctrl + F1) if (drawMode === true) { // Если делаем просто щелчок по границе if (X1 === X2 && Y1 === Y2) { return this.DrawBorderByClick(X1, Y1, CurPageStart); } // Если рисуем вертикальную линию else if (Math.abs(Y2 - Y1) > 2 && Math.abs(X2 - X1) < 3) { this.DrawVertLine(X1, Y1, X2, Y2, CurPageStart) } // Если рисуем горизонтальную линию else if (Math.abs(X2 - X1) > 2 && Math.abs(Y2 - Y1) < 3) { this.DrawHorLine(X1, Y1, X2, Y2, CurPageStart); } // Если рисуем ячейку, внутри другой ячейки else { this.DrawCellInCell(X1, Y1, X2, Y2, CurPageStart); } } // Если стираем (ctrl + F2) else if (drawMode === false) { return this.EraseTable(X1, Y1, X2, Y2, CurPageStart); } }; /** * Split a table vertically * @param X1 - coordinate * @param X2 - coordinate * @param Y1 - coordinate * @param Y2 - coordinate * @param {Number} CurPageStart */ CTable.prototype.DrawVertLine = function(X1, Y1, X2, Y2, CurPageStart) { //если рисуем линию снизу вверх if (Y1 > Y2) { var cache; cache = Y2; Y2 = Y1; Y1 = cache; } if (Y2 < this.Pages[CurPageStart].Bounds.Bottom && Y2 > this.Pages[CurPageStart].Bounds.Top && Y1 < this.Pages[CurPageStart].Bounds.Top) { Y1 = this.Pages[CurPageStart].Bounds.Top; } var CellAdded = false; // была ли добавлена ячейка var Rows = []; // массив строк подлежащих делению (которые мы режем) var rowsInfo = []; // масив строк с ширинами ячеейк (используется для создания новой сетки таблицы) // Индексы строк, попавших под режущую линию Rows = this.GetAffectedRows(X1, Y1, X2, Y2, CurPageStart, 0); //если массив строк подлежащих делению пуст, выходим if (Rows.length === 0) return; rowsInfo = this.CalculateNewRowsInfo(X1, Rows); CellAdded = this.VertSplitCells(X1, Rows); if (!CellAdded) return; this.SetTableGrid(this.Internal_CreateNewGrid(rowsInfo)); }; /** * Split a table horizontally * @param X1 - coordinate * @param X2 - coordinate * @param Y1 - coordinate * @param Y2 - coordinate * @param {Number} CurPageStart */ CTable.prototype.DrawHorLine = function(X1, Y1, X2, Y2, CurPageStart) { if (X1 > X2) { var cache; cache = X2; X2 = X1; X1 = cache; } var RowNumb = []; // Строка, попавшая в вертикальное разбиение var CellsIndexes = []; // Массив номеров ячеек, попавших в вертикальное разбиение RowNumb = this.GetAffectedRows(X1, Y1, X2, Y2, CurPageStart, 1); if (RowNumb.length === 0) return; else { for (var curCell = 0; curCell < this.GetRow(RowNumb[0]).Get_CellsCount(); curCell++) { if (X1 < this.GetRow(RowNumb[0]).CellsInfo[curCell].X_cell_start && X2 > this.GetRow(RowNumb[0]).CellsInfo[curCell].X_cell_start || X1 < this.GetRow(RowNumb[0]).CellsInfo[curCell].X_cell_end && X2 > this.GetRow(RowNumb[0]).CellsInfo[curCell].X_cell_end || X1 > this.GetRow(RowNumb[0]).CellsInfo[curCell].X_cell_start && X2 < this.GetRow(RowNumb[0]).CellsInfo[curCell].X_cell_end) CellsIndexes.push(curCell); } } if (CellsIndexes.length === 0) return; this.HorSplitCells(Y1, RowNumb[0], CellsIndexes, CurPageStart); this.ReIndexing(); this.Recalc_CompiledPr2(); this.private_RecalculateGrid(); this.Internal_Recalculate_1(); }; /** * Eraser of table * @param {Number} X1 - coordinate * @param {Number} X2 - coordinate * @param {Number} Y1 - coordinate * @param {Number} Y2 - coordinate * @param {Number} CurPageStart */ CTable.prototype.EraseTable = function(X1, Y1, X2, Y2, CurPageStart) { var isClearMerge = false; var oldRows = []; // количество строк и ячеек может изменяться в процессе работы ластика, это необходимо учитывать, поэтому запоминаем изначальное их количество var oldCells = []; for (var curRow = 0; curRow < this.Get_RowsCount(); curRow++) { oldCells[curRow] = []; for (var curCell = 0; curCell < this.GetRow(curRow).Get_CellsCount(); curCell++) { oldCells[curRow].push(this.GetRow(curRow).Get_Cell(curCell)); } } for (var curRow = 0; curRow < this.Get_RowsCount(); curRow++) { oldRows.push(this.GetRow(curRow)); } // Проверка, была ли выбрана граница (для случая, когда щелкаем по границе); // Проверка, были ли выбраны начало и конец выделения // *Необходимо для случаев, когда у ячейки VMerge_count > 1* var isSelected = false; // Для щелчка по границе var isVSelect = false; // Была ли выбрана вертикальная граница var isHSelect = false; // Была ли выбрана горизонтальная граница var isRightBorder = false; var isLeftBorder = false; var isTopBorder = false; var isBottomBorder = false; var click = false; // ключ, по которому определяем, был совершен клик или было совершено выделение (true - Был клик) var Y_Over = false; // выделение начинается выше таблицы var Y_Under = false; // выделение заканчивается ниже таблицы var X_Front = false; // выделение начинается левее таблицы var X_After = false; // выделение заканчивается правее таблицы // Заполнение this.Selection.Data // Если делаем просто щелчок по границе if (X1 === X2 && Y1 === Y2) { var SelectedCells = this.GetCellAndBorderByClick(X1, Y1, CurPageStart, false); isVSelect = SelectedCells.isVSelect; // Была ли выбрана вертикальная граница isHSelect = SelectedCells.isHSelect; // Была ли выбрана горизонтальная граница isRightBorder = SelectedCells.isRightBorder; isLeftBorder = SelectedCells.isLeftBorder; isTopBorder = SelectedCells.isTopBorder; isBottomBorder = SelectedCells.isBottomBorder; if (SelectedCells.Cells.length === 0) return false; else if (!isRightBorder && !isLeftBorder && !isTopBorder && !isBottomBorder && !isVSelect && !isHSelect) return true; isSelected = true; click = true; this.private_SetSelectionData(SelectedCells.Cells); } // Если выделяем несколько ячеек else { this.Selection.Data = this.GetCellsByRect(X1, Y1, X2, Y2, CurPageStart); if (this.Selection.Data.length != 0) isSelected = true; // Если выделение справа налево if (X1 > X2) { var cache; cache = X2; X2 = X1; X1 = cache; } // Если выделение снизу вверх if (Y1 > Y2) { var cache; cache = Y2; Y2 = Y1; Y1 = cache; } // Проверяем, выходит ли наш rect за границы таблицы if (Y2 >= this.RowsInfo[this.Pages[CurPageStart].LastRow].Y[CurPageStart] + this.RowsInfo[this.Pages[CurPageStart].LastRow].H[CurPageStart]) Y_Under = true; if (Y1 <= this.RowsInfo[this.Pages[CurPageStart].FirstRow].Y[CurPageStart]) Y_Over = true; if (X1 <= this.TableSumGrid[-1]) X_Front = true; if (X2 >= this.TableSumGrid[this.TableSumGrid.length - 1]) X_After = true; } // Если не были определены границы для удаления или ячейки для объединения -> выход if (isSelected === false || this.Selection.Data === null) return; // В массиве this.Selection.Data идет список ячеек по строкам (без разрывов) // Перед объединением мы должны проверить совпадают ли начальная и конечная колонки // в сетке TableGrid для каждого ряда. var Temp = this.Internal_CheckMerge(); var bCanMerge = Temp.bCanMerge; var Grid_start = Temp.Grid_start; var Grid_end = Temp.Grid_end; var RowsInfo = Temp.RowsInfo; // Проверяем можем ли удалить всю таблицу целиком, или её часть (столбец или строку, или несколько) if (this.DeleteTablePart(X_Front, X_After, Y_Over, Y_Under, bCanMerge)) return; var CellsCanBeMerge = [];// Массив из групп ячеек, которые можно будет объеденить CellsCanBeMerge.push(this.Selection.Data); // Добавляем массив с выделенными ячейками, если они не объединяемы, тогда будет осуществлять поиск тех, которые объединить можно var CellsCantBeMerge = []; // Ячейки, которые нельзя объединить var SelectedCells = this.Selection.Data; // Массив ячеек, которые были выделены // Удаление внешних границ, // в выделении должна быть только одна ячейка if (this.Selection.Data.length === 1) { var Cell_pos = this.Selection.Data[0]; var Row = this.GetRow(Cell_pos.Row); var Cell = Row.Get_Cell(Cell_pos.Cell); var Grid_start = Row.Get_CellInfo(Cell_pos.Cell).StartGridCol; var Grid_span = Cell.Get_GridSpan(); var VMerge_Count = this.Internal_GetVertMergeCount(Cell_pos.Row, Grid_start, Grid_span); var rowHSum = 0; var CellsToDelete = []; if (VMerge_Count >= 1) { for (var Index = Cell_pos.Row; Index < Cell_pos.Row + VMerge_Count; Index++) { rowHSum += this.RowsInfo[Index].H[CurPageStart] } } if (!click) { if (this.RowsInfo[Cell.Row.Index].Y[CurPageStart] + rowHSum < Y2) Y_Under = true; if (this.RowsInfo[Cell.Row.Index].Y[CurPageStart] > Y1) Y_Over = true; if (Cell.Index === 0 && this.GetRow(Cell.Row.Index).CellsInfo[Cell.Index].X_cell_start > X1) X_Front = true; if (Cell.Index === this.GetRow(Cell.Row.Index).Get_CellsCount() - 1 && this.GetRow(Cell.Row.Index).CellsInfo[Cell.Index].X_cell_end < X2) X_After = true; } var BordersToDelete = { isHSelect : isHSelect, isTopBorder : isTopBorder, isBottomBorder : isBottomBorder, isVSelect : isVSelect, isRightBorder : isRightBorder, isLeftBorder : isLeftBorder, X_Front : X_Front, X_After : X_After, Y_Over : Y_Over, Y_Under : Y_Under }; this.DeleteExternalBorders(BordersToDelete, Cell_pos, click, CurPageStart); if (this.DeleteExternalRows(Cell_pos, click) === true) return; var ArrayCellsToDelete = this.FindCellsToDelete(Cell_pos); if (ArrayCellsToDelete.length !== 0) { for (var Index = 0; Index < ArrayCellsToDelete.length; Index++) CellsToDelete.push(ArrayCellsToDelete[Index]); } this.CreateNewGridWithoutCells(CellsToDelete); return; } // Если текущее выделение невозможно объеденить, // пробуем из него выделить группы, которые объеденить можно if (false === bCanMerge) { CellsCanBeMerge = this.FindCellsCanBeMerge(SelectedCells); // После выполнения функции FindCellsCanBeMerge в массиве SelectedCells остались только те ячейки, которые нельзя объединить CellsCantBeMerge = SelectedCells; } else { // При объединении двух ячеек следующих друг за другом, // необходимо, чтобы правый Border ячейки справа сохранился в новой ячейке if (this.Selection.Data.length === 2) { var Cell_pos_1 = this.Selection.Data[0]; var Cell_pos_2 = this.Selection.Data[1]; var Row_1 = this.GetRow(Cell_pos_1.Row); var Cell_1 = Row_1.Get_Cell(Cell_pos_1.Cell); var Row_2 = this.GetRow(Cell_pos_2.Row); var Cell_2 = Row_2.Get_Cell(Cell_pos_2.Cell); if (Cell_2.GetBorder(1).Value === 1) Cell_1.CheckNonEmptyBorder(1); else Cell_1.CheckEmptyBorder(1); } } // Для каждой группы из CellsCanBeMerge объединяем ячейки for (var Selection = 0; Selection < CellsCanBeMerge.length; Selection++) { var curRows = []; var curCells = []; X_Front = false; X_After = false; Y_Over = false; Y_Under = false; this.Selection.Data = CellsCanBeMerge[Selection]; var Temp = this.Internal_CheckMerge(); var bCanMerge = Temp.bCanMerge; var Grid_start = Temp.Grid_start; var Grid_end = Temp.Grid_end; var RowsInfo = Temp.RowsInfo; var Pos_tl = this.Selection.Data[0]; var Cell_tl = this.GetRow(Pos_tl.Row).Get_Cell(Pos_tl.Cell); // Объединяем содержимое всех ячеек в левую верхнюю ячейку. (Все выделенные // ячейки идут у нас последовательно, начиная с левой верхней), и объединяем // сами ячейки. for (var Index = 0; Index < this.Selection.Data.length; Index++) { var Pos = this.Selection.Data[Index]; var Row = this.GetRow(Pos.Row); var Cell = Row.Get_Cell(Pos.Cell); // Добавляем содержимое данной ячейки к содержимому левой верхней ячейки if (0 != Index) { Cell_tl.Content_Merge(Cell.Content); Cell.Content.Clear_Content(); } } if (true !== isClearMerge) { // Выставим ширину результируещей ячейки var SumW = 0; for (var CurGridCol = Grid_start; CurGridCol <= Grid_end; CurGridCol++) { SumW += this.TableGridCalc[CurGridCol]; } Cell_tl.Set_W(new CTableMeasurement(tblwidth_Mm, SumW)); } // Теперь нам надо удалить лишние ячейки и добавить ячейки с // вертикальным объединением. for (var RowIndex in RowsInfo) { var Row = this.GetRow(RowIndex); for (var CellIndex = 0; CellIndex < Row.Get_CellsCount(); CellIndex++) { var Cell_grid_start = Row.Get_CellInfo(CellIndex).StartGridCol; if (Grid_start === Cell_grid_start) { if (RowIndex != Pos_tl.Row) { var Cell = Row.Get_Cell(CellIndex); Cell.Set_GridSpan(Grid_end - Grid_start + 1); Cell.SetVMerge(vmerge_Continue); } else { Cell_tl.Set_GridSpan(Grid_end - Grid_start + 1); } } else if (Cell_grid_start > Grid_start && Cell_grid_start <= Grid_end) { Row.Remove_Cell(CellIndex); CellIndex--; } else if (Cell_grid_start > Grid_end) break; } } // Ячейки были объединены в ячейку Cell_tl, посчитаем для неё VMergeCount var Cell_tl_VMergeCount = this.GetVMergeCount(Cell_tl.GetIndex(), Cell_tl.GetRow().GetIndex()); if (!click) { if (this.TableSumGrid[Grid_start - 1] > X1) X_Front = true; if (this.TableSumGrid[Grid_end] < X2) X_After = true; if (this.RowsInfo[Cell_tl.GetRow().GetIndex() + Cell_tl_VMergeCount - 1].Y[CurPageStart] + this.RowsInfo[Cell_tl.GetRow().GetIndex() + Cell_tl_VMergeCount - 1].H[CurPageStart] < Y2) Y_Under = true; if (this.RowsInfo[Pos_tl.Row].Y[CurPageStart] > Y1) Y_Over = true; } // Удаляем лишние строки this.CorrectTableRows(true !== isClearMerge ? true : false); for (var PageNum = 0; PageNum < this.Pages.length - 1; PageNum++) { if (Pos_tl.Row <= this.Pages[PageNum + 1].FirstRow) break; } this.CurCell = Cell_tl; this.CurCell.GetContent().SelectAll(); if (X_Front && X_After && this.GetRow(Pos_tl.Row).Get_CellsCount() === 1) { this.RemoveTableRow(Pos_tl.Row); CellsCanBeMerge[Selection] = []; } for (var Index = 0; Index < this.Get_RowsCount(); Index++) { curRows.push(this.GetRow(Index)); } for (var curRow = 0; curRow < this.Get_RowsCount(); curRow++) { curCells[curRow] = []; for (var curCell = 0; curCell < this.GetRow(curRow).Get_CellsCount(); curCell++) { curCells[curRow].push(this.GetRow(curRow).Get_Cell(curCell)); } } // Если количество строк уменьшилось, мы должны изменить координаты ячеек в следующих объединениях for (var Index = 0; Index < curRows.length; Index++) { if (oldRows[Index].Id != curRows[Index].Id) { for (var newIndex = Selection; newIndex < CellsCanBeMerge.length; newIndex++) { for (var Index2 = 0; Index2 < CellsCanBeMerge[newIndex].length; Index2++) { if (CellsCanBeMerge[newIndex][Index2].Row > Index) CellsCanBeMerge[newIndex][Index2].Row -= 1; } } for (var Index2 = 0; Index2 < CellsCantBeMerge.length; Index2++) { if (CellsCantBeMerge[Index2].Row > Index) CellsCantBeMerge[Index2].Row -= 1; } oldRows.splice(Index, 1); oldCells.splice(Index, 1); Index = -1; } } for (var Index = 0; Index < curCells.length; Index++) { for (var Index2 = 0; Index2 < curCells[Index].length; Index2++) { if (oldCells[Index][Index2] != curCells[Index][Index2]) { for (var newIndex = Selection; newIndex < CellsCanBeMerge.length; newIndex++) { for (var Index3 = 0; Index3 < CellsCanBeMerge[newIndex].length; Index3++) { if (CellsCanBeMerge[newIndex][Index3].Row === Index && CellsCanBeMerge[newIndex][Index3].Cell > Index2) CellsCanBeMerge[newIndex][Index3].Cell -= 1; } } for (var Index3 = 0; Index3 < CellsCantBeMerge.length; Index3++) { if (CellsCantBeMerge[Index3].Row === Index && CellsCantBeMerge[Index3].Cell > Index2) CellsCantBeMerge[Index3].Cell -= 1; } oldCells[Index].splice(Index2, 1); Index2 = -1; } } } } if (CellsCanBeMerge.length >= 1) { for (var nTempIndex = 0, nTempLen = CellsCanBeMerge.length; nTempIndex < nTempLen; ++nTempIndex) { var Item = CellsCanBeMerge[nTempIndex]; if (Item.length !== 0) CellsCantBeMerge.push(Item[0]); } } // если остались ячейки которые нельзя объединить, удаляем между ними и между объединенными границы if (CellsCantBeMerge.length >= 1) { var CellsToDelete = []; for (var firstCellPos = 0; firstCellPos < CellsCantBeMerge.length; firstCellPos++) { Y_Over = false; Y_Under = false; X_Front = false; X_After = false; var Cell_pos_1 = CellsCantBeMerge[firstCellPos]; var Row_1 = this.GetRow(Cell_pos_1.Row); if (Row_1 === undefined || Row_1 === null) continue; var Cell_1 = Row_1.Get_Cell(Cell_pos_1.Cell); if (Cell_1 === undefined || Cell_1 === null) continue; var Grid_start_1 = Row_1.Get_CellInfo(Cell_pos_1.Cell).StartGridCol; var Grid_span_1 = Cell_1.Get_GridSpan(); var Grid_end_1 = Grid_start_1 + Grid_span_1 - 1; var VMerge_count_1 = this.Internal_GetVertMergeCount(Cell_pos_1.Row, Grid_start_1, Grid_span_1); var rowHSum = 0; if (VMerge_count_1 >= 1) { for (var newIndex = Cell_pos_1.Row; newIndex < Cell_pos_1.Row + VMerge_count_1; newIndex++) { if (this.Content[newIndex].Get_Height().Value != 0) rowHSum += this.Content[newIndex].Get_Height().Value; else rowHSum += this.RowsInfo[newIndex].H[CurPageStart] } } if (!click) { if (this.RowsInfo[Cell_pos_1.Row].Y[CurPageStart] + rowHSum < Y2) Y_Under = true; if (this.RowsInfo[Cell_pos_1.Row].Y[CurPageStart] > Y1) Y_Over = true; if (Cell_pos_1.Cell === 0 && this.GetRow(Cell_pos_1.Row).CellsInfo[Cell_pos_1.Cell].X_cell_start > X1) X_Front = true; if (Cell_pos_1.Cell === this.GetRow(Cell_pos_1.Row).Get_CellsCount() - 1 && this.TableSumGrid[Grid_end_1] < X2) X_After = true; } if (Y_Over) { Cell_1.CheckEmptyBorder(0); } if (Y_Under) { Cell_1.CheckEmptyBorder(2); } if (X_Front) { Cell_1.CheckEmptyBorder(3); } if (X_After) { Cell_1.CheckEmptyBorder(1); } for (var secondCellPos = firstCellPos + 1; secondCellPos < CellsCantBeMerge.length; secondCellPos++) { var Cell_pos_2 = CellsCantBeMerge[secondCellPos]; var Row_2 = this.GetRow(Cell_pos_2.Row); if (Row_2 === undefined || Row_2 === null) continue; var Cell_2 = Row_2.Get_Cell(Cell_pos_2.Cell); if (Cell_2 === undefined || Cell_2 === null) continue; this.DeleteBorderBetweenCells(Cell_pos_1, Cell_pos_2); } } // Если объединить ячейки нельзя, стираем все границы под выделением, // если у ячейки отсутсвуют все внешние границы - удаляем её for (var curCellPos = 0, nTempLen = CellsCantBeMerge.length; curCellPos < nTempLen; ++curCellPos) { var cur_pos = CellsCantBeMerge[curCellPos]; var Row = this.GetRow(cur_pos.Row); if (Row === undefined || Row === null) continue; var Cell = Row.Get_Cell(cur_pos.Cell); if (Cell === undefined || Cell === null) continue; var Grid_start = Row.Get_CellInfo(cur_pos.Cell).StartGridCol; var Grid_span = Cell.Get_GridSpan(); var VMerge_Count = this.Internal_GetVertMergeCount(cur_pos.Row, Grid_start, Grid_span); var ArrayCellsToDelete = this.FindCellsToDelete(cur_pos); if (ArrayCellsToDelete.length !== 0) { for (var Index = 0; Index < ArrayCellsToDelete.length; Index++) CellsToDelete.push(ArrayCellsToDelete[Index]); } } this.CreateNewGridWithoutCells(CellsToDelete); } }; /** * Deletion of external borders. Deletion rules differ in the case of a click and selection. * @param {object} bordersToDelete - boundary data to be deleted * @param {object} cellPos - cell position * @param {bool} click - selection or click * @return {Array} */ CTable.prototype.DeleteExternalBorders = function(bordersToDelete, cellPos, click) { var Row = this.GetRow(cellPos.Row); var Cell = Row.Get_Cell(cellPos.Cell); var Grid_start = Row.Get_CellInfo(cellPos.Cell).StartGridCol; var Grid_span = Cell.Get_GridSpan(); var VMerge_Count = this.Internal_GetVertMergeCount(cellPos.Row, Grid_start, Grid_span); // Удаление внешних границ, если это клик if (click) { // Удаление горизонтальных внешних границ if (bordersToDelete.isHSelect) { if (bordersToDelete.isTopBorder) { Cell.CheckEmptyBorder(0); } else if (bordersToDelete.isBottomBorder) { Cell.CheckEmptyBorder(2) } } // Удаление вертикальных внешних границ else if (bordersToDelete.isVSelect) { if (bordersToDelete.isRightBorder) { for (var curRow = cellPos.Row; curRow < cellPos.Row + VMerge_Count; curRow++) { var TempCell = this.GetCellByStartGridCol(curRow, Grid_start); TempCell.CheckEmptyBorder(1); } } else if (bordersToDelete.isLeftBorder) { for (var curRow = cellPos.Row; curRow < cellPos.Row + VMerge_Count; curRow++) { var TempCell = this.GetCellByStartGridCol(curRow, Grid_start); TempCell.CheckEmptyBorder(3); } } } } // Удаление внешних границ, если это rect выделение else if (!click) { if (bordersToDelete.X_Front) { for (var curRow = cellPos.Row; curRow < cellPos.Row + VMerge_Count; curRow++) { var TempCell = this.GetCellByStartGridCol(curRow, Grid_start); TempCell.CheckEmptyBorder(3); } } if (bordersToDelete.X_After) { for (var curRow = cellPos.Row; curRow < cellPos.Row + VMerge_Count; curRow++) { var TempCell = this.GetCellByStartGridCol(curRow, Grid_start); TempCell.CheckEmptyBorder(1); } } if (bordersToDelete.Y_Over) { Cell.CheckEmptyBorder(0); } if (bordersToDelete.Y_Under) { var TempCell = this.GetCellByStartGridCol(cellPos.Row + VMerge_Count - 1, Grid_start); TempCell.CheckEmptyBorder(2); Cell.CheckEmptyBorder(2); } } }; /** * Deletion of external lines. The cell must be the only one in the row. * Deletion rules differ in the case of a click and selection * @param {object} cellPos - cell position * @return {bool} - returns false if nothing has been deleted */ CTable.prototype.DeleteExternalRows = function(cellPos, click) { var Row = this.GetRow(cellPos.Row); var Cell = Row.Get_Cell(cellPos.Cell); var Grid_start = Row.Get_CellInfo(cellPos.Cell).StartGridCol; var Grid_span = Cell.Get_GridSpan(); var VMerge_Count = this.Internal_GetVertMergeCount(cellPos.Row, Grid_start, Grid_span); if (click) { // удаление строки if (Cell.Row.Get_CellsCount() === 1 && Cell.Row.Index === 0) { if (Cell.Get_Border(0).Value === 0 && Cell.Get_Border(1).Value === 0 && Cell.Get_Border(2).Value === 0) { for (var curRow = Cell.Row.Index; curRow < Cell.Row.Index + VMerge_Count; curRow++) { this.RemoveTableRow(curRow); } return true; } if (Cell.Get_Border(0).Value === 0 && Cell.Get_Border(1).Value === 0 && Cell.Get_Border(3).Value === 0) { for (var curRow = Cell.Row.Index; curRow < Cell.Row.Index + VMerge_Count; curRow++) { this.RemoveTableRow(curRow); } return true; } if (Cell.Get_Border(0).Value === 0 && Cell.Get_Border(2).Value === 0 && Cell.Get_Border(3).Value === 0) { for (var curRow = Cell.Row.Index; curRow < Cell.Row.Index + VMerge_Count; curRow++) { this.RemoveTableRow(curRow); } return true; } } else if (Cell.Row.Get_CellsCount() === 1 && Cell.Row.Index === this.Get_RowsCount() - 1) { if (Cell.Get_Border(0).Value === 0 && Cell.Get_Border(1).Value === 0 && Cell.Get_Border(2).Value === 0) { for (var curRow = Cell.Row.Index; curRow < Cell.Row.Index + VMerge_Count; curRow++) { this.RemoveTableRow(curRow); } return true; } if (Cell.Get_Border(0).Value === 0 && Cell.Get_Border(3).Value === 0 && Cell.Get_Border(2).Value === 0) { for (var curRow = Cell.Row.Index; curRow < Cell.Row.Index + VMerge_Count; curRow++) { this.RemoveTableRow(curRow); } return true; } if (Cell.Get_Border(1).Value === 0 && Cell.Get_Border(3).Value === 0 && Cell.Get_Border(2).Value === 0) { for (var curRow = Cell.Row.Index; curRow < Cell.Row.Index + VMerge_Count; curRow++) { this.RemoveTableRow(curRow); } return true; } } else if (Cell.Row.Get_CellsCount() === 1) { if (Cell.Get_Border(0).Value === 0 && Cell.Get_Border(1).Value === 0 && Cell.Get_Border(2).Value === 0 && Cell.Get_Border(3).Value === 0) { for (var curRow = Cell.Row.Index; curRow < Cell.Row.Index + VMerge_Count; curRow++) { this.RemoveTableRow(curRow); } return true; } } } else if (!click) { if (Cell.Row.Get_CellsCount() === 1) { if (Cell.Get_Border(1).Value === 0 && Cell.Get_Border(3).Value === 0 && Cell.Get_Border(2).Value === 0 || Cell.Get_Border(1).Value === 0 && Cell.Get_Border(3).Value === 0 && Cell.Get_Border(0).Value === 0) { for (var curRow = Cell.Row.Index; curRow < Cell.Row.Index + VMerge_Count; curRow++) { this.RemoveTableRow(curRow); } return true; } else if (Cell.Get_Border(0).Value === 0 && Cell.Get_Border(1).Value === 0 && Cell.Get_Border(2).Value === 0) { for (var curRow = Cell.Row.Index; curRow < Cell.Row.Index + VMerge_Count; curRow++) { this.RemoveTableRow(curRow); } return true; } else if (Cell.Get_Border(0).Value === 0 && Cell.Get_Border(3).Value === 0 && Cell.Get_Border(2).Value === 0) { for (var curRow = Cell.Row.Index; curRow < Cell.Row.Index + VMerge_Count; curRow++) { this.RemoveTableRow(curRow); } return true; } } } else if (click === undefined) { if (this.GetRow(cellPos.Row).Get_CellsCount() === 1) { if (cellPos.Row === 0) { if (Cell.Get_Border(1).Value === 0 && Cell.Get_Border(3).Value === 0 && Cell.Get_Border(0).Value === 0) { this.RemoveTableRow(cellPos.Row); return true; } else if (Cell.Get_Border(3).Value === 0 && Cell.Get_Border(0).Value === 0 && Cell.Get_Border(2).Value === 0) { this.RemoveTableRow(cellPos.Row); return true; } } else if (cellPos.Row === this.Get_RowsCount() - 1) { if (Cell.Get_Border(1).Value === 0 && Cell.Get_Border(3).Value === 0 && Cell.Get_Border(2).Value === 0) { this.RemoveTableRow(cellPos.Row); return true; } } else if (Cell.Get_Border(1).Value === 0 && Cell.Get_Border(3).Value === 0 && Cell.Get_Border(0).Value === 0 && Cell.Get_Border(2).Value === 0) { this.RemoveTableRow(cellPos.Row); return true; } } } return false; }; /** * Returns an array with cells that can be deleted (given the cell’s VMergeCount) * @param {object} cellPos - cell position * @return {Array} */ CTable.prototype.FindCellsToDelete = function(cellPos) { // Ячейка без границ может содержать вертикальное объединение, находим все ячейки в нем var CellsToDelete = []; var Row = this.GetRow(cellPos.Row); var Cell = Row.Get_Cell(cellPos.Cell); var Grid_start = Row.Get_CellInfo(cellPos.Cell).StartGridCol; var Grid_span = Cell.Get_GridSpan(); var VMerge_Count = this.Internal_GetVertMergeCount(cellPos.Row, Grid_start, Grid_span); // Проверка какие ячейки стоит удалить // Если ячейка находится внешне слева if (Cell.Index === 0) { // Если у ячейки отсутствуют все внешние границы, то её нужно будет удалить if (Cell.GetBorder(0).Value === 0 && this.GetCellByStartGridCol(cellPos.Row + VMerge_Count - 1, Grid_start).GetBorder(2).Value === 0 && Cell.GetBorder(3).Value === 0) { for (var curRow = Cell.Row.Index; curRow < Cell.Row.Index + VMerge_Count; curRow++) { var TempCell = this.GetCellByStartGridCol(curRow, Grid_start); if (TempCell) { // т.к. ячейка может иметь верт. объединение необходимо это учитывать // и добавить в Cells все ячейки входящие в это объединение if (TempCell.GetVMerge() === 2) { CellsToDelete.push(TempCell); } else if (TempCell.GetVMerge() === 1) { CellsToDelete.push(TempCell); } } } } } // Если ячейка находится внешне справа else if (Cell.Index === this.GetRow(Cell.Row.Index).Get_CellsCount() - 1) { if (Cell.GetBorder(0).Value === 0 && this.GetCellByStartGridCol(cellPos.Row + VMerge_Count - 1, Grid_start).GetBorder(2).Value === 0 && Cell.GetBorder(1).Value === 0) { for (var curRow = Cell.Row.Index; curRow < Cell.Row.Index + VMerge_Count; curRow++) { var TempCell = this.GetCellByStartGridCol(curRow, Grid_start); if (TempCell) { if (TempCell.GetVMerge() === 2) { CellsToDelete.push(TempCell); } else if (TempCell.GetVMerge() === 1) { CellsToDelete.push(TempCell); } } } } } return CellsToDelete; }; /** * Sets a new grid for the table, considering the cells that need to be removed * @param {Array} CellsToDelete - cells to be deleted * @return {Bool} - returns false if @param CellsToDelete is empty */ CTable.prototype.CreateNewGridWithoutCells = function(CellsToDelete) { // Генерация новой сетки // учитывая ячейки, которые будем удалять if (CellsToDelete.length > 0) { var rowsInfo = []; for (var curRow = 0; curRow < this.Get_RowsCount(); curRow++) { var goToNextRow = false; var cellsInfo = []; for (var curCell = 0; curCell < this.GetRow(curRow).Get_CellsCount(); curCell++) { if (goToNextRow) break; var isContinue = false; var ViewCell = this.GetRow(curRow).Get_Cell(curCell); for (var nTempCellIndex = 0, nTempCellsLength = CellsToDelete.length; nTempCellIndex < nTempCellsLength; ++nTempCellIndex) { var cur_cell = CellsToDelete[nTempCellIndex]; if (ViewCell.Id === cur_cell.Id && cur_cell.Index === 0) { var grid_span = cur_cell.Get_GridSpan(); var grid_start = cur_cell.Row.Get_CellInfo(cur_cell.Index).StartGridCol; if (this.GetRow(curRow).Get_CellsCount() !== 1) { var cell = { W : this.TableSumGrid[grid_start + grid_span - 1], Type : -1, Grid_span : 1 }; cellsInfo[cellsInfo.length] = cell; isContinue = true; cur_cell.Row.RemoveCell(cur_cell.Index); curCell--; break; } else { this.RemoveTableRow(cur_cell.GetRow().GetIndex()); curRow--; goToNextRow = true; isContinue = true; break; } } else if (ViewCell.Id === cur_cell.Id && cur_cell.Index === cur_cell.Row.Get_CellsCount() - 1) { this.CurCell = cur_cell; cur_cell.Row.RemoveCell(cur_cell.Index); isContinue = true; } } if (goToNextRow) break; if (isContinue) continue; var Grid_start = this.GetRow(curRow).Get_CellInfo(curCell).StartGridCol; var Grid_span = this.GetRow(curRow).Get_Cell(curCell).Get_GridSpan(); var X_start = this.TableSumGrid[Grid_start - 1]; var X_end = this.TableSumGrid[Grid_start + Grid_span - 1]; var cellWidth = X_end - X_start; //Проверяем есть ли отступ у строки перед первой ячейкой, если да, то учитываем это в сетке //GridBefore строки должен совпадать с Grid_Start ячейки(перед которой отступ), чтобы условие выполнилось ровно один раз if (this.GetRow(curRow).Get_Before().GridBefore >= 1 && Grid_start === this.GetRow(curRow).Get_Before().GridBefore) { var cell_Indent = { W: X_end - cellWidth, Type: -1, Grid_span: 1 }; cellsInfo[cellsInfo.length] = cell_Indent; } var cell = { W: cellWidth, Type: 0, GridSpan: 1 }; cellsInfo[cellsInfo.length] = cell; rowsInfo[curRow] = cellsInfo; } } if (rowsInfo.length !== 0) this.SetTableGrid(this.Internal_CreateNewGrid(rowsInfo)); return true; } else return false; }; CTable.prototype.GetDrawLine = function(X1, Y1, X2, Y2, CurPageStart, CurPageEnd, drawMode) { var X1_origin = 0; var X2_origin = 0; X1_origin += X1; X2_origin += X2; var Y1_origin = 0; var Y2_origin = 0; Y1_origin += Y1; Y2_origin += Y2; // Приводим к координатам таблицы X1 = X1 - this.Pages[CurPageStart].X; X2 = X2 - this.Pages[CurPageStart].X; if (X1 > X2) { var cache; cache = X2; X2 = X1; X1 = cache; } if (drawMode === true) { if (Y1 < 0) Y1 = 0; if (Y2 < 0) Y2 = 0; var borders = []; // Рисуем вертикальную линию if (Math.abs(Y2 - Y1) > 2 && Math.abs(X2 - X1) < 3) { //если поставили просто точку => выход из функции if (Y1 === Y2) return; //если рисуем линию снизу вверх if (Y1 > Y2) { var cache; cache = Y2; Y2 = Y1; Y1 = cache; } var Rows = []; // массив номеров строк подлежащих делению (которые мы режем) var CellsIndexes = []; // Индексы ячеек в Rows, которые были задеты линией деления // Находим строки, попавшие под линию деления Rows = this.GetAffectedRows(X1, Y1, X2, Y2, CurPageStart, 0); var StartRow = Rows[0]; var EndRow = Rows[Rows.length - 1]; // Находим ячейки, попавшие под линию деления for (var Index = 0; Index < Rows.length; Index++) { for (var curCell = 0; curCell < this.GetRow(Rows[Index]).Get_CellsCount(); curCell++) { if (X1 > this.GetRow(Rows[Index]).CellsInfo[curCell].X_cell_start && X1 < this.GetRow(Rows[Index]).CellsInfo[curCell].X_cell_end) CellsIndexes[Rows[Index]] = curCell; } } // Если задетых ячеек нет, просто возвращаем линию с изначальными координатами if (CellsIndexes.length === 0) { var Line = { X1 : X1_origin, X2 : X2_origin, Y1 : Y1_origin, Y2 : Y2_origin, Color : "Red", Bold : false }; borders.push(Line); return borders; } var Row = this.GetRow(Rows[0]); var Cell = null; for (var Index = 0; Index < CellsIndexes.length; Index++) { if (CellsIndexes[Index] !== undefined) { Cell = this.GetRow(Index).Get_Cell(CellsIndexes[Index]); break; } } if (Y2 - Y1 >= this.RowsInfo[Rows[0]].H[CurPageStart]/2) { if (Math.abs(Cell.Metrics.X_cell_start - X1) <= 1.5) { var Vline = { X1 : Cell.Metrics.X_cell_start + this.Pages[CurPageStart].X, X2 : Cell.Metrics.X_cell_start + this.Pages[CurPageStart].X, Y1 : this.RowsInfo[StartRow].Y[CurPageStart], Y2 : this.RowsInfo[EndRow].Y[CurPageStart] + this.RowsInfo[EndRow].H[CurPageStart], Color : "Grey", Bold : true }; borders.push(Vline); } else if (Math.abs(Cell.Metrics.X_cell_end - X1) <= 1.5) { var Vline = { X1 : Cell.Metrics.X_cell_end + this.Pages[CurPageStart].X, X2 : Cell.Metrics.X_cell_end + this.Pages[CurPageStart].X, Y1 : this.RowsInfo[StartRow].Y[CurPageStart], Y2 : this.RowsInfo[EndRow].Y[CurPageStart] + this.RowsInfo[EndRow].H[CurPageStart], Color : "Grey", Bold : true }; borders.push(Vline); } else { var Vline = { X1 : X1_origin, X2 : X1_origin, Y1 : this.RowsInfo[StartRow].Y[CurPageStart], Y2 : this.RowsInfo[EndRow].Y[CurPageStart] + this.RowsInfo[EndRow].H[CurPageStart], Color : "Grey", Bold : false }; borders.push(Vline); } } else if (Y2 - Y1 < this.RowsInfo[Rows[0]].H[CurPageStart]/2) { var Vline = { X1 : X1_origin, X2 : X2_origin, Y1 : Y1_origin, Y2 : Y2_origin, Color : "Red", Bold : false }; borders.push(Vline); } return borders; } // Рисуем горизонтальную линию else if (Math.abs(X2 - X1) > 2 && Math.abs(Y2 - Y1) < 3) { if (X1 === X2) return; if (X1 > X2) { var cache; cache = X2; X2 = X1; X1 = cache; } var RowNumb = []; // Строка, попавшая в вертикальное разбиение var CellsIndexes = []; // Массив номеров ячеек, попавших в вертикальное разбиение RowNumb = this.GetAffectedRows(X1, Y1, X2, Y2, CurPageStart, 1); // Если никакие строки не задеты, просто рисуем линию по изначальным координатам if (RowNumb.length === 0) { var Line = { X1 : X1_origin, X2 : X2_origin, Y1 : Y1, Y2 : Y2, Color : "Red", Bold : false }; borders.push(Line); return borders; } // Если строки были задеты, то заполняем массив ячейками, где индекс массива = индекс строки, значение равно индексу ячейки else { for (var curCell = 0; curCell < this.GetRow(RowNumb[0]).Get_CellsCount(); curCell++) { if (X1 < this.GetRow(RowNumb[0]).CellsInfo[curCell].X_cell_start && X2 > this.GetRow(RowNumb[0]).CellsInfo[curCell].X_cell_start || X1 < this.GetRow(RowNumb[0]).CellsInfo[curCell].X_cell_end && X2 > this.GetRow(RowNumb[0]).CellsInfo[curCell].X_cell_end || X1 > this.GetRow(RowNumb[0]).CellsInfo[curCell].X_cell_start && X2 < this.GetRow(RowNumb[0]).CellsInfo[curCell].X_cell_end) CellsIndexes.push(curCell); } } // Если строки были задеты, но ячейки нет, просто рисуем линию по начальным координатам if (CellsIndexes.length === 0) { var Line = { X1 : X1_origin, X2 : X2_origin, Y1 : Y1, Y2 : Y2, Color : "Red", Bold : false }; borders.push(Line); return borders; } if (Math.abs(X2_origin - X1_origin) >= (this.GetRow(RowNumb[0]).Get_Cell(CellsIndexes[0]).Metrics.X_cell_end - this.GetRow(RowNumb[0]).Get_Cell(CellsIndexes[0]).Metrics.X_cell_start)/2 || Math.abs(X2_origin - X1_origin) < (this.GetRow(RowNumb[0]).Get_Cell(CellsIndexes[0]).Metrics.X_cell_end - this.GetRow(RowNumb[0]).Get_Cell(CellsIndexes[0]).Metrics.X_cell_start)/2) { if (Math.abs(this.RowsInfo[RowNumb[0]].Y[CurPageStart] - Y1) <= 1.5) { var Row = this.GetRow(RowNumb[0]); var startCell = Row.Get_Cell(CellsIndexes[0]); var endCell = Row.Get_Cell(CellsIndexes[CellsIndexes.length - 1]); if (startCell.GetVMerge() === 2) { var Hline = { Y1 : this.RowsInfo[RowNumb[0]].Y[CurPageStart], Y2 : this.RowsInfo[RowNumb[0]].Y[CurPageStart], X1 : startCell.Metrics.X_cell_start + this.Pages[CurPageStart].X, X2 : endCell.Metrics.X_cell_end + this.Pages[CurPageStart].X, Color : "Grey", Bold : false }; borders.push(Hline); } else { var Hline = { Y1 : this.RowsInfo[RowNumb[0]].Y[CurPageStart], Y2 : this.RowsInfo[RowNumb[0]].Y[CurPageStart], X1 : startCell.Metrics.X_cell_start + this.Pages[CurPageStart].X, X2 : endCell.Metrics.X_cell_end + this.Pages[CurPageStart].X, Color : "Grey", Bold : true }; borders.push(Hline); } } else if (Math.abs(this.RowsInfo[RowNumb[0]].Y[CurPageStart] + this.RowsInfo[RowNumb[0]].H[CurPageStart] - Y1) <= 1.5) { var Row = this.GetRow(RowNumb[0]); var startCell = Row.Get_Cell(CellsIndexes[0]); var endCell = Row.Get_Cell(CellsIndexes[CellsIndexes.length - 1]); var Grid_start = Row.Get_CellInfo(startCell.Index).StartGridCol; var Grid_span = startCell.Get_GridSpan(); var VMerge_count = this.Internal_GetVertMergeCount(Row.Index, Grid_start, Grid_span); if (VMerge_count > 1) { var Hline = { Y1 : this.RowsInfo[RowNumb[0]].Y[CurPageStart] + this.RowsInfo[RowNumb[0]].H[CurPageStart], Y2 : this.RowsInfo[RowNumb[0]].Y[CurPageStart] + this.RowsInfo[RowNumb[0]].H[CurPageStart], X1 : startCell.Metrics.X_cell_start + this.Pages[CurPageStart].X, X2 : endCell.Metrics.X_cell_end + this.Pages[CurPageStart].X, Color : "Grey", Bold : false }; borders.push(Hline); } else { var Hline = { Y1 : this.RowsInfo[RowNumb[0]].Y[CurPageStart] + this.RowsInfo[RowNumb[0]].H[CurPageStart], Y2 : this.RowsInfo[RowNumb[0]].Y[CurPageStart] + this.RowsInfo[RowNumb[0]].H[CurPageStart], X1 : startCell.Metrics.X_cell_start + this.Pages[CurPageStart].X, X2 : endCell.Metrics.X_cell_end + this.Pages[CurPageStart].X, Color : "Grey", Bold : true }; borders.push(Hline); } } else { var Hline = { Y1 : Y1, Y2 : Y1, X1 : this.GetRow(RowNumb[0]).Get_Cell(CellsIndexes[0]).Metrics.X_cell_start + this.Pages[CurPageStart].X, X2 : this.GetRow(RowNumb[0]).Get_Cell(CellsIndexes[CellsIndexes.length - 1]).Metrics.X_cell_end + this.Pages[CurPageStart].X, Color : "Grey", Bold : false }; borders.push(Hline); } } return borders; } else { var Cell_pos = this.private_GetCellByXY(X1 + this.Pages[CurPageStart].X, Y1, CurPageStart); var Row = this.GetRow(Cell_pos.Row); var Cell = Row.Get_Cell(Cell_pos.Cell); //текущая ячейка var X_start = Row.CellsInfo[Cell_pos.Cell].X_cell_start; var X_end = Row.CellsInfo[Cell_pos.Cell].X_cell_end; var Cell_width = X_end - X_start; var Grid_start = Row.Get_CellInfo(Cell_pos.Cell).StartGridCol; var Grid_span = Cell.Get_GridSpan(); var VMerge_count = this.Internal_GetVertMergeCount(Cell_pos.Row, Grid_start, Grid_span); var rowHSum = 0; var CellSpacing = Row.Get_CellSpacing(); var CellMar = Cell.GetMargins(); var MinW = CellSpacing + CellMar.Right.W + CellMar.Left.W; if (VMerge_count >= 1) { for (var Index = Cell_pos.Row; Index < Cell_pos.Row + VMerge_count; Index++) { rowHSum += this.RowsInfo[Index].H[CurPageStart] } } // Если рисуемая ячейка соответствует минимальным размерам и не выходит за границы ячейки, в котором рисуем, тогда отрисовываем контуры новой ячейки if (Cell_width >= MinW * 1.5 && X2 - X1 > MinW * 1.5 && rowHSum >= 4.63864881727431 * 1.5 && Math.abs(Y2 - Y1) >= 4.63864881727431 * 1.5 && !(X2 > X_end || Y2 < this.RowsInfo[Cell_pos.Row].Y[CurPageStart] || Y2 > this.RowsInfo[Cell_pos.Row].Y[CurPageStart] + rowHSum)) { var tLine = { X1 : X1_origin, X2 : X2_origin, Y1 : Y1, Y2 : Y1, Color : "Grey", Bold : false }; var lLine = { X1 : X1_origin, X2 : X1_origin, Y1 : Y1, Y2 : Y2, Color : "Grey", Bold : false }; var rLine = { X1 : X2_origin, X2 : X2_origin, Y1 : Y1, Y2 : Y2, Color : "Grey", Bold : false }; var bLine = { X1 : X1_origin, X2 : X2_origin, Y1 : Y2, Y2 : Y2, Color : "Grey", Bold : false }; borders.push(tLine, lLine, rLine, bLine); } else { var Line = { X1 : X1_origin, X2 : X2_origin, Y1 : Y1, Y2 : Y2, Color : "Red", Bold : false }; borders.push(Line); } return borders; } } else if (drawMode === false) { if (X1 > X2) { var cache; cache = X2; X2 = X1; X1 = cache; } if (Y1 > Y2) { var cache; cache = Y2; Y2 = Y1; Y1 = cache; } var Rows = []; // Строки попавшие под линию удаления(объединения) var Borders = []; this.Selection.Data = []; var SizeOfIndent = this.Pages[0].X; SizeOfIndent += (this.Pages[CurPageStart].X - this.Pages[CurPageStart].X - (this.Pages[0].X - this.Pages[CurPageStart].X)); // Индексы строк, попавших под режущую линию Rows = this.GetAffectedRows(X1, Y1, X2, Y2, CurPageStart, 2); // Далее мы определяем, какие ячейки в строках(попавших под выделение) попадают под выделение // и заполняем this.Selection.Data for (var curRow = 0; curRow < this.Get_RowsCount(); curRow++) { // Проверка строки на наличие в массиве Rows if (Rows.indexOf(curRow) != -1) { for (var curCell = 0; curCell < this.GetRow(curRow).Get_CellsCount(); curCell++) { var Cell = this.GetRow(curRow).Get_Cell(curCell); var Row = this.GetRow(curRow); var Grid_start = Row.Get_CellInfo(curCell).StartGridCol; var Grid_span = Cell.Get_GridSpan(); var VMerge_count = this.Internal_GetVertMergeCount(curRow, Grid_start, Grid_span); if (X1 < this.GetRow(curRow).CellsInfo[curCell].X_cell_start && X2 > this.GetRow(curRow).CellsInfo[curCell].X_cell_start || X1 < this.GetRow(curRow).CellsInfo[curCell].X_cell_end && X2 > this.GetRow(curRow).CellsInfo[curCell].X_cell_end || X1 > this.GetRow(curRow).CellsInfo[curCell].X_cell_start && X2 < this.GetRow(curRow).CellsInfo[curCell].X_cell_end) { for (var curRow2 = curRow; curRow2 >= 0; curRow2--) { var TempCell = this.GetCellByStartGridCol(curRow2, Grid_start); if (!TempCell) continue; var TempRow = this.GetRow(curRow2); var TempGrid_start = Row.Get_CellInfo(curCell).StartGridCol; var TempGrid_span = Cell.Get_GridSpan(); var TempVMerge_count = this.Internal_GetVertMergeCount(TempRow.Index, TempGrid_start, TempGrid_span); var TempRowHSum = 0; if (TempVMerge_count >= 1) { for (var Index = TempRow.Index; Index < TempRow.Index + TempVMerge_count; Index++) { TempRowHSum += this.RowsInfo[Index].H[CurPageStart] } } if (TempCell.GetVMerge() === 1) { var cell_pos = { Cell : TempCell.GetIndex(), Row : curRow2, } for (var Index = 0; Index < this.Selection.Data.length; Index++) { if (cell_pos.Row === this.Selection.Data[Index].Row && cell_pos.Cell === this.Selection.Data[Index].Cell) { break; } } this.Selection.Data.push(cell_pos); if (X1 <= TempCell.Metrics.X_cell_start) { var Line = { X1 : TempCell.Metrics.X_cell_start + SizeOfIndent, X2 : TempCell.Metrics.X_cell_start + SizeOfIndent, Y1 : this.RowsInfo[TempCell.Row.Index].Y[CurPageStart], Y2 : this.RowsInfo[TempCell.Row.Index].Y[CurPageStart] + TempRowHSum, Color : "Red", Bold : false }; Borders.push(Line); } if (X2 >= TempCell.Metrics.X_cell_end) { var Line = { X1 : TempCell.Metrics.X_cell_end + SizeOfIndent, X2 : TempCell.Metrics.X_cell_end + SizeOfIndent, Y1 : this.RowsInfo[TempCell.Row.Index].Y[CurPageStart], Y2 : this.RowsInfo[TempCell.Row.Index].Y[CurPageStart] + TempRowHSum, Color : "Red", Bold : false }; Borders.push(Line); } if (Y1 <= this.RowsInfo[TempCell.Row.Index].Y[CurPageStart] && Y2 > this.RowsInfo[TempCell.Row.Index].Y[CurPageStart] ) { var Line = { X1 : TempCell.Metrics.X_cell_start + SizeOfIndent, X2 : TempCell.Metrics.X_cell_end + SizeOfIndent, Y1 : this.RowsInfo[TempCell.Row.Index].Y[CurPageStart], Y2 : this.RowsInfo[TempCell.Row.Index].Y[CurPageStart], Color : "Red", Bold : false }; Borders.push(Line); } if (Y2 >= this.RowsInfo[TempCell.Row.Index].Y[CurPageStart] + TempRowHSum && Y1 < this.RowsInfo[TempCell.Row.Index].Y[CurPageStart] + TempRowHSum) { var Line = { X1 : TempCell.Metrics.X_cell_start + SizeOfIndent, X2 : TempCell.Metrics.X_cell_end + SizeOfIndent, Y1 : this.RowsInfo[TempCell.Row.Index].Y[CurPageStart] + TempRowHSum, Y2 : this.RowsInfo[TempCell.Row.Index].Y[CurPageStart] + TempRowHSum, Color : "Red", Bold : false }; Borders.push(Line); } break; } } } } } else continue; } // Удаление одинаковых линий for (var Index1 = 0; Index1 <= Borders.length - 1; Index1++) { for (var Index2 = Index1 + 1; Index2 < Borders.length; Index2++) { if (Borders[Index1].X1 == Borders[Index2].X1) { if (Borders[Index1].X2 == Borders[Index2].X2) { if (Borders[Index1].Y1 == Borders[Index2].Y1) { if (Borders[Index1].Y2 == Borders[Index2].Y2) { Borders.splice(Index2, 1); Index2--; } } } } } } return Borders; } }; CTable.prototype.DrawCellInCell = function(X1, Y1, X2, Y2, CurPageStart) { if (Y1 > Y2) { var cache = Y2; Y2 = Y1; Y1 = cache; } if (X1 > X2) { var cache = X2; X2 = X1; X1 = cache; } var Cell_pos = this.private_GetCellByXY(X1 + this.Pages[CurPageStart].X, Y1, CurPageStart); var oRow = this.GetRow(Cell_pos.Row); var oCell = oRow.GetCell(Cell_pos.Cell); //текущая ячейка var oCellContent = oCell.GetContent(); var nInnerPos = oCellContent.Internal_GetContentPosByXY(X1 + this.Pages[CurPageStart].X, Y1, CurPageStart - oCellContent.GetRelativeStartPage()); var nInnerCount = oCellContent.GetElementsCount(); while (!oCellContent.GetElement(nInnerPos).IsParagraph()) { nInnerPos++; if (nInnerPos >= nInnerCount) { // Такого не должно происходить, последний элемент всегда должен быть параграф return; } } var oParagraph = oCellContent.GetElement(nInnerPos); if (!oParagraph || !oParagraph.IsParagraph()) return; oCellContent.CurPos.ContentPos = nInnerPos; oParagraph.MoveCursorToStartPos(); var oCellInfo = oRow.GetCellInfo(Cell_pos.Cell); if (!oCellInfo) return; var X_start = oCellInfo.X_cell_start; var X_end = oCellInfo.X_cell_end; var Cell_width = X_end - X_start; var Grid_start = oCellInfo.StartGridCol; var Grid_span = oCell.GetGridSpan(); var VMerge_count = this.Internal_GetVertMergeCount(Cell_pos.Row, Grid_start, Grid_span); var CellMar = oCell.GetMargins(); var MinW = oRow.GetCellSpacing() + CellMar.Right.W + CellMar.Left.W; var rowHSum = 0; if (VMerge_count >= 1) { for (var Index = Cell_pos.Row; Index < Cell_pos.Row + VMerge_count; Index++) { rowHSum += this.RowsInfo[Index].H[CurPageStart] } } // Если выходим за пределы текущей ячейки, не создаем новую if (X2 > X_end || X1 < X_start || Y1 < this.RowsInfo[Cell_pos.Row].Y[CurPageStart] || Y2 > this.RowsInfo[Cell_pos.Row].Y[CurPageStart] + rowHSum) { return; } if (Cell_width >= MinW * 1.5 && X2 - X1 > MinW * 1.5 && rowHSum >= 4.63864881727431 * 1.5 && Y2 - Y1 >= 4.63864881727431 * 1.5) { var oTable = oCellContent.AddInlineTable(1, 1); if (oTable && oTable.GetRowsCount() > 0) { oTable.Set_Inline(false); oTable.Set_PositionH(c_oAscHAnchor.Page, false, X1 - X_start); oTable.Set_PositionV(c_oAscVAnchor.Page, false, Y1 - this.RowsInfo[Cell_pos.Row].Y[CurPageStart]); oTable.GetRow(0).SetHeight(Math.abs(this.LogicDocument.DrawTableMode.EndY - this.LogicDocument.DrawTableMode.StartY), Asc.linerule_AtLeast); oTable.Set_TableW(tblwidth_Mm, Math.abs(this.LogicDocument.DrawTableMode.EndX - this.LogicDocument.DrawTableMode.StartX - new CDocumentBorder().Size * 2)); oTable.Set_Distance(3.2, undefined, 3.2, undefined); oTable.MoveCursorToStartPos(); oTable.Document_SetThisElementCurrent(); } } }; CTable.prototype.DrawBorderByClick = function(X1, Y1, CurPageStart) { // Проверка, была ли выбрана граница (для случая, когда щелкаем по границе); // Проверка, были ли выбраны начало и конец выделения // *Необходимо для случаев, когда у ячейки VMerge_count > 1* var SelectedCells = this.GetCellAndBorderByClick(X1, Y1, CurPageStart, true); var isVSelect = SelectedCells.isVSelect; // Была ли выбрана вертикальная граница var isHSelect = SelectedCells.isHSelect; // Была ли выбрана горизонтальная граница var isRightBorder = SelectedCells.isRightBorder; var isLeftBorder = SelectedCells.isLeftBorder; var isTopBorder = SelectedCells.isTopBorder; var isBottomBorder = SelectedCells.isBottomBorder; if (SelectedCells.Cells.length === 0) return false; else if (isRightBorder || isLeftBorder || isTopBorder || isBottomBorder || isVSelect || isHSelect) this.Selection.Data = SelectedCells.Cells; else return true; //отрисовка бордеров if (this.Selection.Data.length === 1) { var Cell_pos = this.Selection.Data[0]; var Row = this.GetRow(Cell_pos.Row); var Cell = Row.Get_Cell(this.Selection.Data[0].Cell); // Отрисовка горизонтальных внешних границ if (isHSelect) { if (isTopBorder) { Cell.CheckNonEmptyBorder(0); } else if (isBottomBorder) { Cell.CheckNonEmptyBorder(2); } } // Отрисовка вертикальных внешних границ else if (isVSelect) { if (isRightBorder) { Cell.CheckNonEmptyBorder(1); } else if (isLeftBorder) { Cell.CheckNonEmptyBorder(3); } } } else if (this.Selection.Data.length === 2) { if (isHSelect) { var Cell_1_pos = this.Selection.Data[0]; var Cell_2_pos = this.Selection.Data[1]; var Row_1 = this.GetRow(Cell_1_pos.Row); var Row_2 = this.GetRow(Cell_2_pos.Row); var Cell_1 = Row_1.Get_Cell(Cell_1_pos.Cell); var Cell_2 = Row_2.Get_Cell(Cell_2_pos.Cell); var Grid_start_1 = Row_1.Get_CellInfo(Cell_1_pos.Cell).StartGridCol; var Grid_span_1 = Cell_1.Get_GridSpan(); var VMerge_count_1 = this.Internal_GetVertMergeCount(Cell_1_pos.Row, Grid_start_1, Grid_span_1); if (VMerge_count_1 > 1) { Cell_1 = this.GetCellByStartGridCol(Cell_1_pos.Row + VMerge_count_1 - 1, Grid_start_1); } Cell_1.CheckNonEmptyBorder(2); Cell_2.CheckNonEmptyBorder(0); } else if (isVSelect) { var Cell_1 = this.GetRow(this.Selection.Data[0].Row).Get_Cell(this.Selection.Data[0].Cell); var Cell_2 = this.GetRow(this.Selection.Data[1].Row).Get_Cell(this.Selection.Data[1].Cell); Cell_1.CheckNonEmptyBorder(1); Cell_2.CheckNonEmptyBorder(3); } } }; /** * Deletes part of the table (row, column or the whole table) * @param {bool} X_Front - selection started in front of table grid * @param {bool} X_After - selection ended after grid table * @param {bool} Y_Over - selection began above the first row of the table * @param {bool} Y_Under - selection ended below the last row of the table * @param {bool} bCanMerge - Is it possible to merge cells under selection * @return {bool} - returns true if any part of the table has been deleted */ CTable.prototype.DeleteTablePart = function(X_Front, X_After, Y_Over, Y_Under, bCanMerge) { // Если вся таблица внутри выделения - удаляем её if (X_Front && X_After && Y_Over && Y_Under) { for (var Index = 0, rowsCount = this.GetRowsCount(); Index < rowsCount; Index++) { this.RemoveTableRow(0); } return true; } // Если выделяем целиком колонку - удаляем её else if (Y_Over && Y_Under && bCanMerge) { let nLastRow = this.Selection.Data[this.Selection.Data.length - 1].Row; let nLastCell = this.Selection.Data[this.Selection.Data.length - 1].Cell; let nVMergeCount = this.GetVMergeCount(nLastCell, nLastRow); if (this.Selection.Data[0].Row === 0 && nLastRow + nVMergeCount === this.GetRowsCount()) { this.Selection.Use = true; this.Selection.Type = 0; this.RemoveTableColumn(); this.Selection.Use = false; return true; } return false; } // Если выделяем строку или несколько строк - удалям их else if (X_Front && X_After && bCanMerge) { var del_count = 0; for (var curRow = this.Selection.Data[0].Row; curRow <= this.Selection.Data[this.Selection.Data.length - 1].Row; curRow++) { if (del_count === this.Selection.Data[this.Selection.Data.length - 1].Row - this.Selection.Data[0].Row + 1) return true; this.RemoveTableRow(curRow); curRow = this.Selection.Data[0].Row - 1; del_count += 1; } return true; } return false; }; /** * Delete border between cells * @param {object} Cell_pos_1 - position of first cell * @param {object} Cell_pos_2 - position of second cell * @return {bool} - returns true if border was deleted */ CTable.prototype.DeleteBorderBetweenCells = function(Cell_pos_1, Cell_pos_2) { var Row_1 = this.GetRow(Cell_pos_1.Row); var Cell_1 = Row_1.Get_Cell(Cell_pos_1.Cell); var Grid_start_1 = Row_1.Get_CellInfo(Cell_pos_1.Cell).StartGridCol; var Grid_span_1 = Cell_1.Get_GridSpan(); var Grid_end_1 = Grid_start_1 + Grid_span_1 - 1; var VMerge_count_1 = this.Internal_GetVertMergeCount(Row_1.GetIndex(), Grid_start_1, Grid_span_1); var Row_2 = this.GetRow(Cell_pos_2.Row); var Cell_2 = Row_2.Get_Cell(Cell_pos_2.Cell); var Grid_start_2 = Row_2.Get_CellInfo(Cell_pos_2.Cell).StartGridCol; var Grid_span_2 = Cell_2.Get_GridSpan(); var Grid_end_2 = Grid_start_2 + Grid_span_2 - 1; var VMerge_count_2 = this.Internal_GetVertMergeCount(Row_2.GetIndex(), Grid_start_2, Grid_span_2); // Определяем взаимное расположение ячеек, удаляем нужные границы if (Grid_end_1 === Grid_start_2 - 1 && ((Cell_pos_2.Row >= Cell_pos_1.Row && Cell_pos_2.Row <= Cell_pos_1.Row + VMerge_count_1 -1) || Cell_pos_1.Row >= Cell_pos_2.Row && Cell_pos_1.Row <= Cell_pos_2.Row + VMerge_count_2 -1)) { // Стираем границу Cell_1.CheckEmptyBorder(1); Cell_2.CheckEmptyBorder(3); return true; } else if (Grid_end_2 === Grid_start_1 - 1 && ((Cell_pos_1.Row >= Cell_pos_2.Row && Cell_pos_1.Row <= Cell_pos_2.Row + VMerge_count_2 -1) || Cell_pos_2.Row >= Cell_pos_1.Row && Cell_pos_2.Row <= Cell_pos_1.Row + VMerge_count_1 -1)) { // Стираем границу Cell_1.CheckEmptyBorder(3); Cell_2.CheckEmptyBorder(1); return true; } // Определяем взаимное расположение ячеек, удаляем нужные границы else if (Cell_pos_1.Row + VMerge_count_1 - 1 === Cell_pos_2.Row - 1) { // Стираем границу Cell_1.CheckEmptyBorder(2); Cell_2.CheckEmptyBorder(0); return true; } else if (Cell_pos_2.Row + VMerge_count_2 - 1 === Cell_pos_1.Row - 1) { // Стираем границу Cell_1.CheckEmptyBorder(0); Cell_2.CheckEmptyBorder(2); return true; } return false; }; /** * Vertical splitting by coordinate X in given Rows * @param {number} X - coordinate * @param {number} RowsIndices - Indices of lines that fall under the cut line * @return {bool} - return true if cells were divided */ CTable.prototype.VertSplitCells = function(X, RowsIndices) { // Была ли добавлена ячейка var CellAdded = false; //Добавляем новые ячейки в горизонтальном разбиении for (var curRow = 0; curRow < this.Get_RowsCount(); curRow++) { for (var curCell = 0; curCell < this.GetRow(curRow).Get_CellsCount(); curCell++) { if ((X - this.GetRow(curRow).CellsInfo[curCell].X_cell_start > 1.5) && (this.GetRow(curRow).CellsInfo[curCell].X_cell_end - X > 1.5)) { //проверка текущей строки на наличие в массиве Rows if (RowsIndices.indexOf(curRow) != -1) { CellAdded = true; var Row = this.GetRow(curRow); //строка текущей ячейки var Cell = Row.Get_Cell(curCell); //текущая ячейка var X_start = Row.CellsInfo[curCell].X_grid_start; var X_end = Row.CellsInfo[curCell].X_grid_end; var Cell_pos = //позиция текущей ячейки { Cell: curCell, Row: curRow }; var Grid_start = Row.Get_CellInfo(Cell_pos.Cell).StartGridCol;//столбец, с которого начинается ячейка var Grid_span = Cell.Get_GridSpan(); //кол-во столбцов, охваченных текущей ячейкой var VMerge_count = this.Internal_GetVertMergeCount(Cell_pos.Row, Grid_start, Grid_span); //кол-во строк охваченных тек. ячейкой var Cells = []; var Cells_pos = []; var Rows_ = []; for (var Index = 0; Index < VMerge_count; Index++) { var TempRow = this.GetRow(Cell_pos.Row + Index); Rows_[Index] = TempRow; Cells[Index] = null; Cells_pos[Index] = null; // Ищем ячейку, начинающуюся с Grid_start var CellsCount = TempRow.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var StartGridCol = TempRow.Get_CellInfo(CurCell).StartGridCol; if (StartGridCol === Grid_start) { Cells[Index] = TempRow.Get_Cell(CurCell); Cells_pos[Index] = { Row: Cell_pos.Row + Index, Cell: CurCell }; } } } //сделаем разбиение по горизонтали // Найдем позиции новых колонок в сетке var Sum_before = this.TableSumGrid[Grid_start - 1]; //координаты конца предыдущей ячейки var Sum_with = this.TableSumGrid[Grid_start + Grid_span - 1]; //координаты конца текущей ячейки var Span_width = Sum_with - Sum_before; //ширина текущей ячейки var Grid_width_1 = X - X_start; var Grid_width_2 = X_end - X; var CellSpacing = Row.Get_CellSpacing(); var CellMar = Cell.GetMargins(); var MinW = CellSpacing + CellMar.Right.W + CellMar.Left.W; // В этих условиях мы проверяем допустимая ли ширина ячеек нами нарисована, // если меньше допустимой, устанавливаем ширину равную минимальной допустимой // если ширина делимой ячейки Span_width < Minw*2 то выдаем ошибку if (Grid_width_1 < MinW) { Grid_width_1 = MinW; Grid_width_2 = Span_width - Grid_width_1; if (Grid_width_2 < MinW) { Grid_width_2 = MinW; } if (Span_width < Grid_width_1 + Grid_width_2) { Span_width = Grid_width_1 + Grid_width_2; } } else if (Grid_width_2 < MinW) { Grid_width_2 = MinW; Grid_width_1 = Span_width - Grid_width_2; if (Grid_width_1 < MinW) { Grid_width_1 = MinW; } if (Span_width < Grid_width_1 + Grid_width_2) { Span_width = Grid_width_1 + Grid_width_2; } } // Данный массив содержит информацию о том сколько новых колонок // было добавлено после i-ой колонки var Grid_Info = []; for (var Index = 0; Index < this.TableGridCalc.length; Index++) Grid_Info[Index] = 0; // Массив содержит информацию о том сколько промежутков будет в // новых ячейках var Grid_Info_new = []; for (var Index = 0; Index < 2; Index++) Grid_Info_new[Index] = 1; var Grid_Info_start = []; for (var Index = 0; Index < this.TableGridCalc.length; Index++) Grid_Info_start[Index] = this.TableGridCalc[Index]; var NewCol_Index = 0; var CurWidth = Sum_before + Grid_width_1; for (var Grid_index = Grid_start; Grid_index < Grid_start + Grid_span; Grid_index++) { var bNewCol = true; // Если мы попали в уже имеющуюся границу не добавляем новую точку if (Math.abs(CurWidth - this.TableSumGrid[Grid_index]) < 0.001) { NewCol_Index++; CurWidth += Grid_width_2; bNewCol = false; continue; } while (CurWidth < this.TableSumGrid[Grid_index]) { if (0 === Grid_Info[Grid_index]) Grid_Info_start[Grid_index] = CurWidth - this.TableSumGrid[Grid_index - 1]; Grid_Info[Grid_index] += 1; NewCol_Index++ CurWidth += Grid_width_2; // Если мы попали в уже имеющуюся границу не добавляем новую точку if (Math.abs(CurWidth - this.TableSumGrid[Grid_index]) < 0.001) { NewCol_Index++; CurWidth += Grid_width_2; bNewCol = false; break; } } if (true === bNewCol) Grid_Info_new[NewCol_Index] += 1; } // Добавим в данной строке (Cols - 1) ячеек, с теми же настроками, // что и исходной. Значение GridSpan мы берем из массива Grid_Info_new for (var Index2 = 0; Index2 < Rows_.length; Index2++) { if (null != Cells[Index2] && null != Cells_pos[Index2]) { var TempRow = Rows_[Index2]; var TempCell = Cells[Index2]; var TempCell_pos = Cells_pos[Index2]; TempCell.Set_GridSpan(Grid_Info_new[0]); TempCell.Set_W(new CTableMeasurement(tblwidth_Mm, Grid_width_1)); var NewCell = TempRow.Add_Cell(TempCell_pos.Cell + 1, TempRow, null, false); NewCell.Copy_Pr(TempCell.Pr); NewCell.CopyParaPrAndTextPr(TempCell); NewCell.Set_GridSpan(Grid_Info_new[1]); NewCell.Set_W(new CTableMeasurement(tblwidth_Mm, Grid_width_2)); if (TempCell.GetBorder(3).Value === 0 && NewCell.GetBorder(1).Value === 0) { TempCell.CheckNonEmptyBorder(1); NewCell.CheckNonEmptyBorder(3); } } } if (VMerge_count > 1) { curRow += VMerge_count - 1; } break; } } else { if (RowsIndices.indexOf(curRow) != -1) { var Cell = this.GetRow(curRow).Get_Cell(curCell); if (Math.abs(X - this.GetRow(curRow).CellsInfo[curCell].X_cell_start) < 1.5) { Cell.CheckNonEmptyBorder(3); } else if (Math.abs(this.GetRow(curRow).CellsInfo[curCell].X_cell_end - X) < 1.5) { Cell.CheckNonEmptyBorder(1); } } } } } return CellAdded; }; /** * Vertical splitting by coordinate X in given Rows * @param {number} Y - coordinate * @param {number} RowIndex - Index of the row to be split * @return {bool} - return true if cells were divided */ CTable.prototype.HorSplitCells = function(Y, RowIndex, CellsIndexes, CurPageStart) { var CallAdded = false; // Если хотим разделить ячейку с VMerge > 1 и линия находится близка к линии строки (невидимой), то делим ячейку по этой линии for (var curCell = 0; curCell < this.GetRow(RowIndex).Get_CellsCount(); curCell++) { if (CellsIndexes.indexOf(curCell) != -1) //проверка ячейки на наличие в массиве Cells { CallAdded = true; var Cell = this.GetRow(RowIndex).Get_Cell(curCell); var Cell_pos = { Cell : curCell, Row : RowIndex }; var Row = this.GetRow(Cell_pos.Row); var Grid_start = Row.Get_CellInfo(Cell_pos.Cell).StartGridCol; var Grid_span = Cell.Get_GridSpan(); var VMerge_count = this.Internal_GetVertMergeCount(Cell_pos.Row, Grid_start, Grid_span); var CellVMerge = Cell.GetVMerge(); var Cells = []; var Cells_pos = []; var Rows_ = []; var ElmsToTransfer = []; var TempCell = null; if (VMerge_count > 1) { var TempRow = null; // Если попадаем в окрестность верхней границы ячейки, то добавляем границу сверху if (Math.abs(this.RowsInfo[RowIndex].Y[CurPageStart] - Y) <= 1.5) { TempRow = this.GetRow(Cell_pos.Row); TempCell = TempRow.Get_Cell(Cell_pos.Cell); TempCell.SetVMerge(vmerge_Restart); } // Если попадаем в окрестность нижней границы, то добавляем границу снизу else if (Math.abs(this.RowsInfo[RowIndex].Y[CurPageStart] + this.RowsInfo[RowIndex].H[CurPageStart]- Y) <= 1.5) { if (RowIndex != this.Get_RowsCount() - 1) { TempRow = this.GetRow(Cell_pos.Row + 1); TempCell = this.GetCellByStartGridCol(TempRow.GetIndex(), Grid_start); TempCell.SetVMerge(vmerge_Restart); } } } else { // Если попадаем в окрестность верхней границы ячейки, то добавляем границу сверху // необходимо для последней строки из строк которые входят в VMerge if (Math.abs(this.RowsInfo[RowIndex].Y[CurPageStart] - Y) <= 1.5) { var TempRow = this.GetRow(Cell_pos.Row); var TempCell = TempRow.Get_Cell(Cell_pos.Cell); TempCell.CheckNonEmptyBorder(0); if (TempCell.GetVMerge() === 2) TempCell.SetVMerge(vmerge_Restart); else continue; } // Если попадаем в нижнюю границу, выходим else if (Math.abs(this.RowsInfo[RowIndex].Y[CurPageStart] + this.RowsInfo[RowIndex].H[CurPageStart] - Y) <= 1.5) { var TempRow = this.GetRow(Cell_pos.Row); var TempCell = TempRow.Get_Cell(Cell_pos.Cell); TempCell.CheckNonEmptyBorder(2); continue; } } // разбиение контента по линии var CellToSplit = null; var Grid_start = Cell.Row.Get_CellInfo(Cell.Index).StartGridCol; if (CellVMerge === 2) { for (var nRow = Cell.Row.Index - 1; nRow >= 0; nRow--) { CellToSplit = this.GetCellByStartGridCol(nRow, Grid_start); if (CellToSplit.GetVMerge() === 1) break; else CellToSplit = null; } } if (!CellToSplit) CellToSplit = Cell; var CellToAddContent = TempCell; if (!TempCell) continue; for (var nElm = 0; nElm < CellToSplit.Content.Content.length; nElm++) { if (Y < CellToSplit.Content.Content[nElm].Y + 1.5) { ElmsToTransfer.push(CellToSplit.Content.Content[nElm].Copy()); CellToSplit.Content.Remove_FromContent(nElm, 1); nElm--; } } for (var nElm = ElmsToTransfer.length - 1; nElm >= 0; nElm--) { CellToAddContent.Content.Add_ToContent(0, ElmsToTransfer[nElm]); } ElmsToTransfer = []; } } // Вертикальное разбиение (условие, что мы не попадаем в горизонтальные границы других ячеек) if (Math.abs(this.RowsInfo[RowIndex].Y[CurPageStart] - Y) >= 1.5 && Math.abs(this.RowsInfo[RowIndex].Y[CurPageStart] + this.RowsInfo[RowIndex].H[CurPageStart] - Y) >= 1.5) { var Cell = this.GetRow(RowIndex).Get_Cell(CellsIndexes[0]); var Cell_pos = { Cell : CellsIndexes[0], Row : RowIndex }; var Row = this.GetRow(Cell_pos.Row); var Grid_start = Row.Get_CellInfo(Cell_pos.Cell).StartGridCol; var Grid_span = Cell.Get_GridSpan(); var VMerge_count = this.Internal_GetVertMergeCount(Cell_pos.Row, Grid_start, Grid_span); var Cells = []; var Cells_pos = []; var Rows_ = []; var ElmsToTransfer = []; Rows_[0] = Row; Cells[0] = Cell; Cells_pos[0] = Cell_pos; var Border_Height = this.GetBottomTableBorder().Size; var rowHeight_1 = Y - this.RowsInfo[Cell_pos.Row].Y[CurPageStart] - Border_Height; var rowHeight_2 = this.RowsInfo[Cell_pos.Row].Y[CurPageStart] + this.RowsInfo[Cell_pos.Row].H[CurPageStart] - Y - Border_Height; var CellsCount = Row.Get_CellsCount(); var NewRow = this.private_AddRow(Cell_pos.Row + 1, CellsCount); NewRow.Copy_Pr(Row.Pr); Row.Set_Height(rowHeight_1, linerule_AtLeast); NewRow.Set_Height(rowHeight_2, linerule_AtLeast); Rows_[1] = NewRow; Cells[1] = null; Cells_pos[1] = null; // Копируем настройки всех ячеек исходной строки в новую строку for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var New_Cell = NewRow.Get_Cell(CurCell); var Old_Cell = Row.Get_Cell(CurCell); New_Cell.Copy_Pr(Old_Cell.Pr); New_Cell.CopyParaPrAndTextPr(Old_Cell); if (CurCell === Cell_pos.Cell) { Cells[1] = New_Cell; Cells_pos[1] = {Row : Cell_pos.Row + 1, Cell : CurCell}; New_Cell.SetVMerge(vmerge_Restart); } else { New_Cell.SetVMerge(vmerge_Continue); } if (CellsIndexes.indexOf(CurCell) != -1) { if (CurCell != CellsIndexes[0]) New_Cell.SetVMerge(vmerge_Restart); } // разбиение контента по линии if (-1 !== CellsIndexes.indexOf(CurCell)) { var CellToSplit = null; var Grid_start = Old_Cell.Row.Get_CellInfo(Old_Cell.Index).StartGridCol; if (Old_Cell.GetVMerge() === 2) { for (var nRow = Old_Cell.Row.Index; nRow >= 0; nRow--) { CellToSplit = this.GetCellByStartGridCol(nRow, Grid_start); if (CellToSplit.GetVMerge() === 1) break; else CellToSplit = null; } } if (!CellToSplit) CellToSplit = Old_Cell; for (var nElm = 0; nElm < CellToSplit.Content.Content.length; nElm++) { if (Y < CellToSplit.Content.Content[nElm].Y) { ElmsToTransfer.push(CellToSplit.Content.Content[nElm].Copy()); CellToSplit.Content.Remove_FromContent(nElm, 1); nElm--; } } for (var nElm = ElmsToTransfer.length - 1; nElm >= 0; nElm--) { New_Cell.Content.Add_ToContent(0, ElmsToTransfer[nElm]); } ElmsToTransfer = []; } Old_Cell.CheckNonEmptyBorder(2); New_Cell.CheckNonEmptyBorder(0); } } return CallAdded; }; /** * Get cells whose borders were clicked, as well as the type of these borders * @param {Array} SelectedCells - an array of cells, among which there will be a search for those that can be merge * @return {Array} - an object containing cells whose borders were clicked, as well as the type of these borders */ CTable.prototype.FindCellsCanBeMerge = function(SelectedCells) { var CellsCanBeMerge = []; var try_again = false; // *Находя ячейки, которые мы можем объединить, мы удаляем их из массива SelectedCells* // Ищем ячейки которые можно будет объеденить for (var curCell = 0; curCell < SelectedCells.length; curCell++) { this.Selection.Data = []; // Добавляем в this.Selection.Data ячейку, с которой будем пытаться объеденить следующие var Cell_1_pos = SelectedCells[curCell]; this.Selection.Data.push(Cell_1_pos); for (var curCell2 = 0; curCell2 < SelectedCells.length; curCell2++) { var Cell_2_pos = SelectedCells[curCell2]; // Исключаем случаи когда рассматриваем объединение ячейки самой с собой if (Cell_1_pos.Row === Cell_2_pos.Row && Cell_1_pos.Cell === Cell_2_pos.Cell) continue; // добавляем ячейку в группу ячеек this.Selection.Data.push(Cell_2_pos); // Проверяем, можно ли объединить получившуюся группу ячеек, если да // удаляем только что добавленную ячейку из массива SelectedCells, т.к. она уже образовывает объединение var newTemp = this.Internal_CheckMerge(); var new_bCanMerge = newTemp.bCanMerge; if (!new_bCanMerge) this.Selection.Data.pop(); else { SelectedCells.splice(curCell2, 1); curCell2 = -1; } } // Если объединений с ячейкой, с которой пытались получить объединение, не было получено, пытаемся со следующей if (this.Selection.Data.length <= 1) continue; // Если объединение было получено, добавляем в массив объединений CellsCanBeMerge.push(this.Selection.Data); // Удаляем из SelectedCells ячейку, с которой пытались получить объединение, т.к. она в него if (CellsCanBeMerge[CellsCanBeMerge.length - 1].length > 1) { for (var Item = 0; Item < SelectedCells.length; Item++) if (SelectedCells[Item].Row === Cell_1_pos.Row && SelectedCells[Item].Cell === Cell_1_pos.Cell) SelectedCells.splice(Item, 1); curCell--; } } // Пробуем полученные объединения объединить между собой // если выходит, перезаполняем объединения for (var Index = 0; Index < CellsCanBeMerge.length; Index++) { this.Selection.Data = []; try_again = false; for (var nPosIndex = 0, nPosLen = CellsCanBeMerge[Index].length; nPosIndex < nPosLen; ++nPosIndex) { var cell_pos = CellsCanBeMerge[Index][nPosIndex]; this.Selection.Data.push(cell_pos); } for (var Index2 = 0; Index < CellsCanBeMerge.length; Index2++) { if (Index === Index2) continue; if ("undefined" === typeof(CellsCanBeMerge[Index2])) break; for (var nPosIndex2 = 0, nPosLen2 = CellsCanBeMerge[Index2].length; nPosIndex2 < nPosLen2; ++nPosIndex2) { var cell_pos2 = CellsCanBeMerge[Index2][nPosIndex2]; this.Selection.Data.push(cell_pos2); } var newTemp = this.Internal_CheckMerge(); var new_bCanMerge = newTemp.bCanMerge; if (!new_bCanMerge) for (var Item = 0; Item < CellsCanBeMerge[Index2].length; Item++) this.Selection.Data.pop(); else { CellsCanBeMerge.splice(Index2, 1); Index2--; } } for (var curCell3 = 0; curCell3 < SelectedCells.length; curCell3++) { this.Selection.Data.push(SelectedCells[curCell3]); var newTemp = this.Internal_CheckMerge(); var new_bCanMerge = newTemp.bCanMerge; if (!new_bCanMerge) this.Selection.Data.pop(); else { SelectedCells.splice(curCell3, 1); curCell3--; // Т.к. мы можем объеденить ячейки, стоит попытаться снова рассмотреть ячейки, которые уже были рассмотрены // но с которыми объединение нельзя было получить try_again = true; } } CellsCanBeMerge[Index] = this.Selection.Data; // Сортировка CellsCanBeMerge CellsCanBeMerge[Index].sort(function(a, b) { if (a.Row > b.Row) return 1; if (a.Row < b.Row) return -1; if (a.Row === b.Row) return 0; }); CellsCanBeMerge[Index].sort(function(a, b) { if (a.Cell > b.Cell && a.Row === b.Row) return 1; if (a.Cell < b.Cell && a.Row === b.Row) return -1; if (a.Cell === b.Cell && a.Row === b.Row) return 0; }); // Начинаем сначала if (try_again) Index = -1; } return CellsCanBeMerge; }; /** * Get cells whose borders were clicked, as well as the type of these borders * @param {number} X - coordinate * @param {number} Y - coordinate * @param {number} CurPageStart - page number of clicked page * @param {boolean} drawMode - pencil or eraser * @return {object} - an object containing cells whose borders were clicked, as well as the type of these borders */ CTable.prototype.GetCellAndBorderByClick = function(X, Y, CurPageStart) { // Проверка, была ли выбрана граница (для случая, когда щелкаем по границе); // Проверка, были ли выбраны начало и конец выделения // *Необходимо для случаев, когда у ячейки VMerge_count > 1* var isSelected = false; // Для щелчка по границе var isVSelect = false; // Была ли выбрана вертикальная граница var isHSelect = false; // Была ли выбрана горизонтальная граница var isRightBorder = false; var isLeftBorder = false; var isTopBorder = false; var isBottomBorder = false; var two_cells = false; var clickedCell = null; var SelectedCells = { Cells : [], isVSelect : false, isHSelect : false, isRightBorder : false, isLeftBorder : false, isTopBorder : false, isBottomBorder : false }; // Поиск границы по которой произведен щелчок for (var curRow = this.Pages[CurPageStart].FirstRow; curRow <= this.Pages[CurPageStart].LastRow; curRow++) { // Если граница уже выбрана, смысла искать больше нет if (isSelected) break; for (var curCell = 0; curCell < this.GetRow(curRow).Get_CellsCount(); curCell++) { if (isSelected) break; var Row = this.GetRow(curRow); var Cell = Row.Get_Cell(curCell); var Grid_start = Row.Get_CellInfo(curCell).StartGridCol; var Grid_span = Cell.Get_GridSpan(); var VMerge_count = this.Internal_GetVertMergeCount(curRow, Grid_start, Grid_span); var rowHSum = 0; // Высота ячейки var isInsideRow = false; // был ли щелчок внутри строки var isInsideCellBorders = false; // Считаем rowHSum с учетом VMerge_count if (VMerge_count >= 1) { for (var Index = curRow; Index < curRow + VMerge_count; Index++) { rowHSum += this.RowsInfo[Index].H[CurPageStart] } } if (this.RowsInfo[curRow].Y[CurPageStart] < Y && Y < this.RowsInfo[curRow].Y[CurPageStart] + rowHSum) isInsideRow = true; if (this.GetRow(curRow).CellsInfo[curCell].X_cell_start < X && X < this.GetRow(curRow).CellsInfo[curCell].X_cell_end) isInsideCellBorders = true; if (isInsideRow && isInsideCellBorders) { clickedCell = { Cell: curCell, Row : curRow }; } // Попадание в правую границу ячейки if (Math.abs(X - this.GetRow(curRow).CellsInfo[curCell].X_cell_end) < 1.5 && isInsideRow) { // Была ли выбрана ячейка справа от границы var isSelected_second = false; // Две позиции ячеек (слева от границы и справа от границы) var cell_pos1 = { Cell: curCell, Row : curRow }; var cell_pos2 = { Cell: null, Row : null }; if (!isSelected_second) { var Grid_start_second = Grid_start + Grid_span; // Поиск второй ячейки for (var curRow2 = this.Pages[CurPageStart].FirstRow; curRow2 <= this.Pages[CurPageStart].LastRow; curRow2++) { var TempCell = this.GetCellByStartGridCol(curRow2, Grid_start_second); if (!TempCell) continue; var TempGridStart = Grid_start_second; var TempGridSpan = TempCell.Get_GridSpan(); var TempVMerge_count = this.Internal_GetVertMergeCount(curRow2, TempGridStart, TempGridSpan); var TempRowHSum = 0; // Высота строки if (TempVMerge_count >= 1) { for (var Index2 = curRow2; Index2 < curRow2 + TempVMerge_count; Index2++) { TempRowHSum += this.RowsInfo[Index2].H[CurPageStart] } } if (this.RowsInfo[curRow2].Y[CurPageStart] < Y && Y < this.RowsInfo[curRow2].Y[CurPageStart] + TempRowHSum) { if (TempCell.GetVMerge() === 1) { cell_pos2 = { Cell: TempCell.GetIndex(), Row : curRow2 }; isSelected_second = true; two_cells = true; break; } } } } // Т.к. граница выбрана меняем на true isSelected = true; isVSelect = true; // Добавление в "выделенные ячейки" if (two_cells) { SelectedCells.Cells.push(cell_pos1, cell_pos2); } else { SelectedCells.Cells.push(cell_pos1); isRightBorder = true; } SelectedCells.isVSelect = isVSelect; SelectedCells.isHSelect = isHSelect; SelectedCells.isTopBorder = isTopBorder; SelectedCells.isBottomBorder = isBottomBorder; SelectedCells.isLeftBorder = isLeftBorder; SelectedCells.isRightBorder = isRightBorder; // Пропускаем следующую ячейку, т.к. она уже добавлена в выделенные curCell++; } // Попадание в левую внешнюю границу ячейки else if (Math.abs(X - this.GetRow(curRow).CellsInfo[curCell].X_cell_start) < 1.5 && curCell === 0 && isInsideRow) { // Должна быть выбрана только одна граница if (isSelected === false) { // Позициями ячейки var cell_pos = { Cell: curCell, Row : curRow }; // Т.к. граница выбрана меняем на true isSelected = true; isVSelect = true; isLeftBorder = true; SelectedCells.Cells.push(cell_pos); SelectedCells.isVSelect = isVSelect; SelectedCells.isHSelect = isHSelect; SelectedCells.isTopBorder = isTopBorder; SelectedCells.isBottomBorder = isBottomBorder; SelectedCells.isLeftBorder = isLeftBorder; SelectedCells.isRightBorder = isRightBorder; break; } } // Для верхних горизонтальных границ else if (Math.abs(Y - this.RowsInfo[curRow].Y[CurPageStart]) < 1.5 && isInsideCellBorders) { for (var Index = 0; Index < this.GetRow(curRow).Get_CellsCount(); Index++) { if (this.GetRow(curRow).CellsInfo[Index].X_cell_start < X && X < this.GetRow(curRow).CellsInfo[Index].X_cell_end) { if (Cell.GetVMerge() === 2) continue; var cell_pos = { Cell: Index, Row : curRow }; isSelected = true; isHSelect = true; isTopBorder = true; SelectedCells.Cells.push(cell_pos); SelectedCells.isVSelect = isVSelect; SelectedCells.isHSelect = isHSelect; SelectedCells.isTopBorder = isTopBorder; SelectedCells.isBottomBorder = isBottomBorder; SelectedCells.isLeftBorder = isLeftBorder; SelectedCells.isRightBorder = isRightBorder; break; } } } // Для нижних горизонтальых границ else if (Math.abs(Y - (this.RowsInfo[curRow].Y[CurPageStart] + rowHSum)) < 1.5 && isInsideCellBorders) { if (Cell.GetVMerge() === 2) continue; var cell_pos1 = { Cell: curCell, Row : curRow }; var cell_pos2 = { Cell : null, Row : null }; if (curRow + VMerge_count <= this.Pages[CurPageStart].LastRow) { for (var Index = 0; Index < this.GetRow(curRow + VMerge_count).Get_CellsCount(); Index++) { if (this.GetRow(curRow + VMerge_count).CellsInfo[Index].X_cell_start < X && X < this.GetRow(curRow + VMerge_count).CellsInfo[Index].X_cell_end) { cell_pos2 = { Cell: Index, Row : curRow + VMerge_count }; two_cells = true; } } } isSelected = true; isHSelect = true; if (two_cells) { SelectedCells.Cells.push(cell_pos1, cell_pos2); } else { SelectedCells.Cells.push(cell_pos1); isBottomBorder = true; } SelectedCells.isVSelect = isVSelect; SelectedCells.isHSelect = isHSelect; SelectedCells.isTopBorder = isTopBorder; SelectedCells.isBottomBorder = isBottomBorder; SelectedCells.isLeftBorder = isLeftBorder; SelectedCells.isRightBorder = isRightBorder; } } } if (SelectedCells.Cells.length === 0 && clickedCell) SelectedCells.Cells.push(clickedCell); return SelectedCells; }; /** * Get an array with affected row indices * @param {number} X1 - coordinate * @param {number} Y1 - coordinate * @param {number} CurPageStart - page number of clicked page * @param {boolean} typeOfDrawing - type of drawing * @return {Array} - Array of affected rows */ CTable.prototype.GetAffectedRows = function(X1, Y1, X2, Y2, CurPageStart, typeOfDrawing) { // Если typeOfDrawing равен // 0: Рисование вертикальных линий // 1: Рисование горизонтальных линий // 2: Ластик var Rows = []; if (typeOfDrawing === 0) { var CellsIndexes = []; // Заполняем массив Rows строками, которые попали под выделение for (var curRow = this.Pages[CurPageStart].FirstRow; curRow <= this.Pages[CurPageStart].LastRow; curRow++) { if (Y1 <= this.RowsInfo[this.Pages[CurPageStart].FirstRow].Y[CurPageStart] && this.RowsInfo[curRow].Y[CurPageStart] <= Y2) Rows.push(curRow); else if (this.RowsInfo[curRow].Y[CurPageStart] <= Y1 && Y1 < this.RowsInfo[curRow].Y[CurPageStart] + this.RowsInfo[curRow].H[CurPageStart]) Rows.push(curRow); else if (Rows.length === 0) continue; else if (this.RowsInfo[curRow].Y[CurPageStart] <= Y2) Rows.push(curRow); } if (Rows.length === 0) return Rows; // Заполняем массив CellsIndexes индексами ячеек, которые попали под выделение в задетых строках for (var Index = 0; Index < Rows.length; Index++) { for (var curCell = 0; curCell < this.GetRow(Rows[Index]).Get_CellsCount(); curCell++) { if (X1 > this.GetRow(Rows[Index]).CellsInfo[curCell].X_cell_start && X1 < this.GetRow(Rows[Index]).CellsInfo[curCell].X_cell_end) CellsIndexes[Rows[Index]] = curCell; } } if (CellsIndexes.length === 0) return Rows; var StartRow = Rows[0]; // строка, с которой стартует линия маркировки var EndRow = Rows[Rows.length - 1]; // строка на которой должна заканчиватся линия маркировки (если у ячейки будет VMerge, то поменяем) // Мы должны учитывать VMerge затронутых ячеек, поэтому реальная строка начала деления может отличаться от найденной выше for (var Index = 0; Index < CellsIndexes.length; Index++) { if (CellsIndexes[Index] !== undefined) { var isFind = false; var curCell = this.GetRow(Index).GetCell(CellsIndexes[Index]); var Grid_start = this.GetRow(Index).Get_CellInfo(curCell.GetIndex()).StartGridCol; if (curCell.GetVMerge() === 2) { for (var curRowIndex = Index - 1; curRowIndex >= 0; curRowIndex--) { var ViewCell = this.GetCellByStartGridCol(curRowIndex, Grid_start); if (ViewCell && ViewCell.GetVMerge() === 1) { StartRow = curRowIndex; isFind = true; break; } } if (isFind) break; } else { StartRow = Index; break; } } } // Мы должны учитывать VMerge затронутых ячеек, поэтому реальная строка конца отрисовки может отличаться от найденной выше for (var Index = CellsIndexes.length; Index >= 0; Index--) { if (CellsIndexes[Index] !== undefined) { var curCell = this.GetRow(Index).GetCell(CellsIndexes[Index]); var VMergeCount = this.GetVMergeCount(curCell.GetIndex(), Index); if (VMergeCount > 1) { EndRow = Index + VMergeCount - 1; break; } else { EndRow = Index; break; } } } // Перезаполняем Rows Rows = []; for (var Index = StartRow; Index <= EndRow; Index++) Rows.push(Index); return Rows; } else if (typeOfDrawing === 1) { // Вычисление Row for (var curRow = 0; curRow < this.Get_RowsCount(); curRow++) { if (Y1 > this.RowsInfo[curRow].Y[CurPageStart] && Y1 < (this.RowsInfo[curRow].Y[CurPageStart] + this.RowsInfo[curRow].H[CurPageStart])) { Rows.push(curRow); break; } } return Rows; } else if (typeOfDrawing === 2) { // Заполняем массив Rows строками, которые попали под выделение for (var curRow = this.Pages[CurPageStart].FirstRow; curRow <= this.Pages[CurPageStart].LastRow; curRow++) { if (Y1 <= this.RowsInfo[this.Pages[CurPageStart].FirstRow].Y[CurPageStart] && this.RowsInfo[curRow].Y[CurPageStart] <= Y2) Rows.push(curRow); else if (this.RowsInfo[curRow].Y[CurPageStart] <= Y1 && Y1 < this.RowsInfo[curRow].Y[CurPageStart] + this.RowsInfo[curRow].H[CurPageStart]) Rows.push(curRow); else if (Rows.length === 0) continue; else if (this.RowsInfo[curRow].Y[CurPageStart] <= Y2) Rows.push(curRow); } return Rows; } }; /** * Get an array of cells that fall under the selection. * @param {number} X1 - coordinate * @param {number} Y1 - coordinate * @param {number} CurPageStart - page number of clicked page * @return {Array} - cells array */ CTable.prototype.GetCellsByRect = function(X1, Y1, X2, Y2, CurPageStart) { // Если выделение справа налево if (X1 > X2) { var cache; cache = X2; X2 = X1; X1 = cache; } // Если выделение снизу вверх if (Y1 > Y2) { var cache; cache = Y2; Y2 = Y1; Y1 = cache; } var Rows = this.GetAffectedRows(X1, Y1, X2, Y2, CurPageStart, 2); var SelectionData = []; if (Rows.length === 0) return SelectionData; // Далее мы определяем, какие ячейки в строках(попавших под выделение) попадают под выделение // и заполняем SelectionData for (var curRow = 0; curRow < this.Get_RowsCount(); curRow++) { // Проверка строки на наличие в массиве Rows if (Rows.indexOf(curRow) === -1) continue; for (var curCell = 0; curCell < this.GetRow(curRow).Get_CellsCount(); curCell++) { var Row = this.GetRow(curRow); var Grid_start = Row.Get_CellInfo(curCell).StartGridCol; if (X1 < this.GetRow(curRow).CellsInfo[curCell].X_cell_start && X2 > this.GetRow(curRow).CellsInfo[curCell].X_cell_start || X1 < this.GetRow(curRow).CellsInfo[curCell].X_cell_end && X2 > this.GetRow(curRow).CellsInfo[curCell].X_cell_end || X1 > this.GetRow(curRow).CellsInfo[curCell].X_cell_start && X2 < this.GetRow(curRow).CellsInfo[curCell].X_cell_end) { var check = false; for (var curRow2 = curRow; curRow2 >= 0; curRow2--) { if (check) break; var TempCell = this.GetCellByStartGridCol(curRow2, Grid_start); if (TempCell) { if (TempCell.GetVMerge() === 1) { var cell_pos = { Cell : TempCell.GetIndex(), Row : curRow2 }; for (var Index = 0; Index < SelectionData.length; Index++) { if (cell_pos.Row === SelectionData[Index].Row && cell_pos.Cell === SelectionData[Index].Cell) { check = true; break; } } if (check) break; SelectionData.push(cell_pos); check = true; } } } } } } return SelectionData; }; /** * Get an array with information about the new grid of the table, taking into account the cut line and cut lines * @param {number} X - coordinate * @param {number} RowsIndices - Indices of lines that fall under the cut line * @return {Array} - array with information about the new grid */ CTable.prototype.CalculateNewRowsInfo = function(X, RowsIndices) { var rowsInfo = []; // заполняем массив rowsInfo строк с ширинами ячеек for (var curRow = 0; curRow < this.Get_RowsCount(); curRow++) { var cellsInfo = []; // информация о ячейке for (var curCell = 0; curCell < this.GetRow(curRow).Get_CellsCount(); curCell++) { if ((X - this.GetRow(curRow).CellsInfo[curCell].X_cell_start > 1.5) && (this.GetRow(curRow).CellsInfo[curCell].X_cell_end - X > 1.5)) { if (RowsIndices.indexOf(curRow) != -1) //проверка на наличие строки curRow в массиве строк которые мы выделили { var Row = this.GetRow(curRow); var Cell = Row.Get_Cell(curCell); //текущая ячейка var X_start = Row.CellsInfo[curCell].X_cell_start; var X_end = Row.CellsInfo[curCell].X_cell_end; var Grid_start = Row.Get_CellInfo(curCell).StartGridCol; var Grid_span = Cell.Get_GridSpan(); var VMerge_count = this.Internal_GetVertMergeCount(curRow, Grid_start, Grid_span); var NarrowCell = false; // является ли делимая ячейка узкой (неделимой (равной минимальной ширине)) //сделаем разбиение по горизонтали // Найдем позиции новых колонок в сетке var Span_width = X_end - X_start; //ширина текущей ячейки var Grid_width_1 = X - X_start; var Grid_width_2 = X_end - X; var CellSpacing = Row.Get_CellSpacing(); var CellMar = Cell.GetMargins(); var MinW = CellSpacing + CellMar.Right.W + CellMar.Left.W; for (var Index = 0; Index < this.TableSumGrid.length; Index++) { if (Math.abs(this.TableSumGrid[Index] - X) < 1.5) { X = this.TableSumGrid[Index]; Grid_width_1 = X - this.TableSumGrid[Grid_start - 1]; Grid_width_2 = this.TableSumGrid[Grid_start + Grid_span - 1] - X; break; } } // В этих условиях мы проверяем допустимая ли ширина ячеек нами нарисована, // если меньше допустимой, устанавливаем ширину равную минимальной допустимой // если ширина делимой ячейки Span_width < Minw*2 то выдаем ошибку if (Grid_width_1 > 0 && Grid_width_2 > 0) { if (Grid_width_1 < MinW) { Grid_width_1 = MinW; Grid_width_2 = Span_width - Grid_width_1; if (Grid_width_2 < MinW) { Grid_width_2 = MinW; NarrowCell = true; } if (Span_width < Grid_width_1 + Grid_width_2) { Span_width = Grid_width_1 + Grid_width_2; } } else if (Grid_width_2 < MinW) { Grid_width_2 = MinW; Grid_width_1 = Span_width - Grid_width_2; if (Grid_width_1 < MinW) { Grid_width_1 = MinW; NarrowCell = true; } if (Span_width < Grid_width_1 + Grid_width_2) { Span_width = Grid_width_1 + Grid_width_2; } } } //Проверяем есть ли GridBefore у строки перед первой ячейкой, если да, то учитываем это в сетке //GridBefore строки должен совпадать с Grid_Start ячейки(перед которой отступ), чтобы условие выполнилось ровно один раз if (this.GetRow(curRow).Get_Before().GridBefore >= 1 && Grid_start === this.GetRow(curRow).Get_Before().GridBefore) { var cell_Indent = { W: X_end - Span_width, Type: -1, Grid_span: 1 } cellsInfo[cellsInfo.length] = cell_Indent; } var cell_1 = { W: Grid_width_1, Type: 0, GridSpan: 1 }; var cell_2 = { W: Grid_width_2, Type: 0, GridSpan: 1 }; if (cell_1.W != 0) { cellsInfo[cellsInfo.length] = cell_1; } if (cell_2.W != 0) { cellsInfo[cellsInfo.length] = cell_2; } if (NarrowCell && Cell.GetVMerge() !== 2) { for (var Index = curCell + 1; Index < this.GetRow(curRow).Get_CellsCount(); Index++) { var Temp_Row1 = this.GetRow(curRow); var Temp_Cell1 = Temp_Row1.Get_Cell(Index); var Temp_Grid_start1 = Temp_Row1.Get_CellInfo(Index).StartGridCol; var Temp_Row2 = this.GetRow(curRow + VMerge_count); if (Temp_Row2 !== null && Temp_Row2 !== undefined) { for (var newIndex = 0; newIndex < Temp_Row2.Get_CellsCount(); newIndex++) { var Temp_Cell2 = Temp_Row2.Get_Cell(newIndex); var Temp_Grid_start2 = Temp_Row2.Get_CellInfo(newIndex).StartGridCol; if (Temp_Grid_start2 === Temp_Grid_start1) { if (Temp_Cell2.GetVMerge() === 2) { Temp_Cell2.SetVMerge(vmerge_Restart); } } } } if (Temp_Cell1.GetVMerge() === 2) { Temp_Cell1.SetVMerge(vmerge_Restart); } } } } else { var Grid_start = this.GetRow(curRow).Get_CellInfo(curCell).StartGridCol; var X_start = this.GetRow(curRow).CellsInfo[curCell].X_cell_start; var X_end = this.GetRow(curRow).CellsInfo[curCell].X_cell_end; var cellWidth = X_end - X_start; //Проверяем есть ли GridBefore у строки перед первой ячейкой, если да, то учитываем это в сетке //GridBefore строки должен совпадать с Grid_Start ячейки(перед которой отступ), чтобы условие выполнилось ровно один раз if (this.GetRow(curRow).Get_Before().GridBefore >= 1 && Grid_start === this.GetRow(curRow).Get_Before().GridBefore) { var cell_Indent = { W: X_end - cellWidth, Type: -1, Grid_span: 1 } cellsInfo[cellsInfo.length] = cell_Indent; } var cell = { W: cellWidth, Type: 0, GridSpan: 1 }; cellsInfo[cellsInfo.length] = cell; } } else { var X_start = this.GetRow(curRow).CellsInfo[curCell].X_cell_start; var X_end = this.GetRow(curRow).CellsInfo[curCell].X_cell_end; var cellWidth = X_end - X_start; var Grid_start = this.GetRow(curRow).Get_CellInfo(curCell).StartGridCol; var Row = this.GetRow(curRow); var Cell = Row.Get_Cell(curCell); //текущая ячейка //Проверяем есть ли отступ у строки перед первой ячейкой, если да, то учитываем это в сетке //GridBefore строки должен совпадать с Grid_Start ячейки(перед которой отступ), чтобы условие выполнилось ровно один раз if (this.GetRow(curRow).Get_Before().GridBefore >= 1 && Grid_start === this.GetRow(curRow).Get_Before().GridBefore) { var cell_Indent = { W: X_end - cellWidth, Type: -1, Grid_span: 1 } cellsInfo[cellsInfo.length] = cell_Indent; } var cell = { W: cellWidth, Type: 0, GridSpan: 1 }; cellsInfo[cellsInfo.length] = cell; } rowsInfo[curRow] = cellsInfo; } } return rowsInfo; }; /** * @param NewMarkup - новая разметка таблицы * @param bCol - где произошли изменения (в колонках или строках) * @param Index - номер границы колонок(строк), у которой произошли изменения */ CTable.prototype.Update_TableMarkupFromRuler = function(NewMarkup, bCol, Index) { var TablePr = this.Get_CompiledPr(false).TablePr; if (true === bCol) { var RowIndex = NewMarkup.Internal.RowIndex; var Row = this.Content[RowIndex]; var Col = 0; var Dx = 0; // границ на 1 больше, чем самих ячеек в строке if (Index === NewMarkup.Cols.length) { Col = Row.Get_CellInfo(Index - 1).StartGridCol + Row.Get_Cell(Index - 1).Get_GridSpan(); Dx = NewMarkup.Cols[Index - 1] - this.Markup.Cols[Index - 1]; } else { Col = Row.Get_CellInfo(Index).StartGridCol; if (0 != Index) Dx = NewMarkup.Cols[Index - 1] - this.Markup.Cols[Index - 1]; else Dx = NewMarkup.X - this.Markup.X; } if (0 === Dx) return; if (0 === Col) { Dx = this.Markup.X - NewMarkup.X; this.X_origin -= Dx; if (true === this.Is_Inline()) { this.Set_TableAlign(align_Left); this.Set_TableInd(TablePr.TableInd - Dx); this.private_SetTableLayoutFixedAndUpdateCellsWidth(-1); this.SetTableGrid(this.private_CopyTableGridCalc()); } else { this.Internal_UpdateFlowPosition(this.X_origin, this.Y); } } else { var GridSpan = 1; if (Dx > 0) { if (Index != NewMarkup.Cols.length) { var Cell = Row.Get_Cell(Index); GridSpan = Cell.Get_GridSpan(); } else { var GridAfter = Row.Get_After().GridAfter; GridSpan = GridAfter; } this.TableGridCalc[Col - 1] = this.TableGridCalc[Col - 1] + Dx; this.Internal_UpdateCellW(Col - 1); this.private_SetTableLayoutFixedAndUpdateCellsWidth(Col - 1); this.SetTableGrid(this.private_CopyTableGridCalc()); } else { if (0 != Index) { var Cell = Row.Get_Cell(Index - 1); GridSpan = Cell.Get_GridSpan(); } else { var GridBefore = Row.Get_Before().GridBefore; // Если GridBefore = 0, тогда мы попадем в случай 0 === Col GridSpan = GridBefore; } if (1 === GridSpan || -Dx < this.TableSumGrid[Col - 1] - this.TableSumGrid[Col - 2]) { this.TableGridCalc[Col - 1] = this.TableGridCalc[Col - 1] + Dx; this.Internal_UpdateCellW(Col - 1); this.private_SetTableLayoutFixedAndUpdateCellsWidth(Col - 1); this.SetTableGrid(this.private_CopyTableGridCalc()); } else { var Rows_info = []; for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { Rows_info[CurRow] = []; var Row = this.Content[CurRow]; var Before_Info = Row.Get_Before(); if (Before_Info.GridBefore > 0) { if (Before_Info.GridBefore >= Col) { var W = Math.max(0, this.TableSumGrid[Before_Info.GridBefore - 1] + Dx); if (W > 0.001) Rows_info[CurRow].push({W : W, Type : -1, GridSpan : 1}); } else Rows_info[CurRow].push({ W : this.TableSumGrid[Before_Info.GridBefore - 1], Type : -1, GridSpan : 1 }); } var CellsCount = Row.Get_CellsCount(); for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var Cell = Row.Get_Cell(CurCell); var CellMargins = Cell.GetMargins(); var Cur_Grid_start = Row.Get_CellInfo(CurCell).StartGridCol; var Cur_Grid_end = Cur_Grid_start + Cell.Get_GridSpan() - 1; if (Cur_Grid_start <= Col - 1 && Cur_Grid_end >= Col - 1) { var W = this.TableSumGrid[Cur_Grid_end] - this.TableSumGrid[Cur_Grid_start - 1] + Dx; W = Math.max(1, Math.max(W, CellMargins.Left.W + CellMargins.Right.W)); Rows_info[CurRow].push({W : W, Type : 0, GridSpan : 1}); } else { var W = this.TableSumGrid[Cur_Grid_end] - this.TableSumGrid[Cur_Grid_start - 1]; W = Math.max(1, Math.max(W, CellMargins.Left.W + CellMargins.Right.W)); Rows_info[CurRow].push({W : W, Type : 0, GridSpan : 1}); } } } this.Internal_CreateNewGrid(Rows_info); } } this.private_RecalculateGrid(); } if (0 !== Index && undefined !== TablePr.TableW && TablePr.TableW.Type !== tblwidth_Auto) { var nTableW = 0; for (var nCurCol = 0, nColsCount = this.TableGrid.length; nCurCol < nColsCount; ++nCurCol) nTableW += this.TableGrid[nCurCol]; var nTableW = Math.max(this.private_GetTableMinWidth(), nTableW); if (tblwidth_Pct === TablePr.TableW.Type) { var nPctWidth = this.private_RecalculatePercentWidth(); if (nPctWidth < 0.01) this.Set_TableW(tblwidth_Auto, 0); else this.Set_TableW(tblwidth_Pct, nTableW / nPctWidth * 100); } else { this.Set_TableW(tblwidth_Mm, nTableW); } } } else { var RowIndex = this.Pages[NewMarkup.Internal.PageNum].FirstRow + Index; if (0 === RowIndex) { if (true === this.Is_Inline()) { // ничего не делаем, позиция по Y в инлайновой таблице изменить нельзя таким способом } else { var Dy = this.Markup.Rows[0].Y - NewMarkup.Rows[0].Y; this.Y -= Dy; this.Internal_UpdateFlowPosition(this.X_origin, this.Y); var NewH = NewMarkup.Rows[0].H; this.Content[0].Set_Height(NewH, linerule_AtLeast); } } else { if (NewMarkup.Internal.PageNum > 0 && 0 === Index) { // ничего не делаем } else { var NewH = NewMarkup.Rows[Index - 1].H; this.Content[RowIndex - 1].Set_Height(NewH, linerule_AtLeast); } } } if (this.LogicDocument) { this.LogicDocument.Recalculate(); this.LogicDocument.UpdateSelection(); } }; /** * Распраделяем выделенные ячейки по ширине или высоте * @param isHorizontally * @returns {boolean} Возвращаем false, если операция невозможна */ CTable.prototype.DistributeTableCells = function(isHorizontally) { if (isHorizontally) return this.DistributeColumns(); else return this.DistributeRows(); }; /** * Удаляем выделенные ячейки таблицы со сдвигом влево * @returns {boolean} */ CTable.prototype.RemoveTableCells = function() { var bApplyToInnerTable = false; if (false === this.Selection.Use || ( true === this.Selection.Use && table_Selection_Text === this.Selection.Type )) bApplyToInnerTable = this.CurCell.Content.RemoveTableColumn(); if (true === bApplyToInnerTable) return true; var arrSelectedCells = this.GetSelectionArray(true); this.RemoveSelection(); var arrDeleteInfo = []; var arrRowsInfo = []; var oDeletedFirstCellPos = null; for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { arrDeleteInfo[nCurRow] = []; arrRowsInfo[nCurRow] = []; var oRow = this.GetRow(nCurRow); var oBeforeInfo = oRow.GetBefore(); if (oBeforeInfo.Grid > 0) arrRowsInfo[nCurRow].push({W : this.TableSumGrid[oBeforeInfo.Grid - 1], Type : -1, GridSpan : 1}); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var isDeleted = false; for (var nSelectedIndex = 0, nSelectedCount = arrSelectedCells.length; nSelectedIndex < nSelectedCount; ++nSelectedIndex) { var oPos = arrSelectedCells[nSelectedIndex]; if (oPos.Cell === nCurCell && oPos.Row === nCurRow) { isDeleted = true; break; } } if (isDeleted) { arrDeleteInfo[nCurRow].push(nCurCell); if (!oDeletedFirstCellPos) oDeletedFirstCellPos = {Row : nCurRow, Cell : nCurCell}; } else { var oCell = oRow.GetCell(nCurCell); var nCellGridStart = oRow.GetCellInfo(nCurCell).StartGridCol; var nCellGridEnd = nCellGridStart + oCell.GetGridSpan() - 1; var W = this.TableSumGrid[nCellGridEnd] - this.TableSumGrid[nCellGridStart - 1]; arrRowsInfo[nCurRow].push({W : W, Type : 0, GridSpan : 1}); } } } if (!oDeletedFirstCellPos) oDeletedFirstCellPos = {Row : 0, Cell : 0}; // Удалим все ячейки for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.Content[nCurRow]; for (var nIndex = arrDeleteInfo[nCurRow].length - 1; nIndex >= 0; --nIndex) { var nCurCell = arrDeleteInfo[nCurRow][nIndex]; oRow.RemoveCell(nCurCell); } } // При удалении колонки возможен случай, когда удаляется строка целиком for (var nCurRow = this.GetRowsCount() - 1; nCurRow >= 0; --nCurRow) { // Строка удалена целиком, если в RowsInfo нет ни одной записи // о ячейках (т.е. с типом равным 0) var isRemove = true; for (var nIndex = 0; nIndex < arrRowsInfo[nCurRow].length; ++nIndex) { if (0 === arrRowsInfo[nCurRow][nIndex].Type) { isRemove = false; break; } } if (isRemove) { this.private_RemoveRow(nCurRow); arrRowsInfo.splice(nCurRow, 1); } } // При удалении последней строки, надо сообщить об этом родительскому классу if (this.GetRowsCount() <= 0) return false; // TODO: При удалении ячеек надо запоминать информацию об вертикально // объединенных ячейках, и в новой сетке объединять ячейки только // если они были объединены изначально. Сейчас если ячейка была // объединена с какой-либо ячейкой, то она может после удаления // объединиться с совсем другой ячейкой. this.private_CreateNewGrid(arrRowsInfo); // Пробегаемся по всем ячейкам и смотрим на их вертикальное объединение, было ли оно нарушено this.private_CorrectVerticalMerge(); // Возможен случай, когда у нас остались строки, полностью состоящие из объединенных вертикально ячеек for (var nCurRow = this.GetRowsCount() - 1; nCurRow >= 0; --nCurRow) { var isRemove = true; var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); if (vmerge_Continue !== oCell.GetVMerge()) { isRemove = false; break; } } if (isRemove) this.private_RemoveRow(nCurRow); } var nCurRow = oDeletedFirstCellPos.Row; var nCurCell = 0; if (nCurRow >= this.GetRowsCount()) nCurRow = this.GetRowsCount() - 1; else nCurCell = Math.min(oDeletedFirstCellPos.Cell, this.GetRow(nCurRow).GetCellsCount() - 1); var oRow = this.GetRow(nCurRow); this.CurCell = oRow.GetCell(nCurCell); this.CurCell.Content.MoveCursorToStartPos(); this.Markup.Internal.RowIndex = nCurRow; this.Markup.Internal.CellIndex = nCurCell; this.Markup.Internal.PageNum = 0; this.Selection.Use = false; this.Selection.Start = false; this.Selection.StartPos.Pos = {Row : nCurRow, Cell : nCurCell}; this.Selection.EndPos.Pos = {Row : nCurRow, Cell : nCurCell}; this.Selection.CurRow = nCurRow; this.private_RecalculateGrid(); return true; }; //---------------------------------------------------------------------------------------------------------------------- // Внутренние функции //---------------------------------------------------------------------------------------------------------------------- /** * TODO: Удалить данную функцию */ CTable.prototype.Internal_Recalculate_1 = function() { return editor.WordControl.m_oLogicDocument.Recalculate(); }; /** * TODO: Удалить данную функцию * Данная функция вызывается после изменений внутри ячейки, а это означает, что с момента * последнего пересчета не изменилась ни сетка, ни границы, и ни расстояние между ячейками в таблицу. * Следовательно, нам надо пересчитать высоту ячейки, в которой произошли изменения, и если * это приведет к изменению высоты строки, то пересчитываем все строки дальше. */ CTable.prototype.Internal_RecalculateFrom = function(RowIndex, CellIndex, bChange, bForceRecalc) { return editor.WordControl.m_oLogicDocument.Recalculate(); }; CTable.prototype.private_GetCellByXY = function(X, Y, PageIndex) { // Сначала определяем колонку в которую мы попали var CurGrid = 0; var CurPage = Math.min(this.Pages.length - 1, Math.max(0, PageIndex)); var Page = this.Pages[CurPage]; var ColsCount = this.TableGridCalc.length; var twX = AscCommon.MMToTwips(X); var twPageX = AscCommon.MMToTwips(Page.X); if (twX >= twPageX) { for (CurGrid = 0; CurGrid < ColsCount; CurGrid++) { var twColStart = AscCommon.MMToTwips(Page.X + this.TableSumGrid[CurGrid - 1]); var twColEnd = AscCommon.MMToTwips(Page.X + this.TableSumGrid[CurGrid]); if (twColStart <= twX && twX < twColEnd) break; } } if (CurGrid >= ColsCount) CurGrid = ColsCount - 1; // Найдем промежуток строк по PageIndex среди которых нам надо искать var PNum = PageIndex; var Row_start, Row_last; if (PNum < 0) { Row_start = 0; Row_last = 0; } else if (PNum >= this.Pages.length) { Row_start = this.Content.length - 1; Row_last = this.Content.length - 1; } else { Row_start = this.Pages[PNum].FirstRow; Row_last = this.Pages[PNum].LastRow; } if (Row_last < Row_start) return {Row : 0, Cell : 0}; for (var CurRow = Row_start; CurRow <= Row_last; CurRow++) { var Row = this.Content[CurRow]; var CellsCount = Row.Get_CellsCount(); var BeforeInfo = Row.Get_Before(); var CurGridCol = BeforeInfo.GridBefore; for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var Cell = Row.Get_Cell(CurCell); var GridSpan = Cell.Get_GridSpan(); var Vmerge = Cell.GetVMerge(); // Обсчет такик ячеек произошел ранее if (vmerge_Continue === Vmerge && Row_start != CurRow) { CurGridCol += GridSpan; continue; } var VMergeCount = this.private_GetVertMergeCountOnPage(PNum, CurRow, CurGridCol, GridSpan); if (VMergeCount <= 0) { CurGridCol += GridSpan; continue; } // Проверяем по X if (CurGrid >= CurGridCol && CurGrid < CurGridCol + GridSpan) { // Проверяем по Y if ("undefined" != typeof(this.RowsInfo[CurRow + VMergeCount - 1].Y[PNum]) && "undefined" != typeof(this.RowsInfo[CurRow + VMergeCount - 1].H[PNum]) && (Y <= (this.RowsInfo[CurRow + VMergeCount - 1].Y[PNum] + this.RowsInfo[CurRow + VMergeCount - 1].H[PNum]) || CurRow + VMergeCount - 1 >= Row_last )) { if (vmerge_Continue === Vmerge && Row_start === CurRow) { Cell = this.Internal_Get_StartMergedCell(CurRow, CurGridCol, GridSpan); if (null != Cell) return {Row : Cell.Row.Index, Cell : Cell.Index}; else return {Row : 0, Cell : 0}; } else return {Row : CurRow, Cell : CurCell}; } } CurGridCol += GridSpan; } } return {Row : 0, Cell : 0}; }; /** * Считаем количество соединенных вертикально ячеек */ CTable.prototype.Internal_GetVertMergeCount = function(StartRow, StartGridCol, GridSpan) { // начинаем с 1, потому что предполагается, что соединение начинается с исходной ячейки var VmergeCount = 1; for (var Index = StartRow + 1; Index < this.Content.length; Index++) { var Row = this.Content[Index]; var BeforeInfo = Row.Get_Before(); var CurGridCol = BeforeInfo.GridBefore; var CurCell = 0; var CellsCount = Row.Get_CellsCount(); var bWasMerged = false; while (CurGridCol <= StartGridCol && CurCell < CellsCount) { var Cell = Row.Get_Cell(CurCell); var CellGridSpan = Cell.Get_GridSpan(); var Vmerge = Cell.GetVMerge(); if (CurGridCol === StartGridCol && GridSpan === CellGridSpan && vmerge_Continue === Vmerge) { bWasMerged = true; VmergeCount++; break; } else if (CurGridCol === StartGridCol && GridSpan === CellGridSpan && vmerge_Continue != Vmerge) { bWasMerged = true; return VmergeCount; } // Если данная ячейка имеет пересечение с заданным промежутком, но польностью с ним не совпадает else if (CurGridCol <= StartGridCol + GridSpan - 1 && CurGridCol + CellGridSpan - 1 >= StartGridCol) break; CurGridCol += CellGridSpan; CurCell++; } if (false === bWasMerged) break; } return VmergeCount; }; /** * Считаем количество соединенных вертикально ячеек, но в обратную сторону (т.е. снизу вверх) */ CTable.prototype.Internal_GetVertMergeCountUp = function(StartRow, StartGridCol, GridSpan) { // Сначала проверим VMerge заданной ячейки let row = this.GetRow(StartRow); if (!row) return 1; let curGridCol = row.GetBefore().Grid; for (let curCell = 0, cellsCount = row.GetCellsCount(); curCell < cellsCount; ++curCell) { let cell = row.GetCell(curCell); if (curGridCol === StartGridCol) { if (vmerge_Restart === cell.GetVMerge()) return 1; break; } else if (curGridCol > StartGridCol) { return 1; } curGridCol += cell.GetGridSpan(); } // начинаем с 1, потому что предполагается, что соединение начинается с исходной ячейки var VmergeCount = 1; for (var Index = StartRow - 1; Index >= 0; Index--) { var Row = this.Content[Index]; var BeforeInfo = Row.Get_Before(); var CurGridCol = BeforeInfo.GridBefore; var CurCell = 0; var CellsCount = Row.Get_CellsCount(); var bWasMerged = false; while (CurGridCol <= StartGridCol && CurCell < CellsCount) { var Cell = Row.Get_Cell(CurCell); var CellGridSpan = Cell.Get_GridSpan(); var Vmerge = Cell.GetVMerge(); if (CurGridCol === StartGridCol && GridSpan === CellGridSpan && vmerge_Continue === Vmerge) { bWasMerged = true; VmergeCount++; break; } else if (CurGridCol === StartGridCol && GridSpan === CellGridSpan && vmerge_Continue != Vmerge) { bWasMerged = true; VmergeCount++; return VmergeCount; } // Если данная ячейка имеет пересечение с заданным промежутком, но польностью с ним не совпадает else if (CurGridCol <= StartGridCol + GridSpan - 1 && CurGridCol + CellGridSpan - 1 >= StartGridCol) break; CurGridCol += CellGridSpan; CurCell++; } if (false === bWasMerged) break; } return VmergeCount; }; /** * Проверяем, нужно ли удалить ненужные строки из нашей таблицы. * Такое может произойти после объединения ячеек или после изменения сетки * таблицы. * @returns {boolean} произошли ли изменения в таблице */ CTable.prototype.CorrectTableRows = function(bSaveHeight) { // HACK: При загрузке мы запрещаем компилировать стили, но нам все-таки это здесь нужно var bLoad = AscCommon.g_oIdCounter.m_bLoad; var bRead = AscCommon.g_oIdCounter.m_bRead; AscCommon.g_oIdCounter.m_bLoad = false; AscCommon.g_oIdCounter.m_bRead = false; // Пробегаемся по всем строкам, если в какой-то строке у всех ячеек стоит // вертикальное объединение, тогда такую строку удаляем, а у предыдущей // строки выставляем минимальную высоту - сумму высот этих двух строк. // Кроме этого нам надо выставить минимальную высоту у строк, в которых // все ячейки состоят в вертикальном объединении, а у самой строки // параметр WBefore или WAfter ненулевой // Сначала пробежимся по строкам и узнаем, какие строки нужно удалить var Rows_to_Delete = []; var Rows_to_CalcH = []; var Rows_to_CalcH2 = []; for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Row = this.Content[CurRow]; var bVmerge_Restart = false; var bVmerge_Continue = false; var bNeedDeleteRow = true; var bNeedCalcHeight = false; if (Row.Get_Before().GridBefore > 0 || Row.Get_After().GridAfter > 0) bNeedCalcHeight = true; for (var CurCell = 0; CurCell < Row.Get_CellsCount(); CurCell++) { var Cell = Row.Get_Cell(CurCell); var VMerge = Cell.GetVMerge(); if (VMerge != vmerge_Continue) { var VMergeCount = this.Internal_GetVertMergeCount(CurRow, Row.Get_CellInfo(CurCell).StartGridCol, Cell.Get_GridSpan()); if (VMergeCount > 1) bVmerge_Restart = true; bNeedDeleteRow = false; if (true === bNeedCalcHeight) { if (1 === VMergeCount) bNeedCalcHeight = false; } } else bVmerge_Continue = true; } if (true === bVmerge_Continue && true === bVmerge_Restart) Rows_to_CalcH2.push(CurRow); else if (true === bNeedCalcHeight) Rows_to_CalcH.push(CurRow); if (true === bNeedDeleteRow) Rows_to_Delete.push(CurRow); } // Сначала разберемся со строками, у которых надо проставить минимальную высоту for (var Index = 0; Index < Rows_to_CalcH2.length; Index++) { var RowIndex = Rows_to_CalcH2[Index]; var MinHeight = -1; var Row = this.Content[RowIndex]; var CellsCount = Row.Get_CellsCount() for (var CurCell = 0; CurCell < CellsCount; CurCell++) { var Cell = Row.Get_Cell(CurCell); var VMerge = Cell.GetVMerge(); if (vmerge_Restart === VMerge) { var CurMinHeight = Cell.Content.Get_EmptyHeight(); if (CurMinHeight < MinHeight || MinHeight === -1) MinHeight = CurMinHeight; } } var OldHeight = this.Content[RowIndex].Get_Height(); if (undefined === OldHeight || Asc.linerule_Auto == OldHeight.HRule || ( MinHeight > OldHeight.Value )) this.Content[RowIndex].Set_Height(MinHeight, linerule_AtLeast); } // HACK: Восстанавливаем флаги и выставляем, что стиль всей таблицы нужно пересчитать AscCommon.g_oIdCounter.m_bLoad = bLoad; AscCommon.g_oIdCounter.m_bRead = bRead; this.Recalc_CompiledPr2(); if (Rows_to_Delete.length <= 0) return false; if (true === bSaveHeight) { // Сначала разберемся со строками, у которых надо проставить минимальную высоту for (var nIndex = 0, nCount = Rows_to_CalcH.length; nIndex < nCount; ++nIndex) { var nCurRow = Rows_to_CalcH[nIndex]; var nHeightValue = null; for (var nCurPage in this.RowsInfo[nCurRow].H) { if (null === nHeightValue) { nHeightValue = this.RowsInfo[nCurRow].H[nCurPage]; } else { nHeightValue = null; break; } } if (null !== nHeightValue) this.GetRow(nCurRow).SetHeight(nHeightValue, linerule_AtLeast); } // Рассчитаем высоты строк, так чтобы после удаления, общий вид таблицы не менялся for (var Counter = 0; Counter < Rows_to_Delete.length;) { var CurRowSpan = 1; var StartRow = Rows_to_Delete[Counter]; while (Counter + CurRowSpan < Rows_to_Delete.length && Rows_to_Delete[Counter] + CurRowSpan === Rows_to_Delete[Counter + CurRowSpan]) CurRowSpan++; if (this.RowsInfo[StartRow - 1 + CurRowSpan].StartPage === this.RowsInfo[StartRow - 1].StartPage) { var StartPage = this.RowsInfo[StartRow - 1 + CurRowSpan].StartPage; var Summary_Height = this.RowsInfo[StartRow - 1 + CurRowSpan].H[StartPage] + this.RowsInfo[StartRow - 1 + CurRowSpan].Y[StartPage] - this.RowsInfo[StartRow - 1].Y[StartPage]; this.Content[StartRow - 1].Set_Height(Summary_Height, linerule_AtLeast); } Counter += CurRowSpan; } } // Удаляем, начиная с последней строки, чтобы не пересчитывать номера строк for (var Index = Rows_to_Delete.length - 1; Index >= 0; Index--) { var Row_to_Delete = Rows_to_Delete[Index]; this.private_RemoveRow(Row_to_Delete); } return true; }; CTable.prototype.private_RemoveRow = function(nIndex) { if (nIndex >= this.Content.length || nIndex < 0) return; this.Content[nIndex].PreDelete(); AscCommon.History.Add(new CChangesTableRemoveRow(this, nIndex, [this.Content[nIndex]])); this.Rows--; this.Content.splice(nIndex, 1); this.TableRowsBottom.splice(nIndex, 1); this.RowsInfo.splice(nIndex, 1); this.Internal_ReIndexing(nIndex); this.private_CheckCurCell(); this.private_UpdateTableGrid(); this.OnContentChange(); this.updateTrackRevisions(); }; CTable.prototype.private_AddRow = function(Index, CellsCount, bReIndexing, _NewRow) { if (Index < 0) Index = 0; if (Index >= this.Content.length) Index = this.Content.length; this.Rows++; var NewRow = ( undefined === _NewRow ? new CTableRow(this, CellsCount) : _NewRow ); AscCommon.History.Add(new CChangesTableAddRow(this, Index, [NewRow])); this.Content.splice(Index, 0, NewRow); this.TableRowsBottom.splice(Index, 0, {}); this.RowsInfo.splice(Index, 0, new CTableRowsInfo()); if (true === bReIndexing) { this.Internal_ReIndexing(Index); } else { if (Index > 0) { this.Content[Index - 1].Next = NewRow; NewRow.Prev = this.Content[Index - 1]; } else NewRow.Prev = null; if (Index < this.Content.length - 1) { this.Content[Index + 1].Prev = NewRow; NewRow.Next = this.Content[Index + 1]; } else NewRow.Next = null; } NewRow.Table = this; this.private_CheckCurCell(); this.private_UpdateTableGrid(); this.OnContentChange(); this.updateTrackRevisions(); return NewRow; }; CTable.prototype.Clear_ContentChanges = function() { this.m_oContentChanges.Clear(); }; CTable.prototype.Add_ContentChanges = function(Changes) { this.m_oContentChanges.Add(Changes); }; CTable.prototype.Refresh_ContentChanges = function() { this.m_oContentChanges.Refresh(); }; CTable.prototype.Internal_ReIndexing = function(StartIndex) { if ("undefined" === typeof(StartIndex)) StartIndex = 0; for (var Ind = StartIndex; Ind < this.Content.length; Ind++) { this.Content[Ind].SetIndex(Ind); this.Content[Ind].Prev = ( Ind > 0 ? this.Content[Ind - 1] : null ); this.Content[Ind].Next = ( Ind < this.Content.length - 1 ? this.Content[Ind + 1] : null ); this.Content[Ind].Table = this; } }; CTable.prototype.ReIndexing = function(StartIndex) { this.Internal_ReIndexing(0); var Count = this.Content.length; for (var Ind = StartIndex; Ind < Count; Ind++) { this.Content[Ind].Internal_ReIndexing(0); } }; /** * Переделываем сетку таблицы заново, исходя из массива RowsInfo * В данном массиве заданы для каждой строки ширины всех ячеек (либо * пропусков до или после строк GridBefore/GridAfter). * На выходе мы отдаем новую сетку TableGrid и массив RowsInfo, в * котором для каждой ячейки(пропуска) указан GridSpan. */ CTable.prototype.private_CreateNewGrid = function(arrRowsInfo) { return this.Internal_CreateNewGrid(arrRowsInfo); }; CTable.prototype.Internal_CreateNewGrid = function(RowsInfo) { var nCellSpacing = this.Content[0].GetCellSpacing(); var CurPos = []; var CurX = []; for (var Index = 0; Index < RowsInfo.length; Index++) { CurPos[Index] = 0; CurX[Index] = RowsInfo[Index][0].W; for (var Index2 = 0; Index2 < RowsInfo[Index].length; Index2++) { RowsInfo[Index][Index2].GridSpan = 1; // Последние элемент всегда должен означать GridAfter, но с // нулевыем начальным значением. if (1 != RowsInfo[Index][RowsInfo[Index].length - 1].Type) { RowsInfo[Index].push({W : 0, Type : 1, GridSpan : 0}); } else { RowsInfo[Index][RowsInfo[Index].length - 1] = {W : 0, Type : 1, GridSpan : 0}; } } } var TableGrid = []; var bEnd = false; var PrevX = 0; while (true != bEnd) { var MinX = -1; for (var Index = 0; Index < RowsInfo.length; Index++) { if ((MinX === -1 || CurX[Index] < MinX) && !( RowsInfo[Index].length - 1 === CurPos[Index] && 1 === RowsInfo[Index][CurPos[Index]].Type )) MinX = CurX[Index]; } for (var Index = 0; Index < RowsInfo.length; Index++) { if (RowsInfo[Index].length - 1 === CurPos[Index] && 1 === RowsInfo[Index][CurPos[Index]].Type) RowsInfo[Index][CurPos[Index]].GridSpan++; else { if (Math.abs(MinX - CurX[Index]) < 0.001) { CurPos[Index]++; CurX[Index] += RowsInfo[Index][CurPos[Index]].W; } else { RowsInfo[Index][CurPos[Index]].GridSpan++; } } } TableGrid.push(MinX - PrevX); PrevX = MinX; bEnd = true; for (var Index = 0; Index < RowsInfo.length; Index++) { if (RowsInfo[Index].length - 1 != CurPos[Index]) { bEnd = false; break; } } } for (var CurRow = 0; CurRow < RowsInfo.length; CurRow++) { var RowInfo = RowsInfo[CurRow]; var Row = this.Content[CurRow]; var CurIndex = 0; if (-1 === RowInfo[0].Type) { if (RowInfo[0].GridSpan > 0) { Row.Set_Before(RowInfo[0].GridSpan); } CurIndex++; } else { Row.Set_Before(0); } for (var CurCell = 0; CurIndex < RowInfo.length; CurIndex++, CurCell++) { if (1 === RowInfo[CurIndex].Type) break; var Cell = Row.Get_Cell(CurCell); Cell.Set_GridSpan(RowInfo[CurIndex].GridSpan); var WType = Cell.Get_W().Type; if (tblwidth_Auto != WType && tblwidth_Nil != WType) { var nW = RowInfo[CurIndex].W; if (null !== nCellSpacing) { if (0 === CurCell || (1 === CurCell && RowInfo[0].Type === -1)) nW -= nCellSpacing / 2; nW -= nCellSpacing; if (RowInfo.length - 2 === CurCell) nW -= nCellSpacing / 2; } Cell.Set_W(new CTableMeasurement(tblwidth_Mm, nW)); } } CurIndex = RowInfo.length - 1; if (1 === RowInfo[CurIndex].Type) { Row.Set_After(RowInfo[CurIndex].GridSpan); } else { Row.Set_After(0); } } this.SetTableGrid(TableGrid); return TableGrid; }; /** * Получаем информацию о всех строках, используемую для генерации ширин колонок * @returns {Array} */ CTable.prototype.private_GetRowsInfo = function() { var arrRowsInfo = []; for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { arrRowsInfo[nCurRow] = []; var oRow = this.GetRow(nCurRow); var oBeforeInfo = oRow.GetBefore(); if (oBeforeInfo.GridBefore > 0) arrRowsInfo[nCurRow].push({W : this.TableSumGrid[oBeforeInfo.Grid - 1], Type : -1, GridSpan : 1}); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); var oCellInfo = oRow.GetCellInfo(nCurCell); if (!oCellInfo) { arrRowsInfo[nCurRow].push({ W : 0, Type : 0, GridSpan : 1 }); } else { var nCurGridStart = oCellInfo.StartGridCol; var nCurGridEnd = nCurGridStart + oCell.GetGridSpan() - 1; if (undefined === this.TableSumGrid[nCurGridEnd] || undefined === this.TableSumGrid[nCurGridStart - 1]) { arrRowsInfo[nCurRow].push({ W : 0, Type : 0, GridSpan : 1 }); } else { arrRowsInfo[nCurRow].push({ W : this.TableSumGrid[nCurGridEnd] - this.TableSumGrid[nCurGridStart - 1], Type : 0, GridSpan : 1 }); } } } } return arrRowsInfo; }; /** * Добавляем в массив информации о строках новую ячейку в заданной строке * @param arrRowsInfo * @param nRowIndex * @param nCellIndex * @param {number} nW - заданная ширина ячейка * @returns {boolean} Удалось ли добавить информацию */ CTable.prototype.private_AddCellToRowsInfo = function(arrRowsInfo, nRowIndex, nCellIndex, nW) { if (!arrRowsInfo || !arrRowsInfo[nRowIndex]) return false; var nPos = nCellIndex; if (-1 === arrRowsInfo[nRowIndex][0].Type) nPos++; if (nPos > arrRowsInfo[nRowIndex].length) return false; arrRowsInfo[nRowIndex].splice(nPos, 0, { W : nW, Type : 0, GridSpan : 1 }); return true; }; CTable.prototype.Internal_UpdateCellW = function(Col) { for (var CurRow = 0; CurRow < this.Content.length; CurRow++) { var Row = this.Content[CurRow]; var Cells_Count = Row.Get_CellsCount(); var CurGridCol = Row.Get_Before().GridBefore; for (var CurCell = 0; CurCell < Cells_Count; CurCell++) { var Cell = Row.Get_Cell(CurCell); var GridSpan = Cell.Get_GridSpan(); if (Col >= CurGridCol && Col < CurGridCol + GridSpan) { var CellWType = Cell.Get_W().Type; if (tblwidth_Auto != CellWType && tblwidth_Nil != CellWType) { var W = 0; for (var CurSpan = CurGridCol; CurSpan < CurGridCol + GridSpan; CurSpan++) W += this.TableGridCalc[CurSpan]; Cell.Set_W(new CTableMeasurement(tblwidth_Mm, W)); } break; } CurGridCol += GridSpan; } } }; /** * Получаем какую из двух заданных конфликтующих границ использовать * @param oBorder1 {CDocumentBorder} * @param oBorder2 {CDocumentBorder} * @param [isTableBorder1=false] {boolean} является ли граница границей всей таблицы * @param [isTableBorder2=false] {boolean} является ли граница границей всей таблицы * @param [isTopMergedCell1=true] {boolean} является ли граница границей текущей ячейки * @param [isTopMergedCell2=true] {boolean} является ли граница границей текущей ячейки * @returns {CDocumentBorder} */ CTable.prototype.private_ResolveBordersConflict = function(oBorder1, oBorder2, isTableBorder1, isTableBorder2, isTopMergedCell1, isTopMergedCell2) { if (undefined === isTableBorder1) isTableBorder1 = false; if (undefined === isTableBorder2) isTableBorder2 = false; // Граница ячейки всегда побеждает границу таблицы, если первая задана if (isTableBorder1) return oBorder2; if (isTableBorder2) return oBorder1; // Всегда побеждает непустая граница if (oBorder1.IsNone()) return oBorder2; if (oBorder2.IsNone()) return oBorder1; if (this.bPresentation) { if (undefined === isTopMergedCell1) isTopMergedCell1 = true; if (!isTopMergedCell1) { return oBorder2; } if (undefined === isTopMergedCell2) isTopMergedCell2 = true; if (!isTopMergedCell2) { return oBorder1; } } // TODO: Как только мы реализуем рисование не только простых границ, // сделать здесь обработку. W_b = Border.Size * Border_Num, // где Border_Num зависит от Border.Value var W_b_1 = oBorder1.Size; var W_b_2 = oBorder2.Size; if (W_b_1 > W_b_2) return oBorder1; else if (W_b_2 > W_b_1) return oBorder2; var Brightness_1_1 = oBorder1.Color.r + oBorder1.Color.b + 2 * oBorder1.Color.g; var Brightness_1_2 = oBorder2.Color.r + oBorder2.Color.b + 2 * oBorder2.Color.g; if (Brightness_1_1 < Brightness_1_2) return oBorder1; else if (Brightness_1_2 < Brightness_1_1) return oBorder2; var Brightness_2_1 = oBorder1.Color.b + 2 * oBorder1.Color.g; var Brightness_2_2 = oBorder2.Color.b + 2 * oBorder2.Color.g; if (Brightness_2_1 < Brightness_2_2) return oBorder1; else if (Brightness_2_2 < Brightness_2_1) return oBorder2; var Brightness_3_1 = oBorder1.Color.g; var Brightness_3_2 = oBorder2.Color.g; if (Brightness_3_1 < Brightness_3_2) return oBorder1; else if (Brightness_3_2 < Brightness_3_1) return oBorder2; // Две границы функционально идентичны, нам все равно какую использовать return oBorder1; }; /** * Получаем левую верхнюю ячейку в текущем объединении */ CTable.prototype.Internal_Get_StartMergedCell = function(StartRow, StartGridCol, GridSpan) { var Result = null; for (var Index = StartRow; Index >= 0; Index--) { var Row = this.Content[Index]; var BeforeInfo = Row.Get_Before(); var CurGridCol = BeforeInfo.GridBefore; var CurCell = 0; var CellsCount = Row.Get_CellsCount(); var bWasMerged = false; while (CurGridCol <= StartGridCol && CurCell < CellsCount) { var Cell = Row.Get_Cell(CurCell); var CellGridSpan = Cell.Get_GridSpan(); var Vmerge = Cell.GetVMerge(); if (CurGridCol === StartGridCol && GridSpan === CellGridSpan && vmerge_Continue === Vmerge) { bWasMerged = true; Result = Cell; break; } else if (CurGridCol === StartGridCol && GridSpan === CellGridSpan && vmerge_Continue != Vmerge) { bWasMerged = true; Result = Cell; return Result; } // Если данная ячейка имеет пересечение с заданным промежутком, но польностью с ним не совпадает else if (CurGridCol <= StartGridCol + GridSpan - 1 && CurGridCol + CellGridSpan - 1 >= StartGridCol) break; CurGridCol += CellGridSpan; CurCell++; } if (false === bWasMerged) break; } return Result; }; /** * Получаем левую верхнюю ячейку в текущем объединении */ CTable.prototype.Internal_Get_EndMergedCell = function(StartRow, StartGridCol, GridSpan) { var Result = null; for (var Index = StartRow, Count = this.Content.length; Index < Count; Index++) { var Row = this.Content[Index]; var BeforeInfo = Row.Get_Before(); var CurGridCol = BeforeInfo.GridBefore; var CurCell = 0; var CellsCount = Row.Get_CellsCount(); var bWasMerged = false; while (CurGridCol <= StartGridCol && CurCell < CellsCount) { var Cell = Row.Get_Cell(CurCell); var CellGridSpan = Cell.Get_GridSpan(); var Vmerge = Cell.GetVMerge(); if (CurGridCol === StartGridCol && GridSpan === CellGridSpan) { if (vmerge_Continue === Vmerge || Index === StartRow) { bWasMerged = true; Result = Cell; break; } else return Result; } // Если данная ячейка имеет пересечение с заданным промежутком, но польностью с ним не совпадает else if (CurGridCol <= StartGridCol + GridSpan - 1 && CurGridCol + CellGridSpan - 1 >= StartGridCol) break; CurGridCol += CellGridSpan; CurCell++; } if (false === bWasMerged) break; } return Result; }; /** * Получаем массив ячеек попадающих в заданное вертикальное объединение */ CTable.prototype.private_GetMergedCells = function(RowIndex, StartGridCol, GridSpan) { // Сначала проверим данну строку var Row = this.Content[RowIndex]; var CellIndex = this.private_GetCellIndexByStartGridCol(RowIndex, StartGridCol); if (-1 === CellIndex) return []; var Cell = Row.Get_Cell(CellIndex); if (GridSpan !== Cell.Get_GridSpan()) return []; var CellsArray = [Cell]; // Ищем ячейки вверх for (var Index = RowIndex - 1; Index >= 0; Index--) { var CellIndex = this.private_GetCellIndexByStartGridCol(Index, StartGridCol); if (-1 === CellIndex) break; var Cell = this.Content[Index].Get_Cell(CellIndex); if (GridSpan !== Cell.Get_GridSpan()) break; var Vmerge = Cell.GetVMerge(); if (vmerge_Continue !== Vmerge) break; CellsArray.splice(0, 0, Cell); } // Ищем ячейки вниз for (var Index = RowIndex + 1, Count = this.Content.length; Index < Count; Index++) { var CellIndex = this.private_GetCellIndexByStartGridCol(Index, StartGridCol); if (-1 === CellIndex) break; var Cell = this.Content[Index].Get_Cell(CellIndex); if (GridSpan !== Cell.Get_GridSpan()) break; var Vmerge = Cell.GetVMerge(); if (vmerge_Continue !== Vmerge) break; CellsArray.push(Cell); } return CellsArray; }; CTable.prototype.private_GetCellsPosArrayByCellsArray = function(CellsArray) { var Result = []; for (var Index = 0, Count = CellsArray.length; Index < Count; Index++) { var Cell = CellsArray[Index]; Result.push({Cell : Cell.Index, Row : Cell.Row.Index}); } return Result; }; /** * Получаем левую верхнюю ячейку в текущем объединении * @param {number} nCellIndex * @param {number} nRowIndex * @returns {?CTableCell} */ CTable.prototype.GetStartMergedCell = function(nCellIndex, nRowIndex) { var oRow = this.GetRow(nRowIndex); if (!oRow) return null; var oCell = oRow.GetCell(nCellIndex); var oCellInfo = oRow.GetCellInfo(nCellIndex); if (!oCell || !oCellInfo) return null; return this.Internal_Get_StartMergedCell(nRowIndex, oCellInfo.StartGridCol, oCell.GetGridSpan()); }; /** * Получаем количество ячеек (=количество строк) попавших в вертикальное объединения, начиная с заданной ячейки внизю * @param nCellIndex номер ячейки в строке * @param nRowIndex номер строки * @returns {number} */ CTable.prototype.GetVMergeCount = function(nCellIndex, nRowIndex) { var oRow = this.GetRow(nRowIndex); if (!oRow) return 1; var oCell = oRow.GetCell(nCellIndex); if (!oCell) return 1; var oCellInfo = oRow.GetCellInfo(nCellIndex); if (!oCellInfo) return 1; return this.Internal_GetVertMergeCount(nRowIndex, oCellInfo.StartGridCol, oCell.GetGridSpan()); }; /** * Получаем номер ячейки в заданной строке по заданной колонке * @param {number} nCurRow * @param {number} nStartGridCol * @param {boolean} [isAllowOverlap = false] true - ищем ячейку, в которой началась данная колонка, false - ищем ячейку, строго начавшуюся с заданной колонки * @returns {number} Возвращаем -1, если не найдена ячейка */ CTable.prototype.private_GetCellIndexByStartGridCol = function(nCurRow, nStartGridCol, isAllowOverlap) { var oRow = this.GetRow(nCurRow); if (!oRow) return -1; var nCurGridCol = oRow.GetBefore().Grid; if (isAllowOverlap) { for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { if (nStartGridCol === nCurGridCol) return nCurCell; else if (nCurGridCol > nStartGridCol) return nCurCell - 1; var oCell = oRow.GetCell(nCurCell); nCurGridCol += oCell.GetGridSpan(); } return oRow.GetCellsCount() - 1; } else { for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { if (nStartGridCol === nCurGridCol) return nCurCell; else if (nCurGridCol > nStartGridCol) return -1; var oCell = oRow.GetCell(nCurCell); nCurGridCol += oCell.GetGridSpan(); } } return -1; }; /** * Получаем ячейку в заданной строке, начинающуюся в заданной колонке * @param {number} nCurRow * @param {number} nStartGridCol * @returns {?CTableCell} */ CTable.prototype.GetCellByStartGridCol = function(nCurRow, nStartGridCol) { var oRow = this.GetRow(nCurRow); if (!oRow) return null; var nCurCell = this.private_GetCellIndexByStartGridCol(nCurRow, nStartGridCol, false); if (-1 === nCurCell) return null; var oCell = oRow.GetCell(nCurCell); return oCell ? oCell : null; }; /** * Запрашиваем пересчет сетки таблицы */ CTable.prototype.private_UpdateTableGrid = function() { this.RecalcInfo.TableGrid = true; }; CTable.prototype.private_UpdateTableMarkup = function(nRowIndex, nCellIndex, nCurPage) { this.Markup.Internal = { RowIndex : nRowIndex, CellIndex : nCellIndex, PageNum : nCurPage }; var oPage = this.Pages[nCurPage]; if (!oPage || !this.IsRecalculated()) return; this.Markup.X = oPage.X; var oRow = this.GetRow(nRowIndex); var nCellSpacing = null === oRow.GetCellSpacing() ? 0 : oRow.GetCellSpacing(); var nCellsCount = oRow.GetCellsCount(); var nGridBefore = oRow.GetBefore().Grid; this.Markup.X += this.TableSumGrid[nGridBefore - 1]; this.Markup.Cols = []; this.Markup.Margins = []; for (var nCurCell = 0; nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); var oCellInfo = oRow.GetCellInfo(nCurCell); var nStartGridCol = oCellInfo.StartGridCol; var nGridSpan = oCell.GetGridSpan(); var oCellMargin = oCell.GetMargins(); this.Markup.Cols.push(this.TableSumGrid[nStartGridCol + nGridSpan - 1] - this.TableSumGrid[nStartGridCol - 1]); var nMarginLeft = oCellMargin.Left.W; var nMarginRight = oCellMargin.Right.W; if (0 === nCurCell) nMarginLeft += nCellSpacing; else nMarginLeft += nCellSpacing / 2; if (nCellsCount - 1 === nCurCell) nMarginRight += nCellSpacing; else nMarginRight += nCellSpacing / 2; this.Markup.Margins.push({Left : nMarginLeft, Right : nMarginRight}); } // Определим какие строки попадают на данную страницу var Row_start = this.Pages[nCurPage].FirstRow; var Row_last = Row_start; if (nCurPage + 1 < this.Pages.length) { Row_last = this.Pages[nCurPage + 1].FirstRow; // Возможно, на данной странице строку, с которой началось разбиение на стрнице, // не надо рисовать. (Если начальная и конечная строки совпадают, тогда это 2 // или более страница данной строки) if ((Row_start !== Row_last || ( 0 === Row_start && 0 === Row_last ) ) && false === this.RowsInfo[Row_last].FirstPage) Row_last--; } else { Row_last = this.Content.length - 1; } this.Markup.Rows = []; for (var CurRow = Row_start; CurRow <= Row_last; CurRow++) { if (this.RowsInfo[CurRow] && undefined !== this.RowsInfo[CurRow].Y[nCurPage] && undefined !== this.RowsInfo[CurRow].H[nCurPage]) this.Markup.Rows.push({Y : this.RowsInfo[CurRow].Y[nCurPage], H : this.RowsInfo[CurRow].H[nCurPage]}); } this.Markup.CurCol = nCellIndex; this.Markup.CurRow = nRowIndex - Row_start; var Transform = this.Get_ParentTextTransform(); this.DrawingDocument.Set_RulerState_Table(this.Markup, Transform); }; /** * Проверяем попадание в границу и определяем дополнительно попадание во вспомогательные области * Значения для поля Border: -1 - не попали в границу * 0 * |---| * 3| |1 * |---| * 2 * @param X * @param Y * @param nCurPage * @returns {{Pos: {Row, Cell}, Border: number, Row: number, RowSelection: boolean, ColumnSelection: boolean, CellSelection: boolean}} */ CTable.prototype.private_CheckHitInBorder = function(X, Y, nCurPage) { // Сначала определим ячейку, у которой границы мы будем проверять var oCellPos = this.private_GetCellByXY(X, Y, nCurPage); var oResult = { Pos : oCellPos, Border : -1, Row : oCellPos.Row, RowSelection : false, ColumnSelection : false, CellSelection : false }; var nCurRow = oCellPos.Row; var nCurCell = oCellPos.Cell; var oRow = this.GetRow(nCurRow); var oCell = oRow.GetCell(nCurCell); var oCellInfo = oRow.GetCellInfo(nCurCell); var nVMergeCount = this.GetVMergeCount(nCurCell, nCurRow); var nVMergeCountOnPage = this.private_GetVertMergeCountOnPage(nCurPage, nCurRow, oCellInfo.StartGridCol, oCell.GetGridSpan()); if (nVMergeCountOnPage <= 0) return oResult; var oPage = this.Pages[nCurPage]; var X_cell_start = oPage.X + oCellInfo.X_grid_start; var X_cell_end = oPage.X + oCellInfo.X_grid_end; var Y_cell_start = this.RowsInfo[nCurRow].Y[nCurPage]; var Y_cell_end = this.RowsInfo[nCurRow + nVMergeCountOnPage - 1].Y[nCurPage] + this.RowsInfo[nCurRow + nVMergeCountOnPage - 1].H[nCurPage]; var nRadius = this.DrawingDocument.GetMMPerDot(3); // 3 px if (Y <= Y_cell_start + nRadius && Y >= Y_cell_start - nRadius) { oResult.Border = 0; } else if (Y <= Y_cell_end + nRadius && Y >= Y_cell_end - nRadius) { if (nVMergeCountOnPage !== nVMergeCount) { oResult.Border = -1; } else { oResult.Border = 2; oResult.Row = nCurRow + nVMergeCount - 1; } } else if (X <= X_cell_start + nRadius && X >= X_cell_start - nRadius) { oResult.Border = 3; } else if (X <= X_cell_end + nRadius && X >= X_cell_end - nRadius) { oResult.Border = 1; } if (0 === nCurCell && X <= X_cell_start) { oResult.RowSelection = true; oResult.Border = -1; } else if (0 === nCurRow && Y <= Y_cell_start + nRadius) { oResult.ColumnSelection = true; oResult.Border = -1; } else if (X_cell_start + nRadius <= X && X <= X_cell_end) { var oLeftMargin = oCell.GetMargins().Left; var nCellSpacing = oRow.GetCellSpacing(); var nSpacingShift = null === nCellSpacing ? 0 : nCellSpacing / 2; if (X <= X_cell_start + nSpacingShift + oLeftMargin.W) { oResult.CellSelection = true; oResult.Border = -1; } } return oResult; }; /** * Обновляем массив выделенных ячеек * @param {boolean} [bForceSelectByLines=false] использовать ли обязательное выделение по строкам */ CTable.prototype.private_UpdateSelectedCellsArray = function(bForceSelectByLines) { if (undefined === bForceSelectByLines) bForceSelectByLines = false; this.Selection.Type = table_Selection_Cell; var arrSelectionData = []; if (this.Parent.IsSelectedSingleElement() && false === bForceSelectByLines) { // Определяем ячейки, которые попали в наш селект // Алгоритм следующий: // 1. Находим максимальную левую и правую границы, у начальной и конечной // ячеек селекта. Границы мы находим по сетке таблицы (TableGrid). // 2. Бежим по строкам и добавляем все ячейки, которые имеют непустое пересечение // с нашим диапазоном в сетке. var StartRow = this.Selection.StartPos.Pos.Row; var StartCell = this.Selection.StartPos.Pos.Cell; var EndRow = this.Selection.EndPos.Pos.Row; var EndCell = this.Selection.EndPos.Pos.Cell; if (EndRow < StartRow) { var TempRow = StartRow; StartRow = EndRow; EndRow = TempRow; var TempCell = StartCell; StartCell = EndCell; EndCell = TempCell; } if (StartRow === EndRow) { if (EndCell < StartCell) { var TempCell = StartCell; StartCell = EndCell; EndCell = TempCell; } var Row = this.Content[StartRow]; for (var CurCell = StartCell; CurCell <= EndCell; CurCell++) { var Cell = Row.Get_Cell(CurCell); var Vmerge = Cell.GetVMerge(); // Обсчет такик ячеек произошел ранее if (vmerge_Continue === Vmerge) continue; arrSelectionData.push({Row : StartRow, Cell : CurCell}); } } else { var Cell_s = this.Content[StartRow].Get_Cell(StartCell); var Cell_e = this.Content[EndRow].Get_Cell(EndCell); var GridCol_cs_start = this.Content[StartRow].Get_StartGridCol(StartCell); var GridCol_cs_end = Cell_s.Get_GridSpan() - 1 + GridCol_cs_start; var GridCol_ce_start = this.Content[EndRow].Get_StartGridCol(EndCell); var GridCol_ce_end = Cell_e.Get_GridSpan() - 1 + GridCol_ce_start; var GridCol_start = GridCol_cs_start; if (GridCol_ce_start < GridCol_start) GridCol_start = GridCol_ce_start; var GridCol_end = GridCol_cs_end; if (GridCol_end < GridCol_ce_end) GridCol_end = GridCol_ce_end; // Ориентируемся не только по логическому расположению колонок, но и по визуальному: // если между колонками расстояние меньше 6 твипсов (примерно 0.1мм), тогда они визуально сольются в // одну колонку, поэтому нам нужно учесть эту погрешность, при учете попадания колонки в селект. // Расстояние 6 твипсов получено с учетом максимального зума в 500% var nMaxError = 0.1; while (GridCol_start < this.TableSumGrid.length - 1 && GridCol_start < GridCol_end) { if (this.TableSumGrid[GridCol_start] - this.TableSumGrid[GridCol_start - 1] < nMaxError) { nMaxError -= this.TableSumGrid[GridCol_start] - this.TableSumGrid[GridCol_start - 1]; GridCol_start++; } else { break; } } nMaxError = 0.1; while (GridCol_end > 0 && GridCol_end > GridCol_start) { if (this.TableSumGrid[GridCol_end] - this.TableSumGrid[GridCol_end - 1] < nMaxError) { nMaxError -= this.TableSumGrid[GridCol_end] - this.TableSumGrid[GridCol_end - 1]; GridCol_end--; } else { break; } } for (var nCurRow = StartRow; nCurRow <= EndRow; ++nCurRow) { var oRow = this.GetRow(nCurRow); var nCurGridCol = oRow.GetBefore().Grid; for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); var nGridSpan = oCell.GetGridSpan(); if (vmerge_Continue === oCell.GetVMerge()) { nCurGridCol += nGridSpan; continue; } if ((nCurGridCol >= GridCol_start && nCurGridCol <= GridCol_end) || (nCurGridCol + nGridSpan - 1 >= GridCol_start && nCurGridCol + nGridSpan - 1 <= GridCol_end) || (nCurGridCol <= GridCol_start && GridCol_end <= nCurGridCol + nGridSpan - 1)) { arrSelectionData.push({Row : nCurRow, Cell : nCurCell}); } nCurGridCol += nGridSpan; } } } } else { var nRowsCount = this.GetRowsCount(); var nStartRow = Math.min(Math.max(0, this.Selection.StartPos.Pos.Row), nRowsCount - 1); var nEndRow = Math.min(Math.max(0, this.Selection.EndPos.Pos.Row), nRowsCount - 1); if (nEndRow < nStartRow) { var nSwapRow = nStartRow; nStartRow = nEndRow; nEndRow = nSwapRow; } for (var nCurRow = nStartRow; nCurRow <= nEndRow; ++nCurRow) { var oRow = this.GetRow(nCurRow); // Если строка, с которой мы начинаем селект целиком смержена по вертикали, то добавляем первую ячейку мержа // чтобы у нас не получился пустой массив селекта if (nCurRow === nStartRow && this.private_IsVMergedRow(nCurRow)) { let cell = this.GetStartMergedCell(0, nCurRow); arrSelectionData.push({Row : cell.GetRow().GetIndex(), Cell : cell.GetIndex()}); } for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); if (vmerge_Continue === oCell.GetVMerge()) continue; arrSelectionData.push({Row : nCurRow, Cell : nCurCell}); } } } if (arrSelectionData.length > 1) this.Selection.CurRow = arrSelectionData[arrSelectionData.length - 1].Row; this.private_SetSelectionData(arrSelectionData); }; CTable.prototype.private_SetSelectionData = function(oData) { if (!this.Selection.Data && !oData) { this.Selection.Data = null; return; } if (!this.Selection.Data) { this.Selection.Data = oData; return this.private_UpdateSelectionInCells(); } if (!oData) { this.Selection.Data = null; return this.private_RemoveSelectionInCells(); } var arrOldSelectionData = this.Selection.Data; this.Selection.Data = oData; var arrFlags = []; for (var nIndex = 0, nCount = arrOldSelectionData.length; nIndex < nCount; ++nIndex) { var oPos = arrOldSelectionData[nIndex]; var nPos = (oPos.Row << 16) | (oPos.Cell & 0xFFFF) arrFlags[nPos] = 1; } for (var nIndex = 0, nCount = this.Selection.Data.length; nIndex < nCount; ++nIndex) { var oPos = this.Selection.Data[nIndex]; var nPos = (oPos.Row << 16) | (oPos.Cell & 0xFFFF) if (undefined !== arrFlags[nPos]) arrFlags[nPos] |= 2; else arrFlags[nPos] = 2; } for (var nIndex = 0, nCount = arrOldSelectionData.length; nIndex < nCount; ++nIndex) { var oPos = arrOldSelectionData[nIndex]; var nPos = (oPos.Row << 16) | (oPos.Cell & 0xFFFF) if (undefined !== arrFlags[nPos] && (arrFlags[nPos] & 1) && !(arrFlags[nPos] & 2)) { var oRow = this.GetRow(oPos.Row); if (!oRow) continue; var oCell = oRow.GetCell(oPos.Cell); if (!oCell) continue; oCell.GetContent().RemoveSelection(); } } for (var nIndex = 0, nCount = this.Selection.Data.length; nIndex < nCount; ++nIndex) { var oPos = this.Selection.Data[nIndex]; var nPos = (oPos.Row << 16) | (oPos.Cell & 0xFFFF) if (undefined !== arrFlags[nPos] && (arrFlags[nPos] & 2) && !(arrFlags[nPos] & 1)) { var oRow = this.GetRow(oPos.Row); if (!oRow) continue; var oCell = oRow.GetCell(oPos.Cell); if (!oCell) continue; oCell.GetContent().SelectAll(); } } }; CTable.prototype.private_RemoveSelectionInCells = function() { if (!this.Selection.Data) return; for (var nIndex = 0, nCount = this.Selection.Data.length; nIndex < nCount; ++nIndex) { var oPos = this.Selection.Data[nIndex]; var oRow = this.GetRow(oPos.Row); if (!oRow) continue; var oCell = oRow.GetCell(oPos.Cell); if (!oCell) continue; oCell.GetContent().RemoveSelection(); } }; CTable.prototype.private_UpdateSelectionInCells = function() { if (!this.Selection.Data) return; if (this.IsCellSelection()) { for (var nIndex = 0, nCount = this.Selection.Data.length; nIndex < nCount; ++nIndex) { var oPos = this.Selection.Data[nIndex]; var oRow = this.GetRow(oPos.Row); if (!oRow) continue; var oCell = oRow.GetCell(oPos.Cell); if (!oCell) continue; oCell.GetContent().SelectAll(); } } }; CTable.prototype.Internal_CompareBorders2 = function(Border1, Border2) { var ResultBorder = new CDocumentBorder(); if (Border1.Value != Border2.Value) ResultBorder.Value = undefined; else ResultBorder.Value = Border1.Value; if (Border1.Size != Border2.Size) ResultBorder.Size = undefined; else ResultBorder.Size = Border1.Size; if (undefined === Border1.Color || undefined === Border2.Color || Border1.Color.r != Border2.Color.r || Border1.Color.g != Border2.Color.g || Border1.Color.b != Border2.Color.b) ResultBorder.Color = undefined; else ResultBorder.Color.Set(Border1.Color.r, Border1.Color.g, Border1.Color.b); return ResultBorder; }; CTable.prototype.Internal_CompareBorders3 = function(Border1, Border2) { if (Border1.Value != Border2.Value) return false; if (Border1.Size != Border2.Size) return false; if (Border1.Color.r != Border2.Color.r || Border1.Color.g != Border2.Color.g || Border1.Color.b != Border2.Color.b) return false; return true; }; CTable.prototype.Internal_CheckNullBorder = function(Border) { if (null === Border || undefined === Border) return true; if (null != Border.Value) return false; if (null != Border.Size) return false; if (null != Border.Color && ( null != Border.Color.r || null != Border.Color.g || null != Border.Color.b ) || Border.Unifill != null) return false; return true; }; /** * Получаем минимальную ширину таблицы * @returns {number} */ CTable.prototype.private_GetTableMinWidth = function() { var nMinWidth = 0; for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); var nCellsCount = oRow.GetCellsCount(); var nCellSpacing = oRow.GetCellSpacing(); if (null === nCellSpacing) nCellSpacing = 0; var nRowWidth = nCellSpacing * (nCellsCount + 1); for (var nCurCell = 0; nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); var oCellMargins = oCell.GetMargins(); nRowWidth += oCellMargins.Left.W + oCellMargins.Right.W; } if (nMinWidth < nRowWidth) nMinWidth = nRowWidth; } return nMinWidth; }; /** * Рассчитываем минимальные знаяения для сетки таблицы * @returns {Array} */ CTable.prototype.private_GetMinGrid = function() { var nColsCount = this.TableGrid.length; var arrSumGrid = []; for (var nIndex = -1; nIndex < nColsCount; ++nIndex) { arrSumGrid[nIndex] = 0; } var arrMinCols = []; for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); var nCellSpacing = oRow.GetCellSpacing(); if (null === nCellSpacing) nCellSpacing = 0; var nCurGridCol = 0; for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); var oCellMargins = oCell.GetMargins(); var nGridSpan = oCell.GetGridSpan(); var nCellMinWidth = oCellMargins.Left.W + oCellMargins.Right.W; if (0 === nCurCell || nCellsCount - 1 === nCurCell) nCellMinWidth += nCellSpacing * 1.5; else nCellMinWidth += nCellSpacing; if (!arrMinCols[nGridSpan]) arrMinCols[nGridSpan] = []; arrMinCols[nGridSpan].push({Col : nCurGridCol, W : nCellMinWidth}); nCurGridCol += nGridSpan; } } for (var nGridSpan = 0; nGridSpan < nColsCount; ++nGridSpan) { var arrCols = arrMinCols[nGridSpan]; if (arrCols) { for (var nIndex = 0, nCount = arrCols.length; nIndex < nCount; ++nIndex) { var nCurGridCol = arrCols[nIndex].Col; var nMinW = arrCols[nIndex].W; if (arrSumGrid[nCurGridCol + nGridSpan - 1] < arrSumGrid[nCurGridCol - 1] + nMinW) { var nDiff = arrSumGrid[nCurGridCol - 1] + nMinW - arrSumGrid[nCurGridCol + nGridSpan - 1]; for (var nCol = nCurGridCol + nGridSpan - 1; nCol < nColsCount; ++nCol) { arrSumGrid[nCol] += nDiff; } } } } } var arrTableGridMin = []; arrTableGridMin[0] = arrSumGrid[0]; for (var nIndex = 1, nCount = arrSumGrid.length; nIndex < nCount; ++nIndex) arrTableGridMin[nIndex] = arrSumGrid[nIndex] - arrSumGrid[nIndex - 1]; return arrTableGridMin; }; CTable.prototype.Internal_ScaleTableWidth = function(SumGrid, TableW) { // Массив означает, какие колонки таблицы нам надо изменить var Grids_to_scale = []; for (var Index = 0; Index < SumGrid.length; Index++) Grids_to_scale[Index] = true; var Grids_to_scale_count = Grids_to_scale.length; var TableGrid = []; TableGrid[0] = SumGrid[0]; for (var Index = 1; Index < SumGrid.length; Index++) TableGrid[Index] = SumGrid[Index] - SumGrid[Index - 1]; var TableGrid_min = this.private_GetMinGrid(); var CurrentW = SumGrid[SumGrid.length - 1]; while (Grids_to_scale_count > 0 && CurrentW > 0.001) { // Пробуем ужать колонки таблицы var Koef = TableW / CurrentW; var TableGrid_cur = []; for (var Index = 0; Index < TableGrid.length; Index++) TableGrid_cur[Index] = TableGrid[Index]; for (var AddIndex = 0; AddIndex <= TableGrid_cur.length - 1; AddIndex++) { if (true === Grids_to_scale[AddIndex]) TableGrid_cur[AddIndex] = TableGrid_cur[AddIndex] * Koef; } var bBreak = true; // Проверяем, не стали ли некоторые колонки меньше минимально возможной ширины for (var AddIndex = 0; AddIndex <= TableGrid_cur.length - 1; AddIndex++) { if (true === Grids_to_scale[AddIndex] && TableGrid_cur[AddIndex] - TableGrid_min[AddIndex] < 0.001) { bBreak = false; Grids_to_scale[AddIndex] = false; Grids_to_scale_count--; CurrentW -= TableGrid[AddIndex]; TableW -= TableGrid_min[AddIndex]; TableGrid[AddIndex] = TableGrid_min[AddIndex]; } } if (true === bBreak) { for (var AddIndex = 0; AddIndex <= TableGrid_cur.length - 1; AddIndex++) { if (true === Grids_to_scale[AddIndex]) TableGrid[AddIndex] = TableGrid_cur[AddIndex]; } break; } } var SumGrid_new = []; SumGrid_new[-1] = 0; for (var Index = 0; Index < TableGrid.length; Index++) SumGrid_new[Index] = TableGrid[Index] + SumGrid_new[Index - 1]; return SumGrid_new; }; CTable.prototype.Internal_Get_NextCell = function(Pos) { var Cell_Index = Pos.Cell; var Row_Index = Pos.Row; if (Cell_Index < this.Content[Row_Index].Get_CellsCount() - 1) { Pos.Cell = Cell_Index + 1; return this.Content[Pos.Row].Get_Cell(Pos.Cell); } else if (Row_Index < this.Content.length - 1) { Pos.Row = Row_Index + 1; Pos.Cell = 0; return this.Content[Pos.Row].Get_Cell(Pos.Cell); } else return null; }; CTable.prototype.Internal_Get_PrevCell = function(Pos) { var Cell_Index = Pos.Cell; var Row_Index = Pos.Row; if (Cell_Index > 0) { Pos.Cell = Cell_Index - 1; return this.Content[Pos.Row].Get_Cell(Pos.Cell); } else if (Row_Index > 0) { Pos.Row = Row_Index - 1; Pos.Cell = this.Content[Row_Index - 1].Get_CellsCount() - 1; return this.Content[Pos.Row].Get_Cell(Pos.Cell); } else return null; }; CTable.prototype.Internal_Copy_Grid = function(Grid) { if (undefined !== Grid && null !== Grid) { var Count = Grid.length; var NewGrid = new Array(Count); var Index = 0; for (; Index < Count; Index++) NewGrid[Index] = Grid[Index]; return NewGrid; } return []; }; CTable.prototype.private_UpdateTableRulerOnBorderMove = function(Pos) { if (null != this.Selection.Data2.Min) Pos = Math.max(Pos, this.Selection.Data2.Min); if (null != this.Selection.Data2.Max) Pos = Math.min(Pos, this.Selection.Data2.Max); // Обновляем Markup по ячейке в которой мы двигаем границу. Так делаем, потому что мы можем находится изначально // на другой странице данной таблице, а там Markup может быть совершенно другим. В конце движения границы // произойдет обновление селекта, и Markup обновится по текущему положению курсора. this.private_UpdateTableMarkup(this.Selection.Data2.Pos.Row, this.Selection.Data2.Pos.Cell, this.Selection.Data2.PageNum); this.DrawingDocument.UpdateTableRuler(this.Selection.Data2.bCol, this.Selection.Data2.Index, Pos); return Pos; }; /** * Получаем массив позиций ячеек, попавших в выделение * @param {boolean} isAddMergedCells - добавляем ли в массив смерженные вертикально ячейки * @returns {{Cell : number, Row : number}[]} */ CTable.prototype.GetSelectionArray = function(isAddMergedCells) { var arrSelectionArray = []; if (true === this.ApplyToAll) { arrSelectionArray = []; for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); if (vmerge_Continue !== oCell.GetVMerge() || isAddMergedCells) { arrSelectionArray.push({ Cell : nCurCell, Row : nCurRow }); } } } } else if (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type) { arrSelectionArray = this.Selection.Data; if (isAddMergedCells) { for (var nIndex = 0, nCount = this.Selection.Data.length; nIndex < nCount; ++nIndex) { var nCurRow = this.Selection.Data[nIndex].Row; var nCurCell = this.Selection.Data[nIndex].Cell; var oRow = this.GetRow(nCurRow); var oCell = oRow.GetCell(nCurCell); var arrMergedCells = this.private_GetMergedCells(nCurRow, oRow.GetCellInfo(nCurCell).StartGridCol, oCell.GetGridSpan()); for (var nMergeIndex = 0, nMergedCount = arrMergedCells.length; nMergeIndex < nMergedCount; ++nMergeIndex) { var nMCell = arrMergedCells[nMergeIndex].GetIndex(); var nMRow = arrMergedCells[nMergeIndex].GetRow().GetIndex(); var isAdded = false; for (var nTempIndex = 0, nTempCount = arrSelectionArray.length; nTempIndex < nTempCount; ++nTempIndex) { if (nMRow === arrSelectionArray[nTempIndex].Row && nMCell === arrSelectionArray[nTempIndex].Cell) { isAdded = true; break; } else if (nMRow < arrSelectionArray[nTempIndex].Row || (nMRow === arrSelectionArray[nTempIndex].Row && nMCell < arrSelectionArray[nTempIndex].Cell)) { isAdded = true; arrSelectionArray.splice(nTempIndex, 0, { Cell : nMCell, Row : nMRow }); break; } } if (!isAdded) { arrSelectionArray.push({ Cell : nMCell, Row : nMRow }); } } } } } else if (this.CurCell) { arrSelectionArray = [{ Cell : this.CurCell.Index, Row : this.CurCell.Row.Index }]; } return arrSelectionArray; }; /** * Считаем количество соединенных вертикально ячеек на заданной странице */ CTable.prototype.private_GetVertMergeCountOnPage = function(CurPage, CurRow, StartGridCol, GridSpan) { var VMergeCount = this.Internal_GetVertMergeCount(CurRow, StartGridCol, GridSpan); if (true !== this.IsEmptyPage(CurPage) && CurRow + VMergeCount - 1 >= this.Pages[CurPage].LastRow) { VMergeCount = this.Pages[CurPage].LastRow + 1 - CurRow; if (false === this.RowsInfo[CurRow + VMergeCount - 1].FirstPage && CurPage === this.RowsInfo[CurRow + VMergeCount - 1].StartPage) VMergeCount--; } return VMergeCount; }; /** * Получаем отрезок выделенных строк * @returns {{Start: number, End: number}} */ CTable.prototype.GetSelectedRowsRange = function() { var arrSelectedCells = this.GetSelectionArray(); var nStartRow = -1, nEndRow = -2; for (var nIndex = 0, nCount = arrSelectedCells.length; nIndex < nCount; ++nIndex) { var nRowIndex = arrSelectedCells[nIndex].Row; if (-1 === nStartRow || nStartRow > nRowIndex) nStartRow = nRowIndex; if (-1 === nEndRow || nEndRow < nRowIndex) nEndRow = nRowIndex; } return { Start : nStartRow, End : nEndRow }; }; /** * Получаем количество строк в заголовке таблицы * @returns {number} */ CTable.prototype.GetRowsCountInHeader = function() { var nRowsInHeader = 0; for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { if (true === this.Content[nCurRow].IsHeader()) nRowsInHeader++; else break; } return nRowsInHeader; }; CTable.prototype.Get_RowsCount = function() { return this.Content.length; }; CTable.prototype.Get_Row = function(Index) { return this.Content[Index]; }; CTable.prototype.GetRowsCount = function() { return this.Content.length; }; CTable.prototype.GetColsCount = function() { return this.TableGrid.length; }; /** * Получаем строку с заданным номером * @param {number} nIndex * @returns {CTableRow} */ CTable.prototype.GetRow = function(nIndex) { return this.Get_Row(nIndex); }; CTable.prototype.CompareDrawingsLogicPositions = function(CompareObject) { for (var CurRow = 0, RowsCount = this.Get_RowsCount(); CurRow < RowsCount; CurRow++) { var Row = this.Get_Row(CurRow); for (var CurCell = 0, CellsCount = Row.Get_CellsCount(); CurCell < CellsCount; CurCell++) { var Cell = Row.Get_Cell(CurCell); Cell.Content.CompareDrawingsLogicPositions(CompareObject); if (0 !== CompareObject.Result) return; } } }; CTable.prototype.StartSelectionFromCurPos = function() { this.Selection.Use = true; this.Selection.StartPos.Pos = {Cell : this.CurCell.Index, Row : this.CurCell.Row.Index}; this.Selection.EndPos.Pos = {Cell : this.CurCell.Index, Row : this.CurCell.Row.Index}; this.private_UpdateSelectedCellsArray(); var oLogicDocument = this.LogicDocument; if (oLogicDocument) { var oRealPos = oLogicDocument.GetCursorRealPosition(); this.Selection.StartPos.X = oRealPos.X; this.Selection.StartPos.Y = oRealPos.Y; } // В функции private_UpdateSelectedCellsArray выставляется тип по ячеейкам, но нам нужен внутри ячейки изначальный селект this.Selection.Type = table_Selection_Text; this.Selection.CurRow = this.CurCell.Row.Index; this.CurCell.Content.StartSelectionFromCurPos(); }; CTable.prototype.SelectRange = function(startCell, startRow, endCell, endRow) { let rowsCount = this.GetRowsCount(); if (rowsCount <= 0) return; startRow = Math.max(0, Math.min(startRow, rowsCount - 1)); endRow = Math.max(0, Math.min(endRow, rowsCount - 1)); startCell = Math.max(0, Math.min(startCell, this.GetRow(startRow).GetCellsCount() - 1)); endCell = Math.max(0, Math.min(endCell, this.GetRow(endRow).GetCellsCount() - 1)); this.Selection.Use = true; this.Selection.Start = false; this.Selection.StartPos.Pos = { Cell : startCell, Row : startRow }; this.Selection.EndPos.Pos = { Cell : endCell, Row : endRow }; this.Selection.Type = table_Selection_Cell; this.Selection.CurRow = endRow; this.CurCell = this.GetRow(endRow).GetCell(endCell); this.private_UpdateSelectedCellsArray(); }; CTable.prototype.GetStyleFromFormatting = function() { var SelectionArray = this.GetSelectionArray(); if (SelectionArray.length > 0) { var Pos = SelectionArray[0]; var Cell = this.Content[Pos.Row].Get_Cell(Pos.Cell); return Cell.Content.GetStyleFromFormatting(); } return null; }; CTable.prototype.SetReviewType = function(ReviewType) { }; CTable.prototype.GetReviewType = function() { return reviewtype_Common; }; CTable.prototype.IsSelectedAll = function() { if (!this.IsCellSelection()) return false; var nArrayPos = 0; var arrSelectionArray = this.Selection.Data; for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell, ++nArrayPos) { if (nArrayPos >= arrSelectionArray.length) return false; var oPos = arrSelectionArray[nArrayPos]; if (oPos.Row !== nCurRow || oPos.Cell !== nCurCell) return false; } } return true; }; CTable.prototype.AcceptRevisionChanges = function(nType, bAll) { var arrSelectionArray = this.GetSelectionArray(); var nFirstRow = arrSelectionArray.length > 0 ? arrSelectionArray[0].Row : 0; var isCellSelection = this.IsCellSelection(); var isAllSelected = this.IsSelectedAll(); if (bAll) { nFirstRow = 0; arrSelectionArray = []; for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { arrSelectionArray.push({Row : nCurRow, Cell : nCurCell}); } } isAllSelected = true; } if (isCellSelection) this.RemoveSelection(); if ((bAll || (isCellSelection && !this.ApplyToAll)) && (undefined === nType || c_oAscRevisionsChangeType.TablePr === nType || c_oAscRevisionsChangeType.RowsAdd === nType || c_oAscRevisionsChangeType.RowsRem === nType || c_oAscRevisionsChangeType.TableRowPr === nType )) { if (isAllSelected && (undefined === nType || c_oAscRevisionsChangeType.TablePr === nType) && this.HavePrChange()) { this.AcceptPrChange(); } var arrSelectedRows = []; for (var nIndex = arrSelectionArray.length - 1; nIndex >= 0; --nIndex) { var nCurRow = arrSelectionArray[nIndex].Row; if (arrSelectedRows.length <= 0 || arrSelectedRows[arrSelectedRows.length - 1] > nCurRow) arrSelectedRows.push(nCurRow); } for (var nSelectedRowIndex = 0, nSelectedRowsCount = arrSelectedRows.length; nSelectedRowIndex < nSelectedRowsCount; ++nSelectedRowIndex) { var nCurRow = arrSelectedRows[nSelectedRowIndex]; var oRow = this.GetRow(nCurRow); if (undefined === nType || c_oAscRevisionsChangeType.TableRowPr === nType) { for (let iCell = 0, nCells = oRow.GetCellsCount(); iCell < nCells; ++iCell) { oRow.GetCell(iCell).AcceptPrChange(); } oRow.AcceptPrChange(); } var nRowReviewType = oRow.GetReviewType(); if (reviewtype_Add === nRowReviewType && (undefined === nType || c_oAscRevisionsChangeType.RowsAdd === nType)) { oRow.SetReviewType(reviewtype_Common); } else if (reviewtype_Remove === nRowReviewType && (undefined === nType || c_oAscRevisionsChangeType.RowsRem === nType)) { oRow.SetReviewType(reviewtype_Common); this.private_RemoveRow(nCurRow); for (var nIndex = arrSelectionArray.length - 1; nIndex >= 0; --nIndex) { if (arrSelectionArray[nIndex].Row === nCurRow) { arrSelectionArray.splice(nIndex, 1); } else if (arrSelectionArray[nIndex].Row > nCurRow) { arrSelectionArray[nIndex].Row--; } } } } } if (this.GetRowsCount() <= 0) return; if (arrSelectionArray.length <= 0) { var nCurRow = nFirstRow < this.GetRowsCount() ? nFirstRow : this.GetRowsCount() - 1; this.CurCell = this.GetRow(nCurRow).GetCell(0); this.Document_SetThisElementCurrent(false); } else { if (isCellSelection && !bAll) this.SelectRows(arrSelectionArray[0].Row, arrSelectionArray[arrSelectionArray.length - 1].Row); else this.CurCell = this.GetRow(arrSelectionArray[0].Row).GetCell(arrSelectionArray[0].Cell); } if (!bAll && this.IsCellSelection() && (c_oAscRevisionsChangeType.TablePr === nType || c_oAscRevisionsChangeType.RowsAdd === nType || c_oAscRevisionsChangeType.RowsRem === nType)) return; for (var nIndex = 0, nCount = arrSelectionArray.length; nIndex < nCount; ++nIndex) { var oRow = this.GetRow(arrSelectionArray[nIndex].Row); var oCell = oRow.GetCell(arrSelectionArray[nIndex].Cell); var oCellContent = oCell.GetContent(); if (isCellSelection) oCellContent.SelectAll(); oCell.GetContent().AcceptRevisionChanges(nType, bAll); if (isCellSelection) oCellContent.RemoveSelection(); } }; CTable.prototype.RejectRevisionChanges = function(nType, bAll) { var arrSelectionArray = this.GetSelectionArray(); var nFirstRow = arrSelectionArray.length > 0 ? arrSelectionArray[0].Row : 0; var isCellSelection = this.IsCellSelection(); var isAllSelected = this.IsSelectedAll(); if (bAll) { nFirstRow = 0; arrSelectionArray = []; for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { arrSelectionArray.push({Row : nCurRow, Cell : nCurCell}); } } isAllSelected = true; isCellSelection = true; } if ((bAll || (this.IsCellSelection() && !this.ApplyToAll)) && (undefined === nType || c_oAscRevisionsChangeType.TablePr === nType || c_oAscRevisionsChangeType.RowsAdd === nType || c_oAscRevisionsChangeType.RowsRem === nType || c_oAscRevisionsChangeType.TableRowPr === nType)) { if (isAllSelected && (undefined === nType || c_oAscRevisionsChangeType.TablePr === nType) && this.HavePrChange()) { this.RejectPrChange(); } var arrSelectedRows = []; for (var nIndex = arrSelectionArray.length - 1; nIndex >= 0; --nIndex) { var nCurRow = arrSelectionArray[nIndex].Row; if (arrSelectedRows.length <= 0 || arrSelectedRows[arrSelectedRows.length - 1] > nCurRow) arrSelectedRows.push(nCurRow); } for (var nSelectedRowIndex = 0, nSelectedRowsCount = arrSelectedRows.length; nSelectedRowIndex < nSelectedRowsCount; ++nSelectedRowIndex) { var nCurRow = arrSelectedRows[nSelectedRowIndex]; var oRow = this.GetRow(nCurRow); if (undefined === nType || c_oAscRevisionsChangeType.TableRowPr === nType) { for (let iCell = 0, nCells = oRow.GetCellsCount(); iCell < nCells; ++iCell) { oRow.GetCell(iCell).RejectPrChange(); } oRow.RejectPrChange(); } var nRowReviewType = oRow.GetReviewType(); if (reviewtype_Add === nRowReviewType && (undefined === nType || c_oAscRevisionsChangeType.RowsAdd === nType)) { oRow.SetReviewType(reviewtype_Common); this.private_RemoveRow(nCurRow); for (var nIndex = arrSelectionArray.length - 1; nIndex >= 0; --nIndex) { if (arrSelectionArray[nIndex].Row === nCurRow) { arrSelectionArray.splice(nIndex, 1); } else if (arrSelectionArray[nIndex].Row > nCurRow) { arrSelectionArray[nIndex].Row--; } } } else if (reviewtype_Remove === nRowReviewType && (undefined === nType || c_oAscRevisionsChangeType.RowsRem === nType)) { oRow.SetReviewType(reviewtype_Common); } } } if (this.GetRowsCount() <= 0) return; if (isCellSelection) this.RemoveSelection(); if (arrSelectionArray.length <= 0) { var nCurRow = nFirstRow < this.GetRowsCount() ? nFirstRow : this.GetRowsCount() - 1; this.CurCell = this.GetRow(nCurRow).GetCell(0); this.Document_SetThisElementCurrent(false); } else { if (isCellSelection && !bAll) this.SelectRows(arrSelectionArray[0].Row, arrSelectionArray[arrSelectionArray.length - 1].Row); else this.CurCell = this.GetRow(arrSelectionArray[0].Row).GetCell(arrSelectionArray[0].Cell); } if (!bAll && this.IsCellSelection() && (c_oAscRevisionsChangeType.TablePr === nType || c_oAscRevisionsChangeType.RowsAdd === nType || c_oAscRevisionsChangeType.RowsRem === nType)) return; for (var nIndex = 0, nCount = arrSelectionArray.length; nIndex < nCount; ++nIndex) { var oRow = this.GetRow(arrSelectionArray[nIndex].Row); var oCell = oRow.GetCell(arrSelectionArray[nIndex].Cell); var oCellContent = oCell.GetContent(); if (isCellSelection) oCellContent.SelectAll(); oCell.GetContent().RejectRevisionChanges(nType, bAll); if (isCellSelection) oCellContent.RemoveSelection(); } }; CTable.prototype.GetRevisionsChangeElement = function(oSearchEngine) { if (true === oSearchEngine.IsFound()) return; if (!oSearchEngine.IsCurrentFound()) { if (this === oSearchEngine.GetCurrentElement()) { oSearchEngine.SetCurrentFound(); if (oSearchEngine.GetDirection() < 0) return; } } else if (oSearchEngine.GetDirection() > 0) { oSearchEngine.SetFoundedElement(this); if (true === oSearchEngine.IsFound()) return; } var nCurCell = 0, nCurRow = 0; if (!oSearchEngine.IsCurrentFound()) { var arrSelectedCells = this.GetSelectionArray(); if (arrSelectedCells.length <= 0) return; nCurRow = arrSelectedCells[0].Row; nCurCell = arrSelectedCells[0].Cell; } else { if (oSearchEngine.GetDirection() > 0) { nCurRow = 0; nCurCell = 0; } else { nCurRow = this.GetRowsCount() - 1; nCurCell = this.GetRow(nCurRow).GetCellsCount() - 1; } } var oCell = this.GetRow(nCurRow).GetCell(nCurCell); while (oCell && vmerge_Restart !== oCell.GetVMerge()) { if (oSearchEngine.GetDirection() > 0) oCell = this.private_GetNextCell(oCell.GetRow().GetIndex(), oCell.GetIndex()); else oCell = this.private_GetPrevCell(oCell.GetRow().GetIndex(), oCell.GetIndex()); } oCell.GetContent().GetRevisionsChangeElement(oSearchEngine); while (!oSearchEngine.IsFound()) { if (oSearchEngine.GetDirection() > 0) { oCell = this.private_GetNextCell(oCell.GetRow().GetIndex(), oCell.GetIndex()); while (oCell && vmerge_Restart !== oCell.GetVMerge()) { oCell = this.private_GetNextCell(oCell.GetRow().GetIndex(), oCell.GetIndex()); } } else { oCell = this.private_GetPrevCell(oCell.GetRow().GetIndex(), oCell.GetIndex()); while (oCell && vmerge_Restart !== oCell.GetVMerge()) { oCell = this.private_GetPrevCell(oCell.GetRow().GetIndex(), oCell.GetIndex()); } } if (!oCell) break; oCell.GetContent().GetRevisionsChangeElement(oSearchEngine); } if (!oSearchEngine.IsFound() && oSearchEngine.GetDirection() < 0) { oSearchEngine.SetFoundedElement(this); } }; CTable.prototype.private_GetNextCell = function(RowIndex, CellIndex) { return this.Internal_Get_NextCell({Cell : CellIndex, Row : RowIndex}); }; CTable.prototype.private_GetPrevCell = function(RowIndex, CellIndex) { return this.Internal_Get_PrevCell({Cell : CellIndex, Row : RowIndex}); }; CTable.prototype.IsChangedTableGrid = function() { let oldGrid = this.Internal_Copy_Grid(this.TableGridCalc); // Используем предыдущие границы, т.к. нового расчета еще могло не быть, и в какой мы колонке или // странице определить невозможно, значит, корректно расчитать PageFields тоже нельзя this.private_RecalculateGrid(this.CalculatedPageFields); let newGrid = this.TableGridCalc; if (newGrid.length !== oldGrid.length) return false; for (let colIndex = 0, colCount = newGrid.length; colIndex < colCount; ++colIndex) { if (Math.abs(oldGrid[colIndex] - newGrid[colIndex]) > 0.001) { this.RecalcInfo.TableBorders = true; return true; } } return false; }; CTable.prototype.GetContentPosition = function(bSelection, bStart, PosArray) { if (!PosArray) PosArray = []; var CurRow = (true === bSelection ? (true === bStart ? this.Selection.StartPos.Pos.Row : this.Selection.EndPos.Pos.Row) : this.CurCell.Row.Index); var CurCell = (true === bSelection ? (true === bStart ? this.Selection.StartPos.Pos.Cell : this.Selection.EndPos.Pos.Cell) : this.CurCell.Index); var Row = this.Get_Row(CurRow); PosArray.push({Class : this, Position : CurRow, Type : this.Selection.Type, Type2 : this.Selection.Type2}); PosArray.push({Class : this.Get_Row(CurRow), Position : CurCell}); if (Row && CurCell >= 0 && CurCell < Row.Get_CellsCount()) { var Cell = Row.Get_Cell(CurCell); Cell.Content.GetContentPosition(bSelection, bStart, PosArray); } return PosArray; }; CTable.prototype.SetContentSelection = function(StartDocPos, EndDocPos, Depth, StartFlag, EndFlag) { if ((0 === StartFlag && (!StartDocPos[Depth] || this !== StartDocPos[Depth].Class)) || (0 === EndFlag && (!EndDocPos[Depth] || this !== EndDocPos[Depth].Class))) return; var isOneElement = true; var StartRow = 0; switch (StartFlag) { case 0 : StartRow = StartDocPos[Depth].Position; break; case 1 : StartRow = 0; isOneElement = false; break; case -1: StartRow = this.Content.length - 1; isOneElement = false; break; } var EndRow = 0; switch (EndFlag) { case 0 : EndRow = EndDocPos[Depth].Position; break; case 1 : EndRow = 0; isOneElement = false; break; case -1: EndRow = this.Content.length - 1; isOneElement = false; break; } var _StartDocPos = StartDocPos, _StartFlag = StartFlag; if (null !== StartDocPos && true === StartDocPos[Depth].Deleted) { if (StartRow < this.Content.length) { _StartDocPos = null; _StartFlag = 1; } else if (StartRow > 0) { StartRow--; _StartDocPos = null; _StartFlag = -1; } else { // Такого не должно быть return; } } var _EndDocPos = EndDocPos, _EndFlag = EndFlag; if (null !== EndDocPos && true === EndDocPos[Depth].Deleted) { if (EndRow < this.Content.length) { _EndDocPos = null; _EndFlag = 1; } else if (EndRow > 0) { EndRow--; _EndDocPos = null; _EndFlag = -1; } else { // Такого не должно быть return; } } var StartCell = 0; switch (_StartFlag) { case 0 : StartCell = _StartDocPos[Depth + 1].Position; break; case 1 : StartCell = 0; break; case -1: StartCell = this.Content[StartRow].Get_CellsCount() - 1; break; } var EndCell = 0; switch (_EndFlag) { case 0 : EndCell = _EndDocPos[Depth + 1].Position; break; case 1 : EndCell = 0; break; case -1: EndCell = this.Content[EndRow].Get_CellsCount() - 1; break; } var __StartDocPos = _StartDocPos, __StartFlag = _StartFlag; if (null !== _StartDocPos && true === _StartDocPos[Depth + 1].Deleted) { if (StartCell < this.Content[StartRow].Get_CellsCount()) { __StartDocPos = null; __StartFlag = 1; } else if (StartCell > 0) { StartCell--; __StartDocPos = null; __StartFlag = -1; } else { // Такого не должно быть return; } } var __EndDocPos = _EndDocPos, __EndFlag = _EndFlag; if (null !== _EndDocPos && true === _EndDocPos[Depth + 1].Deleted) { if (EndCell < this.Content[EndCell].Get_CellsCount()) { __EndDocPos = null; __EndFlag = 1; } else if (EndCell > 0) { EndCell--; __EndDocPos = null; __EndFlag = -1; } else { // Такого не должно быть return; } } this.Selection.Use = true; this.Selection.StartPos.Pos = {Row : StartRow, Cell : StartCell}; this.Selection.EndPos.Pos = {Row : EndRow, Cell : EndCell}; this.Selection.CurRow = EndRow; this.Selection.Type2 = table_Selection_Common; this.Selection.Data2 = null; this.private_SetSelectionData(null); if (StartRow === EndRow && StartCell === EndCell && null !== __StartDocPos && null !== __EndDocPos) { this.CurCell = this.Get_Row(StartRow).Get_Cell(StartCell); this.Selection.Type = table_Selection_Text; this.CurCell.Content.SetContentSelection(__StartDocPos, __EndDocPos, Depth + 2, __StartFlag, __EndFlag); } else { this.Selection.Type = table_Selection_Cell; this.private_UpdateSelectedCellsArray(isOneElement ? false : true); } if (null !== EndDocPos && undefined !== EndDocPos[Depth].Type && undefined !== EndDocPos[Depth].Type2) { this.Selection.Type = EndDocPos[Depth].Type; this.Selection.Type2 = EndDocPos[Depth].Type2; if (table_Selection_Cell === this.Selection.Type) this.private_UpdateSelectedCellsArray(!isOneElement || table_Selection_Rows === this.Selection.Type2 ? true : false); } }; CTable.prototype.SetContentPosition = function(DocPos, Depth, Flag) { if (this.GetRowsCount() <= 0) return; if (0 === Flag && (!DocPos[Depth] || this !== DocPos[Depth].Class)) return; var CurRow = 0; switch (Flag) { case 0 : CurRow = DocPos[Depth].Position; break; case 1 : CurRow = 0; break; case -1: CurRow = this.Content.length - 1; break; } var _DocPos = DocPos, _Flag = Flag; if (null !== DocPos && true === DocPos[Depth].Deleted) { if (CurRow < this.Content.length) { _DocPos = null; _Flag = 1; } else if (CurRow > 0) { CurRow--; _DocPos = null; _Flag = -1; } else { // Такого не должно быть return; } } if (CurRow >= this.GetRowsCount()) { CurRow = this.GetRowsCount() - 1; _DocPos = null; _Flag = -1; } else if (CurRow < 0) { CurRow = 0; _DocPos = null; _Flag = 1; } var Row = this.GetRow(CurRow); if (!Row) return; var CurCell = 0; switch (_Flag) { case 0 : CurCell = _DocPos[Depth + 1].Position; break; case 1 : CurCell = 0; break; case -1: CurCell = Row.GetCellsCount() - 1; break; } var __DocPos = _DocPos, __Flag = _Flag; if (null !== _DocPos && true === _DocPos[Depth + 1].Deleted) { if (CurCell < Row.GetCellsCount()) { __DocPos = null; __Flag = 1; } else if (CurCell > 0) { CurCell--; __DocPos = null; __Flag = -1; } else { // Такого не должно быть return; } } if (CurCell >= Row.GetCellsCount()) { CurCell = Row.GetCellsCount() - 1; __DocPos = null; __Flag = -1; } else if (CurCell < 0) { CurCell = 0; __DocPos = null; __Flag = 1; } var Cell = Row.GetCell(CurCell); if (!Cell) return; this.CurCell = Cell; this.CurCell.Content.SetContentPosition(__DocPos, Depth + 2, __Flag); }; CTable.prototype.Set_CurCell = function(Cell) { if (!Cell || this !== Cell.Get_Table()) return; this.CurCell = Cell; }; CTable.prototype.IsEmptyPage = function(CurPage) { if (!this.Pages[CurPage] || (this.Pages[CurPage].LastRow < this.Pages[CurPage].FirstRow) || (0 === CurPage && (!this.RowsInfo[0] || true !== this.RowsInfo[0].FirstPage))) return true; return false; }; CTable.prototype.Check_EmptyPages = function(CurPage) { for (var _CurPage = CurPage; _CurPage >= 0; --_CurPage) { if (true !== this.IsEmptyPage(_CurPage)) return false; } return true; }; CTable.prototype.private_StartTrackTable = function(CurPage) { if (CurPage < 0 || CurPage >= this.Pages.length) return; var Bounds = this.Get_PageBounds(CurPage); var NewOutline = new AscCommon.CTableOutline(this, this.GetAbsolutePage(CurPage), Bounds.Left, Bounds.Top, Bounds.Right - Bounds.Left, Bounds.Bottom - Bounds.Top); var Transform = this.Get_ParentTextTransform(); this.DrawingDocument.StartTrackTable(NewOutline, Transform); }; CTable.prototype.CorrectBadTable = function() { // TODO: Пока оставим эту заглушку на случай загрузки плохих таблиц. В будущем надо будет // сделать нормальный обсчет для случая, когда у нас есть "пустые" строки (составленные // из вертикально объединенных ячеек). this.CorrectVMerge(); this.CorrectTableRows(false); this.CorrectEmptyTable(); this.CorrectBadGrid(); this.CorrectHMerge(); }; CTable.prototype.CorrectEmptyTable = function() { if (this.GetRowsCount() > 0) return; this.private_AddRow(0, 1); }; /** * Специальная функция, которая обрабатывает устаревший параметр HMerge и заменяет его на GridSpan во время открытия файла */ CTable.prototype.CorrectHMerge = function() { // HACK: При загрузке мы запрещаем компилировать стили, но нам все-таки это здесь нужно var bLoad = AscCommon.g_oIdCounter.m_bLoad; var bRead = AscCommon.g_oIdCounter.m_bRead; AscCommon.g_oIdCounter.m_bLoad = false; AscCommon.g_oIdCounter.m_bRead = false; var nColsCount = this.TableGrid.length; for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); var nCurGridCol = oRow.GetBefore().Grid; for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); var nGridSpan = oCell.GetGridSpan(); var nWType = oCell.GetW().Type; var nWValue = oCell.GetW().W; if (nCurCell < nCellsCount - 1) { var nNextCurCell = nCurCell + 1; while (nNextCurCell < nCellsCount) { var oNextCell = oRow.GetCell(nNextCurCell); if (vmerge_Continue === oNextCell.GetHMerge()) { nGridSpan += oNextCell.GetGridSpan(); oRow.RemoveCell(nNextCurCell); nCellsCount--; nNextCurCell--; if (nWType === oNextCell.GetW().Type) nWValue += oNextCell.GetW().Value; } else { break; } nNextCurCell++; } } if (nGridSpan !== oCell.GetGridSpan()) { if (nGridSpan + nCurGridCol > nColsCount) nGridSpan = Math.max(1, nColsCount - nCurGridCol); oCell.SetGridSpan(nGridSpan); oCell.SetW(new CTableMeasurement(nWType, nWValue)); } nCurGridCol += nGridSpan; } } // HACK: Восстанавливаем флаги и выставляем, что стиль всей таблицы нужно пересчитать AscCommon.g_oIdCounter.m_bLoad = bLoad; AscCommon.g_oIdCounter.m_bRead = bRead; this.Recalc_CompiledPr2(); }; /** * Специальная функция, проверяющая корректность вертикального объединения всех ячеек в таблице */ CTable.prototype.CorrectVMerge = function() { if (this.GetRowsCount() <= 0) return; // HACK: При загрузке мы запрещаем компилировать стили, но нам все-таки это здесь нужно var bLoad = AscCommon.g_oIdCounter.m_bLoad; var bRead = AscCommon.g_oIdCounter.m_bRead; AscCommon.g_oIdCounter.m_bLoad = false; AscCommon.g_oIdCounter.m_bRead = false; for (let curRow = 0, rowsCount = this.GetRowsCount(); curRow < rowsCount; ++curRow) { let row = this.GetRow(curRow); let gridCol = row.GetBefore().Grid; for (let curCell = 0, cellsCount = row.GetCellsCount(); curCell < cellsCount; ++curCell) { let cell = row.GetCell(curCell); let gridSpan = cell.GetGridSpan(); if (vmerge_Continue !== cell.GetVMerge()) { gridCol += gridSpan; continue; } if (0 === curRow || this.Internal_GetVertMergeCountUp(curRow, gridCol, gridSpan) <= 1) cell.SetVMerge(vmerge_Restart); gridCol += gridSpan; } } // HACK: Восстанавливаем флаги и выставляем, что стиль всей таблицы нужно пересчитать AscCommon.g_oIdCounter.m_bLoad = bLoad; AscCommon.g_oIdCounter.m_bRead = bRead; this.Recalc_CompiledPr2(); }; CTable.prototype.GetNumberingInfo = function(oNumberingEngine) { if (oNumberingEngine.IsStop()) return; for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); if (oCell.IsMergedCell()) continue; oCell.GetContent().GetNumberingInfo(oNumberingEngine); if (oNumberingEngine.IsStop()) return; } } }; CTable.prototype.IsTableFirstRowOnNewPage = function(CurRow) { for (var CurPage = 0, PagesCount = this.Pages.length; CurPage < PagesCount; ++CurPage) { if (CurRow === this.Pages[CurPage].FirstRow && CurRow <= this.Pages[CurPage].LastRow) { if (0 === CurPage && ((null != this.Get_DocumentPrev() && !this.Parent.IsElementStartOnNewPage(this.GetIndex())) || (true === this.Parent.IsTableCellContent() && true !== this.Parent.IsTableFirstRowOnNewPage()) || (true === this.Parent.IsBlockLevelSdtContent() && true !== this.Parent.IsBlockLevelSdtFirstOnNewPage()))) return false; return true; } } return false; }; CTable.prototype.private_UpdateCellsGrid = function() { for (var nCurRow = 0, nRowsCount = this.Content.length; nCurRow < nRowsCount; ++nCurRow) { var Row = this.Content[nCurRow]; var BeforeInfo = Row.Get_Before(); var CurGridCol = BeforeInfo.GridBefore; for (var nCurCell = 0, nCellsCount = Row.Get_CellsCount(); nCurCell < nCellsCount; ++nCurCell) { var Cell = Row.Get_Cell(nCurCell); var GridSpan = Cell.Get_GridSpan(); Cell.Set_Metrics(CurGridCol, 0, 0, 0, 0, 0, 0); Row.Update_CellInfo(nCurCell); CurGridCol += GridSpan; } } // Мы обнулили метрики, нужно будет их заново пересчитать this.RecalcInfo.RecalcBorders(); }; CTable.prototype.SetTableGrid = function(arrGrid) { var isChanged = false; if (arrGrid.length != this.TableGrid.length) { isChanged = true; } else { for (var nIndex = 0, nCount = arrGrid.length; nIndex < nCount; ++nIndex) { if (Math.abs(arrGrid[nIndex] - this.TableGrid[nIndex]) > 0.001) { isChanged = true; break; } } } if (!isChanged) return; var oLogicDocument = this.LogicDocument; if (oLogicDocument && oLogicDocument.IsTrackRevisions() && !this.TableGridChange) { this.SetTableGridChange(this.private_CopyTableGrid()); this.private_AddPrChange(); } AscCommon.History.Add(new CChangesTableTableGrid(this, this.TableGrid, arrGrid)); this.TableGrid = arrGrid; this.private_UpdateTableGrid(); }; /** * Выставляем поле для рецензирования, запоминающее исходное состояние сетки таблицы * @param {Array | undefined} arrTableGridChange */ CTable.prototype.SetTableGridChange = function(arrTableGridChange) { AscCommon.History.Add(new CChangesTableTableGridChange(this, this.TableGridChange, arrTableGridChange)); this.TableGridChange = arrTableGridChange; this.updateTrackRevisions(); }; /** * Получаем ширину заданного промежутка в сетке таблицы * @param nStartCol * @param nGridSpan * @returns {number} */ CTable.prototype.GetSpanWidth = function(nStartCol, nGridSpan) { if (nStartCol < 0 || nStartCol + nGridSpan < 0 || nGridSpan <= 0 || nStartCol + nGridSpan > this.TableGrid.length) return 0; var nSum = 0; for (var nCurCol = nStartCol; nCurCol < nStartCol + nGridSpan; ++nCurCol) { nSum += this.TableGrid[nCurCol]; } return nSum; }; CTable.prototype.private_CopyTableGrid = function() { var arrGrid = []; for (var nIndex = 0, nCount = this.TableGrid.length; nIndex < nCount; ++nIndex) { arrGrid[nIndex] = this.TableGrid[nIndex]; } return arrGrid; }; CTable.prototype.private_CopyTableGridCalc = function() { var arrGrid = []; for (var nIndex = 0, nCount = this.TableGridCalc.length; nIndex < nCount; ++nIndex) { arrGrid[nIndex] = this.TableGridCalc[nIndex]; } return arrGrid; }; CTable.prototype.CorrectBadGrid = function() { // HACK: При загрузке мы запрещаем компилировать стили, но нам все-таки это здесь нужно var bLoad = AscCommon.g_oIdCounter.m_bLoad; var bRead = AscCommon.g_oIdCounter.m_bRead; AscCommon.g_oIdCounter.m_bLoad = false; AscCommon.g_oIdCounter.m_bRead = false; // Сначала пробежимся по всем ячейкам и посмотрим, чтобы у них были корректные GridSpan (т.е. >= 1) for (var Index = 0; Index < this.Content.length; Index++) { var Row = this.Content[Index]; var CellsCount = Row.Get_CellsCount(); for (var CellIndex = 0; CellIndex < CellsCount; CellIndex++) { var Cell = Row.Get_Cell(CellIndex); var GridSpan = Cell.Get_GridSpan(); if (GridSpan <= 0) Cell.Set_GridSpan(1); } } var RowGrid = []; var GridCount = 0; for (var Index = 0; Index < this.Content.length; Index++) { var Row = this.Content[Index]; Row.SetIndex(Index); // Смотрим на ширину пропущенных колонок сетки в начале строки var BeforeInfo = Row.Get_Before(); var CurGridCol = BeforeInfo.GridBefore; var CellsCount = Row.Get_CellsCount(); for (var CellIndex = 0; CellIndex < CellsCount; CellIndex++) { var Cell = Row.Get_Cell(CellIndex); var GridSpan = Cell.Get_GridSpan(); CurGridCol += GridSpan; } // Смотрим на ширину пропущенных колонок сетки в конце строки var AfterInfo = Row.Get_After(); CurGridCol += AfterInfo.GridAfter; if (GridCount < CurGridCol) GridCount = CurGridCol; RowGrid[Index] = CurGridCol; } for (var Index = 0; Index < this.Content.length; Index++) { var Row = this.Content[Index]; var AfterInfo = Row.Get_After(); if (RowGrid[Index] < GridCount) { Row.Set_After(AfterInfo.GridAfter + GridCount - RowGrid[Index], AfterInfo.WAfter); } } var arrGrid = this.private_CopyTableGrid(); // MSWord плохо работает с файлами, где GridCol равен 0, поэтому такие правим let isZeroColumns = false; for (let nIndex = 0, nCount = arrGrid.length; nIndex < nCount; ++nIndex) { if (arrGrid[nIndex] < 0.001) { isZeroColumns = true; arrGrid[nIndex] = 20; } } if (arrGrid.length !== GridCount || isZeroColumns) { if (arrGrid.length < GridCount) { for (var nIndex = 0; nIndex < GridCount; ++nIndex) arrGrid[nIndex] = 20; } else { arrGrid.splice(GridCount, arrGrid.length - GridCount); } this.SetTableGrid(arrGrid); } // HACK: Восстанавливаем флаги и выставляем, что стиль всей таблицы нужно пересчитать AscCommon.g_oIdCounter.m_bLoad = bLoad; AscCommon.g_oIdCounter.m_bRead = bRead; this.Recalc_CompiledPr2(); }; CTable.prototype.private_CorrectVerticalMerge = function() { // Пробегаемся по всем ячейкам и смотрим на их вертикальное объединение, было ли оно нарушено for (var nCurRow = 0, nRowsCount = this.Content.length; nCurRow < nRowsCount; ++nCurRow) { var oRow = this.Content[nCurRow]; var nGridCol = oRow.Get_Before().GridBefore; for (var nCurCell = 0, nCellsCount = oRow.Get_CellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.Get_Cell(nCurCell); var nVMergeType = oCell.GetVMerge(); var nGridSpan = oCell.Get_GridSpan(); if (vmerge_Continue === nVMergeType) { var bNeedReset = true; if (0 !== nCurRow) { var oPrevRow = this.Content[nCurRow - 1]; var nPrevGridCol = oPrevRow.Get_Before().GridBefore; for (var nPrevCell = 0, nPrevCellsCount = oPrevRow.Get_CellsCount(); nPrevCell < nPrevCellsCount; ++nPrevCell) { var oPrevCell = oPrevRow.Get_Cell(nPrevCell); var nPrevGridSpan = oPrevCell.Get_GridSpan(); if (nPrevGridCol === nGridCol) { if (nPrevGridSpan === nGridSpan) bNeedReset = false; break; } else if (nPrevGridCol > nGridCol) break; nPrevGridCol += nPrevGridSpan; } } if (true === bNeedReset) oCell.SetVMerge(vmerge_Restart); } nGridCol += nGridSpan; } } }; CTable.prototype.private_SetTableLayoutFixedAndUpdateCellsWidth = function(nExceptColNum) { if (tbllayout_AutoFit === this.Get_CompiledPr(false).TablePr.TableLayout) { this.SetTableLayout(tbllayout_Fixed); // Обновляем ширины ячеек var nColsCount = this.TableGrid.length; for (var nColIndex = 0; nColIndex < nColsCount; nColIndex++) { if (nColIndex != nExceptColNum) this.Internal_UpdateCellW(nColIndex); } } }; CTable.prototype.GotoFootnoteRef = function(isNext, isCurrent, isStepFootnote, isStepEndnote) { var nRow = 0, nCell = 0; if (true === isCurrent) { if (true === this.Selection.Use) { var nStartRow = this.Selection.StartPos.Pos.Row; var nStartCell = this.Selection.StartPos.Pos.Cell; var nEndRow = this.Selection.EndPos.Pos.Row; var nEndCell = this.Selection.EndPos.Pos.Cell; if (nStartRow < nEndRow || (nStartRow === nEndRow && nStartCell <= nEndCell)) { nRow = nStartRow; nCell = nStartCell; } else { nRow = nEndRow; nCell = nEndCell; } } else { nCell = this.CurCell.Index; nRow = this.CurCell.Row.Index; } } else { if (true === isNext) { nRow = 0; nCell = 0; } else { nRow = this.Content.length - 1; nCell = this.Content[nRow].Get_CellsCount() - 1; } } if (true === isNext) { for (var nCurRow = nRow, nRowsCount = this.Content.length; nCurRow < nRowsCount; ++nCurRow) { var oRow = this.Content[nCurRow]; var nStartCell = (nCurRow === nRow ? nCell : 0); for (var nCurCell = nStartCell, nCellsCount = oRow.Get_CellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.Get_Cell(nCurCell); if (oCell.Content.GotoFootnoteRef(true, true === isCurrent && nCurRow === nRow && nCurCell === nCell, isStepFootnote, isStepEndnote)) return true; } } } else { for (var nCurRow = nRow; nCurRow >= 0; --nCurRow) { var oRow = this.Content[nCurRow]; var nStartCell = (nCurRow === nRow ? nCell : oRow.Get_CellsCount() - 1); for (var nCurCell = nStartCell; nCurCell >= 0; --nCurCell) { var oCell = oRow.Get_Cell(nCurCell); if (oCell.Content.GotoFootnoteRef(false, true === isCurrent && nCurRow === nRow && nCurCell === nCell, isStepFootnote, isStepEndnote)) return true; } } } return false; }; /** * Проверяем можно ли обновлять положение курсора на заданной странице * @param nCurPage * @returns {boolean} */ CTable.prototype.CanUpdateTarget = function(nCurPage) { if (this.Pages.length <= 0) return false; var oRow, oCell; if (this.IsSelectionUse()) { oRow = this.GetRow(this.Selection.EndPos.Pos.Row); oCell = oRow.GetCell(this.Selection.EndPos.Pos.Cell); } else { oCell = this.CurCell; oRow = this.CurCell.GetRow(); } if (!oRow || !oCell) return false; if (nCurPage >= this.Pages.length) { var nLastPage = this.Pages.length - 1; if (this.Pages[nLastPage].LastRow >= oRow.Index) return true; return false; } else { if (this.Pages[nCurPage].LastRow > oRow.Index) return true; else if (this.Pages[nCurPage].LastRow < oRow.Index) return false; return oCell.Content.CanUpdateTarget(nCurPage - oCell.Content.GetRelativeStartPage()); } }; /** * Проверяем, выделение идет по ячейкам или нет * @returns {boolean} */ CTable.prototype.IsCellSelection = function() { if (true === this.ApplyToAll || (true === this.Selection.Use && table_Selection_Cell === this.Selection.Type && this.Selection.Data.length > 0)) return true; return false; }; /** * Проверяем, идет ли выделение по целым строкам * @return {boolean} * @constructor */ CTable.prototype.IsRowSelection = function() { if (!this.IsCellSelection()) return false; var arrSelectionArray = this.GetSelectionArray(true); var oPrevPos = null; for (var nIndex = 0, nCount = arrSelectionArray.length; nIndex < nCount; ++nIndex) { var oPos = arrSelectionArray[nIndex]; if ((!oPrevPos && 0 !== oPos.Cell) || (oPrevPos && ((oPrevPos.Row === oPos.Row && oPos.Cell !== oPrevPos.Cell + 1) || (oPrevPos.Row !== oPos.Row && (0 !== oPos.Cell || this.GetRow(oPrevPos.Row).GetCellsCount() - 1 !== oPrevPos.Cell))))) return false; oPrevPos = oPos; } return !(!oPrevPos || this.GetRow(oPrevPos.Row).GetCellsCount() - 1 !== oPrevPos.Cell); }; CTable.prototype.SetTableProps = function(oProps) { return this.Set_Props(oProps); }; CTable.prototype.GetTableProps = function() { return this.Get_Props(); }; CTable.prototype.AddContentControl = function(nContentControlType) { if (this.CurCell) return this.CurCell.Content.AddContentControl(nContentControlType); return null; }; CTable.prototype.GetAllContentControls = function(arrContentControls) { for (var nCurRow = 0, nRowsCount = this.Content.length; nCurRow < nRowsCount; ++nCurRow) { var oRow = this.Content[nCurRow]; for (var nCurCell = 0, nCellsCount = oRow.Get_CellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.Get_Cell(nCurCell); oCell.Content.GetAllContentControls(arrContentControls); } } }; CTable.prototype.GetOutlineParagraphs = function(arrOutline, oPr) { if (oPr && oPr.SkipTables) return; for (var nCurRow = 0, nRowsCount = this.Content.length; nCurRow < nRowsCount; ++nCurRow) { var oRow = this.Content[nCurRow]; for (var nCurCell = 0, nCellsCount = oRow.Get_CellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.Get_Cell(nCurCell); if (oCell) oCell.Content.GetOutlineParagraphs(arrOutline, oPr); } } }; CTable.prototype.GetSimilarNumbering = function(oContinueNumbering) { if (oContinueNumbering.IsFound()) return; for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { oRow.GetCell(nCurCell).GetContent().GetSimilarNumbering(oContinueNumbering); if (oContinueNumbering.IsFound()) break; } } }; CTable.prototype.UpdateBookmarks = function(oManager) { for (var nCurRow = 0, nRowsCount = this.Content.length; nCurRow < nRowsCount; ++nCurRow) { var oRow = this.Content[nCurRow]; for (var nCurCell = 0, nCellsCount = oRow.Get_CellsCount(); nCurCell < nCellsCount; ++nCurCell) { oRow.Get_Cell(nCurCell).Content.UpdateBookmarks(oManager); } } }; /** * Вставляем содержимое заданной таблицы в текущую (специальная вставка) * @param _nRowIndex - Номер * @param _nCellIndex * @param oTable */ CTable.prototype.InsertTableContent = function(_nCellIndex, _nRowIndex, oTable) { // Нужно пересчитать сетку, чтобы если придется добавлять новые ячейки сетка была рассчитана oTable.private_RecalculateGrid(); oTable.private_RecalculateGridCols(); var oCell = this.GetStartMergedCell(_nCellIndex, _nRowIndex); if (!oCell) return; var nCellIndex = oCell.Index; var nRowIndex = oCell.Row.Index; if (nRowIndex >= this.GetRowsCount()) return; // Добавляем новые строки, если необходимо var nAddRows = oTable.GetRowsCount() + nRowIndex - this.GetRowsCount(); while (nAddRows > 0) { this.RemoveSelection(); this.CurCell = this.GetRow(this.GetRowsCount() - 1).GetCell(0); this.AddTableRow(false, undefined, false); nAddRows--; this.private_RecalculateGridCols(); } var arrClearedCells = []; function private_IsProcessedCell(oCell) { for (var nIndex = 0, nCount = arrClearedCells.length; nIndex < nCount; ++nIndex) { if (arrClearedCells[nIndex] === oCell) return true; } return false; } var isNeedRebuildGrid = false, arrRowsInfo = this.private_GetRowsInfo(); var oFirstCell = null; for (var nCurRow = 0, nRowsCount = oTable.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oInsertedRow = oTable.GetRow(nCurRow); var oCurRow = this.GetRow(nRowIndex + nCurRow); for (var nCurCell = 0, nCellsCount = oInsertedRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oCurRow.GetCell(nCellIndex + nCurCell); var oInsertedCell = oInsertedRow.GetCell(nCurCell); if (!oFirstCell) oFirstCell = oCell; if (!oCell) { var nCellPos = oCurRow.GetCellsCount(); oCell = oInsertedCell.Copy(oCurRow); oCurRow.AddCell(nCellPos, oCurRow, oCell, true); isNeedRebuildGrid = true; this.private_AddCellToRowsInfo(arrRowsInfo, oCurRow.Index, nCellPos, oInsertedCell.GetCalculatedW()); } else if (oCell) { var oTopCell = this.GetStartMergedCell(oCell.Index, oCell.Row.Index); if (oTopCell === oCell) { oCell.Content.ClearContent(false); oCell.Content.AddContent(oInsertedCell.Content.Content); arrClearedCells.push(oCell); } else { if (private_IsProcessedCell(oTopCell)) oTopCell.Content.AddContent(oInsertedCell.Content.Content); } } } } if (true === isNeedRebuildGrid) this.private_CreateNewGrid(arrRowsInfo); this.RemoveSelection(); if (oFirstCell) { this.CurCell = oFirstCell; this.SelectTable(c_oAscTableSelectionType.Cell); } else { this.MoveCursorToStartPos(false); } this.Document_SetThisElementCurrent(false); }; /** * Изменяем размер тширину и высоту таблицы * @param nWidth * @param nHeight */ CTable.prototype.Resize = function(nWidth, nHeight) { var nMinWidth = this.GetMinWidth(); var nMinHeight = this.GetMinHeight(); var nSummaryHeight = this.GetSummaryHeight(); var nCellSpacing = this.Content[0].GetCellSpacing(); if (null !== nCellSpacing) { nSummaryHeight -= nCellSpacing * (this.GetRowsCount() + 1); nMinHeight -= nCellSpacing * (this.GetRowsCount() + 1); for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { if (!this.RowsInfo[nCurRow]) continue; nSummaryHeight -= this.RowsInfo[nCurRow].MaxTopBorder[0] + this.RowsInfo[nCurRow].MaxBotBorder; nMinHeight -= this.RowsInfo[nCurRow].MaxTopBorder[0] + this.RowsInfo[nCurRow].MaxBotBorder; } var oTopBorder = this.GetTopTableBorder(); var oBottomBorder = this.GetBottomTableBorder(); nSummaryHeight -= oTopBorder.GetWidth() + oBottomBorder.GetWidth(); nMinHeight -= oTopBorder.GetWidth() + oBottomBorder.GetWidth(); } else { if(!this.bPresentation) { nSummaryHeight -= this.RowsInfo[this.RowsInfo.length - 1].MaxBotBorder; nMinHeight -= this.RowsInfo[this.RowsInfo.length - 1].MaxBotBorder; } } if (this.Pages.length <= 0) return; var oBounds = this.GetPageBounds(this.Pages.length - 1); var nDiffX = nWidth - oBounds.Right + oBounds.Left; var nDiffY = nHeight - oBounds.Bottom + oBounds.Top; var nSummaryWidth = oBounds.Right - oBounds.Left; if (nSummaryWidth + nDiffX < nMinWidth) nDiffX = nMinWidth - nSummaryWidth; if (nSummaryHeight + nDiffY < nMinHeight) nDiffY = nMinHeight - nSummaryHeight; if (nDiffY > 0.01) { var arrRowsH = []; var nTableSumH = 0; for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var nRowSummaryH = 0; for (var nCurPage in this.RowsInfo[nCurRow].H) nRowSummaryH += this.RowsInfo[nCurRow].H[nCurPage]; arrRowsH[nCurRow] = nRowSummaryH; nTableSumH += nRowSummaryH; } for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); var oRowH = oRow.GetHeight(); var nNewH = arrRowsH[nCurRow] / nTableSumH * (nSummaryHeight + nDiffY); if(!this.bPresentation) { if (null !== nCellSpacing) nNewH += nCellSpacing; else if (this.RowsInfo[nCurRow] && this.RowsInfo[nCurRow].TopDy[0]) nNewH -= this.RowsInfo[nCurRow].TopDy[0]; var nTopMargin = 0, nBotMargin = 0; for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); var oMargins = oCell.GetMargins(); if (oMargins.Top.W > nTopMargin) nTopMargin = oMargins.Top.W; if (oMargins.Bottom.W > nBotMargin) nBotMargin = oMargins.Bottom.W; } nNewH -= nTopMargin + nBotMargin; } oRow.SetHeight(nNewH, oRowH.HRule === Asc.linerule_Exact ? Asc.linerule_Exact : Asc.linerule_AtLeast); } } else if (nDiffY < -0.01) { var nNewTableH = nSummaryHeight + nDiffY; var arrRowsMinH = []; var arrRowsH = []; var nTableSumH = 0; var arrRowsFlag = []; for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var nRowSummaryH = 0; for (var nCurPage in this.RowsInfo[nCurRow].H) nRowSummaryH += this.RowsInfo[nCurRow].H[nCurPage]; arrRowsH[nCurRow] = nRowSummaryH; arrRowsMinH[nCurRow] = this.GetMinRowHeight(nCurRow); arrRowsFlag[nCurRow] = true; nTableSumH += nRowSummaryH; } var arrNewH = []; while (true) { var isForceBreak = false; var isContinue = false; for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { if (arrRowsFlag[nCurRow]) { arrNewH[nCurRow] = arrRowsH[nCurRow] / nTableSumH * nNewTableH; if (arrNewH[nCurRow] < arrRowsMinH[nCurRow]) { nTableSumH -= arrRowsH[nCurRow]; nNewTableH -= arrRowsMinH[nCurRow]; arrNewH[nCurRow] = arrRowsMinH[nCurRow]; arrRowsFlag[nCurRow] = false; if (nNewTableH < 0.01 || nTableSumH < 0.01) isForceBreak = true; isContinue = true; } } } if (isForceBreak || !isContinue) break; } for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { if (undefined !== arrNewH[nCurRow]) { var oRow = this.GetRow(nCurRow); var oRowH = oRow.GetHeight(); var nNewH = arrNewH[nCurRow]; if(!this.bPresentation) { if (null !== nCellSpacing) nNewH += nCellSpacing; else if (this.RowsInfo[nCurRow] && this.RowsInfo[nCurRow].TopDy[0]) nNewH -= this.RowsInfo[nCurRow].TopDy[0]; var nTopMargin = 0, nBotMargin = 0; for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); var oMargins = oCell.GetMargins(); if (oMargins.Top.W > nTopMargin) nTopMargin = oMargins.Top.W; if (oMargins.Bottom.W > nBotMargin) nBotMargin = oMargins.Bottom.W; } nNewH -= nTopMargin + nBotMargin; } oRow.SetHeight(nNewH, oRowH.HRule === Asc.linerule_Exact ? Asc.linerule_Exact : Asc.linerule_AtLeast); } } } this.private_RecalculateGrid(); var nFinalTableSum = null; if (nDiffX > 0.001) { var arrColsW = []; var nTableSumW = 0; for (var nCurCol = 0, nColsCount = this.TableGridCalc.length; nCurCol < nColsCount; ++nCurCol) { arrColsW[nCurCol] = this.TableGridCalc[nCurCol]; nTableSumW += arrColsW[nCurCol]; } nFinalTableSum = 0; var arrNewGrid = []; for (var nCurCol = 0, nColsCount = this.TableGridCalc.length; nCurCol < nColsCount; ++nCurCol) { arrNewGrid[nCurCol] = arrColsW[nCurCol] / nTableSumW * (nTableSumW + nDiffX); nFinalTableSum += arrNewGrid[nCurCol]; } this.SetTableGrid(arrNewGrid); } else if (nDiffX < -0.01) { var arrColsMinW = this.GetMinWidth(true); var arrColsW = []; var nTableSumW = 0; var arrColsFlag = []; for (var nCurCol = 0, nColsCount = this.TableGridCalc.length; nCurCol < nColsCount; ++nCurCol) { arrColsW[nCurCol] = this.TableGridCalc[nCurCol]; nTableSumW += arrColsW[nCurCol]; arrColsFlag[nCurCol] = true; } var nNewTableW = nTableSumW + nDiffX; var arrNewGrid = []; while (true) { var isForceBreak = false; var isContinue = false; for (var nCurCol = 0, nColsCount = this.TableGridCalc.length; nCurCol < nColsCount; ++nCurCol) { if (arrColsFlag[nCurCol]) { arrNewGrid[nCurCol] = arrColsW[nCurCol] / nTableSumW * nNewTableW; if (arrNewGrid[nCurCol] < arrColsMinW[nCurCol]) { nTableSumW -= arrColsW[nCurCol]; nNewTableW -= arrColsMinW[nCurCol]; arrNewGrid[nCurCol] = arrColsMinW[nCurCol]; arrColsFlag[nCurCol] = false; if (nNewTableW < 0.01 || nTableSumW < 0.01) isForceBreak = true; isContinue = true; } } } if (isForceBreak || !isContinue) break; } nFinalTableSum = 0; for (var nCurCol = 0, nColsCount = this.TableGridCalc.length; nCurCol < nColsCount; ++nCurCol) { nFinalTableSum += arrNewGrid[nCurCol]; } this.SetTableGrid(arrNewGrid); } var nPercentWidth = this.private_RecalculatePercentWidth(); if (null !== nFinalTableSum) { for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); var oBefore = oRow.GetBefore(); if (oBefore.W && oBefore.Grid > 0) { var nW = this.GetSpanWidth(0, oBefore.Grid); if (oBefore.W.IsMM()) oRow.SetBefore(oBefore.Grid, new CTableMeasurement(tblwidth_Mm, nW)); else if (oBefore.W.IsPercent() && nPercentWidth > 0.001) oRow.SetBefore(oBefore.Grid, new CTableMeasurement(tblwidth_Pct, nW / nPercentWidth * 100)); else oRow.SetBefore(oBefore.Grid, new CTableMeasurement(tblwidth_Auto, 0)); } var nCellSpacing = oRow.GetCellSpacing(); var nCurCol = oBefore.Grid; for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); var oCellW = oCell.GetW(); var nGridSpan = oCell.GetGridSpan(); if (oCellW) { var nW = this.GetSpanWidth(nCurCol, nGridSpan); if (null !== nCellSpacing) { if (0 === nCurCell) nW -= nCellSpacing / 2; nW -= nCellSpacing; if (nCellsCount - 1 === nCurCell) nW -= nCellSpacing / 2; } if (oCellW.IsMM()) oCell.SetW(new CTableMeasurement(tblwidth_Mm, nW)); else if (oCellW.IsPercent() && nPercentWidth > 0.001) oCell.SetW(new CTableMeasurement(tblwidth_Pct, nW / nPercentWidth * 100)); else oCell.SetW(new CTableMeasurement(tblwidth_Auto, 0)); } nCurCol += nGridSpan; } var oAfter = oRow.GetAfter(); if (oAfter.W && oAfter.Grid > 0) { var nW = this.GetSpanWidth(nCurCol, oAfter.Grid); if (oAfter.W.IsMM()) oRow.SetAfter(oAfter.Grid, new CTableMeasurement(tblwidth_Mm, nW)); else if (oAfter.W.IsPercent() && nPercentWidth > 0.001) oRow.SetAfter(oAfter.Grid, new CTableMeasurement(tblwidth_Pct, nW / nPercentWidth * 100)); else oRow.SetAfter(oAfter.Grid, new CTableMeasurement(tblwidth_Auto, 0)); } } var oTableW = this.GetTableW(); if (oTableW) { if (oTableW.IsMM()) this.SetTableW(tblwidth_Mm, nFinalTableSum); else if (oTableW.IsPercent() && nPercentWidth > 0.001) this.SetTableW(tblwidth_Pct, nFinalTableSum / nPercentWidth * 100); else this.SetTableW(tblwidth_Auto, 0); } } }; /** * Изменяем размер тширину и высоту таблицы в документе (создается точка в истории и запускается пересчет) * @param nWidth * @param nHeight */ CTable.prototype.ResizeTableInDocument = function(nWidth, nHeight) { if (!this.LogicDocument) return; if (true === this.LogicDocument.Document_Is_SelectionLocked(AscCommon.changestype_Table_Properties, null, true)) return; this.LogicDocument.StartAction(AscDFH.historydescription_Document_ResizeTable); this.Resize(nWidth, nHeight); this.LogicDocument.Recalculate(); this.StartTrackTable(); this.LogicDocument.UpdateSelection(); this.LogicDocument.FinalizeAction(); }; /** * Получаем минимальную ширину таблицы * @param {number} [isReturnByColumns=false] * @returns {number} */ CTable.prototype.GetMinWidth = function(isReturnByColumns) { var arrMinMargin = []; var nGridCount = this.TableGrid.length; for (var nCurCol = 0; nCurCol < nGridCount; ++nCurCol) { arrMinMargin[nCurCol] = 0; } for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.Content[nCurRow]; var nSpacing = oRow.GetCellSpacing(); var nCurGridCol = oRow.Get_Before().GridBefore; for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); var nGridSpan = oCell.GetGridSpan(); var oCellMargins = oCell.GetMargins(); var oCellRBorder = oCell.GetBorder(1); var oCellLBorder = oCell.GetBorder(3); var nCellMarginsLeftW = 0, nCellMarginsRightW = 0; if (null !== nSpacing) { nCellMarginsLeftW = oCellMargins.Left.W; nCellMarginsRightW = oCellMargins.Right.W; if (border_None !== oCellRBorder.Value) nCellMarginsRightW += oCellRBorder.Size; if (border_None !== oCellLBorder.Value) nCellMarginsLeftW += oCellLBorder.Size; } else { if (border_None !== oCellRBorder.Value) nCellMarginsRightW += Math.max(oCellRBorder.Size / 2, oCellMargins.Right.W); else nCellMarginsRightW += oCellMargins.Right.W; if (border_None !== oCellLBorder.Value) nCellMarginsLeftW += Math.max(oCellLBorder.Size / 2, oCellMargins.Left.W); else nCellMarginsLeftW += oCellMargins.Left.W; } if (nGridSpan <= 1) { if (arrMinMargin[nCurGridCol] < nCellMarginsLeftW + nCellMarginsRightW) arrMinMargin[nCurGridCol] = nCellMarginsLeftW + nCellMarginsRightW; } else { if (arrMinMargin[nCurGridCol] < nCellMarginsLeftW) arrMinMargin[nCurGridCol] = nCellMarginsLeftW; if (arrMinMargin[nCurGridCol + nGridSpan - 1] < nCellMarginsRightW) arrMinMargin[nCurGridCol + nGridSpan - 1] = nCellMarginsRightW; } nCurGridCol += nGridSpan; } } if (isReturnByColumns) return arrMinMargin; var nSumMin = 0; for (var nCurCol = 0; nCurCol < nGridCount; ++nCurCol) { nSumMin += arrMinMargin[nCurCol]; } return nSumMin; }; /** * Получаем минимальную высоту таблицы * @returns {number} */ CTable.prototype.GetMinHeight = function() { var nSumMin = 0; for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.Content[nCurRow]; var nSpacing = oRow.GetCellSpacing(); var nMaxTopMargin = 0, nMaxBottomMargin = 0, nMaxTopBorder = 0, nMaxBottomBorder = 0; for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); var oCellMargins = oCell.GetMargins(); var oCellTBorder = oCell.GetBorder(0); var oCellBBorder = oCell.GetBorder(2); if (border_None !== oCellTBorder.Value && nMaxTopBorder < oCellTBorder.Size) nMaxTopBorder = oCellTBorder.Size; if (border_None !== oCellBBorder.Value && nMaxBottomBorder < oCellBBorder.Size) nMaxBottomBorder = oCellBBorder.Size; if (nMaxTopMargin < oCellMargins.Top.W) nMaxTopMargin = oCellMargins.Top.W; if (nMaxBottomMargin < oCellMargins.Bottom.W) nMaxBottomMargin = oCellMargins.Bottom.W; } nSumMin += 4.5; // Стандартная минимальная высота строки в таблице без учета границ и отступов if (null !== nSpacing) { if (0 === nCurRow) nSumMin += this.GetTopTableBorder().GetWidth(); nSumMin += nSpacing; nSumMin += nMaxTopBorder; nSumMin += nMaxTopMargin; nSumMin += nMaxBottomMargin; nSumMin += nMaxBottomBorder; nSumMin += nRowsCount - 1 === nCurRow ? nSpacing : 0; if (nRowsCount - 1 === nCurRow) nSumMin += this.GetBottomTableBorder().GetWidth(); } else { nSumMin += Math.max(nMaxTopBorder, nMaxTopMargin); nSumMin += nMaxBottomMargin; if (nRowsCount - 1 === nCurRow) nSumMin += nMaxBottomBorder; } } return nSumMin; }; /** * Получаем минимальную высоту для заданной строки таблицы * @param nCurRow * @returns {number} */ CTable.prototype.GetMinRowHeight = function(nCurRow) { var nSumMin = 0; var oRow = this.Content[nCurRow]; var nMaxTopMargin = 0, nMaxBottomMargin = 0, nMaxTopBorder = 0; for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); var oCellMargins = oCell.GetMargins(); var oCellTBorder = oCell.GetBorder(0); var oCellBBorder = oCell.GetBorder(2); if (border_None !== oCellTBorder.Value && nMaxTopBorder < oCellTBorder.Size) nMaxTopBorder = oCellTBorder.Size; if (nMaxTopMargin < oCellMargins.Top.W) nMaxTopMargin = oCellMargins.Top.W; if (nMaxBottomMargin < oCellMargins.Bottom.W) nMaxBottomMargin = oCellMargins.Bottom.W; } nSumMin += 4.5; // Стандартная минимальная высота строки в таблице без учета границ и отступов nSumMin += Math.max(nMaxTopBorder, nMaxTopMargin); nSumMin += nMaxBottomMargin; return nSumMin; }; /** * Получаем суммарную высоту таблицы, с учетом ее разбиения на нескольких страницах * @returns {number} */ CTable.prototype.GetSummaryHeight = function() { var nSum = 0; for (var nCurPage = 0, nPagesCount = this.Pages.length; nCurPage < nPagesCount; ++nCurPage) { var oBounds = this.GetPageBounds(nCurPage); nSum += oBounds.Bottom - oBounds.Top; } return nSum; }; CTable.prototype.GetTableOfContents = function(isUnique, isCheckFields) { for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oResult = oRow.GetCell(nCurCell).Content.GetTableOfContents(isUnique, isCheckFields); if (oResult) return oResult; } } return null; }; CTable.prototype.GetTablesOfFigures = function(arrComplexFields) { for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { oRow.GetCell(nCurCell).Content.GetTablesOfFigures(arrComplexFields); } } }; /** * Делаем выделенные ячейки равными по ширине * @returns {boolean} Возрвщаем false, если операция невозможна */ CTable.prototype.DistributeColumns = function() { if ((true != this.Selection.Use || (true === this.Selection.Use && table_Selection_Text === this.Selection.Type)) && this.CurCell.Content.DistributeTableCells(true)) return true; var isApplyToAll = this.ApplyToAll; if (!this.Selection.Use || table_Selection_Text === this.Selection.Type) this.ApplyToAll = true; var arrSelectedCells = this.GetSelectionArray(); this.ApplyToAll = isApplyToAll; if (arrSelectedCells.length <= 1) return false; var arrRows = []; var arrCheckMergedCells = []; for (var nIndex = 0, nCount = arrSelectedCells.length; nIndex < nCount; ++nIndex) { var nCurCell = arrSelectedCells[nIndex].Cell; var nCurRow = arrSelectedCells[nIndex].Row; if (!arrRows[nCurRow]) { arrRows[nCurRow] = { Start : nCurCell, End : nCurCell }; } else { if (arrRows[nCurRow].Start > nCurCell) arrRows[nCurRow].Start = nCurCell; if (arrRows[nCurRow].End < nCurCell) arrRows[nCurRow].End = nCurCell; } var oCell = this.Content[nCurRow].GetCell(nCurCell); if (oCell) { var oCellInfo = this.Content[nCurRow].GetCellInfo(nCurCell); var arrMergedCells = this.private_GetMergedCells(nCurRow, oCellInfo.StartGridCol, oCell.GetGridSpan()); if (arrMergedCells.length > 1) { arrCheckMergedCells.push([nCurRow]); } for (var nMergeIndex = 1, nMergedCount = arrMergedCells.length; nMergeIndex < nMergedCount; ++nMergeIndex) { var nCurCell2 = arrMergedCells[nMergeIndex].Index; var nCurRow2 = arrMergedCells[nMergeIndex].Row.Index; if (!arrRows[nCurRow2]) { arrRows[nCurRow2] = { Start : nCurCell2, End : nCurCell2 }; } else { if (arrRows[nCurRow2].Start > nCurCell2) arrRows[nCurRow2].Start = nCurCell2; if (arrRows[nCurRow2].End < nCurCell2) arrRows[nCurRow2].End = nCurCell2; } arrCheckMergedCells[arrCheckMergedCells.length - 1].push(nCurRow2); } } } for (var nIndex = 0, nCount = arrCheckMergedCells.length; nIndex < nCount; ++nIndex) { var nFirstStartGridCol = null, arrFirstGridSpans = null; for (var nRowIndex = 0, nRowsCount = arrCheckMergedCells[nIndex].length; nRowIndex < nRowsCount; ++nRowIndex) { var nCurRow = arrCheckMergedCells[nIndex][nRowIndex]; var oRow = this.GetRow(nCurRow); var nStartGridCol = this.Content[nCurRow].GetBefore().Grid; var arrGridSpans = []; for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var nGridSpan = oRow.GetCell(nCurCell).GetGridSpan(); if (nCurCell < arrRows[nCurRow].Start) nStartGridCol += nGridSpan; else if (nCurCell <= arrRows[nCurRow].End) arrGridSpans.push(nGridSpan); else break; } if (null === nFirstStartGridCol) { nFirstStartGridCol = nStartGridCol; arrFirstGridSpans = arrGridSpans; } else { if (nStartGridCol !== nFirstStartGridCol || arrFirstGridSpans.length !== arrGridSpans.length) { return false; } else { for (var nSpanIndex = 0, nSpansCount = arrGridSpans.length; nSpanIndex < nSpansCount; ++nSpanIndex) { if (arrFirstGridSpans[nSpanIndex] !== arrGridSpans[nSpanIndex]) return false; } } } } } var isAutofitLayout = this.GetTableLayout() === tbllayout_AutoFit; var isNeedChangeLayout = false; var arrRowsInfo = this.private_GetRowsInfo(); for (nCurRow in arrRows) { if (!arrRowsInfo[nCurRow] || arrRowsInfo[nCurRow].length <= 0) continue; var nStartCell = arrRows[nCurRow].Start; var nEndCell = arrRows[nCurRow].End; var nSum = 0; var nAdd = -1 === arrRowsInfo[nCurRow][0].Type ? 1 : 0; for (var nCurCell = nStartCell; nCurCell <= nEndCell; ++nCurCell) { nSum += arrRowsInfo[nCurRow][nCurCell + nAdd].W; } for (var nCurCell = nStartCell; nCurCell <= nEndCell; ++nCurCell) { var nNewW = nSum / (nEndCell - nStartCell + 1); arrRowsInfo[nCurRow][nCurCell + nAdd].W = nNewW; // TODO: Надо поправить баг в рассчете AutoFit из-за которого тут сдвиг происходит var oRow = this.GetRow(nCurRow); if (!oRow) continue; var oCell = oRow.GetCell(nCurCell); if (!oCell) continue; if (isAutofitLayout && !isNeedChangeLayout && oCell.RecalculateMinMaxContentWidth(false, this.private_RecalculatePercentWidth()).Max - 0.001 > nNewW) isNeedChangeLayout = true; } } if (isAutofitLayout && isNeedChangeLayout) this.SetTableLayout(tbllayout_Fixed); this.private_CreateNewGrid(arrRowsInfo); this.private_RecalculateGrid(); return true; }; /** * Делаем выделенные ячейки равными по высоте * @returns {boolean} */ CTable.prototype.DistributeRows = function() { if ((true != this.Selection.Use || (true === this.Selection.Use && table_Selection_Text === this.Selection.Type)) && this.CurCell.Content.DistributeTableCells(false)) return true; var isApplyToAll = this.ApplyToAll; if (!this.Selection.Use || table_Selection_Text === this.Selection.Type) this.ApplyToAll = true; var arrSelectedCells = this.GetSelectionArray(); this.ApplyToAll = isApplyToAll; if (arrSelectedCells.length <= 1) return false; var arrRows = [], nRowsCount = 0; for (var nIndex = 0, nCount = arrSelectedCells.length; nIndex < nCount; ++nIndex) { if (true !== arrRows[arrSelectedCells[nIndex].Row]) { arrRows[arrSelectedCells[nIndex].Row] = true; nRowsCount++; } var oCell = this.GetStartMergedCell(arrSelectedCells[nIndex].Cell, arrSelectedCells[nIndex].Row); if (oCell) { var nVMergeCount = this.GetVMergeCount(oCell.Index, oCell.Row.Index); if (nVMergeCount > 1) { for (var nCurRow = oCell.Row.Index; nCurRow < oCell.Row.Index + nVMergeCount - 1; ++nCurRow) { if (true !== arrRows[nCurRow]) { arrRows[nCurRow] = true; nRowsCount++; } } } } } if (nRowsCount <= 0) return false; var nCellSpacing = this.GetRow(0).GetCellSpacing(); var nSumH = 0; for (var nCurRow in arrRows) { var nRowSummaryH = 0; for (var nCurPage in this.RowsInfo[nCurRow].H) nRowSummaryH += this.RowsInfo[nCurRow].H[nCurPage]; for (var nCurPage in this.RowsInfo[nCurRow].TopDy) nRowSummaryH -= this.RowsInfo[nCurRow].TopDy[nCurPage]; if(!this.bPresentation) { var oRow = this.GetRow(nCurRow); nRowSummaryH -= oRow.GetTopMargin() + oRow.GetBottomMargin(); } nSumH += nRowSummaryH; } var nNewValueH = nSumH / nRowsCount; for (var nCurRow in arrRows) { nCurRow = parseInt(nCurRow); var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); if (vmerge_Restart !== oCell.GetVMerge()) continue; var nVMergeCount = this.GetVMergeCount(nCurCell, nCurRow); var nNewH = nNewValueH; if (null !== nCellSpacing) nNewH += nCellSpacing; var nContentH = oCell.GetContent().GetSummaryHeight(); if (nNewH * nVMergeCount < nContentH) nNewValueH += (nContentH / nVMergeCount - nNewH); } } for (var nCurRow in arrRows) { nCurRow = parseInt(nCurRow); var oRow = this.GetRow(nCurRow); var oRowH = oRow.GetHeight(); var nNewH = nNewValueH; if (null !== nCellSpacing) nNewH += nCellSpacing; oRow.SetHeight(nNewH, oRowH.HRule === Asc.linerule_Exact ? Asc.linerule_Exact : Asc.linerule_AtLeast); } return true; }; /** * Выставляем ширину текущей колонки * @param nWidth */ CTable.prototype.SetColumnWidth = function(nWidth) { if (nWidth < 4.2) nWidth = 4.2; if (nWidth > 558.8) nWidth = 558.8; var arrSelectedCells = this.GetSelectionArray(); var oCells = {}; for (var nIndex = 0, nCount = arrSelectedCells.length; nIndex < nCount; ++nIndex) { var nCurCell = arrSelectedCells[nIndex].Cell; if (!oCells[nCurCell]) oCells[nCurCell] = 1; } var arrRowsInfo = this.private_GetRowsInfo(); for (var nCurRow = 0, nCount = arrRowsInfo.length; nCurRow < nCount; ++nCurRow) { var nAdd = -1 === arrRowsInfo[nCurRow][0].Type ? 1 : 0; for (var nCurCell in oCells) { var _nCurCell = nCurCell | 0; if (arrRowsInfo[nCurRow][_nCurCell + nAdd]) arrRowsInfo[nCurRow][_nCurCell + nAdd].W = nWidth; } } this.private_CreateNewGrid(arrRowsInfo); }; /** * Выставляем высоту текущей строки * @param nHeight */ CTable.prototype.SetRowHeight = function(nHeight) { var oRowsRange = this.GetSelectedRowsRange(); for (var nCurRow = oRowsRange.Start; nCurRow <= oRowsRange.End; ++nCurRow) { var oRow = this.GetRow(nCurRow); var oRowH = oRow.GetHeight(); if (oRowH.IsAuto()) oRow.SetHeight(nHeight, Asc.linerule_AtLeast); else oRow.SetHeight(nHeight, oRowH.GetRule()); } }; /** * Проверяем попадает ли данная строка в заголовок таблицы * @param nRow * @returns {boolean} */ CTable.prototype.IsInHeader = function(nRow) { for (var nCurRow = 0; nCurRow <= nRow; ++nCurRow) { var oRow = this.GetRow(nCurRow); if (!oRow.IsHeader()) return false; } return true; }; CTable.prototype.GetLastParagraph = function() { var nRowsCount = this.GetRowsCount(); if (nRowsCount <= 0) return null; var oRow = this.GetRow(nRowsCount - 1); var nCellsCount = oRow.GetCellsCount(); if (nCellsCount <= 0) return null; return oRow.GetCell(nCellsCount - 1).GetContent().GetLastParagraph(); }; CTable.prototype.GetPlaceHolderObject = function() { if (this.IsCellSelection()) return null; return this.CurCell.GetContent().GetPlaceHolderObject(); }; CTable.prototype.GetPresentationField = function() { if (this.IsCellSelection()) return null; return this.CurCell.GetContent().GetPresentationField(); }; /** * Получаем колонку в виде массива ячеек * @returns {[CTableCell]} */ CTable.prototype.GetColumn = function(nCurCell, nCurRow) { if (null === nCurRow || undefined === nCurRow) nCurRow = 0; var oRow = this.GetRow(nCurRow); if (!oRow) return []; if (nCurCell < 0) nCurCell = 0; if (nCurCell >= oRow.GetCellsCount()) nCurCell = oRow.GetCellsCount() - 1; var oCell = oRow.GetCell(nCurCell); if (!oCell) return []; var nGridStart = oRow.GetCellInfo(nCurCell).StartGridCol; var nGridEnd = nGridStart + oCell.GetGridSpan() - 1; var arrCells = []; var arrPoses = this.private_GetColumnByGridRange(nGridStart, nGridEnd); for (var nIndex = 0, nCount = arrPoses.length; nIndex < nCount; ++nIndex) { var oPos = arrPoses[nIndex]; arrCells.push(this.GetRow(oPos.Row).GetCell(oPos.Cell)); } return arrCells; }; CTable.prototype.private_GetColumnByGridRange = function(nGridStart, nGridEnd, arrPos) { if (!arrPos) arrPos = []; for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); if (vmerge_Continue === oCell.GetVMerge()) continue; var nStartGridCol = oRow.GetCellInfo(nCurCell).StartGridCol; var nEndGridCol = nStartGridCol + oCell.GetGridSpan() - 1; if ((nEndGridCol >= nGridStart && nStartGridCol <= nGridEnd) || (nStartGridCol <= nGridStart && nGridEnd <= nEndGridCol)) arrPos.push({Cell : nCurCell, Row : nCurRow}); } } return arrPos; }; CTable.prototype.HavePrChange = function() { return this.Pr.HavePrChange(); }; CTable.prototype.AddPrChange = function(oPr) { if (false === this.HavePrChange()) { if (oPr && oPr.Comparison) { oPr.Comparison.addTablePrChange(this.Pr); } else { this.Pr.AddPrChange(); } AscCommon.History.Add(new CChangesTablePrChange(this, { PrChange : undefined, ReviewInfo : undefined }, { PrChange : this.Pr.PrChange, ReviewInfo : this.Pr.ReviewInfo })); this.updateTrackRevisions(); } }; CTable.prototype.RemovePrChange = function() { if (true === this.HavePrChange()) { AscCommon.History.Add(new CChangesTablePrChange(this, { PrChange : this.Pr.PrChange, ReviewInfo : this.Pr.ReviewInfo }, { PrChange : undefined, ReviewInfo : undefined })); this.Pr.RemovePrChange(); this.updateTrackRevisions(); } }; CTable.prototype.private_AddPrChange = function() { if (this.LogicDocument && true === this.LogicDocument.IsTrackRevisions() && true !== this.HavePrChange()) this.AddPrChange(); }; CTable.prototype.GetPrReviewColor = function() { if (this.Pr.ReviewInfo) return this.Pr.ReviewInfo.Get_Color(); return REVIEW_COLOR; }; CTable.prototype.CheckRevisionsChanges = function(oRevisionsManager) { // TODO: Пока у нас нет отдельного типа для изменений настроек у строки // поэтому мы их передаем как у всей таблицы var nRowsCount = this.GetRowsCount(); if (nRowsCount <= 0) return; let tableId = this.GetId(); let table = this; let tablePrChange = false; function private_FlushTablePrChange(reviewInfo, startRow, endRow) { let change = new CRevisionsChange(); change.put_Paragraph(table); change.put_StartPos(startRow); change.put_EndPos(endRow); change.put_Type(c_oAscRevisionsChangeType.TablePr); change.put_UserId(reviewInfo.GetUserId()); change.put_UserName(reviewInfo.GetUserName()); change.put_DateTime(reviewInfo.GetDateTime()); oRevisionsManager.AddChange(tableId, change); tablePrChange = true; } if (this.HavePrChange()) private_FlushTablePrChange(this.Pr.ReviewInfo, 0, nRowsCount - 1); function private_FlushTableChange(nType, nStartRow, nEndRow) { if (reviewtype_Common === nType) return; var oRow = table.GetRow(nStartRow); var oRowReviewInfo = oRow.GetReviewInfo(); var oChange = new CRevisionsChange(); oChange.put_Paragraph(table); oChange.put_StartPos(nStartRow); oChange.put_EndPos(nEndRow); oChange.put_Type(nType === reviewtype_Add ? c_oAscRevisionsChangeType.RowsAdd : c_oAscRevisionsChangeType.RowsRem); oChange.put_UserId(oRowReviewInfo.GetUserId()); oChange.put_UserName(oRowReviewInfo.GetUserName()); oChange.put_DateTime(oRowReviewInfo.GetDateTime()); oRevisionsManager.AddChange(tableId, oChange); } function private_FlushTableRowPrChange(reviewInfo, startRow, endRow) { let change = new CRevisionsChange(); change.put_Paragraph(table); change.put_StartPos(startRow); change.put_EndPos(endRow); change.put_Type(c_oAscRevisionsChangeType.TableRowPr); change.put_UserId(reviewInfo.GetUserId()); change.put_UserName(reviewInfo.GetUserName()); change.put_DateTime(reviewInfo.GetDateTime()); oRevisionsManager.AddChange(tableId, change); } var nType = reviewtype_Common; var nStartRow = 0; var nEndRow = 0; var sUserId = ""; for (var nCurRow = 0; nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); var nRowReviewType = oRow.GetReviewType(); var oRowReviewInfo = oRow.GetReviewInfo(); if (!tablePrChange) { let rowReviewInfo = null; if (oRow.HavePrChange() && oRow.Pr.ReviewInfo) rowReviewInfo = oRow.Pr.ReviewInfo; else if (oRow.HaveCellPrChange()) rowReviewInfo = oRow.GetFirstCellReviewInfo(); if (rowReviewInfo) private_FlushTableRowPrChange(rowReviewInfo, oRow.GetIndex(), oRow.GetIndex()); } if (reviewtype_Common === nType) { if (reviewtype_Common !== nRowReviewType) { nType = nRowReviewType; nStartRow = nCurRow; nEndRow = nCurRow; sUserId = oRowReviewInfo.GetUserId(); } } else { if (nType === nRowReviewType && oRowReviewInfo.GetUserId() == sUserId) { nEndRow = nCurRow; } else if (reviewtype_Common === nRowReviewType) { private_FlushTableChange(nType, nStartRow, nEndRow); nType = reviewtype_Common; } else { private_FlushTableChange(nType, nStartRow, nEndRow); nType = nRowReviewType; nStartRow = nCurRow; nEndRow = nCurRow; sUserId = oRowReviewInfo.GetUserId(); } } } private_FlushTableChange(nType, nStartRow, nEndRow); }; CTable.prototype.AcceptPrChange = function() { this.RemovePrChange(); for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); oCell.RemovePrChange(); } oRow.AcceptPrChange(); } this.SetTableGridChange(undefined); }; CTable.prototype.RejectPrChange = function() { if (true === this.HavePrChange()) { this.SetPr(this.Pr.PrChange); this.RemovePrChange(); } for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); oCell.RejectPrChange(); } oRow.RejectPrChange(); } if (undefined !== this.TableGridChange) { // Важно сначала выставить обычную сетку, т.к. там идет проверка на наличие TableGridChange this.SetTableGrid(this.TableGridChange); this.SetTableGridChange(undefined); // Может так случиться, что сетка станет некорректной для текущего состояния таблицы, поэтому нужно // произвести корректировку this.CorrectBadGrid(); } }; CTable.prototype.private_CheckCurCell = function() { if (this.CurCell) { var oRow = this.CurCell.GetRow(); if (!oRow || oRow.GetTable() !== this || this.GetRow(oRow.GetIndex()) !== oRow || this.CurCell !== oRow.GetCell(this.CurCell.GetIndex())) this.CurCell = null; } if (!this.CurCell) { for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); if (oRow.GetCellsCount() > 0) { this.CurCell = oRow.GetCell(0); break; } } } // TODO: SelectionData переделать с индексов на массив самих ячеек, и при изменениях мы будем проверять сами ячейки if (this.Selection.Use && this.Selection.Data && this.Selection.Data.length) { for (let i = this.Selection.Data.length - 1; i >= 0; --i) { let row = this.Selection.Data[i].Row; let cell = this.Selection.Data[i].Cell; if (row >= this.Content.length || row < 0 || cell >= this.GetRow(row).GetCellsCount() || cell < 0) this.Selection.Data.splice(i, 1); } } }; CTable.prototype.CheckRunContent = function(fCheck) { for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { if (oRow.GetCell(nCurCell).GetContent().CheckRunContent(fCheck)) { return true; } } } return false; }; CTable.prototype.CheckSelectedRunContent = function(fCheck) { if (!this.Selection.Use) return false; var arrCells = this.GetSelectionArray(false); for (let nIndex = 0, nCount = arrCells.length; nIndex < nCount; ++nIndex) { let oPos = arrCells[nIndex]; let oCell = this.GetRow(oPos.Row).GetCell(oPos.Cell); let oContent = oCell.GetContent(); oContent.SetApplyToAll(true); let result = oContent.CheckSelectedRunContent(fCheck); oContent.SetApplyToAll(false); if (result) return true; } return false; }; CTable.prototype.Document_Is_SelectionLocked = function(CheckType, bCheckInner) { var bCheckContentControl = false; switch (CheckType) { 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: case AscCommon.changestype_Document_Content: case AscCommon.changestype_Document_Content_Add: case AscCommon.changestype_Delete: case AscCommon.changestype_Image_Properties: { if (this.IsCellSelection()) { var arrCells = this.GetSelectionArray(); var Count = arrCells.length; for (var Index = 0; Index < Count; Index++) { var Pos = arrCells[Index]; var Cell = this.Content[Pos.Row].Get_Cell(Pos.Cell); Cell.Content.SetApplyToAll(true); Cell.Content.Document_Is_SelectionLocked(CheckType); Cell.Content.SetApplyToAll(false); } } else if (this.CurCell) { this.CurCell.Content.Document_Is_SelectionLocked(CheckType); } bCheckContentControl = true; break; } case AscCommon.changestype_Remove: { if (this.IsCellSelection()) { this.Lock.Check(this.Get_Id()); var arrCells = this.GetSelectionArray(); for (var nIndex = 0, nCellsCount = arrCells.length; nIndex < nCellsCount; ++nIndex) { var oPos = arrCells[nIndex]; var oCell = this.GetRow(oPos.Row).GetCell(oPos.Cell); var oCellContent = oCell.GetContent(); oCellContent.SetApplyToAll(true); oCellContent.Document_Is_SelectionLocked(CheckType); oCellContent.SetApplyToAll(false); } } else if (this.CurCell) { this.CurCell.Content.Document_Is_SelectionLocked(CheckType); } bCheckContentControl = true; break; } case AscCommon.changestype_Table_Properties: { if ( false != bCheckInner && true === this.IsInnerTable() ) this.CurCell.Content.Document_Is_SelectionLocked( CheckType ); else this.Lock.Check( this.Get_Id() ); bCheckContentControl = true; break; } case AscCommon.changestype_Table_RemoveCells: { /* // Проверяем все ячейки if ( true === this.Selection.Use && table_Selection_Cell === this.Selection.Type ) { var Count = this.Selection.Data.length; for ( var Index = 0; Index < Count; Index++ ) { var Pos = this.Selection.Data[Index]; var Cell = this.Content[Pos.Row].Get_Cell( Pos.Cell ); Cell.Content.Document_Is_SelectionLocked( CheckType ); } } else this.CurCell.Content.Document_Is_SelectionLocked( CheckType ); */ // Проверяем саму таблицу if ( false != bCheckInner && true === this.IsInnerTable() ) this.CurCell.Content.Document_Is_SelectionLocked( CheckType ); else this.Lock.Check( this.Get_Id() ); bCheckContentControl = true; break; } case AscCommon.changestype_Document_SectPr: { AscCommon.CollaborativeEditing.Add_CheckLock(true); break; } } if (bCheckContentControl && this.Parent && this.Parent.CheckContentControlEditingLock) this.Parent.CheckContentControlEditingLock(); }; CTable.prototype.GetAllTablesOnPage = function(nPageAbs, arrTables) { if (!arrTables) return arrTables = []; var nFirstRow = -1; var nLastRow = -2; for (var nCurPage = 0, nPagesCount = this.Pages.length; nCurPage < nPagesCount; ++nCurPage) { var nTempPageAbs = this.GetAbsolutePage(nCurPage); if (nPageAbs === nTempPageAbs) { if (-1 === nFirstRow) { nFirstRow = this.Pages[nCurPage].FirstRow; } nLastRow = this.Pages[nCurPage].LastRow; arrTables.push({Table : this, Page : nCurPage}); } else if (nTempPageAbs > nPageAbs) { break; } } for (var nCurRow = nFirstRow; nCurRow <= nLastRow; ++nCurRow) { var oRow = this.GetRow(nCurRow); if (oRow) { for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); if (oCell.IsMergedCell()) continue; oCell.GetContent().GetAllTablesOnPage(nPageAbs, arrTables); } } } return arrTables; }; CTable.prototype.ProcessComplexFields = function() { for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { oRow.GetCell(nCurCell).GetContent().ProcessComplexFields(); } } }; CTable.prototype.RecalculateEndInfo = function() { for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { var oCell = oRow.GetCell(nCurCell); oCell.GetContent().RecalculateEndInfo(); } } }; CTable.prototype.GetMaxTableGridWidth = function() { this.private_RecalculateGrid(); var nIndent = this.Get_CompiledPr(false).TablePr.TableInd; return { GapLeft : -this.GetTableOffsetCorrection() - nIndent, GapRight : this.GetRightTableOffsetCorrection() + nIndent, GridWidth : this.TableSumGrid[this.TableSumGrid.length - 1] + this.GetTableOffsetCorrection() - this.GetRightTableOffsetCorrection() }; }; CTable.prototype.GetDocumentPositionFromObject = function(arrPos) { arrPos = CDocumentContentElementBase.prototype.GetDocumentPositionFromObject.call(this, arrPos); if(this.Parent instanceof AscFormat.CGraphicFrame) { arrPos.splice(0, 1); } return arrPos; }; CTable.prototype.CalculateTextToTable = function(oEngine) { oEngine.OnTable(this); }; CTable.prototype.RestartSpellCheck = function() { this.Recalc_CompiledPr(); for (let nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { let oRow = this.GetRow(nCurRow); oRow.Recalc_CompiledPr(); for (let nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { let oCell = oRow.GetCell(nCurCell); oCell.Recalc_CompiledPr(); oCell.GetContent().RestartSpellCheck(); } } }; //---------------------------------------------------------------------------------------------------------------------- // Search //---------------------------------------------------------------------------------------------------------------------- CTable.prototype.Search = function(oSearchEngine, nType) { for (var nCurRow = 0, nRowsCount = this.GetRowsCount(); nCurRow < nRowsCount; ++nCurRow) { var oRow = this.GetRow(nCurRow); for (var nCurCell = 0, nCellsCount = oRow.GetCellsCount(); nCurCell < nCellsCount; ++nCurCell) { oRow.GetCell(nCurCell).GetContent().Search(oSearchEngine, nType); } } }; CTable.prototype.GetSearchElementId = function(bNext, bCurrent) { if ( true === bCurrent ) { var Id = null; var CurRow = 0; var CurCell = 0; if ( true === this.Selection.Use && table_Selection_Cell === this.Selection.Type ) { var Pos = ( true === bNext ? this.Selection.Data[this.Selection.Data.length - 1] : this.Selection.Data[0] ); CurRow = Pos.Row; CurCell = Pos.CurCell; } else { Id = this.CurCell.Content.GetSearchElementId(bNext, true); if ( Id != null ) return Id; CurRow = this.CurCell.Row.Index; CurCell = this.CurCell.Index; } var Rows_Count = this.Content.length; if ( true === bNext ) { for ( var _CurRow = CurRow; _CurRow < Rows_Count; _CurRow++ ) { var Row = this.Content[_CurRow]; var Cells_Count = Row.Get_CellsCount(); var StartCell = ( _CurRow === CurRow ? CurCell + 1 : 0 ); for ( var _CurCell = StartCell; _CurCell < Cells_Count; _CurCell++ ) { var Cell = Row.Get_Cell(_CurCell); Id = Cell.Content.GetSearchElementId( true, false ); if ( null != Id ) return Id; } } } else { for ( var _CurRow = CurRow; _CurRow >= 0; _CurRow-- ) { var Row = this.Content[_CurRow]; var Cells_Count = Row.Get_CellsCount(); var StartCell = ( _CurRow === CurRow ? CurCell - 1 : Cells_Count - 1 ); for ( var _CurCell = StartCell; _CurCell >= 0; _CurCell-- ) { var Cell = Row.Get_Cell(_CurCell); Id = Cell.Content.GetSearchElementId( false, false ); if ( null != Id ) return Id; } } } } else { var Rows_Count = this.Content.length; if ( true === bNext ) { for ( var _CurRow = 0; _CurRow < Rows_Count; _CurRow++ ) { var Row = this.Content[_CurRow]; var Cells_Count = Row.Get_CellsCount(); for ( var _CurCell = 0; _CurCell < Cells_Count; _CurCell++ ) { var Cell = Row.Get_Cell(_CurCell); Id = Cell.Content.GetSearchElementId( true, false ); if ( null != Id ) return Id; } } } else { for ( var _CurRow = Rows_Count - 1; _CurRow >= 0; _CurRow-- ) { var Row = this.Content[_CurRow]; var Cells_Count = Row.Get_CellsCount(); for ( var _CurCell = Cells_Count - 1; _CurCell >= 0; _CurCell-- ) { var Cell = Row.Get_Cell(_CurCell); Id = Cell.Content.GetSearchElementId( false, false ); if ( null != Id ) return Id; } } } } return Id; }; //---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- // Класс CTableAnchorPosition //---------------------------------------------------------------------------------------------------------------------- function CTableAnchorPosition() { // Рассчитанные координаты this.CalcX = 0; this.CalcY = 0; // Данные для Flow-объектов this.W = 0; this.H = 0; this.X = 0; this.Y = 0; this.Left_Margin = 0; this.Right_Margin = 0; this.Top_Margin = 0; this.Bottom_Margin = 0; this.Page_W = 0; this.Page_H = 0; this.Page_Top = 0; this.Page_Bottom = 0; this.X_min = 0; this.Y_min = 0; this.X_max = 0; this.Y_max = 0; } CTableAnchorPosition.prototype = { Set_X : function(W, X, Left_Margin, Right_Margin, Page_W, X_min, X_max) { this.W = W; this.X = X; this.Left_Margin = Left_Margin; this.Right_Margin = Right_Margin; this.Page_W = Page_W; this.X_min = X_min; this.X_max = X_max; }, Set_Y : function(H, Y, Top_Margin, Bottom_Margin, Page_H, Y_min, Y_max, Page_Top, Page_Bottom) { this.H = H; this.Y = Y; this.Top_Margin = Top_Margin; this.Bottom_Margin = Bottom_Margin; this.Page_H = Page_H; this.Y_min = Y_min; this.Y_max = Y_max; this.Page_Top = Page_Top; this.Page_Bottom = Page_Bottom; }, Calculate_X : function(RelativeFrom, bAlign, Value) { // Вычисляем координату по X switch(RelativeFrom) { // TODO: пока нет колонок варианты Text и Margin ничем не отличаются, // когда появятся колонки доделать тут case c_oAscHAnchor.Text: case c_oAscHAnchor.Margin: { if ( true === bAlign ) { switch ( Value ) { case c_oAscXAlign.Center: { this.CalcX = (this.Left_Margin + this.Right_Margin - this.W) / 2; break; } case c_oAscXAlign.Inside: case c_oAscXAlign.Outside: case c_oAscXAlign.Left: { this.CalcX = this.Left_Margin; break; } case c_oAscXAlign.Right: { this.CalcX = this.Right_Margin - this.W; break; } } } else this.CalcX = this.Left_Margin + Value; break; } case c_oAscHAnchor.Page: { var W = this.X_max - this.X_min; if ( true === bAlign ) { switch ( Value ) { case c_oAscXAlign.Center: { this.CalcX = this.X_min + (W - this.W) / 2; break; } case c_oAscXAlign.Inside: case c_oAscXAlign.Outside: case c_oAscXAlign.Left: { this.CalcX = this.X_min; break; } case c_oAscXAlign.Right: { this.CalcX = this.X_max - this.W; break; } } } else this.CalcX = this.X_min + Value; break; } } return this.CalcX; }, Calculate_Y : function(RelativeFrom, bAlign, Value) { // Вычисляем координату по Y switch(RelativeFrom) { case c_oAscVAnchor.Margin: { if ( true === bAlign ) { switch(Value) { case c_oAscYAlign.Bottom: { this.CalcY = this.Bottom_Margin - this.H; break; } case c_oAscYAlign.Center: { this.CalcY = (this.Bottom_Margin + this.Top_Margin - this.H) / 2; break; } case c_oAscYAlign.Inline: case c_oAscYAlign.Inside: case c_oAscYAlign.Outside: case c_oAscYAlign.Top: { this.CalcY = this.Top_Margin; break; } } } else this.CalcY = this.Top_Margin + Value; break; } case c_oAscVAnchor.Page: { if ( true === bAlign ) { switch(Value) { case c_oAscYAlign.Bottom: { this.CalcY = this.Page_Bottom - this.H; break; } case c_oAscYAlign.Center: { this.CalcY = (this.Page_Bottom - this.H) / 2; break; } case c_oAscYAlign.Inline: case c_oAscYAlign.Inside: case c_oAscYAlign.Outside: case c_oAscYAlign.Top: { this.CalcY = this.Page_Top; break; } } } else this.CalcY = this.Page_Top + Value; break; } case c_oAscVAnchor.Text: { if (true === bAlign) { // Word не дает делать прилегания в данном случае, но при этом почему-то наезжает на верхний // параграф (см. баг #41115) this.CalcY = this.Y - AscCommon.TwipsToMM(2); } else { this.CalcY = this.Y + Value; } break; } } return this.CalcY; }, Correct_Values : function(X_min, Y_min, X_max, Y_max, AllowOverlap, OtherFlowTables, CurTable) { var W = this.W; var H = this.H; var CurX = this.CalcX; var CurY = this.CalcY; var bBreak = false; while ( true != bBreak ) { bBreak = true; for ( var Index = 0; Index < OtherFlowTables.length; Index++ ) { var FlowTable = OtherFlowTables[Index]; if ( FlowTable.Table != CurTable && ( false === AllowOverlap || false === FlowTable.Table.Get_AllowOverlap() ) && ( CurX <= FlowTable.X + FlowTable.W && CurX + W >= FlowTable.X && CurY <= FlowTable.Y + FlowTable.H && CurY + H >= FlowTable.Y ) ) { /* // Если убирается справа, размещаем справа от картинки if ( FlowTable.X + FlowTable.W < X_max - W - 0.001 ) CurX = FlowTable.X + FlowTable.W + 0.001; else { CurX = this.CalcX; CurY = FlowTable.Y + FlowTable.H + 0.001; } */ // TODO: Пока у нас смещение по X плохо работает(смотри CTable.Shift), поэтому смещаем таблицу сразу по Y CurY = FlowTable.Y + FlowTable.H + 0.001; bBreak = false; } } } // TODO: Пока у нас смещение по X плохо работает(смотри CTable.Shift), поэтому смещаем таблицу сразу по Y /* // Скорректируем рассчитанную позицию, так чтобы объект не выходил за заданные пределы if ( CurX + W > X_max ) CurX = X_max - W; if ( CurX < X_min ) CurX = X_min; */ // Скорректируем рассчитанную позицию, так чтобы объект не выходил за заданные пределы if ( CurY + H > Y_max ) CurY = Y_max - H; if ( CurY < this.Y_min ) CurY = this.Y_min; this.CalcY = CurY; this.CalcX = CurX; }, // По значению CalcX получем Value Calculate_X_Value : function(RelativeFrom) { var Value = 0; switch(RelativeFrom) { case c_oAscHAnchor.Text: case c_oAscHAnchor.Margin: { Value = this.CalcX - this.Left_Margin; break; } case c_oAscHAnchor.Page: { Value = this.CalcX - this.X_min; break; } } return Value; }, // По значению CalcY и заданному RelativeFrom получем Value Calculate_Y_Value : function(RelativeFrom) { var Value = 0; switch(RelativeFrom) { case c_oAscVAnchor.Margin: { Value = this.CalcY - this.Top_Margin; break; } case c_oAscVAnchor.Page: { Value = this.CalcY - this.Page_Top; break; } case c_oAscVAnchor.Text: { Value = this.CalcY - this.Y; break; } } return Value; } }; function CTableRowsInfo() { this.Pages = 1; this.Y = []; this.H = []; this.TopDy = []; this.MaxTopBorder = []; this.FirstPage = true; this.StartPage = 0; this.X0 = 0; this.X1 = 0; this.MaxBotBorder = 0; this.VMerged = false; } CTableRowsInfo.prototype.Init = function() { this.Y[0] = 0.0; this.H[0] = 0.0; this.TopDy[0] = 0.0; this.MaxTopBorder[0] = 0.0; }; //--------------------------------------------------------export---------------------------------------------------- window['AscCommonWord'] = window['AscCommonWord'] || {}; window['AscCommonWord'].CTable = CTable; window['AscCommonWord'].type_Table = type_Table; window['AscWord'].CTable = CTable; window['AscWord'].Table = CTable;