Files
Yajbir Singh f1b860b25c
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

4697 lines
132 KiB
JavaScript

/*
* (c) Copyright Ascensio System SIA 2010-2024
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
"use strict";
(function(window, undefined){
var AscCommon = window['AscCommon'];
// класс для регистрации кнопок, для загрузки только нужных
// для текущего devicePixelRatio
function StorageBaseImageCtrl()
{
this.controls = [];
this.updateIndex = 0;
this.isNeedUpdate = false;
}
// регистрируем
StorageBaseImageCtrl.prototype.register = function(image)
{
this.controls.push(image);
};
// картинка не готова, но запрошена. значит после загрузки - нужно перерисоваться
StorageBaseImageCtrl.prototype.updateLater = function()
{
this.updateIndex++;
};
StorageBaseImageCtrl.prototype.needUpdate = function()
{
this.isNeedUpdate = true;
};
// картинка загрузилась - нужно проверить, надо ли перерисовать оверлей
StorageBaseImageCtrl.prototype.updateOverlay = function()
{
if (this.updateIndex == 0)
return;
this.updateIndex--;
if (this.updateIndex < 0)
this.updateIndex = 0;
if (this.updateIndex != 0)
{
// обновится, когда все загрузятся
return;
}
if (!this.isNeedUpdate)
{
// не было запроса на отрисовку, пока грузили
return;
}
this.isNeedUpdate = false;
var wordControl = window.editor ? window.editor.WordControl : undefined;
if (wordControl)
{
wordControl.ShowOverlay();
wordControl.StartUpdateOverlay();
wordControl.OnUpdateOverlay();
wordControl.EndUpdateOverlay();
// TODO: Пока временно сделаем так, в будущем надо отделить загрузку и обновление картинок, которые
// рисуются не на оверлее
let drawingDocument = wordControl.m_oDrawingDocument;
if (drawingDocument)
{
drawingDocument.ClearCachePages();
drawingDocument.FirePaint();
}
}
};
StorageBaseImageCtrl.prototype.resize = function()
{
for (var i = 0, len = this.controls.length; i < len; i++)
{
this.controls[i]._loadIndex(undefined);
if (this.controls[i].images_active.length > 0)
this.controls[i]._loadActiveIndex(undefined);
}
}
AscCommon.g_imageControlsStorage = new StorageBaseImageCtrl();
function BaseImageCtrl()
{
// регистрируем
AscCommon.g_imageControlsStorage.register(this);
this.images = [];
this.images_active = [];
this.images_hover = [];
this.url = "";
this.baseUrl = "";
}
// поддерживаемые devicePixelRatio
BaseImageCtrl.prototype.support = [1, 1.25, 1.5, 1.75, 2];
// на старте - грузим сразу ВСЕ размеры (не используем этот режим)
BaseImageCtrl.prototype.isLoadAllSizes = false;
// дописка к урлу (@..x)
BaseImageCtrl.prototype.getAddon = function(val)
{
val = (val * 100) >> 0;
if (100 === val)
return "";
while (0 === (val % 10))
val = (val / 10) >> 0;
if (val < 10)
return "@" + val + "x";
var str = "" + val;
return "@" + str.substring(0, 1) + "." + str.substr(1) + "x";
};
// индекс картинки под текущий devicePixelRatio
BaseImageCtrl.prototype.getIndex = function()
{
var scale = AscCommon.AscBrowser.retinaPixelRatio;
var index = 0;
var len = this.support.length;
while (index < len)
{
if (this.support[index] > (scale + 0.01))
break;
++index;
}
--index;
if (index < 0)
return 0;
if (index >= len)
return len - 1;
return index;
};
// стартовые загрузки
BaseImageCtrl.prototype.load = function(type, url, index)
{
this.url = url;
if (index !== undefined)
{
this._loadByIndex(index, url);
return;
}
if (!this.isLoadAllSizes)
{
this._loadIndex();
return;
}
for (var i = 0, len = this.support.length; i < len; i++)
{
this._loadIndex(i);
}
};
BaseImageCtrl.prototype.loadActive = function(url, index)
{
if (index !== undefined)
{
this._loadActiveByIndex(index, url);
return;
}
if (!this.isLoadAllSizes)
{
this._loadActiveIndex();
return;
}
for (var i = 0, len = this.support.length; i < len; i++)
{
this._loadActiveIndex(i);
}
};
BaseImageCtrl.prototype.loadHover = function(url, index)
{
if (index !== undefined)
{
this._loadHoverByIndex(index, url);
return;
}
if (!this.isLoadAllSizes)
{
this._loadHoverByIndex(index, url);
return;
}
for (var i = 0, len = this.support.length; i < len; i++)
{
this._loadHoverByIndex(i, url);
}
};
// берем картинку. если ее нет - то грузим, если не готова - то просто после загрузки - обновляем оверлей
BaseImageCtrl.prototype.get = function(isActive, isHover)
{
if (isActive)
{
let activeImg = this.getActive();
if (activeImg)
return activeImg;
}
if (isHover)
{
let hoverImg = this.getHover();
if (hoverImg)
return hoverImg;
}
var index = this.getIndex();
if (!this.images[index])
{
AscCommon.g_imageControlsStorage.needUpdate();
this._loadIndex(index);
return null;
}
if (!this.images[index].asc_complete)
{
AscCommon.g_imageControlsStorage.needUpdate();
return null;
}
return this.images[index];
};
BaseImageCtrl.prototype.getActive = function()
{
var index = this.getIndex();
if (!this.images_active[index])
{
AscCommon.g_imageControlsStorage.needUpdate();
this._loadActiveIndex(index);
return null;
}
if (!this.images_active[index].asc_complete)
{
AscCommon.g_imageControlsStorage.needUpdate();
return null;
}
return this.images_active[index];
};
BaseImageCtrl.prototype.getHover = function()
{
var index = this.getIndex();
if (!this.images_hover[index])
{
AscCommon.g_imageControlsStorage.needUpdate();
this._loadHoverByIndex(index);
return null;
}
if (!this.images_hover[index].asc_complete)
{
AscCommon.g_imageControlsStorage.needUpdate();
return null;
}
return this.images_hover[index];
};
BaseImageCtrl.prototype._loadImg = function(url)
{
let img = new Image();
img.src = url;
if (img.complete)
{
img.asc_complete = true;
}
else
{
AscCommon.g_imageControlsStorage.updateLater();
img.onload = function()
{
this.asc_complete = true;
AscCommon.g_imageControlsStorage.updateOverlay();
};
img.onerror = function()
{
this.asc_complete = false;
AscCommon.g_imageControlsStorage.updateOverlay();
};
AscCommon.backoffOnErrorImg(img);
}
return img;
};
// загрузка картинки по индексу. если индекса нет - то текущий
BaseImageCtrl.prototype._loadIndex = function(index)
{
if (undefined === index)
index = this.getIndex();
if (!this.images[index])
this.images[index] = this._loadImg(this.baseUrl + "/" + this.url + this.getAddon(this.support[index]) + ".png");
};
BaseImageCtrl.prototype._loadActiveIndex = function(index)
{
if (undefined === index)
index = this.getIndex();
if (!this.images_active[index])
this.images_active[index] = this._loadImg(this.baseUrl + "/" + this.url + "_active" + this.getAddon(this.support[index]) + ".png");
};
BaseImageCtrl.prototype._loadHoverIndex = function(index)
{
if (undefined === index)
index = this.getIndex();
if (!this.images_hover[index])
this.images_hover[index] = this._loadImg(this.baseUrl + "/" + this.url + "_hover" + this.getAddon(this.support[index]) + ".png");
};
BaseImageCtrl.prototype._loadByIndex = function(index, url)
{
if (undefined === index)
index = this.getIndex();
if (!this.images[index])
this.images[index] = this._loadImg(this.baseUrl + url);
};
BaseImageCtrl.prototype._loadActiveByIndex = function(index, url)
{
if (undefined === index)
index = this.getIndex();
if (!this.images_active[index])
this.images_active[index] = this._loadImg(this.baseUrl + url);
};
BaseImageCtrl.prototype._loadHoverByIndex = function(index, url)
{
if (undefined === index)
index = this.getIndex();
if (!this.images_hover[index])
this.images_hover[index] = this._loadImg(this.baseUrl + url);
};
AscCommon.BaseImageCtrl = BaseImageCtrl;
function iconsStr2IconsObj (icons) {
if (typeof icons !== 'string')
return icons;
/*
valid params:
theme-type - {string} theme type (light|dark|common)
theme-name - {string} the name of theme
state - {string} state of icons for different situations (normal|hover|active)
scale - {string} list of avaliable scales (100|125|150|175|200|default|extended)
extension - {string} use it after symbol "." (png|jpeg|svg)
Example: "resources/%theme-type%(light|dark)/icon%state%(normal|hover)%scale%(default).%extension%(png)"
*/
let params_array = {
"theme-name" : { origin : "", values : [""] },
"theme-type" : { origin : "", values : [""] },
"state" : { origin : "", values : ["normal"] },
"scale" : { origin : "", values : [] },
"extension" : { origin : "", values : [] }
};
// For bug in version <= 8.2.0
let initScaleAddon = "";
let param_parse = function(name) {
let posOrigin = icons.indexOf("%" + name + "%");
if (posOrigin === -1)
return;
let pos = posOrigin + name.length + 2;
let pos1 = icons.indexOf("(", pos);
if (pos1 != pos)
return;
let pos2 = icons.indexOf(")", pos1);
params_array[name].origin = icons.substring(posOrigin, pos2 + 1);
params_array[name].values = icons.substring(pos1 + 1, pos2).split("|");
if ("scale" === name && posOrigin > 0 && icons.charCodeAt(posOrigin - 1) == 47)
initScaleAddon = "icon";
};
for (let name in params_array)
param_parse(name);
for (let styleIndex = 0, stylesLen = params_array["scale"].values.length; styleIndex < stylesLen; styleIndex++) {
if ("default" === params_array["scale"].values[styleIndex])
params_array["scale"].values.splice(styleIndex, 1, "100", "125", "150", "175", "200");
}
let rasterExt = "";
let isSvgPresent = false;
for (let extIndex = 0, extsLen = params_array["extension"].values.length; extIndex < extsLen; extIndex++) {
if ("svg" === params_array["extension"].values[extIndex])
isSvgPresent = true;
else
rasterExt = params_array["extension"].values[extIndex];
}
if (isSvgPresent && rasterExt === "")
rasterExt = "svg";
let iconsObject = [];
for (let themeNameIndex = 0, themeNamesLen = params_array["theme-name"].values.length; themeNameIndex < themeNamesLen; themeNameIndex++) {
let themeName = params_array["theme-name"].values[themeNameIndex];
for (let themeTypeIndex = 0, themeTypesLen = params_array["theme-type"].values.length; themeTypeIndex < themeTypesLen; themeTypeIndex++) {
let url = icons;
let themeType = params_array["theme-type"].values[themeTypeIndex];
let obj = {};
if ("" !== themeName)
obj["theme"] = themeName;
if ("" !== themeType)
obj["style"] = themeType;
if ("" != params_array["theme-name"].origin)
url = url.replaceAll(params_array["theme-name"].origin, themeName);
if ("" != params_array["theme-type"].origin)
url = url.replaceAll(params_array["theme-type"].origin, themeType);
let scalesLen = params_array["scale"].values.length;
if (0 == scalesLen) {
params_array["scale"].values.push("100");
scalesLen++;
}
for (let scaleIndex = 0; scaleIndex < scalesLen; scaleIndex++) {
let scaleValue = params_array["scale"].values[scaleIndex];
let isAll = false;
if (scaleValue.length > 0) {
if (scaleValue === "*")
isAll = true;
else if (scaleValue.charAt(scaleValue.length - 1) === "%")
scaleValue = scaleValue.substring(0, scaleValue.length - 1);
} else {
isAll = true;
scaleValue = "*";
}
let addonScale = "";
if (!isAll) {
let intScale = parseInt(scaleValue);
if (intScale !== 100) {
let addon100 = intScale % 100;
addonScale = "@" + ((intScale / 100) >> 0);
if (addon100 !== 0) {
if (0 === (addon100 % 10))
addon100 /= 10;
addonScale += ("." + addon100);
}
addonScale += "x";
}
scaleValue = scaleValue + "%";
}
let urlAll = url;
if (params_array["scale"].origin != "")
urlAll = urlAll.replaceAll(params_array["scale"].origin, initScaleAddon + addonScale);
if (params_array["extension"].origin != "")
urlAll = urlAll.replaceAll(params_array["extension"].origin, (isAll && isSvgPresent) ? "svg" : rasterExt);
obj[scaleValue] = {};
let states = params_array["state"].values;
for (let stateIndex = 0, statesLen = states.length; stateIndex < statesLen; stateIndex++) {
let stateValue = params_array["state"].values[stateIndex];
if (params_array["state"].origin !== "") {
if ("normal" === stateValue) {
let statePos = urlAll.indexOf(params_array["state"].origin);
obj[scaleValue][stateValue] = urlAll.replace(params_array["state"].origin, "");
if (obj[scaleValue][stateValue].charAt(statePos) == "/")
obj[scaleValue][stateValue] = obj[scaleValue][stateValue].substring(0, statePos) + obj[scaleValue][stateValue].substring(statePos + 1);
} else {
obj[scaleValue][stateValue] = urlAll.replace(params_array["state"].origin, "_" + stateValue);
}
} else
obj[scaleValue][stateValue] = urlAll;
}
}
iconsObject.push(obj);
}
}
return iconsObject;
}
AscCommon.IconsStr2IconsObj = iconsStr2IconsObj;
})(window);
/*
OVERLAY ICONS
*/
(function(window, undefined){
/**
* @constructor
* @extends {AscCommon.BaseImageCtrl}
*/
function OverlayRasterIcon()
{
AscCommon.BaseImageCtrl.call(this);
this.baseUrl = "../../../../sdkjs/common/Images/icons";
}
OverlayRasterIcon.prototype = Object.create(AscCommon.BaseImageCtrl.prototype);
OverlayRasterIcon.prototype.constructor = OverlayRasterIcon;
AscCommon.OverlayRasterIcon = OverlayRasterIcon;
AscCommon.OverlayRasterIcons = {};
AscCommon.OverlayRasterIcons.Anchor = new OverlayRasterIcon();
AscCommon.OverlayRasterIcons.Anchor.load(0, "anchor");
})(window);
/*
PLACEHOLDERS
*/
(function(window, undefined){
var AscCommon = window['AscCommon'];
AscCommon.PlaceholderButtonType = {
Image : 0,
ImageUrl : 1,
Chart : 2,
Table : 3,
Video : 4,
Audio : 5,
SmartArt: 6
};
var exportObj = AscCommon.PlaceholderButtonType;
AscCommon["PlaceholderButtonType"] = exportObj;
exportObj["Image"] = exportObj.Image;
exportObj["ImageUrl"] = exportObj.ImageUrl;
exportObj["Chart"] = exportObj.Chart;
exportObj["Table"] = exportObj.Table;
exportObj["Video"] = exportObj.Video;
exportObj["Audio"] = exportObj.Audio;
exportObj["SmartArt"] = exportObj.SmartArt;
AscCommon.PlaceholderButtonState = {
None : 0,
Active : 1,
Over : 2
};
var ButtonSize1x = 42;
var ButtonImageSize1x = 28;
var ButtonBetweenSize1x = 8;
/**
* @constructor
* @extends {AscCommon.BaseImageCtrl}
*/
function PI()
{
AscCommon.BaseImageCtrl.call(this);
this.baseUrl = "../../../../sdkjs/common/Images/placeholders";
}
PI.prototype = Object.create(AscCommon.BaseImageCtrl.prototype);
PI.prototype.constructor = PI;
function PlaceholderIcons()
{
this.images = [];
this.register = function(type, url, support_active)
{
this.images[type] = new PI();
this.images[type].load(type, url);
support_active && this.images[type].loadActive();
};
this.get = function(type)
{
return this.images[type] ? this.images[type].get() : null;
};
this.getActive = function(type)
{
return this.images[type] ? this.images[type].getActive() : null;
};
}
AscCommon.CreateDrawingPlaceholder = function(id, buttons, page, rect, transform, isDisabled)
{
var placeholder = new Placeholder();
placeholder.id = id;
placeholder.buttons = buttons;
placeholder.anchor.page = page;
placeholder.anchor.rect = rect;
placeholder.anchor.transform = transform;
placeholder.isDisabled = isDisabled;
for (var i = 0; i < placeholder.buttons.length; i++)
placeholder.states[i] = AscCommon.PlaceholderButtonState.None;
return placeholder;
};
// объект плейсхордер - может содержать в себе несколько кнопок
// сам решает, где и как рисовать
function Placeholder()
{
this.events = null; // Placeholders
this.buttonSize = ButtonSize1x;
this.buttonBetweenSize = ButtonBetweenSize1x;
this.buttonImageSize = ButtonImageSize1x;
// id button (parent shape id)
this.id = null;
this.api = Asc.editor || editor;
// list of buttons {AscCommon.PlaceholderButtonType}
this.buttons = [];
this.states = []; // states
// position
this.anchor = {
page : -1,
rect : { x : 0, y : 0, w : 0, h : 0 },
transform : null
};
this.isDisabled = false;
}
Placeholder.prototype.getCenterInPixels = function(pixelsRect, pageWidthMM, pageHeightMM)
{
var cx = this.anchor.rect.x + this.anchor.rect.w / 2;
var cy = this.anchor.rect.y + this.anchor.rect.h / 2;
if (this.anchor.transform)
{
var tmpCx = cx;
var tmpCy = cy;
cx = this.anchor.transform.TransformPointX(tmpCx, tmpCy);
cy = this.anchor.transform.TransformPointY(tmpCx, tmpCy);
}
return {
x : (0.5 + pixelsRect.left + cx * (pixelsRect.right - pixelsRect.left) / pageWidthMM) >> 0,
y : (0.5 + pixelsRect.top + cy * (pixelsRect.bottom - pixelsRect.top) / pageHeightMM) >> 0
};
};
// расчет всех ректов кнопок
Placeholder.prototype.getButtonRects = function(pointCenter, scale, isDraw)
{
//координаты ретины - масштабируются при отрисовке
var ButtonSize = this.buttonSize;//AscCommon.AscBrowser.convertToRetinaValue(ButtonSize1x, true);
var ButtonBetweenSize = this.buttonBetweenSize;//AscCommon.AscBrowser.convertToRetinaValue(ButtonBetweenSize1x, true);
if (isDraw)
{
ButtonSize = AscCommon.AscBrowser.convertToRetinaValue(ButtonSize, true);
ButtonBetweenSize = AscCommon.AscBrowser.convertToRetinaValue(ButtonBetweenSize, true);
}
// максимум 2 ряда
var buttonsCount = this.buttons.length;
var countColumn = (buttonsCount < 3) ? buttonsCount : (this.buttons.length + 1) >> 1;
var countColumn2 = buttonsCount - countColumn;
var sizeAllHor = (countColumn * ButtonSize + (countColumn - 1) * ButtonBetweenSize);
var sizeAllHor2 = (countColumn2 * ButtonSize + (countColumn2 - 1) * ButtonBetweenSize);
var xStart = pointCenter.x - (sizeAllHor >> 1);
var yStart = pointCenter.y - (((buttonsCount == countColumn) ? ButtonSize : (2 * ButtonSize + ButtonBetweenSize)) >> 1);
var ret = [];
var x = xStart;
var y = yStart;
var i = 0;
while (i < countColumn)
{
ret.push({x : x, y : y});
x += (ButtonSize + ButtonBetweenSize);
i++;
}
x = xStart + ((sizeAllHor - sizeAllHor2) >> 1);
y = yStart + ButtonSize + ButtonBetweenSize;
while (i < buttonsCount)
{
ret.push({x : x, y : y});
x += (ButtonSize + ButtonBetweenSize);
i++;
}
return ret;
};
Placeholder.prototype.isInside = function(x, y, pixelsRect, pageWidthMM, pageHeightMM, pointMenu)
{
var pointCenter = this.getCenterInPixels(pixelsRect, pageWidthMM, pageHeightMM);
var scale = {
x : (pixelsRect.right - pixelsRect.left) / pageWidthMM,
y : (pixelsRect.bottom - pixelsRect.top) / pageHeightMM
};
var rects = this.getButtonRects(pointCenter, scale);
var ButtonSize = this.buttonSize;//AscCommon.AscBrowser.convertToRetinaValue(ButtonSize1x, true);
var px = (0.5 + pixelsRect.left + x * (pixelsRect.right - pixelsRect.left) / pageWidthMM) >> 0;
var py = (0.5 + pixelsRect.top + y * (pixelsRect.bottom - pixelsRect.top) / pageHeightMM) >> 0;
var rect;
for (var i = 0; i < rects.length; i++)
{
rect = rects[i];
if ((px >= rect.x) && (px <= (rect.x + ButtonSize)) && (py >= rect.y) && (py <= (rect.y + ButtonSize)))
{
if (pointMenu)
{
pointMenu.x = rect.x;
pointMenu.y = rect.y;
}
return i;
}
}
return -1;
};
Placeholder.prototype.recalculateButtonsSize = function (scale) {
const buttonSize = AscCommon.AscBrowser.convertToRetinaValue(ButtonSize1x, true);
const buttonBetweenSize = AscCommon.AscBrowser.convertToRetinaValue(ButtonBetweenSize1x, true);
const buttonsCount = this.buttons.length;
const countColumn = (buttonsCount < 3) ? buttonsCount : (this.buttons.length + 1) >> 1;
const sizeAllHor = (countColumn * buttonSize + (countColumn - 1) * buttonBetweenSize);
let sizeAllVer = buttonsCount > 0 ? buttonSize : 0;
if (buttonsCount > countColumn)
sizeAllVer += (buttonSize + buttonBetweenSize);
const parentW = (this.anchor.rect.w * scale.x) >> 0;
const parentH = (this.anchor.rect.h * scale.y) >> 0;
const widthCoefficient = parentW / (sizeAllHor + (buttonBetweenSize << 1));
const heightCoefficient = parentH / (sizeAllVer + (buttonBetweenSize << 1));
const nScaleCoefficient = Math.min(widthCoefficient, heightCoefficient, 1);
this.buttonSize = (ButtonSize1x * nScaleCoefficient) >> 0;
this.buttonBetweenSize = (ButtonBetweenSize1x * nScaleCoefficient) >> 0;
this.buttonImageSize = (ButtonImageSize1x * nScaleCoefficient) >> 0;
};
Placeholder.prototype.onPointerDown = function(x, y, pixelsRect, pageWidthMM, pageHeightMM)
{
if(this.isDisabled) return false;
let pointMenu = { x : 0, y : 0 };
let indexButton = this.isInside(x, y, pixelsRect, pageWidthMM, pageHeightMM, pointMenu);
if (-1 == indexButton)
return false;
if (this.states[indexButton] == AscCommon.PlaceholderButtonState.Active)
{
this.states[indexButton] = AscCommon.PlaceholderButtonState.Over;
this.events.onUpdateOverlay();
this.events.endUpdateOverlay();
this.events.closeCallback(this.buttons[indexButton], this);
return true;
}
else if (this.events.mapActive[this.buttons[indexButton]])
{
for (var i = 0; i < this.buttons.length; i++)
{
if (indexButton != i)
this.states[i] = AscCommon.PlaceholderButtonState.None;
}
this.states[indexButton] = AscCommon.PlaceholderButtonState.Active;
this.events.onUpdateOverlay();
this.events.endUpdateOverlay();
}
var xCoord = pointMenu.x;
var yCoord = pointMenu.y;
var word_control = this.events.document.m_oWordControl;
switch (this.api.editorId)
{
case AscCommon.c_oEditorId.Word:
if (true === word_control.m_bIsRuler)
{
xCoord += (5 * AscCommon.g_dKoef_mm_to_pix) >> 0;
yCoord += (7 * AscCommon.g_dKoef_mm_to_pix) >> 0;
}
break;
case AscCommon.c_oEditorId.Presentation:
xCoord += ((word_control.m_oMainParent.AbsolutePosition.L + word_control.m_oMainView.AbsolutePosition.L) * AscCommon.g_dKoef_mm_to_pix) >> 0;
yCoord += ((word_control.m_oMainParent.AbsolutePosition.T + word_control.m_oMainView.AbsolutePosition.T) * AscCommon.g_dKoef_mm_to_pix) >> 0;
yCoord += this.buttonSize;
break;
default:
break;
}
this.events.callCallback(this.buttons[indexButton], this, xCoord, yCoord);
return true;
};
Placeholder.prototype.onPointerMove = function(x, y, pixelsRect, pageWidthMM, pageHeightMM, checker)
{
if(this.isDisabled) return false;
var indexButton = this.isInside(x, y, pixelsRect, pageWidthMM, pageHeightMM);
// может в кнопку-то и не попали, но состояние могло смениться => нужно перерисовать интерфейс
var isUpdate = false;
for (var i = 0; i < this.buttons.length; i++)
{
if (i == indexButton)
{
if (this.states[i] == AscCommon.PlaceholderButtonState.None)
{
this.states[i] = AscCommon.PlaceholderButtonState.Over;
isUpdate = true;
}
}
else
{
if (this.states[i] == AscCommon.PlaceholderButtonState.Over)
{
this.states[i] = AscCommon.PlaceholderButtonState.None;
isUpdate = true;
}
}
}
checker.isNeedUpdateOverlay |= isUpdate;
if (this.buttons[indexButton] !== undefined)
{
checker.placeholderType = this.buttons[indexButton];
checker.page = this.anchor.page;
}
return (-1 !== indexButton);
};
Placeholder.prototype.onPointerUp = function(x, y, pixelsRect, pageWidthMM, pageHeightMM)
{
// ничего. нажимаем сразу при down
};
Placeholder.prototype.draw = function(overlay, pixelsRect, pageWidthMM, pageHeightMM)
{
var pointCenter = this.getCenterInPixels(pixelsRect, pageWidthMM, pageHeightMM);
var scale = {
x : (pixelsRect.right - pixelsRect.left) / pageWidthMM,
y : (pixelsRect.bottom - pixelsRect.top) / pageHeightMM
};
this.recalculateButtonsSize(scale);
var rects = this.getButtonRects(pointCenter, scale, true);
if (rects.length != this.buttons.length)
return;
var buttonSize = AscCommon.AscBrowser.convertToRetinaValue(this.buttonSize, true);
var buttonImageSize = AscCommon.AscBrowser.convertToRetinaValue(this.buttonImageSize, true);
var offsetImage = (buttonSize - buttonImageSize) >> 1;
var ctx = overlay.m_oContext;
for (var i = 0; i < this.buttons.length; i++)
{
overlay.CheckPoint(rects[i].x, rects[i].y);
overlay.CheckPoint(rects[i].x + buttonSize, rects[i].y + buttonSize);
var img = (this.states[i] == AscCommon.PlaceholderButtonState.Active) ? this.events.icons.getActive(this.buttons[i]) : this.events.icons.get(this.buttons[i]);
if (img)
{
var oldGlobalAlpha = ctx.globalAlpha;
ctx.globalAlpha = ((this.states[i] == AscCommon.PlaceholderButtonState.None) ? 0.5 : 1);
/* первый вариант
ctx.beginPath();
ctx.fillStyle = "#F1F1F1";
ctx.fillRect(rects[i].x, rects[i].y, ButtonSize, ButtonSize);
ctx.beginPath();
*/
// второй вариант
ctx.beginPath();
ctx.fillStyle = (this.states[i] == AscCommon.PlaceholderButtonState.Active) ? "#7D858C" : "#F1F1F1";
var x = rects[i].x;
var y = rects[i].y;
var r = 4;
ctx.moveTo(x + r, y);
ctx.lineTo(x + buttonSize - r, y);
ctx.quadraticCurveTo(x + buttonSize, y, x + buttonSize, y + r);
ctx.lineTo(x + buttonSize, y + buttonSize - r);
ctx.quadraticCurveTo(x + buttonSize, y + buttonSize, x + buttonSize - r, y + buttonSize);
ctx.lineTo(x + r, y + buttonSize);
ctx.quadraticCurveTo(x, y + buttonSize, x, y + buttonSize - r);
ctx.lineTo(x, y + r);
ctx.quadraticCurveTo(x, y, x + r, y);
ctx.fill();
ctx.beginPath();
ctx.drawImage(img, rects[i].x + offsetImage, rects[i].y + offsetImage, buttonImageSize, buttonImageSize);
ctx.globalAlpha = oldGlobalAlpha;
}
}
};
AscCommon.DrawingPlaceholder = Placeholder;
function Placeholders(drDocument)
{
this.document = drDocument;
this.callbacks = [];
this.objects = [];
this.api = Asc.editor || editor;
this.icons = new PlaceholderIcons();
this.icons.register(AscCommon.PlaceholderButtonType.Image, "image");
this.icons.register(AscCommon.PlaceholderButtonType.ImageUrl, "image_url");
this.icons.register(AscCommon.PlaceholderButtonType.Table, "table", true);
this.icons.register(AscCommon.PlaceholderButtonType.Chart, "chart", true);
this.icons.register(AscCommon.PlaceholderButtonType.Audio, "audio");
this.icons.register(AscCommon.PlaceholderButtonType.Video, "video");
this.icons.register(AscCommon.PlaceholderButtonType.SmartArt, "smartart", true);
// типы, которые поддерживают состояние Active
this.mapActive = [];
this.mapActive[AscCommon.PlaceholderButtonType.Table] = true;
this.mapActive[AscCommon.PlaceholderButtonType.Chart] = true;
this.mapActive[AscCommon.PlaceholderButtonType.SmartArt] = true;
}
Placeholders.prototype.registerCallback = function(type, callback)
{
this.callbacks[type] = callback;
};
Placeholders.prototype.callCallback = function(type, obj, xCoord, yCoord)
{
this.callbacks[type] && this.callbacks[type](obj, xCoord, yCoord);
};
Placeholders.prototype.closeCallback = function(type, obj)
{
this.api.sendEvent("asc_onHidePlaceholderActions");
};
Placeholders.prototype.closeAllActive = function()
{
var isUpdate = false;
for (var i = 0; i < this.objects.length; i++)
{
var obj = this.objects[i];
for (var j = 0; j < obj.states.length; j++)
{
if (obj.states[j] == AscCommon.PlaceholderButtonState.Active)
{
isUpdate = true;
obj.states[j] = AscCommon.PlaceholderButtonState.None;
}
}
}
if (isUpdate)
this.onUpdateOverlay();
};
Placeholders.prototype.draw = function(overlay, page, pixelsRect, pageWidthMM, pageHeightMM)
{
for (var i = 0; i < this.objects.length; i++)
{
if (this.objects[i].anchor.page != page)
continue;
this.objects[i].draw(overlay, pixelsRect, pageWidthMM, pageHeightMM);
}
};
Placeholders.prototype.onPointerDown = function(pos, pixelsRect, pageWidthMM, pageHeightMM)
{
for (var i = 0; i < this.objects.length; i++)
{
if (this.objects[i].anchor.page != pos.Page)
continue;
if (this.objects[i].onPointerDown(pos.X, pos.Y, pixelsRect, pageWidthMM, pageHeightMM))
return true;
}
return false;
};
Placeholders.prototype.onUpdateOverlay = function () {
if (this.api.editorId === AscCommon.c_oEditorId.Spreadsheet) {
const oController = this.api.getGraphicController();
oController.updateOverlay();
} else {
if (this.api.WordControl) {
this.api.WordControl.OnUpdateOverlay();
}
}
};
Placeholders.prototype.endUpdateOverlay = function () {
if (this.api.editorId !== AscCommon.c_oEditorId.Spreadsheet) {
this.api.WordControl.EndUpdateOverlay();
}
};
Placeholders.prototype.updateCursorType = function (nX, nY, nPlaceholder, nPage)
{
if (this.api.editorId !== AscCommon.c_oEditorId.Spreadsheet)
{
this.api.sync_MouseMoveStartCallback();
const oMouseMoveData = new AscCommon.CMouseMoveData();
const oCoords = this.api.getDrawingDocument().ConvertCoordsToCursorWR(nX, nY, nPage);
oMouseMoveData.X_abs = oCoords.X;
oMouseMoveData.Y_abs = oCoords.Y;
oMouseMoveData.Type = Asc.c_oAscMouseMoveDataTypes.Placeholder;
oMouseMoveData.PlaceholderType = nPlaceholder;
this.document.SetCursorType("default", oMouseMoveData);
this.api.sync_MouseMoveEndCallback();
}
};
Placeholders.prototype.onPointerMove = function(pos, pixelsRect, pageWidthMM, pageHeightMM)
{
const oChecker = { isNeedUpdateOverlay : false, placeholderType: null, page: null };
for (let i = 0; i < this.objects.length; i++)
{
if (this.objects[i].anchor.page != pos.Page)
continue;
this.objects[i].onPointerMove(pos.X, pos.Y, pixelsRect, pageWidthMM, pageHeightMM, oChecker);
}
const bIsButton = oChecker.placeholderType !== null;
if (bIsButton)
this.updateCursorType(pos.X, pos.Y, oChecker.placeholderType, oChecker.page);
// обновить оверлей
if (oChecker.isNeedUpdateOverlay)
{
this.onUpdateOverlay();
if (bIsButton)
this.endUpdateOverlay();
}
if (bIsButton)
{
return {placeholderType: oChecker.placeholderType, cursor: "default"};
}
return null;
};
Placeholders.prototype.onPointerUp = function(pos, pixelsRect, pageWidthMM, pageHeightMM)
{
return this.onPointerMove(pos, pixelsRect, pageWidthMM, pageHeightMM);
};
Placeholders.prototype.update = function(objects)
{
if (this.api.isViewMode || this.api.isRestrictionSignatures())
objects = [];
var count = this.objects.length;
var newCount = objects ? objects.length : 0;
if (count != newCount)
return this._onUpdate(objects);
var t1, t2;
for (var i = 0; i < count; i++)
{
if (this.objects[i].id != objects[i].id)
return this._onUpdate(objects);
if (this.objects[i].anchor.page != objects[i].anchor.page)
return this._onUpdate(objects);
t1 = this.objects[i].anchor.rect;
t2 = objects[i].anchor.rect;
if (Math.abs(t1.x - t2.x) > 0.001 || Math.abs(t1.y - t2.y) > 0.001 ||
Math.abs(t1.w - t2.w) > 0.001 || Math.abs(t1.h - t2.h) > 0.001)
return this._onUpdate(objects);
t1 = this.objects[i].anchor.transform;
t2 = objects[i].anchor.transform;
if (!t1 && !t2)
continue;
if ((t1 && !t2) || (!t1 && t2))
return this._onUpdate(objects);
if (Math.abs(t1.sx - t2.sx) > 0.001 || Math.abs(t1.sy - t2.sy) > 0.001 ||
Math.abs(t1.shx - t2.shx) > 0.001 || Math.abs(t1.shy - t2.shy) > 0.001 ||
Math.abs(t1.tx - t2.tx) > 0.001 || Math.abs(t1.ty - t2.ty) > 0.001)
return this._onUpdate(objects);
}
};
Placeholders.prototype._onUpdate = function(objects)
{
this.objects = objects ? objects : [];
for (var i = 0; i < this.objects.length; i++)
{
this.objects[i].events = this;
}
this.onUpdateOverlay();
};
AscCommon.DrawingPlaceholders = Placeholders;
// example use
/*
placeholders.registerCallback(AscCommon.PlaceholderButtonType.Image, function(obj, x, y) {});
this.placeholders.update(
[
AscCommon.CreateDrawingPlaceholder(0, [
AscCommon.PlaceholderButtonType.Image,
AscCommon.PlaceholderButtonType.Video,
AscCommon.PlaceholderButtonType.Audio,
AscCommon.PlaceholderButtonType.Table,
AscCommon.PlaceholderButtonType.Chart
], 0, { x : 10, y : 10, w : 100, h : 100 }, null),
AscCommon.CreateDrawingPlaceholder(0, [AscCommon.PlaceholderButtonType.Image], 0, { x : 100, y : 100, w : 100, h : 100 }, null)
]
);
*/
})(window);
/*
CONTENTCONTROLS
*/
(function(window, undefined){
var AscCommon = window['AscCommon'];
AscCommon.CCButtonType = {
Name : 0,
Toc : 1,
Image : 2,
Combo : 3,
Date : 4,
Signature : 5
};
var exportObj = AscCommon.CCButtonType;
AscCommon["CCButtonType"] = exportObj;
exportObj["Name"] = exportObj.Name;
exportObj["Toc"] = exportObj.Toc;
exportObj["Combo"] = exportObj.Combo;
exportObj["Date"] = exportObj.Date;
exportObj["Signature"] = exportObj.Signature;
AscCommon.ContentControlTrack = {
Hover : 0,
In : 1
};
function getOutlineCC(isActive)
{
var _editor = Asc.editor || editor;
if (_editor && _editor.isDarkMode === true)
return isActive ? "rgba(255, 255, 255, 0.7)" : "rgba(255, 255, 255, 0.23)";
return isActive ? AscCommon.GlobalSkin.FormsContentControlsOutlineActive : AscCommon.GlobalSkin.FormsContentControlsOutlineHover;
}
// показ диалогов в мобильной версии должен быть только по клику
function _sendEventToApi(api, obj, x, y, isclick)
{
if (!api.isMobileVersion || isclick || obj["type"] !== Asc.c_oAscContentControlSpecificType.Picture || !obj["isForm"])
{
api.sendEvent("asc_onShowContentControlsActions", obj, x, y);
return;
}
api.setHandlerOnClick(function(){
api.sendEvent("asc_onShowContentControlsActions", obj, x, y);
});
}
function CCIcons()
{
/**
* @constructor
* @extends {AscCommon.BaseImageCtrl}
*/
function CCI(baseUrl)
{
AscCommon.BaseImageCtrl.call(this);
this.baseUrl = baseUrl ? baseUrl : "../../../../sdkjs/common/Images/content_controls";
}
CCI.prototype = Object.create(AscCommon.BaseImageCtrl.prototype);
CCI.prototype.constructor = CCI;
this.images = [];
this.pluginImages = {};
this.registerIconObj = function(type, images, baseUrl)
{
for (let i = 0; i < images.length; i++)
{
let image = new CCI(baseUrl);
let oCurrentThemeImages = images[i];
let style = oCurrentThemeImages.style || "default";
let theme = oCurrentThemeImages.theme || "default";
delete oCurrentThemeImages.style;
delete oCurrentThemeImages.theme;
let keys = Object.keys(oCurrentThemeImages);
for (let j = 0; j < keys.length; j++)
{
let key = keys[j];
let index = this.calculateIndex(key, image)
let icon = oCurrentThemeImages[keys[j]];
this.registerExternalIcon(image, index,{
type: type,
style: style,
theme: theme,
icon: icon,
});
}
}
};
this.calculateIndex = function (index, image)
{
if (index)
index = index.slice(0, -1); // delete %
index = index/100;
if (typeof index === 'number')
{
for (let p = 0; p < image.support.length; p++)
{
if (image.support[p] === index)
{
return p;
}
}
}
return false;
};
this.registerExternalIcon = function(image, index, data)
{
if (index === false)
return;
let type = data.type; // id of icon
let style = data.style;// type of theme
let theme = data.theme;// name of theme
let icon = data.icon; // {normal_url | active_url | hover_url}
if (image.support[index])
{
image.load(type, icon["normal"], index);
if (icon["active"])
image.loadActive(icon["active"], index);
if (icon["hover"])
image.loadHover(icon["hover"], index);
if (!this.pluginImages[type])
this.pluginImages[type] = {};
if (!this.pluginImages[type][style])
this.pluginImages[type][style] = {};
this.pluginImages[type][style][theme] = image;
}
};
this.register = function(type, url, baseUrl)
{
var image = new CCI(baseUrl);
image.load(type, url);
image.loadActive();
this.images[type] = image;
};
this.registerNoActive = function(type, url, baseUrl)
{
var image = new CCI(baseUrl);
image.load(type, url);
this.images[type] = image;
};
this.getImage = function(type, isActive, isHover)
{
let pluginImage = this.pluginImages[type];
if (pluginImage)
{
let skinType = AscCommon.GlobalSkin.Type;
let skinStyle = AscCommon.GlobalSkin.Name;
if (pluginImage[skinType] && pluginImage[skinType][skinStyle])
{
return pluginImage[skinType][skinStyle].get(isActive, isHover);
}
else if (pluginImage[skinType] && pluginImage[skinType]['default'])
{
return pluginImage[skinType]['default'].get(isActive, isHover);
}
else if (pluginImage['default']['default'])
{
return pluginImage['default']['default'].get(isActive, isHover);
}
}
if (!this.images[type])
return null;
return this.images[type].get(isActive);
};
this.generateComboImages = function()
{
var imageCC = new CCI();
this.images[AscCommon.CCButtonType.Combo] = imageCC;
imageCC.type = AscCommon.CCButtonType.Combo;
var sizes = [20, 25, 30, 35, 40];
var sizes_count = 2 * sizes.length;
for (var i = 0; i < sizes_count; i++)
{
var index = i >> 1;
var isActive = (0x01 === (0x01 & i));
var size = sizes[index];
var image = document.createElement("canvas");
image.width = size;
image.height = size;
var ctx = image.getContext("2d");
var data = ctx.createImageData(size, size);
var px = data.data;
var len = (size >> 1) - 1;
var count = (len + 1) >> 1;
var x = (size - len) >> 1;
var y = (size - count) >> 1;
var color = isActive ? 255 : 0;
while ( len > 0 )
{
var ind = 4 * (size * y + x);
for ( var j = 0; j < len; j++ )
{
px[ind++] = color;
px[ind++] = color;
px[ind++] = color;
px[ind++] = 255;
}
x += 1;
y += 1;
len -= 2;
}
ctx.putImageData(data, 0, 0);
image.asc_complete = true;
if (isActive)
imageCC.images_active[index] = image;
else
imageCC.images[index] = image;
}
};
}
var CONTENT_CONTROL_HEADER_MOVER_W = 15;
var CONTENT_CONTROL_TRACK_H = 20;
function CContentControlTrack(parent, obj, state, geom)
{
if (window["NATIVE_EDITOR_ENJINE"])
return;
// contentControls
this.parent = parent;
// native contentControl
this.base = obj;
this.type = this.base.GetSpecificType();
this.isForm = this.base.IsForm();
this.formInfo = null;
this.state = state;
this.visualState = - 1;
this.isFixedForm = this.base.IsFixedForm();
this.OffsetX = 0;
this.OffsetY = 0;
this.transform = null;
this.invertTransform = null;
this.UpdateTransform();
this.Pos = { X : 0, Y : 0, Page : 0 };
this.ComboRect = null;
this.Buttons = []; // header buttons
this.pluginButtons = [];
this.Name = this.base.GetAlias();
if (this.base.IsBuiltInTableOfContents && this.base.IsBuiltInTableOfContents())
this.Name = AscCommon.translateManager.getValue("Table of Contents");
this.Color = this.base.GetColor();
this.HoverButtonIndex = -2; // -1 => Text, otherwise index in this.Buttons
this.ActiveButtonIndex = -2; // -1 => Text, otherwise index in this.Buttons
this.IsNoButtons = false;
if (this.parent.document.m_oWordControl.m_oApi.isViewMode)
this.IsNoButtons = true;
this.IsFillFormsMode = false;
if (this.parent.document.m_oLogicDocument)
this.IsFillFormsMode = this.parent.document.m_oLogicDocument.IsFillingFormMode();
this.geom = undefined;
this.rects = undefined;
this.paths = undefined;
this.UpdateGeom(geom);
}
CContentControlTrack.prototype.UpdateTransform = function()
{
this.OffsetX = 0;
this.OffsetY = 0;
this.isFixedForm = this.base.IsFixedForm();
this.transform = this.base.Get_ParentTextTransform ? this.base.Get_ParentTextTransform() : null;
if (this.transform && this.transform.IsIdentity())
this.transform = null;
if (this.transform && this.transform.IsIdentity2())
{
this.OffsetX = this.transform.tx;
this.OffsetY = this.transform.ty;
this.transform = null;
}
this.invertTransform = this.transform ? AscCommon.global_MatrixTransformer.Invert(this.transform) : null;
};
CContentControlTrack.prototype.UpdateGeom = function(geom)
{
this.UpdateTransform();
this.geom = geom;
this.rects = undefined;
this.paths = undefined;
if (undefined === geom[0].Points)
this.rects = geom;
else
this.paths = geom;
this.formInfo = null;
this.Pos = { X : 0, Y : 0, Page : 0 };
this.GetPosition();
this.CalculateNameRect();
this.CalculateMoveRect();
this.CalculateButtons();
};
CContentControlTrack.prototype.IsUseMoveRect = function()
{
if (this.IsNoButtons || this.IsFillFormsMode || this.isFixedForm)
return false;
return true;
};
CContentControlTrack.prototype.IsNoUseButtons = function()
{
if (this.IsNoButtons)
return true;
if (this.base && !this.base.CheckOFormUserMaster())
return true;
switch (this.type)
{
case Asc.c_oAscContentControlSpecificType.TOC:
{
if (this.IsFillFormsMode)
return true;
return false;
}
case Asc.c_oAscContentControlSpecificType.Signature:
case Asc.c_oAscContentControlSpecificType.Picture:
case Asc.c_oAscContentControlSpecificType.ComboBox:
case Asc.c_oAscContentControlSpecificType.DropDownList:
case Asc.c_oAscContentControlSpecificType.DateTime:
{
return false;
}
default:
break;
}
return false;
};
// является ли имя кнопкой
CContentControlTrack.prototype.IsNameAdvanced = function()
{
if (this.parent.document.m_oWordControl.m_oApi.isViewMode)
return false;
if (Asc.c_oAscContentControlSpecificType.TOC === this.type)
return true;
return false;
};
CContentControlTrack.prototype.fillText = function(ctx, text, x, y, maxWidth)
{
if (AscCommon.AscBrowser.isMozilla)
ctx.fillText(text, x, y, maxWidth);
else
ctx.fillText(text, x, y);
};
CContentControlTrack.prototype.CalculateNameRectNatural = function()
{
return this.parent.measure(this.Name);
};
CContentControlTrack.prototype.CalculateNameRect = function(koefX, koefY)
{
if (this.Name == "")
return null;
var width = this.parent.measure(this.Name);
width += 6; // 3 + 3
if (this.IsNameAdvanced() && !this.IsNoUseButtons())
{
width += 5;
width += 3;
}
else
{
width += 3;
}
var rect = {
X : this.Pos.X,
Y : this.Pos.Y - CONTENT_CONTROL_TRACK_H / koefY,
W : width / koefX,
H : CONTENT_CONTROL_TRACK_H / koefY
};
if (!this.IsNoUseButtons())
rect.X += CONTENT_CONTROL_HEADER_MOVER_W / koefX;
return rect;
};
// расчет области для переноса
CContentControlTrack.prototype.CalculateMoveRect = function(koefX, koefY, isCheckTrack)
{
if (this.IsNoUseButtons() || this.IsFillFormsMode || this.isFixedForm)
{
if (true !== isCheckTrack)
return null;
var rectEmpty = {
X : this.Pos.X,
Y : this.Pos.Y,
W : 0,
H : CONTENT_CONTROL_TRACK_H / koefY
};
rectEmpty.Y -= rectEmpty.H;
return rectEmpty;
}
var rect = {
X : this.Pos.X,
Y : this.Pos.Y,
W : CONTENT_CONTROL_HEADER_MOVER_W / koefX,
H : CONTENT_CONTROL_TRACK_H / koefY
};
if (this.formInfo && undefined !== this.formInfo.MoveRectH)
{
rect.W = CPolygonCC.prototype.rectMoveWidthPx / koefX;
rect.H = this.formInfo.MoveRectH;
rect.X -= rect.W;
return rect;
}
if (this.Name == "" && this.Buttons.length == 0)
rect.X -= rect.W;
else
rect.Y -= rect.H;
return rect;
};
// генерация кнопок по типу
CContentControlTrack.prototype.CalculateButtons = function()
{
this.Buttons = [];
if (this.IsNoUseButtons())
return;
switch (this.type)
{
case Asc.c_oAscContentControlSpecificType.TOC:
{
this.Buttons.push(AscCommon.CCButtonType.Toc);
break;
}
case Asc.c_oAscContentControlSpecificType.Signature:
{
this.Buttons.push(AscCommon.CCButtonType.Signature);
break;
}
case Asc.c_oAscContentControlSpecificType.Picture:
{
this.Buttons.push(AscCommon.CCButtonType.Image);
break;
}
case Asc.c_oAscContentControlSpecificType.ComboBox:
case Asc.c_oAscContentControlSpecificType.DropDownList:
case Asc.c_oAscContentControlSpecificType.DateTime:
default:
break;
}
this.Buttons = this.Buttons.concat(this.pluginButtons);
};
CContentControlTrack.prototype.CalculateComboRect = function(koefX, koefY)
{
if (this.IsNoUseButtons() || !this.ComboRect)
return null;
var rect = {
X : this.ComboRect.X,
Y : this.ComboRect.Y,
W : CONTENT_CONTROL_TRACK_H / koefX,
H : (this.ComboRect.B - this.ComboRect.Y),
Page : this.ComboRect.Page
};
if (this.formInfo)
{
rect.W = CPolygonCC.prototype.rectComboWidthPx / koefX;
}
return rect;
};
CContentControlTrack.prototype._addToArray = function(arr, x)
{
for (var indexA = arr.length - 1; indexA >= 0; indexA--)
{
if (Math.abs(x - arr[indexA]) < 0.00001)
return;
}
arr.push(x);
};
CContentControlTrack.prototype.GetPosition = function()
{
var eps = 0.00001;
var i, j, count, curRect, curSavedRect;
var arrY = [];
var countY = 0;
var counter2 = 0;
if (this.rects)
{
count = this.rects.length;
for (i = 0; i < count; i++)
{
curRect = this.rects[i];
counter2 = 0;
for (j = 0; j < countY; j++)
{
curSavedRect = arrY[j];
// проверяем Y
if ((0x01 == (0x01 & counter2)) && Math.abs(curSavedRect.Y - curRect.Y) < eps)
{
this._addToArray(curSavedRect.allX, curRect.X);
this._addToArray(curSavedRect.allX, curRect.R);
if (curSavedRect.X > curRect.X)
curSavedRect.X = curRect.X;
if (curSavedRect.R < curRect.R)
curSavedRect.R = curRect.R;
counter2 |= 1;
}
// проверяем B
if ((0x02 == (0x02 & counter2)) && Math.abs(curSavedRect.B - curRect.Y) < eps)
{
this._addToArray(curSavedRect.allX, curRect.X);
this._addToArray(curSavedRect.allX, curRect.R);
if (curSavedRect.X > curRect.X)
curSavedRect.X = curRect.X;
if (curSavedRect.R < curRect.R)
curSavedRect.R = curRect.R;
counter2 |= 2;
}
if (3 == counter2)
break;
}
// добавляем новые
if (0x01 != (0x01 & counter2))
{
arrY.push({ X : curRect.X, R : curRect.R, Y : curRect.Y, Page : curRect.Page, allX : [curRect.X, curRect.R] });
++countY;
}
if ((0x02 != (0x02 & counter2)) && (Math.abs(curRect.B - curRect.Y) > eps))
{
arrY.push({ X : curRect.X, R : curRect.R, Y : curRect.B, Page : curRect.Page, allX : [curRect.X, curRect.R] });
++countY;
}
}
}
if (this.paths)
{
count = this.paths.length;
var k, page;
for (i = 0; i < count; i++)
{
page = this.paths[i].Page;
for (k = 0; k < this.paths[i].Points.length; k++)
{
curRect = this.paths[i].Points[k];
counter2 = 0;
for (j = 0; j < countY; j++)
{
curSavedRect = arrY[j];
// проверяем Y
if (Math.abs(curSavedRect.Y - curRect.Y) < eps)
{
this._addToArray(curSavedRect.allX, curRect.X);
if (curSavedRect.X > curRect.X)
curSavedRect.X = curRect.X;
if (curSavedRect.R < curRect.X)
curSavedRect.R = curRect.X;
counter2 = 1;
}
if (1 == counter2)
break;
}
// добавляем новый
if (1 != counter2)
{
arrY.push({ X : curRect.X, R : curRect.X, Y : curRect.Y, Page : page, allX : [curRect.X] });
++countY;
}
}
}
}
let curPage = this.parent.getCurrentPage();
arrY.sort(function(a, b){
if (curPage === a.Page && curPage !== b.Page)
return -1;
else if (curPage !== a.Page && curPage !== b.Page)
return 1;
else if (a.Page !== b.Page)
return a.Page - b.Page;
return a.Y - b.Y;
});
if (arrY.length > 0)
{
this.Pos.X = arrY[0].X;
this.Pos.Y = arrY[0].Y;
this.Pos.Page = arrY[0].Page;
}
// ComboRect
if (!this.IsNoUseButtons())
{
switch (this.type)
{
case Asc.c_oAscContentControlSpecificType.ComboBox:
case Asc.c_oAscContentControlSpecificType.DropDownList:
case Asc.c_oAscContentControlSpecificType.DateTime:
{
var len = arrY.length;
if (len > 0)
{
this.ComboRect = { X : arrY[len - 1].R, Y : arrY[len - 1].Y, B : arrY[len - 1].Y, Page : arrY[len - 1].Page };
for (i = len - 2; i >= 0; i--)
{
if (this.ComboRect.Page != arrY[i].Page || Math.abs(this.ComboRect.X - arrY[i].R) > eps || arrY[i].allX.length > 2)
break;
}
if (i == (len - 1)) i--;
if (i < 0) i = 0;
if (i >= 0)
this.ComboRect.Y = arrY[i].Y;
}
break;
}
default:
break;
}
}
if (this.isForm)
{
this.formInfo = {};
var _geom, _polygonDrawer;
if (this.rects)
{
_geom = this.rects[0];
_polygonDrawer = new CPolygonCC();
_polygonDrawer.init(this, AscCommon.g_dKoef_mm_to_pix, 0, 1);
_polygonDrawer.moveTo(_geom.R, _geom.Y);
_polygonDrawer.lineTo(_geom.X, _geom.Y);
_polygonDrawer.lineTo(_geom.X, _geom.B);
_polygonDrawer.lineTo(_geom.R, _geom.B);
_polygonDrawer.closePath();
this.formInfo.MoveRectH = _polygonDrawer.rectMove ? _polygonDrawer.rectMove.h : 0;
this.formInfo.bounds = _polygonDrawer.bounds;
}
else if (this.paths)
{
_geom = this.paths[0];
_polygonDrawer = new CPolygonCC();
_polygonDrawer.init(this, AscCommon.g_dKoef_mm_to_pix, 0, 1);
for (var pointIndex = 0, pointCount = _geom.Points.length; pointIndex < pointCount; pointIndex++)
{
_polygonDrawer.lineTo(_geom.Points[pointIndex].X, _geom.Points[pointIndex].Y);
}
_polygonDrawer.closePath();
this.formInfo.MoveRectH = _polygonDrawer.rectMove ? _polygonDrawer.rectMove.h : 0;
this.formInfo.bounds = _polygonDrawer.bounds;
}
}
};
CContentControlTrack.prototype.GetButtonObj = function(indexButton)
{
var button = AscCommon.CCButtonType.Name;
if (indexButton >= 0 && indexButton < this.Buttons.length)
button = this.Buttons[indexButton];
if (indexButton == this.Buttons.length)
{
switch (this.type)
{
case Asc.c_oAscContentControlSpecificType.ComboBox:
case Asc.c_oAscContentControlSpecificType.DropDownList:
{
button = AscCommon.CCButtonType.Combo;
break;
}
case Asc.c_oAscContentControlSpecificType.DateTime:
{
button = AscCommon.CCButtonType.Date;
break;
}
}
}
return new Asc.CButtonData( {
"obj" : this.base,
"type" : this.type,
"button" : button,
"isForm" : this.isForm,
"pr" : this.base.GetContentControlPr ? this.base.GetContentControlPr() : null
});
};
CContentControlTrack.prototype.Copy = function()
{
let newCCTrack = new CContentControlTrack(this.parent, this.base, this.state, this.geom);
newCCTrack.pluginButtons = this.pluginButtons.slice();
newCCTrack.visualState = this.visualState;
return newCCTrack;
};
CContentControlTrack.prototype.isFormFullOneButtonHover = function()
{
return (!this.IsNoUseButtons()
&& this.formInfo
&& (Asc.c_oAscContentControlSpecificType.Picture === this.type || Asc.c_oAscContentControlSpecificType.Signature === this.type));
};
CContentControlTrack.prototype.isHitInMoveRect = function(xPos, yPos, koefX, koefY)
{
let rectMove = this.CalculateMoveRect(koefX, koefY, true);
return (rectMove && rectMove.W > 0.001 && xPos > rectMove.X && xPos < (rectMove.X + rectMove.W) && yPos > rectMove.Y && yPos < (rectMove.Y + rectMove.H))
};
CContentControlTrack.prototype.isHitInNameRect = function(xPos, yPos, koefX, koefY)
{
let rectName = this.IsNameAdvanced() ? this.CalculateNameRect(koefX, koefY) : null;
return (rectName && xPos > rectName.X && xPos < (rectName.X + rectName.W) && yPos > rectName.Y && yPos < (rectName.Y + rectName.H))
};
CContentControlTrack.prototype.isHitInComboRect = function(xPos, yPos, koefX, koefY)
{
let rectCombo = this.CalculateComboRect(koefX, koefY);
return (rectCombo && xPos > rectCombo.X && xPos < (rectCombo.X + rectCombo.W) && yPos > rectCombo.Y && yPos < (rectCombo.Y + rectCombo.H));
};
CContentControlTrack.prototype.getButton = function(xPos, yPos, koefX, koefY)
{
if (!this.Buttons.length)
return null;
var indexButton = -1;
var x, y, w, h;
let resX = 0, resY = 0;
if (this.formInfo)
{
if (this.isFormFullOneButtonHover())
{
x = this.formInfo.bounds.x;
y = this.formInfo.bounds.y;
w = this.formInfo.bounds.w;
h = this.formInfo.bounds.h;
}
else
{
w = CONTENT_CONTROL_TRACK_H / koefX;
h = CONTENT_CONTROL_TRACK_H / koefY;
x = this.formInfo.bounds.x + (this.formInfo.bounds.w - w) / 2;
y = this.formInfo.bounds.y + (this.formInfo.bounds.h - h) / 2;
}
if (xPos > x && xPos < (x + w) && yPos > y && yPos < (y + h))
{
indexButton = 0;
resX = x;
resY = y + h;
}
}
else
{
let rectOrigin = this.CalculateNameRect(koefX, koefY) || this.CalculateMoveRect(koefX, koefY);
if (!rectOrigin)
return null;
x = rectOrigin.X + rectOrigin.W;
y = rectOrigin.Y;
w = CONTENT_CONTROL_TRACK_H / koefX;
h = CONTENT_CONTROL_TRACK_H / koefY;
for (var indexB = 0; indexB < this.Buttons.length; indexB++)
{
if (xPos > x && xPos < (x + w) && yPos > y && yPos < (y + h))
{
resX = x + this.OffsetX;
resY = rectOrigin.Y + rectOrigin.H + this.OffsetY;
indexButton = indexB;
break;
}
x += w;
}
}
if (-1 === indexButton)
return null;
return {
index : indexButton,
x : resX,
y : resY,
button : this.Buttons[indexButton]
};
};
CContentControlTrack.prototype.isEqual = function(track)
{
if (this.base.GetId() !== track.base.GetId())
return false;
if (this.state !== track.state)
return false;
if (this.rects && track.rects)
{
let count1 = this.rects.length;
let count2 = track.rects.length;
if (count1 !== count2)
return false;
for (let j = 0; j < count1; ++j)
{
if (this.rects[j].Page !== track.rects[j].Page
|| Math.abs(this.rects[j].X - track.rects[j].X) > 0.00001
|| Math.abs(this.rects[j].Y - track.rects[j].Y) > 0.00001
|| Math.abs(this.rects[j].R - track.rects[j].R) > 0.00001
|| Math.abs(this.rects[j].B - track.rects[j].B) > 0.00001)
{
return false;
}
}
}
else if (this.path && track.path)
{
let count1 = this.paths.length;
let count2 = track.paths.length;
if (count1 !== count2)
return false;
for (var j = 0; j < count1; j++)
{
if (this.paths[j].Page !== track.paths[j].Page)
return false;
let _points1 = this.paths[j].Points;
let _points2 = track.paths[j].Points;
if (_points1.length !== _points2.length)
return false;
for (var k = 0; k < _points1.length; k++)
{
if (Math.abs(_points1[k].X - _points2[k].X) > 0.00001 || Math.abs(_points1[k].Y - _points2[k].Y) > 0.00001)
return false;
}
}
}
else
{
return false;
}
return true;
};
CContentControlTrack.prototype.addPluginButtons = function(buttons, pluginGuid, baseUrl)
{
if (!this.base || this.base.IsForm())
return 0;
let result = 0;
for (let i = 0; i < buttons.length; ++i)
{
let buttonId = buttons[i]["id"];
if (this.pluginButtons.includes(buttonId))
continue;
this.parent.registerPluginButton(buttons[i], pluginGuid, baseUrl);
this.Buttons.push(buttonId);
this.pluginButtons.push(buttonId);
result += 1;
}
return result;
};
CContentControlTrack.prototype.isPluginButton = function(buttonId)
{
return this.pluginButtons.includes(buttonId);
};
CContentControlTrack.prototype.isPluginButtonActive = function()
{
let index = this.ActiveButtonIndex;
if (index < 0 || index >= this.Buttons.length)
return false;
return this.isPluginButton(this.Buttons[index]);
};
CContentControlTrack.prototype.removePluginButton = function(buttonId)
{
let pos = this.Buttons.indexOf(buttonId);
if (-1 !== pos)
this.Buttons.splice(pos, 1);
pos = this.pluginButtons.indexOf(buttonId);
if (-1 !== pos)
this.pluginButtons.splice(pos, 1);
};
// draw methods
CContentControlTrack.prototype.SetColor = function(ctx)
{
if (this.Color)
{
ctx.strokeStyle = "rgba(" + this.Color.r + ", " + this.Color.g + ", " + this.Color.b + ", 1)";
ctx.fillStyle = "rgba(" + this.Color.r + ", " + this.Color.g + ", " + this.Color.b + ", 0.25)";
}
else
{
ctx.strokeStyle = "#ADADAD";
ctx.fillStyle = "rgba(205, 205, 205, 0.5)";
}
};
function ContentControls(drDocument)
{
this.document = drDocument;
this.icons = new CCIcons();
this.icons.register(AscCommon.CCButtonType.Toc, "toc");
this.icons.register(AscCommon.CCButtonType.Image, "img");
this.icons.registerNoActive(AscCommon.CCButtonType.Signature, "signature");
this.icons.generateComboImages();
this.ContentControlObjects = [];
this.ContentControlObjectsLast = [];
this.ContentControlSmallChangesCheck = { X: 0, Y: 0, Page: 0, Min: 2, IsSmall : true };
this.lastActive = null;
this.lastHover = null;
this.lastInline = null;
this.measures = {};
this.pluginButtons = {};
this.clearAttack = function()
{
this.ContentControlObjects = [];
this.ContentControlObjectsLast = [];
};
this.addPluginButtons = function(pluginButtons)
{
let pluginGuid = pluginButtons["guid"];
let baseUrl = pluginButtons["baseUrl"];
let items = pluginButtons["items"];
let added = 0;
for (let ccId in items)
{
let buttons = items[ccId];
for (let i = 0; i < this.ContentControlObjects.length; i++)
{
let ccTrack = this.ContentControlObjects[i];
if (ccTrack.base.GetId() === ccId)
{
added += ccTrack.addPluginButtons(buttons, pluginGuid, baseUrl);
break;
}
}
}
if (added)
this.updateOverlay();
};
this.registerPluginButton = function(button, pluginGuid, baseUrl)
{
if (!this.pluginButtons[pluginGuid])
this.pluginButtons[pluginGuid] = {};
let buttonId = button["id"];
if (this.pluginButtons[pluginGuid][buttonId])
return;
this.pluginButtons[pluginGuid][buttonId] = true;
let icons = AscCommon.IconsStr2IconsObj(button["icons"]);
this.icons.registerIconObj(button["id"], icons, baseUrl);
};
this.onClickPluginButton = function(buttonId, ccTrack)
{
if (!ccTrack || !ccTrack.base)
return;
window.g_asc_plugins.onPluginEvent2(
"onContentControlButtonClick",
{
"buttonId": buttonId,
"contentControlId": ccTrack.base.GetId()
}
);
};
this.removePluginButtons = function(pluginGuid)
{
if (!this.pluginButtons[pluginGuid])
return;
for (let buttonId in this.pluginButtons[pluginGuid])
{
for (let i = 0, len = this.ContentControlObjects.length; i < len; ++i)
{
let ccTrack = this.ContentControlObjects[i];
if (AscCommon.ContentControlTrack.In === ccTrack.state)
ccTrack.removePluginButton(buttonId);
}
}
delete this.pluginButtons[pluginGuid];
this.updateOverlay();
};
this.getFont = function(koef)
{
if (!koef)
return "11px Helvetica, Arial, sans-serif";
var size = (1 + 2 * 11 / koef) >> 0;
if (size & 1)
return (size >> 1) + ".5px Helvetica, Arial, sans-serif";
return (size >> 1) + "px Helvetica, Arial, sans-serif";
};
this.measure = function(text)
{
if (!this.measures[text])
{
var ctx = this.document.CanvasHitContext;
ctx.font = "11px Helvetica, Arial, sans-serif";
this.measures[text] = ctx.measureText(text).width;
}
return this.measures[text];
};
// сохранение текущих в последние
// вызывается в конце метода DrawContentControlsTrack
this.ContentControlsSaveLast = function()
{
this.ContentControlObjectsLast = [];
for (var i = 0; i < this.ContentControlObjects.length; i++)
{
this.ContentControlObjectsLast.push(this.ContentControlObjects[i].Copy());
}
};
// совпадают ли текущие с последними? (true не совпадают)
// вызывается на onPointerMove, если никаких других причин для обновления интерфейса нет - то
// смотрим, сменилось ли тут чего-то
this.ContentControlsCheckLast = function()
{
let _len1 = this.ContentControlObjects.length;
let _len2 = this.ContentControlObjectsLast.length;
if (_len1 !== _len2)
return true;
for (var i = 0; i < _len1; i++)
{
let _obj1 = this.ContentControlObjects[i];
let _obj2 = this.ContentControlObjectsLast[i];
if (!_obj1.isEqual(_obj2))
return true;
}
return false;
};
this._getContentControlsForTrackIn = function(tracks)
{
let result = {};
for (let i = 0, len = tracks.length; i < len; ++i)
{
if (AscCommon.ContentControlTrack.In === tracks[i].state)
result[tracks[i].base.GetId()] = tracks[i].base;
}
return result;
};
this.sendShowHidePluginEvent = function()
{
let prev = this._getContentControlsForTrackIn(this.lastTracks);
let curr = this._getContentControlsForTrackIn(this.ContentControlObjects);
let hide = [];
for (let id in prev)
{
if (!curr[id])
hide.push(id);
}
let show = [];
for (let id in curr)
{
if (!prev[id])
show.push(id);
}
if (hide.length)
window.g_asc_plugins.onPluginEvent("onHideContentControlTrack", hide);
if (show.length)
window.g_asc_plugins.onPluginEvent("onShowContentControlTrack", show);
};
this.onAttachPluginEvent = function(pluginGuid)
{
let controls = Object.keys(this._getContentControlsForTrackIn(this.ContentControlObjects));
let guids = {};
guids[pluginGuid] = true;
if (controls.length)
window.g_asc_plugins.onPluginEvent2("onShowContentControlTrack", controls, guids);
};
// отрисовка
this.DrawContentControlsTrack = function(overlay)
{
var ctx = overlay.m_oContext;
var _object;
var _pages = this.document.m_arrPages;
var _drawingPage;
var _pageStart = this.document.m_lDrawingFirst;
var _pageEnd = this.document.m_lDrawingEnd;
var _geom;
if (_pageStart < 0)
return;
var _x, _y, _r, _b;
var _koefX = (_pages[_pageStart].drawingPage.right - _pages[_pageStart].drawingPage.left) / _pages[_pageStart].width_mm;
var _koefY = (_pages[_pageStart].drawingPage.bottom - _pages[_pageStart].drawingPage.top) / _pages[_pageStart].height_mm;
var rPR = AscCommon.AscBrowser.retinaPixelRatio;
let arrDraw = [];
for (var nIndexContentControl = 0; nIndexContentControl < this.ContentControlObjects.length; nIndexContentControl++)
{
_object = this.ContentControlObjects[nIndexContentControl];
_object.SetColor(ctx);
ctx.lineWidth = Math.round(rPR);
if (!_object.isForm)
{
if (!_object.transform)
{
if (_object.rects)
{
for (var j = 0; j < _object.rects.length; j++)
{
_geom = _object.rects[j];
if (_geom.Page < _pageStart || _geom.Page > _pageEnd)
continue;
_drawingPage = _pages[_geom.Page].drawingPage;
ctx.beginPath();
_x = (_drawingPage.left + _koefX * (_geom.X + _object.OffsetX)) * rPR;
_y = (_drawingPage.top + _koefY * (_geom.Y + _object.OffsetY)) * rPR;
_r = (_drawingPage.left + _koefX * (_geom.R + _object.OffsetX)) * rPR;
_b = (_drawingPage.top + _koefY * (_geom.B + _object.OffsetY)) * rPR;
overlay.CheckRect(_x, _y, _r - _x, _b - _y);
ctx.rect((_x >> 0) + 0.5 * Math.round(rPR), (_y >> 0) + 0.5 * Math.round(rPR), (_r - _x) >> 0, (_b - _y) >> 0);
if (_object.state == AscCommon.ContentControlTrack.Hover)
ctx.fill();
ctx.stroke();
ctx.beginPath();
}
}
else if (_object.paths)
{
for (var j = 0; j < _object.paths.length; j++)
{
_geom = _object.paths[j];
if (_geom.Page < _pageStart || _geom.Page > _pageEnd)
continue;
_drawingPage = _pages[_geom.Page].drawingPage;
ctx.beginPath();
for (var pointIndex = 0, pointCount = _geom.Points.length; pointIndex < pointCount; pointIndex++)
{
_x = (_drawingPage.left + _koefX * (_geom.Points[pointIndex].X + _object.OffsetX)) * rPR;
_y = (_drawingPage.top + _koefY * (_geom.Points[pointIndex].Y + _object.OffsetY)) * rPR;
overlay.CheckPoint(_x, _y);
_x = (_x >> 0) + 0.5 * Math.round(rPR);
_y = (_y >> 0) + 0.5 * Math.round(rPR);
if (0 == pointCount)
ctx.moveTo(_x, _y);
else
ctx.lineTo(_x, _y);
}
ctx.closePath();
if (_object.state == AscCommon.ContentControlTrack.Hover)
ctx.fill();
ctx.stroke();
ctx.beginPath();
}
}
}
else
{
if (_object.rects)
{
for (var j = 0; j < _object.rects.length; j++)
{
_geom = _object.rects[j];
if (_geom.Page < _pageStart || _geom.Page > _pageEnd)
continue;
_drawingPage = _pages[_geom.Page].drawingPage;
var x1 = _object.transform.TransformPointX(_geom.X, _geom.Y);
var y1 = _object.transform.TransformPointY(_geom.X, _geom.Y);
var x2 = _object.transform.TransformPointX(_geom.R, _geom.Y);
var y2 = _object.transform.TransformPointY(_geom.R, _geom.Y);
var x3 = _object.transform.TransformPointX(_geom.R, _geom.B);
var y3 = _object.transform.TransformPointY(_geom.R, _geom.B);
var x4 = _object.transform.TransformPointX(_geom.X, _geom.B);
var y4 = _object.transform.TransformPointY(_geom.X, _geom.B);
x1 = (_drawingPage.left + _koefX * x1) * rPR;
x2 = (_drawingPage.left + _koefX * x2) * rPR;
x3 = (_drawingPage.left + _koefX * x3) * rPR;
x4 = (_drawingPage.left + _koefX * x4) * rPR;
y1 = (_drawingPage.top + _koefY * y1) * rPR;
y2 = (_drawingPage.top + _koefY * y2) * rPR;
y3 = (_drawingPage.top + _koefY * y3) * rPR;
y4 = (_drawingPage.top + _koefY * y4) * rPR;
ctx.beginPath();
overlay.CheckPoint(x1, y1);
overlay.CheckPoint(x2, y2);
overlay.CheckPoint(x3, y3);
overlay.CheckPoint(x4, y4);
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.lineTo(x3, y3);
ctx.lineTo(x4, y4);
ctx.closePath();
if (_object.state == AscCommon.ContentControlTrack.Hover)
ctx.fill();
ctx.stroke();
ctx.beginPath();
}
}
else if (_object.paths)
{
for (var j = 0; j < _object.paths.length; j++)
{
_geom = _object.paths[j];
if (_geom.Page < _pageStart || _geom.Page > _pageEnd)
continue;
_drawingPage = _pages[_geom.Page].drawingPage;
ctx.beginPath();
for (var pointIndex = 0, pointCount = _geom.Points.length; pointIndex < pointCount; pointIndex++)
{
_x = _object.transform.TransformPointX(_geom.Points[pointIndex].X, _geom.Points[pointIndex].Y);
_y = _object.transform.TransformPointY(_geom.Points[pointIndex].X, _geom.Points[pointIndex].Y);
_x = (_drawingPage.left + _koefX * _x) * rPR;
_y = (_drawingPage.top + _koefY * _y) * rPR;
overlay.CheckPoint(_x, _y);
if (0 == pointCount)
ctx.moveTo(_x, _y);
else
ctx.lineTo(_x, _y);
}
ctx.closePath();
if (_object.state == AscCommon.ContentControlTrack.Hover)
ctx.fill();
ctx.stroke();
ctx.beginPath();
}
}
}
}
else
{
if (_object.rects)
{
for (var j = 0; j < _object.rects.length; j++)
{
_geom = _object.rects[j];
if (_geom.Page < _pageStart || _geom.Page > _pageEnd)
continue;
_drawingPage = _pages[_geom.Page].drawingPage;
var _polygonDrawer = new CPolygonCC();
_polygonDrawer.init(_object, (_koefX + _koefY) / 2, j, _object.rects.length);
_polygonDrawer.moveTo(_geom.R, _geom.Y);
_polygonDrawer.lineTo(_geom.X, _geom.Y);
_polygonDrawer.lineTo(_geom.X, _geom.B);
_polygonDrawer.lineTo(_geom.R, _geom.B);
_polygonDrawer.closePath();
_polygonDrawer.draw(overlay, _object, _drawingPage, _koefX, _koefY, this.icons);
}
}
else if (_object.paths)
{
for (var j = 0; j < _object.paths.length; j++)
{
_geom = _object.paths[j];
if (_geom.Page < _pageStart || _geom.Page > _pageEnd)
continue;
_drawingPage = _pages[_geom.Page].drawingPage;
var _polygonDrawer = new CPolygonCC();
_polygonDrawer.init(_object, (_koefX + _koefY) / 2, j, _object.paths.length);
for (var pointIndex = 0, pointCount = _geom.Points.length; pointIndex < pointCount; pointIndex++)
{
_polygonDrawer.lineTo(_geom.Points[pointIndex].X, _geom.Points[pointIndex].Y);
}
_polygonDrawer.closePath();
_polygonDrawer.draw(overlay, _object, _drawingPage, _koefX, _koefY, this.icons);
}
}
}
if (_object.state == AscCommon.ContentControlTrack.In && !_object.isForm)
{
let cctw = Math.round(CONTENT_CONTROL_TRACK_H * rPR);
// draw header
if (_object.Pos.Page >= _pageStart && _object.Pos.Page <= _pageEnd)
{
_drawingPage = _pages[_object.Pos.Page].drawingPage;
if (!_object.transform)
{
_x = (((_drawingPage.left + _koefX * (_object.Pos.X + _object.OffsetX)) * rPR) >> 0) + 0.5 * Math.round(rPR);
_y = (((_drawingPage.top + _koefY * (_object.Pos.Y + _object.OffsetY)) * rPR) >> 0) + 0.5 * Math.round(rPR);
if (_object.Name != "" || 0 != _object.Buttons.length)
_y -= cctw;
else
_x -= Math.round(CONTENT_CONTROL_HEADER_MOVER_W * rPR);
var widthName = 0;
if (_object.Name != "")
widthName = ((_object.CalculateNameRect(_koefX, _koefY).W * _koefX) * rPR) >> 0;
var widthHeader = (widthName + CONTENT_CONTROL_TRACK_H * _object.Buttons.length * rPR) >> 0 ;
var xText = _x;
if (_object.IsUseMoveRect())
{
widthHeader += Math.round(CONTENT_CONTROL_HEADER_MOVER_W * rPR);
xText += Math.round(CONTENT_CONTROL_HEADER_MOVER_W * rPR);
}
if (0 != widthHeader)
{
// сразу чекаем весь хедер
overlay.CheckRect(_x, _y, widthHeader, cctw);
// рисуем подложку
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsBack;
ctx.rect(_x, _y, widthHeader, cctw);
ctx.fill();
ctx.beginPath();
// draw mover in header
if (_object.IsUseMoveRect())
{
ctx.rect(_x, _y, Math.round(CONTENT_CONTROL_HEADER_MOVER_W * rPR), cctw);
ctx.fillStyle = (1 === _object.visualState) ? AscCommon.GlobalSkin.ContentControlsAnchorActive : AscCommon.GlobalSkin.ContentControlsBack;
ctx.fill();
ctx.beginPath();
var cx = _x - 0.5 * Math.round(rPR) + Math.round(5 * rPR);
var cy = _y - 0.5 * Math.round(rPR) + Math.round(5 * rPR);
var px3 = Math.round(2 * rPR);
var px5 = Math.round(4 * rPR);
var px10 = Math.round(8 * rPR);
var _color = "#ADADAD";
if (0 === _object.visualState || 1 === _object.visualState)
_color = "#444444";
overlay.AddRect(cx, cy, px3, px3);
overlay.AddRect(cx, cy + px5, px3, px3);
overlay.AddRect(cx, cy + px10, px3, px3);
overlay.AddRect(cx + px5, cy, px3, px3);
overlay.AddRect(cx + px5, cy + px5, px3, px3);
overlay.AddRect(cx + px5, cy + px10, px3, px3);
ctx.fillStyle = _color;
ctx.fill();
ctx.beginPath();
}
// draw name
if (_object.Name != "")
{
if (_object.ActiveButtonIndex == -1)
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsActive;
else if (_object.HoverButtonIndex == -1)
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsHover;
else
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsBack;
ctx.rect(xText, _y, widthName, cctw);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = (_object.ActiveButtonIndex == -1) ? AscCommon.GlobalSkin.ContentControlsTextActive : AscCommon.GlobalSkin.ContentControlsText;
ctx.font = Math.round(11 * rPR) + "px Helvetica, Arial, sans-serif";
let _textShift = ctx.direction === "rtl" ? _object.CalculateNameRectNatural() * rPR : 0;
_object.fillText(ctx, _object.Name, xText + Math.round(3 * rPR) + _textShift, _y + cctw - Math.round(6 * rPR), _object.CalculateNameRectNatural() * rPR);
if (_object.IsNameAdvanced() && !_object.IsNoUseButtons())
{
var nY = _y - 0.5 * Math.round(rPR);
nY += Math.round(10 * rPR);
nY -= Math.round(rPR);
var plus = AscCommon.AscBrowser.isCustomScalingAbove2() ? 0.5 * (rPR >> 0): (rPR >> 0);
ctx.lineWidth = Math.round(rPR);
var nX = (xText + widthName - (7 * rPR >> 0)) >> 0;
for (var i = 0; i <= (2 * rPR >> 0); i+=plus)
ctx.rect(nX + i, nY + i, Math.round(rPR), Math.round(rPR));
for (var i = 0; i <= (2 * rPR >> 0); i+=plus)
ctx.rect(nX + Math.round(4 * rPR) - i, nY + i, Math.round(rPR), Math.round(rPR));
ctx.fill();
ctx.beginPath();
}
}
// draw buttons
for (var nIndexB = 0; nIndexB < _object.Buttons.length; nIndexB++)
{
if (_object.Buttons[nIndexB] === AscCommon.CCButtonType.Signature)
continue;
var isFill = false;
if (_object.ActiveButtonIndex == nIndexB)
{
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsActive;
isFill = true;
}
else if (_object.HoverButtonIndex == nIndexB)
{
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsHover;
isFill = true;
}
if (isFill)
{
ctx.rect(xText + widthName + rPR * CONTENT_CONTROL_TRACK_H * nIndexB, _y, cctw, cctw);
ctx.fill();
ctx.beginPath();
}
var image = this.icons.getImage(_object.Buttons[nIndexB], nIndexB == _object.ActiveButtonIndex, nIndexB === _object.HoverButtonIndex);
if (image)
ctx.drawImage(image, (xText + widthName + rPR * CONTENT_CONTROL_TRACK_H * nIndexB) >> 0, _y >> 0, cctw, cctw);
}
// рисуем единую обводку
_object.SetColor(ctx);
ctx.beginPath();
ctx.rect(_x, _y, widthHeader, cctw);
ctx.stroke();
ctx.beginPath();
if (!arrDraw.includes(_object.base.GetId()))
{
arrDraw.push(_object.base.GetId());
}
}
// есть ли комбо-кнопка?
if (_object.ComboRect)
{
_x = (((_drawingPage.left + _koefX * (_object.ComboRect.X + _object.OffsetX)) * rPR) >> 0) + 0.5 * Math.round(rPR);
_y = (((_drawingPage.top + _koefY * (_object.ComboRect.Y + _object.OffsetY)) * rPR) >> 0) + 0.5 * Math.round(rPR);
_b = (((_drawingPage.top + _koefY * (_object.ComboRect.B + _object.OffsetY)) * rPR) >> 0) + 0.5 * Math.round(rPR);
var nIndexB = _object.Buttons.length;
ctx.beginPath();
ctx.rect(_x, _y, cctw, _b - _y);
overlay.CheckRect(_x, _y, cctw, _b - _y);
if (_object.ActiveButtonIndex == nIndexB)
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsActive;
else if (_object.HoverButtonIndex == nIndexB)
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsHover;
else
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsBack;
ctx.fill();
ctx.stroke();
ctx.beginPath();
var image = this.icons.getImage(AscCommon.CCButtonType.Combo, _object.Buttons.length == _object.ActiveButtonIndex);
if (image && Math.round(7 * rPR) < (_b - _y))
ctx.drawImage(image, _x + 0.5 * Math.round(rPR), _y + 1.5 * Math.round(rPR) + ((_b - _y - cctw) >> 1), cctw, cctw);
}
}
else
{
var _ft = _object.transform.CreateDublicate();
var coords = new AscCommon.CMatrix();
coords.sx = _koefX * rPR;
coords.sy = _koefY * rPR;
coords.tx = _drawingPage.left * rPR;
coords.ty = _drawingPage.top * rPR;
global_MatrixTransformer.MultiplyAppend(_ft, coords);
ctx.transform(_ft.sx, _ft.shy, _ft.shx, _ft.sy, _ft.tx, _ft.ty);
var scaleX_15 = CONTENT_CONTROL_HEADER_MOVER_W / _koefX;
var scaleX_20 = CONTENT_CONTROL_TRACK_H / _koefX;
var scaleY_20 = CONTENT_CONTROL_TRACK_H / _koefY;
// check overlay bounds ----------
_x = _object.Pos.X - scaleX_15;
_y = _object.Pos.Y;
if (_object.Name != "" || 0 != _object.Buttons.length)
{
_x = _object.Pos.X;
_y = _object.Pos.Y - scaleY_20;
}
var widthName = 0;
if (_object.Name != "")
widthName = _object.CalculateNameRect(_koefX, _koefY).W;
var widthHeader = widthName + scaleX_20 * _object.Buttons.length;
var xText = _x;
if (_object.IsUseMoveRect())
{
widthHeader += scaleX_15;
xText += scaleX_15;
}
if (widthHeader > 0.001)
{
_r = _x + widthHeader;
_b = _y + scaleY_20;
var x1 = _ft.TransformPointX(_x, _y);
var y1 = _ft.TransformPointY(_x, _y);
var x2 = _ft.TransformPointX(_r, _y);
var y2 = _ft.TransformPointY(_r, _y);
var x3 = _ft.TransformPointX(_r, _b);
var y3 = _ft.TransformPointY(_r, _b);
var x4 = _ft.TransformPointX(_x, _b);
var y4 = _ft.TransformPointY(_x, _b);
x1 = _drawingPage.left + _koefX * x1;
x2 = _drawingPage.left + _koefX * x2;
x3 = _drawingPage.left + _koefX * x3;
x4 = _drawingPage.left + _koefX * x4;
y1 = _drawingPage.top + _koefY * y1;
y2 = _drawingPage.top + _koefY * y2;
y3 = _drawingPage.top + _koefY * y3;
y4 = _drawingPage.top + _koefY * y4;
overlay.CheckPoint(x1, y1);
overlay.CheckPoint(x2, y2);
overlay.CheckPoint(x3, y3);
overlay.CheckPoint(x4, y4);
// --------------------------------
// рисуем подложку
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsBack;
ctx.rect(_x, _y, widthHeader, scaleY_20);
ctx.fill();
ctx.beginPath();
// draw mover
if (_object.IsUseMoveRect())
{
ctx.rect(_x, _y, scaleX_15, scaleY_20);
ctx.fillStyle = (1 === _object.visualState) ? AscCommon.GlobalSkin.ContentControlsAnchorActive : AscCommon.GlobalSkin.ContentControlsBack;
ctx.fill();
ctx.beginPath();
var cx1 = _x + 5 / _koefX;
var cy1 = _y + 5 / _koefY;
var cx2 = _x + 10 / _koefX;
var cy2 = _y + 5 / _koefY;
var cx3 = _x + 5 / _koefX;
var cy3 = _y + 10 / _koefY;
var cx4 = _x + 10 / _koefX;
var cy4 = _y + 10 / _koefY;
var cx5 = _x + 5 / _koefX;
var cy5 = _y + CONTENT_CONTROL_HEADER_MOVER_W / _koefY;
var cx6 = _x + 10 / _koefX;
var cy6 = _y + CONTENT_CONTROL_HEADER_MOVER_W / _koefY;
var rad = 1.5 / _koefX;
overlay.AddEllipse2(cx1, cy1, rad);
overlay.AddEllipse2(cx2, cy2, rad);
overlay.AddEllipse2(cx3, cy3, rad);
overlay.AddEllipse2(cx4, cy4, rad);
overlay.AddEllipse2(cx5, cy5, rad);
overlay.AddEllipse2(cx6, cy6, rad);
var _color1 = "#ADADAD";
if (0 === _object.visualState || 1 === _object.visualState)
_color1 = "#444444";
ctx.fillStyle = _color1;
ctx.fill();
ctx.beginPath();
}
// draw name
if (_object.Name != "")
{
if (_object.ActiveButtonIndex == -1)
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsActive;
else if (_object.HoverButtonIndex == -1)
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsHover;
else
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsBack;
ctx.rect(_x + (_object.IsNoUseButtons() ? 0 : scaleX_15), _y, widthName, scaleY_20);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = (_object.ActiveButtonIndex == -1) ? AscCommon.GlobalSkin.ContentControlsTextActive : AscCommon.GlobalSkin.ContentControlsText;
ctx.font = this.getFont(_koefY);
let _textShift = ctx.direction === "rtl" ? _object.CalculateNameRectNatural() / _koefX : 0;
_object.fillText(ctx, _object.Name, xText + 3 / _koefX + _textShift, _y + (CONTENT_CONTROL_TRACK_H - 6) / _koefY, _object.CalculateNameRectNatural() / _koefX);
if (_object.IsNameAdvanced() && !_object.IsNoUseButtons())
{
var nY = _y + 9 / _koefY;
var nX = xText + widthName - 6 / _koefX;
for (var i = 0; i < 3; i++)
ctx.rect(_x + nX + i / _koefX, nY + i / _koefY, 1 / _koefX, 1 / _koefY);
for (var i = 0; i < 2; i++)
ctx.rect(_x + nX + (4 - i) / _koefX, nY + i / _koefY, 1 / _koefX, 1 / _koefY);
ctx.fill();
ctx.beginPath();
}
}
// draw buttons
for (var nIndexB = 0; nIndexB < _object.Buttons.length; nIndexB++)
{
var isFill = false;
if (_object.ActiveButtonIndex == nIndexB)
{
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsActive;
isFill = true;
}
else if (_object.HoverButtonIndex == nIndexB)
{
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsHover;
isFill = true;
}
if (isFill)
{
ctx.rect(xText + widthName + scaleX_20 * nIndexB, _y, scaleX_20, scaleY_20);
ctx.fill();
ctx.beginPath();
}
var image = this.icons.getImage(_object.Buttons[nIndexB], nIndexB == _object.ActiveButtonIndex);
if (image)
ctx.drawImage(image, xText + widthName + scaleX_20 * nIndexB, _y, scaleX_20, scaleY_20);
}
}
// есть ли комбо-кнопка?
if (_object.ComboRect)
{
_x = _object.ComboRect.X;
_y = _object.ComboRect.Y;
_b = _object.ComboRect.B;
var nIndexB = _object.Buttons.length;
ctx.beginPath();
ctx.rect(_x, _y, scaleX_20, _b - _y);
overlay.CheckRect(_x, _y, scaleX_20, _b - _y);
if (_object.ActiveButtonIndex == nIndexB)
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsActive;
else if (_object.HoverButtonIndex == nIndexB)
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsHover;
else
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsBack;
ctx.fill();
ctx.lineWidth = 1 / _koefY;
ctx.stroke();
ctx.lineWidth = 1;
ctx.beginPath();
var image = this.icons.getImage(AscCommon.CCButtonType.Combo, _object.Buttons.length == _object.ActiveButtonIndex);
var scaleY_7 = 7 / _koefY;
if (image && scaleY_7 < (_b - _y))
ctx.drawImage(image, _x, _y + ((_b - _y - scaleY_20) / 2), scaleX_20, scaleY_20);
}
// рисуем единую обводку
_object.SetColor(ctx);
overlay.SetBaseTransform();
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.lineTo(x3, y3);
ctx.lineTo(x4, y4);
ctx.closePath();
ctx.stroke();
ctx.beginPath();
}
}
}
}
this.ContentControlsSaveLast();
};
this.getCurrentPage = function()
{
return this.document.m_oWordControl && this.document.m_oWordControl.m_oLogicDocument ? this.document.m_oWordControl.m_oLogicDocument.CurPage : 0;
};
this.startCollectTracks = function()
{
// We can have many Track.In and just one Track.Hover
// If we have an inline move, then we hold the current stack of tracks (which ends with track being moved)
this.lastActive = null;
this.lastHover = null;
this.lastInline = null;
this.lastTracks = this.ContentControlObjects.slice();
for (let i = 0; i < this.ContentControlObjects.length; ++i)
{
let ccTrack = this.ContentControlObjects[i];
if (AscCommon.ContentControlTrack.In === ccTrack.state && -2 !== ccTrack.ActiveButtonIndex)
this.lastActive = ccTrack;
if (AscCommon.ContentControlTrack.Hover === ccTrack.state)
this.lastHover = ccTrack;
if (1 === ccTrack.visualState)
{
this.lastInline = ccTrack;
this.ContentControlObjects.length = i + 1;
break;
}
}
if (!this.lastInline)
this.ContentControlObjects.length = 0;
};
this.addTrackIn = function(obj, geom)
{
if (!geom || (Array.isArray(geom) && geom.length === 0) || this.lastInline)
return;
if (this.lastActive && this.lastActive.base && obj && this.lastActive.base.GetId() === obj.GetId())
{
this.lastActive.UpdateGeom(geom);
this.ContentControlObjects.push(this.lastActive);
}
else
{
let lastTrack = this.findTrackInLast(obj);
let newTrack;
if (lastTrack)
{
newTrack = lastTrack.Copy();
newTrack.UpdateGeom(geom);
}
else
{
newTrack = new CContentControlTrack(this, obj, AscCommon.ContentControlTrack.In, geom);
}
this.ContentControlObjects.push(newTrack);
}
};
this.endCollectTracks = function()
{
if (this.lastActive)
{
if (-1 === this.ContentControlObjects.indexOf(this.lastActive))
this.document.m_oWordControl.m_oApi.sendEvent("asc_onHideContentControlsActions");
}
if (this.lastHover)
{
for (let i = 0; i < this.ContentControlObjects.length; ++i)
{
let ccTrack = this.ContentControlObjects[i];
if (AscCommon.ContentControlTrack.In === ccTrack.state
&& this.lastHover.base
&& ccTrack.base
&& this.lastHover.base.GetId() === ccTrack.base.GetId())
{
this.lastHover = null;
break;
}
}
if (this.lastHover)
this.ContentControlObjects.push(this.lastHover);
}
if (!this.lastInline)
this.ContentControlObjects = this.ContentControlObjects.reverse();
this.sendShowHidePluginEvent();
this.lastHover = null;
this.lastActive = null;
this.lastInline = null;
this.lastTracks = [];
};
this.addTrackHover = function(obj, geom)
{
if (!geom || (Array.isArray(geom) && geom.length === 0))
return this.removeTrackHover();
for (let i = 0; i < this.ContentControlObjects.length; ++i)
{
let ccTrack = this.ContentControlObjects[i];
if (ccTrack.state === AscCommon.ContentControlTrack.In && obj.GetId() === ccTrack.base.GetId())
return;
}
for (let i = 0; i < this.ContentControlObjects.length; ++i)
{
let ccTrack = this.ContentControlObjects[i];
if (ccTrack.state === AscCommon.ContentControlTrack.Hover && obj === ccTrack.base)
{
ccTrack.UpdateGeom(geom);
return;
}
}
this.removeTrackHover();
this.ContentControlObjects.push(new CContentControlTrack(this, obj, AscCommon.ContentControlTrack.Hover, geom));
};
this.removeTrackHover = function()
{
for (let i = this.ContentControlObjects.length - 1; i >= 0; --i)
{
if (AscCommon.ContentControlTrack.Hover === this.ContentControlObjects[i].state)
this.ContentControlObjects.splice(i, 1);
}
};
this.findTrackInLast = function(obj)
{
let objId = obj.GetId();
for (let i = 0; i < this.lastTracks.length; ++i)
{
let ccTrack = this.lastTracks[i];
if (ccTrack.state === AscCommon.ContentControlTrack.In
&& ccTrack.base
&& ccTrack.base.GetId() === objId)
return ccTrack;
}
return null;
};
this.checkSmallChanges = function(pos)
{
if (!this.ContentControlSmallChangesCheck.IsSmall)
return;
if (pos.Page != this.ContentControlSmallChangesCheck.Page ||
Math.abs(pos.X - this.ContentControlSmallChangesCheck.X) > this.ContentControlSmallChangesCheck.Min ||
Math.abs(pos.Y - this.ContentControlSmallChangesCheck.Y) > this.ContentControlSmallChangesCheck.Min)
{
this.ContentControlSmallChangesCheck.IsSmall = false;
}
};
this.getInlineMoveTrack = function()
{
for (let i = 0; i < this.ContentControlObjects.length; ++i)
{
if (AscCommon.ContentControlTrack.In === this.ContentControlObjects[i].state && 1 === this.ContentControlObjects[i].visualState)
return this.ContentControlObjects[i];
}
return null;
};
this.checkPointerInButtons = function(pos)
{
for (var i = 0; i < this.ContentControlObjects.length; i++)
{
let _object = this.ContentControlObjects[i];
if (AscCommon.ContentControlTrack.In !== _object.state || _object.Pos.Page !== pos.Page)
continue;
let _pos = this._getTrackRelativePos(pos, _object);
let xPos = _pos.xPos;
let yPos = _pos.yPos;
let koefX = _pos.koefX;
let koefY = _pos.koefY;
if (_object.isHitInMoveRect(xPos, yPos, koefX, koefY))
return true;
if (_object.getButton(xPos, yPos, koefX, koefY))
return true;
if (_object.isHitInNameRect(xPos, yPos, koefX, koefY))
return true;
if (_object.isHitInComboRect(xPos, yPos, koefX, koefY))
return true;
}
return false;
};
this._getTrackRelativePos = function(pos, ccTrack)
{
var _page = this.document.m_arrPages[ccTrack.Pos.Page];
if (!_page)
return null;
var drawingPage = _page.drawingPage;
var koefX = (drawingPage.right - drawingPage.left) / _page.width_mm;
var koefY = (drawingPage.bottom - drawingPage.top) / _page.height_mm;
var xPos = pos.X - ccTrack.OffsetX;
var yPos = pos.Y - ccTrack.OffsetY;
if (ccTrack.transform)
{
var tmp = ccTrack.invertTransform.TransformPointX(xPos, yPos);
yPos = ccTrack.invertTransform.TransformPointY(xPos, yPos);
xPos = tmp;
}
return {
xPos : xPos,
yPos : yPos,
koefX : koefX,
koefY : koefY
}
};
this.onPointerDown = function(pos)
{
var oWordControl = this.document.m_oWordControl;
for (var i = this.ContentControlObjects.length - 1; i >= 0; --i)
{
let _object = this.ContentControlObjects[i];
if (AscCommon.ContentControlTrack.In !== _object.state || _object.Pos.Page !== pos.Page)
continue;
let _pos = this._getTrackRelativePos(pos, _object);
let xPos = _pos.xPos;
let yPos = _pos.yPos;
let koefX = _pos.koefX;
let koefY = _pos.koefY;
if (_object.isHitInMoveRect(xPos, yPos, koefX, koefY))
{
_object.visualState = 1;
this.ContentControlSmallChangesCheck.X = pos.X;
this.ContentControlSmallChangesCheck.Y = pos.Y;
this.ContentControlSmallChangesCheck.Page = pos.Page;
this.ContentControlSmallChangesCheck.IsSmall = true;
this.document.InlineTextTrack = null;
this.document.InlineTextTrackPage = -1;
oWordControl.ShowOverlay();
oWordControl.OnUpdateOverlay();
oWordControl.EndUpdateOverlay();
this.document.LockCursorType("default");
// Важно селектить контрол после всех действий, т.к. селект вызывает перерисовку треков и текущий стек измениться
oWordControl.m_oLogicDocument.SelectContentControl(_object.base.GetId());
return true;
}
if (_object.isHitInNameRect(xPos, yPos, koefX, koefY))
{
if (_object.ActiveButtonIndex == -1)
{
_object.ActiveButtonIndex = -2;
oWordControl.m_oApi.sendEvent("asc_onHideContentControlsActions");
}
else
{
_object.ActiveButtonIndex = -1;
let rectName = _object.CalculateNameRect(koefX, koefY);
var xCC = rectName.X + _object.OffsetX;
var yCC = rectName.Y + rectName.H + _object.OffsetY;
if (_object.transform) {
var tmp = _object.transform.TransformPointX(xCC, yCC);
yCC = _object.transform.TransformPointY(xCC, yCC);
xCC = tmp;
}
var posOnScreen = this.document.ConvertCoordsToCursorWR(xCC, yCC, _object.Pos.Page);
_sendEventToApi(oWordControl.m_oApi, _object.GetButtonObj(-1), posOnScreen.X, posOnScreen.Y);
}
oWordControl.ShowOverlay();
oWordControl.OnUpdateOverlay();
oWordControl.EndUpdateOverlay();
this.document.LockCursorType("default");
return true;
}
let buttonInfo = _object.getButton(xPos, yPos, koefX, koefY);
if (buttonInfo && -1 !== buttonInfo.index)
{
let indexButton = buttonInfo.index;
let xCC = buttonInfo.x;
let yCC = buttonInfo.y;
if (_object.ActiveButtonIndex === indexButton)
{
_object.ActiveButtonIndex = -2;
oWordControl.m_oApi.sendEvent("asc_onHideContentControlsActions");
}
else
{
_object.ActiveButtonIndex = indexButton;
xCC += _object.OffsetX;
yCC += _object.OffsetY;
if (_object.transform)
{
var tmp = _object.transform.TransformPointX(xCC, yCC);
yCC = _object.transform.TransformPointY(xCC, yCC);
xCC = tmp;
}
var posOnScreen = this.document.ConvertCoordsToCursorWR(xCC, yCC, _object.Pos.Page);
let oButtonData = _object.GetButtonObj(indexButton);
if (!_object.isPluginButton(oButtonData.button))
_sendEventToApi(oWordControl.m_oApi, oButtonData, posOnScreen.X, posOnScreen.Y);
}
oWordControl.ShowOverlay();
oWordControl.OnUpdateOverlay();
oWordControl.EndUpdateOverlay();
this.document.LockCursorType("default");
return true;
}
if (_object.isHitInComboRect(xPos, yPos, koefX, koefY))
{
var indexB = _object.Buttons.length;
if (_object.ActiveButtonIndex == indexB)
{
_object.ActiveButtonIndex = -2;
oWordControl.m_oApi.sendEvent("asc_onHideContentControlsActions");
}
else
{
_object.ActiveButtonIndex = indexB;
let rectCombo = _object.CalculateComboRect(koefX, koefY)
var xCC = rectCombo.X + _object.OffsetX + CONTENT_CONTROL_TRACK_H / koefX;
var yCC = rectCombo.Y + rectCombo.H + _object.OffsetY;
if (_object.transform)
{
var tmp = _object.transform.TransformPointX(xCC, yCC);
yCC = _object.transform.TransformPointY(xCC, yCC);
xCC = tmp;
}
var posOnScreen = this.document.ConvertCoordsToCursorWR(xCC, yCC, rectCombo.Page);
_sendEventToApi(oWordControl.m_oApi, _object.GetButtonObj(indexB), posOnScreen.X, posOnScreen.Y);
}
oWordControl.ShowOverlay();
oWordControl.OnUpdateOverlay();
oWordControl.EndUpdateOverlay();
this.document.LockCursorType("default");
return true;
}
}
return false;
};
this.onPointerLeave = function()
{
let updateOverlay = false;
for (var i = 0; i < this.ContentControlObjects.length; i++)
{
let ccTrack = this.ContentControlObjects[i];
if (-2 !== ccTrack.HoverButtonIndex)
{
updateOverlay = true;
ccTrack.HoverButtonIndex = -2;
}
if (-1 !== ccTrack.visualState)
{
updateOverlay = true;
ccTrack.visualState = -1;
}
}
if (updateOverlay)
this.document.m_oWordControl.OnUpdateOverlay();
};
this.onPointerMove = function(pos, isWithoutCoords)
{
var oWordControl = this.document.m_oWordControl;
let updateOverlay = false;
for (let i = 0; i < this.ContentControlObjects.length; i++)
{
let ccTrack = this.ContentControlObjects[i];
if (-2 !== ccTrack.HoverButtonIndex)
{
updateOverlay = true;
ccTrack.HoverButtonIndex = -2;
}
}
for (var i = this.ContentControlObjects.length - 1; i >= 0; --i)
{
let _object = this.ContentControlObjects[i];
if (AscCommon.ContentControlTrack.In !== _object.state
|| pos.Page !== _object.Pos.Page
|| !this.document.m_arrPages[pos.Page])
continue;
if (!_object.IsNoUseButtons() && 1 === _object.visualState)
{
if (pos.Page == this.ContentControlSmallChangesCheck.Page &&
Math.abs(pos.X - this.ContentControlSmallChangesCheck.X) < this.ContentControlSmallChangesCheck.Min &&
Math.abs(pos.Y - this.ContentControlSmallChangesCheck.Y) < this.ContentControlSmallChangesCheck.Min)
{
oWordControl.ShowOverlay();
oWordControl.OnUpdateOverlay();
oWordControl.EndUpdateOverlay();
return true;
}
this.document.InlineTextTrackEnabled = true;
this.ContentControlSmallChangesCheck.IsSmall = false;
this.document.InlineTextTrack = oWordControl.m_oLogicDocument.Get_NearestPos(pos.Page, pos.X, pos.Y);
this.document.InlineTextTrackPage = pos.Page;
oWordControl.ShowOverlay();
oWordControl.OnUpdateOverlay();
oWordControl.EndUpdateOverlay();
return true;
}
if (-1 !== _object.visualState)
{
updateOverlay = true;
_object.visualState = -1;
}
let _pos = this._getTrackRelativePos(pos, _object);
let xPos = _pos.xPos;
let yPos = _pos.yPos;
let koefX = _pos.koefX;
let koefY = _pos.koefY;
if (!_object.IsNoUseButtons())
{
if (_object.isHitInMoveRect(xPos, yPos, koefX, koefY))
{
_object.visualState = 0;
oWordControl.ShowOverlay();
oWordControl.OnUpdateOverlay();
oWordControl.EndUpdateOverlay();
this.document.SetCursorType("default");
oWordControl.m_oApi.sync_MouseMoveStartCallback();
oWordControl.m_oApi.sync_MouseMoveEndCallback();
return true;
}
if (_object.isHitInNameRect(xPos, yPos, koefX, koefY))
{
_object.HoverButtonIndex = -1;
oWordControl.ShowOverlay();
oWordControl.OnUpdateOverlay();
oWordControl.EndUpdateOverlay();
this.document.SetCursorType("default");
oWordControl.m_oApi.sync_MouseMoveStartCallback();
oWordControl.m_oApi.sync_MouseMoveEndCallback();
return true;
}
let buttonInfo = (isWithoutCoords !== true)
? _object.getButton(xPos, yPos, koefX, koefY)
: null;
if (buttonInfo)
{
_object.HoverButtonIndex = buttonInfo.index;
oWordControl.ShowOverlay();
oWordControl.OnUpdateOverlay();
oWordControl.EndUpdateOverlay();
this.document.SetCursorType("default");
oWordControl.m_oApi.sync_MouseMoveStartCallback();
oWordControl.m_oApi.sync_MouseMoveEndCallback();
return true;
}
}
if (_object.isHitInComboRect(xPos, yPos, koefX, koefY))
{
_object.HoverButtonIndex = _object.Buttons.length;
oWordControl.ShowOverlay();
oWordControl.OnUpdateOverlay();
oWordControl.EndUpdateOverlay();
this.document.SetCursorType("default");
oWordControl.m_oApi.sync_MouseMoveStartCallback();
oWordControl.m_oApi.sync_MouseMoveEndCallback();
return true;
}
}
if (updateOverlay)
oWordControl.OnUpdateOverlay();
return false;
};
this.onPointerUp = function(pos)
{
var oldContentControlSmall = this.ContentControlSmallChangesCheck.IsSmall;
this.ContentControlSmallChangesCheck.IsSmall = true;
let updateOverlay = false;
let moveTrack = this.getInlineMoveTrack();
let result;
if (!moveTrack)
{
for (let i = 0; i < this.ContentControlObjects.length; ++i)
{
let ccTrack = this.ContentControlObjects[i];
if (ccTrack.state !== AscCommon.ContentControlTrack.In)
continue;
if (ccTrack.isPluginButtonActive())
{
let _pos = this._getTrackRelativePos(pos, ccTrack);
let buttonInfo = ccTrack.getButton(_pos.xPos, _pos.yPos, _pos.koefX, _pos.koefY);
if (buttonInfo && buttonInfo.index === ccTrack.ActiveButtonIndex)
this.onClickPluginButton(buttonInfo.button, ccTrack);
ccTrack.ActiveButtonIndex = -2;
updateOverlay = true;
}
}
result = false;
}
else
{
moveTrack.visualState = -1;
if (this.document.InlineTextTrackEnabled)
{
if (this.document.InlineTextTrack && !oldContentControlSmall) // значит был MouseMove
{
this.document.InlineTextTrack = this.document.m_oLogicDocument.Get_NearestPos(pos.Page, pos.X, pos.Y);
this.document.m_oLogicDocument.OnContentControlTrackEnd(moveTrack.base.GetId(), this.document.InlineTextTrack, AscCommon.global_keyboardEvent.CtrlKey);
this.document.InlineTextTrackEnabled = false;
this.document.InlineTextTrack = null;
this.document.InlineTextTrackPage = -1;
}
else
{
this.document.InlineTextTrackEnabled = false;
}
}
this.onPointerMove(pos);
result = true;
updateOverlay = true;
}
if (updateOverlay)
this.updateOverlay();
return result;
};
this.updateOverlay = function()
{
let wordControl = this.document.m_oWordControl;
wordControl.ShowOverlay();
wordControl.StartUpdateOverlay();
wordControl.OnUpdateOverlay();
wordControl.EndUpdateOverlay();
};
}
AscCommon.DrawingContentControls = ContentControls;
// по точкам (paths) нужно определить отрезки и точки по порядку, чтобы была возможность делать скругления.
// и по-всякому рисовать якорьки (движение/выпадашку для комбобокса и т.д.)
function isEqualFloat(coord1, coord2)
{
return (Math.abs(coord1 - coord2) < 0.0001) ? true : false;
}
var PointDirection = {
Unitialized : 0,
Up : 1,
Down : 2,
Right : 3,
Left : 4
};
var PointRound = {
Unitialized : 0,
True : 1,
False : 2
};
function CPointCC(x, y)
{
this.x = x;
this.y = y;
this.inDir = PointDirection.Unitialized;
this.outDir = PointDirection.Unitialized;
this.round = PointRound.Unitialized;
}
function CPolygonCC()
{
this.points = [];
this.rectMove = null;
this.rectCombo = null;
this.bounds = null;
this.indexMin = 0;
this.indexMax = 0;
this.roundSizePx = 1;
this.rectMoveWidth = 1;
this.rectComboWidth = 1;
this.roundSize = 1;
this.isClockwise = false;
this.isActive = false;
this.isUseMoveRect = true;
this.isCombobox = false;
this.isImage = false;
this.wideOutlineX = 0;
this.wideOutlineY = 0;
this.koef = 1;
}
CPolygonCC.prototype.rectMoveWidthPx = 13;
CPolygonCC.prototype.rectComboWidthPx = 22;
CPolygonCC.prototype.rectMoveImageMaxH = 30;
CPolygonCC.prototype.nextIndex = function(index, add)
{
if (add === false)
index--;
else
index++;
if (index < 0)
return this.points.length - index;
if (index >= this.points.length)
return index - this.points.length;
return index;
};
CPolygonCC.prototype.widePoint = function(point, x, y)
{
if (x !== 0)
point.x += (x === 1) ? this.wideOutlineX : -this.wideOutlineX;
if (y !== 0)
point.y += (y === 1) ? this.wideOutlineY : -this.wideOutlineY;
};
CPolygonCC.prototype.wideRects = function()
{
if (this.rectMove)
{
this.rectMove.x -= this.wideOutlineX;
this.rectMove.y -= this.wideOutlineY;
this.rectMove.w += this.wideOutlineX;
this.rectMove.h += this.wideOutlineY;
}
if (this.rectCombo)
{
this.rectCombo.w += this.wideOutlineX;
this.rectCombo.h += this.wideOutlineY;
}
};
CPolygonCC.prototype.init = function(object, koef, indexPath, countPaths)
{
switch (object.type)
{
case Asc.c_oAscContentControlSpecificType.ComboBox:
case Asc.c_oAscContentControlSpecificType.DropDownList:
case Asc.c_oAscContentControlSpecificType.DateTime:
{
this.isCombobox = !(object && object.IsNoUseButtons());
break;
}
case Asc.c_oAscContentControlSpecificType.Picture:
{
this.isImage = true;
break;
}
default:
break;
}
if (object.parent.document.m_oWordControl.m_oApi.isViewMode)
{
this.isUseMoveRect = false;
this.isCombobox = false;
}
else if (object.parent.document.m_oLogicDocument && object.parent.document.m_oLogicDocument.IsFillingFormMode())
{
this.isUseMoveRect = false;
}
if (object.isFixedForm)
{
this.isUseMoveRect = false;
}
if (object.state === AscCommon.ContentControlTrack.In)
{
this.isActive = true;
}
if (!this.isActive)
{
this.isUseMoveRect = false;
this.isCombobox = false;
}
if (0 !== indexPath)
this.isUseMoveRect = false;
if (indexPath !== (countPaths - 1))
this.isCombobox = false;
this.roundSizePx = this.isActive ? AscCommon.GlobalSkin.FormsContentControlsOutlineBorderRadiusActive : AscCommon.GlobalSkin.FormsContentControlsOutlineBorderRadiusHover;
this.rectMoveWidth = this.rectMoveWidthPx / koef;
this.rectComboWidth = this.rectComboWidthPx / koef;
this.roundSize = this.roundSizePx / koef;
if (!object.transform)
{
//this.wideOutlineX = 1 / koef;
this.wideOutlineY = 1 / koef;
}
this.koef = koef;
};
CPolygonCC.prototype.moveTo = function(x, y)
{
if (this.points.length > 0)
this.points = [];
this.indexMin = 0;
this.indexMax = 0;
this.points.push(new CPointCC(x, y));
};
CPolygonCC.prototype.lineTo = function(x, y)
{
if (this.points.length == 0)
{
this.moveTo(x, y);
return;
}
var lastPoint = this.points[this.points.length - 1];
var isEqualX = isEqualFloat(lastPoint.x, x);
var isEqualY = isEqualFloat(lastPoint.y, y);
if (isEqualX && isEqualY)
{
// дублируемые не добавляем
return;
}
var firstPoint = this.points[0];
if (isEqualFloat(firstPoint.x, x) && isEqualFloat(firstPoint.y, y))
{
// закроем path на closePath
return;
}
var newPoint = new CPointCC(x, y);
// minimum check
var pointCheck = this.points[this.indexMin];
if (isEqualFloat(pointCheck.y, newPoint.y))
{
if (pointCheck.x > newPoint.x)
this.indexMin = this.points.length;
}
if (pointCheck.y > newPoint.y)
this.indexMin = this.points.length;
// maximum check
pointCheck = this.points[this.indexMax];
if (isEqualFloat(pointCheck.y, newPoint.y))
{
if (pointCheck.x < newPoint.x)
this.indexMax = this.points.length;
}
if (pointCheck.y < newPoint.y)
this.indexMax = this.points.length;
this.points.push(newPoint);
};
CPolygonCC.prototype.closePath = function()
{
this.calcRects();
this.calcDirections();
this.calcRounds();
};
CPolygonCC.prototype.calcRects = function()
{
var pointsLen = this.points.length;
var minPoint = this.points[this.indexMin];
var maxPoint = this.points[this.indexMax];
// определяем bounds
this.bounds = {x : minPoint.x, y : minPoint.y, w : (maxPoint.x - minPoint.x), h : (maxPoint.y - minPoint.y) };
if (this.isUseMoveRect)
{
// определяем первый рект (для перетаскивания) и передвигаем точки
// нужно найти направление, по которому мы шли, так как это экстремум, а проход в один конец, то
// верное направление одно
var direction = -1; // назад
var indexMinFriend = this.nextIndex(this.indexMin);
if (isEqualFloat(minPoint.x, this.points[indexMinFriend].x))
direction = 1;
this.isClockwise = (direction === 1) ? false : true;
// зацикливаем
var indexMinFriend = this.nextIndex(this.indexMin, direction === 1);
var yMax = minPoint.y;
while (isEqualFloat(this.points[indexMinFriend].x, minPoint.x))
{
// точка учавствует в пути - проходная или конечная
this.points[indexMinFriend].x -= this.rectMoveWidth;
if (this.points[indexMinFriend].y > yMax) // по идее всегда так
yMax = this.points[indexMinFriend].y;
if (this.isImage)
{
var yMaxLimit = minPoint.y + this.rectMoveImageMaxH / this.koef;
if (yMax > yMaxLimit)
{
var x1 = this.points[indexMinFriend].x;
var x2 = this.points[indexMinFriend].x + this.rectMoveWidth;
this.points[indexMinFriend].x += this.rectMoveWidth;
this.points.splice(indexMinFriend, 0, new CPointCC(x1, yMaxLimit));
this.points.splice(indexMinFriend + 1, 0, new CPointCC(x2, yMaxLimit));
yMax = yMaxLimit;
break;
}
}
indexMinFriend = this.nextIndex(indexMinFriend, direction === 1);
}
minPoint.x -= this.rectMoveWidth;
this.rectMove = {x: minPoint.x, y: minPoint.y, w: this.rectMoveWidth, h: (yMax - minPoint.y)};
}
if (this.isCombobox)
{
// определяем второй рект (для комбобокса), и передвигаем точки
// нужно найти направление, по которому мы шли, так как это экстремум, а проход в один конец, то
// верное направление одно
direction = -1; // назад
var indexMaxFriend = this.nextIndex(this.indexMax);
if (isEqualFloat(maxPoint.x, this.points[indexMaxFriend].x))
direction = 1;
// зацикливаем
var indexMaxFriend = this.nextIndex(this.indexMax, direction === 1);
var yMin = maxPoint.y;
while (isEqualFloat(this.points[indexMaxFriend].x, maxPoint.x))
{
// точка учавствует в пути - проходная или конечная
this.points[indexMaxFriend].x += this.rectComboWidth;
if (this.points[indexMaxFriend].y < yMin) // по идее всегда так
yMin = this.points[indexMaxFriend].y;
indexMaxFriend = this.nextIndex(indexMaxFriend, direction === 1);
}
this.rectCombo = {x: maxPoint.x, y: yMin, w: this.rectComboWidth, h: (maxPoint.y - yMin)};
maxPoint.x += this.rectComboWidth;
}
};
CPolygonCC.prototype.calcDirections = function()
{
for (var i = 0, len = this.points.length; i < len; i++)
{
var curPoint = this.points[i];
var nextPoint = (i == (len - 1)) ? this.points[0] : this.points[i + 1];
if (isEqualFloat(curPoint.y, nextPoint.y))
{
if (curPoint.x < nextPoint.x)
{
curPoint.outDir = nextPoint.inDir = PointDirection.Right;
}
else
{
curPoint.outDir = nextPoint.inDir = PointDirection.Left;
}
}
else if (isEqualFloat(curPoint.x, nextPoint.x))
{
if (curPoint.y < nextPoint.y)
{
curPoint.outDir = nextPoint.inDir = PointDirection.Down;
}
else
{
curPoint.outDir = nextPoint.inDir = PointDirection.Up;
}
}
}
};
CPolygonCC.prototype.calcRounds = function()
{
for (var i = 0, len = this.points.length; i < len; i++)
{
var curPoint = this.points[i];
var nextPoint = (i == (len - 1)) ? this.points[0] : this.points[i + 1];
// 1) короткая ли линия?
var lineLen = Math.abs(curPoint.x - nextPoint.x) + Math.abs(curPoint.y - nextPoint.y);
if (lineLen < this.roundSize)
{
curPoint.round = nextPoint.round = PointRound.False;
}
// 2) скругляем только внешние углы.
// зависит от направлений и от общего направления обхода
// и тут же сразу 3) расширяем рамку!
if (curPoint.round === PointRound.Unitialized)
{
switch (curPoint.inDir)
{
case PointDirection.Left:
{
switch (curPoint.outDir)
{
case PointDirection.Left:
case PointDirection.Right:
{
curPoint.round = PointRound.False;
break;
}
case PointDirection.Up:
{
if (this.isClockwise)
{
curPoint.round = PointRound.True;
this.widePoint(curPoint, -1, 1);
}
else
{
curPoint.round = PointRound.False;
this.widePoint(curPoint, 1, -1);
}
break;
}
case PointDirection.Down:
{
if (this.isClockwise)
{
curPoint.round = PointRound.False;
this.widePoint(curPoint, 1, 1);
}
else
{
curPoint.round = PointRound.True;
this.widePoint(curPoint, -1, -1);
}
break;
}
default:
break;
}
break;
}
case PointDirection.Right:
{
switch (curPoint.outDir)
{
case PointDirection.Left:
case PointDirection.Right:
{
curPoint.round = PointRound.False;
break;
}
case PointDirection.Up:
{
if (this.isClockwise)
{
curPoint.round = PointRound.False;
this.widePoint(curPoint, -1, -1);
}
else
{
curPoint.round = PointRound.True;
this.widePoint(curPoint, 1, 1);
}
break;
}
case PointDirection.Down:
{
if (this.isClockwise)
{
curPoint.round = PointRound.True;
this.widePoint(curPoint, 1, -1);
}
else
{
curPoint.round = PointRound.False;
this.widePoint(curPoint, -1, 1);
}
break;
}
default:
break;
}
break;
}
case PointDirection.Up:
{
switch (curPoint.outDir)
{
case PointDirection.Left:
{
if (this.isClockwise)
{
curPoint.round = PointRound.False;
this.widePoint(curPoint, -1, 1);
}
else
{
curPoint.round = PointRound.True;
this.widePoint(curPoint, 1, -1);
}
break;
}
case PointDirection.Right:
{
if (this.isClockwise)
{
curPoint.round = PointRound.True;
this.widePoint(curPoint, -1, -1);
}
else
{
curPoint.round = PointRound.False;
this.widePoint(curPoint, 1, 1);
}
break;
}
case PointDirection.Up:
{
curPoint.round = PointRound.False;
this.widePoint(curPoint, this.isClockwise ? -1 : 1, 0);
break;
}
case PointDirection.Down:
{
curPoint.round = PointRound.False;
break;
}
default:
break;
}
break;
}
case PointDirection.Down:
{
switch (curPoint.outDir)
{
case PointDirection.Left:
{
if (this.isClockwise)
{
curPoint.round = PointRound.True;
this.widePoint(curPoint, 1, 1);
}
else
{
curPoint.round = PointRound.False;
this.widePoint(curPoint, -1, -1);
}
break;
}
case PointDirection.Right:
{
if (this.isClockwise)
{
curPoint.round = PointRound.False;
this.widePoint(curPoint, 1, -1);
}
else
{
curPoint.round = PointRound.True;
this.widePoint(curPoint, -1, 1);
}
break;
}
case PointDirection.Up:
{
curPoint.round = PointRound.False;
}
case PointDirection.Down:
{
curPoint.round = PointRound.False;
this.widePoint(curPoint, this.isClockwise ? 1 : -1, 0);
break;
}
default:
break;
}
break;
}
default:
break;
}
}
}
this.wideRects();
};
var const_rad = 0.9142; // (Math.sqrt(2) - 0.5)
CPolygonCC.prototype.draw = function(overlay, object, drPage, koefX, koefY, icons)
{
var ctx = overlay.m_oContext;
var rPR = AscCommon.AscBrowser.retinaPixelRatio;
var indent = 0.5 * Math.round(rPR);
var pointsLen = this.points.length;
if (!object.transform)
{
var point;
var _x, _y;
var countIteration = (0 === this.roundSizePx) ? 1 : 2;
var currentIteration = 0;
if (countIteration > 1 && null === this.rectMove && null === this.rectCombo)
countIteration = 1;
while (true)
{
++currentIteration;
if (currentIteration === countIteration)
{
var _x1, _x2, _y1, _y2, _x3, _y3, _x4, _y4;
var lineH = koefY * object.base.GetBoundingPolygonFirstLineH();
if (this.rectMove)
{
if (this.isImage)
lineH = koefY * this.rectMove.h;
// draw move rect
_x1 = ((drPage.left + koefX * (this.rectMove.x + object.OffsetX)) * rPR) >> 0;
_y1 = ((drPage.top + koefY * (this.rectMove.y + object.OffsetY)) * rPR) >> 0;
_x2 = 1 + ((drPage.left + koefX * (this.rectMove.x + this.rectMove.w + object.OffsetX)) * rPR) >> 0;
_y2 = _y1;
_x3 = _x2;
_y3 = 1 + ((drPage.top + koefY * (this.rectMove.y + this.rectMove.h + object.OffsetY)) * rPR) >> 0;
_x4 = _x1;
_y4 = _y3;
ctx.moveTo(_x1, _y1);
ctx.lineTo(_x2, _y2);
ctx.lineTo(_x3, _y3);
ctx.lineTo(_x4, _y4);
ctx.closePath();
ctx.fill();
ctx.beginPath();
var yCenterPos = ((_y1 + 0.5 * lineH * rPR) >> 0) + indent;
var xCenter = _x1 + this.rectMoveWidthPx / 2 * rPR;
var wCenter = (this.rectMoveWidthPx * rPR / 3 + Math.round(rPR)) >> 0;
xCenter -= wCenter / 2;
xCenter = xCenter >> 0;
xCenter += Math.round(rPR); // lineWidth
if (!this.isActive)
ctx.strokeStyle = AscCommon.GlobalSkin.FormsContentControlsOutlineHover;
else
{
switch (object.visualState)
{
case 0:
ctx.strokeStyle = AscCommon.GlobalSkin.FormsContentControlsOutlineMoverHover;
break;
case 1:
ctx.strokeStyle = AscCommon.GlobalSkin.FormsContentControlsOutlineMoverActive;
break;
default:
ctx.strokeStyle = AscCommon.GlobalSkin.FormsContentControlsOutlineActive;
break;
}
}
ctx.moveTo(xCenter, yCenterPos);
ctx.lineTo(xCenter + wCenter, yCenterPos);
ctx.moveTo(xCenter, yCenterPos - Math.round(2 * rPR));
ctx.lineTo(xCenter + wCenter, yCenterPos - Math.round(2 * rPR));
ctx.moveTo(xCenter, yCenterPos + Math.round(2 * rPR));
ctx.lineTo(xCenter + wCenter, yCenterPos + Math.round(2 * rPR));
ctx.lineWidth = Math.round(rPR);
ctx.stroke();
ctx.beginPath();
}
if (this.rectCombo)
{
// draw combo rect
_x1 = ((drPage.left + koefX * (this.rectCombo.x + object.OffsetX)) * rPR) >> 0;
_y1 = ((drPage.top + koefY * (this.rectCombo.y + object.OffsetY)) * rPR)>> 0;
_x2 = (drPage.left + koefX * (this.rectCombo.x + this.rectCombo.w + object.OffsetX)) * rPR >> 0;
_y2 = _y1;
_x3 = _x2;
_y3 = ((drPage.top + koefY * (this.rectCombo.y + this.rectCombo.h + object.OffsetY)) * rPR) >> 0;
_x4 = _x1;
_y4 = _y3;
ctx.moveTo(_x1, _y1);
ctx.lineTo(_x2, _y2);
ctx.lineTo(_x3, _y3);
ctx.lineTo(_x4, _y4);
ctx.closePath();
var indexButton = object.Buttons.length;
if (object.ActiveButtonIndex === indexButton)
ctx.fillStyle = AscCommon.GlobalSkin.FormsContentControlsMarkersBackgroundActive;
else if (object.HoverButtonIndex === indexButton)
ctx.fillStyle = AscCommon.GlobalSkin.FormsContentControlsMarkersBackgroundHover;
else
ctx.fillStyle = AscCommon.GlobalSkin.FormsContentControlsMarkersBackground;
ctx.fill();
ctx.beginPath();
var image = icons.getImage(AscCommon.CCButtonType.Combo, false);
if (image)
{
var canvas = document.createElement('canvas'),
context = canvas.getContext('2d');
var len = Math.floor(9 * rPR);
var width = Math.round(18 * rPR),
height = Math.round(18 * rPR);
// теперь делаем нечетную длину
if ( 0 == (len & 1) )
len += 1;
var countPart = (len + 1) >> 1,
_data, px,
_x = ((width - len) >> 1),
_y = height - 2 * countPart,
r, g, b;
r = 0;
g = 0;
b = 0;
_data = context.createImageData(width, height);
px = _data.data;
while (len > 0) {
var ind = 4 * (width * _y + _x);
for (var i = 0; i < len; i++) {
px[ind++] = r;
px[ind++] = g;
px[ind++] = b;
px[ind++] = 255;
}
r = r >> 0;
g = g >> 0;
b = b >> 0;
_x += 1;
_y += 1;
len -= 2;
}
var yPos = _y4 - height - 0.5 * (lineH * rPR - height) >> 0;
var xPos = _x1 + (0.5 * (this.rectComboWidthPx * rPR - width) >> 0) + Math.round(rPR);
context.putImageData(_data, 0, 0);
ctx.drawImage(canvas, xPos, yPos);
}
}
// Hover and normal states are rendering in the main context
if (this.isImage && 0 === object.ActiveButtonIndex)
{
_x1 = (drPage.left + koefX * (this.bounds.x + object.OffsetX)) * rPR;
_y1 = (drPage.top + koefY * (this.bounds.y + object.OffsetY)) * rPR;
_x4 = (drPage.left + koefX * (this.bounds.x + this.bounds.w + object.OffsetX)) * rPR;
_y4 = (drPage.top + koefY * (this.bounds.y + this.bounds.h + object.OffsetY)) * rPR;
var imageW = AscCommon.AscBrowser.convertToRetinaValue(CONTENT_CONTROL_TRACK_H, true);
var imageH = AscCommon.AscBrowser.convertToRetinaValue(CONTENT_CONTROL_TRACK_H, true);
var xPos = (_x1 + _x4 - imageW) >> 1;
var yPos = (_y1 + _y4 - imageH) >> 1;
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsActive;
ctx.rect(xPos, yPos, imageW, imageH);
ctx.fill();
ctx.beginPath();
var image = icons.getImage(AscCommon.CCButtonType.Image, true);
if (image)
ctx.drawImage(image, xPos, yPos, imageW, imageH);
}
if (2 === currentIteration)
{
ctx.restore();
}
}
for (var i = 0; i < pointsLen; i++)
{
point = this.points[i];
_x = (drPage.left + koefX * (point.x + object.OffsetX)) * rPR;
_y = (drPage.top + koefY * (point.y + object.OffsetY)) * rPR;
overlay.CheckPoint(_x, _y);
_x = (_x >> 0) + 0.5 * Math.round(rPR);
_y = (_y >> 0) + 0.5 * Math.round(rPR);
if (point.round !== PointRound.True)
{
if (0 === i)
ctx.moveTo(_x, _y);
else
ctx.lineTo(_x, _y);
}
else
{
var x1, y1, x2, y2, xCP, yCP;
var isX = true;
switch (point.inDir)
{
case PointDirection.Left:
{
x1 = _x + this.roundSizePx;
y1 = _y;
break;
}
case PointDirection.Right:
{
x1 = _x - this.roundSizePx;
y1 = _y;
break;
}
case PointDirection.Up:
{
x1 = _x;
y1 = _y + this.roundSizePx;
isX = false;
break;
}
case PointDirection.Down:
{
x1 = _x;
y1 = _y - this.roundSizePx;
isX = false;
break;
}
default:
break;
}
switch (point.outDir)
{
case PointDirection.Left:
{
x2 = _x - this.roundSizePx;
y2 = _y;
break;
}
case PointDirection.Right:
{
x2 = _x + this.roundSizePx;
y2 = _y;
break;
}
case PointDirection.Up:
{
x2 = _x;
y2 = _y - this.roundSizePx;
break;
}
case PointDirection.Down:
{
x2 = _x;
y2 = _y + this.roundSizePx;
break;
}
default:
break;
}
if (isX)
{
xCP = x1 + (x2 - x1) * const_rad;
yCP = y1 + (y2 - y1) * (1 - const_rad);
}
else
{
xCP = x1 + (x2 - x1) * (1 - const_rad);
yCP = y1 + (y2 - y1) * const_rad;
}
if (0 === i)
ctx.moveTo(x1, y1);
else
ctx.lineTo(x1, y1);
ctx.quadraticCurveTo(xCP, yCP, x2, y2);
}
}
ctx.closePath();
if (currentIteration === countIteration)
{
if (!this.isActive)
ctx.strokeStyle = getOutlineCC(false);
else
ctx.strokeStyle = getOutlineCC(true);
ctx.lineWidth = Math.round(rPR);
ctx.stroke();
ctx.beginPath();
break;
}
else
{
ctx.save();
ctx.clip();
ctx.fillStyle = AscCommon.GlobalSkin.FormsContentControlsMarkersBackground;
ctx.beginPath();
}
}
}
else
{
var point;
var _x, _y;
var countIteration = (0 === this.roundSizePx) ? 1 : 2;
var currentIteration = 0;
if (countIteration > 1 && null === this.rectMove && null === this.rectCombo)
countIteration = 1;
var matrix = object.transform;
var coordMatrix = new AscCommon.CMatrix();
coordMatrix.sx = koefX * rPR;
coordMatrix.sy = koefY * rPR;
coordMatrix.tx = drPage.left * rPR;
coordMatrix.ty = drPage.top * rPR;
AscCommon.global_MatrixTransformer.MultiplyPrepend(coordMatrix, matrix);
while (true)
{
++currentIteration;
if (currentIteration === countIteration)
{
ctx.transform(coordMatrix.sx, coordMatrix.shy, coordMatrix.shx, coordMatrix.sy, coordMatrix.tx, coordMatrix.ty);
var lineH = object.base.GetBoundingPolygonFirstLineH();
if (this.rectMove)
{
if (this.isImage)
lineH = this.rectMove.h;
// draw move rect
ctx.moveTo(this.rectMove.x, this.rectMove.y);
ctx.lineTo(this.rectMove.x + this.rectMove.w, this.rectMove.y);
ctx.lineTo(this.rectMove.x + this.rectMove.w, this.rectMove.y + this.rectMove.h);
ctx.lineTo(this.rectMove.x, this.rectMove.y + this.rectMove.h);
ctx.closePath();
ctx.fill();
ctx.beginPath();
var xLine = this.rectMove.x + this.rectMove.w / 3;
var wLine = this.rectMove.w / 3;
var yLine = this.rectMove.y + 0.5 * lineH;
var hLine = 2 / koefY;
if (!this.isActive)
ctx.strokeStyle = AscCommon.GlobalSkin.FormsContentControlsOutlineHover;
else
{
switch (object.visualState)
{
case 0:
ctx.strokeStyle = AscCommon.GlobalSkin.FormsContentControlsOutlineMoverHover;
break;
case 1:
ctx.strokeStyle = AscCommon.GlobalSkin.FormsContentControlsOutlineMoverActive;
break;
default:
ctx.strokeStyle = AscCommon.GlobalSkin.FormsContentControlsOutlineActive;
break;
}
}
ctx.moveTo(xLine, yLine - hLine);
ctx.lineTo(xLine + wLine, yLine - hLine);
ctx.moveTo(xLine, yLine);
ctx.lineTo(xLine + wLine, yLine);
ctx.moveTo(xLine, yLine + hLine);
ctx.lineTo(xLine + wLine, yLine + hLine);
ctx.lineWidth = 1 / koefY;
ctx.stroke();
ctx.beginPath();
}
if (this.rectCombo)
{
// draw combo rect
ctx.moveTo(this.rectCombo.x, this.rectCombo.y);
ctx.lineTo(this.rectCombo.x + this.rectCombo.w, this.rectCombo.y);
ctx.lineTo(this.rectCombo.x + this.rectCombo.w, this.rectCombo.y + this.rectCombo.h);
ctx.lineTo(this.rectCombo.x, this.rectCombo.y + this.rectCombo.h);
ctx.closePath();
var indexButton = object.Buttons.length;
if (object.ActiveButtonIndex === indexButton)
ctx.fillStyle = AscCommon.GlobalSkin.FormsContentControlsMarkersBackgroundActive;
else if (object.HoverButtonIndex === indexButton)
ctx.fillStyle = AscCommon.GlobalSkin.FormsContentControlsMarkersBackgroundHover;
else
ctx.fillStyle = AscCommon.GlobalSkin.FormsContentControlsMarkersBackground;
ctx.fill();
ctx.beginPath();
var image = icons.getImage(AscCommon.CCButtonType.Combo, false);
if (image)
{
var imageW = CONTENT_CONTROL_TRACK_H / koefX; // 1x scale!
var imageH = CONTENT_CONTROL_TRACK_H / koefY;
var yPos = this.rectCombo.y + this.rectCombo.h - imageH - 0.5 * (lineH - imageH);
var xPos = this.rectCombo.x + 0.5 * (this.rectCombo.w - imageW);
ctx.drawImage(image, xPos, yPos, imageW, imageH);
}
}
// Hover and normal states now are rendering in the main context
if (this.isImage && 0 === object.ActiveButtonIndex)
{
var imageW = CONTENT_CONTROL_TRACK_H / koefX; // 1x scale!
var imageH = CONTENT_CONTROL_TRACK_H / koefY;
var xPos = this.bounds.x + (this.bounds.w - imageW) / 2;
var yPos = this.bounds.y + (this.bounds.h - imageH) / 2;
ctx.fillStyle = AscCommon.GlobalSkin.ContentControlsActive;
ctx.rect(xPos, yPos, imageW, imageH);
ctx.fill();
ctx.beginPath();
var image = icons.getImage(AscCommon.CCButtonType.Image, true);
if (image)
ctx.drawImage(image, xPos, yPos, imageW, imageH);
}
overlay.SetBaseTransform();
if (2 === currentIteration)
{
ctx.restore();
}
}
for (var i = 0; i < pointsLen; i++)
{
point = this.points[i];
_x = matrix.TransformPointX(point.x, point.y);
_y = matrix.TransformPointY(point.x, point.y);
_x = (drPage.left + koefX * _x) * rPR;
_y = (drPage.top + koefY * _y) * rPR;
overlay.CheckPoint(_x, _y);
if (point.round !== PointRound.True)
{
if (0 === i)
ctx.moveTo(_x, _y);
else
ctx.lineTo(_x, _y);
}
else
{
var x1, y1, x2, y2, xCP, yCP;
var isX = true;
var roundSizePxTmp = 0; // this.roundSizePx
switch (point.inDir)
{
case PointDirection.Left:
{
x1 = _x + roundSizePxTmp;
y1 = _y;
break;
}
case PointDirection.Right:
{
x1 = _x - roundSizePxTmp;
y1 = _y;
break;
}
case PointDirection.Up:
{
x1 = _x;
y1 = _y + roundSizePxTmp;
isX = false;
break;
}
case PointDirection.Down:
{
x1 = _x;
y1 = _y - roundSizePxTmp;
isX = false;
break;
}
default:
break;
}
switch (point.outDir)
{
case PointDirection.Left:
{
x2 = _x - roundSizePxTmp;
y2 = _y;
break;
}
case PointDirection.Right:
{
x2 = _x + roundSizePxTmp;
y2 = _y;
break;
}
case PointDirection.Up:
{
x2 = _x;
y2 = _y - roundSizePxTmp;
break;
}
case PointDirection.Down:
{
x2 = _x;
y2 = _y + roundSizePxTmp;
break;
}
default:
break;
}
if (isX)
{
xCP = x1 + (x2 - x1) * const_rad;
yCP = y1 + (y2 - y1) * (1 - const_rad);
}
else
{
xCP = x1 + (x2 - x1) * (1 - const_rad);
yCP = y1 + (y2 - y1) * const_rad;
}
if (0 === i)
ctx.moveTo(x1, y1);
else
ctx.lineTo(x1, y1);
ctx.quadraticCurveTo(xCP, yCP, x2, y2);
}
}
ctx.closePath();
if (currentIteration === countIteration)
{
if (!this.isActive)
ctx.strokeStyle = getOutlineCC(false);
else
ctx.strokeStyle = getOutlineCC(true);
ctx.lineWidth = 1;
ctx.stroke();
ctx.beginPath();
break;
}
else
{
ctx.save();
ctx.clip();
ctx.fillStyle = AscCommon.GlobalSkin.FormsContentControlsMarkersBackground;
ctx.beginPath();
}
}
}
};
})(window);