Files
Yajbir Singh f1b860b25c
Some checks failed
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
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* (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);