diff --git a/apps/api/documents/api.js b/apps/api/documents/api.js index b9f069c743..d593008512 100644 --- a/apps/api/documents/api.js +++ b/apps/api/documents/api.js @@ -14,7 +14,7 @@ type: 'desktop or mobile or embedded', width: '100% by default', height: '100% by default', - documentType: 'word' | 'cell' | 'slide' | 'pdf' ,// deprecate 'text' | 'spreadsheet' | 'presentation', + documentType: 'word' | 'cell' | 'slide' | 'pdf' | 'draw' ,// deprecate 'text' | 'spreadsheet' | 'presentation', token: encrypted signature document: { title: 'document title', @@ -466,11 +466,12 @@ 'word': 'docx', 'cell': 'xlsx', 'slide': 'pptx', - 'pdf': 'pdf' + 'pdf': 'pdf', + 'draw': 'vsdx' }, app; if (_config.documentType=='text' || _config.documentType=='spreadsheet' ||_config.documentType=='presentation') - console.warn("The \"documentType\" parameter for the config object must take one of the values word/cell/slide/pdf."); + console.warn("The \"documentType\" parameter for the config object must take one of the values word/cell/slide/pdf/draw."); if (typeof _config.documentType === 'string' && _config.documentType != '') { app = appMap[_config.documentType.toLowerCase()]; @@ -484,7 +485,7 @@ if (typeof _config.document.fileType === 'string' && _config.document.fileType != '') { _config.document.fileType = _config.document.fileType.toLowerCase(); - var type = /^(?:(xls|xlsx|ods|csv|gsheet|xlsm|xlt|xltm|xltx|fods|ots|xlsb|sxc|et|ett)|(pps|ppsx|ppt|pptx|odp|gslides|pot|potm|potx|ppsm|pptm|fodp|otp|sxi|dps|dpt)|(pdf|djvu|xps|oxps)|(doc|docx|odt|gdoc|txt|rtf|mht|htm|html|mhtml|epub|docm|dot|dotm|dotx|fodt|ott|fb2|xml|oform|docxf|sxw|stw|wps|wpt))$/ + var type = /^(?:(xls|xlsx|ods|csv|gsheet|xlsm|xlt|xltm|xltx|fods|ots|xlsb|sxc|et|ett)|(pps|ppsx|ppt|pptx|odp|gslides|pot|potm|potx|ppsm|pptm|fodp|otp|sxi|dps|dpt)|(pdf|djvu|xps|oxps)|(doc|docx|odt|gdoc|txt|rtf|mht|htm|html|mhtml|epub|docm|dot|dotm|dotx|fodt|ott|fb2|xml|oform|docxf|sxw|stw|wps|wpt)|(vsdx))$/ .exec(_config.document.fileType); if (!type) { window.alert("The \"document.fileType\" parameter for the config object is invalid. Please correct it."); @@ -493,7 +494,8 @@ if (typeof type[1] === 'string') _config.documentType = 'cell'; else if (typeof type[2] === 'string') _config.documentType = 'slide'; else if (typeof type[3] === 'string') _config.documentType = 'pdf'; else - if (typeof type[4] === 'string') _config.documentType = 'word'; + if (typeof type[4] === 'string') _config.documentType = 'word'; else + if (typeof type[5] === 'string') _config.documentType = 'draw'; } } @@ -1019,6 +1021,7 @@ 'cell': 'spreadsheeteditor', 'slide': 'presentationeditor', 'pdf': 'pdfeditor', + 'draw': 'visioeditor', 'common': 'common' }, appType = 'word', @@ -1027,7 +1030,7 @@ isForm = false; if (config.document) { if (typeof config.document.fileType === 'string') - type = /^(?:(pdf)|(djvu|xps|oxps)|(xls|xlsx|ods|csv|xlst|xlsy|gsheet|xlsm|xlt|xltm|xltx|fods|ots|xlsb)|(pps|ppsx|ppt|pptx|odp|pptt|ppty|gslides|pot|potm|potx|ppsm|pptm|fodp|otp)|(oform|docxf))$/ + type = /^(?:(pdf)|(djvu|xps|oxps)|(xls|xlsx|ods|csv|xlst|xlsy|gsheet|xlsm|xlt|xltm|xltx|fods|ots|xlsb)|(pps|ppsx|ppt|pptx|odp|pptt|ppty|gslides|pot|potm|potx|ppsm|pptm|fodp|otp)|(oform|docxf)|(vsdx))$/ .exec(config.document.fileType); if (config.document.permissions) @@ -1049,7 +1052,8 @@ appType = config.documentType.toLowerCase(); else { if (type && typeof type[3] === 'string') appType = 'cell'; else - if (type && typeof type[4] === 'string') appType = 'slide'; + if (type && typeof type[4] === 'string') appType = 'slide'; else + if (type && typeof type[6] === 'string') appType = 'draw'; } } if (!(config.editorConfig && config.editorConfig.shardkey && config.document && config.editorConfig.shardkey!==config.document.key)) diff --git a/apps/common/main/lib/controller/Desktop.js b/apps/common/main/lib/controller/Desktop.js index 4e2ea068d0..f9ed9b8894 100644 --- a/apps/common/main/lib/controller/Desktop.js +++ b/apps/common/main/lib/controller/Desktop.js @@ -40,7 +40,7 @@ define([ ], function () { 'use strict'; - var webapp = window.DE || window.PE || window.SSE || window.PDFE; + var webapp = window.DE || window.PE || window.SSE || window.PDFE || window.VE; var features = Object.assign({ version: '{{PRODUCT_VERSION}}', eventloading: true, @@ -296,7 +296,8 @@ define([ if ( !!titlebuttons.quickprint ) { const var_name = window.SSE ? 'sse-settings-quick-print-button' : window.PE ? 'pe-settings-quick-print-button' : - window.PDFE ? 'pdfe-settings-quick-print-button' : 'de-settings-quick-print-button'; + window.PDFE ? 'pdfe-settings-quick-print-button' : + window.VE ? 've-settings-quick-print-button' : 'de-settings-quick-print-button'; const is_btn_visible = Common.localStorage.getBool(var_name, false); if ( titlebuttons.quickprint.visible != is_btn_visible ) { @@ -617,7 +618,7 @@ define([ menu.hide(); } else if ( action == 'create:fromtemplate' ) { - native.execCommand('create:new', 'template:' + (!!window.SSE ? 'cell' : !!window.PE ? 'slide' : !!window.PDFE ? 'form' : + native.execCommand('create:new', 'template:' + (!!window.SSE ? 'cell' : !!window.PE ? 'slide' : !!window.VE ? 'draw' : !!window.PDFE ? 'form' : window.PDFE || config.isPDFForm ? 'form' : 'word')); menu.hide(); } @@ -651,7 +652,7 @@ define([ } else if ( opts == 'create:new' ) { if (config.createUrl == 'desktop://create.new') { - native.execCommand("create:new", !!window.SSE ? 'cell' : !!window.PE ? 'slide' : + native.execCommand("create:new", !!window.SSE ? 'cell' : !!window.PE ? 'slide' :!!window.VE ? 'draw' : window.PDFE || config.isPDFForm ? 'form' : 'word'); return true; } @@ -693,7 +694,8 @@ define([ if ( !!nativevars && nativevars.helpUrl ) { var webapp = window.SSE ? 'spreadsheeteditor' : window.PE ? 'presentationeditor' : - window.PDFE ? 'pdfeditor' : 'documenteditor'; + window.PDFE ? 'pdfeditor' : + window.VE ? 'visioeditor' : 'documenteditor'; return nativevars.helpUrl + '/' + webapp + '/main/resources/help'; } diff --git a/apps/common/main/lib/controller/FocusManager.js b/apps/common/main/lib/controller/FocusManager.js index b80b769453..4066eecf9f 100644 --- a/apps/common/main/lib/controller/FocusManager.js +++ b/apps/common/main/lib/controller/FocusManager.js @@ -65,9 +65,9 @@ Common.UI.FocusManager = new(function() { item.selector = '.listview'; else if (field instanceof Common.UI.CheckBox) item.selector = '.checkbox-indeterminate'; - else if (field instanceof Common.UI.RadioBox) + else if (Common.UI.RadioBox && field instanceof Common.UI.RadioBox) item.selector = '.radiobox'; - else if (field instanceof Common.UI.TreeView) + else if (Common.UI.TreeView && field instanceof Common.UI.TreeView) item.selector = '.treeview'; else if (field instanceof Common.UI.Button) item.selector = field.split ? '.btn-group' : 'button'; diff --git a/apps/common/main/lib/controller/LaunchController.js b/apps/common/main/lib/controller/LaunchController.js index a6c0f40b65..47f15a1440 100644 --- a/apps/common/main/lib/controller/LaunchController.js +++ b/apps/common/main/lib/controller/LaunchController.js @@ -46,7 +46,7 @@ define([ const load_scripts = function () { const me = this; - const app = window.DE || window.PE || window.SSE || window.PDFE; + const app = window.DE || window.PE || window.SSE || window.PDFE || window.VE; !app.postLaunchScripts && (app.postLaunchScripts = []); // console.log('on_app_ready', app.postLaunchScripts); diff --git a/apps/common/main/lib/controller/Plugins.js b/apps/common/main/lib/controller/Plugins.js index 8a2ad38740..225c8fdbac 100644 --- a/apps/common/main/lib/controller/Plugins.js +++ b/apps/common/main/lib/controller/Plugins.js @@ -129,7 +129,7 @@ define([ loadConfig: function(data) { var me = this; me.configPlugins.config = data.config.plugins; - me.editor = !!window.PDFE ? 'pdf' : !!window.DE ? 'word' : !!window.PE ? 'slide' : 'cell'; + me.editor = !!window.PDFE ? 'pdf' : !!window.DE ? 'word' : !!window.PE ? 'slide' : !!window.VE ? 'draw' : 'cell'; me.isPDFEditor = !!window.PDFE; }, diff --git a/apps/common/main/lib/controller/ScreenReaderFocus.js b/apps/common/main/lib/controller/ScreenReaderFocus.js index ee7b3caf5a..16964f629d 100644 --- a/apps/common/main/lib/controller/ScreenReaderFocus.js +++ b/apps/common/main/lib/controller/ScreenReaderFocus.js @@ -266,7 +266,7 @@ Common.UI.ScreenReaderFocusManager = new(function() { if (Common.Utils.isIE || Common.UI.isMac && Common.Utils.isGecko) // turn off hints on IE and FireFox (shortcut F6 selects link in address bar) return; _api = api; - _app = window.DE || window.PE || window.SSE || window.PDFE; + _app = window.DE || window.PE || window.SSE || window.PDFE || window.VE; _isDocReady = true; var filter = Common.localStorage.getKeysFilter(); diff --git a/apps/common/main/lib/util/utils.js b/apps/common/main/lib/util/utils.js index 87e51aeebd..85940ecd76 100644 --- a/apps/common/main/lib/util/utils.js +++ b/apps/common/main/lib/util/utils.js @@ -914,7 +914,7 @@ define([], function () { Common.Utils.showBrowserRestriction = function () { if (document.getElementsByClassName && document.getElementsByClassName('app-error-panel').length > 0) return; - var editor = (window.DE ? 'Document' : window.SSE ? 'Spreadsheet' : window.PE ? 'Presentation' : window.PDFE ? 'PDF' : 'that'); + var editor = (window.DE ? 'Document' : window.SSE ? 'Spreadsheet' : window.PE ? 'Presentation' : window.PDFE ? 'PDF' : window.VE ? 'Visio' : 'that'); var newDiv = document.createElement("div"); newDiv.innerHTML = '
' + '
' + @@ -1206,7 +1206,7 @@ define([], function () { if (opts.disablefunc) opts.disablefunc(true); - var app = window.DE || window.PE || window.SSE || window.PDFE; + var app = window.DE || window.PE || window.SSE || window.PDFE || window.VE; Common.UI.warning({ msg: Common.Locale.get("warnFileLocked", { diff --git a/apps/common/main/lib/view/DocumentHolderExt.js b/apps/common/main/lib/view/DocumentHolderExt.js index 0039577765..60e3ecbc70 100644 --- a/apps/common/main/lib/view/DocumentHolderExt.js +++ b/apps/common/main/lib/view/DocumentHolderExt.js @@ -33,7 +33,7 @@ define([], function () { 'use strict'; - let _editor = window.DE || window.PDFE ||window.PDFE || window.PE || window.SSE; + let _editor = window.DE || window.PDFE ||window.PDFE || window.PE || window.SSE || window.VE; if (_editor && _editor.Views && _editor.Views.DocumentHolder) { let dh = _editor.Views.DocumentHolder.prototype; diff --git a/apps/common/main/resources/less/colors-table-ie-fix.less b/apps/common/main/resources/less/colors-table-ie-fix.less index acca3c3235..1f474cff80 100644 --- a/apps/common/main/resources/less/colors-table-ie-fix.less +++ b/apps/common/main/resources/less/colors-table-ie-fix.less @@ -3,21 +3,25 @@ @toolbar-header-spreadsheet-ie: #40865c; @toolbar-header-presentation-ie: #BE664F; @toolbar-header-pdf-ie: #AA5252; +@toolbar-header-visio-ie: #444796; @text-toolbar-header-on-background-document-ie: #38567A; @text-toolbar-header-on-background-spreadsheet-ie: #336B49; @text-toolbar-header-on-background-presentation-ie: #854535; @text-toolbar-header-on-background-pdf-ie: #8D4444; +@text-toolbar-header-on-background-visio-ie: #444796; @tab-header-document-ie: #fff; @tab-header-spreadsheet-ie: #fff; @tab-header-presentation-ie: #fff; @tab-header-pdf-ie: #fff; +@tab-header-visio-ie: #fff; @tab-toolbar-document-ie: #446995; @tab-toolbar-spreadsheet-ie: #40865c; @tab-toolbar-presentation-ie: #BE664F; @tab-toolbar-pdf-ie: #AA5252; +@tab-toolbar-visio-ie: #444796; @background-normal-ie: #fff; @background-toolbar-ie: #f1f1f1; diff --git a/apps/common/main/resources/less/colors-table.less b/apps/common/main/resources/less/colors-table.less index fd281616ed..824d199182 100644 --- a/apps/common/main/resources/less/colors-table.less +++ b/apps/common/main/resources/less/colors-table.less @@ -15,11 +15,13 @@ --toolbar-header-spreadsheet: #40865c; --toolbar-header-presentation: #BE664F; --toolbar-header-pdf: #AA5252; + --toolbar-header-visio: #444796; --text-toolbar-header-on-background-document: #38567A; --text-toolbar-header-on-background-spreadsheet: #336B49; --text-toolbar-header-on-background-presentation: #854535; --text-toolbar-header-on-background-pdf: #8D4444; + --text-toolbar-header-on-background-visio: #444796; --background-normal: #fff; --background-toolbar: #f7f7f7; @@ -87,11 +89,13 @@ --highlight-header-tab-underline-spreadsheet: var(--text-toolbar-header); --highlight-header-tab-underline-presentation: var(--text-toolbar-header); --highlight-header-tab-underline-pdf: var(--text-toolbar-header); + --highlight-header-tab-underline-visio: var(--text-toolbar-header); --highlight-toolbar-tab-underline-document: #446995; --highlight-toolbar-tab-underline-spreadsheet: #40865c; --highlight-toolbar-tab-underline-presentation: #BE664F; --highlight-toolbar-tab-underline-pdf: #AA5252; + --highlight-toolbar-tab-underline-visio: #444796; // Canvas diff --git a/apps/visioeditor/main/app.js b/apps/visioeditor/main/app.js new file mode 100644 index 0000000000..99f28f3b91 --- /dev/null +++ b/apps/visioeditor/main/app.js @@ -0,0 +1,185 @@ +/* + * (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 + * + */ +/** + * app.js + * + * Created on 11/07/24 + * + */ + +'use strict'; +var reqerr; +require.config({ + // The shim config allows us to configure dependencies for + // scripts that do not call define() to register a module + baseUrl: '../../', + paths: { + jquery : '../vendor/jquery/jquery', + underscore : '../vendor/underscore/underscore', + backbone : '../vendor/backbone/backbone', + text : '../vendor/requirejs-text/text', + perfectscrollbar: 'common/main/lib/mods/perfect-scrollbar', + jmousewheel : '../vendor/perfect-scrollbar/src/jquery.mousewheel', + xregexp : '../vendor/xregexp/xregexp-all-min', + socketio : '../vendor/socketio/socket.io.min', + // allfonts : '../../sdkjs/common/AllFonts', + sdk : '../../sdkjs/word/sdk-all-min', + api : 'api/documents/api', + core : 'common/main/lib/core/application', + notification : 'common/main/lib/core/NotificationCenter', + keymaster : 'common/main/lib/core/keymaster', + tip : 'common/main/lib/util/Tip', + localstorage : 'common/main/lib/util/LocalStorage', + analytics : 'common/Analytics', + gateway : 'common/Gateway', + locale : 'common/locale', + irregularstack : 'common/IrregularStack' + }, + + shim: { + backbone: { + deps: [ + 'underscore', + 'jquery' + ], + exports: 'Backbone' + }, + perfectscrollbar: { + deps: [ + 'jmousewheel' + ] + }, + notification: { + deps: [ + 'backbone' + ] + }, + core: { + deps: [ + 'backbone', + 'notification', + 'irregularstack' + ] + }, + sdk: { + deps: [ + 'jquery', + // 'allfonts', + 'xregexp', + 'socketio' + ] + }, + gateway: { + deps: [ + 'jquery' + ] + }, + analytics: { + deps: [ + 'jquery' + ] + } + } +}); + +require([ + 'sdk', + 'backbone', + 'underscore', + 'core', + 'analytics', + 'gateway', + 'locale' +], function (Sdk, Backbone, _, Core) { + if (Backbone.History && Backbone.History.started) + return; + Backbone.history.start(); + window._ = _; + + /** + * Application instance with VE namespace defined + */ + var app = new Backbone.Application({ + nameSpace: 'VE', + autoCreate: false, + controllers : [ + 'Viewport', + 'DocumentHolder', + 'Toolbar', + 'Statusbar', + 'LeftMenu', + 'Main', + 'ViewTab', + 'Search', + 'Common.Controllers.Chat', + // 'Common.Controllers.Comments', + 'Common.Controllers.Plugins' + ] + }); + + Common.Locale.apply( + function() { + require([ + 'common/main/lib/mods/dropdown', + 'common/main/lib/mods/tooltip', + 'common/main/lib/util/LocalStorage', + 'common/main/lib/controller/Scaling', + 'common/main/lib/controller/Desktop', + 'visioeditor/main/app/controller/Viewport', + 'visioeditor/main/app/controller/DocumentHolder', + 'visioeditor/main/app/controller/Toolbar', + 'visioeditor/main/app/controller/Statusbar', + 'visioeditor/main/app/controller/LeftMenu', + 'visioeditor/main/app/controller/Main', + 'visioeditor/main/app/controller/ViewTab', + 'visioeditor/main/app/controller/Search', + 'common/main/lib/util/utils', + // 'common/main/lib/controller/Comments', + 'common/main/lib/controller/Chat', + /** coauthoring end **/ + 'common/main/lib/controller/Plugins' + ], function() { + app.postLaunchScripts = [ + 'visioeditor/main/code' + ]; + + app.start(); + }); + } + ); +}, function(err) { + if (err.requireType == 'timeout' && !reqerr && window.requireTimeourError) { + reqerr = window.requireTimeourError(); + window.alert(reqerr); + window.location.reload(); + } +}); \ No newline at end of file diff --git a/apps/visioeditor/main/app/controller/DocumentHolder.js b/apps/visioeditor/main/app/controller/DocumentHolder.js new file mode 100644 index 0000000000..a8c67a0816 --- /dev/null +++ b/apps/visioeditor/main/app/controller/DocumentHolder.js @@ -0,0 +1,712 @@ +/* + * (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 + * + */ +/** + * DocumentHolder.js + * + * DocumentHolder controller + * + * Created on 11/07/24 + * + */ + +var c_paragraphLinerule = { + LINERULE_LEAST: 0, + LINERULE_AUTO: 1, + LINERULE_EXACT: 2 +}; + +var c_paragraphTextAlignment = { + RIGHT: 0, + LEFT: 1, + CENTERED: 2, + JUSTIFIED: 3 +}; + +var c_paragraphSpecial = { + NONE_SPECIAL: 0, + FIRST_LINE: 1, + HANGING: 2 +}; + +define([ + 'core', + 'visioeditor/main/app/view/DocumentHolder' +], function () { + 'use strict'; + + VE.Controllers.DocumentHolder = Backbone.Controller.extend({ + models: [], + collections: [], + views: [ + 'DocumentHolder' + ], + + initialize: function() { + // + this.addListeners({ + 'DocumentHolder': { + 'createdelayedelements': this.createDelayedElements + }, + 'FileMenu': { + 'settings:apply': _.bind(this.applySettings, this) + }, + }); + + var me = this; + + me._TtHeight = 20; + me.usertips = []; + me.fastcoauthtips = []; + me._isDisabled = false; + me._state = {}; + me.mode = {}; + me.mouseMoveData = null; + me.isTooltipHiding = false; + + me.screenTip = { + toolTip: new Common.UI.Tooltip({ + owner: this, + html: true, + title: '
Press Ctrl and click link', + cls: 'link-tooltip' +// style: 'word-wrap: break-word;' + }), + strTip: '', + isHidden: true, + isVisible: false + }; + me.userTooltip = true; + me.wrapEvents = { + userTipMousover: _.bind(me.userTipMousover, me), + userTipMousout: _.bind(me.userTipMousout, me) + }; + }, + + onLaunch: function() { + this.documentHolder = this.createView('DocumentHolder').render(); + this.documentHolder.el.tabIndex = -1; + this.onAfterRender(); + + var me = this; + Common.NotificationCenter.on({ + 'window:show': function(e){ + me.screenTip.toolTip.hide(); + me.screenTip.isVisible = false; + me.userTipHide(); + me.mode && me.mode.isDesktopApp && me.api && me.api.asc_onShowPopupWindow(); + + }, + 'modal:show': function(e){ + me.hideTips(); + }, + 'layout:changed': function(e){ + me.screenTip.toolTip.hide(); + me.screenTip.isVisible = false; + /** coauthoring begin **/ + me.userTipHide(); + /** coauthoring end **/ + me.hideTips(); + me.onDocumentHolderResize(); + } + }); + Common.NotificationCenter.on('script:loaded', _.bind(me.createPostLoadElements, me)); + }, + + setApi: function(o) { + this.api = o; + + if (this.api) { + this.api.asc_registerCallback('asc_onContextMenu', _.bind(this.onContextMenu, this)); + this.api.asc_registerCallback('asc_onMouseMoveStart', _.bind(this.onMouseMoveStart, this)); + this.api.asc_registerCallback('asc_onMouseMoveEnd', _.bind(this.onMouseMoveEnd, this)); + + //hyperlink + this.api.asc_registerCallback('asc_onHyperlinkClick', _.bind(this.onHyperlinkClick, this)); + this.api.asc_registerCallback('asc_onMouseMove', _.bind(this.onMouseMove, this)); + + if (this.mode.isEdit === true) { + } + this.api.asc_registerCallback('asc_onCoAuthoringDisconnect', _.bind(this.onCoAuthoringDisconnect, this)); + Common.NotificationCenter.on('api:disconnect', _.bind(this.onCoAuthoringDisconnect, this)); + + this.api.asc_registerCallback('asc_onFocusObject', _.bind(this.onFocusObject, this)); + this.api.asc_registerCallback('onPluginContextMenu', _.bind(this.onPluginContextMenu, this)); + + this.documentHolder.setApi(this.api); + } + + return this; + }, + + setMode: function(m) { + this.mode = m; + this.documentHolder.setMode(m); + }, + + createPostLoadElements: function() { + }, + + createDelayedElements: function(view, type) { + var me = this, + view = me.documentHolder; + + if (type==='view') { + view.menuViewCopy.on('click', _.bind(me.onCutCopyPaste, me)); + } else if (type==='edit') { + view.menuEditCopy.on('click', _.bind(me.onCutCopyPaste, me)); + } + }, + + getView: function (name) { + return !name ? + this.documentHolder : Backbone.Controller.prototype.getView.call() + }, + + showPopupMenu: function(menu, value, event, docElement, eOpts){ + var me = this; + if (!_.isUndefined(menu) && menu !== null){ + Common.UI.Menu.Manager.hideAll(); + + var showPoint = [event.get_X(), event.get_Y()], + menuContainer = $(me.documentHolder.el).find(Common.Utils.String.format('#menu-container-{0}', menu.id)); + + if (!menu.rendered) { + // Prepare menu container + if (menuContainer.length < 1) { + menuContainer = $(Common.Utils.String.format('', menu.id)); + $(me.documentHolder.el).append(menuContainer); + } + + menu.render(menuContainer); + menu.cmpEl.attr({tabindex: "-1"}); + } + + menuContainer.css({ + left: showPoint[0], + top : showPoint[1] + }); + + menu.show(); + + if (_.isFunction(menu.options.initMenu)) { + menu.options.initMenu(value); + menu.alignPosition(); + } + _.delay(function() { + menu.cmpEl.focus(); + }, 10); + + me.documentHolder.currentMenu = menu; + me.api.onPluginContextMenuShow && me.api.onPluginContextMenuShow(event); + } + }, + + fillViewMenuProps: function(selectedElements) { + // if (!selectedElements || !_.isArray(selectedElements)) return; + + var documentHolder = this.documentHolder; + if (!documentHolder.viewModeMenu) + documentHolder.createDelayedElementsViewer(); + + var menu_props = {}; + return {menu_to_show: documentHolder.viewModeMenu, menu_props: menu_props}; + }, + + fillEditMenuProps: function(selectedElements) { + var documentHolder = this.documentHolder; + if (!documentHolder.editModeMenu) + documentHolder.createDelayedElementsEditor(); + + if (!selectedElements || !_.isArray(selectedElements) || selectedElements.length<1) + return {menu_to_show: documentHolder.editModeMenu, menu_props: {}} + + var me = this, + menu_props = {}, + menu_to_show = null; + return {menu_to_show: menu_to_show, menu_props: menu_props}; + }, + + applyEditorMode: function() { + if (this.mode && this.mode.isEdit && !this.documentHolder.editModeMenu) { + this.documentHolder.createDelayedElementsEditor(); + } + }, + + showObjectMenu: function(event, docElement, eOpts){ + var me = this; + if (me.api){ + var obj = me.mode && me.mode.isEdit ? me.fillEditMenuProps(me.api.getSelectedElements()) : me.fillViewMenuProps(me.api.getSelectedElements()); + if (obj) me.showPopupMenu(obj.menu_to_show, obj.menu_props, event, docElement, eOpts); + } + }, + + onContextMenu: function(event){ + if (Common.UI.HintManager.isHintVisible()) + Common.UI.HintManager.clearHints(); + if (!event) { + Common.UI.Menu.Manager.hideAll(); + return; + } + + var me = this; + _.delay(function(){ + if (event.get_Type() == Asc.c_oAscPdfContextMenuTypes.Thumbnails) { + } else + me.showObjectMenu.call(me, event); + },10); + }, + + onFocusObject: function(selectedElements) { + var me = this, + currentMenu = me.documentHolder.currentMenu; + if (currentMenu && currentMenu.isVisible()){ + var obj = me.mode && me.mode.isEdit ? me.fillEditMenuProps(selectedElements) : me.fillViewMenuProps(selectedElements); + if (obj) { + if (obj.menu_to_show===currentMenu) { + currentMenu.options.initMenu(obj.menu_props); + currentMenu.alignPosition(); + } + } + } + if (this.mode && this.mode.isEdit) { + } + }, + + handleDocumentWheel: function(event) { + var me = this; + if (me.api) { + var delta = (_.isUndefined(event.originalEvent)) ? event.wheelDelta : event.originalEvent.wheelDelta; + if (_.isUndefined(delta)) { + delta = event.deltaY; + } + + if (event.ctrlKey && !event.altKey) { + if (delta < 0) { + me.api.zoomOut(); + } else if (delta > 0) { + me.api.zoomIn(); + } + + event.preventDefault(); + event.stopPropagation(); + } + } + }, + + handleDocumentKeyDown: function(event){ + var me = this; + if (me.api){ + var key = event.keyCode; + if ((event.ctrlKey || event.metaKey) && !event.shiftKey && !event.altKey){ + if (key === Common.UI.Keys.NUM_PLUS || key === Common.UI.Keys.EQUALITY || (Common.Utils.isGecko && key === Common.UI.Keys.EQUALITY_FF) || (Common.Utils.isOpera && key == 43)){ + me.api.zoomIn(); + event.preventDefault(); + event.stopPropagation(); + return false; + } + else if (key === Common.UI.Keys.NUM_MINUS || key === Common.UI.Keys.MINUS || (Common.Utils.isGecko && key === Common.UI.Keys.MINUS_FF) || (Common.Utils.isOpera && key == 45)){ + me.api.zoomOut(); + event.preventDefault(); + event.stopPropagation(); + return false; + } else if (key === Common.UI.Keys.ZERO || key === Common.UI.Keys.NUM_ZERO) {// 0 + me.api.zoom(100); + event.preventDefault(); + event.stopPropagation(); + return false; + } + } + if (me.documentHolder.currentMenu && me.documentHolder.currentMenu.isVisible()) { + if (key == Common.UI.Keys.UP || + key == Common.UI.Keys.DOWN) { + $('ul.dropdown-menu', me.documentHolder.currentMenu.el).focus(); + } + } + + if (key == Common.UI.Keys.ESC) { + Common.UI.Menu.Manager.hideAll(); + } + } + }, + + onDocumentHolderResize: function(e){ + var me = this; + me._XY = [ + Common.Utils.getOffset(me.documentHolder.cmpEl).left - $(window).scrollLeft(), + Common.Utils.getOffset(me.documentHolder.cmpEl).top - $(window).scrollTop() + ]; + me._Height = me.documentHolder.cmpEl.height(); + me._Width = me.documentHolder.cmpEl.width(); + me._BodyWidth = $('body').width(); + }, + + onAfterRender: function(ct){ + var me = this; + var meEl = me.documentHolder.cmpEl; + if (meEl) { + meEl.on('contextmenu', function(e) { + e.preventDefault(); + e.stopPropagation(); + return false; + }); + meEl.on('click', function(e){ + if (e.target.localName == 'canvas') { + if (me._preventClick) + me._preventClick = false; + else + meEl.focus(); + } + }); + meEl.on('mousedown', function(e){ + if (e.target.localName == 'canvas' && $(e.target).closest('[type=menuitem]').length<1) + Common.UI.Menu.Manager.hideAll(); + }); + + //NOTE: set mouse wheel handler + + var addEvent = function( elem, type, fn ) { + elem.addEventListener ? elem.addEventListener( type, fn, false ) : elem.attachEvent( "on" + type, fn ); + }; + + var eventname=(/Firefox/i.test(navigator.userAgent))? 'DOMMouseScroll' : 'mousewheel'; + addEvent(me.documentHolder.el, eventname, _.bind(me.handleDocumentWheel, me)); + } + + !Common.Utils.isChrome ? $(document).on('mousewheel', _.bind(me.handleDocumentWheel, me)) : + document.addEventListener('mousewheel', _.bind(me.handleDocumentWheel, me), {passive: false}); + $(document).on('keydown', _.bind(me.handleDocumentKeyDown, me)); + + $(window).on('resize', _.bind(me.onDocumentHolderResize, me)); + var viewport = me.getApplication().getController('Viewport').getView('Viewport'); + viewport.hlayout.on('layout:resizedrag', _.bind(me.onDocumentHolderResize, me)); + }, + + getUserName: function(id){ + var usersStore = VE.getCollection('Common.Collections.Users'); + if (usersStore){ + var rec = usersStore.findUser(id); + if (rec) + return AscCommon.UserInfoParser.getParsedName(rec.get('username')); + } + return this.documentHolder.guestText; + }, + + isUserVisible: function(id){ + var usersStore = VE.getCollection('Common.Collections.Users'); + if (usersStore){ + var rec = usersStore.findUser(id); + if (rec) + return !rec.get('hidden'); + } + return true; + }, + + userTipMousover: function (evt, el, opt) { + var me = this; + if (me.userTooltip===true) { + me.userTooltip = new Common.UI.Tooltip({ + owner: evt.currentTarget, + title: me.documentHolder.tipIsLocked + }); + + me.userTooltip.show(); + } + }, + + userTipHide: function () { + var me = this; + if (typeof me.userTooltip == 'object') { + me.userTooltip.hide(); + me.userTooltip = undefined; + + for (var i=0; i0) { + if (typeof me.userTooltip == 'object') { + me.userTooltip.hide(); + me.userTooltip = true; + } + _.each(me.usertips, function(item) { + item.remove(); + }); + } + me.usertips = []; + me.usertipcount = 0; + /** coauthoring end **/ + }, + + onMouseMoveEnd: function() { + var me = this; + if (me.screenTip.isHidden && me.screenTip.isVisible) { + me.screenTip.isVisible = false; + me.isTooltipHiding = true; + me.screenTip.toolTip.hide(function(){ + me.isTooltipHiding = false; + if (me.mouseMoveData) me.onMouseMove(me.mouseMoveData); + me.mouseMoveData = null; + }); + } + }, + + onMouseMove: function(moveData) { + var me = this, + cmpEl = me.documentHolder.cmpEl, + screenTip = me.screenTip; + if (me._XY === undefined) { + me._XY = [ + Common.Utils.getOffset(cmpEl).left - $(window).scrollLeft(), + Common.Utils.getOffset(cmpEl).top - $(window).scrollTop() + ]; + me._Height = cmpEl.height(); + me._Width = cmpEl.width(); + me._BodyWidth = $('body').width(); + } + + if (moveData) { + var showPoint, ToolTip, + type = moveData.get_Type(); + + if (type==Asc.c_oAscMouseMoveDataTypes.Hyperlink) { + if (me.isTooltipHiding) { + me.mouseMoveData = moveData; + return; + } + + var hyperProps = moveData.get_Hyperlink(); + if (!hyperProps) return; + ToolTip = (_.isEmpty(hyperProps.get_ToolTip())) ? hyperProps.get_Value() : hyperProps.get_ToolTip(); + if (ToolTip.length>256) + ToolTip = ToolTip.substr(0, 256) + '...'; + + var recalc = false; + screenTip.isHidden = false; + + ToolTip = Common.Utils.String.htmlEncode(ToolTip); + + if (screenTip.tipType !== type || screenTip.tipLength !== ToolTip.length || screenTip.strTip.indexOf(ToolTip)<0 ) { + screenTip.toolTip.setTitle((type==Asc.c_oAscMouseMoveDataTypes.Hyperlink) ? (ToolTip + '
' + Common.Utils.String.platformKey('Ctrl', me.documentHolder.txtPressLink) + '') : ToolTip); + screenTip.tipLength = ToolTip.length; + screenTip.strTip = ToolTip; + screenTip.tipType = type; + recalc = true; + } + + showPoint = [moveData.get_X(), moveData.get_Y()]; + showPoint[1] += (me._XY[1]-15); + showPoint[0] += (me._XY[0]+5); + + if (!screenTip.isVisible || recalc) { + screenTip.isVisible = true; + screenTip.toolTip.show([-10000, -10000]); + } + + if ( recalc ) { + screenTip.tipHeight = screenTip.toolTip.getBSTip().$tip.height(); + screenTip.tipWidth = screenTip.toolTip.getBSTip().$tip.width(); + } + + recalc = false; + if (showPoint[0] + screenTip.tipWidth > me._BodyWidth ) { + showPoint[0] = me._BodyWidth - screenTip.tipWidth; + recalc = true; + } + if (showPoint[1] - screenTip.tipHeight < 0) { + showPoint[1] = (recalc) ? showPoint[1]+30 : 0; + } else + showPoint[1] -= screenTip.tipHeight; + + screenTip.toolTip.getBSTip().$tip.css({top: showPoint[1] + 'px', left: showPoint[0] + 'px'}); + } + /** coauthoring begin **/ + else if (moveData.get_Type()==Asc.c_oAscMouseMoveDataTypes.LockedObject && me.mode.isEdit && me.isUserVisible(moveData.get_UserId())) { // 2 - locked object + var src; + if (me.usertipcount >= me.usertips.length) { + src = $(document.createElement("div")); + src.addClass('username-tip'); + src.css({height: me._TtHeight + 'px', position: 'absolute', zIndex: '900', visibility: 'visible'}); + $(document.body).append(src); + if (me.userTooltip) { + src.on('mouseover', me.wrapEvents.userTipMousover); + src.on('mouseout', me.wrapEvents.userTipMousout); + } + + me.usertips.push(src); + } + src = me.usertips[me.usertipcount]; + me.usertipcount++; + + ToolTip = me.getUserName(moveData.get_UserId()); + + showPoint = [moveData.get_X()+me._XY[0], moveData.get_Y()+me._XY[1]]; + var maxwidth = showPoint[0]; + showPoint[0] = me._BodyWidth - showPoint[0]; + showPoint[1] -= ((moveData.get_LockedObjectType()==2) ? me._TtHeight : 0); + + if (showPoint[1] > me._XY[1] && showPoint[1]+me._TtHeight < me._XY[1]+me._Height) { + src.text(ToolTip); + src.css({visibility: 'visible', top: showPoint[1] + 'px', right: showPoint[0] + 'px', 'max-width': maxwidth + 'px'}); + } else { + src.css({visibility: 'hidden'}); + } + } + /** coauthoring end **/ + } + }, + + onCoAuthoringDisconnect: function() { + this.mode.isEdit = false; + }, + + SetDisabled: function(state) { + this._isDisabled = state; + this.documentHolder.SetDisabled(state); + }, + + changePosition: function() { + var me = this, + cmpEl = me.documentHolder.cmpEl; + me._XY = [ + Common.Utils.getOffset(cmpEl).left - $(window).scrollLeft(), + Common.Utils.getOffset(cmpEl).top - $(window).scrollTop() + ]; + me._Height = cmpEl.height(); + me._Width = cmpEl.width(); + me._BodyWidth = $('body').width(); + me.onMouseMoveStart(); + }, + + onCutCopyPaste: function(item, e) { + var me = this; + if (me.api) { + var res = (item.value == 'cut') ? me.api.Cut() : ((item.value == 'copy') ? me.api.Copy() : me.api.Paste()); + if (!res) { + if (!Common.localStorage.getBool("ve-hide-copywarning")) { + (new Common.Views.CopyWarningDialog({ + handler: function(dontshow) { + if (dontshow) Common.localStorage.setItem("ve-hide-copywarning", 1); + me.editComplete(); + } + })).show(); + } + } + item.isFromBar && me.api.SetShowTextSelectPanel(false); + } + me.editComplete(); + }, + + onPrintSelection: function(item){ + if (this.api){ + var printopt = new Asc.asc_CAdjustPrint(); + printopt.asc_setPrintType(Asc.c_oAscPrintType.Selection); + var opts = new Asc.asc_CDownloadOptions(null, Common.Utils.isChrome || Common.Utils.isOpera || Common.Utils.isGecko && Common.Utils.firefoxVersion>86); // if isChrome or isOpera == true use asc_onPrintUrl event + opts.asc_setAdvancedOptions(printopt); + this.api.asc_Print(opts); + this.editComplete(); + Common.component.Analytics.trackEvent('DocumentHolder', 'Print Selection'); + } + }, + + onPluginContextMenu: function(data) { + if (data && data.length>0 && this.documentHolder && this.documentHolder.currentMenu && this.documentHolder.currentMenu.isVisible()){ + this.documentHolder.updateCustomItems(this.documentHolder.currentMenu, data); + } + }, + + editComplete: function() { + this.documentHolder && this.documentHolder.fireEvent('editcomplete', this.documentHolder); + }, + + applySettings: function() { + }, + + clearSelection: function() { + } + }); +}); \ No newline at end of file diff --git a/apps/visioeditor/main/app/controller/LeftMenu.js b/apps/visioeditor/main/app/controller/LeftMenu.js new file mode 100644 index 0000000000..bb3499bae9 --- /dev/null +++ b/apps/visioeditor/main/app/controller/LeftMenu.js @@ -0,0 +1,812 @@ +/* + * (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 + * + */ +/** + * LeftMenu.js + * + * Controller + * + * Created on 11/07/24 + * + */ + +define([ + 'core', + 'common/main/lib/util/Shortcuts', + 'visioeditor/main/app/view/LeftMenu', + 'visioeditor/main/app/view/FileMenu', + 'visioeditor/main/app/view/ViewTab' +], function () { + 'use strict'; + + VE.Controllers.LeftMenu = Backbone.Controller.extend(_.extend({ + views: [ + 'LeftMenu', + 'FileMenu', + 'ViewTab' + ], + + initialize: function() { + + this.addListeners({ + 'Common.Views.Chat': { + 'hide': _.bind(this.onHideChat, this) + }, + 'Common.Views.Header': { + 'rename': _.bind(function (value) { + this.mode && this.mode.wopi && this.api ? this.api.asc_wopi_renameFile(value) : Common.Gateway.requestRename(value); + }, this) + }, + 'Common.Views.About': { + 'show': _.bind(this.aboutShowHide, this, false), + 'hide': _.bind(this.aboutShowHide, this, true) + }, + 'Common.Views.Plugins': { + 'plugins:addtoleft': _.bind(this.addNewPlugin, this), + 'pluginsleft:open': _.bind(this.openPlugin, this), + 'pluginsleft:close': _.bind(this.closePlugin, this), + 'pluginsleft:hide': _.bind(this.onHidePlugins, this), + 'pluginsleft:updateicons': _.bind(this.updatePluginButtonsIcons, this) + }, + 'LeftMenu': { + 'panel:show': _.bind(this.menuExpand, this), + 'comments:show': _.bind(this.commentsShowHide, this, 'show'), + 'comments:hide': _.bind(this.commentsShowHide, this, 'hide'), + 'button:click': _.bind(this.onBtnCategoryClick, this) + }, + 'FileMenu': { + 'menu:hide': _.bind(this.menuFilesShowHide, this, 'hide'), + 'menu:show': _.bind(this.menuFilesShowHide, this, 'show'), + 'item:click': _.bind(this.clickMenuFileItem, this), + 'saveas:format': _.bind(function(menu, format, ext) { + if (this.mode && this.mode.wopi && ext!==undefined) { // save copy as in wopi + this.saveAsInWopi(menu, format, ext); + } else + this.clickSaveAsFormat(menu, format, ext); + }, this), + 'settings:apply': _.bind(this.applySettings, this), + 'create:new': _.bind(this.onCreateNew, this), + 'recent:open': _.bind(this.onOpenRecent, this) + }, + 'Toolbar': { + 'file:settings': _.bind(this.clickToolbarSettings,this), + 'file:open': this.clickToolbarTab.bind(this, 'file'), + 'file:close': this.clickToolbarTab.bind(this, 'other'), + // 'save:disabled': this.changeToolbarSaveState.bind(this) + }, + 'ViewTab': { + 'leftmenu:hide': _.bind(this.onLeftMenuHide, this) + }, + 'SearchBar': { + 'search:show': _.bind(this.onShowHideSearch, this) + } + }); + + Common.NotificationCenter.on('leftmenu:change', _.bind(this.onMenuChange, this)); + // Common.NotificationCenter.on('app:comment:add', _.bind(this.onAppAddComment, this)); + Common.NotificationCenter.on('file:print', _.bind(this.clickToolbarPrint, this)); + }, + + onLaunch: function() { + this.leftMenu = this.createView('LeftMenu').render(); + this.leftMenu.btnThumbs.on('toggle', _.bind(this.onShowTumbnails, this)); + this.leftMenu.btnSearchBar.on('toggle', _.bind(this.onMenuSearchBar, this)); + this._state = { + disableEditing: false + }; + + var keymap = { + // 'command+shift+s,ctrl+shift+s': _.bind(this.onShortcut, this, 'save'), + 'command+f,ctrl+f': _.bind(this.onShortcut, this, 'search'), + 'esc': _.bind(this.onShortcut, this, 'escape'), + /** coauthoring begin **/ + // 'command+shift+h,ctrl+shift+h': _.bind(this.onShortcut, this, 'comments'), + /** coauthoring end **/ + 'f1': _.bind(this.onShortcut, this, 'help') + }; + keymap[Common.Utils.isMac ? 'ctrl+alt+f' : 'alt+f'] = _.bind(this.onShortcut, this, 'file'); + keymap[Common.Utils.isMac ? 'ctrl+alt+q' : 'alt+q'] = _.bind(this.onShortcut, this, 'chat'); + Common.util.Shortcuts.delegateShortcuts({shortcuts:keymap}); + Common.util.Shortcuts.suspendEvents(); + }, + + setApi: function(api) { + this.api = api; + this.api.asc_registerCallback('asc_onThumbnailsShow', _.bind(this.onThumbnailsShow, this)); + this.api.asc_registerCallback('asc_onCoAuthoringDisconnect', _.bind(this.onApiServerDisconnect, this)); + Common.NotificationCenter.on('api:disconnect', _.bind(this.onApiServerDisconnect, this)); + this.api.asc_registerCallback('asc_onDownloadUrl', _.bind(this.onDownloadUrl, this)); + /** coauthoring begin **/ + if (this.mode.canCoAuthoring) { + if (this.mode.canChat) + this.api.asc_registerCallback('asc_onCoAuthoringChatReceiveMessage', _.bind(this.onApiChatMessage, this)); + // if (this.mode.canComments) { + // this.api.asc_registerCallback('asc_onAddComment', _.bind(this.onApiAddComment, this)); + // this.api.asc_registerCallback('asc_onAddComments', _.bind(this.onApiAddComments, this)); + // var collection = this.getApplication().getCollection('Common.Collections.Comments'), + // resolved = Common.Utils.InternalSettings.get("ve-settings-resolvedcomment"); + // for (var i = 0; i < collection.length; ++i) { + // var comment = collection.at(i); + // if (!comment.get('hide') && comment.get('userid') !== this.mode.user.id && comment.get('userid') !== '' && (resolved || !comment.get('resolved'))) { + // this.leftMenu.markCoauthOptions('comments', true); + // break; + // } + // } + // } + } + /** coauthoring end **/ + var value = Common.UI.LayoutManager.getInitValue('leftMenu'); + value = (value!==undefined) ? !value : false; + this.isThumbsShown = !Common.localStorage.getBool("ve-hidden-leftmenu", value); + this.leftMenu.btnThumbs.toggle(this.isThumbsShown); + this.leftMenu.getMenu('file').setApi(api); + this.getApplication().getController('Search').setApi(this.api).setMode(this.mode); + this.leftMenu.setOptionsPanel('advancedsearch', this.getApplication().getController('Search').getView('Common.Views.SearchPanel')); + return this; + }, + + setMode: function(mode) { + this.mode = mode; + this.leftMenu.setMode(mode); + this.leftMenu.getMenu('file').setMode(mode); + return this; + }, + + createDelayedElements: function() { + /** coauthoring begin **/ + if ( this.mode.canCoAuthoring ) { + // this.leftMenu.btnComments[(this.mode.canViewComments && !this.mode.isLightVersion) ? 'show' : 'hide'](); + // if (this.mode.canViewComments) + // this.leftMenu.setOptionsPanel('comment', this.getApplication().getController('Common.Controllers.Comments').getView()); + + this.leftMenu.btnChat[(this.mode.canChat && !this.mode.isLightVersion) ? 'show' : 'hide'](); + if (this.mode.canChat) + this.leftMenu.setOptionsPanel('chat', this.getApplication().getController('Common.Controllers.Chat').getView('Common.Views.Chat')); + } else { + this.leftMenu.btnChat.hide(); + this.leftMenu.btnComments.hide(); + } + /** coauthoring end **/ + + (this.mode.trialMode || this.mode.isBeta) && this.leftMenu.setDeveloperMode(this.mode.trialMode, this.mode.isBeta, this.mode.buildVersion); + Common.util.Shortcuts.resumeEvents(); + this.leftMenu.setButtons(); + this.leftMenu.setMoreButton(); + return this; + }, + + enablePlugins: function() { + (this.mode.trialMode || this.mode.isBeta) && this.leftMenu.setDeveloperMode(this.mode.trialMode, this.mode.isBeta, this.mode.buildVersion); + }, + + clickMenuFileItem: function(menu, action, isopts) { + var close_menu = true; + switch (action) { + case 'back': + break; + case 'save': Common.NotificationCenter.trigger('leftmenu:save'); break; + case 'save-desktop': this.api.asc_DownloadAs(); break; + case 'saveas': + if ( isopts ) close_menu = false; + else this.clickSaveAsFormat(); + break; + case 'save-copy': + if ( isopts ) close_menu = false; + else this.clickSaveAsFormat(undefined, undefined, true); + break; + case 'print': this.api.asc_Print(new Asc.asc_CDownloadOptions(null, Common.Utils.isChrome || Common.Utils.isOpera || Common.Utils.isGecko && Common.Utils.firefoxVersion>86)); break; + case 'exit': Common.NotificationCenter.trigger('goback'); break; + case 'edit': + this.getApplication().getController('Statusbar').setStatusCaption(this.requestEditRightsText); + Common.Gateway.requestEditRights(); + break; + case 'new': + if ( isopts ) close_menu = false; + else this.onCreateNew(undefined, 'blank'); + break; + case 'rename': + var me = this, + documentCaption = me.api.asc_getDocumentName(); + (new Common.Views.RenameDialog({ + filename: documentCaption, + maxLength: this.mode.wopi ? this.mode.wopi.FileNameMaxLength : undefined, + handler: function(result, value) { + if (result == 'ok' && !_.isEmpty(value.trim()) && documentCaption !== value.trim()) { + me.mode.wopi ? me.api.asc_wopi_renameFile(value) : Common.Gateway.requestRename(value); + } + Common.NotificationCenter.trigger('edit:complete', me); + } + })).show(); + break; + case 'external-help': + close_menu = !!isopts; + break; + case 'close-editor': Common.NotificationCenter.trigger('close'); break; + default: close_menu = false; + } + + if (close_menu && menu) { + menu.hide(); + } + }, + + clickSaveAsFormat: function(menu, format) { + this.api.asc_DownloadAs(new Asc.asc_CDownloadOptions(format)); + menu.hide(); + }, + + clickSaveCopyAsFormat: function(menu, format, ext, wopiPath) { + this.isFromFileDownloadAs = ext; + var options = new Asc.asc_CDownloadOptions(format, true); + options.asc_setIsSaveAs(true); + wopiPath && options.asc_setWopiSaveAsPath(wopiPath); + this.api.asc_DownloadAs(options); + + menu.hide(); + }, + + saveAsInWopi: function(menu, format, ext) { + var me = this, + defFileName = this.getApplication().getController('Viewport').getView('Common.Views.Header').getDocumentCaption(); + !defFileName && (defFileName = me.txtUntitled); + var idx = defFileName.lastIndexOf('.'); + if (idx>0) + defFileName = defFileName.substring(0, idx); + (new Common.Views.TextInputDialog({ + label: me.textSelectPath, + value: defFileName || '', + inputFixedConfig: {fixedValue: ext, fixedWidth: 40}, + inputConfig: { + maxLength: me.mode.wopi.FileNameMaxLength + }, + handler: function(result, value) { + if (result == 'ok') { + if (typeof ext === 'string') + value = value + ext; + me.clickSaveAsFormat(menu, format, ext, value); + } + } + })).show(); + }, + + onDownloadUrl: function(url, fileType) { + if (this.isFromFileDownloadAs) { + var me = this, + defFileName = this.getApplication().getController('Viewport').getView('Common.Views.Header').getDocumentCaption(); + !defFileName && (defFileName = me.txtUntitled); + + if (typeof this.isFromFileDownloadAs == 'string') { + var idx = defFileName.lastIndexOf('.'); + if (idx>0) + defFileName = defFileName.substring(0, idx) + this.isFromFileDownloadAs; + } + + if (me.mode.canRequestSaveAs) { + Common.Gateway.requestSaveAs(url, defFileName, fileType); + } else { + me._saveCopyDlg = new Common.Views.SaveAsDlg({ + saveFolderUrl: me.mode.saveAsUrl, + saveFileUrl: url, + defFileName: defFileName + }); + me._saveCopyDlg.on('saveaserror', function(obj, err){ + var config = { + closable: false, + title: me.notcriticalErrorTitle, + msg: err, + iconCls: 'warn', + buttons: ['ok'], + callback: function(btn){ + Common.NotificationCenter.trigger('edit:complete', me); + } + }; + Common.UI.alert(config); + }).on('close', function(obj){ + me._saveCopyDlg = undefined; + }); + me._saveCopyDlg.show(); + } + } + this.isFromFileDownloadAs = false; + }, + + applySettings: function(menu) { + var value = Common.localStorage.getBool("ve-settings-cachemode", true); + Common.Utils.InternalSettings.set("ve-settings-cachemode", value); + this.api.asc_setDefaultBlitMode(value); + + value = Common.localStorage.getItem("ve-settings-fontrender"); + Common.Utils.InternalSettings.set("ve-settings-fontrender", value); + this.api.SetFontRenderingMode(parseInt(value)); + + if (this.mode.isEdit) { + } + value = Common.localStorage.getBool("app-settings-screen-reader"); + Common.Utils.InternalSettings.set("app-settings-screen-reader", value); + this.api.setSpeechEnabled(value); + + /* update zoom */ + var newZoomValue = Common.localStorage.getItem("ve-settings-zoom"); + var oldZoomValue = Common.Utils.InternalSettings.get("ve-settings-zoom"); + var lastZoomValue = Common.Utils.InternalSettings.get("ve-last-zoom"); + + if (oldZoomValue === null || oldZoomValue == lastZoomValue || oldZoomValue == -3) { + if (newZoomValue == -1) { + this.api.zoomFitToPage(); + } else if (newZoomValue == -2) { + this.api.zoomFitToWidth(); + } else if (newZoomValue > 0) { + this.api.zoom(newZoomValue); + } + } + + Common.Utils.InternalSettings.set("ve-settings-zoom", newZoomValue); + + menu.hide(); + }, + + onCreateNew: function(menu, type) { + if ( !Common.Controllers.Desktop.process('create:new') ) { + if (type == 'blank' && this.mode.canRequestCreateNew) + Common.Gateway.requestCreateNew(); + else { + var newDocumentPage = window.open(type == 'blank' ? this.mode.createUrl : type, "_blank"); + if (newDocumentPage) newDocumentPage.focus(); + } + } + + if (menu) { + menu.hide(); + } + }, + + onOpenRecent: function(menu, url) { + if (menu) { + menu.hide(); + } + + var recentDocPage = window.open(url); + if (recentDocPage) + recentDocPage.focus(); + + Common.component.Analytics.trackEvent('Open Recent'); + }, + + clickToolbarSettings: function(obj) { + this.leftMenu.showMenu('file:opts'); + }, + + clickToolbarTab: function (tab, e) { + if (tab == 'file') + this.leftMenu.showMenu('file'); else + this.leftMenu.menuFile.hide(); + }, + + clickToolbarPrint: function () { + if (this.mode.canPrint) + this.clickMenuFileItem(null, 'print'); + }, + + changeToolbarSaveState: function (state) { + var btnSave = this.leftMenu.menuFile.getButton('save'); + btnSave && btnSave.setDisabled(state); + }, + + /** coauthoring begin **/ + onHideChat: function() { + $(this.leftMenu.btnChat.el).blur(); + Common.NotificationCenter.trigger('layout:changed', 'leftmenu'); + }, + /** coauthoring end **/ + + onHidePlugins: function() { + Common.NotificationCenter.trigger('layout:changed', 'leftmenu'); + }, + + addNewPlugin: function (button, $button, $panel) { + this.leftMenu.insertButton(button, $button); + this.leftMenu.insertPanel($panel); + }, + + onBtnCategoryClick: function (btn) { + if (btn.options.type === 'plugin' && !btn.isDisabled()) { + if (btn.pressed) { + this.tryToShowLeftMenu(); + this.leftMenu.fireEvent('plugins:showpanel', [btn.options.value]); // show plugin panel + } else { + this.leftMenu.fireEvent('plugins:hidepanel', [btn.options.value]); + } + this.leftMenu.onBtnMenuClick(btn); + } + }, + + openPlugin: function (guid) { + this.leftMenu.openPlugin(guid); + }, + + closePlugin: function (guid) { + this.leftMenu.closePlugin(guid); + Common.NotificationCenter.trigger('layout:changed', 'leftmenu'); + }, + + updatePluginButtonsIcons: function (icons) { + this.leftMenu.updatePluginButtonsIcons(icons); + }, + + onApiServerDisconnect: function(enableDownload) { + this.mode.isEdit = false; + this.leftMenu.close(); + + /** coauthoring begin **/ + // this.leftMenu.btnComments.setDisabled(true); + this.leftMenu.btnChat.setDisabled(true); + /** coauthoring end **/ + this.leftMenu.setDisabledPluginButtons(true); + + this.leftMenu.getMenu('file').setMode({isDisconnected: true, enableDownload: !!enableDownload}); + }, + + setPreviewMode: function(mode) { + this._state.disableEditing = mode; + this.updatePreviewMode(); + }, + + updatePreviewMode: function() { + var viewmode = this._state.disableEditing; + if (this.viewmode === viewmode) return; + this.viewmode = viewmode; + this.leftMenu.setDisabledPluginButtons(this.viewmode); + }, + + SetDisabled: function(disable, options) { + if (this.leftMenu._state.disabled !== disable) { + this.leftMenu._state.disabled = disable; + if (this.mode) { + if (disable) { + this.previsEdit = this.mode.isEdit; + this.prevcanEdit = this.mode.canEdit; + this.mode.isEdit = this.mode.canEdit = !disable; + } else { + this.mode.isEdit = this.previsEdit; + this.mode.canEdit = this.prevcanEdit; + } + } + } + + if (disable) this.leftMenu.close(); + + // if (!options || options.comments && options.comments.disable) + // this.leftMenu.btnComments.setDisabled(disable); + if (!options || options.chat) + this.leftMenu.btnChat.setDisabled(disable); + this.leftMenu.btnThumbs.setDisabled(disable); + this.leftMenu.setDisabledPluginButtons(disable); + }, + + /** coauthoring begin **/ + onApiChatMessage: function() { + this.leftMenu.markCoauthOptions('chat'); + }, + + onApiAddComment: function(id, data) { + var resolved = Common.Utils.InternalSettings.get("ve-settings-resolvedcomment"); + if (data && data.asc_getUserId() !== this.mode.user.id && (resolved || !data.asc_getSolved()) && AscCommon.UserInfoParser.canViewComment(data.asc_getUserName())) + this.leftMenu.markCoauthOptions('comments'); + }, + + onApiAddComments: function(data) { + var resolved = Common.Utils.InternalSettings.get("ve-settings-resolvedcomment"); + for (var i = 0; i < data.length; ++i) { + if (data[i].asc_getUserId() !== this.mode.user.id && (resolved || !data[i].asc_getSolved()) && AscCommon.UserInfoParser.canViewComment(data.asc_getUserName())) { + this.leftMenu.markCoauthOptions('comments'); + break; + } + } + }, + + onAppAddComment: function(sender) { + var me = this; + if ( this.api.can_AddQuotedComment() === false ) { + (new Promise(function(resolve, reject) { + resolve(); + })).then(function () { + Common.UI.Menu.Manager.hideAll(); + me.leftMenu.showMenu('comments'); + + var ctrl = VE.getController('Common.Controllers.Comments'); + ctrl.getView().showEditContainer(true); + ctrl.onAfterShow(); + }); + } + }, + + commentsShowHide: function(mode) { + if (mode === 'show') { + this.getApplication().getController('Common.Controllers.Comments').onAfterShow(); + } + $(this.leftMenu.btnComments.el).blur(); + }, + /** coauthoring end **/ + + aboutShowHide: function(value) { + if (this.api) + this.api.asc_enableKeyEvents(value); + if (value) $(this.leftMenu.btnAbout.el).blur(); + if (value && this.leftMenu._state.pluginIsRunning) { + this.leftMenu.panelPlugins.show(); + if (this.mode.canCoAuthoring) { + // this.mode.canViewComments && this.leftMenu.panelComments['hide'](); + this.mode.canChat && this.leftMenu.panelChat['hide'](); + } + } + }, + + menuFilesShowHide: function(state) { + (state === 'hide') && Common.NotificationCenter.trigger('menu:hide'); + }, + + onMenuChange: function (value) { + if ('hide' === value) { + if (this.api) { + // if (this.leftMenu.btnComments.isActive()) { + // this.leftMenu.btnComments.toggle(false); + // this.leftMenu.onBtnMenuClick(this.leftMenu.btnComments); + // // focus to sdk + // this.api.asc_enableKeyEvents(true); + // } else + if (this.leftMenu.btnSearchBar.isActive()) { + this.leftMenu.btnSearchBar.toggle(false); + this.leftMenu.onBtnMenuClick(this.leftMenu.btnSearchBar); + } + else if (this.leftMenu.btnChat.isActive()) { + this.leftMenu.btnChat.toggle(false); + this.leftMenu.onBtnMenuClick(this.leftMenu.btnChat); + } + } + } + }, + + onShortcut: function(s, e) { + if (!this.mode) return; + + switch (s) { + case 'search': + Common.UI.Menu.Manager.hideAll(); + var full_menu_pressed = this.leftMenu.btnAbout.pressed; + this.leftMenu.btnAbout.toggle(false); + full_menu_pressed && this.menuExpand(this.leftMenu.btnAbout, 'files', false); + + var selectedText = this.api.asc_GetSelectedText(); + if (this.isSearchPanelVisible()) { + selectedText && this.leftMenu.panelSearch.setFindText(selectedText); + this.leftMenu.panelSearch.focus(selectedText !== '' ? s : 'search'); + this.leftMenu.fireEvent('search:aftershow', selectedText ? [selectedText] : undefined); + return false; + } else if (this.getApplication().getController('Viewport').isSearchBarVisible()) { + var viewport = this.getApplication().getController('Viewport'); + if (s === 'replace') { + viewport.header.btnSearch.toggle(false); + this.onShowHideSearch(true, viewport.searchBar.inputSearch.val()); + } else { + selectedText && viewport.searchBar.setText(selectedText); + viewport.searchBar.focus(); + return false; + } + } else if (s === 'search') { + Common.NotificationCenter.trigger('search:show'); + return false; + } else { + this.onShowHideSearch(true, selectedText ? selectedText : undefined); + } + this.leftMenu.btnSearchBar.toggle(true,true); + this.leftMenu.panelSearch.focus(selectedText ? s : 'search'); + return false; + case 'save': + if (this.mode.canDownload) { + if (this.mode.isDesktopApp && this.mode.isOffline) this.api.asc_DownloadAs(); + else { + if (this.mode.canDownload) { + Common.UI.Menu.Manager.hideAll(); + this.leftMenu.showMenu('file:saveas'); + } + } + } + return false; + case 'help': + if ( this.mode.canHelp ) { // TODO: unlock 'help' for 'view' mode + Common.UI.Menu.Manager.hideAll(); + this.leftMenu.showMenu('file:help'); + } + return false; + case 'file': + Common.UI.Menu.Manager.hideAll(); + this.leftMenu.showMenu('file'); + return false; + case 'escape': +// if (!this.leftMenu.isOpened()) return true; + var btnSearch = this.getApplication().getController('Viewport').header.btnSearch; + btnSearch.pressed && btnSearch.toggle(false); + + if ( this.leftMenu.menuFile.isVisible() ) { + if (Common.UI.HintManager.needCloseFileMenu()) + this.leftMenu.menuFile.hide(); + return false; + } + + var statusbar = VE.getController('Statusbar'); + var menu_opened = statusbar.statusbar.$el.find('.open > [data-toggle="dropdown"]'); + if (menu_opened.length) { + $.fn.dropdown.Constructor.prototype.keydown.call(menu_opened[0], e); + return false; + } + if (this.mode.canPlugins && this.leftMenu.panelPlugins) { + menu_opened = this.leftMenu.panelPlugins.$el.find('#menu-plugin-container.open > [data-toggle="dropdown"]'); + if (menu_opened.length) { + $.fn.dropdown.Constructor.prototype.keydown.call(menu_opened[0], e); + return false; + } + } + if (this.leftMenu.btnAbout.pressed) { + if (!Common.UI.HintManager.isHintVisible()) { + this.leftMenu.close(); + Common.NotificationCenter.trigger('layout:changed', 'leftmenu'); + } + return false; + } + break; + /** coauthoring begin **/ + case 'chat': + if (this.mode.canCoAuthoring && this.mode.canChat && !this.mode.isLightVersion) { + Common.UI.Menu.Manager.hideAll(); + this.leftMenu.showMenu('chat'); + } + return false; + // case 'comments': + // if (this.mode.canCoAuthoring && this.mode.canViewComments && !this.mode.isLightVersion) { + // Common.UI.Menu.Manager.hideAll(); + // this.leftMenu.showMenu('comments'); + // this.getApplication().getController('Common.Controllers.Comments').onAfterShow(); + // } + // return false; + /** coauthoring end **/ + } + }, + + onPluginOpen: function(panel, type, action) { + if ( type == 'onboard' ) { + if ( action == 'open' ) { + this.tryToShowLeftMenu(); + this.leftMenu.close(); + this.leftMenu.panelPlugins.show(); + this.leftMenu.onBtnMenuClick({pressed:true, options: {action: 'plugins'}}); + this.leftMenu._state.pluginIsRunning = true; + } else { + this.leftMenu._state.pluginIsRunning = false; + this.leftMenu.close(); + } + } + }, + + onShowHideChat: function(state) { + if (this.mode.canCoAuthoring && this.mode.canChat && !this.mode.isLightVersion) { + if (state) { + Common.UI.Menu.Manager.hideAll(); + this.tryToShowLeftMenu(); + this.leftMenu.showMenu('chat'); + } else { + this.leftMenu.btnChat.toggle(false, true); + this.leftMenu.onBtnMenuClick(this.leftMenu.btnChat); + } + } + }, + + onShowHideSearch: function (state, findText) { + if (state) { + Common.UI.Menu.Manager.hideAll(); + this.tryToShowLeftMenu(); + this.leftMenu.showMenu('advancedsearch', undefined, true); + this.leftMenu.fireEvent('search:aftershow', this.leftMenu, findText); + } else { + this.leftMenu.btnSearchBar.toggle(false, true); + this.leftMenu.onBtnMenuClick(this.leftMenu.btnSearchBar); + } + }, + + onMenuSearchBar: function(obj, show) { + if (show) { + this.leftMenu.panelSearch.setSearchMode('no-replace'); + } + }, + + isSearchPanelVisible: function () { + return this.leftMenu && this.leftMenu.panelSearch && this.leftMenu.panelSearch.isVisible(); + }, + + isCommentsVisible: function() { + return this.leftMenu && this.leftMenu.panelComments && this.leftMenu.panelComments.isVisible(); + }, + + onLeftMenuHide: function (view, status) { + if (this.leftMenu) { + if (status) { + this.leftMenu.show(); + } else { + this.menuExpand(this, 'thumbs', false); + this.leftMenu.close(); + this.leftMenu.hide(); + } + Common.localStorage.setBool('ve-hidden-leftmenu', !status); + + !view && this.leftMenu.fireEvent('view:hide', [this, !status]); + } + + Common.NotificationCenter.trigger('layout:changed', 'main'); + Common.NotificationCenter.trigger('edit:complete', this.leftMenu); + }, + + tryToShowLeftMenu: function() { + if ((!this.mode.canBrandingExt || !this.mode.customization || this.mode.customization.leftMenu !== false) && Common.UI.LayoutManager.isElementVisible('leftMenu')) + this.onLeftMenuHide(null, true); + }, + + onShowTumbnails: function(obj, show) { + this.api.ShowThumbnails(show); + + }, + + onThumbnailsShow: function(isShow) { + if (isShow && !this.isThumbsShown) { + this.leftMenu.btnThumbs.toggle(true, false); + } else if (!isShow && this.isThumbsShown) + this.leftMenu.btnThumbs.toggle(false, false); + this.isThumbsShown = isShow; + }, + + menuExpand: function(obj, panel, show) { + if (panel == 'thumbs') { + this.isThumbsShown = show; + } else { + if (!show && this.isThumbsShown && !this.leftMenu._state.pluginIsRunning && !this.leftMenu._state.historyIsRunning) { + this.leftMenu.btnThumbs.toggle(true, false); + } + } + }, + + textNoTextFound : 'Text not found', + newDocumentTitle : 'Unnamed document', + requestEditRightsText : 'Requesting editing rights...', + notcriticalErrorTitle: 'Warning', + leavePageText: 'All unsaved changes in this document will be lost.
Click \'Cancel\' then \'Save\' to save them. Click \'OK\' to discard all the unsaved changes.', + txtUntitled: 'Untitled', + textSelectPath: 'Enter a new name for saving the file copy' + + }, VE.Controllers.LeftMenu || {})); +}); \ No newline at end of file diff --git a/apps/visioeditor/main/app/controller/Main.js b/apps/visioeditor/main/app/controller/Main.js new file mode 100644 index 0000000000..dd9b33d523 --- /dev/null +++ b/apps/visioeditor/main/app/controller/Main.js @@ -0,0 +1,2154 @@ +/* + * (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 + * + */ +/** + * Main.js + * + * Main controller + * + * Created on 11/07/24 + * + */ + +define([ + 'core', + 'irregularstack', + 'common/main/lib/component/Window', + 'common/main/lib/component/LoadMask', + 'common/main/lib/component/Tooltip', + 'common/main/lib/util/LocalStorage', + 'common/main/lib/controller/FocusManager', + 'common/main/lib/controller/LaunchController', + 'common/main/lib/controller/HintManager', + 'common/main/lib/controller/LayoutManager', + 'common/main/lib/controller/ExternalUsers', + 'common/main/lib/view/OpenDialog', + 'common/main/lib/view/UserNameDialog' +], function () { + 'use strict'; + + VE.Controllers.Main = Backbone.Controller.extend(_.extend((function() { + var appHeader; + var ApplyEditRights = -255; + var LoadingDocument = -256; + + var mapCustomizationElements = { + about: 'button#left-btn-about', + feedback: 'button#left-btn-support' + }; + + var mapCustomizationExtElements = { + toolbar: '#viewport #toolbar', + leftMenu: '#viewport #left-menu, #viewport #id-toolbar-full-placeholder-btn-settings, #viewport #id-toolbar-short-placeholder-btn-settings', + statusBar: '#statusbar' + }; + + Common.localStorage.setId('visio'); + Common.localStorage.setKeysFilter('ve-,asc.visio'); + Common.localStorage.sync(); + + return { + + models: [], + collections: [ + ], + views: [], + + initialize: function() { + this.addListeners({ + 'FileMenu': { + 'settings:apply': _.bind(this.applySettings, this) + } + }); + + this.translationTable = { + }; + }, + + onLaunch: function() { + var me = this; + + this.stackLongActions = new Common.IrregularStack({ + strongCompare : function(obj1, obj2){return obj1.id === obj2.id && obj1.type === obj2.type;}, + weakCompare : function(obj1, obj2){return obj1.type === obj2.type;} + }); + + this.stackDisableActions = new Common.IrregularStack({ + strongCompare : function(obj1, obj2){return obj1.type === obj2.type;}, + weakCompare : function(obj1, obj2){return obj1.type === obj2.type;} + }); + + this.stackMacrosRequests = []; + + this._state = {isDisconnected: false, usersCount: 1, fastCoauth: true, lostEditingRights: false, licenseType: false, isDocModified: false}; + this.languages = null; + + // Initialize viewport + + if (!Common.Utils.isBrowserSupported()){ + Common.Utils.showBrowserRestriction(); + Common.Gateway.reportError(undefined, this.unsupportedBrowserErrorText); + return; + } + + // Initialize api + window["flat_desine"] = true; + this.api = this.getApplication().getController('Viewport').getApi(); + + Common.UI.FocusManager.init(); + Common.UI.HintManager.init(this.api); + Common.UI.Themes.init(this.api); + Common.Controllers.LaunchController.init(this.api); + + if (this.api){ + this.api.SetDrawingFreeze(true); + + var value = Common.localStorage.getBool("ve-settings-cachemode", true); + Common.Utils.InternalSettings.set("ve-settings-cachemode", value); + this.api.asc_setDefaultBlitMode(!!value); + + value = Common.localStorage.getItem("ve-settings-fontrender"); + if (value === null) + value = '0'; + Common.Utils.InternalSettings.set("ve-settings-fontrender", value); + switch (value) { + case '0': this.api.SetFontRenderingMode(3); break; + case '1': this.api.SetFontRenderingMode(1); break; + case '2': this.api.SetFontRenderingMode(2); break; + } + + value = Common.localStorage.getBool("app-settings-screen-reader"); + Common.Utils.InternalSettings.set("app-settings-screen-reader", value); + this.api.setSpeechEnabled(value); + + if ( !Common.Utils.isIE ) { + if ( /^https?:\/\//.test('{{HELP_CENTER_WEB_DE}}') ) { + const _url_obj = new URL('{{HELP_CENTER_WEB_DE}}'); + if ( !!_url_obj.searchParams ) + _url_obj.searchParams.set('lang', Common.Locale.getCurrentLanguage()); + + Common.Utils.InternalSettings.set("url-help-center", _url_obj.toString()); + } + } + + this.api.asc_registerCallback('asc_onError', _.bind(this.onError, this)); + this.api.asc_registerCallback('asc_onDocumentContentReady', _.bind(this.onDocumentContentReady, this)); + this.api.asc_registerCallback('asc_onOpenDocumentProgress', _.bind(this.onOpenDocument, this)); + this.api.asc_registerCallback('asc_onDocumentUpdateVersion', _.bind(this.onUpdateVersion, this)); + this.api.asc_registerCallback('asc_onServerVersion', _.bind(this.onServerVersion, this)); + this.api.asc_registerCallback('asc_onAdvancedOptions', _.bind(this.onAdvancedOptions, this)); + this.api.asc_registerCallback('asc_onDocumentName', _.bind(this.onDocumentName, this)); + this.api.asc_registerCallback('asc_onPrintUrl', _.bind(this.onPrintUrl, this)); + this.api.asc_registerCallback('asc_onMeta', _.bind(this.onMeta, this)); + // this.api.asc_registerCallback('asc_onThumbnailsShow', _.bind(this.onThumbnailsShow, this)); + + Common.NotificationCenter.on('api:disconnect', _.bind(this.onCoAuthoringDisconnect, this)); + Common.NotificationCenter.on('goback', _.bind(this.goBack, this)); + Common.NotificationCenter.on('close', _.bind(this.closeEditor, this)); + Common.NotificationCenter.on('markfavorite', _.bind(this.markFavorite, this)); + Common.NotificationCenter.on('download:advanced', _.bind(this.onAdvancedOptions, this)); + Common.NotificationCenter.on('showmessage', _.bind(this.onExternalMessage, this)); + Common.NotificationCenter.on('showerror', _.bind(this.onError, this)); + Common.NotificationCenter.on('editing:disable', _.bind(this.onEditingDisable, this)); + + this.isShowOpenDialog = false; + + // Initialize api gateway + this.editorConfig = {}; + this.appOptions = {}; + Common.Gateway.on('init', _.bind(this.loadConfig, this)); + Common.Gateway.on('showmessage', _.bind(this.onExternalMessage, this)); + Common.Gateway.on('opendocument', _.bind(this.loadDocument, this)); + Common.Gateway.on('opendocumentfrombinary', _.bind(this.loadBinary, this)); + Common.Gateway.on('grabfocus', _.bind(this.onGrabFocus, this)); + Common.Gateway.appReady(); + +// $(window.top).resize(_.bind(this.onDocumentResize, this)); + this.getApplication().getController('Viewport').setApi(this.api); + this.getApplication().getController('Statusbar').setApi(this.api); + + // this.contComments = this.getApplication().getController('Common.Controllers.Comments'); + + // Syncronize focus with api + $(document.body).on('focus', 'input, textarea', function(e) { + if (!/area_id/.test(e.target.id)) { + if (/msg-reply/.test(e.target.className)) { + me.dontCloseDummyComment = true; + me.beforeShowDummyComment = me.beforeCloseDummyComment = false; + } else if (/textarea-control/.test(e.target.className)) + me.inTextareaControl = true; + else if (!Common.Utils.ModalWindow.isVisible() && /form-control/.test(e.target.className)) + me.inFormControl = true; + } + }); + + $(document.body).on('blur', 'input, textarea', function(e) { + if (!Common.Utils.ModalWindow.isVisible()) { + if (/form-control/.test(e.target.className)) + me.inFormControl = false; + if (me.getApplication().getController('LeftMenu').getView('LeftMenu').getMenu('file').isVisible()) + return; + if (!e.relatedTarget || + !/area_id/.test(e.target.id) + && !(e.target.localName == 'input' && $(e.target).parent().find(e.relatedTarget).length>0) /* Check if focus in combobox goes from input to it's menu button or menu items, or from comment editing area to Ok/Cancel button */ + && !(e.target.localName == 'textarea' && $(e.target).closest('.asc-window').find('.dropdown-menu').find(e.relatedTarget).length>0) /* Check if focus in comment goes from textarea to it's email menu */ + && (e.relatedTarget.localName != 'input' || !/form-control/.test(e.relatedTarget.className)) /* Check if focus goes to text input with class "form-control" */ + && (e.relatedTarget.localName != 'textarea' || /area_id/.test(e.relatedTarget.id))) /* Check if focus goes to textarea, but not to "area_id" */ { + if (Common.Utils.isIE && e.originalEvent && e.originalEvent.target && /area_id/.test(e.originalEvent.target.id) && (e.originalEvent.target === e.originalEvent.srcElement)) + return; + if (Common.Utils.isLinux && me.appOptions && me.appOptions.isDesktopApp) { + if (e.relatedTarget || !e.originalEvent || e.originalEvent.sourceCapabilities) + me.api.asc_enableKeyEvents(true); + } else + me.api.asc_enableKeyEvents(true); + if (me.dontCloseDummyComment && /msg-reply/.test(e.target.className)) { + if ($(e.target).closest('.user-comment-item').find(e.relatedTarget).length<1) /* Check if focus goes to buttons in the comment window */ + me.dontCloseDummyComment = me.beforeCloseDummyComment = false; + else + me.beforeCloseDummyComment = true; + } + else if (/textarea-control/.test(e.target.className)) + me.inTextareaControl = false; + } + } + }).on('dragover', function(e) { + var event = e.originalEvent; + if (event.target && $(event.target).closest('#editor_sdk').length<1 ) { + event.preventDefault(); + event.dataTransfer.dropEffect ="none"; + return false; + } + }).on('dragstart', function(e) { + var event = e.originalEvent; + if (event.target ) { + var target = $(event.target); + if (target.closest('.combobox').length>0 || target.closest('.dropdown-menu').length>0 || + target.closest('.input-field').length>0 || target.closest('.spinner').length>0 || target.closest('.textarea-field').length>0 || + target.closest('.ribtab').length>0 || target.closest('.combo-dataview').length>0) { + event.preventDefault(); + } + } + }).on('mouseup', function(e){ + me.beforeCloseDummyComment && setTimeout(function(){ // textbox in dummy comment lost focus + me.dontCloseDummyComment = me.beforeCloseDummyComment = false; + }, 10); + }); + + Common.Utils.isChrome && $(document.body).on('keydown', 'textarea', function(e) {// chromium bug890248 (Bug 39614) + if (e.keyCode===Common.UI.Keys.PAGEUP || e.keyCode===Common.UI.Keys.PAGEDOWN) { + setTimeout(function(){ + $('#viewport').scrollLeft(0); + $('#viewport').scrollTop(0); + }, 0); + } + }); + + Common.NotificationCenter.on({ + 'modal:show': function(){ + Common.Utils.ModalWindow.show(); + me.api.asc_enableKeyEvents(false); + }, + 'modal:close': function(dlg) { + Common.Utils.ModalWindow.close(); + if (!Common.Utils.ModalWindow.isVisible()) + me.api.asc_enableKeyEvents(true); + }, + 'modal:hide': function(dlg) { + Common.Utils.ModalWindow.close(); + if (!Common.Utils.ModalWindow.isVisible()) + me.api.asc_enableKeyEvents(true); + }, + 'settings:unitschanged':_.bind(this.unitsChanged, this), + 'dataview:focus': function(e){ + }, + 'dataview:blur': function(e){ + if (!Common.Utils.ModalWindow.isVisible()) { + me.api.asc_enableKeyEvents(true); + } + }, + 'menu:show': function(e){ + }, + 'menu:hide': function(e, isFromInputControl){ + if (!Common.Utils.ModalWindow.isVisible() && !isFromInputControl) + me.api.asc_enableKeyEvents(true); + }, + 'edit:complete': _.bind(me.onEditComplete, me) + }); + + Common.util.Shortcuts.delegateShortcuts({ + shortcuts: { + 'command+s,ctrl+s,command+p,ctrl+p,command+d,ctrl+d': _.bind(function (e) { + e.preventDefault(); + e.stopPropagation(); + }, this) + } + }); + } + + me.defaultTitleText = '{{APP_TITLE_TEXT}}'; + me.warnNoLicense = me.warnNoLicense.replace(/%1/g, '{{COMPANY_NAME}}'); + me.warnNoLicenseUsers = me.warnNoLicenseUsers.replace(/%1/g, '{{COMPANY_NAME}}'); + me.textNoLicenseTitle = me.textNoLicenseTitle.replace(/%1/g, '{{COMPANY_NAME}}'); + me.warnLicenseExceeded = me.warnLicenseExceeded.replace(/%1/g, '{{COMPANY_NAME}}'); + me.warnLicenseUsersExceeded = me.warnLicenseUsersExceeded.replace(/%1/g, '{{COMPANY_NAME}}'); + }, + + loadConfig: function(data) { + this.editorConfig = $.extend(this.editorConfig, data.config); + + this.appOptions.customization = this.editorConfig.customization; + this.appOptions.canRenameAnonymous = !((typeof (this.appOptions.customization) == 'object') && (typeof (this.appOptions.customization.anonymous) == 'object') && (this.appOptions.customization.anonymous.request===false)); + this.appOptions.guestName = (typeof (this.appOptions.customization) == 'object') && (typeof (this.appOptions.customization.anonymous) == 'object') && + (typeof (this.appOptions.customization.anonymous.label) == 'string') && this.appOptions.customization.anonymous.label.trim()!=='' ? + Common.Utils.String.htmlEncode(this.appOptions.customization.anonymous.label) : this.textGuest; + var value; + if (this.appOptions.canRenameAnonymous) { + value = Common.localStorage.getItem("guest-username"); + Common.Utils.InternalSettings.set("guest-username", value); + Common.Utils.InternalSettings.set("save-guest-username", !!value); + } + if (this.appOptions.customization.font) { + if (this.appOptions.customization.font.name && typeof this.appOptions.customization.font.name === 'string') { + var arr = this.appOptions.customization.font.name.split(','); + for (var i=0; i
'); + } + + this.api.asc_registerCallback('asc_onGetEditorPermissions', _.bind(this.onEditorPermissions, this)); + this.api.asc_registerCallback('asc_onLicenseChanged', _.bind(this.onLicenseChanged, this)); + // this.api.asc_registerCallback('asc_onRunAutostartMacroses', _.bind(this.onRunAutostartMacroses, this)); + this.api.asc_setDocInfo(docInfo); + this.api.asc_getEditorPermissions(this.editorConfig.licenseUrl, this.editorConfig.customerId); + + if (data.doc) { + appHeader.setDocumentCaption(data.doc.title); + } + }, + + onRunAutostartMacroses: function() { + if (!this.editorConfig.customization || (this.editorConfig.customization.macros!==false)) { + this.api.asc_runAutostartMacroses(); + } + }, + + onProcessSaveResult: function(data) { + this.api.asc_OnSaveEnd(data.result); + if (data && data.result === false) { + Common.UI.error({ + title: this.criticalErrorTitle, + msg : _.isEmpty(data.message) ? this.errorProcessSaveResult : data.message + }); + } + }, + + onProcessRightsChange: function(data) { + if (data && data.enabled === false) { + var me = this, + old_rights = this._state.lostEditingRights; + this._state.lostEditingRights = !this._state.lostEditingRights; + this.api.asc_coAuthoringDisconnect(); + Common.NotificationCenter.trigger('collaboration:sharingdeny'); + Common.NotificationCenter.trigger('api:disconnect'); + if (!old_rights) + Common.UI.warning({ + title: this.notcriticalErrorTitle, + maxwidth: 600, + msg : _.isEmpty(data.message) ? this.warnProcessRightsChange : data.message, + callback: function(){ + me._state.lostEditingRights = false; + me.onEditComplete(); + } + }); + } + }, + + onDownloadAs: function(format) { + if ( !this.appOptions.canDownload && !this.appOptions.canDownloadOrigin) { + Common.Gateway.reportError(Asc.c_oAscError.ID.AccessDeny, this.errorAccessDeny); + return; + } + + this._state.isFromGatewayDownloadAs = true; + var _format = (format && (typeof format == 'string')) ? Asc.c_oAscFileType[ format.toUpperCase() ] : null, + _supported = [ + Asc.c_oAscFileType.VSDX, + Asc.c_oAscFileType.PDF, + Asc.c_oAscFileType.PDFA + ]; + + if ( !_format || _supported.indexOf(_format) < 0 ) + _format = Asc.c_oAscFileType.VSDX; + var options = new Asc.asc_CDownloadOptions(_format, true); + options.asc_setIsSaveAs(true); + this.api.asc_DownloadAs(options); + }, + + onProcessMouse: function(data) { + if (data.type == 'mouseup') { + var e = document.getElementById('editor_sdk'); + if (e) { + var r = Common.Utils.getBoundingClientRect(e); + this.api.OnMouseUp( + data.x - r.left, + data.y - r.top + ); + } + } + }, + + disableEditing: function(disable, type) { + !type && (type = 'disconnect'); + var temp = type==='reconnect'; + Common.NotificationCenter.trigger('editing:disable', disable, { + viewMode: disable, + allowSignature: false, + statusBar: true, + // rightMenu: {clear: !temp, disable: true}, + leftMenu: {disable: true, previewMode: true}, + fileMenu: {protect: true}, + comments: {disable: !temp, previewMode: true}, + chat: true, + viewport: true, + documentHolder: {clear: !temp, disable: true}, + toolbar: true, + // plugins: false, + header: {search: type==='not-loaded'}, + shortcuts: type==='not-loaded' + }, type || 'disconnect'); + }, + + onEditingDisable: function(disable, options, type) { + var app = this.getApplication(); + + var action = {type: type, disable: disable, options: options}; + if (disable && !this.stackDisableActions.get({type: type})) + this.stackDisableActions.push(action); + !disable && this.stackDisableActions.pop({type: type}); + var prev_options = !disable && (this.stackDisableActions.length()>0) ? this.stackDisableActions.get(this.stackDisableActions.length()-1) : null; + + if (options.statusBar) { + app.getController('Statusbar').getView('Statusbar').SetDisabled(disable); + } + if (options.viewport) { + app.getController('Viewport').SetDisabled(disable); + } + if (options.toolbar) { + app.getController('Toolbar').DisableToolbar(disable, options.viewMode, options.reviewMode, options.fillFormMode); + } + if (options.documentHolder) { + options.documentHolder.clear && app.getController('DocumentHolder').clearSelection(); + options.documentHolder.disable && app.getController('DocumentHolder').SetDisabled(disable, options.allowProtect, options.fillFormMode); + } + if (options.leftMenu) { + if (options.leftMenu.disable) + app.getController('LeftMenu').SetDisabled(disable, options); + if (options.leftMenu.previewMode) + app.getController('LeftMenu').setPreviewMode(disable); + } + if (options.fileMenu) { + app.getController('LeftMenu').leftMenu.getMenu('file').SetDisabled(disable, options.fileMenu); + if (options.leftMenu.disable) + app.getController('LeftMenu').leftMenu.getMenu('file').applyMode(); + } + if (options.comments) { + var comments = this.getApplication().getController('Common.Controllers.Comments'); + if (comments && options.comments.previewMode) + comments.setPreviewMode(disable); + } + // if (options.plugins) { + // app.getController('Common.Controllers.Plugins').getView('Common.Views.Plugins').SetDisabled(disable, options.reviewMode, options.fillFormMode); + // } + if (options.header) { + if (options.header.search) + appHeader && appHeader.lockHeaderBtns('search', disable); + } + + if (options.shortcuts) { + disable ? Common.util.Shortcuts.suspendEvents() : Common.util.Shortcuts.resumeEvents(); + } + + if (prev_options) { + this.onEditingDisable(prev_options.disable, prev_options.options, prev_options.type); + } + }, + + disableLiveViewing: function(disable) { + this.appOptions.canLiveView = !disable; + this.api.asc_SetFastCollaborative(!disable); + Common.Utils.InternalSettings.set("ve-settings-coauthmode", !disable); + }, + + onRequestClose: function() { + var me = this; + if (this.api.isDocumentModified()) { + this.api.asc_stopSaving(); + Common.UI.warning({ + closable: false, + width: 500, + title: this.notcriticalErrorTitle, + msg: this.leavePageTextOnClose, + buttons: ['ok', 'cancel'], + primary: 'ok', + callback: function(btn) { + if (btn == 'ok') { + me.api.asc_undoAllChanges(); + me.api.asc_continueSaving(); + Common.Gateway.requestClose(); + // Common.Controllers.Desktop.requestClose(); + } else + me.api.asc_continueSaving(); + } + }); + } else { + Common.Gateway.requestClose(); + // Common.Controllers.Desktop.requestClose(); + } + }, + + goBack: function(current) { + if ( !Common.Controllers.Desktop.process('goback') ) { + if (this.appOptions.customization.goback.requestClose && this.appOptions.canRequestClose) { + this.onRequestClose(); + } else { + var href = this.appOptions.customization.goback.url; + if (!current && this.appOptions.customization.goback.blank!==false) { + window.open(href, "_blank"); + } else { + parent.location.href = href; + } + } + } + }, + + closeEditor: function() { + this.appOptions.canRequestClose && this.onRequestClose(); + }, + + markFavorite: function(favorite) { + if ( !Common.Controllers.Desktop.process('markfavorite') ) { + Common.Gateway.metaChange({ + favorite: favorite + }); + } + }, + + onSetFavorite: function(favorite) { + this.appOptions.canFavorite && appHeader.setFavorite(!!favorite); + }, + + onEditComplete: function(cmp) { + var application = this.getApplication(), + toolbarController = application.getController('Toolbar'), + toolbarView = toolbarController.getView(); + + application.getController('DocumentHolder').getView().focus(); + + // if (this.api && this.appOptions.isEdit && this.api.asc_isDocumentCanSave) { + // var cansave = this.api.asc_isDocumentCanSave(), + // forcesave = this.appOptions.forcesave || this.appOptions.canSaveDocumentToBinary, + // isSyncButton = (toolbarView.btnCollabChanges.rendered) ? toolbarView.btnCollabChanges.cmpEl.hasClass('notify') : false, + // isDisabled = !cansave && !isSyncButton && !forcesave || this._state.isDisconnected || this._state.fastCoauth && this._state.usersCount>1 && !forcesave; + // toolbarView.btnSave.setDisabled(isDisabled); + // } + Common.UI.HintManager.clearHints(true); + }, + + onLongActionBegin: function(type, id) { + var action = {id: id, type: type}; + this.stackLongActions.push(action); + this.setLongActionView(action); + }, + + onLongActionEnd: function(type, id) { + var action = {id: id, type: type}; + this.stackLongActions.pop(action); + + appHeader && appHeader.setDocumentCaption(this.api.asc_getDocumentName()); + this.updateWindowTitle(true); + + action = this.stackLongActions.get({type: Asc.c_oAscAsyncActionType.Information}); + if (action) { + this.setLongActionView(action) + } else { + var me = this; + if ((id==Asc.c_oAscAsyncAction['Save'] || id==Asc.c_oAscAsyncAction['ForceSaveButton']) && !this.appOptions.isOffline) { + if (this._state.fastCoauth && this._state.usersCount>1) { + me._state.timerSave = setTimeout(function () { + me.getApplication().getController('Statusbar').setStatusCaption(me.textChangesSaved, false, 3000); + }, 500); + } else + me.getApplication().getController('Statusbar').setStatusCaption(me.textChangesSaved, false, 3000); + } else + this.getApplication().getController('Statusbar').setStatusCaption(''); + } + + action = this.stackLongActions.get({type: Asc.c_oAscAsyncActionType.BlockInteraction}); + action ? this.setLongActionView(action) : this.loadMask && this.loadMask.hide(); + + // if (this.appOptions.isEdit && (id==Asc.c_oAscAsyncAction['Save'] || id==Asc.c_oAscAsyncAction['ForceSaveButton']) && (!this._state.fastCoauth || this._state.usersCount<2)) + // this.synchronizeChanges(); + // else if (this.appOptions.isEdit && (id==Asc.c_oAscAsyncAction['Save'] || id==Asc.c_oAscAsyncAction['ForceSaveButton'] || id == Asc.c_oAscAsyncAction['ApplyChanges']) && + // this._state.fastCoauth) + // this.getApplication().getController('Common.Controllers.ReviewChanges').synchronizeChanges(); + + if ( id == Asc.c_oAscAsyncAction['Disconnect']) { + this._state.timerDisconnect && clearTimeout(this._state.timerDisconnect); + this.disableEditing(false, 'reconnect'); + this.getApplication().getController('Statusbar').hideDisconnectTip(); + this.getApplication().getController('Statusbar').setStatusCaption(this.textReconnect); + } + + if ( type == Asc.c_oAscAsyncActionType.BlockInteraction && + (!this.getApplication().getController('LeftMenu').dlgSearch || !this.getApplication().getController('LeftMenu').dlgSearch.isVisible()) && + (!this.getApplication().getController('Toolbar').dlgSymbolTable || !this.getApplication().getController('Toolbar').dlgSymbolTable.isVisible()) && + !((id == Asc.c_oAscAsyncAction['LoadDocumentFonts'] || id == Asc.c_oAscAsyncAction['LoadFonts'] || id == Asc.c_oAscAsyncAction['ApplyChanges'] || id == Asc.c_oAscAsyncAction['DownloadAs']) && (this.dontCloseDummyComment || this.inTextareaControl || Common.Utils.ModalWindow.isVisible() || this.inFormControl)) ) { +// this.onEditComplete(this.loadMask); //если делать фокус, то при принятии чужих изменений, заканчивается свой композитный ввод + this.api.asc_enableKeyEvents(true); + } + }, + + setLongActionView: function(action) { + var title = '', text = '', force = false; + var statusCallback = null; // call after showing status + + switch (action.id) { + case Asc.c_oAscAsyncAction['Open']: + title = this.openTitleText; + text = this.openTextText; + break; + + case Asc.c_oAscAsyncAction['Save']: + case Asc.c_oAscAsyncAction['ForceSaveButton']: + clearTimeout(this._state.timerSave); + force = true; + title = this.saveTitleText; + text = (!this.appOptions.isOffline) ? this.saveTextText : ''; + break; + + case Asc.c_oAscAsyncAction['LoadDocumentFonts']: + title = this.loadFontsTitleText; + text = this.loadFontsTextText; + break; + + case Asc.c_oAscAsyncAction['LoadDocumentImages']: + title = this.loadImagesTitleText; + text = this.loadImagesTextText; + break; + + case Asc.c_oAscAsyncAction['LoadFont']: + title = this.loadFontTitleText; + text = this.loadFontTextText; + break; + + case Asc.c_oAscAsyncAction['LoadImage']: + title = this.loadImageTitleText; + text = this.loadImageTextText; + break; + + case Asc.c_oAscAsyncAction['DownloadAs']: + title = this.downloadTitleText; + text = this.downloadTextText; + break; + + case Asc.c_oAscAsyncAction['Print']: + title = this.printTitleText; + text = this.printTextText; + break; + + case Asc.c_oAscAsyncAction['UploadImage']: + title = this.uploadImageTitleText; + text = this.uploadImageTextText; + break; + + case Asc.c_oAscAsyncAction['ApplyChanges']: + title = this.applyChangesTitleText; + text = this.applyChangesTextText; + break; + + case Asc.c_oAscAsyncAction['Waiting']: + title = this.waitText; + text = this.waitText; + break; + + case ApplyEditRights: + title = this.txtEditingMode; + text = this.txtEditingMode; + break; + + case LoadingDocument: + title = this.loadingDocumentTitleText + ' '; + text = this.loadingDocumentTextText; + break; + + case Asc.c_oAscAsyncAction['Disconnect']: + text = this.textDisconnect; + Common.UI.Menu.Manager.hideAll(); + this.disableEditing(true, 'reconnect'); + var me = this; + statusCallback = function() { + me._state.timerDisconnect = setTimeout(function(){ + me.getApplication().getController('Statusbar').showDisconnectTip(); + }, me._state.unloadTimer || 0); + }; + break; + + default: + if (typeof action.id == 'string'){ + title = action.id; + text = action.id; + } + break; + } + + if (action.type == Asc.c_oAscAsyncActionType['BlockInteraction']) { + if (!this.loadMask) + this.loadMask = new Common.UI.LoadMask({owner: $('#viewport')}); + + this.loadMask.setTitle(title); + + if (!this.isShowOpenDialog) + this.loadMask.show(action.id===Asc.c_oAscAsyncAction['Open']); + } else { + this.getApplication().getController('Statusbar').setStatusCaption(text, force, 0, statusCallback); + } + }, + + onApplyEditRights: function(data) { + this.getApplication().getController('Statusbar').setStatusCaption(''); + + if (data && !data.allowed) { + Common.UI.info({ + title: this.requestEditFailedTitleText, + msg: data.message || this.requestEditFailedMessageText + }); + } + }, + + onDocumentContentReady: function() { + if (this._isDocReady) + return; + + if (this._state.openDlg) + this._state.openDlg.close(); + + var me = this, + value; + + value = Common.localStorage.getItem("ve-settings-zoom"); + Common.Utils.InternalSettings.set("ve-settings-zoom", value); + var zf = (value!==null) ? parseInt(value) : (this.appOptions.customization && this.appOptions.customization.zoom ? parseInt(this.appOptions.customization.zoom) : 100); + value = Common.localStorage.getItem("ve-last-zoom"); + var lastZoom = (value!==null) ? parseInt(value):0; + + me._isDocReady = true; + Common.NotificationCenter.trigger('app:ready', this.appOptions); + + me.api.SetDrawingFreeze(false); + me.hidePreloader(); + me.onLongActionEnd(Asc.c_oAscAsyncActionType['BlockInteraction'], LoadingDocument); + + // Common.Utils.InternalSettings.set("ve-settings-livecomment", true); + // Common.Utils.InternalSettings.set("ve-settings-resolvedcomment", false); + + if (zf == -1) { + this.api.zoomFitToPage(); + } else if (zf == -2) { + this.api.zoomFitToWidth(); + } else if (zf == -3) { + if (lastZoom > 0) { + this.api.zoom(lastZoom); + } else if (lastZoom == -1) { + this.api.zoomFitToPage(); + } else if (lastZoom == -2) { + this.api.zoomFitToWidth(); + } + } else { + this.api.zoom(zf > 0 ? zf : 100); + } + + + value = Common.localStorage.getBool("ve-settings-compatible", false); + Common.Utils.InternalSettings.set("ve-settings-compatible", value); + + function checkWarns() { + if (!Common.Controllers.Desktop.isActive()) { + var tips = []; + Common.Utils.isIE9m && tips.push(me.warnBrowserIE9); + + if (tips.length) me.showTips(tips); + } + document.removeEventListener('visibilitychange', checkWarns); + } + + if (typeof document.hidden !== 'undefined' && document.hidden) { + document.addEventListener('visibilitychange', checkWarns); + } else checkWarns(); + + me.api.asc_registerCallback('asc_onStartAction', _.bind(me.onLongActionBegin, me)); + me.api.asc_registerCallback('asc_onEndAction', _.bind(me.onLongActionEnd, me)); + me.api.asc_registerCallback('asc_onCoAuthoringDisconnect', _.bind(me.onCoAuthoringDisconnect, me)); + me.api.asc_registerCallback('asc_onPrint', _.bind(me.onPrint, me)); + // me.api.asc_registerCallback('asc_onConfirmAction', _.bind(me.onConfirmAction, me)); + + appHeader.setDocumentCaption(me.api.asc_getDocumentName()); + me.updateWindowTitle(true); + + value = Common.localStorage.getBool("ve-settings-show-alt-hints", Common.Utils.isMac ? false : true); + Common.Utils.InternalSettings.set("ve-settings-show-alt-hints", value); + + /** coauthoring begin **/ + me.onCoAuthApply(); + /** coauthoring end **/ + + var application = me.getApplication(); + var toolbarController = application.getController('Toolbar'), + statusbarController = application.getController('Statusbar'), + documentHolderController = application.getController('DocumentHolder'), + leftmenuController = application.getController('LeftMenu'), + chatController = application.getController('Common.Controllers.Chat'); + // pluginsController = application.getController('Common.Controllers.Plugins'); + + + leftmenuController.getView('LeftMenu').getMenu('file').loadDocument({doc:me.document}); + leftmenuController.createDelayedElements().setApi(me.api); + + chatController.setApi(this.api).setMode(this.appOptions); + // pluginsController.setApi(me.api); + + documentHolderController.setApi(me.api); + statusbarController.createDelayedElements(); + + leftmenuController.getView('LeftMenu').disableMenu('all',false); + + if (me.appOptions.canBranding) + me.getApplication().getController('LeftMenu').leftMenu.getMenu('about').setLicInfo(me.editorConfig.customization); + + documentHolderController.getView().on('editcomplete', _.bind(me.onEditComplete, me)); + + if (me.appOptions.isEdit) { + if (me.appOptions.isEdit && me.appOptions.canForcesave) {// use asc_setIsForceSaveOnUserSave only when customization->forcesave = true + me.appOptions.forcesave = Common.localStorage.getBool("ve-settings-forcesave", me.appOptions.canForcesave); + Common.Utils.InternalSettings.set("ve-settings-forcesave", me.appOptions.forcesave); + me.api.asc_setIsForceSaveOnUserSave(me.appOptions.forcesave); + } + + if (me.needToUpdateVersion) + Common.NotificationCenter.trigger('api:disconnect'); + + var timer_sl = setTimeout(function(){ + toolbarController.createDelayedElements(); + toolbarController.activateControls(); + documentHolderController.applyEditorMode(); + if (me.needToUpdateVersion) + toolbarController.onApiCoAuthoringDisconnect(); + toolbarController.onApiFocusObject([]); + me.api.UpdateInterfaceState(); + + Common.NotificationCenter.trigger('document:ready', 'main'); + me.applyLicense(); + }, 500); + } else { + Common.NotificationCenter.trigger('document:ready', 'main'); + Common.Utils.injectSvgIcons(); + me.applyLicense(); + } + + // TODO bug 43960 + var dummyClass = ~~(1e6*Math.random()); + $('.toolbar').prepend(Common.Utils.String.format('
', dummyClass)); + setTimeout(function() { $(Common.Utils.String.format('.toolbar .lazy-{0}', dummyClass)).remove(); }, 10); + + if (this.appOptions.canAnalytics && false) + Common.component.Analytics.initialize('UA-12442749-13', 'Document Editor'); + + Common.Gateway.on('applyeditrights', _.bind(me.onApplyEditRights, me)); + // Common.Gateway.on('processsaveresult', _.bind(me.onProcessSaveResult, me)); + Common.Gateway.on('processrightschange', _.bind(me.onProcessRightsChange, me)); + Common.Gateway.on('processmouse', _.bind(me.onProcessMouse, me)); + Common.Gateway.on('downloadas', _.bind(me.onDownloadAs, me)); + Common.Gateway.on('setfavorite', _.bind(me.onSetFavorite, me)); + Common.Gateway.on('requestclose', _.bind(me.onRequestClose, me)); + this.appOptions.canRequestSaveAs && Common.Gateway.on('internalcommand', function(data) { + if (data.command == 'wopi:saveAsComplete') { + me.onExternalMessage({msg: me.txtSaveCopyAsComplete}); + } + }); + Common.Gateway.sendInfo({mode:me.appOptions.isEdit?'edit':'view'}); + + if (!!me.appOptions.sharingSettingsUrl && me.appOptions.sharingSettingsUrl.length || me.appOptions.canRequestSharingSettings) { + Common.Gateway.on('showsharingsettings', _.bind(me.changeAccessRights, me)); + Common.Gateway.on('setsharingsettings', _.bind(me.setSharingSettings, me)); + Common.NotificationCenter.on('collaboration:sharing', _.bind(me.changeAccessRights, me)); + Common.NotificationCenter.on('collaboration:sharingdeny', _.bind(me.setSharingSettings, me)); + } + + $(document).on('contextmenu', _.bind(me.onContextMenu, me)); + Common.Gateway.documentReady(); + + $('.doc-placeholder').remove(); + + this.appOptions.user.guest && this.appOptions.canRenameAnonymous && (Common.Utils.InternalSettings.get("guest-username")===null) && this.showRenameUserDialog(); + if (this._needToSaveAsFile) // warning received before document is ready + this.getApplication().getController('LeftMenu').leftMenu.showMenu('file:saveas'); + }, + + onLicenseChanged: function(params) { + var licType = params.asc_getLicenseType(); + if (licType !== undefined && (this.appOptions.canEdit || this.appOptions.isRestrictedEdit) && this.editorConfig.mode !== 'view' && + (licType===Asc.c_oLicenseResult.Connections || licType===Asc.c_oLicenseResult.UsersCount || licType===Asc.c_oLicenseResult.ConnectionsOS || licType===Asc.c_oLicenseResult.UsersCountOS + || licType===Asc.c_oLicenseResult.SuccessLimit && (this.appOptions.trialMode & Asc.c_oLicenseMode.Limited) !== 0)) + this._state.licenseType = licType; + + if (licType !== undefined && this.appOptions.canLiveView && (licType===Asc.c_oLicenseResult.ConnectionsLive || licType===Asc.c_oLicenseResult.ConnectionsLiveOS|| + licType===Asc.c_oLicenseResult.UsersViewCount || licType===Asc.c_oLicenseResult.UsersViewCountOS)) + this._state.licenseType = licType; + + if (this._isDocReady) + this.applyLicense(); + }, + + applyLicense: function() { + if (this.editorConfig.mode === 'view') { + if (this.appOptions.canLiveView && (this._state.licenseType===Asc.c_oLicenseResult.ConnectionsLive || this._state.licenseType===Asc.c_oLicenseResult.ConnectionsLiveOS || + this._state.licenseType===Asc.c_oLicenseResult.UsersViewCount || this._state.licenseType===Asc.c_oLicenseResult.UsersViewCountOS || + !this.appOptions.isAnonymousSupport && !!this.appOptions.user.anonymous)) { + // show warning or write to log if Common.Utils.InternalSettings.get("de-settings-coauthmode") was true ??? + this.disableLiveViewing(true); + } + } else if (!this.appOptions.isAnonymousSupport && !!this.appOptions.user.anonymous) { + this.disableEditing(true); + this.api.asc_coAuthoringDisconnect(); + Common.NotificationCenter.trigger('api:disconnect'); + Common.UI.warning({ + title: this.notcriticalErrorTitle, + msg : this.warnLicenseAnonymous, + buttons: ['ok'] + }); + } else if (this._state.licenseType) { + var license = this._state.licenseType, + buttons = ['ok'], + primary = 'ok'; + if ((this.appOptions.trialMode & Asc.c_oLicenseMode.Limited) !== 0 && + (license===Asc.c_oLicenseResult.SuccessLimit || this.appOptions.permissionsLicense===Asc.c_oLicenseResult.SuccessLimit)) { + license = this.warnLicenseLimitedRenewed; + } else if (license===Asc.c_oLicenseResult.Connections || license===Asc.c_oLicenseResult.UsersCount) { + license = (license===Asc.c_oLicenseResult.Connections) ? this.warnLicenseExceeded : this.warnLicenseUsersExceeded; + } else { + license = (license===Asc.c_oLicenseResult.ConnectionsOS) ? this.warnNoLicense : this.warnNoLicenseUsers; + buttons = [{value: 'buynow', caption: this.textBuyNow}, {value: 'contact', caption: this.textContactUs}]; + primary = 'buynow'; + } + + if (this._state.licenseType!==Asc.c_oLicenseResult.SuccessLimit && (this.appOptions.isEdit || this.appOptions.isRestrictedEdit)) { + this.disableEditing(true); + this.api.asc_coAuthoringDisconnect(); + Common.NotificationCenter.trigger('api:disconnect'); + } + + var value = Common.localStorage.getItem("ve-license-warning"); + value = (value!==null) ? parseInt(value) : 0; + var now = (new Date).getTime(); + if (now - value > 86400000) { + Common.UI.info({ + maxwidth: 500, + title: this.textNoLicenseTitle, + msg : license, + buttons: buttons, + primary: primary, + callback: function(btn) { + Common.localStorage.setItem("ve-license-warning", now); + if (btn == 'buynow') + window.open('{{PUBLISHER_URL}}', "_blank"); + else if (btn == 'contact') + window.open('mailto:{{SALES_EMAIL}}', "_blank"); + } + }); + } + } else if (!this.appOptions.isDesktopApp && !this.appOptions.canBrandingExt && + this.editorConfig && this.editorConfig.customization && (this.editorConfig.customization.loaderName || this.editorConfig.customization.loaderLogo || + this.editorConfig.customization.font && (this.editorConfig.customization.font.size || this.editorConfig.customization.font.name))) { + Common.UI.warning({ + title: this.textPaidFeature, + msg : this.textCustomLoader, + buttons: [{value: 'contact', caption: this.textContactUs}, {value: 'close', caption: this.textClose}], + primary: 'contact', + callback: function(btn) { + if (btn == 'contact') + window.open('mailto:{{SALES_EMAIL}}', "_blank"); + } + }); + } + }, + + onOpenDocument: function(progress) { + var elem = document.getElementById('loadmask-text'); + var proc = (progress.asc_getCurrentFont() + progress.asc_getCurrentImage())/(progress.asc_getFontsCount() + progress.asc_getImagesCount()); + proc = this.textLoadingDocument + ': ' + Common.Utils.String.fixedDigits(Math.min(Math.round(proc*100), 100), 3, " ") + "%"; + elem ? elem.innerHTML = proc : this.loadMask && this.loadMask.setTitle(proc); + }, + + onEditorPermissions: function(params) { + var licType = params.asc_getLicenseType(); + if (Asc.c_oLicenseResult.Expired === licType || Asc.c_oLicenseResult.Error === licType || Asc.c_oLicenseResult.ExpiredTrial === licType || + Asc.c_oLicenseResult.NotBefore === licType || Asc.c_oLicenseResult.ExpiredLimited === licType) { + Common.UI.warning({ + title: Asc.c_oLicenseResult.NotBefore === licType ? this.titleLicenseNotActive : this.titleLicenseExp, + msg: Asc.c_oLicenseResult.NotBefore === licType ? this.warnLicenseBefore : this.warnLicenseExp, + buttons: [], + closable: false + }); + return; + } + + if ( this.onServerVersion(params.asc_getBuildVersion()) || !this.onLanguageLoaded()) return; + + if (params.asc_getRights() !== Asc.c_oRights.Edit) + this.permissions.edit = this.permissions.review = false; + + this.appOptions.permissionsLicense = licType; + this.appOptions.isOffline = this.api.asc_isOffline(); + this.appOptions.isCrypted = this.api.asc_isCrypto(); + this.appOptions.canLicense = (licType === Asc.c_oLicenseResult.Success || licType === Asc.c_oLicenseResult.SuccessLimit); + this.appOptions.isLightVersion = params.asc_getIsLight(); + /** coauthoring begin **/ + this.appOptions.canCoAuthoring = !this.appOptions.isLightVersion; + /** coauthoring end **/ + this.appOptions.canRequestEditRights = this.editorConfig.canRequestEditRights; + this.appOptions.canEdit = false;//this.permissions.edit !== false && // can edit + // (this.editorConfig.canRequestEditRights || this.editorConfig.mode !== 'view'); // if mode=="view" -> canRequestEditRights must be defined + this.appOptions.isEdit = this.appOptions.canLicense && this.appOptions.canEdit && this.editorConfig.mode !== 'view'; + this.appOptions.canDownload = this.permissions.download !== false; + this.appOptions.canAnalytics = params.asc_getIsAnalyticsEnable(); + this.appOptions.canComments = false;//this.appOptions.canLicense && (this.permissions.comment===undefined ? this.appOptions.isEdit : this.permissions.comment) && (this.editorConfig.mode !== 'view'); + this.appOptions.canComments = false;//this.appOptions.canComments && !((typeof (this.editorConfig.customization) == 'object') && this.editorConfig.customization.comments===false); + this.appOptions.canViewComments = this.appOptions.canComments || !((typeof (this.editorConfig.customization) == 'object') && this.editorConfig.customization.comments===false); + this.appOptions.canChat = this.appOptions.canLicense && !this.appOptions.isOffline && !(this.permissions.chat===false || (this.permissions.chat===undefined) && + (typeof (this.editorConfig.customization) == 'object') && this.editorConfig.customization.chat===false); + if ((typeof (this.editorConfig.customization) == 'object') && this.editorConfig.customization.chat!==undefined) { + console.log("Obsolete: The 'chat' parameter of the 'customization' section is deprecated. Please use 'chat' parameter in the permissions instead."); + } + this.appOptions.canPrint = (this.permissions.print !== false); + this.appOptions.canPreviewPrint = false; + this.appOptions.canQuickPrint = this.appOptions.canPrint && !Common.Utils.isMac && this.appOptions.isDesktopApp; + this.appOptions.canRename = this.editorConfig.canRename; + this.appOptions.canForcesave = this.appOptions.isEdit && !this.appOptions.isOffline && (typeof (this.editorConfig.customization) == 'object' && !!this.editorConfig.customization.forcesave); + this.appOptions.forcesave = this.appOptions.canForcesave; + this.appOptions.canEditComments= this.appOptions.isOffline || !this.permissions.editCommentAuthorOnly; + this.appOptions.canDeleteComments= this.appOptions.isOffline || !this.permissions.deleteCommentAuthorOnly; + if ((typeof (this.editorConfig.customization) == 'object') && this.editorConfig.customization.commentAuthorOnly===true) { + console.log("Obsolete: The 'commentAuthorOnly' parameter of the 'customization' section is deprecated. Please use 'editCommentAuthorOnly' and 'deleteCommentAuthorOnly' parameters in the permissions instead."); + if (this.permissions.editCommentAuthorOnly===undefined && this.permissions.deleteCommentAuthorOnly===undefined) + this.appOptions.canEditComments = this.appOptions.canDeleteComments = this.appOptions.isOffline; + } + this.appOptions.buildVersion = params.asc_getBuildVersion(); + this.appOptions.trialMode = params.asc_getLicenseMode(); + this.appOptions.isBeta = params.asc_getIsBeta(); + this.appOptions.isSignatureSupport= this.appOptions.isEdit && this.appOptions.isDesktopApp && this.appOptions.isOffline && this.api.asc_isSignaturesSupport() && (this.permissions.protect!==false); + this.appOptions.isPasswordSupport = this.appOptions.isEdit && this.api.asc_isProtectionSupport() && (this.permissions.protect!==false); + this.appOptions.canProtect = (this.permissions.protect!==false); + this.appOptions.canHelp = !((typeof (this.editorConfig.customization) == 'object') && this.editorConfig.customization.help===false); + this.appOptions.isRestrictedEdit = !this.appOptions.isEdit && this.appOptions.canComments; + this.appOptions.canSaveToFile = this.appOptions.isEdit || this.appOptions.isRestrictedEdit; + this.appOptions.showSaveButton = this.appOptions.isEdit; + + this.appOptions.compactHeader = this.appOptions.customization && (typeof (this.appOptions.customization) == 'object') && !!this.appOptions.customization.compactHeader; + this.appOptions.twoLevelHeader = this.appOptions.isEdit; // when compactHeader=true some buttons move to toolbar + + this.appOptions.canUseHistory = false;//this.appOptions.canLicense && this.editorConfig.canUseHistory && this.appOptions.canCoAuthoring && !this.appOptions.isOffline; + this.appOptions.canHistoryClose = this.editorConfig.canHistoryClose; + this.appOptions.canHistoryRestore= this.editorConfig.canHistoryRestore; + + if ( this.appOptions.isLightVersion ) { + this.appOptions.canUseHistory = false; + } + + this.appOptions.canBrandingExt = params.asc_getCanBranding() && (typeof this.editorConfig.customization == 'object' || this.editorConfig.plugins); + Common.UI.LayoutManager.init(this.editorConfig.customization ? this.editorConfig.customization.layout : null, this.appOptions.canBrandingExt, this.api); + this.editorConfig.customization && Common.UI.FeaturesManager.init(this.editorConfig.customization.features, this.appOptions.canBrandingExt); + Common.UI.TabStyler.init(this.editorConfig.customization); // call after Common.UI.FeaturesManager.init() !!! + + this.appOptions.canBranding = params.asc_getCustomization(); + if (this.appOptions.canBranding) + appHeader.setBranding(this.editorConfig.customization, this.appOptions); + + this.appOptions.canFavorite = this.document.info && (this.document.info.favorite!==undefined && this.document.info.favorite!==null) && !this.appOptions.isOffline; + this.appOptions.canFavorite && appHeader.setFavorite(this.document.info.favorite); + + this.appOptions.canUseCommentPermissions = this.appOptions.canLicense && !!this.permissions.commentGroups; + this.appOptions.canUseUserInfoPermissions = this.appOptions.canLicense && !!this.permissions.userInfoGroups; + AscCommon.UserInfoParser.setParser(true); + AscCommon.UserInfoParser.setCurrentName(this.appOptions.user.fullname); + this.appOptions.canUseCommentPermissions && AscCommon.UserInfoParser.setCommentPermissions(this.permissions.commentGroups); + this.appOptions.canUseUserInfoPermissions && AscCommon.UserInfoParser.setUserInfoPermissions(this.permissions.userInfoGroups); + appHeader.setUserName(AscCommon.UserInfoParser.getParsedName(AscCommon.UserInfoParser.getCurrentName())); + appHeader.setUserId(this.appOptions.user.id); + appHeader.setUserAvatar(this.appOptions.user.image); + + this.appOptions.canRename && appHeader.setCanRename(true); + this.getApplication().getController('Common.Controllers.Plugins').setMode(this.appOptions); + Common.UI.ExternalUsers.init(this.appOptions.canRequestUsers, this.api); + this.appOptions.user.image ? Common.UI.ExternalUsers.setImage(this.appOptions.user.id, this.appOptions.user.image) : Common.UI.ExternalUsers.get('info', this.appOptions.user.id); + + // change = true by default in editor + this.appOptions.canLiveView = !!params.asc_getLiveViewerSupport() && (this.editorConfig.mode === 'view'); // viewer: change=false when no flag canLiveViewer (i.g. old license), change=true by default when canLiveViewer==true + this.appOptions.canChangeCoAuthoring = this.appOptions.isEdit && this.appOptions.canCoAuthoring && !(this.editorConfig.coEditing && typeof this.editorConfig.coEditing == 'object' && this.editorConfig.coEditing.change===false) || + this.appOptions.canLiveView && !(this.editorConfig.coEditing && typeof this.editorConfig.coEditing == 'object' && this.editorConfig.coEditing.change===false); + this.appOptions.isAnonymousSupport = !!this.api.asc_isAnonymousSupport(); + + this.loadCoAuthSettings(); + this.applyModeCommonElements(); + this.applyModeEditorElements(); + + if ( !this.appOptions.isEdit ) { + Common.NotificationCenter.trigger('app:face', this.appOptions); + + this.hidePreloader(); + this.onLongActionBegin(Asc.c_oAscAsyncActionType['BlockInteraction'], LoadingDocument); + } + + this.api.asc_setViewMode(!this.appOptions.isEdit && !this.appOptions.isRestrictedEdit); + this.api.asc_setCanSendChanges(this.appOptions.canSaveToFile); + (this.appOptions.isRestrictedEdit && this.appOptions.canComments) && this.api.asc_setRestriction(Asc.c_oAscRestrictionType.OnlyComments); + this.api.asc_LoadDocument(); + }, + + loadCoAuthSettings: function() { + Common.Utils.InternalSettings.set("ve-settings-coauthmode", false); + Common.Utils.InternalSettings.set("ve-settings-autosave", 0); + }, + + loadDefaultMetricSettings: function() { + var region = ''; + if (this.appOptions.location) { + console.log("Obsolete: The 'location' parameter of the 'editorConfig' section is deprecated. Please use 'region' parameter in the 'editorConfig' section instead."); + region = this.appOptions.location; + } else if (this.appOptions.region) { + var val = this.appOptions.region; + val = Common.util.LanguageInfo.getLanguages().hasOwnProperty(val) ? Common.util.LanguageInfo.getLocalLanguageName(val)[0] : val; + if (val && typeof val === 'string') { + var arr = val.split(/[\-_]/); + (arr.length>1) && (region = arr[arr.length-1]); + } + } else { + var arr = (this.appOptions.lang || 'en').split(/[\-_]/); + (arr.length>1) && (region = arr[arr.length-1]); + if (!region) { + arr = (navigator.language || '').split(/[\-_]/); + (arr.length>1) && (region = arr[arr.length-1]); + } + } + + if (/^(ca|us)$/i.test(region)) + Common.Utils.Metric.setDefaultMetric(Common.Utils.Metric.c_MetricUnits.inch); + Common.Utils.InternalSettings.set("ve-config-region", region); + }, + + onCoAuthApply: function() { + if (!this.api) return; + + this._state.fastCoauth = Common.Utils.InternalSettings.get("ve-settings-coauthmode"); + this.api.asc_SetFastCollaborative(this._state.fastCoauth); + this.api.asc_setAutoSaveGap(Common.Utils.InternalSettings.get("ve-settings-autosave")); + + this.getApplication().getController('LeftMenu').leftMenu.getMenu('file').applyMode(); + }, + + applyModeCommonElements: function() { + window.editor_elements_prepared = true; + + var app = this.getApplication(), + viewport = app.getController('Viewport'), + statusbarView = app.getController('Statusbar').getView('Statusbar'), + documentHolder = app.getController('DocumentHolder'), + toolbarController = app.getController('Toolbar'), + leftMenu = app.getController('LeftMenu'); + + viewport && viewport.setMode(this.appOptions); + statusbarView && statusbarView.setMode(this.appOptions); + toolbarController.setMode(this.appOptions); + documentHolder.setMode(this.appOptions); + leftMenu.setMode(this.appOptions); + + viewport.applyCommonMode(); + + this.api.asc_registerCallback('asc_onDownloadUrl', _.bind(this.onDownloadUrl, this)); + this.api.asc_registerCallback('asc_onAuthParticipantsChanged', _.bind(this.onAuthParticipantsChanged, this)); + this.api.asc_registerCallback('asc_onParticipantsChanged', _.bind(this.onAuthParticipantsChanged, this)); + this.api.asc_registerCallback('asc_onConnectionStateChanged', _.bind(this.onUserConnection, this)); + // this.api.asc_registerCallback('asc_onDocumentModifiedChanged', _.bind(this.onDocumentModifiedChanged, this)); + + var value = Common.localStorage.getItem('ve-settings-unit'); + value = (value!==null) ? parseInt(value) : (this.appOptions.customization && this.appOptions.customization.unit ? Common.Utils.Metric.c_MetricUnits[this.appOptions.customization.unit.toLocaleLowerCase()] : Common.Utils.Metric.getDefaultMetric()); + (value===undefined) && (value = Common.Utils.Metric.getDefaultMetric()); + Common.Utils.Metric.setCurrentMetric(value); + Common.Utils.InternalSettings.set("ve-settings-unit", value); + + // this.contComments.setMode(this.appOptions); + // this.contComments.setConfig({config: this.editorConfig}, this.api); + + toolbarController.setApi(this.api); + }, + + applyModeEditorElements: function() { + var me = this, + application = this.getApplication(); + + if (this.appOptions.isEdit) { + + } else + window.onbeforeunload = _.bind(me.onBeforeUnloadView, me); + }, + + onExternalMessage: function(msg, options) { + if (msg && msg.msg) { + msg.msg = (msg.msg).toString(); + this.showTips([msg.msg.charAt(0).toUpperCase() + msg.msg.substring(1)], options); + + Common.component.Analytics.trackEvent('External Error'); + } + }, + + onError: function(id, level, errData) { + if (id == Asc.c_oAscError.ID.LoadingScriptError) { + this.showTips([this.scriptLoadError]); + this.tooltip && this.tooltip.getBSTip().$tip.css('z-index', 10000); + return; + } else if (id == Asc.c_oAscError.ID.CanNotPasteImage) { + this.showTips([this.errorCannotPasteImg], {timeout: 7000, hideCloseTip: true}); + return; + } + + this.hidePreloader(); + this.onLongActionEnd(Asc.c_oAscAsyncActionType['BlockInteraction'], LoadingDocument); + + var config = { + closable: true + }; + + switch (id) + { + case Asc.c_oAscError.ID.Unknown: + config.msg = this.unknownErrorText; + break; + + case Asc.c_oAscError.ID.ConvertationTimeout: + config.msg = this.convertationTimeoutText; + break; + + case Asc.c_oAscError.ID.ConvertationOpenError: + config.msg = this.openErrorText; + break; + + case Asc.c_oAscError.ID.ConvertationSaveError: + config.msg = (this.appOptions.isDesktopApp && this.appOptions.isOffline) ? this.saveErrorTextDesktop : this.saveErrorText; + break; + + case Asc.c_oAscError.ID.DownloadError: + config.msg = this.downloadErrorText; + break; + + case Asc.c_oAscError.ID.UplImageSize: + config.msg = this.uploadImageSizeMessage; + break; + + case Asc.c_oAscError.ID.UplImageExt: + config.msg = this.uploadImageExtMessage; + break; + + case Asc.c_oAscError.ID.UplImageFileCount: + config.msg = this.uploadImageFileCountMessage; + break; + + case Asc.c_oAscError.ID.UplDocumentSize: + config.msg = this.uploadDocSizeMessage; + break; + + case Asc.c_oAscError.ID.UplDocumentExt: + config.msg = this.uploadDocExtMessage; + break; + + case Asc.c_oAscError.ID.UplDocumentFileCount: + config.msg = this.uploadDocFileCountMessage; + break; + + case Asc.c_oAscError.ID.VKeyEncrypt: + config.msg = this.errorToken; + break; + + case Asc.c_oAscError.ID.KeyExpire: + config.msg = this.errorTokenExpire; + break; + + case Asc.c_oAscError.ID.UserCountExceed: + config.msg = this.errorUsersExceed; + break; + + case Asc.c_oAscError.ID.CoAuthoringDisconnect: + config.msg = this.errorViewerDisconnect; + break; + + case Asc.c_oAscError.ID.ConvertationPassword: + config.msg = this.errorFilePassProtect; + break; + + case Asc.c_oAscError.ID.Database: + config.msg = this.errorDatabaseConnection; + break; + + case Asc.c_oAscError.ID.UserDrop: + if (this._state.lostEditingRights) { + this._state.lostEditingRights = false; + return; + } + this._state.lostEditingRights = true; + config.msg = this.errorUserDrop; + Common.NotificationCenter.trigger('collaboration:sharingdeny'); + break; + + case Asc.c_oAscError.ID.Warning: + config.msg = this.errorConnectToServer; + config.closable = false; + break; + + case Asc.c_oAscError.ID.SessionAbsolute: + config.msg = this.errorSessionAbsolute; + break; + + case Asc.c_oAscError.ID.SessionIdle: + config.msg = this.errorSessionIdle; + break; + + case Asc.c_oAscError.ID.SessionToken: + config.msg = this.errorSessionToken; + break; + + case Asc.c_oAscError.ID.AccessDeny: + config.msg = this.errorAccessDeny; + break; + + case Asc.c_oAscError.ID.UplImageUrl: + config.msg = this.errorBadImageUrl; + break; + + case Asc.c_oAscError.ID.ForceSaveButton: + case Asc.c_oAscError.ID.ForceSaveTimeout: + config.msg = this.errorForceSave; + config.maxwidth = 600; + break; + + case Asc.c_oAscError.ID.DataEncrypted: + config.msg = this.errorDataEncrypted; + break; + + case Asc.c_oAscError.ID.EditingError: + config.msg = (this.appOptions.isDesktopApp && this.appOptions.isOffline) ? this.errorEditingSaveas : this.errorEditingDownloadas; + break; + + case Asc.c_oAscError.ID.ConvertationOpenLimitError: + config.msg = this.errorFileSizeExceed; + break; + + case Asc.c_oAscError.ID.UpdateVersion: + config.msg = this.errorUpdateVersionOnDisconnect; + config.maxwidth = 600; + break; + + case Asc.c_oAscError.ID.DirectUrl: + config.msg = this.errorDirectUrl; + break; + + case Asc.c_oAscError.ID.Password: + config.msg = this.errorSetPassword; + break; + + case Asc.c_oAscError.ID.LoadingFontError: + config.msg = this.errorLoadingFont; + break; + + case Asc.c_oAscError.ID.PasswordIsNotCorrect: + config.msg = this.errorPasswordIsNotCorrect; + break; + + case Asc.c_oAscError.ID.ConvertationOpenFormat: + config.maxwidth = 600; + if (errData === 'pdf') + config.msg = this.errorInconsistentExtPdf.replace('%1', this.document.fileType || ''); + else if (errData === 'docx') + config.msg = this.errorInconsistentExtDocx.replace('%1', this.document.fileType || ''); + else if (errData === 'xlsx') + config.msg = this.errorInconsistentExtXlsx.replace('%1', this.document.fileType || ''); + else if (errData === 'pptx') + config.msg = this.errorInconsistentExtPptx.replace('%1', this.document.fileType || ''); + else + config.msg = this.errorInconsistentExt; + break; + + default: + config.msg = (typeof id == 'string') ? id : this.errorDefaultMessage.replace('%1', id); + break; + } + + if (level == Asc.c_oAscError.Level.Critical) { + + // report only critical errors + Common.Gateway.reportError(id, config.msg); + + config.title = this.criticalErrorTitle; + config.iconCls = 'error'; + config.closable = false; + + if (this.appOptions.canBackToFolder && !this.appOptions.isDesktopApp && typeof id !== 'string') { + config.msg += '

' + this.criticalErrorExtText; + config.callback = function(btn) { + if (btn == 'ok') + Common.NotificationCenter.trigger('goback', true); + } + } + if (id == Asc.c_oAscError.ID.DataEncrypted || id == Asc.c_oAscError.ID.ConvertationOpenLimitError) { + this.api.asc_coAuthoringDisconnect(); + Common.NotificationCenter.trigger('api:disconnect'); + } + } + else { + Common.Gateway.reportWarning(id, config.msg); + + config.title = this.notcriticalErrorTitle; + config.iconCls = 'warn'; + config.buttons = ['ok']; + config.callback = _.bind(function(btn){ + if (id == Asc.c_oAscError.ID.Warning && btn == 'ok' && (this.appOptions.canDownload || this.appOptions.canDownloadOrigin)) { + Common.UI.Menu.Manager.hideAll(); + if (this.appOptions.isDesktopApp && this.appOptions.isOffline) + this.api.asc_DownloadAs(); + else { + if (this.appOptions.canDownload) { + this._isDocReady ? this.getApplication().getController('LeftMenu').leftMenu.showMenu('file:saveas') : (this._needToSaveAsFile = true); + } else + this.api.asc_DownloadOrigin(); + } + } else if (id == Asc.c_oAscError.ID.EditingError) { + this.disableEditing(true); + Common.NotificationCenter.trigger('api:disconnect', true); // enable download and print + } + this._state.lostEditingRights = false; + this.onEditComplete(); + }, this); + } + + if (!Common.Utils.ModalWindow.isVisible() || $('.asc-window.modal.alert[data-value=' + id + ']').length<1) + Common.UI.alert(config).$window.attr('data-value', id); + + (id!==undefined) && Common.component.Analytics.trackEvent('Internal Error', id.toString()); + }, + + onCoAuthoringDisconnect: function() { + this.getApplication().getController('Viewport').getView('Viewport').setMode({isDisconnected:true}); + appHeader.setCanRename(false); + this.appOptions.canRename = false; + this._state.isDisconnected = true; + }, + + showTips: function(strings, options) { + var me = this; + if (!strings.length) return; + if (typeof(strings)!='object') strings = [strings]; + + function closeTip(cmp){ + me.tipTimeout && clearTimeout(me.tipTimeout); + setTimeout(showNextTip, 300); + } + + function showNextTip() { + var str_tip = strings.shift(); + if (str_tip) { + if (!(options && options.hideCloseTip)) + str_tip += '\n' + me.textCloseTip; + me.tooltip.setTitle(str_tip); + me.tooltip.show(); + me.tipTimeout && clearTimeout(me.tipTimeout); + if (options && options.timeout) { + me.tipTimeout = setTimeout(function () { + me.tooltip.hide(); + closeTip(); + }, options.timeout); + } + } + } + + if (!this.tooltip) { + this.tooltip = new Common.UI.Tooltip({ + owner: this.getApplication().getController('Toolbar').getView(), + hideonclick: true, + placement: 'bottom', + cls: 'main-info', + offset: 30 + }); + this.tooltip.on('tooltip:hideonclick',closeTip); + } + + showNextTip(); + }, + + updateWindowTitle: function(force) { + var isModified = this.api.isDocumentModified(); + if (this._state.isDocModified !== isModified || force) { + var title = this.defaultTitleText; + + if (appHeader && !_.isEmpty(appHeader.getDocumentCaption())) + title = appHeader.getDocumentCaption() + ' - ' + title; + + if (isModified) { + clearTimeout(this._state.timerCaption); + if (!_.isUndefined(title)) { + title = '* ' + title; + } + } + + if (window.document.title != title) + window.document.title = title; + + this._isDocReady && (this._state.isDocModified !== isModified) && Common.Gateway.setDocumentModified(isModified); + if (isModified && (!this._state.fastCoauth || this._state.usersCount<2)) + this.getApplication().getController('Statusbar').setStatusCaption('', true); + + this._state.isDocModified = isModified; + } + }, + + onDocumentModifiedChanged: function() { + var isModified = this.api.asc_isDocumentCanSave(); + if (this._state.isDocModified !== isModified) { + this._isDocReady && Common.Gateway.setDocumentModified(this.api.isDocumentModified()); + } + + this.updateWindowTitle(); + + var toolbarView = this.getApplication().getController('Toolbar').getView('Toolbar'); + if (toolbarView && toolbarView.btnCollabChanges) { + var isSyncButton = toolbarView.btnCollabChanges.cmpEl.hasClass('notify'), + forcesave = this.appOptions.forcesave || this.appOptions.canSaveDocumentToBinary, + isDisabled = !isModified && !isSyncButton && !forcesave || this._state.isDisconnected || this._state.fastCoauth && this._state.usersCount>1 && !forcesave; + toolbarView.btnSave.setDisabled(isDisabled); + } + }, + + onDocumentCanSaveChanged: function (isCanSave) { + var toolbarView = this.getApplication().getController('Toolbar').getView('Toolbar'); + if ( toolbarView ) { + var isSyncButton = toolbarView.btnCollabChanges.cmpEl.hasClass('notify'), + forcesave = this.appOptions.forcesave || this.appOptions.canSaveDocumentToBinary, + isDisabled = !isCanSave && !isSyncButton && !forcesave || this._state.isDisconnected || this._state.fastCoauth && this._state.usersCount>1 && !forcesave; + toolbarView.btnSave.setDisabled(isDisabled); + } + }, + + onContextMenu: function(event){ + var canCopyAttr = event.target.getAttribute('data-can-copy'), + isInputEl = (event.target instanceof HTMLInputElement) || (event.target instanceof HTMLTextAreaElement); + + if ((isInputEl && canCopyAttr === 'false') || + (!isInputEl && canCopyAttr !== 'true')) { + event.stopPropagation(); + event.preventDefault(); + return false; + } + }, + + onBeforeUnload: function() { + Common.localStorage.save(); + + if (this.api.isDocumentModified()) { + var me = this; + this.api.asc_stopSaving(); + this._state.unloadTimer = 1000; + this.continueSavingTimer = window.setTimeout(function() { + me.api.asc_continueSaving(); + me._state.unloadTimer = 0; + }, 500); + + return this.leavePageText; + } else + this._state.unloadTimer = 10000; + }, + + onUnload: function() { + if (this.continueSavingTimer) clearTimeout(this.continueSavingTimer); + }, + + onBeforeUnloadView: function() { + Common.localStorage.save(); + this._state.unloadTimer = 10000; + }, + + hidePreloader: function() { + var promise; + if (!this._state.customizationDone) { + this._state.customizationDone = true; + if (this.appOptions.customization) { + if (this.appOptions.isDesktopApp) + this.appOptions.customization.about = false; + else if (!this.appOptions.canBrandingExt) + this.appOptions.customization.about = true; + } + Common.Utils.applyCustomization(this.appOptions.customization, mapCustomizationElements); + if (this.appOptions.canBrandingExt) { + Common.Utils.applyCustomization(this.appOptions.customization, mapCustomizationExtElements); + Common.UI.LayoutManager.applyCustomization(); + if (this.appOptions.customization && (typeof (this.appOptions.customization) == 'object')) { + if (this.appOptions.customization.leftMenu!==undefined) + console.log("Obsolete: The 'leftMenu' parameter of the 'customization' section is deprecated. Please use 'leftMenu' parameter in the 'customization.layout' section instead."); + if (this.appOptions.customization.statusBar!==undefined) + console.log("Obsolete: The 'statusBar' parameter of the 'customization' section is deprecated. Please use 'statusBar' parameter in the 'customization.layout' section instead."); + if (this.appOptions.customization.toolbar!==undefined) + console.log("Obsolete: The 'toolbar' parameter of the 'customization' section is deprecated. Please use 'toolbar' parameter in the 'customization.layout' section instead."); + } + promise = this.getApplication().getController('Common.Controllers.Plugins').applyUICustomization(); + } + } + Common.NotificationCenter.trigger('layout:changed', 'main'); + + (promise || (new Promise(function(resolve, reject) { + resolve(); + }))).then(function() { + $('#loading-mask').hide().remove(); + Common.Controllers.Desktop.process('preloader:hide'); + }); + }, + + onDownloadUrl: function(url, fileType) { + if (this._state.isFromGatewayDownloadAs) { + Common.Gateway.downloadAs(url, fileType); + } + this._state.isFromGatewayDownloadAs = false; + }, + + onUpdateVersion: function(callback) { + var me = this; + me.needToUpdateVersion = true; + me.onLongActionEnd(Asc.c_oAscAsyncActionType['BlockInteraction'], LoadingDocument); + Common.UI.warning({ + title: me.titleUpdateVersion, + msg: this.errorUpdateVersion, + callback: function() { + _.defer(function() { + Common.Gateway.updateVersion(); + if (callback) callback.call(me); + me.onLongActionBegin(Asc.c_oAscAsyncActionType['BlockInteraction'], LoadingDocument); + }) + } + }); + this.disableEditing(true, 'not-loaded'); + Common.NotificationCenter.trigger('api:disconnect'); + }, + + onServerVersion: function(buildVersion) { + if (this.changeServerVersion) return true; + + const cur_version = this.getApplication().getController('LeftMenu').leftMenu.getMenu('about').txtVersionNum; + const cropped_version = cur_version.match(/^(\d+.\d+.\d+)/); + if (!window.compareVersions && (!cropped_version || cropped_version[1] !== buildVersion)) { + this.changeServerVersion = true; + Common.UI.warning({ + title: this.titleServerVersion, + msg: this.errorServerVersion, + callback: function() { + _.defer(function() { + Common.Gateway.updateVersion(); + }) + } + }); + return true; + } + return false; + }, + + /** coauthoring begin **/ +// fillUserStore: function(users){ +// if (!_.isEmpty(users)){ +// var userStore = this.getCommonStoreUsersStore(); +// +// if (userStore) +// userStore.add(users); +// } +// }, + + unitsChanged: function(m) { + var value = Common.localStorage.getItem("ve-settings-unit"); + value = (value!==null) ? parseInt(value) : Common.Utils.Metric.getDefaultMetric(); + Common.Utils.Metric.setCurrentMetric(value); + Common.Utils.InternalSettings.set("ve-settings-unit", value); + this.api.asc_SetDocumentUnits((value==Common.Utils.Metric.c_MetricUnits.inch) ? Asc.c_oAscDocumentUnits.Inch : ((value==Common.Utils.Metric.c_MetricUnits.pt) ? Asc.c_oAscDocumentUnits.Point : Asc.c_oAscDocumentUnits.Millimeter)); + this.getApplication().getController('Toolbar').getView().updateMetricUnit(); + }, + + onAdvancedOptions: function(type, advOptions, mode, formatOptions) { + if (this._state.openDlg) return; + + var me = this; + if (type == Asc.c_oAscAdvancedOptionsID.DRM) { + me._state.openDlg = new Common.Views.OpenDialog({ + title: Common.Views.OpenDialog.prototype.txtTitleProtected, + closeFile: me.appOptions.canRequestClose, + type: Common.Utils.importTextType.DRM, + warning: !(me.appOptions.isDesktopApp && me.appOptions.isOffline) && (typeof advOptions == 'string'), + warningMsg: advOptions, + validatePwd: !!me._state.isDRM, + handler: function (result, value) { + me.isShowOpenDialog = false; + if (result == 'ok') { + if (me.api) { + me.api.asc_setAdvancedOptions(type, value.drmOptions); + me.loadMask && me.loadMask.show(); + } + } else { + Common.Gateway.requestClose(); + Common.Controllers.Desktop.requestClose(); + } + me._state.openDlg = null; + } + }); + me._state.isDRM = true; + } + if (me._state.openDlg) { + this.isShowOpenDialog = true; + this.loadMask && this.loadMask.hide(); + this.onLongActionEnd(Asc.c_oAscAsyncActionType.BlockInteraction, LoadingDocument); + me._state.openDlg.show(); + } + }, + + onTryUndoInFastCollaborative: function() { + if (!Common.localStorage.getBool("ve-hide-try-undoredo")) + Common.UI.info({ + width: 500, + msg: this.appOptions.canChangeCoAuthoring ? this.textTryUndoRedo : this.textTryUndoRedoWarn, + iconCls: 'info', + buttons: this.appOptions.canChangeCoAuthoring ? [{value: 'custom', caption: this.textStrict}, 'cancel'] : ['ok'], + primary: this.appOptions.canChangeCoAuthoring ? 'custom' : 'ok', + dontshow: true, + callback: _.bind(function(btn, dontshow){ + if (dontshow) Common.localStorage.setItem("ve-hide-try-undoredo", 1); + if (btn == 'custom') { + Common.localStorage.setItem("ve-settings-coauthmode", 0); + this.api.asc_SetFastCollaborative(false); + Common.Utils.InternalSettings.set("ve-settings-coauthmode", false); + this.getApplication().getController('Common.Controllers.ReviewChanges').applySettings(); + this._state.fastCoauth = false; + } + this.onEditComplete(); + }, this) + }); + }, + + onAuthParticipantsChanged: function(users) { + var length = 0; + _.each(users, function(item){ + if (!item.asc_getView()) + length++; + }); + this._state.usersCount = length; + }, + + onUserConnection: function(change){ + if (change && this.appOptions.user.guest && this.appOptions.canRenameAnonymous && (change.asc_getIdOriginal() == this.appOptions.user.id)) { // change name of the current user + var name = change.asc_getUserName(); + if (name && name !== AscCommon.UserInfoParser.getCurrentName() ) { + this._renameDialog && this._renameDialog.close(); + AscCommon.UserInfoParser.setCurrentName(name); + appHeader.setUserName(AscCommon.UserInfoParser.getParsedName(name)); + + var idx1 = name.lastIndexOf('('), + idx2 = name.lastIndexOf(')'), + str = (idx1>0) && (idx10 ? meta.title.substring(0, idx) : meta.title); + } + }, + + onPrint: function() { + if (!this.appOptions.canPrint || Common.Utils.ModalWindow.isVisible()) return; + Common.NotificationCenter.trigger('file:print'); + Common.component.Analytics.trackEvent('Print'); + }, + + onPrintUrl: function(url) { + if (this.iframePrint) { + this.iframePrint.parentNode.removeChild(this.iframePrint); + this.iframePrint = null; + } + if (!this.iframePrint) { + var me = this; + this.iframePrint = document.createElement("iframe"); + this.iframePrint.id = "id-print-frame"; + this.iframePrint.style.display = 'none'; + this.iframePrint.style.visibility = "hidden"; + this.iframePrint.style.position = "fixed"; + this.iframePrint.style.right = "0"; + this.iframePrint.style.bottom = "0"; + document.body.appendChild(this.iframePrint); + this.iframePrint.onload = function() { + try { + me.iframePrint.contentWindow.focus(); + me.iframePrint.contentWindow.print(); + me.iframePrint.contentWindow.blur(); + window.focus(); + } catch (e) { + me.api.asc_DownloadAs(new Asc.asc_CDownloadOptions(Asc.c_oAscFileType.PDF)); + } + }; + } + if (url) this.iframePrint.src = url; + }, + + onPrintQuick: function() { + if (!this.appOptions.canQuickPrint) return; + + var value = Common.localStorage.getBool("ve-hide-quick-print-warning"), + me = this, + handler = function () { + var printopt = new Asc.asc_CAdjustPrint(); + printopt.asc_setNativeOptions({quickPrint: true}); + var opts = new Asc.asc_CDownloadOptions(); + opts.asc_setAdvancedOptions(printopt); + me.api.asc_Print(opts); + Common.component.Analytics.trackEvent('Print'); + }; + + if (value) { + handler.call(this); + } else { + Common.UI.warning({ + msg: this.textTryQuickPrint, + buttons: ['yes', 'no'], + primary: 'yes', + dontshow: true, + maxwidth: 500, + callback: function(btn, dontshow){ + dontshow && Common.localStorage.setBool("ve-hide-quick-print-warning", true); + if (btn === 'yes') { + setTimeout(handler, 1); + } + } + }); + } + }, + + warningDocumentIsLocked: function() { + var me = this; + var _disable_ui = function (disable) { + me.disableEditing(disable, 'reconnect'); + }; + + Common.Utils.warningDocumentIsLocked({disablefunc: _disable_ui}); + }, + + showRenameUserDialog: function() { + if (this._renameDialog) return; + + var me = this; + this._renameDialog = new Common.Views.UserNameDialog({ + label: this.textRenameLabel, + error: this.textRenameError, + value: Common.Utils.InternalSettings.get("guest-username") || '', + check: Common.Utils.InternalSettings.get("save-guest-username") || false, + validation: function(value) { + return value.length<128 ? true : me.textLongName; + }, + handler: function(result, settings) { + if (result == 'ok') { + var name = settings.input ? settings.input + ' (' + me.appOptions.guestName + ')' : me.textAnonymous; + var _user = new Asc.asc_CUserInfo(); + _user.put_FullName(name); + + var docInfo = new Asc.asc_CDocInfo(); + docInfo.put_UserInfo(_user); + me.api.asc_changeDocInfo(docInfo); + + settings.checkbox ? Common.localStorage.setItem("guest-username", settings.input) : Common.localStorage.removeItem("guest-username"); + Common.Utils.InternalSettings.set("guest-username", settings.input); + Common.Utils.InternalSettings.set("save-guest-username", settings.checkbox); + } + } + }); + this._renameDialog.on('close', function() { + me._renameDialog = undefined; + }); + this._renameDialog.show(Common.Utils.innerWidth() - this._renameDialog.options.width - 15, 30); + }, + + onGrabFocus: function() { + this.getApplication().getController('DocumentHolder').getView().focus(); + }, + + onLanguageLoaded: function() { + if (!Common.Locale.getCurrentLanguage()) { + Common.UI.warning({ + msg: this.errorLang, + buttons: [], + closable: false + }); + return false; + } + return true; + }, + + onConfirmAction: function(id, apiCallback, data) { + var me = this; + if (id == Asc.c_oAscConfirm.ConfirmMaxChangesSize) { + Common.UI.warning({ + title: this.notcriticalErrorTitle, + msg: this.confirmMaxChangesSize, + buttons: [{value: 'ok', caption: this.textUndo, primary: true}, {value: 'cancel', caption: this.textContinue}], + maxwidth: 600, + callback: _.bind(function(btn) { + if (apiCallback) { + apiCallback(btn === 'ok'); + } + me.onEditComplete(); + }, this) + }); + } + }, + + onLostEditRights: function() { + this._readonlyRights = true; + }, + + changeAccessRights: function(btn,event,opts) { + if (this._docAccessDlg || this._readonlyRights) return; + + if (this.appOptions.canRequestSharingSettings) { + Common.Gateway.requestSharingSettings(); + } else { + var me = this; + me._docAccessDlg = new Common.Views.DocumentAccessDialog({ + settingsurl: this.appOptions.sharingSettingsUrl + }); + me._docAccessDlg.on('accessrights', function(obj, rights){ + me.setSharingSettings({sharingSettings: rights}); + }).on('close', function(obj){ + me._docAccessDlg = undefined; + }); + + me._docAccessDlg.show(); + } + }, + + setSharingSettings: function(data) { + if (data) { + this.document.info.sharingSettings = data.sharingSettings; + Common.NotificationCenter.trigger('collaboration:sharingupdate', data.sharingSettings); + Common.NotificationCenter.trigger('mentions:clearusers', this); + } + }, + + + onSaveDocumentBinary: function(data) { + Common.Gateway.saveDocument(data); + }, + + loadBinary: function(data) { + data && this.api.asc_openDocumentFromBytes(new Uint8Array(data)); + }, + + errorLang: 'The interface language is not loaded.
Please contact your Document Server administrator.' + } + })(), VE.Controllers.Main || {})) +}); \ No newline at end of file diff --git a/apps/visioeditor/main/app/controller/Search.js b/apps/visioeditor/main/app/controller/Search.js new file mode 100644 index 0000000000..3467a3ac1e --- /dev/null +++ b/apps/visioeditor/main/app/controller/Search.js @@ -0,0 +1,459 @@ +/* + * (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 + * + */ + +/** + * ViewTab.js + * + * Created on 11/07/24 + * + */ + +define([ + 'core', + 'common/main/lib/view/SearchPanel' +], function () { + 'use strict'; + + VE.Controllers.Search = Backbone.Controller.extend(_.extend({ + sdkViewName : '#id_main', + + views: [ + 'Common.Views.SearchPanel' + ], + + initialize: function () { + this.addListeners({ + 'SearchBar': { + 'search:back': _.bind(this.onSearchNext, this, 'back'), + 'search:next': _.bind(this.onSearchNext, this, 'next'), + 'search:input': _.bind(function (text) { + if (this._state.searchText === text) { + Common.NotificationCenter.trigger('search:updateresults', this._state.currentResult, this._state.resultsNumber); + return; + } + this.onInputSearchChange(text); + }, this), + 'search:keydown': _.bind(this.onSearchNext, this, 'keydown') + }, + 'Common.Views.SearchPanel': { + 'search:back': _.bind(this.onSearchNext, this, 'back'), + 'search:next': _.bind(this.onSearchNext, this, 'next'), + 'search:replace': _.bind(this.onQueryReplace, this), + 'search:replaceall': _.bind(this.onQueryReplaceAll, this), + 'search:input': _.bind(this.onInputSearchChange, this), + 'search:options': _.bind(this.onChangeSearchOption, this), + 'search:keydown': _.bind(this.onSearchNext, this, 'keydown'), + 'show': _.bind(this.onShowPanel, this), + 'hide': _.bind(this.onHidePanel, this), + }, + 'LeftMenu': { + 'search:aftershow': _.bind(this.onShowAfterSearch, this) + } + }); + }, + onLaunch: function () { + this._state = { + searchText: '', + matchCase: false, + matchWord: false, + useRegExp: false, + isContentChanged: false + }; + }, + + setMode: function (mode) { + this.view = this.createView('Common.Views.SearchPanel', { mode: mode }); + }, + + setApi: function (api) { + if (api) { + this.api = api; + this.api.asc_registerCallback('asc_onSetSearchCurrent', _.bind(this.onUpdateSearchCurrent, this)); + this.api.asc_registerCallback('asc_onStartTextAroundSearch', _.bind(this.onStartTextAroundSearch, this)); + this.api.asc_registerCallback('asc_onEndTextAroundSearch', _.bind(this.onEndTextAroundSearch, this)); + this.api.asc_registerCallback('asc_onGetTextAroundSearchPack', _.bind(this.onApiGetTextAroundSearch, this)); + this.api.asc_registerCallback('asc_onRemoveTextAroundSearch', _.bind(this.onApiRemoveTextAroundSearch, this)); + this.api.asc_registerCallback('asc_onSearchEnd', _.bind(this.onApiSearchEnd, this)); + this.api.asc_registerCallback('asc_onReplaceAll', _.bind(this.onApiTextReplaced, this)); + } + return this; + }, + + getView: function(name) { + return !name && this.view ? + this.view : Backbone.Controller.prototype.getView.call(this, name); + }, + + onChangeSearchOption: function (option, checked) { + switch (option) { + case 'case-sensitive': + this._state.matchCase = checked; + break; + case 'match-word': + this._state.matchWord = checked; + break; + case 'regexp': + this._state.useRegExp = checked; + break; + } + if (this._state.searchText) { + this.onQuerySearch(); + } + }, + + checkPunctuation: function (text) { + if (!!text) { + var isPunctuation = false; + for (var l = 0; l < text.length; l++) { + var charCode = text.charCodeAt(l), + char = text.charAt(l); + if (AscCommon.IsPunctuation(charCode) || char.trim() === '') { + isPunctuation = true; + break; + } + } + if (isPunctuation) { + if (this._state.matchWord) { + this.view.chMatchWord.setValue(false, true); + this._state.matchWord = false; + } + this.view.chMatchWord.setDisabled(true); + } else if (this.view.chMatchWord.isDisabled()) { + this.view.chMatchWord.setDisabled(false); + } + } + }, + + onSearchNext: function (type, text, e) { + var isReturnKey = type === 'keydown' && e.keyCode === Common.UI.Keys.RETURN; + if (text && text.length > 0 && (isReturnKey || type !== 'keydown')) { + this.checkPunctuation(text); + this._state.searchText = text; + this.onQuerySearch(type, !(this.searchTimer || isReturnKey)); + } + }, + + onInputSearchChange: function (text) { + var me = this; + if ((text && this._state.searchText !== text) || (!text && this._state.newSearchText)) { + this._state.newSearchText = text; + this._lastInputChange = (new Date()); + if (this.searchTimer === undefined) { + this.searchTimer = setInterval(function(){ + if ((new Date()) - me._lastInputChange < 400) return; + + me.checkPunctuation(me._state.newSearchText); + me._state.searchText = me._state.newSearchText; + if (!(me._state.newSearchText !== '' && me.onQuerySearch()) && me._state.newSearchText === '') { + me.api.asc_endFindText(); + me.view.updateResultsNumber('no-results'); + me.hideResults(); + me.view.disableNavButtons(); + me.view.disableReplaceButtons(true); + clearInterval(me.searchTimer); + me.searchTimer = undefined; + + Common.NotificationCenter.trigger('search:updateresults'); + } + }, 10); + } + } + }, + + onQuerySearch: function (d, noUpdate) { + var update = !noUpdate || this._state.isContentChanged; + this._state.isContentChanged = false; + this.searchTimer && clearInterval(this.searchTimer); + this.searchTimer = undefined; + update && this.hideResults(); + + var searchSettings = new AscCommon.CSearchSettings(); + searchSettings.put_Text(this._state.searchText); + searchSettings.put_MatchCase(this._state.matchCase); + searchSettings.put_WholeWords(this._state.matchWord); + if (!this.api.asc_findText(searchSettings, d != 'back')) { + this.resultItems = []; + this.view.updateResultsNumber(undefined, 0); + this.hideResults(); + this.view.disableReplaceButtons(true); + this._state.currentResult = 0; + this._state.resultsNumber = 0; + this.view.disableNavButtons(); + + Common.NotificationCenter.trigger('search:updateresults'); + return false; + } + + if (update && this.view.$el.is(':visible') && this.view.$resultsContainer.find('.many-results').length === 0) { + this.api.asc_StartTextAroundSearch(); + } + this.view.disableReplaceButtons(false); + return true; + }, + + onQueryReplace: function(textSearch, textReplace) { + if (textSearch !== '') { + var searchSettings = new AscCommon.CSearchSettings(); + searchSettings.put_Text(textSearch); + searchSettings.put_MatchCase(this._state.matchCase); + searchSettings.put_WholeWords(this._state.matchWord); + if (!this.api.asc_replaceText(searchSettings, textReplace, false)) { + this.removeResultItems(); + } + } + }, + + onQueryReplaceAll: function(textSearch, textReplace) { + if (textSearch !== '') { + var searchSettings = new AscCommon.CSearchSettings(); + searchSettings.put_Text(textSearch); + searchSettings.put_MatchCase(this._state.matchCase); + searchSettings.put_WholeWords(this._state.matchWord); + this.api.asc_replaceText(searchSettings, textReplace, true); + + this.removeResultItems('replace-all'); + } + }, + + removeResultItems: function (type) { + this.resultItems = []; + type !== 'replace-all' && this.view.updateResultsNumber(type, 0); // type === undefined, count === 0 -> no matches + this.hideResults(); + this.view.disableReplaceButtons(true); + this._state.currentResult = 0; + this._state.resultsNumber = 0; + this.view.disableNavButtons(); + }, + + onUpdateSearchCurrent: function (current, all) { + if (current === -1) return; + this._state.currentResult = current; + this._state.resultsNumber = all; + if (this.view) { + this.view.updateResultsNumber(current, all); + this.view.disableNavButtons(current, all); + if (this.resultItems && this.resultItems.length > 0) { + this.resultItems.forEach(function (item) { + item.selected = false; + }); + if (this.resultItems[current]) { + this.resultItems[current].selected = true; + $('#search-results').find('.item').removeClass('selected'); + $(this.resultItems[current].el).addClass('selected'); + this.scrollToSelectedResult(current); + } + } + } + Common.NotificationCenter.trigger('search:updateresults', current, all); + }, + + scrollToSelectedResult: function (ind) { + var index = ind !== undefined ? ind : _.findIndex(this.resultItems, {selected: true}); + if (index !== -1) { + var item = this.resultItems[index].$el, + itemHeight = item.outerHeight(), + itemTop = Common.Utils.getPosition(item).top, + container = this.view.$resultsContainer, + containerHeight = container.outerHeight(), + containerTop = container.scrollTop(); + if (itemTop < 0 || (containerTop === 0 && itemTop > containerHeight)) { + container.scroller.scrollTop(containerTop + itemTop - 12); + } else if (itemTop + itemHeight > containerHeight) { + container.scroller.scrollTop(containerTop + itemHeight); + } + } + }, + + onStartTextAroundSearch: function () { + if (this.view) { + this._state.isStartedAddingResults = true; + } + }, + + onEndTextAroundSearch: function () { + if (this.view) { + this.view.updateScrollers(); + } + }, + + onApiGetTextAroundSearch: function (data) { + if (this.view && this._state.isStartedAddingResults) { + this._state.isStartedAddingResults = false; + if (data.length > 300 || !data.length) return; + var me = this, + selectedInd; + me.resultItems = []; + data.forEach(function (item, ind) { + var el = document.createElement("div"), + isSelected = ind === me._state.currentResult; + el.className = 'item'; + var innerHtml = ""; + for (var i = 0, count = item[1].length; i < count; ++i) { + if (1 == i) + innerHtml += "" + Common.Utils.String.htmlEncode(item[1][i]) + ""; + else + innerHtml += Common.Utils.String.htmlEncode(item[1][i]); + } + el.innerHTML = innerHtml.trim(); + el.setAttribute('role', 'listitem'); + me.view.$resultsContainer.append(el); + if (isSelected) { + $(el).addClass('selected'); + selectedInd = ind; + } + + var resultItem = {id: item[0], $el: $(el), el: el, selected: isSelected}; + me.resultItems.push(resultItem); + $(el).on('click', _.bind(function (el) { + if (me._state.isContentChanged) { + me.onQuerySearch(); + return; + } + var id = item[0]; + me.api.asc_SelectSearchElement(id); + }, me)); + }); + + this.view.$resultsContainer.show(); + this.scrollToSelectedResult(selectedInd); + } + }, + + onApiRemoveTextAroundSearch: function (arr) { + var me = this; + arr.forEach(function (id) { + var ind = _.findIndex(me.resultItems, {id: id}); + if (ind !== -1) { + me.resultItems[ind].$el.remove(); + me.resultItems.splice(ind, 1); + } + }); + }, + + hideResults: function () { + if (this.view) { + if (this.view.$resultsContainer.find('.many-results').length === 0) { + this.view.$resultsContainer.hide(); + } + this.view.$resultsContainer.find('.item').remove(); + } + }, + + onShowAfterSearch: function (findText) { + var viewport = this.getApplication().getController('Viewport'); + if (viewport.isSearchBarVisible()) { + viewport.searchBar.hide(); + } + + var selectedText = this.api.asc_GetSelectedText(), + text = typeof findText === 'string' ? findText : (selectedText && selectedText.trim() || this._state.searchText); + this.checkPunctuation(text); + if (text) { + this.view.setFindText(text); + } else if (text !== undefined) { // panel was opened from empty searchbar, clear to start new search + this.view.setFindText(''); + this._state.searchText = undefined; + } + + this.hideResults(); + if (text && text !== '' && text === this._state.searchText) { // search was made + this.view.disableReplaceButtons(false); + if (this.view.$resultsContainer.find('.many-results').length === 0) { + this.api.asc_StartTextAroundSearch(); + } + } else if (text && text !== '') { // search wasn't made + this.onInputSearchChange(text); + } else { + this.resultItems = []; + this.view.disableReplaceButtons(true); + this.view.clearResultsNumber(); + } + this.view.disableNavButtons(this._state.currentResult, this._state.resultsNumber); + }, + + onShowPanel: function () { + if (this.resultItems && this.resultItems.length > 0 && !this._state.isStartedAddingResults) { + var me = this; + this.view.$resultsContainer.show(); + this.resultItems.forEach(function (item) { + me.view.$resultsContainer.append(item.el); + $(item.el)[item.selected ? 'addClass' : 'removeClass']('selected'); + $(item.el).on('click', function (el) { + me.api.asc_SelectSearchElement(item.id); + $('#search-results').find('.item').removeClass('selected'); + $(el.currentTarget).addClass('selected'); + }); + }); + this.scrollToSelectedResult(); + } + }, + + onHidePanel: function () { + this.hideResults(); + }, + + onApiSearchEnd: function () { + if (!this._state.isContentChanged) { + this._state.isContentChanged = true; + this.view.updateResultsNumber('content-changed'); + this.view.disableReplaceButtons(true); + } + }, + + onApiTextReplaced: function(found, replaced) { + if (found) { + !(found - replaced > 0) ? + /*Common.UI.info( {msg: Common.Utils.String.format(this.textReplaceSuccess, replaced)} ) : + Common.UI.warning( {msg: Common.Utils.String.format(this.textReplaceSkipped, found-replaced)} );*/ + this.view.updateResultsNumber('replace-all', replaced) : + this.view.updateResultsNumber('replace', [replaced, found, found-replaced]); + } else { + Common.UI.info({msg: this.textNoTextFound}); + } + }, + + getSearchText: function () { + return this._state.searchText; + }, + + getResultsNumber: function () { + return [this._state.currentResult, this._state.resultsNumber]; + }, + + notcriticalErrorTitle: 'Warning', + warnReplaceString: '{0} is not a valid special character for the Replace With box.', + textReplaceSuccess: 'Search has been done. {0} occurrences have been replaced', + textReplaceSkipped: 'The replacement has been made. {0} occurrences were skipped.', + textNoTextFound: 'The data you have been searching for could not be found. Please adjust your search options.' + + }, VE.Controllers.Search || {})); +}); \ No newline at end of file diff --git a/apps/visioeditor/main/app/controller/Statusbar.js b/apps/visioeditor/main/app/controller/Statusbar.js new file mode 100644 index 0000000000..6a7e1f85b5 --- /dev/null +++ b/apps/visioeditor/main/app/controller/Statusbar.js @@ -0,0 +1,224 @@ +/* + * (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 + * + */ +/** + * Statusbar.js + * + * Statusbar controller + * + * Created on 11/07/24 + * + */ + +define([ + 'core', + 'visioeditor/main/app/view/Statusbar', + 'common/main/lib/util/LanguageInfo', + 'common/main/lib/component/InputField' +], function () { + 'use strict'; + + VE.Controllers.Statusbar = Backbone.Controller.extend(_.extend({ + models: [], + collections: [], + views: [ + 'Statusbar' + ], + + initialize: function() { + var me = this; + this.addListeners({ + 'Statusbar': { + 'zoom:value': function(value) { + this.api.zoom(value); + Common.NotificationCenter.trigger('edit:complete', this.statusbar); + }.bind(this) + }, + 'ViewTab': { + 'statusbar:hide': _.bind(me.onChangeCompactView, me) + } + }); + }, + + events: function() { + return { + 'click #btn-zoom-down': _.bind(this.zoomDocument,this,'down'), + 'click #btn-zoom-up': _.bind(this.zoomDocument,this,'up'), + 'click #btn-zoom-topage': _.bind(this.onBtnZoomTo, this, 'topage'), + 'click #btn-zoom-towidth': _.bind(this.onBtnZoomTo, this, 'towidth') + }; + }, + + + onLaunch: function() { + this.statusbar = this.createView('Statusbar', { + // storeUsers: this.getApplication().getCollection('Common.Collections.Users') + }); + + var me = this; + Common.NotificationCenter.on('app:face', function (cfg) { + me.statusbar.render(cfg); + me.statusbar.$el.css('z-index', 1); + + var lblzoom = $('.statusbar #label-zoom'); + lblzoom.css('min-width', 80); + lblzoom.text(Common.Utils.String.format(me.zoomText, 100)); + }); + Common.NotificationCenter.on('app:ready', me.onAppReady.bind(me)); + }, + + onAppReady: function (config) { + var me = this; + me._isDocReady = true; + (new Promise(function(resolve) { + resolve(); + })).then(function () { + me.bindViewEvents(me.statusbar, me.events); + }); + }, + + onChangeCompactView: function (view, status) { + this.statusbar.setVisible(!status); + Common.localStorage.setBool('ve-hidden-status', status); + + if (view.$el.closest('.btn-slot').prop('id') === 'slot-btn-options') { + this.statusbar.fireEvent('view:hide', [this, status]); + } + + Common.NotificationCenter.trigger('layout:changed', 'status'); + Common.NotificationCenter.trigger('edit:complete', this.statusbar); + }, + + setApi: function(api) { + this.api = api; + this.api.asc_registerCallback('asc_onZoomChange', _.bind(this._onZoomChange, this)); + this.statusbar.setApi(api); + }, + + onBtnZoomTo: function(d, e) { + var _btn, _func; + if ( d == 'topage' ) { + _btn = 'btnZoomToPage'; + _func = 'zoomFitToPage'; + } else { + _btn = 'btnZoomToWidth'; + _func = 'zoomFitToWidth'; + } + + if ( !this.statusbar[ _btn ].pressed ) + this.api.zoomCustomMode(); else + this.api[ _func ](); + + Common.NotificationCenter.trigger('edit:complete', this.statusbar); + }, + + zoomDocument: function(d,e) { + switch (d) { + case 'up': this.api.zoomIn(); break; + case 'down': this.api.zoomOut(); break; + } + Common.NotificationCenter.trigger('edit:complete', this.statusbar); + }, + + /* + * api events + * */ + + _onZoomChange: function(percent, type) { + this.statusbar.btnZoomToPage.toggle(type == 2, true); + this.statusbar.btnZoomToWidth.toggle(type == 1, true); + $('.statusbar #label-zoom').text(Common.Utils.String.format(this.zoomText, percent)); + if(!this._isDocReady) return; + var value = type == 2 ? -1 : (type == 1 ? -2 : percent); + Common.localStorage.setItem('ve-last-zoom', value); + Common.Utils.InternalSettings.set('ve-last-zoom', value); + }, + + setStatusCaption: function(text, force, delay, callback) { + if (this.timerCaption && ( ((new Date()) < this.timerCaption) || text.length==0 ) && !force ) + return; + + this.timerCaption = undefined; + if (text.length) { + this.statusbar.showStatusMessage(text); + callback && callback(); + if (delay>0) + this.timerCaption = (new Date()).getTime() + delay; + } else + this.statusbar.clearStatusMessage(); + }, + + createDelayedElements: function() { + this.statusbar.$el.css('z-index', ''); + }, + + synchronizeChanges: function() { + this.setStatusCaption(''); + }, + + showDisconnectTip: function () { + var me = this; + if (!this.disconnectTip) { + var target = this.statusbar.getStatusLabel(); + target = target.is(':visible') ? target.parent() : this.statusbar.isVisible() ? this.statusbar.$el : $(document.body); + this.disconnectTip = new Common.UI.SynchronizeTip({ + target : target, + text : this.textDisconnect, + placement: 'top', + position: this.statusbar.isVisible() ? undefined : {bottom: 0}, + showLink: false, + style: 'max-width: 310px;' + }); + this.disconnectTip.on({ + 'closeclick': function() { + me.disconnectTip.hide(); + me.disconnectTip = null; + } + }); + } + this.disconnectTip.show(); + }, + + hideDisconnectTip: function() { + this.disconnectTip && this.disconnectTip.hide(); + this.disconnectTip = null; + }, + + onSelectTool: function (type, btn, e) { + if (this.api) { + this.api.asc_setViewerTargetType(type); + } + }, + + zoomText : 'Zoom {0}%', + textDisconnect: 'Connection is lost
Trying to connect. Please check connection settings.' + }, VE.Controllers.Statusbar || {})); +}); \ No newline at end of file diff --git a/apps/visioeditor/main/app/controller/Toolbar.js b/apps/visioeditor/main/app/controller/Toolbar.js new file mode 100644 index 0000000000..dd6d9865ad --- /dev/null +++ b/apps/visioeditor/main/app/controller/Toolbar.js @@ -0,0 +1,442 @@ +/* + * (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 + * + */ +/** + * Toolbar.js + * + * Toolbar Controller + * + * Created on 11/07/24 + * + */ + +define([ + 'core', + 'common/main/lib/component/Window', + 'visioeditor/main/app/view/Toolbar' +], function () { + 'use strict'; + + VE.Controllers.Toolbar = Backbone.Controller.extend(_.extend({ + models: [], + collections: [], + controllers: [], + views: [ + 'Toolbar' + ], + + initialize: function() { + this._state = { + activated: false, + can_copy: undefined, + can_cut: undefined, + pageCount: 1, + currentPage: 0, + initEditing: true + }; + this.editMode = true; + this.binding = {}; + + this.addListeners({ + 'Toolbar': { + 'change:compact' : this.onClickChangeCompact, + 'home:open' : this.onHomeOpen, + 'tab:active' : this.onActiveTab, + 'tab:collapse' : this.onTabCollapse + }, + 'FileMenu': { + 'menu:hide': this.onFileMenu.bind(this, 'hide'), + 'menu:show': this.onFileMenu.bind(this, 'show'), + 'settings:apply': this.applySettings.bind(this), + }, + 'Common.Views.Header': { + 'print': function (opts) { + var _main = this.getApplication().getController('Main'); + _main.onPrint(); + }, + 'print-quick': function (opts) { + var _main = this.getApplication().getController('Main'); + _main.onPrintQuick(); + }, + 'save': function (opts) { + this.tryToSave(); + }, + 'downloadas': function (opts) { + var _main = this.getApplication().getController('Main'); + var _file_type = _main.document.fileType, + _format; + if ( !!_file_type ) { + _format = Asc.c_oAscFileType[ _file_type.toUpperCase() ]; + } + + var _supported = [ + Asc.c_oAscFileType.VSDX, + Asc.c_oAscFileType.PDFA + ]; + + if ( !_format || _supported.indexOf(_format) < 0 ) + _format = Asc.c_oAscFileType.PDF; + + _main.api.asc_DownloadAs(new Asc.asc_CDownloadOptions(_format)); + }, + 'go:editor': function() { + Common.Gateway.requestEditRights(); + } + }, + 'ViewTab': { + 'toolbar:setcompact': this.onChangeCompactView.bind(this) + } + }); + + Common.NotificationCenter.on('toolbar:collapse', _.bind(function () { + this.toolbar.collapse(); + }, this)); + }, + + onLaunch: function() { + // Create toolbar view + this.toolbar = this.createView('Toolbar'); + this.toolbar.on('render:before', function (cmp) { + }); + + Common.NotificationCenter.on('app:ready', this.onAppReady.bind(this)); + Common.NotificationCenter.on('app:face', this.onAppShowed.bind(this)); + }, + + setMode: function(mode) { + this.mode = mode; + this.toolbar.applyLayout(mode); + }, + + attachCommonUIEvents: function(toolbar) { + }, + + attachEditUIEvents: function(toolbar) { + if (!this.mode || !this.mode.isEdit) return; + }, + + attachUIEvents: function(toolbar) { + /** + * UI Events + */ + this.attachCommonUIEvents(toolbar); + if (this.mode.isEdit) { + this.attachEditUIEvents(toolbar); + } + }, + + attachCommonApiEvents: function() { + this.api.asc_registerCallback('asc_onCountPages', _.bind(this.onCountPages, this)); + this.api.asc_registerCallback('asc_onCurrentPage', _.bind(this.onCurrentPage, this)); + this.api.asc_registerCallback('asc_onDownloadUrl', _.bind(this.onDownloadUrl, this)); + this.api.asc_registerCallback('onPluginToolbarMenu', _.bind(this.onPluginToolbarMenu, this)); + this.api.asc_registerCallback('onPluginToolbarCustomMenuItems', _.bind(this.onPluginToolbarCustomMenuItems, this)); + Common.NotificationCenter.on('document:ready', _.bind(this.onDocumentReady, this)); + }, + + attachEditApiEvents: function() { + if (!this.mode.isEdit) return; + + // this.api.asc_registerCallback('asc_onFocusObject', _.bind(this.onApiFocusObject, this)); + }, + + setApi: function(api) { + this.api = api; + this.attachCommonApiEvents(); + + if (this.mode.isEdit) { + this.attachEditApiEvents(); + } + }, + + onChangeCompactView: function(view, compact) { + this.toolbar.setFolded(compact); + this.toolbar.fireEvent('view:compact', [this, compact]); + + compact && this.onTabCollapse(); + + Common.localStorage.setBool('ve-compact-toolbar', compact); + Common.NotificationCenter.trigger('layout:changed', 'toolbar'); + Common.NotificationCenter.trigger('edit:complete', this.toolbar); + }, + + onClickChangeCompact: function (from) { + if ( from != 'file' ) { + var me = this; + setTimeout(function () { + me.onChangeCompactView(null, !me.toolbar.isCompact()); + }, 0); + } + }, + + onContextMenu: function() { + this.toolbar.collapse(); + }, + + onCountPages: function(count) { + this._state.pageCount = count; + }, + + onCurrentPage: function(value) { + this._state.currentPage = value; + }, + + onNewDocument: function(btn, e) { + if (this.api) + this.api.OpenNewDocument(); + + Common.NotificationCenter.trigger('edit:complete', this.toolbar); + Common.component.Analytics.trackEvent('ToolBar', 'New Document'); + }, + + onOpenDocument: function(btn, e) { + if (this.api) + this.api.LoadDocumentFromDisk(); + + Common.NotificationCenter.trigger('edit:complete', this.toolbar); + Common.component.Analytics.trackEvent('ToolBar', 'Open Document'); + }, + + onPrint: function(e) { + if (this.toolbar.btnPrint.options.printType == 'print') { + Common.NotificationCenter.trigger('file:print', this.toolbar); + Common.NotificationCenter.trigger('edit:complete', this.toolbar); + } else { + var _main = this.getApplication().getController('Main'); + _main.onPrintQuick(); + } + Common.component.Analytics.trackEvent('Print'); + Common.component.Analytics.trackEvent('ToolBar', 'Print'); + + }, + + onPrintMenu: function (btn, e){ + var oldType = this.toolbar.btnPrint.options.printType; + var newType = e.value; + + if(newType != oldType) { + this.toolbar.btnPrint.changeIcon({ + next: e.options.iconClsForMainBtn, + curr: this.toolbar.btnPrint.menu.getItems().filter(function(item){return item.value == oldType;})[0].options.iconClsForMainBtn + }); + this.toolbar.btnPrint.updateHint([e.caption + e.options.platformKey]); + this.toolbar.btnPrint.options.printType = newType; + } + this.onPrint(e); + }, + + tryToSave: function () { + var toolbar = this.toolbar, + mode = toolbar.mode, + me = this; + if (!mode.canSaveToFile) { + } else if (this.api) { + } + }, + + onDownloadUrl: function(url, fileType) { + if (this._state.isFromToolbarDownloadAs) { + var me = this, + defFileName = this.getApplication().getController('Viewport').getView('Common.Views.Header').getDocumentCaption(); + !defFileName && (defFileName = me.txtUntitled); + + if (me.toolbar.mode.canRequestSaveAs) { + Common.Gateway.requestSaveAs(url, defFileName, fileType); + } else { + me._saveCopyDlg = new Common.Views.SaveAsDlg({ + saveFolderUrl: me.toolbar.mode.saveAsUrl, + saveFileUrl: url, + defFileName: defFileName + }); + me._saveCopyDlg.on('saveaserror', function(obj, err){ + Common.UI.warning({ + closable: false, + msg: err, + callback: function(btn){ + Common.NotificationCenter.trigger('edit:complete', me); + } + }); + }).on('close', function(obj){ + me._saveCopyDlg = undefined; + }); + me._saveCopyDlg.show(); + } + } + this._state.isFromToolbarDownloadAs = false; + }, + + onBtnChangeState: function(prop) { + if ( /\:disabled$/.test(prop) ) { + var _is_disabled = arguments[2]; + this.toolbar.fireEvent(prop, [_is_disabled]); + } + }, + + activateControls: function() { + this.toolbar.lockToolbar(Common.enumLock.disableOnStart, false); + this._state.activated = true; + }, + + onHideMenus: function(e){ + Common.NotificationCenter.trigger('edit:complete', this.toolbar); + }, + + onApiCoAuthoringDisconnect: function(enableDownload) { + (this.mode.isEdit) && this.toolbar.setMode({isDisconnected:true, enableDownload: !!enableDownload}); + this.editMode = false; + this.DisableToolbar(true, true); + }, + + DisableToolbar: function(disable, viewMode) { + if (viewMode!==undefined) this.editMode = !viewMode; + disable = disable || !this.editMode; + + var mask = $('.toolbar-mask'); + if (disable && mask.length>0 || !disable && mask.length==0) return; + + var toolbar = this.toolbar; + toolbar.hideMoreBtns(); + toolbar.$el.find('.toolbar').toggleClass('masked', disable); + + if(disable) { + mask = $("
").appendTo(toolbar.$el.find('.toolbar')); + } else { + mask.remove(); + } + }, + + createDelayedElements: function() { + this.toolbar.createDelayedElements(); + this.attachUIEvents(this.toolbar); + Common.Utils.injectSvgIcons(); + }, + + onAppShowed: function (config) { + var me = this; + + var compactview = !config.isEdit; + if ( config.isEdit ) { + if ( Common.localStorage.itemExists("ve-compact-toolbar") ) { + compactview = Common.localStorage.getBool("ve-compact-toolbar"); + } else + if ( config.customization && config.customization.compactToolbar ) + compactview = true; + + } + me.toolbar.render(_.extend({compactview: compactview}, config)); + + if ( config.isEdit) { + me.toolbar.setMode(config); + if (!config.compactHeader) { + // hide 'print' and 'save' buttons group and next separator + me.toolbar.btnPrint.$el.parents('.group').hide().next().hide(); + + // hide 'undo' and 'redo' buttons and retrieve parent container + var $box = me.toolbar.btnUndo.$el.hide().next().hide().parent(); + + // move 'paste' button to the container instead of 'undo' and 'redo' + me.toolbar.btnPaste.$el.detach().appendTo($box); + me.toolbar.btnPaste.$el.find('button').attr('data-hint-direction', 'bottom'); + me.toolbar.btnCopy.$el.removeClass('split'); + me.toolbar.processPanelVisible(null, true); + } + } + var tab = {caption: me.toolbar.textTabView, action: 'view', extcls: config.isEdit ? 'canedit' : '', layoutname: 'toolbar-view', dataHintTitle: 'W'}; + var viewtab = me.getApplication().getController('ViewTab'); + viewtab.setApi(me.api).setConfig({toolbar: me, mode: config}); + var $panel = viewtab.createToolbarPanel(); + if ($panel) { + me.toolbar.addTab(tab, $panel, 8); + me.toolbar.setVisible('view', Common.UI.LayoutManager.isElementVisible('toolbar-view')); + } + }, + + onAppReady: function (config) { + var me = this; + me.appOptions = config; + + (new Promise(function(accept) { + accept(); + })).then(function () { + }); + }, + + getView: function (name) { + return !name ? this.toolbar : Backbone.Controller.prototype.getView.apply(this, arguments); + }, + + onFileMenu: function (opts) { + if ( opts == 'show' ) { + if ( !this.toolbar.isTabActive('file') ) + this.toolbar.setTab('file'); + } else { + if ( this.toolbar.isTabActive('file') ) + this.toolbar.setTab(); + } + }, + + onActiveTab: function(tab) { + }, + + onTabCollapse: function(tab) { + }, + + applySettings: function() { + }, + + onPluginToolbarMenu: function(data) { + this.toolbar && Array.prototype.push.apply(this.toolbar.lockControls, Common.UI.LayoutManager.addCustomControls(this.toolbar, data)); + }, + + onPluginToolbarCustomMenuItems: function(action, data) { + if (!this._isDocReady) { + this._state.customPluginData = (this._state.customPluginData || []).concat([{action: action, data: data}]); + return; + } + var api = this.api; + this.toolbar && Common.UI.LayoutManager.addCustomMenuItems(action, data, function(guid, value) { + api && api.onPluginContextMenuItemClick(guid, value); + }); + }, + + onDocumentReady: function() { + this._isDocReady = true; + var me = this; + this._state.customPluginData && this._state.customPluginData.forEach(function(plugin) { + me.onPluginToolbarCustomMenuItems(plugin.action, plugin.data); + }); + this._state.customPluginData = null; + }, + + txtUntitled: 'Untitled' + + }, VE.Controllers.Toolbar || {})); +}); diff --git a/apps/visioeditor/main/app/controller/ViewTab.js b/apps/visioeditor/main/app/controller/ViewTab.js new file mode 100644 index 0000000000..36d56bffcb --- /dev/null +++ b/apps/visioeditor/main/app/controller/ViewTab.js @@ -0,0 +1,209 @@ +/* + * (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 + * + */ + +/** + * ViewTab.js + * + * Created on 11/07/24 + * + */ + +define([ + 'core', + 'visioeditor/main/app/view/ViewTab' +], function () { + 'use strict'; + + VE.Controllers.ViewTab = Backbone.Controller.extend(_.extend({ + models : [], + collections : [ + ], + views : [ + 'ViewTab' + ], + sdkViewName : '#id_main', + + initialize: function () { + }, + onLaunch: function () { + this._state = { + zoom_type: undefined, + zoom_percent: undefined + }; + Common.NotificationCenter.on('uitheme:changed', this.onThemeChanged.bind(this)); + Common.NotificationCenter.on('document:ready', _.bind(this.onDocumentReady, this)); + Common.NotificationCenter.on('tabstyle:changed', this.onTabStyleChange.bind(this)); + }, + + setApi: function (api) { + if (api) { + this.api = api; + this.api.asc_registerCallback('asc_onZoomChange', _.bind(this.onZoomChange, this)); + this.api.asc_registerCallback('asc_onCoAuthoringDisconnect', _.bind(this.onCoAuthoringDisconnect, this)); + Common.NotificationCenter.on('api:disconnect', _.bind(this.onCoAuthoringDisconnect, this)); + } + return this; + }, + + setConfig: function(config) { + var mode = config.mode; + this.toolbar = config.toolbar; + this.view = this.createView('ViewTab', { + toolbar: this.toolbar.toolbar, + mode: mode, + compactToolbar: this.toolbar.toolbar.isCompactView + }); + this.addListeners({ + 'ViewTab': { + 'zoom:selected': _.bind(this.onSelectedZoomValue, this), + 'zoom:changedbefore': _.bind(this.onZoomChanged, this), + 'zoom:changedafter': _.bind(this.onZoomChanged, this), + 'zoom:toslide': _.bind(this.onBtnZoomTo, this, 'toslide'), + 'zoom:towidth': _.bind(this.onBtnZoomTo, this, 'towidth') + }, + 'Toolbar': { + 'view:compact': _.bind(function (toolbar, state) { + this.view.chToolbar.setValue(!state, true); + }, this) + }, + 'Statusbar': { + 'view:hide': _.bind(function (statusbar, state) { + this.view.chStatusbar.setValue(!state, true); + }, this) + }, + 'LeftMenu': { + 'view:hide': _.bind(function (leftmenu, state) { + this.view.chLeftMenu.setValue(!state, true); + }, this) + } + }); + }, + + SetDisabled: function(state) { + this.view && this.view.SetDisabled(state); + }, + + createToolbarPanel: function() { + return this.view.getPanel(); + }, + + getView: function(name) { + return !name && this.view ? + this.view : Backbone.Controller.prototype.getView.call(this, name); + }, + + onCoAuthoringDisconnect: function() { + this.SetDisabled(true); + }, + + onDocumentReady: function() { + Common.Utils.lockControls(Common.enumLock.disableOnStart, false, {array: this.view.lockedControls}); + }, + + onZoomChange: function (percent, type) { + if (this._state.zoom_type !== type) { + this.view.btnFitToSlide.toggle(type == 2, true); + this.view.btnFitToWidth.toggle(type == 1, true); + this._state.zoom_type = type; + } + if (this._state.zoom_percent !== percent) { + this.view.cmbZoom.setValue(percent, percent + '%'); + this._state.zoom_percent = percent; + } + }, + + onBtnZoomTo: function (type, btn) { + this._state.zoom_type = undefined; + this._state.zoom_percent = undefined; + if (!btn.pressed) + this.api.zoomCustomMode(); + else + this.api[type === 'toslide' ? 'zoomFitToPage' : 'zoomFitToWidth'](); + Common.NotificationCenter.trigger('edit:complete', this.view); + }, + + onThemeChanged: function () { + if (this.view && Common.UI.Themes.available()) { + var current_theme = Common.UI.Themes.currentThemeId() || Common.UI.Themes.defaultThemeId(), + menu_item = _.findWhere(this.view.btnInterfaceTheme.menu.getItems(true), {value: current_theme}); + if ( !!menu_item ) { + this.view.btnInterfaceTheme.menu.clearAll(true); + menu_item.setChecked(true, true); + } + } + }, + + applyZoom: function (value) { + this._state.zoom_percent = undefined; + this._state.zoom_type = undefined; + var val = Math.max(10, Math.min(500, value)); + if (this._state.zoomValue === val) + this.view.cmbZoom.setValue(this._state.zoomValue, this._state.zoomValue + '%'); + this.api.zoom(val); + Common.NotificationCenter.trigger('edit:complete', this.view); + }, + + onSelectedZoomValue: function (combo, record) { + this.applyZoom(record.value); + }, + + onZoomChanged: function (before, combo, record, e) { + var value = parseFloat(record.value); + if (before) { + var expr = new RegExp('^\\s*(\\d*(\\.|,)?\\d+)\\s*(%)?\\s*$'); + if (!expr.exec(record.value)) { + this.view.cmbZoom.setValue(this._state.zoom_percent, this._state.zoom_percent + '%'); + Common.NotificationCenter.trigger('edit:complete', this.view); + } + } else { + if (this._state.zoom_percent !== value && !isNaN(value)) { + this.applyZoom(value); + } else if (record.value !== this._state.zoom_percent + '%') { + this.view.cmbZoom.setValue(this._state.zoom_percent, this._state.zoom_percent + '%'); + } + } + }, + + onComboBlur: function() { + Common.NotificationCenter.trigger('edit:complete', this.view); + }, + + onTabStyleChange: function () { + if (this.view && this.view.menuTabStyle) { + _.each(this.view.menuTabStyle.items, function(item){ + item.setChecked(Common.Utils.InternalSettings.get("settings-tab-style")===item.value, true); + }); + } + } + + }, VE.Controllers.ViewTab || {})); +}); \ No newline at end of file diff --git a/apps/visioeditor/main/app/controller/Viewport.js b/apps/visioeditor/main/app/controller/Viewport.js new file mode 100644 index 0000000000..b7ba91c9ef --- /dev/null +++ b/apps/visioeditor/main/app/controller/Viewport.js @@ -0,0 +1,337 @@ +/* + * (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 + * + */ +/** + * Viewport.js + * + * This is out main controller which will do most of job + * It will listen for view and collection events and manage all data-related operations + * + * Created on 11/07/24 + * + */ + +define([ + 'core', + 'common/main/lib/view/Header', + 'common/main/lib/view/SearchBar', + 'visioeditor/main/app/view/Viewport', + 'visioeditor/main/app/view/LeftMenu' +], function (Viewport) { + 'use strict'; + + VE.Controllers.Viewport = Backbone.Controller.extend(_.assign({ + // Specifying a Viewport model + models: [], + + // Specifying a collection of out Viewport + collections: [], + + // Specifying application views + views: [ + 'Viewport', // is main application layout + 'Common.Views.Header' + ], + + // When controller is created let's setup view event listeners + initialize: function() { + // This most important part when we will tell our controller what events should be handled + + var me = this; + this.addListeners({ + 'FileMenu': { + 'menu:hide': me.onFileMenu.bind(me, 'hide'), + 'menu:show': me.onFileMenu.bind(me, 'show'), + 'settings:apply': me.applySettings.bind(me) + }, + 'Statusbar': { + 'view:compact': function (statusbar, state) { + me.viewport.vlayout.getItem('statusbar').height = state ? 25 : 50; + } + }, + 'Toolbar': { + 'render:before' : function (toolbar) { + var config = VE.getController('Main').appOptions; + toolbar.setExtra('right', me.header.getPanel('right', config)); + if (!config.twoLevelHeader || config.compactHeader) + toolbar.setExtra('left', me.header.getPanel('left', config)); + + /*var value = Common.localStorage.getBool("ve-settings-quick-print-button", true); + Common.Utils.InternalSettings.set("ve-settings-quick-print-button", value); + if (me.header && me.header.btnPrintQuick) + me.header.btnPrintQuick[value ? 'show' : 'hide']();*/ + }, + 'view:compact' : function (toolbar, state) { + me.viewport.vlayout.getItem('toolbar').height = state ? + Common.Utils.InternalSettings.get('toolbar-height-compact') : Common.Utils.InternalSettings.get('toolbar-height-normal'); + }, + 'print:disabled' : function (state) { + if ( me.header.btnPrint ) + me.header.btnPrint.setDisabled(state); + if ( me.header.btnPrintQuick ) + me.header.btnPrintQuick.setDisabled(state); + }, + 'save:disabled' : function (state) { + if ( me.header.btnSave ) + me.header.btnSave.setDisabled(state); + } + } + }); + Common.NotificationCenter.on('tabstyle:changed', this.onTabStyleChange.bind(this)); + Common.NotificationCenter.on('tabbackground:changed', this.onTabBackgroundChange.bind(this)); + this._initEditing = true; + }, + + setApi: function(api) { + this.api = api; + this.api.asc_registerCallback('asc_onCoAuthoringDisconnect',this.onApiCoAuthoringDisconnect.bind(this)); + Common.NotificationCenter.on('api:disconnect', this.onApiCoAuthoringDisconnect.bind(this)); + }, + + getApi: function() { + return this.api; + }, + + setMode: function(mode) { + this.mode = mode; + this.viewport && this.viewport.setMode(mode); + }, + + // When our application is ready, lets get started + onLaunch: function() { + // Create and render main view + this.viewport = this.createView('Viewport').render(); + + this.api = new Asc.asc_docs_api({ + 'id-view' : 'editor_sdk', + 'translate': this.getApplication().getController('Main').translationTable + }); + + this.header = this.createView('Common.Views.Header', { + headerCaption: 'Visio Editor', + storeUsers: VE.getCollection('Common.Collections.Users') + }); + + Common.NotificationCenter.on('layout:changed', _.bind(this.onLayoutChanged, this)); + $(window).on('resize', _.bind(this.onWindowResize, this)); + + var leftPanel = $('#left-menu'); + this.viewport.hlayout.on('layout:resizedrag', function() { + this.api.Resize(); + Common.localStorage.setItem('ve-mainmenu-width', leftPanel.width() ); + }, this); + + this.boxSdk = $('#editor_sdk'); + this.boxSdk.css('border-left', 'none'); + + Common.NotificationCenter.on('app:face', this.onAppShowed.bind(this)); + Common.NotificationCenter.on('app:ready', this.onAppReady.bind(this)); + Common.NotificationCenter.on('search:show', _.bind(this.onSearchShow, this)); + }, + + onAppShowed: function (config) { + var me = this; + me.appConfig = config; + + var _intvars = Common.Utils.InternalSettings; + var $filemenu = $('.toolbar-fullview-panel'); + $filemenu.css('top', Common.UI.LayoutManager.isElementVisible('toolbar') ? _intvars.get('toolbar-height-tabs') : 0); + + if ( !config.isEdit || + ( !Common.localStorage.itemExists("ve-compact-toolbar") && + config.customization && config.customization.compactToolbar )) + { + me.viewport.vlayout.getItem('toolbar').height = _intvars.get('toolbar-height-compact'); + } + + me.onTabStyleChange(); + me.onTabBackgroundChange(); + if ( config.customization && config.customization.toolbarHideFileName ) + me.viewport.vlayout.getItem('toolbar').el.addClass('style-skip-docname'); + + if ( config.twoLevelHeader && !config.compactHeader) { + var $title = me.viewport.vlayout.getItem('title').el; + $title.html(me.header.getPanel('title', config)).show(); + $title.find('.extra').html(me.header.getPanel('left', config)); + + var toolbar = me.viewport.vlayout.getItem('toolbar'); + toolbar.el.addClass('top-title'); + toolbar.height -= _intvars.get('toolbar-height-tabs') - _intvars.get('toolbar-height-tabs-top-title'); + + var _tabs_new_height = _intvars.get('toolbar-height-tabs-top-title'); + _intvars.set('toolbar-height-tabs', _tabs_new_height); + _intvars.set('toolbar-height-compact', _tabs_new_height); + _intvars.set('toolbar-height-normal', _tabs_new_height + _intvars.get('toolbar-height-controls')); + + $filemenu.css('top', (Common.UI.LayoutManager.isElementVisible('toolbar') ? _tabs_new_height : 0) + _intvars.get('document-title-height')); + + toolbar = me.getApplication().getController('Toolbar').getView('Toolbar'); + toolbar.btnCollabChanges = me.header.btnSave; + } + + me.header.btnSearch.on('toggle', me.onSearchToggle.bind(this)); + }, + + onAppReady: function (config) { + }, + + onLayoutChanged: function(area) { + switch (area) { + default: + this.viewport.vlayout.doLayout(); + case 'leftmenu': + var panel = this.viewport.hlayout.getItem('left'); + if (panel.resize.el) { + if (panel.el.width() > 40) { + this.boxSdk.css('border-left', ''); + panel.resize.el.show(); + } else { + panel.resize.el.hide(); + this.boxSdk.css('border-left', '0 none'); + } + } + this.viewport.hlayout.doLayout(); + break; + case 'header': + case 'toolbar': + case 'status': + this.viewport.vlayout.doLayout(); + break; + } + this.api.Resize(); + }, + + onWindowResize: function(e) { + this.onLayoutChanged('window'); + Common.NotificationCenter.trigger('window:resize'); + }, + + onFileMenu: function (opts) { + var me = this; + var _need_disable = opts == 'show'; + + me.header.lockHeaderBtns( 'users', _need_disable ); + }, + + applySettings: function () { + // var value = Common.localStorage.getBool("ve-settings-quick-print-button", true); + // Common.Utils.InternalSettings.set("ve-settings-quick-print-button", value); + // if (this.header && this.header.btnPrintQuick) + // this.header.btnPrintQuick[value ? 'show' : 'hide'](); + }, + + onApiCoAuthoringDisconnect: function(enableDownload) { + if (this.header) { + if (this.header.btnDownload && !enableDownload) + this.header.btnDownload.hide(); + if (this.header.btnPrint && !enableDownload) + this.header.btnPrint.hide(); + if (this.header.btnPrintQuick && !enableDownload) + this.header.btnPrintQuick.hide(); + if (this.header.btnEdit) + this.header.btnEdit.hide(); + this.header.lockHeaderBtns( 'rename-user', true); + } + }, + + SetDisabled: function(disable) { + this.header && this.header.lockHeaderBtns( 'rename-user', disable); + }, + + onSearchShow: function () { + this.header.btnSearch && this.header.btnSearch.toggle(true); + }, + + onSearchToggle: function () { + var leftMenu = this.getApplication().getController('LeftMenu'); + if (leftMenu.isSearchPanelVisible()) { + this.header.btnSearch.toggle(false, true); + leftMenu.getView('LeftMenu').panelSearch.focus(); + return; + } + if (!this.searchBar) { + var hideLeftPanel = this.mode.canBrandingExt && + (!Common.UI.LayoutManager.isElementVisible('leftMenu') || this.mode.customization && this.mode.customization.leftMenu === false); + this.searchBar = new Common.UI.SearchBar( hideLeftPanel ? { + showOpenPanel: false, + width: 303 + } : {}); + this.searchBar.on('hide', _.bind(function () { + this.header.btnSearch.toggle(false, true); + Common.NotificationCenter.trigger('edit:complete'); + }, this)); + } + if (this.header.btnSearch.pressed) { + var selectedText = this.api.asc_GetSelectedText(), + searchController = this.getApplication().getController('Search'), + resultsNumber = searchController.getResultsNumber(); + this.searchBar.show(selectedText && selectedText.trim() || searchController.getSearchText()); + this.searchBar.updateResultsNumber(resultsNumber[0], resultsNumber[1]); + } else { + this.searchBar.hide(); + } + }, + + isSearchBarVisible: function () { + return this.searchBar && this.searchBar.isVisible(); + }, + + applyCommonMode: function() { + if ( Common.localStorage.getBool('ve-hidden-status') ) + this.getApplication().getController('Statusbar').getView('Statusbar').setVisible(false); + + var value = Common.UI.LayoutManager.getInitValue('leftMenu'); + value = (value!==undefined) ? !value : false; + Common.localStorage.getBool("ve-hidden-leftmenu", value) && this.getApplication().getController('LeftMenu').getView('LeftMenu').hide(); + }, + + applyEditorMode: function() { + if (!this.viewport) return; + + if (this.mode.isEdit && this._initEditing) { + this._initEditing = false; + } + }, + + onTabStyleChange: function (style) { + style = style || Common.Utils.InternalSettings.get("settings-tab-style"); + this.viewport.vlayout.getItem('toolbar').el.toggleClass('lined-tabs', style==='line'); + }, + + onTabBackgroundChange: function (background) { + background = background || Common.Utils.InternalSettings.get("settings-tab-background"); + this.viewport.vlayout.getItem('toolbar').el.toggleClass('style-off-tabs', background==='toolbar'); + }, + + textFitPage: 'Fit to Page', + textFitWidth: 'Fit to Width' + }, VE.Controllers.Viewport)); +}); diff --git a/apps/visioeditor/main/app/template/FileMenu.template b/apps/visioeditor/main/app/template/FileMenu.template new file mode 100644 index 0000000000..0d9ed859c9 --- /dev/null +++ b/apps/visioeditor/main/app/template/FileMenu.template @@ -0,0 +1,31 @@ + +
+
+
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/apps/visioeditor/main/app/template/LeftMenu.template b/apps/visioeditor/main/app/template/LeftMenu.template new file mode 100644 index 0000000000..3090baaa76 --- /dev/null +++ b/apps/visioeditor/main/app/template/LeftMenu.template @@ -0,0 +1,18 @@ +
+ +
+ + + +
+
\ No newline at end of file diff --git a/apps/visioeditor/main/app/template/StatusBar.template b/apps/visioeditor/main/app/template/StatusBar.template new file mode 100644 index 0000000000..2bcf6f5624 --- /dev/null +++ b/apps/visioeditor/main/app/template/StatusBar.template @@ -0,0 +1,21 @@ + +
+
+
+
+
+ +
+
+
+ + + +
+ +
+ +
+
diff --git a/apps/visioeditor/main/app/template/Toolbar.template b/apps/visioeditor/main/app/template/Toolbar.template new file mode 100644 index 0000000000..239c19563e --- /dev/null +++ b/apps/visioeditor/main/app/template/Toolbar.template @@ -0,0 +1,15 @@ +
+
+
+ <%= tabsmarkup %> +
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/apps/visioeditor/main/app/template/ToolbarView.template b/apps/visioeditor/main/app/template/ToolbarView.template new file mode 100644 index 0000000000..ff388fce36 --- /dev/null +++ b/apps/visioeditor/main/app/template/ToolbarView.template @@ -0,0 +1,12 @@ +
+
+
+ <%= tabsmarkup %> +
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/apps/visioeditor/main/app/template/Viewport.template b/apps/visioeditor/main/app/template/Viewport.template new file mode 100644 index 0000000000..1fa182a4b1 --- /dev/null +++ b/apps/visioeditor/main/app/template/Viewport.template @@ -0,0 +1,17 @@ +
+
+ +
+
+
+ +
+
+
+ +
+
+
+
+
+
\ No newline at end of file diff --git a/apps/visioeditor/main/app/view/DocumentHolder.js b/apps/visioeditor/main/app/view/DocumentHolder.js new file mode 100644 index 0000000000..f0b5e4f4b5 --- /dev/null +++ b/apps/visioeditor/main/app/view/DocumentHolder.js @@ -0,0 +1,106 @@ +/* + * (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 + * + */ +/** + * DocumentHolder.js + * + * DocumentHolder view + * + * Created on 11/07/24 + * + */ + +define([ + 'jquery', + 'underscore', + 'backbone', + 'gateway', + 'common/main/lib/util/utils', + 'common/main/lib/component/Menu' +], function ($, _, Backbone, gateway) { 'use strict'; + + VE.Views.DocumentHolder = Backbone.View.extend(_.extend({ + el: '#editor_sdk', + + // Compile our stats template + template: null, + + // Delegated events for creating new items, and clearing completed ones. + events: { + }, + + initialize: function () { + this._isDisabled = false; + this._preventCustomClick = null; + this._hasCustomItems = false; + this._pagesCount = 0; + }, + + render: function () { + this.fireEvent('render:before', this); + + this.cmpEl = $(this.el); + + this.fireEvent('render:after', this); + return this; + }, + + setApi: function(o) { + this.api = o; + return this; + }, + + setMode: function(m) { + this.mode = m; + return this; + }, + + createDelayedElementsViewer: function() {}, + + createDelayedElementsEditor: function() {}, + + focus: function() { + var me = this; + _.defer(function(){ me.cmpEl.focus(); }, 50); + }, + + SetDisabled: function(state, canProtect, fillFormMode) { + this._isDisabled = state; + }, + + updateCustomItems: function() {}, + + clearCustomItems: function() {}, + + parseIcons: function() {} + + }, VE.Views.DocumentHolder || {})); +}); \ No newline at end of file diff --git a/apps/visioeditor/main/app/view/DocumentHolderExt.js b/apps/visioeditor/main/app/view/DocumentHolderExt.js new file mode 100644 index 0000000000..b175128bc9 --- /dev/null +++ b/apps/visioeditor/main/app/view/DocumentHolderExt.js @@ -0,0 +1,105 @@ +/* + * (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 + * + */ + +define([], function () { + 'use strict'; + + if (window.VE && window.VE.Views && window.VE.Views.DocumentHolder) { + let dh = window.VE.Views.DocumentHolder.prototype; + + dh.createDelayedElementsViewer = function() { + var me = this; + + if (me.menuViewCopy) return; // menu is already inited + + me.menuViewCopy = new Common.UI.MenuItem({ + iconCls: 'menu__icon btn-copy', + caption: me.textCopy, + value: 'copy' + }); + + this.viewModeMenu = new Common.UI.Menu({ + cls: 'shifted-right', + initMenu: function (value) { + me.menuViewCopy.setDisabled(!(me.api && me.api.can_CopyCut())); + }, + items: [ + me.menuViewCopy + ] + }).on('hide:after', function (menu, e, isFromInputControl) { + me.clearCustomItems(menu); + me.currentMenu = null; + if (me.suppressEditComplete) { + me.suppressEditComplete = false; + return; + } + + if (!isFromInputControl) me.fireEvent('editcomplete', me); + }); + + this.fireEvent('createdelayedelements', [this, 'view']); + }; + + dh.createDelayedElementsEditor = function() { + var me = this; + + if (me.menuEditCopy) return; // menu is already inited + + me.menuEditCopy = new Common.UI.MenuItem({ + iconCls: 'menu__icon btn-copy', + caption: me.textCopy, + value: 'copy' + }); + + this.editModeMenu = new Common.UI.Menu({ + cls: 'shifted-right', + initMenu: function (value) { + me.menuEditCopy.setDisabled(!(me.api && me.api.can_CopyCut())); + }, + items: [ + me.menuEditCopy + ] + }).on('hide:after', function (menu, e, isFromInputControl) { + me.clearCustomItems(menu); + me.currentMenu = null; + if (me.suppressEditComplete) { + me.suppressEditComplete = false; + return; + } + + if (!isFromInputControl) me.fireEvent('editcomplete', me); + }); + + this.fireEvent('createdelayedelements', [this, 'edit']); + }; + } +}); \ No newline at end of file diff --git a/apps/visioeditor/main/app/view/FileMenu.js b/apps/visioeditor/main/app/view/FileMenu.js new file mode 100644 index 0000000000..f2674334a4 --- /dev/null +++ b/apps/visioeditor/main/app/view/FileMenu.js @@ -0,0 +1,621 @@ +/* + * (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 + * + */ +/** + * FileMenu.js + * + * Describes menu 'File' for the left tool menu + * + * Created on 11/07/24 + * + */ + +define([ + 'text!visioeditor/main/app/template/FileMenu.template', + 'underscore', + 'common/main/lib/component/BaseView', + 'common/main/lib/view/RecentFiles' +], function (tpl, _) { + 'use strict'; + + VE.Views.FileMenu = Common.UI.BaseView.extend(_.extend({ + el: '#file-menu-panel', + rendered: false, + options: {alias:'FileMenu'}, + + template: _.template(tpl), + + events: function() { + return { + 'click .fm-btn': _.bind(function(event){ + this.mode && this.mode.isEdit && Common.UI.TooltipManager.closeTip('customInfo'); + var $item = $(event.currentTarget); + if ($item.hasClass('disabled')) { + return; + } else + if (!$item.hasClass('active')) { + $('.fm-btn',this.el).removeClass('active'); + $item.addClass('active'); + } + + var item = _.findWhere(this.items, {el: event.currentTarget}); + if (item) { + var panel = this.panels[item.options.action]; + if (item.options.action === 'help') { + if ( panel.noHelpContents === true && navigator.onLine ) { + this.fireEvent('item:click', [this, 'external-help', true]); + const helpCenter = Common.Utils.InternalSettings.get('url-help-center'); + !!helpCenter && window.open(helpCenter, '_blank'); + return; + } + } + this.fireEvent('item:click', [this, item.options.action, !!panel]); + + if (panel) { + this.$el.find('.content-box:visible').hide(); + this.active = item.options.action; + panel.show(); + } + } + }, this) + }; + }, + + initialize: function () { + }, + + render: function () { + var $markup = $(this.template({scope: this})); + + this.miClose = new Common.UI.MenuItem({ + el : $markup.elementById('#fm-btn-return'), + action : 'back', + caption : this.btnCloseMenuCaption, + canFocused: false, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [-2, 22], + iconCls: 'menu__icon btn-previtem' + }); + + this.miSave = new Common.UI.MenuItem({ + el : $markup.elementById('#fm-btn-save'), + action : 'save', + caption : this.btnSaveCaption, + canFocused: false, + disabled: true, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [-2, 22], + dataHintTitle: 'S', + iconCls: 'menu__icon btn-save' + }); + if ( !!this.options.miSave ) { + this.miSave.setDisabled(this.options.miSave.isDisabled()); + delete this.options.miSave; + } + + this.miEdit = new Common.UI.MenuItem({ + el : $markup.elementById('#fm-btn-edit'), + action : 'edit', + caption : this.btnToEditCaption, + canFocused: false, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [-2, 22], + iconCls: 'menu__icon btn-edit' + }); + + this.miDownload = new Common.UI.MenuItem({ + el : $markup.elementById('#fm-btn-download'), + action : 'saveas', + caption : this.btnDownloadCaption, + canFocused: false, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [-2, 22], + iconCls: 'menu__icon btn-download' + }); + + this.miSaveCopyAs = new Common.UI.MenuItem({ + el : $markup.elementById('#fm-btn-save-copy'), + action : 'save-copy', + caption : this.btnSaveCopyAsCaption, + canFocused: false, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [-2, 22], + iconCls: 'menu__icon btn-save-copy' + }); + + this.miSaveAs = new Common.UI.MenuItem({ + el : $markup.elementById('#fm-btn-save-desktop'), + action : 'save-desktop', + caption : this.btnSaveAsCaption, + canFocused: false, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [2, 14] + }); + + this.miPrint = new Common.UI.MenuItem({ + el : $markup.elementById('#fm-btn-print'), + action : 'print', + caption : this.btnPrintCaption, + canFocused: false, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [-2, 22], + dataHintTitle: 'P', + iconCls: 'menu__icon btn-print' + }); + + this.miRename = new Common.UI.MenuItem({ + el : $markup.elementById('#fm-btn-rename'), + action : 'rename', + caption : this.btnRenameCaption, + canFocused: false, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [-2, 22], + iconCls: 'menu__icon btn-rename' + }); + if ( !!this.options.miRename ) { + this.miRename.setDisabled(this.options.miRename.isDisabled()); + delete this.options.miRename; + } + + this.miRecent = new Common.UI.MenuItem({ + el : $markup.elementById('#fm-btn-recent'), + action : 'recent', + caption : this.btnRecentFilesCaption, + canFocused: false, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [2, 14] + }); + + this.miNew = new Common.UI.MenuItem({ + el : $markup.elementById('#fm-btn-create'), + action : 'new', + caption : this.btnCreateNewCaption, + canFocused: false, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [-2, 22], + iconCls: 'menu__icon btn-create-new' + }); + + this.miInfo = new Common.UI.MenuItem({ + el : $markup.elementById('#fm-btn-info'), + action : 'info', + caption : this.btnInfoCaption, + canFocused: false, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [-2, 22], + iconCls: 'menu__icon btn-menu-about' + }); + + this.miAccess = new Common.UI.MenuItem({ + el : $markup.elementById('#fm-btn-rights'), + action : 'rights', + caption : this.btnRightsCaption, + canFocused: false, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [-2, 22], + iconCls: 'menu__icon btn-users-share' + }); + + this.miHelp = new Common.UI.MenuItem({ + el : $markup.elementById('#fm-btn-help'), + action : 'help', + caption : this.btnHelpCaption, + canFocused: false, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [-2, 22], + iconCls: 'menu__icon btn-help' + }); + + this.miSettings = new Common.UI.MenuItem({ + el : $markup.elementById('#fm-btn-settings'), + action : 'opts', + caption : this.btnSettingsCaption, + canFocused: false, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [-2, 22], + iconCls: 'menu__icon btn-settings' + }); + + this.miBack = new Common.UI.MenuItem({ + el : $markup.elementById('#fm-btn-back'), + action : 'exit', + caption : this.btnBackCaption, + canFocused: false, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [-2, 22], + iconCls: 'menu__icon btn-goback' + }); + + this.items = []; + this.items.push( + this.miClose, + this.miSave, + this.miEdit, + this.miDownload, + this.miSaveCopyAs, + this.miSaveAs, + this.miPrint, + this.miRename, + this.miRecent, + this.miNew, + this.miInfo, + this.miAccess, + this.miSettings, + this.miHelp, + this.miBack + ); + + this.rendered = true; + this.$el.html($markup); + this.$el.find('.content-box').hide(); + if (_.isUndefined(this.scroller)) { + var me = this; + this.scroller = new Common.UI.Scroller({ + el: this.$el.find('.panel-menu'), + suppressScrollX: true, + alwaysVisibleY: true + }); + Common.NotificationCenter.on('window:resize', function() { + me.scroller.update(); + }); + } + this.applyMode(); + + if ( Common.Controllers.Desktop.isActive() ) { + Common.NotificationCenter.trigger('update:recents', Common.Controllers.Desktop.recentFiles()); + } + + if ( !!this.api ) { + this.panels['info'].setApi(this.api); + if (this.panels['opts']) this.panels['opts'].setApi(this.api); + } + + this.fireEvent('render:after', [this]); + return this; + }, + + show: function(panel, opts) { + if (this.isVisible() && panel===undefined || !this.mode || !Common.Controllers.LaunchController.isScriptLoaded()) return; + + if ( !this.rendered ) + this.render(); + + var defPanel = (this.mode.canDownload && (!this.mode.isDesktopApp || !this.mode.isOffline)) ? 'saveas' : 'info'; + if (!panel) + panel = this.active || defPanel; + this.$el.show(); + this.scroller.update(); + this.selectMenu(panel, opts, defPanel); + + this.api && this.api.asc_enableKeyEvents(false); + + this.mode.isEdit && Common.UI.TooltipManager.showTip('customInfo'); + this.fireEvent('menu:show', [this]); + }, + + hide: function() { + this.mode && this.mode.isEdit && Common.UI.TooltipManager.closeTip('customInfo'); + this.$el.hide(); + this.fireEvent('menu:hide', [this]); + // this.api && this.api.asc_enableKeyEvents(true); + }, + + applyMode: function() { + if (!this.rendered) return; + + if (!this.panels) { + this.panels = { + 'opts' : (new VE.Views.FileMenuPanels.Settings({menu:this})).render(this.$el.find('#panel-settings')), + 'info' : (new VE.Views.FileMenuPanels.DocumentInfo({menu:this})).render(this.$el.find('#panel-info')), + 'rights' : (new VE.Views.FileMenuPanels.DocumentRights({menu:this})).render(this.$el.find('#panel-rights')) + }; + } + + if (!this.mode) return; + + var lastSeparator, + separatorVisible = false; + + var isVisible = Common.UI.LayoutManager.isElementVisible('toolbar-file-close'); + this.miClose[isVisible?'show':'hide'](); + this.miClose.$el.find('+.devider')[isVisible?'show':'hide'](); + isVisible && (lastSeparator = this.miClose.$el.find('+.devider')); + + this.miDownload[(this.mode.canDownload && (!this.mode.isDesktopApp || !this.mode.isOffline))?'show':'hide'](); + var isBCSupport = Common.Controllers.Desktop.isActive() ? Common.Controllers.Desktop.call("isBlockchainSupport") : false; + this.miSaveCopyAs[(this.mode.canDownload && (!this.mode.isDesktopApp || !this.mode.isOffline)) && (this.mode.canRequestSaveAs || this.mode.saveAsUrl) && !isBCSupport ?'show':'hide'](); + this.miSaveAs[(this.mode.canDownload && this.mode.isDesktopApp && this.mode.isOffline)?'show':'hide'](); + this.miSave[this.mode.showSaveButton && Common.UI.LayoutManager.isElementVisible('toolbar-file-save') ?'show':'hide'](); + this.miEdit[!this.mode.isEdit && this.mode.canEdit && this.mode.canRequestEditRights ?'show':'hide'](); + this.miPrint[this.mode.canPrint && !this.mode.canPreviewPrint ?'show':'hide'](); + this.miRename[(this.mode.canRename && !this.mode.isDesktopApp) ?'show':'hide'](); + separatorVisible = (this.mode.canDownload || this.mode.isEdit && Common.UI.LayoutManager.isElementVisible('toolbar-file-save') || this.mode.canPrint || + !this.mode.isEdit && this.mode.canEdit && this.mode.canRequestEditRights || this.mode.canRename && !this.mode.isDesktopApp) && !this.mode.isDisconnected; + separatorVisible && (lastSeparator = this.miRename.$el.find('+.devider')); + + this.miRecent[this.mode.canOpenRecent?'show':'hide'](); + this.miNew[this.mode.canCreateNew?'show':'hide'](); + if (!this.mode.canOpenRecent && !this.mode.canCreateNew) { + this.miRecent.$el.find('+.devider').hide(); + } + + isVisible = Common.UI.LayoutManager.isElementVisible('toolbar-file-info'); + separatorVisible = isVisible; + this.miInfo[isVisible?'show':'hide'](); + isVisible = !this.mode.isOffline && this.document&&this.document.info && + (this.document.info.sharingSettings&&this.document.info.sharingSettings.length>0 || + (this.mode.sharingSettingsUrl&&this.mode.sharingSettingsUrl.length || this.mode.canRequestSharingSettings)); + separatorVisible = separatorVisible || isVisible; + this.miAccess[isVisible?'show':'hide'](); + separatorVisible && (lastSeparator = this.miAccess.$el.find('+.devider')); + + isVisible = Common.UI.LayoutManager.isElementVisible('toolbar-file-settings'); + this.miSettings[isVisible?'show':'hide'](); + this.miSettings.$el.find('+.devider')[isVisible?'show':'hide'](); + isVisible && (lastSeparator = this.miSettings.$el.find('+.devider')); + + isVisible = this.mode.canHelp; + this.miHelp[isVisible ?'show':'hide'](); + this.miHelp.$el.find('+.devider')[isVisible?'show':'hide'](); + isVisible && (lastSeparator = this.miHelp.$el.find('+.devider')); + + isVisible = this.mode.canBack; + this.miBack[isVisible ?'show':'hide'](); + lastSeparator && !isVisible && lastSeparator.hide(); + + if (!this.customizationDone) { + this.customizationDone = true; + this.mode.canBack && this.mode.customization.goback.text && typeof this.mode.customization.goback.text === 'string' && this.miBack.setCaption(this.mode.customization.goback.text); + } + + this.panels['opts'].setMode(this.mode); + this.panels['info'].setMode(this.mode); + !this.mode.isDisconnected && this.panels['info'].updateInfo(this.document); + this.panels['rights'].setMode(this.mode); + !this.mode.isDisconnected && this.panels['rights'].updateInfo(this.document); + + if ( this.mode.canCreateNew ) { + if (this.mode.templates && this.mode.templates.length) { + !this.panels['new'] && (this.panels['new'] = (new VE.Views.FileMenuPanels.CreateNew({menu: this, docs: this.mode.templates, blank: this.mode.canRequestCreateNew || !!this.mode.createUrl})).render()); + } + } + + if ( this.mode.canOpenRecent && this.mode.recent ) { + !this.panels['recent'] && (this.panels['recent'] = (new Common.Views.RecentFiles({ el: '#panel-recentfiles', menu:this, recent: this.mode.recent})).render()); + } + + if (this.mode.canDownload) { + !this.panels['saveas'] && (this.panels['saveas'] = ((new VE.Views.FileMenuPanels.ViewSaveAs({menu: this, fileType: this.document.fileType})).render())); + } + + if (this.mode.canDownload && (this.mode.canRequestSaveAs || this.mode.saveAsUrl)) { + !this.panels['save-copy'] && (this.panels['save-copy'] = ((new VE.Views.FileMenuPanels.ViewSaveCopy({menu: this, fileType: this.document.fileType})).render())); + } + + if (this.mode.canHelp && !this.panels['help']) { + this.panels['help'] = ((new VE.Views.FileMenuPanels.Help({menu: this})).render()); + this.panels['help'].setLangConfig(this.mode.lang); + } + + if ( Common.Controllers.Desktop.isActive() ) { + if (this.$el.find('#fm-btn-local-open').length<1) { + $('
  • ').insertBefore($('#fm-btn-recent', this.$el)); + this.items.push( + new Common.UI.MenuItem({ + el: $('#fm-btn-local-open', this.$el), + action: 'file:open', + caption: this.btnFileOpenCaption, + canFocused: false, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [-2, 22], + iconCls: 'menu__icon btn-open' + })); + } + + if (this.$el.find('#fm-btn-exit').length<1) { + $('
  • ' + + '
  • ').insertAfter($('#fm-btn-back', this.$el)); + this.items.push( + new Common.UI.MenuItem({ + el: $('#fm-btn-exit', this.$el), + action: 'file:exit', + caption: this.btnExitCaption, + canFocused: false, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [-2, 22], + iconCls: 'menu__icon btn-close' + })); + } + } else if (this.mode.canCloseEditor && this.$el.find('#fm-btn-close').length<1) { + $('
  • ' + + '
  • ').insertAfter($('#fm-btn-back', this.$el)); + this.items.push( + new Common.UI.MenuItem({ + el : $('#fm-btn-close', this.$el), + action : 'close-editor', + caption : this.mode.customization.close.text || this.btnCloseEditor, + canFocused: false, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [-2, 22], + iconCls: 'menu__icon btn-close' + })); + } + }, + + setMode: function(mode, delay) { + if (mode.isDisconnected) { + this.mode.canEdit = this.mode.isEdit = false; + this.mode.canOpenRecent = this.mode.canCreateNew = false; + this.mode.isDisconnected = mode.isDisconnected; + this.mode.canRename = false; + if (!mode.enableDownload) + this.mode.canPrint = this.mode.canDownload = false; + } else { + this.mode = mode; + } + + if (!delay) { + this.applyMode(); + } + }, + + setApi: function(api) { + this.api = api; + + if ( this.rendered ) { + this.panels['info'].setApi(api); + if (this.panels['opts']) this.panels['opts'].setApi(api); + } + this.api.asc_registerCallback('asc_onDocumentName', _.bind(this.onDocumentName, this)); + return this; + }, + + loadDocument: function(data) { + this.document = data.doc; + }, + + selectMenu: function(menu, opts, defMenu) { + if ( menu ) { + var item = this._getMenuItem(menu), + panel = this.panels[menu]; + if ( item.isDisabled() || !item.isVisible()) { + item = this._getMenuItem(defMenu); + panel = this.panels[defMenu]; + } + if ( item && panel ) { + $('.fm-btn',this.el).removeClass('active'); + item.$el.addClass('active'); + + this.$el.find('.content-box:visible').hide(); + panel.show(opts); + + if (this.scroller) { + var itemTop = Common.Utils.getPosition(item.$el).top, + itemHeight = item.$el.outerHeight(), + listHeight = this.$el.outerHeight(); + if (itemTop < 0 || itemTop + itemHeight > listHeight) { + var height = this.scroller.$el.scrollTop() + itemTop + (itemHeight - listHeight)/2; + height = (Math.floor(height/itemHeight) * itemHeight); + this.scroller.scrollTop(height); + } + } + + this.active = menu; + } + } + }, + + disableMenu: function(menu, status) { + if ( menu ) { + var item = this._getMenuItem(menu); + if ( item ) { + item.setDisabled(status); + } + } + }, + + _getMenuItem: function(action) { + return _.find(this.items, function(item) { + return item.options.action == action; + }); + }, + + onDocumentName: function(name) { + this.document.title = name; + if (this.rendered) + this.panels['info'].updateInfo(this.document); + }, + + isVisible: function () { + return !this.$el.is(':hidden'); + }, + + getButton: function(type) { + if ( !this.rendered ) { + if (type == 'save') { + return this.options.miSave ? this.options.miSave : (this.options.miSave = new Common.UI.MenuItem({})); + } else + if (type == 'rename') { + return this.options.miRename ? this.options.miRename : (this.options.miRename = new Common.UI.MenuItem({})); + } + } else { + if (type == 'save') { + return this.miSave; + } else + if (type == 'rename') { + return this.miRename; + } + } + }, + + SetDisabled: function(disable, options) { + }, + + btnSaveCaption : 'Save', + btnDownloadCaption : 'Download as...', + btnInfoCaption : 'Document Info...', + btnRightsCaption : 'Access Rights...', + btnCreateNewCaption : 'Create New', + btnRecentFilesCaption : 'Open Recent...', + btnPrintCaption : 'Print', + btnHelpCaption : 'Help...', + btnReturnCaption : 'Back to Document', + btnToEditCaption : 'Edit Document', + btnBackCaption : 'Go to Documents', + btnSettingsCaption : 'Advanced Settings...', + btnSaveAsCaption : 'Save as', + btnRenameCaption : 'Rename...', + btnCloseMenuCaption : 'Back', + btnSaveCopyAsCaption : 'Save Copy as...', + btnExitCaption : 'Exit', + btnFileOpenCaption : 'Open...', + btnCloseEditor : 'Close File', + ariaFileMenu : 'File menu' + }, VE.Views.FileMenu || {})); +}); diff --git a/apps/visioeditor/main/app/view/FileMenuPanels.js b/apps/visioeditor/main/app/view/FileMenuPanels.js new file mode 100644 index 0000000000..4375e54125 --- /dev/null +++ b/apps/visioeditor/main/app/view/FileMenuPanels.js @@ -0,0 +1,1591 @@ +/* + * (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 + * + */ +/** + * FileMenuPanels.js + * + * Contains views for menu 'File' + * + * Created on 11/07/24 + * + */ + +define([], function () { + 'use strict'; + + !VE.Views.FileMenuPanels && (VE.Views.FileMenuPanels = {}); + + VE.Views.FileMenuPanels.ViewSaveAs = Common.UI.BaseView.extend({ + el: '#panel-saveas', + menu: undefined, + + formats: [[ + {name: 'VSDX', imgCls: 'vsdx', type: Asc.c_oAscFileType.VSDX}, + {name: 'PDF', imgCls: 'pdf', type: Asc.c_oAscFileType.PDF}, + {name: 'PDFA', imgCls: 'pdfa', type: Asc.c_oAscFileType.PDFA} + ]], + + + template: _.template([ + '
    ', + '
    <%= header %>
    ', + '
    ', + '<% _.each(rows, function(row) { %>', + '<% _.each(row, function(item) { %>', + '
    ', + '
    ', + '
    ', + '<% }) %>', + '
    ', + '<% }) %>', + '
    ', + '
    ' + ].join('')), + + initialize: function(options) { + Common.UI.BaseView.prototype.initialize.call(this,arguments); + + this.menu = options.menu; + this.fileType = options.fileType; + + Common.NotificationCenter.on({ + 'window:resize': _.bind(function() { + var divided = Common.Utils.innerWidth() >= this.maxWidth; + if (this.isDivided !== divided) { + this.$el.find('.divider').css('width', divided ? '100%' : '0'); + this.isDivided = divided; + } + }, this) + }); + }, + + render: function() { + this.$el.html(this.template({rows:this.formats, + fileType: (this.fileType || 'pptx').toLowerCase(), + header: /*this.textDownloadAs*/ Common.Locale.get('btnDownloadCaption', {name:'VE.Views.FileMenu', default:this.textDownloadAs})})); + $('.btn-doc-format',this.el).on('click', _.bind(this.onFormatClick,this)); + + if (_.isUndefined(this.scroller)) { + this.scroller = new Common.UI.Scroller({ + el: this.$el, + suppressScrollX: true, + alwaysVisibleY: true + }); + } + + var itemWidth = 70 + 24, // width + margin + maxCount = 0; + this.formats.forEach(_.bind(function (item, index) { + var count = item.length; + if (count > maxCount) { + maxCount = count; + } + }, this)); + this.maxWidth = $('#file-menu-panel .panel-menu').outerWidth() + 20 + 10 + itemWidth * maxCount; // menu + left padding + margin + + if (Common.Utils.innerWidth() >= this.maxWidth) { + this.$el.find('.divider').css('width', '100%'); + this.isDivided = true; + } + + return this; + }, + + show: function() { + Common.UI.BaseView.prototype.show.call(this,arguments); + this.scroller && this.scroller.update(); + }, + + onFormatClick: function(e) { + var type = e.currentTarget.attributes['format']; + if (!_.isUndefined(type) && this.menu) { + this.menu.fireEvent('saveas:format', [this.menu, parseInt(type.value)]); + } + }, + + textDownloadAs: "Download as" + }); + + VE.Views.FileMenuPanels.ViewSaveCopy = Common.UI.BaseView.extend({ + el: '#panel-savecopy', + menu: undefined, + + formats: [[ + {name: 'VSDX', imgCls: 'vsdx', type: Asc.c_oAscFileType.VSDX, ext: '.vsdx'}, + {name: 'PDF', imgCls: 'pdf', type: Asc.c_oAscFileType.PDF, ext: '.pdf'}, + {name: 'PDFA', imgCls: 'pdfa', type: Asc.c_oAscFileType.PDFA, ext: '.pdf'} + ]], + + template: _.template([ + '
    ', + '
    <%= header %>
    ', + '
    ', + '<% _.each(rows, function(row) { %>', + '<% _.each(row, function(item) { %>', + '
    ', + '
    ', + '
    ', + '<% }) %>', + '
    ', + '<% }) %>', + '
    ', + '
    ' + ].join('')), + + initialize: function(options) { + Common.UI.BaseView.prototype.initialize.call(this,arguments); + + this.menu = options.menu; + this.fileType = options.fileType; + + Common.NotificationCenter.on({ + 'window:resize': _.bind(function() { + var divided = Common.Utils.innerWidth() >= this.maxWidth; + if (this.isDivided !== divided) { + this.$el.find('.divider').css('width', divided ? '100%' : '0'); + this.isDivided = divided; + } + }, this) + }); + }, + + render: function() { + this.$el.html(this.template({rows:this.formats, + fileType: (this.fileType || 'pptx').toLowerCase(), + header: /*this.textSaveCopyAs*/ Common.Locale.get('btnSaveCopyAsCaption', {name:'VE.Views.FileMenu', default:this.textSaveCopyAs})})); + $('.btn-doc-format',this.el).on('click', _.bind(this.onFormatClick,this)); + + if (_.isUndefined(this.scroller)) { + this.scroller = new Common.UI.Scroller({ + el: this.$el, + suppressScrollX: true, + alwaysVisibleY: true + }); + } + + var itemWidth = 70 + 24, // width + margin + maxCount = 0; + this.formats.forEach(_.bind(function (item, index) { + var count = item.length; + if (count > maxCount) { + maxCount = count; + } + }, this)); + this.maxWidth = $('#file-menu-panel .panel-menu').outerWidth() + 20 + 10 + itemWidth * maxCount; // menu + left padding + margin + + if (Common.Utils.innerWidth() >= this.maxWidth) { + this.$el.find('.divider').css('width', '100%'); + this.isDivided = true; + } + + return this; + }, + + show: function() { + Common.UI.BaseView.prototype.show.call(this,arguments); + this.scroller && this.scroller.update(); + }, + + onFormatClick: function(e) { + var type = e.currentTarget.attributes['format'], + ext = e.currentTarget.attributes['format-ext']; + if (!_.isUndefined(type) && !_.isUndefined(ext) && this.menu) { + this.menu.fireEvent('savecopy:format', [this.menu, parseInt(type.value), ext.value]); + } + }, + + textSaveCopyAs: "Save Copy as" + }); + + VE.Views.FileMenuPanels.Settings = Common.UI.BaseView.extend(_.extend({ + el: '#panel-settings', + menu: undefined, + + template: _.template([ + '
    ', + '
    <%= scope.txtAdvancedSettings %>
    ', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + // '', + // '', + // '', + // '', + '', + '', + '', + '', + '', + '
    ', + '
    ', + '' + ].join('')), + + initialize: function(options) { + Common.UI.BaseView.prototype.initialize.call(this,arguments); + + this.menu = options.menu; + }, + + render: function(node) { + var me = this; + var $markup = $(this.template({scope: this})); + + + this.chUseAltKey = new Common.UI.CheckBox({ + el: $markup.findById('#fms-chb-use-alt-key'), + labelText: Common.Utils.isMac ? this.txtUseOptionKey : this.txtUseAltKey, + dataHint: '2', + dataHintDirection: 'left', + dataHintOffset: 'small' + }); + (Common.Utils.isIE || Common.Utils.isMac && Common.Utils.isGecko) && this.chUseAltKey.$el.parent().parent().hide(); + + this.chScreenReader = new Common.UI.CheckBox({ + el: $markup.findById('#fms-chb-scrn-reader'), + labelText: this.txtScreenReader, + dataHint: '2', + dataHintDirection: 'left', + dataHintOffset: 'small' + }); + + this.cmbZoom = new Common.UI.ComboBox({ + el : $markup.findById('#fms-cmb-zoom'), + style : 'width: 160px;', + editable : false, + restoreMenuHeightAndTop: true, + cls : 'input-group-nr', + menuStyle : 'min-width:100%; max-height: 157px;', + data : [ + { value: -3, displayValue: this.txtLastUsed }, + { value: -1, displayValue: this.txtFitSlide }, + { value: -2, displayValue: this.txtFitWidth }, + { value: 50, displayValue: "50%" }, + { value: 60, displayValue: "60%" }, + { value: 70, displayValue: "70%" }, + { value: 80, displayValue: "80%" }, + { value: 90, displayValue: "90%" }, + { value: 100, displayValue: "100%" }, + { value: 110, displayValue: "110%" }, + { value: 120, displayValue: "120%" }, + { value: 150, displayValue: "150%" }, + { value: 175, displayValue: "175%" }, + { value: 200, displayValue: "200%" }, + { value: 300, displayValue: "300%" }, + { value: 400, displayValue: "400%" }, + { value: 500, displayValue: "500%" } + ], + dataHint: '2', + dataHintDirection: 'bottom', + dataHintOffset: 'big' + }); + + var itemsTemplate = + _.template([ + '<% _.each(items, function(item) { %>', + '
  • class="border-top" style="margin-top: 5px;padding-top: 5px;" <% } %> > class="checked" <% } %> ><%= scope.getDisplayValue(item) %>
  • ', + '<% }); %>' + ].join('')); + this.cmbFontRender = new Common.UI.ComboBox({ + el : $markup.findById('#fms-cmb-font-render'), + style : 'width: 160px;', + editable : false, + restoreMenuHeightAndTop: true, + menuStyle : 'min-width:100%;', + cls : 'input-group-nr', + itemsTemplate: itemsTemplate, + data : [ + { value: Asc.c_oAscFontRenderingModeType.hintingAndSubpixeling, displayValue: this.txtWin }, + { value: Asc.c_oAscFontRenderingModeType.noHinting, displayValue: this.txtMac }, + { value: Asc.c_oAscFontRenderingModeType.hinting, displayValue: this.txtNative }, + { value: 'custom', displayValue: this.txtCacheMode } + ], + dataHint: '2', + dataHintDirection: 'bottom', + dataHintOffset: 'big' + }); + this.cmbFontRender.on('selected', _.bind(this.onFontRenderSelected, this)); + + // this.cmbMacros = new Common.UI.ComboBox({ + // el : $markup.findById('#fms-cmb-macros'), + // style : 'width: 160px;', + // editable : false, + // restoreMenuHeightAndTop: true, + // menuStyle : 'min-width:100%;', + // cls : 'input-group-nr', + // data : [ + // { value: 2, displayValue: this.txtStopMacros, descValue: this.txtStopMacrosDesc }, + // { value: 0, displayValue: this.txtWarnMacros, descValue: this.txtWarnMacrosDesc }, + // { value: 1, displayValue: this.txtRunMacros, descValue: this.txtRunMacrosDesc } + // ], + // itemsTemplate: _.template([ + // '<% _.each(items, function(item) { %>', + // '
  • ', + // '
  • ', + // '<% }); %>' + // ].join('')), + // dataHint: '2', + // dataHintDirection: 'bottom', + // dataHintOffset: 'big' + // }).on('selected', function(combo, record) { + // me.lblMacrosDesc.text(record.descValue); + // }); + // this.lblMacrosDesc = $markup.findById('#fms-lbl-macros'); + + this.btnCustomizeQuickAccess = new Common.UI.Button({ + el: $markup.findById('#fms-btn-customize-quick-access') + }); + this.btnCustomizeQuickAccess.on('click', _.bind(this.customizeQuickAccess, this)); + + this.cmbTheme = new Common.UI.ComboBox({ + el : $markup.findById('#fms-cmb-theme'), + style : 'width: 160px;', + editable : false, + restoreMenuHeightAndTop: true, + menuStyle : 'min-width:100%;', + cls : 'input-group-nr', + dataHint : '2', + dataHintDirection: 'bottom', + dataHintOffset: 'big' + }); + + this.cmbTabStyle = new Common.UI.ComboBox({ + el : $markup.findById('#fms-cmb-tab-style'), + style : 'width: 160px;', + menuStyle : 'min-width:100%;', + editable : false, + restoreMenuHeightAndTop: true, + cls : 'input-group-nr', + data : [ + {value: 'fill', displayValue: this.textFill}, + {value: 'line', displayValue: this.textLine} + ], + dataHint: '2', + dataHintDirection: 'bottom', + dataHintOffset: 'big' + }); + + this.chTabBack = new Common.UI.CheckBox({ + el: $markup.findById('#fms-chb-tab-background'), + labelText: this.txtTabBack, + dataHint: '2', + dataHintDirection: 'left', + dataHintOffset: 'small' + }); + + $markup.find('.btn.primary').each(function(index, el){ + (new Common.UI.Button({ + el: $(el) + })).on('click', _.bind(me.applySettings, me)); + }); + + /*this.chQuickPrint = new Common.UI.CheckBox({ + el: $markup.findById('#fms-chb-quick-print'), + labelText: '', + dataHint: '2', + dataHintDirection: 'left', + dataHintOffset: 'small' + }); + this.chQuickPrint.$el.parent().on('click', function (){ + me.chQuickPrint.setValue(!me.chQuickPrint.isChecked()); + });*/ + + this.pnlSettings = $markup.find('.flex-settings').addBack().filter('.flex-settings'); + this.pnlApply = $markup.find('.fms-flex-apply').addBack().filter('.fms-flex-apply'); + this.pnlTable = this.pnlSettings.find('table'); + this.trApply = $markup.find('.fms-btn-apply'); + + this.$el = $(node).html($markup); + + if (_.isUndefined(this.scroller)) { + this.scroller = new Common.UI.Scroller({ + el: this.pnlSettings, + suppressScrollX: true, + alwaysVisibleY: true + }); + } + + Common.NotificationCenter.on({ + 'window:resize': function() { + me.isVisible() && me.updateScroller(); + } + }); + + return this; + }, + + show: function() { + Common.UI.BaseView.prototype.show.call(this,arguments); + + this.updateSettings(); + this.updateScroller(); + }, + + updateScroller: function() { + if (this.scroller) { + Common.UI.Menu.Manager.hideAll(); + var scrolled = this.$el.height() < this.pnlTable.parent().height() + 25 + this.pnlApply.height(); + this.pnlApply.toggleClass('hidden', !scrolled); + this.trApply.toggleClass('hidden', scrolled); + this.pnlSettings.css('overflow', scrolled ? 'hidden' : 'visible'); + this.scroller.update(); + this.pnlSettings.toggleClass('bordered', this.scroller.isVisible()); + this.cmbZoom.options.menuAlignEl = scrolled ? this.pnlSettings : null; + this.cmbFontRender.options.menuAlignEl = scrolled ? this.pnlSettings : null; + this.cmbTheme.options.menuAlignEl = scrolled ? this.pnlSettings : null; + // this.cmbMacros.options.menuAlignEl = scrolled ? this.pnlSettings : null; + this.cmbTabStyle.options.menuAlignEl = scrolled ? this.pnlSettings : null; + } + }, + + setMode: function(mode) { + this.mode = mode; + + var fast_coauth = Common.Utils.InternalSettings.get("ve-settings-coauthmode"); + $('tr.edit', this.el)[mode.isEdit?'show':'hide'](); + $('tr.macros', this.el)[(mode.customization && mode.customization.macros===false) ? 'hide' : 'show'](); + $('tr.quick-print', this.el)[mode.canQuickPrint && !(mode.compactHeader && mode.isEdit) ? 'show' : 'hide'](); + $('tr.tab-background', this.el)[!Common.Utils.isIE && Common.UI.FeaturesManager.canChange('tabBackground', true) ? 'show' : 'hide'](); + $('tr.tab-style', this.el)[Common.UI.FeaturesManager.canChange('tabStyle', true) ? 'show' : 'hide'](); + if ( !Common.UI.Themes.available() ) { + $('tr.themes, tr.themes + tr.divider', this.el).hide(); + } + if (mode.compactHeader) { + $('tr.quick-access', this.el).hide(); + } + }, + + setApi: function(o) { + this.api = o; + return this; + }, + + updateSettings: function() { + this.chUseAltKey.setValue(Common.Utils.InternalSettings.get("ve-settings-show-alt-hints")); + this.chScreenReader.setValue(Common.Utils.InternalSettings.get("app-settings-screen-reader")); + + var value = Common.Utils.InternalSettings.get("ve-settings-zoom"); + value = (value!==null) ? parseInt(value) : (this.mode.customization && this.mode.customization.zoom ? parseInt(this.mode.customization.zoom) : -1); + var item = this.cmbZoom.store.findWhere({value: value}); + this.cmbZoom.setValue(item ? parseInt(item.get('value')) : (value>0 ? value+'%' : 100)); + + value = Common.Utils.InternalSettings.get("ve-settings-fontrender"); + item = this.cmbFontRender.store.findWhere({value: parseInt(value)}); + this.cmbFontRender.setValue(item ? item.get('value') : Asc.c_oAscFontRenderingModeType.hintingAndSubpixeling); + this._fontRender = this.cmbFontRender.getValue(); + + value = Common.Utils.InternalSettings.get("ve-settings-cachemode"); + item = this.cmbFontRender.store.findWhere({value: 'custom'}); + item && value && item.set('checked', !!value); + item && value && this.cmbFontRender.cmpEl.find('#' + item.get('id') + ' a').addClass('checked'); + + // item = this.cmbMacros.store.findWhere({value: Common.Utils.InternalSettings.get("ve-macros-mode")}); + // this.cmbMacros.setValue(item ? item.get('value') : 0); + // this.lblMacrosDesc.text(item ? item.get('descValue') : this.txtWarnMacrosDesc); + + var data = []; + for (var t in Common.UI.Themes.map()) { + data.push({value: t, displayValue: Common.UI.Themes.get(t).text}); + } + + if ( data.length ) { + this.cmbTheme.setData(data); + item = this.cmbTheme.store.findWhere({value: Common.UI.Themes.currentThemeId()}); + this.cmbTheme.setValue(item ? item.get('value') : Common.UI.Themes.defaultThemeId()); + } + this.chTabBack.setValue(Common.Utils.InternalSettings.get("settings-tab-background")==='toolbar'); + value = Common.Utils.InternalSettings.get("settings-tab-style"); + item = this.cmbTabStyle.store.findWhere({value: value}); + this.cmbTabStyle.setValue(item ? item.get('value') : 'fill'); + }, + + applySettings: function() { + Common.UI.Themes.setTheme(this.cmbTheme.getValue()); + if (Common.UI.FeaturesManager.canChange('spellcheck') && this.mode.isEdit) { + Common.localStorage.setItem("ve-settings-spellcheck", this.chSpell.isChecked() ? 1 : 0); + Common.localStorage.setBool("ve-spellcheck-ignore-uppercase-words", this.chIgnoreUppercase.isChecked()); + Common.localStorage.setBool("ve-spellcheck-ignore-numbers-words", this.chIgnoreNumbers.isChecked()); + } + Common.localStorage.setItem("ve-settings-show-alt-hints", this.chUseAltKey.isChecked() ? 1 : 0); + Common.Utils.InternalSettings.set("ve-settings-show-alt-hints", Common.localStorage.getBool("ve-settings-show-alt-hints")); + + Common.localStorage.setItem("ve-settings-zoom", this.cmbZoom.getValue()); + + Common.localStorage.setItem("app-settings-screen-reader", this.chScreenReader.isChecked() ? 1 : 0); + /** coauthoring begin **/ + Common.localStorage.setItem("ve-settings-fontrender", this.cmbFontRender.getValue()); + var item = this.cmbFontRender.store.findWhere({value: 'custom'}); + Common.localStorage.setItem("ve-settings-cachemode", item && !item.get('checked') ? 0 : 1); + // Common.localStorage.setItem("ve-macros-mode", this.cmbMacros.getValue()); + // Common.Utils.InternalSettings.set("ve-macros-mode", this.cmbMacros.getValue()); + + if (!Common.Utils.isIE && Common.UI.FeaturesManager.canChange('tabBackground', true)) { + Common.UI.TabStyler.setBackground(this.chTabBack.isChecked() ? 'toolbar' : 'header'); + } + if (Common.UI.FeaturesManager.canChange('tabStyle', true)) { + Common.UI.TabStyler.setStyle(this.cmbTabStyle.getValue()); + } + Common.localStorage.save(); + + if (this.menu) { + this.menu.fireEvent('settings:apply', [this.menu]); + } + }, + + onFontRenderSelected: function(combo, record) { + if (record.value == 'custom') { + var item = combo.store.findWhere({value: 'custom'}); + item && item.set('checked', !record.checked); + combo.cmpEl.find('#' + record.id + ' a').toggleClass('checked', !record.checked); + combo.setValue(this._fontRender); + } + this._fontRender = combo.getValue(); + }, + + customizeQuickAccess: function () { + if (this.dlgQuickAccess && this.dlgQuickAccess.isVisible()) return; + this.dlgQuickAccess = new Common.Views.CustomizeQuickAccessDialog({ + showSave: this.mode.showSaveButton, + showPrint: this.mode.canPrint && this.mode.twoLevelHeader, + showQuickPrint: this.mode.canQuickPrint && this.mode.twoLevelHeader, + mode: this.mode, + props: { + save: Common.localStorage.getBool('ve-quick-access-save', true), + print: Common.localStorage.getBool('ve-quick-access-print', true), + quickPrint: Common.localStorage.getBool('ve-quick-access-quick-print', true), + undo: Common.localStorage.getBool('ve-quick-access-undo', true), + redo: Common.localStorage.getBool('ve-quick-access-redo', true) + } + }); + this.dlgQuickAccess.show(); + }, + + strZoom: 'Default Zoom Value', + okButtonText: 'Apply', + txtFitSlide: 'Fit to Slide', + txtWin: 'as Windows', + txtMac: 'as OS X', + txtNative: 'Native', + strFontRender: 'Font Hinting', + txtFitWidth: 'Fit to Width', + txtCacheMode: 'Default cache mode', + strMacrosSettings: 'Macros Settings', + txtWarnMacros: 'Show Notification', + txtRunMacros: 'Enable All', + txtStopMacros: 'Disable All', + txtWarnMacrosDesc: 'Disable all macros with notification', + txtRunMacrosDesc: 'Enable all macros without notification', + txtStopMacrosDesc: 'Disable all macros without notification', + strTheme: 'Theme', + txtThemeLight: 'Light', + txtThemeDark: 'Dark', + txtWorkspace: 'Workspace', + txtHieroglyphs: 'Hieroglyphs', + txtUseAltKey: 'Use Alt key to navigate the user interface using the keyboard', + txtUseOptionKey: 'Use Option key to navigate the user interface using the keyboard', + txtAdvancedSettings: 'Advanced Settings', + txtQuickPrint: 'Show the Quick Print button in the editor header', + txtQuickPrintTip: 'The document will be printed on the last selected or default printer', + txtLastUsed: 'Last used', + txtScreenReader: 'Turn on screen reader support', + txtCustomizeQuickAccess: 'Customize quick access', + txtTabBack: 'Use toolbar color as tabs background', + strTabStyle: 'Tab style', + textFill: 'Fill', + textLine: 'Line', + txtAppearance: 'Appearance' + }, VE.Views.FileMenuPanels.Settings || {})); + + VE.Views.FileMenuPanels.CreateNew = Common.UI.BaseView.extend(_.extend({ + el: '#panel-createnew', + menu: undefined, + + events: function() { + return { + 'click .blank-document-btn':_.bind(this._onBlankDocument, this), + 'click .thumb-list .thumb-wrap': _.bind(this._onDocumentTemplate, this) + }; + }, + + template: _.template([ + '
    <%= scope.txtCreateNew %>
    ', + '
    ', + '<% if (blank) { %> ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    <%= scope.txtBlank %>
    ', + '
    ', + '<% } %>', + '<% _.each(docs, function(item, index) { %>', + '
    ', + '
    ', + ' style="background-image: url(<%= item.image %>);">', + ' <%} else {' + + 'print(\">
    \")' + + ' } %>', + '
    ', + '
    <%= Common.Utils.String.htmlEncode(item.title || item.name || "") %>
    ', + '
    ', + '<% }) %>', + '
    ' + ].join('')), + + initialize: function(options) { + Common.UI.BaseView.prototype.initialize.call(this,arguments); + + this.menu = options.menu; + this.docs = options.docs; + this.blank = !!options.blank; + }, + + render: function() { + this.$el.html(this.template({ + scope: this, + docs: this.docs, + blank: this.blank + })); + var docs = (this.blank ? [{title: this.txtBlank}] : []).concat(this.docs); + var thumbsElm= this.$el.find('.thumb-wrap, .blank-document'); + _.each(thumbsElm, function (tmb, index){ + $(tmb).find('.title').tooltip({ + title : docs[index].title, + placement : 'cursor' + }); + }); + + if (_.isUndefined(this.scroller)) { + this.scroller = new Common.UI.Scroller({ + el: this.$el, + suppressScrollX: true, + alwaysVisibleY: true + }); + } + + return this; + }, + + show: function() { + Common.UI.BaseView.prototype.show.call(this,arguments); + this.scroller && this.scroller.update(); + }, + + _onBlankDocument: function() { + if ( this.menu ) + this.menu.fireEvent('create:new', [this.menu, 'blank']); + }, + + _onDocumentTemplate: function(e) { + if ( this.menu ) + this.menu.fireEvent('create:new', [this.menu, e.currentTarget.attributes['template'].value]); + }, + + txtBlank: 'Blank document', + txtCreateNew: 'Create New' + }, VE.Views.FileMenuPanels.CreateNew || {})); + + VE.Views.FileMenuPanels.DocumentInfo = Common.UI.BaseView.extend(_.extend({ + el: '#panel-info', + menu: undefined, + + initialize: function(options) { + Common.UI.BaseView.prototype.initialize.call(this,arguments); + this.rendered = false; + + this.template = _.template([ + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + // '', + // '', + // '', + // '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '
    ' + this.txtVisioInfo + '
    ', + '', + '', + '', + '', + '
    ', + '
    ', + '', + '
    ', + ].join('')); + + this.menu = options.menu; + this.coreProps = null; + this.authors = []; + this._locked = false; + }, + + render: function(node) { + var me = this; + var $markup = $(me.template({scope: me})); + + // server info + this.lblPlacement = $markup.findById('#id-info-placement'); + this.lblOwner = $markup.findById('#id-info-owner'); + this.lblUploaded = $markup.findById('#id-info-uploaded'); + + // edited info + var keyDownBefore = function(input, e){ + if (e.keyCode === Common.UI.Keys.ESC) { + var newVal = input._input.val(), + oldVal = input.getValue(); + if (newVal !== oldVal) { + input.setValue(oldVal); + e.stopPropagation(); + } + } + }; + + this.inputTitle = new Common.UI.InputField({ + el : $markup.findById('#id-info-title'), + style : 'width: 200px;', + placeHolder : this.txtAddText, + validateOnBlur: false, + dataHint: '2', + dataHintDirection: 'left', + dataHintOffset: 'small' + }).on('keydown:before', keyDownBefore).on('changed:after', function(_, newValue) { + me.coreProps.asc_putTitle(newValue); + me.api.asc_setCoreProps(me.coreProps); + }); + + this.inputTags = new Common.UI.InputField({ + el : $markup.findById('#id-info-tags'), + style : 'width: 200px;', + placeHolder : this.txtAddText, + validateOnBlur: false, + dataHint: '2', + dataHintDirection: 'left', + dataHintOffset: 'small' + }).on('keydown:before', keyDownBefore).on('changed:after', function(_, newValue) { + me.coreProps.asc_putKeywords(newValue); + me.api.asc_setCoreProps(me.coreProps); + }); + + this.inputSubject = new Common.UI.InputField({ + el : $markup.findById('#id-info-subject'), + style : 'width: 200px;', + placeHolder : this.txtAddText, + validateOnBlur: false, + dataHint: '2', + dataHintDirection: 'left', + dataHintOffset: 'small' + }).on('keydown:before', keyDownBefore).on('changed:after', function(_, newValue) { + me.coreProps.asc_putSubject(newValue); + me.api.asc_setCoreProps(me.coreProps); + }); + + this.inputComment = new Common.UI.InputField({ + el : $markup.findById('#id-info-comment'), + style : 'width: 200px;', + placeHolder : this.txtAddText, + validateOnBlur: false, + dataHint: '2', + dataHintDirection: 'left', + dataHintOffset: 'small' + }).on('keydown:before', keyDownBefore).on('changed:after', function(_, newValue) { + me.coreProps.asc_putDescription(newValue); + me.api.asc_setCoreProps(me.coreProps); + }); + + // modify info + this.lblModifyDate = $markup.findById('#id-info-modify-date'); + this.lblModifyBy = $markup.findById('#id-info-modify-by'); + + // creation info + this.lblDate = $markup.findById('#id-info-date'); + this.lblApplication = $markup.findById('#id-info-appname'); + this.tblAuthor = $markup.findById('#id-info-author table'); + this.trAuthor = $markup.findById('#id-info-add-author').closest('tr'); + this.authorTpl = '
    '; + + this.tblAuthor.on('click', function(e) { + var btn = $markup.find(e.target); + if (btn.hasClass('close') && !btn.hasClass('disabled')) { + var el = btn.closest('tr'), + idx = me.tblAuthor.find('tr').index(el); + el.remove(); + me.authors.splice(idx, 1); + me.coreProps.asc_putCreator(me.authors.join(';')); + me.api.asc_setCoreProps(me.coreProps); + me.updateScroller(true); + } + }); + + this.inputAuthor = new Common.UI.InputField({ + el : $markup.findById('#id-info-add-author'), + style : 'width: 200px;', + validateOnBlur: false, + placeHolder: this.txtAddAuthor, + dataHint: '2', + dataHintDirection: 'left', + dataHintOffset: 'small' + }).on('changed:after', function(input, newValue, oldValue, e) { + if (newValue == oldValue) return; + + var val = newValue.trim(); + if (!!val && val !== oldValue.trim()) { + var isFromApply = e && e.relatedTarget && (e.relatedTarget.id == 'fminfo-btn-apply'); + val.split(/\s*[,;]\s*/).forEach(function(item){ + var str = item.trim(); + if (str) { + me.authors.push(item); + if (!isFromApply) { + var div = $(Common.Utils.String.format(me.authorTpl, Common.Utils.String.htmlEncode(str))); + me.trAuthor.before(div); + me.updateScroller(); + } + } + }); + !isFromApply && me.inputAuthor.setValue(''); + } + + me.coreProps.asc_putCreator(me.authors.join(';')); + me.api.asc_setCoreProps(me.coreProps); + }).on('keydown:before', keyDownBefore); + + this.btnAddProperty = new Common.UI.Button({ + el: $markup.findById('#fminfo-btn-add-property') + }); + this.btnAddProperty.on('click', _.bind(this.onAddPropertyClick, this)); + + this.rendered = true; + + this.updateInfo(this.doc); + + this.$el = $(node).html($markup); + if (_.isUndefined(this.scroller)) { + this.scroller = new Common.UI.Scroller({ + el: this.$el, + alwaysVisibleY: true + }); + } + + Common.NotificationCenter.on({ + 'window:resize': function() { + me.isVisible() && me.updateScroller(); + } + }); + + return this; + }, + + show: function() { + Common.UI.BaseView.prototype.show.call(this,arguments); + + this.updateFileInfo(); + this.scroller && this.scroller.scrollTop(0); + this.updateScroller(); + }, + + hide: function() { + Common.UI.BaseView.prototype.hide.call(this,arguments); + }, + + updateScroller: function(destroy) { + if (this.scroller) { + this.scroller.update(destroy ? {} : undefined); + } + }, + + updateInfo: function(doc) { + this.doc = doc; + if (!this.rendered) + return; + + var visible = false; + doc = doc || {}; + if (doc.info) { + // server info + if (doc.info.folder ) + this.lblPlacement.text( doc.info.folder ); + visible = this._ShowHideInfoItem(this.lblPlacement, doc.info.folder!==undefined && doc.info.folder!==null) || visible; + var value = doc.info.owner; + if (value) + this.lblOwner.text(value); + visible = this._ShowHideInfoItem(this.lblOwner, !!value) || visible; + value = doc.info.uploaded; + if (value) + this.lblUploaded.text(value); + visible = this._ShowHideInfoItem(this.lblUploaded, !!value) || visible; + } else + this._ShowHideDocInfo(false); + $('tr.divider.general', this.el)[visible?'show':'hide'](); + + var appname = (this.api) ? this.api.asc_getAppProps() : null; + if (appname) { + appname = (appname.asc_getApplication() || '') + (appname.asc_getAppVersion() ? ' ' : '') + (appname.asc_getAppVersion() || ''); + this.lblApplication.text(appname); + } + this._ShowHideInfoItem(this.lblApplication, !!appname); + + this.coreProps = (this.api) ? this.api.asc_getCoreProps() : null; + if (this.coreProps) { + var value = this.coreProps.asc_getCreated(); + this.lblDate.text(this.dateToString(value)); + this._ShowHideInfoItem(this.lblDate, !!value); + } + + this.renderCustomProperties(); + }, + + updateFileInfo: function() { + if (!this.rendered) + return; + + var me = this, + props = (this.api) ? this.api.asc_getCoreProps() : null, + value; + + this.coreProps = props; + // var app = (this.api) ? this.api.asc_getAppProps() : null; + // if (app) { + // value = app.asc_getTotalTime(); + // if (value) + // this.lblEditTime.text(value + ' ' + this.txtMinutes); + // } + // this._ShowHideInfoItem(this.lblEditTime, !!value); + + if (props) { + var visible = false; + value = props.asc_getModified(); + this.lblModifyDate.text(this.dateToString(value)); + visible = this._ShowHideInfoItem(this.lblModifyDate, !!value) || visible; + value = props.asc_getLastModifiedBy(); + if (value) + this.lblModifyBy.text(AscCommon.UserInfoParser.getParsedName(value)); + visible = this._ShowHideInfoItem(this.lblModifyBy, !!value) || visible; + $('tr.divider.modify', this.el)[visible?'show':'hide'](); + + value = props.asc_getTitle(); + this.inputTitle.setValue(value || ''); + value = props.asc_getKeywords(); + this.inputTags.setValue(value || ''); + value = props.asc_getSubject(); + this.inputSubject.setValue(value || ''); + value = props.asc_getDescription(); + this.inputComment.setValue(value || ''); + + this.inputAuthor.setValue(''); + this.tblAuthor.find('tr:not(:last-of-type)').remove(); + this.authors = []; + value = props.asc_getCreator();//"123\"\"\"\<\>,456"; + value && value.split(/\s*[,;]\s*/).forEach(function(item) { + var div = $(Common.Utils.String.format(me.authorTpl, Common.Utils.String.htmlEncode(item))); + me.trAuthor.before(div); + me.authors.push(item); + }); + this.tblAuthor.find('.close').toggleClass('hidden', !this.mode.isEdit); + !this.mode.isEdit && this._ShowHideInfoItem(this.tblAuthor, !!this.authors.length); + } + this.SetDisabled(); + }, + + tplCustomProperty: function(name, type, value) { + if (type === AscCommon.c_oVariantTypes.vtBool) { + value = value ? this.txtYes : this.txtNo; + } else if (type === AscCommon.c_oVariantTypes.vtFiletime) { + value = this.dateToString(new Date(value), true); + } + + return '' + + '' + + '
    ' + + '' + + '
    ' + + '
    '; + }, + + dateToString: function (value, hideTime) { + var text = ''; + if (value) { + var lang = (this.mode.lang || 'en').replace('_', '-').toLowerCase(); + try { + if ( lang == 'ar-SA'.toLowerCase() ) lang = lang + '-u-nu-latn-ca-gregory'; + text = value.toLocaleString(lang, {year: 'numeric', month: '2-digit', day: '2-digit'}) + (!hideTime ? ' ' + value.toLocaleString(lang, {timeStyle: 'short'}) : ''); + } catch (e) { + lang = 'en'; + text = value.toLocaleString(lang, {year: 'numeric', month: '2-digit', day: '2-digit'}) + (!hideTime ? ' ' + value.toLocaleString(lang, {timeStyle: 'short'}) : ''); + } + } + return text; + }, + + renderCustomProperties: function() { + if (!this.api) { + return; + } + + $('tr[data-custom-property]').remove(); + + var properties = this.api.asc_getAllCustomProperties(); + _.each(properties, _.bind(function(prop, idx) { + var me = this, name = prop.asc_getName(), type = prop.asc_getType(), value = prop.asc_getValue(); + var $propertyEl = $(this.tplCustomProperty(name, type, value)); + + $('tbody.properties-tab').append($propertyEl); + + $propertyEl.on('click', function (e) { + if ($propertyEl.find('div.disabled').length) { + return; + } + + var btn = $propertyEl.find(e.target); + if (btn.hasClass('close')) { + me.api.asc_removeCustomProperty(idx); + me.renderCustomProperties(); + } else if (btn.hasClass('form-control')) { + (new Common.Views.DocumentPropertyDialog({ + title: me.txtDocumentPropertyUpdateTitle, + lang: me.mode.lang, + defaultValue: { + name: name, + type: type, + value: value + }, + nameValidator: function(newName) { + if (newName !== name && _.some(properties, function (prop) { return prop.asc_getName() === newName; })) { + return me.txtPropertyTitleConflictError; + } + + return true; + }, + handler: function(result, name, type, value) { + if (result === 'ok') { + me.api.asc_modifyCustomProperty(idx, name, type, value); + me.renderCustomProperties(); + } + } + })).show(); + } + }); + }, this)); + }, + + setDisabledCustomProperties: function(disable) { + _.each($('tr[data-custom-property]'), function(prop) { + $(prop).find('div.custom-property-wrapper')[disable ? 'addClass' : 'removeClass']('disabled'); + $(prop).find('div.close')[disable ? 'hide' : 'show'](); + }) + }, + + onAddPropertyClick: function() { + var me = this; + (new Common.Views.DocumentPropertyDialog({ + lang: me.mode.lang, + nameValidator: function(newName) { + var properties = me.api.asc_getAllCustomProperties(); + if (_.some(properties, function (prop) { return prop.asc_getName() === newName; })) { + return me.txtPropertyTitleConflictError; + } + + return true; + }, + handler: function(result, name, type, value) { + if (result === 'ok') { + me.api.asc_addCustomProperty(name, type, value); + me.renderCustomProperties(); + } + } + })).show(); + }, + + _ShowHideInfoItem: function(el, visible) { + el.closest('tr')[visible?'show':'hide'](); + return visible; + }, + + _ShowHideDocInfo: function(visible) { + this._ShowHideInfoItem(this.lblPlacement, visible); + this._ShowHideInfoItem(this.lblOwner, visible); + this._ShowHideInfoItem(this.lblUploaded, visible); + }, + + setMode: function(mode) { + this.mode = mode; + this.inputAuthor.setVisible(mode.isEdit); + this.btnAddProperty.setVisible(mode.isEdit); + this.tblAuthor.find('.close').toggleClass('hidden', !mode.isEdit); + if (!mode.isEdit) { + this.inputTitle._input.attr('placeholder', ''); + this.inputTags._input.attr('placeholder', ''); + this.inputSubject._input.attr('placeholder', ''); + this.inputComment._input.attr('placeholder', ''); + this.inputAuthor._input.attr('placeholder', ''); + } + this.SetDisabled(); + return this; + }, + + setApi: function(o) { + this.api = o; + this.api.asc_registerCallback('asc_onLockCore', _.bind(this.onLockCore, this)); + this.updateInfo(this.doc); + return this; + }, + + onLockCore: function(lock) { + this._locked = lock; + this.updateFileInfo(); + }, + + SetDisabled: function() { + var disable = !this.mode.isEdit || this._locked; + this.inputTitle.setDisabled(disable); + this.inputTags.setDisabled(disable); + this.inputSubject.setDisabled(disable); + this.inputComment.setDisabled(disable); + this.inputAuthor.setDisabled(disable); + this.tblAuthor.find('.close').toggleClass('disabled', this._locked); + this.tblAuthor.toggleClass('disabled', disable); + this.btnAddProperty.setDisabled(disable); + this.setDisabledCustomProperties(disable); + }, + + txtPlacement: 'Location', + txtOwner: 'Owner', + txtUploaded: 'Uploaded', + txtAppName: 'Application', + txtEditTime: 'Total Editing time', + txtTitle: 'Title', + txtTags: 'Tags', + txtSubject: 'Subject', + txtComment: 'Comment', + txtModifyDate: 'Last Modified', + txtModifyBy: 'Last Modified By', + txtCreated: 'Created', + txtAuthor: 'Author', + txtAddAuthor: 'Add Author', + txtAddText: 'Add Text', + txtMinutes: 'min', + okButtonText: 'Apply', + txtVisioInfo: 'Document Info', + txtCommon: 'Common', + txtProperties: 'Properties', + txtDocumentPropertyUpdateTitle: "Document Property", + txtAddProperty: 'Add property', + txtYes: 'Yes', + txtNo: 'No', + txtPropertyTitleConflictError: 'Property with this title already exists', + }, VE.Views.FileMenuPanels.DocumentInfo || {})); + + VE.Views.FileMenuPanels.DocumentRights = Common.UI.BaseView.extend(_.extend({ + el: '#panel-rights', + menu: undefined, + + initialize: function(options) { + Common.UI.BaseView.prototype.initialize.call(this,arguments); + this.rendered = false; + + this.template = _.template([ + '
    ' + this.txtAccessRights + '
    ', + '', + '', + '', + '', + '', + '', + '', + '', + '
    ' + ].join('')); + + this.templateRights = _.template([ + '', + '<% _.each(users, function(item) { %>', + '', + '', + '', + '', + '<% }); %>', + '
    <%= Common.Utils.String.htmlEncode(item.user) %><%= Common.Utils.String.htmlEncode(item.permissions) %>
    ' + ].join('')); + + this.menu = options.menu; + }, + + render: function(node) { + var $markup = $(this.template()); + + this.cntRights = $markup.findById('#id-info-rights'); + this.btnEditRights = new Common.UI.Button({ + el: $markup.findById('#id-info-btn-edit') + }); + this.btnEditRights.on('click', _.bind(this.changeAccessRights, this)); + + this.rendered = true; + + this.updateInfo(this.doc); + + this.$el = $(node).html($markup); + + if (_.isUndefined(this.scroller)) { + this.scroller = new Common.UI.Scroller({ + el: this.$el, + suppressScrollX: true, + alwaysVisibleY: true + }); + } + + Common.NotificationCenter.on('collaboration:sharingupdate', this.updateSharingSettings.bind(this)); + Common.NotificationCenter.on('collaboration:sharingdeny', this.onLostEditRights.bind(this)); + + return this; + }, + + show: function() { + Common.UI.BaseView.prototype.show.call(this,arguments); + this.scroller && this.scroller.update(); + }, + + hide: function() { + Common.UI.BaseView.prototype.hide.call(this,arguments); + }, + + updateInfo: function(doc) { + this.doc = doc; + if (!this.rendered) + return; + + doc = doc || {}; + + if (doc.info) { + if (doc.info.sharingSettings) + this.cntRights.html(this.templateRights({users: doc.info.sharingSettings})); + this._ShowHideInfoItem('rights', doc.info.sharingSettings!==undefined && doc.info.sharingSettings!==null && doc.info.sharingSettings.length>0); + this._ShowHideInfoItem('edit-rights', (!!this.sharingSettingsUrl && this.sharingSettingsUrl.length || this.mode.canRequestSharingSettings) && this._readonlyRights!==true); + } else + this._ShowHideDocInfo(false); + }, + + _ShowHideInfoItem: function(cls, visible) { + $('tr.'+cls, this.el)[visible?'show':'hide'](); + }, + + _ShowHideDocInfo: function(visible) { + this._ShowHideInfoItem('rights', visible); + this._ShowHideInfoItem('edit-rights', visible); + }, + + setMode: function(mode) { + this.mode = mode; + this.sharingSettingsUrl = mode.sharingSettingsUrl; + return this; + }, + + changeAccessRights: function(btn,event,opts) { + Common.NotificationCenter.trigger('collaboration:sharing'); + }, + + updateSharingSettings: function(rights) { + this._ShowHideInfoItem('rights', this.doc.info.sharingSettings!==undefined && this.doc.info.sharingSettings!==null && this.doc.info.sharingSettings.length>0); + this.cntRights.html(this.templateRights({users: this.doc.info.sharingSettings})); + }, + + onLostEditRights: function() { + this._readonlyRights = true; + if (!this.rendered) + return; + + this._ShowHideInfoItem('edit-rights', false); + }, + + txtRights: 'Persons who have rights', + txtBtnAccessRights: 'Change access rights', + txtAccessRights: 'Access Rights' + }, VE.Views.FileMenuPanels.DocumentRights || {})); + + VE.Views.FileMenuPanels.Help = Common.UI.BaseView.extend({ + el: '#panel-help', + menu: undefined, + + template: _.template([ + '
    ', + '
    ', + '
    ', + '
    ' + ].join('')), + + initialize: function(options) { + Common.UI.BaseView.prototype.initialize.call(this,arguments); + + this.menu = options.menu; + this.urlPref = 'resources/help/{{DEFAULT_LANG}}/'; + this.openUrl = null; + + this.en_data = [ + {"src": "ProgramInterface/ProgramInterface.htm", "name": "Introducing Visio Editor user interface", "headername": "Program Interface"}, + {"src": "ProgramInterface/FileTab.htm", "name": "File tab"}, + {"src": "UsageInstructions/OpenCreateNew.htm", "name": "Create a new document or open an existing one", "headername": "Basic operations" }, + {"src": "UsageInstructions/ViewVisioInfo.htm", "name": "View document information", "headername": "Tools and settings"}, + {"src": "HelpfulHints/About.htm", "name": "About Visio Editor", "headername": "Helpful hints"}, + {"src": "HelpfulHints/SupportedFormats.htm", "name": "Supported formats of electronic documents"}, + {"src": "HelpfulHints/KeyboardShortcuts.htm", "name": "Keyboard shortcuts"} + ]; + + if (Common.Utils.isIE) { + window.onhelp = function () { return false; } + } + }, + + render: function() { + var me = this; + this.$el.html(this.template()); + + this.viewHelpPicker = new Common.UI.DataView({ + el: $('#id-help-contents'), + store: new Common.UI.DataViewStore([]), + keyMoveDirection: 'vertical', + itemTemplate: _.template([ + '
    ', + '
    <%= name %>
    ', + '
    ' + ].join('')) + }); + this.viewHelpPicker.on('item:add', function(dataview, itemview, record) { + if (record.has('headername')) { + $(itemview.el).before('
    ' + record.get('headername') + '
    '); + } + }); + + this.viewHelpPicker.on('item:select', function(dataview, itemview, record) { + me.onSelectItem(record.get('src')); + }); + + this.iFrame = document.createElement('iframe'); + + this.iFrame.src = ""; + this.iFrame.align = "top"; + this.iFrame.frameBorder = "0"; + this.iFrame.width = "100%"; + this.iFrame.height = "100%"; + if (Common.Utils.isChrome || Common.Utils.isOpera || Common.Utils.isGecko && Common.Utils.firefoxVersion>86) + this.iFrame.onload = function() { + try { + me.findUrl(me.iFrame.contentWindow.location.href); + } catch (e) { + } + }; + + Common.Gateway.on('internalcommand', function(data) { + if (data.type == 'help:hyperlink') { + me.findUrl(data.data); + } + }); + + $('#id-help-frame').append(this.iFrame); + + return this; + }, + + setLangConfig: function(lang) { + var me = this; + var store = this.viewHelpPicker.store; + if (lang) { + lang = lang.split(/[\-\_]/)[0]; + var config = { + dataType: 'json', + error: function () { + if ( me.urlPref.indexOf('resources/help/{{DEFAULT_LANG}}/')<0 ) { + me.urlPref = 'resources/help/{{DEFAULT_LANG}}/'; + store.url = 'resources/help/{{DEFAULT_LANG}}/Contents.json'; + store.fetch(config); + } else { + me.urlPref = 'resources/help/{{DEFAULT_LANG}}/'; + store.reset(me.en_data); + } + }, + success: function () { + var rec = me.openUrl ? store.find(function(record){ + return (me.openUrl.indexOf(record.get('src'))>=0); + }) : store.at(0); + if (rec) { + me.viewHelpPicker.selectRecord(rec, true); + me.viewHelpPicker.scrollToRecord(rec); + } + me.onSelectItem(me.openUrl ? me.openUrl : rec.get('src')); + } + }; + + if ( Common.Controllers.Desktop.isActive() ) { + if ( !Common.Controllers.Desktop.isHelpAvailable() ) { + me.noHelpContents = true; + me.iFrame.src = '../../common/main/resources/help/download.html'; + } else { + me.urlPref = Common.Controllers.Desktop.helpUrl() + '/'; + store.url = me.urlPref + 'Contents.json'; + store.fetch(config); + } + } else { + store.url = 'resources/help/' + lang + '/Contents.json'; + store.fetch(config); + this.urlPref = 'resources/help/' + lang + '/'; + } + } + }, + + show: function (url) { + Common.UI.BaseView.prototype.show.call(this); + if (!this._scrollerInited) { + this.viewHelpPicker.scroller.update(); + this._scrollerInited = true; + } + if (url) { + if (this.viewHelpPicker.store.length>0) { + this.findUrl(url); + this.onSelectItem(url); + } else + this.openUrl = url; + } + }, + + onSelectItem: function(src) { + this.iFrame.src = this.urlPref + src; + }, + + findUrl: function(src) { + var rec = this.viewHelpPicker.store.find(function(record){ + return (src.indexOf(record.get('src'))>=0); + }); + if (rec) { + this.viewHelpPicker.selectRecord(rec, true); + this.viewHelpPicker.scrollToRecord(rec); + } + } + }); + +}); diff --git a/apps/visioeditor/main/app/view/LeftMenu.js b/apps/visioeditor/main/app/view/LeftMenu.js new file mode 100644 index 0000000000..01b71d5848 --- /dev/null +++ b/apps/visioeditor/main/app/view/LeftMenu.js @@ -0,0 +1,475 @@ +/* + * (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 + * + */ +/** + * LeftMenu.js + * + * Created on 11/07/24 + * + */ + +define([ + 'text!visioeditor/main/app/template/LeftMenu.template', + 'jquery', + 'underscore', + 'backbone', + 'common/main/lib/component/SideMenu', + 'common/main/lib/component/Button', + 'common/main/lib/view/About', + 'common/main/lib/view/Chat', + 'common/main/lib/view/Plugins', + 'common/main/lib/view/About', + 'visioeditor/main/app/view/FileMenu' +], function (menuTemplate, $, _, Backbone) { + 'use strict'; + + var SCALE_MIN = 40; + var MENU_SCALE_PART = 300; + + VE.Views.LeftMenu = Common.UI.SideMenu.extend(_.extend({ + el: '#left-menu', + + template: _.template(menuTemplate), + + initialize: function () { + this.minimizedMode = true; + this._state = {disabled: false}; + }, + + render: function () { + var $markup = $(this.template({scope: this})); + + this.btnMoreContainer = $markup.find('#slot-left-menu-more'); + Common.UI.SideMenu.prototype.render.call(this); + this.btnMore.menu.menuAlign = 'tl-tr'; + + this.btnSearchBar = new Common.UI.Button({ + action: 'advancedsearch', + el: $markup.elementById('#left-btn-searchbar'), + hint: this.tipSearch, + disabled: true, + iconCls: 'btn-menu-search', + enableToggle: true, + toggleGroup: 'leftMenuGroup' + }); + this.btnSearchBar.on('click', this.onBtnMenuClick.bind(this)); + + this.btnAbout = new Common.UI.Button({ + action: 'about', + el: $markup.elementById('#left-btn-about'), + hint: this.tipAbout, + enableToggle: true, + disabled: true, + iconCls: 'btn-menu-about', + toggleGroup: 'leftMenuGroup' + }); + this.btnAbout.on('toggle', this.onBtnMenuToggle.bind(this)); + + this.btnSupport = new Common.UI.Button({ + action: 'support', + el: $markup.elementById('#left-btn-support'), + hint: this.tipSupport, + iconCls: 'btn-menu-support', + disabled: true + }); + this.btnSupport.on('click', _.bind(function() { + var config = this.mode.customization; + config && !!config.feedback && !!config.feedback.url ? + window.open(config.feedback.url) : + window.open('{{SUPPORT_URL}}'); + }, this)); + + /** coauthoring begin **/ + // this.btnComments = new Common.UI.Button({ + // el: $markup.elementById('#left-btn-comments'), + // hint: this.tipComments + Common.Utils.String.platformKey('Ctrl+Shift+H'), + // enableToggle: true, + // disabled: true, + // iconCls: 'btn-menu-comments', + // toggleGroup: 'leftMenuGroup' + // }); + // this.btnComments.on('click', this.onBtnMenuClick.bind(this)); + // this.btnComments.on('toggle', this.onBtnCommentsToggle.bind(this)); + + this.btnChat = new Common.UI.Button({ + el: $markup.elementById('#left-btn-chat'), + hint: this.tipChat + Common.Utils.String.platformKey('Alt+Q', ' (' + (Common.Utils.isMac ? Common.Utils.String.textCtrl + '+' : '') + '{0})'), + enableToggle: true, + disabled: true, + iconCls: 'btn-menu-chat', + toggleGroup: 'leftMenuGroup' + }); + this.btnChat.on('click', this.onBtnMenuClick.bind(this)); + + // this.btnComments.hide(); + this.btnChat.hide(); + + /** coauthoring end **/ + + this.menuFile = new VE.Views.FileMenu(); + this.btnAbout.panel = new Common.Views.About({el: '#about-menu-panel', appName: this.txtEditor}); + + this.btnThumbs = new Common.UI.Button({ + action: 'thumbs', + el: $markup.elementById('#left-btn-thumbs'), + hint: this.tipSlides, + enableToggle: true, + disabled: true, + iconCls: 'btn-menu-thumbs', + toggleGroup: 'leftMenuGroup' + }); + this.btnThumbs.on('click', _.bind(this.onBtnMenuClick, this)); + + this.$el.html($markup); + + return this; + }, + + onBtnMenuToggle: function(btn, state) { + if (state) { + btn.panel['show'](); + if (!this._state.pluginIsRunning) + this.$el.width(SCALE_MIN); + } else { + btn.panel['hide'](); + } + VE.getController('Toolbar').DisableToolbar(state==true); + if (!this.supressEvents) + Common.NotificationCenter.trigger('layout:changed', 'leftmenu'); + }, + + onBtnCommentsToggle: function(btn, state) { + if (!state) + this.fireEvent('comments:hide', this); + }, + + onBtnMenuClick: function(btn, e) { + this.supressEvents = true; + if (this.btnAbout.pressed) this.btnAbout.toggle(false); + + if (btn.options.action == 'thumbs') { + if (!btn.pressed && this._state.pluginIsRunning) { + this.$el.width(Common.localStorage.getItem('pe-mainmenu-width') || MENU_SCALE_PART); + } else { + var width = this.$el.width(); + if (width > SCALE_MIN) { + Common.localStorage.setItem('pe-mainmenu-width',width); + this.$el.width(SCALE_MIN); + } + if (this._state.pluginIsRunning) // hide comments or chat panel when plugin is running + this.onCoauthOptions(); + } + } else { + if (btn.pressed) { + if (!(this.$el.width() > SCALE_MIN)) { + this.$el.width(Common.localStorage.getItem('ve-mainmenu-width') || MENU_SCALE_PART); + } + } else if (!this._state.pluginIsRunning){ + var width = this.$el.width(); + this.isVisible() && (width>SCALE_MIN) && Common.localStorage.setItem('ve-mainmenu-width',width); + this.$el.width(SCALE_MIN); + } + this.onCoauthOptions(); + } + + this.fireEvent('panel:show', [this, btn.options.action, btn.pressed]); + Common.NotificationCenter.trigger('layout:changed', 'leftmenu'); + + this.supressEvents = false; + }, + + onCoauthOptions: function(e) { + /** coauthoring begin **/ + if (this.mode.canCoAuthoring) { + // if (this.mode.canViewComments) { + // if (this.btnComments.pressed && this.btnComments.$el.hasClass('notify')) + // this.btnComments.$el.removeClass('notify'); + // this.panelComments[this.btnComments.pressed?'show':'hide'](); + // this.fireEvent((this.btnComments.pressed) ? 'comments:show' : 'comments:hide', this); + // } + if (this.mode.canChat) { + if (this.btnChat.pressed) { + if (this.btnChat.$el.hasClass('notify')) + this.btnChat.$el.removeClass('notify'); + + this.panelChat.show(); + this.panelChat.focus(); + } else + this.panelChat['hide'](); + } + } + if (this.panelSearch) { + if (this.btnSearchBar.pressed) { + this.panelSearch.show(); + this.panelSearch.focus(); + } else { + this.panelSearch.hide(); + } + } + /** coauthoring end **/ + }, + + getFocusElement: function () { + var btn = false; + if (this.btnChat && this.btnChat.pressed) { + btn = this.panelChat.getFocusElement(); + } else if (this.btnSearchBar && this.btnSearchBar.pressed) { + btn = this.panelSearch.getFocusElement(); + } + return btn; + }, + + setOptionsPanel: function(name, panel) { + /** coauthoring begin **/ + if (name == 'chat') { + this.panelChat = panel.render('#left-panel-chat'); + } else if (name == 'comment') { + this.panelComments = panel; + } else /** coauthoring end **/ + if (name == 'advancedsearch') { + this.panelSearch = panel.render('#left-panel-search'); + } + }, + + /** coauthoring begin **/ + markCoauthOptions: function(opt, ignoreDisabled) { + if (opt=='chat' && (this.btnChat.isVisible() || this.isButtonInMoreMenu(this.btnChat)) && + !this.btnChat.isDisabled() && !this.btnChat.pressed) { + this.btnChat.$el.addClass('notify'); + } + // if (opt=='comments' && (this.btnComments.isVisible() || this.isButtonInMoreMenu(this.btnComments)) && !this.btnComments.pressed && + // (!this.btnComments.isDisabled() || ignoreDisabled) ) { + // this.btnComments.$el.addClass('notify'); + // } + }, + /** coauthoring end **/ + + close: function(menu) { + if ( this.menuFile.isVisible() ) { + this.menuFile.hide(); + } else { + this.btnAbout.toggle(false); + this.btnThumbs.toggle(false, !this.mode); + if (!this._state.pluginIsRunning) + this.$el.width(SCALE_MIN); + /** coauthoring begin **/ + if (this.mode && this.mode.canCoAuthoring) { + // if (this.mode.canViewComments) { + // this.panelComments && this.panelComments['hide'](); + // if (this.btnComments.pressed) + // this.fireEvent('comments:hide', this); + // this.btnComments.toggle(false, true); + // } + if (this.mode.canChat) { + this.panelChat && this.panelChat['hide'](); + this.btnChat.toggle(false); + } + } + /** coauthoring end **/ + if (this.panelSearch) { + this.panelSearch['hide'](); + this.btnSearchBar.toggle(false, true); + } + this.toggleActivePluginButton(false); + } + }, + + isOpened: function() { + var isopened = this.btnSearchBar.pressed; + /** coauthoring begin **/ + !isopened && (isopened = this.btnComments.pressed || this.btnChat.pressed); + /** coauthoring end **/ + return isopened; + }, + + disableMenu: function(menu, disable) { + this.btnSearchBar.setDisabled(false); + this.btnAbout.setDisabled(false); + this.btnSupport.setDisabled(false); + /** coauthoring begin **/ + // this.btnComments.setDisabled(false); + this.btnChat.setDisabled(false); + /** coauthoring end **/ + this.btnThumbs.setDisabled(disable); + this.setDisabledAllMoreMenuItems(false); + }, + + showMenu: function(menu, opts, suspendAfter) { + var re = /^(\w+):?(\w*)$/.exec(menu); + if ( re[1] == 'file' ) { + if (!Common.Controllers.LaunchController.isScriptLoaded()) return; + if ( !this.menuFile.isVisible() ) { + // this.btnFile.toggle(true); + } + this.menuFile.show(re[2].length ? re[2] : undefined, opts); + } else { + /** coauthoring begin **/ + if (menu == 'chat') { + if ((this.btnChat.isVisible() || this.isButtonInMoreMenu(this.btnChat)) && + !this.btnChat.isDisabled() && !this.btnChat.pressed) { + this.btnChat.toggle(true); + this.onBtnMenuClick(this.btnChat); + this.panelChat.focus(); + } + // } else + // if (menu == 'comments') { + // if ((this.btnComments.isVisible() || this.isButtonInMoreMenu(this.btnComments)) && + // !this.btnComments.isDisabled() && !this.btnComments.pressed) { + // this.btnComments.toggle(true); + // this.onBtnMenuClick(this.btnComments); + // } + } else if (menu == 'advancedsearch') { + if ((this.btnSearchBar.isVisible() || this.isButtonInMoreMenu(this.btnSearchBar)) && + !this.btnSearchBar.isDisabled() && !this.btnSearchBar.pressed) { + this.btnSearchBar.toggle(true); + this.onBtnMenuClick(this.btnSearchBar); + this.panelSearch.focus(); + !suspendAfter && this.fireEvent('search:aftershow', this); + } + } + /** coauthoring end **/ + } + }, + + getMenu: function(type) { + switch (type) { + default: return null; + case 'file': return this.menuFile; + case 'about': return this.btnAbout.panel; + } + }, + + setMode: function(mode) { + this.mode = mode; + this.btnAbout.panel.setMode(mode); + return this; + }, + + setDeveloperMode: function(mode, beta, version) { + if ( !this.$el.is(':visible') ) return; + + if ((mode & Asc.c_oLicenseMode.Trial) || (mode & Asc.c_oLicenseMode.Developer)) { + if (!this.developerHint) { + var str = ''; + if ((mode & Asc.c_oLicenseMode.Trial) && (mode & Asc.c_oLicenseMode.Developer)) + str = this.txtTrialDev; + else if ((mode & Asc.c_oLicenseMode.Trial)!==0) + str = this.txtTrial; + else if ((mode & Asc.c_oLicenseMode.Developer)!==0) + str = this.txtDeveloper; + str = str.toUpperCase(); + this.developerHint = $('
    ' + str + '
    ').appendTo(this.$el); + this.devHeight = this.developerHint.outerHeight(); + !this.devHintInited && $(window).on('resize', _.bind(this.onWindowResize, this)); + this.devHintInited = true; + } + } + this.developerHint && this.developerHint.toggleClass('hidden', !((mode & Asc.c_oLicenseMode.Trial) || (mode & Asc.c_oLicenseMode.Developer))); + + if (beta) { + if (!this.betaHint) { + var style = (mode) ? 'style="margin-top: 4px;"' : '', + arr = (version || '').split('.'), + ver = ''; + (arr.length>0) && (ver += ('v. ' + arr[0])); + (arr.length>1) && (ver += ('.' + arr[1])); + this.betaHint = $('
    ' + (ver + ' (beta)' ) + '
    ').appendTo(this.$el); + this.betaHeight = this.betaHint.outerHeight(); + !this.devHintInited && $(window).on('resize', _.bind(this.onWindowResize, this)); + this.devHintInited = true; + } + } + this.betaHint && this.betaHint.toggleClass('hidden', !beta); + + var btns = this.$el.find('button.btn-category:visible'), + lastbtn = (btns.length>0) ? $(btns[btns.length-1]) : null; + this.minDevPosition = (lastbtn) ? (Common.Utils.getOffset(lastbtn).top - Common.Utils.getOffset(lastbtn.offsetParent()).top + lastbtn.height() + 20) : 20; + this.onWindowResize(); + }, + + setLimitMode: function() { + if ( !this.$el.is(':visible') ) return; + + if (!this.limitHint) { + var str = this.txtLimit.toUpperCase(); + this.limitHint = $('
    ' + str + '
    ').appendTo(this.$el); + this.limitHeight = this.limitHint.outerHeight(); + !this.devHintInited && $(window).on('resize', _.bind(this.onWindowResize, this)); + this.devHintInited = true; + } + this.limitHint && this.limitHint.toggleClass('hidden', false); + + var btns = this.$el.find('button.btn-category:visible'), + lastbtn = (btns.length>0) ? $(btns[btns.length-1]) : null; + this.minDevPosition = (lastbtn) ? (Common.Utils.getOffset(lastbtn).top - Common.Utils.getOffset(lastbtn.offsetParent()).top + lastbtn.height() + 20) : 20; + this.onWindowResize(); + }, + + onWindowResize: function() { + var height = (this.devHeight || 0) + (this.betaHeight || 0) + (this.limitHeight || 0); + var top = Math.max((this.$el.height()-height)/2, this.minDevPosition); + if (this.developerHint) { + this.developerHint.css('top', top); + top += this.devHeight; + } + if (this.betaHint) { + this.betaHint.css('top', top); + top += (this.betaHeight + 4); + } + this.limitHint && this.limitHint.css('top', top); + }, + + isVisible: function () { + return this.$el && this.$el.is(':visible'); + }, + + setButtons: function () { + var allButtons = [this.btnSearchBar, this.btnThumbs, /*this.btnComments,*/ this.btnChat, this.btnSupport, this.btnAbout]; + Common.UI.SideMenu.prototype.setButtons.apply(this, [allButtons]); + }, + + /** coauthoring begin **/ + // tipComments : 'Comments', + tipChat : 'Chat', + /** coauthoring end **/ + tipAbout : 'About', + tipSupport : 'Feedback & Support', + tipSearch : 'Search', + tipPlugins : 'Plugins', + tipSlides: 'Slides', + txtDeveloper: 'DEVELOPER MODE', + txtTrial: 'TRIAL MODE', + txtTrialDev: 'Trial Developer Mode', + txtLimit: 'Limit Access', + txtEditor: 'Visio Editor', + ariaLeftMenu: 'Left menu' + }, VE.Views.LeftMenu || {})); +}); diff --git a/apps/visioeditor/main/app/view/Statusbar.js b/apps/visioeditor/main/app/view/Statusbar.js new file mode 100644 index 0000000000..438bec836c --- /dev/null +++ b/apps/visioeditor/main/app/view/Statusbar.js @@ -0,0 +1,219 @@ +/* + * (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 + * + */ + +define([ + 'text!visioeditor/main/app/template/StatusBar.template', + 'jquery', + 'underscore', + 'backbone', + 'tip', + 'common/main/lib/component/Menu', + 'common/main/lib/component/Window' + ], + function(template, $, _, Backbone){ + 'use strict'; + + function _onAppReady(config) { + var me = this; + me.btnZoomToPage.updateHint(me.tipFitPage); + me.btnZoomToWidth.updateHint(me.tipFitWidth); + me.btnZoomDown.updateHint(me.tipZoomOut + Common.Utils.String.platformKey('Ctrl+-')); + me.btnZoomUp.updateHint(me.tipZoomIn + Common.Utils.String.platformKey('Ctrl++')); + + me.cntZoom.updateHint(me.tipZoomFactor); + me.cntZoom.cmpEl.on({ + 'show.bs.dropdown': function () { + _.defer(function(){ + me.cntZoom.cmpEl.find('ul').focus(); + }, 100); + }, + 'hide.bs.dropdown': function () { + _.defer(function(){ + me.api.asc_enableKeyEvents(true); + }, 100); + } + }); + + me.zoomMenu.on('item:click', function(menu, item) { + me.fireEvent('zoom:value', [item.value]); + }); + } + + VE.Views.Statusbar = Backbone.View.extend(_.extend({ + el: '#statusbar', + template: _.template(template), + + events: { + }, + + api: undefined, + + initialize: function (options) { + _.extend(this, options); + this._state = { + }; + this._isDisabled = false; + + var me = this; + this.$layout = $(this.template({})); + + this.btnZoomToPage = new Common.UI.Button({ + hintAnchor: 'top', + toggleGroup: 'status-zoom', + enableToggle: true + }); + + this.btnZoomToWidth = new Common.UI.Button({ + hintAnchor: 'top', + toggleGroup: 'status-zoom', + enableToggle: true + }); + + this.cntZoom = new Common.UI.Button({ + hintAnchor: 'top' + }); + + this.btnZoomDown = new Common.UI.Button({ + hintAnchor: 'top' + }); + + this.btnZoomUp = new Common.UI.Button({ + hintAnchor: 'top-right' + }); + + this.zoomMenu = new Common.UI.Menu({ + style: 'margin-top:-5px;', + menuAlign: 'bl-tl', + items: [ + { caption: "50%", value: 50 }, + { caption: "75%", value: 75 }, + { caption: "100%", value: 100 }, + { caption: "125%", value: 125 }, + { caption: "150%", value: 150 }, + { caption: "175%", value: 175 }, + { caption: "200%", value: 200 }, + { caption: "300%", value: 300 }, + { caption: "400%", value: 400 }, + { caption: "500%", value: 500 } + ] + }); + + var promise = new Promise(function (accept, reject) { + accept(); + }); + + Common.NotificationCenter.on('app:ready', function(mode) { + promise.then( _onAppReady.bind(this, mode) ); + }.bind(this)); + }, + + render: function(config) { + var me = this; + + function _btn_render(button, slot) { + button.setElement(slot, false); + button.render(); + } + + this.fireEvent('render:before', [this.$layout]); + + _btn_render(me.btnZoomToPage, $('#btn-zoom-topage', me.$layout)); + _btn_render(me.btnZoomToWidth, $('#btn-zoom-towidth', me.$layout)); + _btn_render(me.cntZoom, $('.cnt-zoom',me.$layout)); + _btn_render(me.btnZoomDown, $('#btn-zoom-down', me.$layout)); + _btn_render(me.btnZoomUp, $('#btn-zoom-up', me.$layout)); + + me.zoomMenu.render($('.cnt-zoom',me.$layout)); + me.zoomMenu.cmpEl.attr({tabindex: -1}); + + this.$el.html(me.$layout); + this.fireEvent('render:after', [this]); + + return this; + }, + + setApi: function(api) { + this.api = api; + + if (this.api) { + // this.api.asc_registerCallback('asc_onCountPages', _.bind(_onCountPages, this)); + // this.api.asc_registerCallback('asc_onCurrentPage', _.bind(_onCurrentPage, this)); + this.api.asc_registerCallback('asc_onCoAuthoringDisconnect',_.bind(this.onApiCoAuthoringDisconnect, this)); + Common.NotificationCenter.on('api:disconnect', _.bind(this.onApiCoAuthoringDisconnect, this)); + } + return this; + + }, + + setMode: function(mode) { + this.mode = mode; + }, + + setVisible: function(visible) { + visible + ? this.show() + : this.hide(); + }, + + isVisible: function() { + return this.$el && this.$el.is(':visible'); + }, + + getStatusLabel: function() { + return $('.statusbar #label-action'); + }, + + showStatusMessage: function(message) { + this.getStatusLabel().text(message); + }, + + clearStatusMessage: function() { + this.getStatusLabel().text(''); + }, + + SetDisabled: function(disable) { + this._isDisabled = disable; + }, + + onApiCoAuthoringDisconnect: function() { + this.setMode({isDisconnected:true}); + this.SetDisabled(true); + }, + + tipFitPage : 'Fit to Page', + tipFitWidth : 'Fit to Width', + tipZoomIn : 'Zoom In', + tipZoomOut : 'Zoom Out', + tipZoomFactor : 'Magnification', + }, VE.Views.Statusbar || {})); + } +); \ No newline at end of file diff --git a/apps/visioeditor/main/app/view/Toolbar.js b/apps/visioeditor/main/app/view/Toolbar.js new file mode 100644 index 0000000000..8fc1045eac --- /dev/null +++ b/apps/visioeditor/main/app/view/Toolbar.js @@ -0,0 +1,354 @@ +/* + * (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 + * + */ +/** + * Toolbar.js + * + * Toolbar view + * + * Created on 11/07/24 + * + */ +if (Common === undefined) + var Common = {}; + +define([ + 'jquery', + 'underscore', + 'backbone', + 'text!visioeditor/main/app/template/Toolbar.template', + 'text!visioeditor/main/app/template/ToolbarView.template', + 'common/main/lib/component/Button', + 'common/main/lib/component/ComboBox', + 'common/main/lib/component/DataView', + 'common/main/lib/component/Menu', + 'common/main/lib/component/Window', + 'common/main/lib/component/SynchronizeTip', + 'common/main/lib/component/Mixtbar' +], function ($, _, Backbone, template, template_view) { + 'use strict'; + + if (!Common.enumLock) + Common.enumLock = {}; + + var enumLock = { + copyLock: 'can-copy', + cutLock: 'can-cut', + inLightTheme: 'light-theme', + cantPrint: 'cant-print', + lostConnect: 'disconnect', + disableOnStart: 'on-start', + firstPage: 'first-page', + lastPage: 'last-page', + fileMenuOpened: 'file-menu-opened' + }; + for (var key in enumLock) { + if (enumLock.hasOwnProperty(key)) { + Common.enumLock[key] = enumLock[key]; + } + } + + VE.Views.Toolbar = Common.UI.Mixtbar.extend(_.extend((function(){ + + return { + el: '#toolbar', + + // Compile our stats template + // template: _.template(template), + + // Delegated events for creating new items, and clearing completed ones. + events: { + // + }, + + initialize: function () { + var me = this; + + /** + * UI Components + */ + + this._state = { + hasCollaborativeChanges: undefined + }; + Common.NotificationCenter.on('app:ready', me.onAppReady.bind(this)); + return this; + }, + + applyLayoutEdit: function(config) { + if (!config.isEdit) return; + + var _set = Common.enumLock, + arr = []; + + Common.UI.LayoutManager.addControls(arr); + return arr; + }, + + applyLayout: function (config) { + var me = this; + me.lockControls = []; + var _set = Common.enumLock; + if ( config.isEdit ) { + } else { + Common.UI.Mixtbar.prototype.initialize.call(this, { + template: _.template(template_view), + tabs: [ + {caption: me.textTabFile, action: 'file', layoutname: 'toolbar-file', haspanel:false, dataHintTitle: 'F'} + ] + } + ); + } + return this; + }, + + render: function (mode) { + var me = this; + + /** + * Render UI layout + */ + + this.fireEvent('render:before', [this]); + + me.isCompactView = mode.compactview; + if ( mode.isEdit) { + // me.$el.html(me.rendererComponents(me.$layout, mode)); + } else { + me.$layout.find('.canedit').hide(); + me.$layout.addClass('folded'); + me.$el.html(me.$layout); + } + + this.fireEvent('render:after', [this]); + Common.UI.Mixtbar.prototype.afterRender.call(this); + + Common.NotificationCenter.on({ + 'window:resize': function() { + Common.UI.Mixtbar.prototype.onResize.apply(me, arguments); + } + }); + + if ( mode.isEdit ) { + // me.setTab('home'); + // me.processPanelVisible(); + // Common.NotificationCenter.on('desktop:window', _.bind(me.onDesktopWindow, me)); + } + + if ( me.isCompactView ) + me.setFolded(true); + + return this; + }, + + onTabClick: function (e) { + var me = this, + tab = $(e.currentTarget).find('> a[data-tab]').data('tab'), + is_file_active = me.isTabActive('file'); + + if (!me._isDocReady || tab === 'file' && !Common.Controllers.LaunchController.isScriptLoaded()) return; + + Common.UI.Mixtbar.prototype.onTabClick.apply(me, arguments); + + if ( is_file_active ) { + me.fireEvent('file:close'); + } else + if ( tab == 'file' ) { + me.fireEvent('file:open'); + me.setTab(tab); + } + }, + + rendererComponentsEdit: function($host, mode) { + }, + + rendererComponentsCommon: function($host) { + var _injectComponent = function (id, cmp) { + Common.Utils.injectComponent($host.findById(id), cmp); + }; + }, + + rendererComponents: function (html, mode) { + var $host = $(html); + this.rendererComponentsCommon($host); + if (mode.isEdit) { + this.rendererComponentsEdit($host, mode); + } + + return $host; + }, + + onAppReady: function (config) { + var me = this; + me._isDocReady = true; + (new Promise( function(resolve, reject) { + resolve(); + })).then(function () { + if ( !config.isEdit ) return; + }); + }, + + createDelayedElementsCommon: function() { + }, + + createDelayedElementsEdit: function() { + if (!this.mode.isEdit) return; + + // this.updateMetricUnit(); + }, + + createDelayedElements: function () { + this.createDelayedElementsCommon(); + if (this.mode.isEdit) { + this.createDelayedElementsEdit(); + } + }, + + onToolbarAfterRender: function(toolbar) { + // DataView and pickers + }, + + setApi: function (api) { + this.api = api; + /** coauthoring begin **/ + // this.api.asc_registerCallback('asc_onCollaborativeChanges', _.bind(this.onCollaborativeChanges, this)); + this.api.asc_registerCallback('asc_onAuthParticipantsChanged', _.bind(this.onApiUsersChanged, this)); + this.api.asc_registerCallback('asc_onParticipantsChanged', _.bind(this.onApiUsersChanged, this)); + /** coauthoring end **/ + return this; + }, + + setMode: function (mode) { + if (mode.isDisconnected) { + this.lockToolbar(Common.enumLock.lostConnect, true); + if ( this.synchTooltip ) + this.synchTooltip.hide(); + if (!mode.enableDownload) + this.lockToolbar(Common.enumLock.cantPrint, true, {array: [this.btnPrint]}); + } else { + this.lockToolbar(Common.enumLock.cantPrint, !mode.canPrint, {array: [this.btnPrint]}); + !mode.canPrint && this.btnPrint.hide(); + } + + this.mode = mode; + }, + + /** coauthoring begin **/ + onCollaborativeChanges: function () { + if (!this.mode.isEdit || Common.Utils.InternalSettings.get("ve-settings-coauthmode")) return; + + if (this._state.hasCollaborativeChanges) return; + if (!this.btnCollabChanges.rendered || this._state.previewmode) { + this.needShowSynchTip = true; + return; + } + + this._state.hasCollaborativeChanges = true; + this.btnCollabChanges.cmpEl.addClass('notify'); + if (this.showSynchTip) { + this.btnCollabChanges.updateHint(''); + if (this.synchTooltip === undefined) + this.createSynchTip(); + + this.synchTooltip.show(); + } else { + this.btnCollabChanges.updateHint(this.tipSynchronize + Common.Utils.String.platformKey('Ctrl+S')); + } + + this.btnSave.setDisabled(!this.mode.isEdit && this.mode.canSaveToFile); + Common.Gateway.collaborativeChanges(); + }, + + createSynchTip: function () { + var direction = Common.UI.isRTL() ? 'left' : 'right'; + this.synchTooltip = new Common.UI.SynchronizeTip({ + extCls: (this.mode.compactHeader) ? undefined : 'inc-index', + placement: this.mode.isDesktopApp ? 'bottom-' + direction : direction + '-bottom', + target: this.btnCollabChanges.$el + }); + this.synchTooltip.on('dontshowclick', function () { + this.showSynchTip = false; + this.synchTooltip.hide(); + this.btnCollabChanges.updateHint(this.tipSynchronize + Common.Utils.String.platformKey('Ctrl+S')); + Common.localStorage.setItem("ve-hide-synch", 1); + }, this); + this.synchTooltip.on('closeclick', function () { + this.synchTooltip.hide(); + this.btnCollabChanges.updateHint(this.tipSynchronize + Common.Utils.String.platformKey('Ctrl+S')); + }, this); + }, + + synchronizeChanges: function () { + if (this.btnCollabChanges.rendered) { + var me = this; + + if ( me.btnCollabChanges.cmpEl.hasClass('notify') ) { + me.btnCollabChanges.cmpEl.removeClass('notify'); + if (this.synchTooltip) + this.synchTooltip.hide(); + this.btnCollabChanges.updateHint(this.btnSaveTip); + this.btnSave.setDisabled(!me.mode.forcesave && !me.mode.canSaveDocumentToBinary); + + this._state.hasCollaborativeChanges = false; + } + } + }, + + onApiUsersChanged: function (users) { + var editusers = []; + _.each(users, function (item) { + if (!item.asc_getView()) + editusers.push(item); + }); + + var length = _.size(editusers); + var cls = (length > 1) ? 'btn-save-coauth' : 'btn-save'; + if (cls !== this.btnSaveCls && this.btnCollabChanges.rendered) { + this.btnSaveTip = ((length > 1) ? this.tipSaveCoauth : this.tipSave ) + Common.Utils.String.platformKey('Ctrl+S'); + this.btnCollabChanges.updateHint(this.btnSaveTip); + this.btnCollabChanges.changeIcon({next: cls, curr: this.btnSaveCls}); + this.btnSaveCls = cls; + } + }, + + onDesktopWindow: function() { + if (this.synchTooltip && this.synchTooltip.isVisible()) { + this.synchTooltip.show(); // change position for visible tip + } + }, + /** coauthoring end **/ + + lockToolbar: function (causes, lock, opts) { + Common.Utils.lockControls(causes, lock, opts, this.lockControls); + } + } + })(), VE.Views.Toolbar || {})); +}); diff --git a/apps/visioeditor/main/app/view/ViewTab.js b/apps/visioeditor/main/app/view/ViewTab.js new file mode 100644 index 0000000000..d81e224781 --- /dev/null +++ b/apps/visioeditor/main/app/view/ViewTab.js @@ -0,0 +1,385 @@ +/* + * (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 + * + */ +/** + * ViewTab.js + * + * Created on 11/07/24 + * + */ + +define([ + 'common/main/lib/util/utils', + 'common/main/lib/component/BaseView', + 'common/main/lib/component/Layout' +], function () { + 'use strict'; + + VE.Views.ViewTab = Common.UI.BaseView.extend(_.extend((function(){ + var template = + '
    ' + + '
    ' + + '
    ' + + '' + + '
    ' + + '
    ' + + '' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '' + + '
    ' + + '
    ' + + '' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '' + + '
    ' + + '
    ' + + '' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    '; + return { + options: {}, + + setEvents: function () { + var me = this; + me.btnFitToSlide && me.btnFitToSlide.on('click', function () { + me.fireEvent('zoom:toslide', [me.btnFitToSlide]); + }); + me.btnFitToWidth && me.btnFitToWidth.on('click', function () { + me.fireEvent('zoom:towidth', [me.btnFitToWidth]); + }); + me.chToolbar && me.chToolbar.on('change', _.bind(function(checkbox, state) { + me.fireEvent('toolbar:setcompact', [me.chToolbar, state !== 'checked']); + }, me)); + me.chStatusbar && me.chStatusbar.on('change', _.bind(function (checkbox, state) { + me.fireEvent('statusbar:hide', [me.chStatusbar, state !== 'checked']); + }, me)); + me.cmbZoom.on('selected', function (combo, record) { + me.fireEvent('zoom:selected', [combo, record]); + }).on('changed:before', function (combo, record) { + me.fireEvent('zoom:changedbefore', [true, combo, record]); + }).on('changed:after', function (combo, record) { + me.fireEvent('zoom:changedafter', [false, combo, record]); + }).on('combo:blur', function () { + me.fireEvent('editcomplete', me); + }).on('combo:focusin', _.bind(this.onComboOpen, this, false)) + .on('show:after', _.bind(this.onComboOpen, this, true)); + + me.chLeftMenu.on('change', _.bind(function (checkbox, state) { + me.fireEvent('leftmenu:hide', [me.chLeftMenu, state === 'checked']); + }, me)); + }, + + initialize: function (options) { + Common.UI.BaseView.prototype.initialize.call(this); + this.toolbar = options.toolbar; + this.appConfig = options.mode; + var _set = Common.enumLock; + + this.lockedControls = []; + + var me = this; + this.cmbZoom = new Common.UI.ComboBox({ + cls: 'input-group-nr', + menuStyle: 'min-width: 55px;', + editable: true, + lock: [_set.disableOnStart], + data: [ + { displayValue: "50%", value: 50 }, + { displayValue: "75%", value: 75 }, + { displayValue: "100%", value: 100 }, + { displayValue: "125%", value: 125 }, + { displayValue: "150%", value: 150 }, + { displayValue: "175%", value: 175 }, + { displayValue: "200%", value: 200 }, + { displayValue: "300%", value: 300 }, + { displayValue: "400%", value: 400 }, + { displayValue: "500%", value: 500 } + ], + dataHint : '1', + dataHintDirection: 'top', + dataHintOffset: 'small' + }); + this.cmbZoom.setValue(100); + this.lockedControls.push(this.cmbZoom); + + this.btnFitToSlide = new Common.UI.Button({ + cls: 'btn-toolbar', + iconCls: 'toolbar__icon btn-ic-zoomtoslide', + caption: this.textFitToSlide, + lock: [_set.disableOnStart], + toggleGroup: 'view-zoom', + enableToggle: true, + dataHint: '1', + dataHintDirection: 'left', + dataHintOffset: 'medium' + }); + this.lockedControls.push(this.btnFitToSlide); + + this.btnFitToWidth = new Common.UI.Button({ + cls: 'btn-toolbar', + iconCls: 'toolbar__icon btn-ic-zoomtowidth', + caption: this.textFitToWidth, + lock: [_set.disableOnStart], + toggleGroup: 'view-zoom', + enableToggle: true, + dataHint: '1', + dataHintDirection: 'left', + dataHintOffset: 'medium' + }); + this.lockedControls.push(this.btnFitToWidth); + + this.btnInterfaceTheme = new Common.UI.Button({ + cls: 'btn-toolbar x-huge icon-top', + iconCls: 'toolbar__icon btn-day', + caption: this.textInterfaceTheme, + lock: [_set.disableOnStart], + menu: true, + dataHint: '1', + dataHintDirection: 'bottom', + dataHintOffset: 'small', + action: 'interface-theme' + }); + this.lockedControls.push(this.btnInterfaceTheme); + + this.chStatusbar = new Common.UI.CheckBox({ + labelText: this.textStatusBar, + value: !Common.localStorage.getBool("ve-hidden-status"), + lock: [_set.disableOnStart], + dataHint: '1', + dataHintDirection: 'left', + dataHintOffset: 'small' + }); + this.lockedControls.push(this.chStatusbar); + + this.chToolbar = new Common.UI.CheckBox({ + labelText: this.textAlwaysShowToolbar, + value: !options.compactToolbar, + lock: [_set.disableOnStart], + dataHint : '1', + dataHintDirection: 'left', + dataHintOffset: 'small' + }); + this.lockedControls.push(this.chToolbar); + + this.chLeftMenu = new Common.UI.CheckBox({ + lock: [_set.disableOnStart], + labelText: !Common.UI.isRTL() ? this.textLeftMenu : this.textRightMenu, + dataHint : '1', + dataHintDirection: 'left', + dataHintOffset: 'small' + }); + this.lockedControls.push(this.chLeftMenu); + Common.UI.LayoutManager.addControls(this.lockedControls); + Common.NotificationCenter.on('app:ready', this.onAppReady.bind(this)); + }, + + render: function (el) { + if ( el ) el.html( this.getPanel() ); + + return this; + }, + + getPanel: function () { + this.$el = $(_.template(template)( {} )); + var $host = this.$el; + + this.cmbZoom.render($host.find('#slot-field-zoom')); + $host.find('#slot-lbl-zoom').text(this.textZoom); + this.btnFitToSlide.render($host.find('#slot-btn-fts')); + this.btnFitToWidth.render($host.find('#slot-btn-ftw')); + this.btnInterfaceTheme.render($host.find('#slot-btn-interface-theme')); + this.chStatusbar.render($host.find('#slot-chk-statusbar')); + this.chToolbar.render($host.find('#slot-chk-toolbar')); + this.chLeftMenu.render($host.find('#slot-chk-leftmenu')); + return this.$el; + }, + + onAppReady: function (config) { + var me = this; + (new Promise(function (accept, reject) { + accept(); + })).then(function () { + me.btnFitToSlide.updateHint(me.tipFitToSlide); + me.btnFitToWidth.updateHint(me.tipFitToWidth); + me.btnInterfaceTheme.updateHint(me.tipInterfaceTheme); + if (!Common.UI.Themes.available()) { + me.btnInterfaceTheme.$el.closest('.group').remove(); + me.$el.find('.separator-theme').remove(); + } + + var emptyGroup = []; + if (config.canBrandingExt && config.customization && config.customization.statusBar === false || !Common.UI.LayoutManager.isElementVisible('statusBar')) { + emptyGroup.push(me.chStatusbar.$el.closest('.elset')); + me.chStatusbar.$el.remove(); + } + + if (config.canBrandingExt && config.customization && config.customization.leftMenu === false || !Common.UI.LayoutManager.isElementVisible('leftMenu')) { + emptyGroup.push(me.chLeftMenu.$el.closest('.elset')); + me.chLeftMenu.$el.remove(); + } else if (emptyGroup.length>0) { + emptyGroup.push(me.chLeftMenu.$el.closest('.elset')); + emptyGroup.shift().append(me.chLeftMenu.$el[0]); + } + if (emptyGroup.length>1) { // remove empty group + emptyGroup[emptyGroup.length-1].closest('.group').remove(); + } + + if (Common.UI.Themes.available()) { + function _add_tab_styles() { + let btn = me.btnInterfaceTheme; + if ( typeof(btn.menu) === 'object' ) + btn.menu.addItem({caption: '--'}, true); + else + btn.setMenu(new Common.UI.Menu()); + let mni = new Common.UI.MenuItem({ + value: -1, + caption: me.textTabStyle, + menu: new Common.UI.Menu({ + menuAlign: 'tl-tr', + items: [ + {value: 'fill', caption: me.textFill, checkable: true, toggleGroup: 'tabstyle'}, + {value: 'line', caption: me.textLine, checkable: true, toggleGroup: 'tabstyle'} + ] + }) + }); + _.each(mni.menu.items, function(item){ + item.setChecked(Common.Utils.InternalSettings.get("settings-tab-style")===item.value, true); + }); + mni.menu.on('item:click', _.bind(function (menu, item) { + Common.UI.TabStyler.setStyle(item.value); + }, me)); + btn.menu.addItem(mni, true); + me.menuTabStyle = mni.menu; + } + function _fill_themes() { + let btn = this.btnInterfaceTheme; + if ( typeof(btn.menu) == 'object' ) btn.menu.removeAll(true); + else btn.setMenu(new Common.UI.Menu()); + + var currentTheme = Common.UI.Themes.currentThemeId() || Common.UI.Themes.defaultThemeId(), + idx = 0; + for (var t in Common.UI.Themes.map()) { + btn.menu.insertItem(idx++, { + value: t, + caption: Common.UI.Themes.get(t).text, + checked: t === currentTheme, + checkable: true, + toggleGroup: 'interface-theme' + }); + } + // Common.UI.FeaturesManager.canChange('tabStyle', true) && _add_tab_styles(); + } + + Common.NotificationCenter.on('uitheme:countchanged', _fill_themes.bind(me)); + _fill_themes.call(me); + + me.btnInterfaceTheme.menu && me.btnInterfaceTheme.menu.on('show:after', function() { + Common.UI.TooltipManager.closeTip('grayTheme'); + }); + if (me.btnInterfaceTheme.menu.getItemsLength(true)) { + me.btnInterfaceTheme.menu.on('item:click', _.bind(function (menu, item) { + var value = item.value; + Common.UI.Themes.setTheme(value); + }, me)); + } + } + + var value = Common.UI.LayoutManager.getInitValue('leftMenu'); + value = (value!==undefined) ? !value : false; + me.chLeftMenu.setValue(!Common.localStorage.getBool("ve-hidden-leftmenu", value)); + + me.setEvents(); + }); + }, + + show: function () { + Common.UI.BaseView.prototype.show.call(this); + this.fireEvent('show', this); + }, + + getButtons: function(type) { + if (type===undefined) + return this.lockedControls; + return []; + }, + + SetDisabled: function (state) { + this.lockedControls && this.lockedControls.forEach(function(button) { + if ( button ) { + button.setDisabled(state); + } + }, this); + }, + + onComboOpen: function (needfocus, combo, e, params) { + if (params && params.fromKeyDown) return; + _.delay(function() { + var input = $('input', combo.cmpEl).select(); + if (needfocus) input.focus(); + else if (!combo.isMenuOpen()) input.one('mouseup', function (e) { e.preventDefault(); }); + }, 10); + }, + + textZoom: 'Zoom', + textFitToSlide: 'Fit To Page', + textFitToWidth: 'Fit To Width', + textInterfaceTheme: 'Interface theme', + textStatusBar: 'Status Bar', + textAlwaysShowToolbar: 'Always show toolbar', + tipFitToSlide: 'Fit to page', + tipFitToWidth: 'Fit to width', + tipInterfaceTheme: 'Interface theme', + textLeftMenu: 'Left panel', + textTabStyle: 'Tab style', + textFill: 'Fill', + textLine: 'Line' + } + }()), VE.Views.ViewTab || {})); +}); \ No newline at end of file diff --git a/apps/visioeditor/main/app/view/Viewport.js b/apps/visioeditor/main/app/view/Viewport.js new file mode 100644 index 0000000000..b5d4d24fea --- /dev/null +++ b/apps/visioeditor/main/app/view/Viewport.js @@ -0,0 +1,150 @@ +/* + * (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 + * + */ +/** + * Viewport.js + * + * Viewport view + * + * Created on 11/07/24 + * + */ + +define([ + 'text!visioeditor/main/app/template/Viewport.template', + 'jquery', + 'underscore', + 'backbone', + 'common/main/lib/component/Layout' +], function (viewportTemplate, $, _, Backbone) { + 'use strict'; + + VE.Views.Viewport = Backbone.View.extend({ + el: '#viewport', + + // Compile our stats template + template: _.template(viewportTemplate), + + // Delegated events for creating new items, and clearing completed ones. + events: { + }, + + // Set innerHTML and get the references to the DOM elements + initialize: function() { + this._initEditing = true; + }, + + // Render layout + render: function() { + var el = $(this.el); + el.html(this.template({})); + + // Workaround Safari's scrolling problem + if (Common.Utils.isSafari) { + $('body').addClass('safari'); + $('body').mousewheel(function(e){ + e.preventDefault(); + e.stopPropagation(); + }); + } else if (Common.Utils.isChrome) { + $('body').addClass('chrome'); + } + + el.on('scroll', function () { el.scrollTop(0); }); + + var $container = $('#viewport-vbox-layout', el); + var items = $container.find(' > .layout-item'); + this.vlayout = new Common.UI.VBoxLayout({ + box: $container, + items: [{ + el: $container.find('> .layout-item#app-title').hide(), + alias: 'title', + height: Common.Utils.InternalSettings.get('document-title-height') + }, { + el: items[1], + alias: 'toolbar', + height: Common.localStorage.getBool('ve-compact-toolbar') ? + Common.Utils.InternalSettings.get('toolbar-height-compact') : Common.Utils.InternalSettings.get('toolbar-height-normal') + }, { + el: items[2], + stretch: true + }, { + el: items[3], + alias: 'statusbar', + height: Common.localStorage.getBool('ve-compact-statusbar', true) ? 25 : 50 + }] + }); + + $container = $('#viewport-hbox-layout', el); + items = $container.find(' > .layout-item'); + + let iarray = [{ + el: items[0], + rely: true, + alias: 'left', + resize: { + hidden: true, + autohide: false, + min: 300, + max: 600 + }}, { + el: items[1], + stretch: true + }]; + + if ( Common.UI.isRTL() ) { + iarray[0].resize.min = -600; + iarray[0].resize.max = -300; + [iarray[0], iarray[1]] = [iarray[1], iarray[0]]; + } + + this.hlayout = new Common.UI.HBoxLayout({ + box: $container, + items: iarray + }); + + return this; + }, + + setMode: function(mode) { + if (mode.isDisconnected) { + /** coauthoring begin **/ + if (_.isUndefined(this.mode)) + this.mode = {}; + + this.mode.canCoAuthoring = false; + /** coauthoring end **/ + } else { + this.mode = mode; + } + } + }); +}); \ No newline at end of file diff --git a/apps/visioeditor/main/app_dev.js b/apps/visioeditor/main/app_dev.js new file mode 100644 index 0000000000..eb7b6c2be9 --- /dev/null +++ b/apps/visioeditor/main/app_dev.js @@ -0,0 +1,193 @@ +/* + * (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 + * + */ +/** + * app.js + * + * Created on 11/07/24 + * + */ + +'use strict'; +var reqerr; +require.config({ + // The shim config allows us to configure dependencies for + // scripts that do not call define() to register a module + baseUrl: '../../', + paths: { + jquery : '../vendor/jquery/jquery', + underscore : '../vendor/underscore/underscore', + backbone : '../vendor/backbone/backbone', + text : '../vendor/requirejs-text/text', + perfectscrollbar: 'common/main/lib/mods/perfect-scrollbar', + jmousewheel : '../vendor/perfect-scrollbar/src/jquery.mousewheel', + xregexp : '../vendor/xregexp/xregexp-all-min', + socketio : '../vendor/socketio/socket.io.min', + api : 'api/documents/api', + core : 'common/main/lib/core/application', + notification : 'common/main/lib/core/NotificationCenter', + keymaster : 'common/main/lib/core/keymaster', + tip : 'common/main/lib/util/Tip', + localstorage : 'common/main/lib/util/LocalStorage', + analytics : 'common/Analytics', + gateway : 'common/Gateway', + locale : 'common/locale', + irregularstack : 'common/IrregularStack' + }, + + shim: { + backbone: { + deps: [ + 'underscore', + 'jquery' + ], + exports: 'Backbone' + }, + perfectscrollbar: { + deps: [ + 'jmousewheel' + ] + }, + notification: { + deps: [ + 'backbone' + ] + }, + core: { + deps: [ + 'backbone', + 'notification', + 'irregularstack' + ] + }, + gateway: { + deps: [ + 'jquery' + ] + }, + analytics: { + deps: [ + 'jquery' + ] + } + } +}); + +require([ + 'backbone', + 'underscore', + 'core', + 'analytics', + 'gateway', + 'locale', + 'socketio', +], function (Backbone, _, Core) { + if (Backbone.History && Backbone.History.started) + return; + Backbone.history.start(); + window._ = _; + + /** + * Application instance with VE namespace defined + */ + var app = new Backbone.Application({ + nameSpace: 'VE', + autoCreate: false, + controllers : [ + 'Viewport', + 'DocumentHolder', + 'Toolbar', + 'Statusbar', + 'LeftMenu', + 'Main', + 'ViewTab', + 'Search' + ,'Common.Controllers.Chat' + // ,'Common.Controllers.Comments' + ,'Common.Controllers.Plugins' + ] + }); + + Common.Locale.apply( + function() { + require([ + 'common/main/lib/mods/dropdown', + 'common/main/lib/mods/tooltip', + 'common/main/lib/util/LocalStorage', + 'common/main/lib/controller/Scaling', + 'common/main/lib/controller/Themes', + 'common/main/lib/controller/TabStyler', + 'common/main/lib/controller/Desktop', + 'visioeditor/main/app/controller/Viewport', + 'visioeditor/main/app/controller/DocumentHolder', + 'visioeditor/main/app/controller/Toolbar', + 'visioeditor/main/app/controller/Statusbar', + 'visioeditor/main/app/controller/LeftMenu', + 'visioeditor/main/app/controller/Main', + 'visioeditor/main/app/controller/ViewTab', + 'visioeditor/main/app/controller/Search', + 'common/main/lib/util/utils' + // 'common/main/lib/controller/Comments' + ,'common/main/lib/controller/Chat' + ,'common/main/lib/controller/Plugins' + ], function() { + app.postLaunchScripts = [ + 'common/main/lib/controller/ScreenReaderFocus', + 'common/main/lib/view/AdvancedSettingsWindow', + 'common/main/lib/view/DocumentAccessDialog', + 'common/main/lib/view/SaveAsDlg', + 'common/main/lib/view/CopyWarningDialog', + 'common/main/lib/view/TextInputDialog', + 'common/main/lib/view/SelectFileDlg', + 'common/main/lib/view/SearchDialog', + 'common/main/lib/view/RenameDialog', + 'common/main/lib/view/PluginDlg', + 'common/main/lib/view/PluginPanel', + 'common/main/lib/view/DocumentHolderExt', + 'common/main/lib/view/CustomizeQuickAccessDialog', + 'common/main/lib/view/PasswordDialog', + + 'visioeditor/main/app/view/FileMenuPanels', + 'visioeditor/main/app/view/DocumentHolderExt' + ]; + + window.compareVersions = true; + app.start(); + }); + } + ); +}, function(err) { + if (err.requireType == 'timeout' && !reqerr && window.requireTimeourError) { + reqerr = window.requireTimeourError(); + window.alert(reqerr); + window.location.reload(); + } +}); \ No newline at end of file diff --git a/apps/visioeditor/main/app_pack.js b/apps/visioeditor/main/app_pack.js new file mode 100644 index 0000000000..88f6a8ec45 --- /dev/null +++ b/apps/visioeditor/main/app_pack.js @@ -0,0 +1,21 @@ +require([ + 'common/main/lib/controller/ScreenReaderFocus', + 'common/main/lib/view/AdvancedSettingsWindow', + 'common/main/lib/view/DocumentAccessDialog', + 'common/main/lib/view/SaveAsDlg', + 'common/main/lib/view/CopyWarningDialog', + 'common/main/lib/view/SelectFileDlg', + 'common/main/lib/view/SearchDialog', + 'common/main/lib/view/RenameDialog', + 'common/main/lib/view/PluginDlg', + 'common/main/lib/view/PluginPanel', + 'common/main/lib/view/TextInputDialog', + 'common/main/lib/view/DocumentHolderExt', + 'common/main/lib/view/CustomizeQuickAccessDialog', + 'common/main/lib/view/PasswordDialog', + + 'visioeditor/main/app/view/FileMenuPanels', + 'visioeditor/main/app/view/DocumentHolderExt' +], function () { + Common.NotificationCenter.trigger('app-pack:loaded'); +}); diff --git a/apps/visioeditor/main/index.html b/apps/visioeditor/main/index.html new file mode 100644 index 0000000000..c7b9c73a03 --- /dev/null +++ b/apps/visioeditor/main/index.html @@ -0,0 +1,465 @@ + + + + ONLYOFFICE Visio Editor + + + + + + + + + + + + + + + + + +
    + + + +
    + +
    + + + + + +
    + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/visioeditor/main/index.html.deploy b/apps/visioeditor/main/index.html.deploy new file mode 100644 index 0000000000..ee5df244f7 --- /dev/null +++ b/apps/visioeditor/main/index.html.deploy @@ -0,0 +1,439 @@ + + + + ONLYOFFICE Visio Editor + + + + + + + + + + + + + + + + + +
    + + + +
    + +
    + + + + + + +
    + + + + + + \ No newline at end of file diff --git a/apps/visioeditor/main/index_loader.html b/apps/visioeditor/main/index_loader.html new file mode 100644 index 0000000000..39db52df4a --- /dev/null +++ b/apps/visioeditor/main/index_loader.html @@ -0,0 +1,301 @@ + + + + ONLYOFFICE Visio Editor + + + + + + + + + + + + + + + + + +
    + + + +
    + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/visioeditor/main/index_loader.html.deploy b/apps/visioeditor/main/index_loader.html.deploy new file mode 100644 index 0000000000..b13e37186f --- /dev/null +++ b/apps/visioeditor/main/index_loader.html.deploy @@ -0,0 +1,331 @@ + + + + ONLYOFFICE Visio Editor + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + + + + \ No newline at end of file diff --git a/apps/visioeditor/main/locale/en.json b/apps/visioeditor/main/locale/en.json new file mode 100644 index 0000000000..1f88298e54 --- /dev/null +++ b/apps/visioeditor/main/locale/en.json @@ -0,0 +1,483 @@ +{ + "Common.Controllers.Chat.notcriticalErrorTitle": "Warning", + "Common.Controllers.Desktop.hintBtnHome": "Show Main window", + "Common.Controllers.Desktop.itemCreateFromTemplate": "Create from template", + "Common.Controllers.Plugins.helpMoveMacros": "To start working with macros, switch to the View tab.", + "Common.Controllers.Plugins.helpMoveMacrosHeader": "The moved Macros button", + "Common.Controllers.Plugins.helpUseMacros": "Find the Macros button here", + "Common.Controllers.Plugins.helpUseMacrosHeader": "Updated access to macros", + "Common.Controllers.Plugins.textPluginsSuccessfullyInstalled": "Plugins are successfully installed. You can access all background plugins here.", + "Common.Controllers.Plugins.textPluginSuccessfullyInstalled": "{0} is successfully installed. You can access all background plugins here.", + "Common.Controllers.Plugins.textRunInstalledPlugins": "Run installed plugins", + "Common.Controllers.Plugins.textRunPlugin": "Run plugin", + "Common.Translation.textMoreButton": "More", + "Common.Translation.tipFileLocked": "Document is locked for editing. You can make changes and save it as local copy later.", + "Common.Translation.tipFileReadOnly": "The file is read-only. To keep your changes, save the file with a new name or in a different location.", + "Common.Translation.warnFileLocked": "You can't edit this file because it's being edited in another app.", + "Common.Translation.warnFileLockedBtnEdit": "Create a copy", + "Common.Translation.warnFileLockedBtnView": "Open for viewing", + "Common.UI.ButtonColored.textAutoColor": "Automatic", + "Common.UI.ButtonColored.textEyedropper": "Eyedropper", + "Common.UI.ButtonColored.textNewColor": "More colors", + "Common.UI.SearchBar.textFind": "Find", + "Common.UI.SearchBar.tipCloseSearch": "Close find", + "Common.UI.SearchBar.tipNextResult": "Next result", + "Common.UI.SearchBar.tipOpenAdvancedSettings": "Open advanced settings", + "Common.UI.SearchBar.tipPreviousResult": "Previous result", + "Common.UI.SearchDialog.textHighlight": "Highlight results", + "Common.UI.SearchDialog.textMatchCase": "Case sensitive", + "Common.UI.SearchDialog.textReplaceDef": "Enter the replacement text", + "Common.UI.SearchDialog.textSearchStart": "Enter your text here", + "Common.UI.SearchDialog.textTitle": "Find and replace", + "Common.UI.SearchDialog.textTitle2": "Find", + "Common.UI.SearchDialog.textWholeWords": "Whole words only", + "Common.UI.SearchDialog.txtBtnHideReplace": "Hide Replace", + "Common.UI.SearchDialog.txtBtnReplace": "Replace", + "Common.UI.SearchDialog.txtBtnReplaceAll": "Replace all", + "Common.UI.SynchronizeTip.textDontShow": "Don't show this message again", + "Common.UI.SynchronizeTip.textGotIt": "Got it", + "Common.UI.SynchronizeTip.textSynchronize": "The document has been changed by another user.
    Please click to save your changes and reload the updates.", + "Common.UI.Themes.txtThemeClassicLight": "Classic light", + "Common.UI.Themes.txtThemeContrastDark": "Contrast Dark", + "Common.UI.Themes.txtThemeDark": "Dark", + "Common.UI.Themes.txtThemeGray": "Gray", + "Common.UI.Themes.txtThemeLight": "Light", + "Common.UI.Themes.txtThemeSystem": "Same as system", + "Common.UI.Window.cancelButtonText": "Cancel", + "Common.UI.Window.closeButtonText": "Close", + "Common.UI.Window.noButtonText": "No", + "Common.UI.Window.okButtonText": "OK", + "Common.UI.Window.textConfirmation": "Confirmation", + "Common.UI.Window.textDontShow": "Don't show this message again", + "Common.UI.Window.textError": "Error", + "Common.UI.Window.textInformation": "Information", + "Common.UI.Window.textWarning": "Warning", + "Common.UI.Window.yesButtonText": "Yes", + "Common.Utils.Metric.txtCm": "cm", + "Common.Utils.Metric.txtPt": "pt", + "Common.Utils.String.textAlt": "Alt", + "Common.Utils.String.textComma": ",", + "Common.Utils.String.textCtrl": "Ctrl", + "Common.Utils.String.textShift": "Shift", + "Common.Views.About.txtAddress": "address: ", + "Common.Views.About.txtLicensee": "LICENSEE", + "Common.Views.About.txtLicensor": "LICENSOR", + "Common.Views.About.txtMail": "email: ", + "Common.Views.About.txtPoweredBy": "Powered by", + "Common.Views.About.txtTel": "tel.: ", + "Common.Views.About.txtVersion": "Version ", + "Common.Views.Chat.textChat": "Chat", + "Common.Views.Chat.textClosePanel": "Close chat", + "Common.Views.Chat.textEnterMessage": "Enter your message here", + "Common.Views.Chat.textSend": "Send", + "Common.Views.Comments.mniAuthorAsc": "Author A to Z", + "Common.Views.Comments.mniAuthorDesc": "Author Z to A", + "Common.Views.Comments.mniDateAsc": "Oldest", + "Common.Views.Comments.mniDateDesc": "Newest", + "Common.Views.Comments.mniFilterGroups": "Filter by Group", + "Common.Views.Comments.mniPositionAsc": "From top", + "Common.Views.Comments.mniPositionDesc": "From bottom", + "Common.Views.Comments.textAdd": "Add", + "Common.Views.Comments.textAddComment": "Add Comment", + "Common.Views.Comments.textAddCommentToDoc": "Add comment to document", + "Common.Views.Comments.textAddReply": "Add reply", + "Common.Views.Comments.textAll": "All", + "Common.Views.Comments.textAnonym": "Guest", + "Common.Views.Comments.textCancel": "Cancel", + "Common.Views.Comments.textClose": "Close", + "Common.Views.Comments.textClosePanel": "Close comments", + "Common.Views.Comments.textComment": "Comment", + "Common.Views.Comments.textComments": "Comments", + "Common.Views.Comments.textEdit": "OK", + "Common.Views.Comments.textEnterCommentHint": "Enter your comment here", + "Common.Views.Comments.textHintAddComment": "Add comment", + "Common.Views.Comments.textOpenAgain": "Open again", + "Common.Views.Comments.textReply": "Reply", + "Common.Views.Comments.textResolve": "Resolve", + "Common.Views.Comments.textResolved": "Resolved", + "Common.Views.Comments.textSort": "Sort comments", + "Common.Views.Comments.textSortFilter": "Sort and filter comments", + "Common.Views.Comments.textSortFilterMore": "Sort, filter and more", + "Common.Views.Comments.textSortMore": "Sort and more", + "Common.Views.Comments.textViewResolved": "You have no permission to reopen the comment", + "Common.Views.Comments.txtEmpty": "There are no comments in the document.", + "Common.Views.CopyWarningDialog.textDontShow": "Don't show this message again", + "Common.Views.CopyWarningDialog.textMsg": "Copy, cut and paste actions using the editor toolbar buttons and context menu actions will be performed within this editor tab only.

    To copy or paste to or from applications outside the editor tab use the following keyboard combinations:", + "Common.Views.CopyWarningDialog.textTitle": "Copy, cut and paste actions", + "Common.Views.CopyWarningDialog.textToCopy": "for Copy", + "Common.Views.CopyWarningDialog.textToCut": "for Cut", + "Common.Views.CopyWarningDialog.textToPaste": "for Paste", + "Common.Views.DocumentAccessDialog.textLoading": "Loading...", + "Common.Views.DocumentAccessDialog.textTitle": "Sharing settings", + "Common.Views.Header.ariaQuickAccessToolbar": "Quick access toolbar", + "Common.Views.Header.labelCoUsersDescr": "Users who are editing the file:", + "Common.Views.Header.textAddFavorite": "Mark as favorite", + "Common.Views.Header.textAdvSettings": "Advanced settings", + "Common.Views.Header.textAnnotateDesc": "Fill forms or annotate", + "Common.Views.Header.textBack": "Open file location", + "Common.Views.Header.textClose": "Close file", + "Common.Views.Header.textComment": "Commenting", + "Common.Views.Header.textCommentDesc": "All changes will be saved to the file. Real time collaboration", + "Common.Views.Header.textCompactView": "Hide Toolbar", + "Common.Views.Header.textDownload": "Download", + "Common.Views.Header.textHideLines": "Hide Rulers", + "Common.Views.Header.textHideStatusBar": "Hide Status Bar", + "Common.Views.Header.textPrint": "Print", + "Common.Views.Header.textReadOnly": "Read only", + "Common.Views.Header.textRemoveFavorite": "Remove from Favorites", + "Common.Views.Header.textShare": "Share", + "Common.Views.Header.textZoom": "Zoom", + "Common.Views.Header.tipAccessRights": "Manage document access rights", + "Common.Views.Header.tipCustomizeQuickAccessToolbar": "Customize Quick Access Toolbar", + "Common.Views.Header.tipDownload": "Download file", + "Common.Views.Header.tipGoEdit": "Edit current file", + "Common.Views.Header.tipPrint": "Print file", + "Common.Views.Header.tipPrintQuick": "Quick print", + "Common.Views.Header.tipRedo": "Redo", + "Common.Views.Header.tipSave": "Save", + "Common.Views.Header.tipSearch": "Find", + "Common.Views.Header.tipUndo": "Undo", + "Common.Views.Header.tipUsers": "View users", + "Common.Views.Header.tipViewSettings": "View settings", + "Common.Views.Header.tipViewUsers": "View users and manage document access rights", + "Common.Views.Header.txtAccessRights": "Change access rights", + "Common.Views.Header.txtRename": "Rename", + "Common.Views.OpenDialog.closeButtonText": "Close file", + "Common.Views.OpenDialog.txtEncoding": "Encoding ", + "Common.Views.OpenDialog.txtIncorrectPwd": "Password is incorrect.", + "Common.Views.OpenDialog.txtOpenFile": "Enter a password to open the file", + "Common.Views.OpenDialog.txtPassword": "Password", + "Common.Views.OpenDialog.txtPreview": "Preview", + "Common.Views.OpenDialog.txtProtected": "Once you enter the password and open the file, the current password to the file will be reset.", + "Common.Views.OpenDialog.txtTitle": "Choose %1 options", + "Common.Views.OpenDialog.txtTitleProtected": "Protected file", + "Common.Views.PasswordDialog.txtDescription": "Set a password to protect this document", + "Common.Views.PasswordDialog.txtIncorrectPwd": "Confirmation password is not identical", + "Common.Views.PasswordDialog.txtPassword": "Password", + "Common.Views.PasswordDialog.txtRepeat": "Repeat password", + "Common.Views.PasswordDialog.txtTitle": "Set password", + "Common.Views.PasswordDialog.txtWarning": "Warning: If you lose or forget the password, it cannot be recovered. Please keep it in a safe place.", + "Common.Views.PluginDlg.textLoading": "Loading", + "Common.Views.PluginPanel.textClosePanel": "Close plugin", + "Common.Views.PluginPanel.textLoading": "Loading", + "Common.Views.Plugins.groupCaption": "Plugins", + "Common.Views.Plugins.strPlugins": "Plugins", + "Common.Views.Plugins.textBackgroundPlugins": "Background plugins", + "Common.Views.Plugins.textClosePanel": "Close plugin", + "Common.Views.Plugins.textLoading": "Loading", + "Common.Views.Plugins.textSettings": "Settings", + "Common.Views.Plugins.textStart": "Start", + "Common.Views.Plugins.textStop": "Stop", + "Common.Views.Plugins.textTheListOfBackgroundPlugins": "The list of background plugins", + "Common.Views.RecentFiles.txtOpenRecent": "Open Recent", + "Common.Views.RenameDialog.textName": "File name", + "Common.Views.RenameDialog.txtInvalidName": "The file name cannot contain any of the following characters: ", + "Common.Views.SaveAsDlg.textLoading": "Loading", + "Common.Views.SaveAsDlg.textTitle": "Folder for save", + "Common.Views.SearchPanel.textCaseSensitive": "Case sensitive", + "Common.Views.SearchPanel.textCloseSearch": "Close find", + "Common.Views.SearchPanel.textContentChanged": "Document changed.", + "Common.Views.SearchPanel.textFind": "Find", + "Common.Views.SearchPanel.textFindAndReplace": "Find and replace", + "Common.Views.SearchPanel.textItemsSuccessfullyReplaced": "{0} items successfully replaced.", + "Common.Views.SearchPanel.textMatchUsingRegExp": "Match using regular expressions", + "Common.Views.SearchPanel.textNoMatches": "No matches", + "Common.Views.SearchPanel.textNoSearchResults": "No search results", + "Common.Views.SearchPanel.textPartOfItemsNotReplaced": "{0}/{1} items replaced. Remaining {2} items are locked by other users.", + "Common.Views.SearchPanel.textReplace": "Replace", + "Common.Views.SearchPanel.textReplaceAll": "Replace All", + "Common.Views.SearchPanel.textReplaceWith": "Replace with", + "Common.Views.SearchPanel.textSearchAgain": "{0}Perform new search{1} for accurate results.", + "Common.Views.SearchPanel.textSearchHasStopped": "Search has stopped", + "Common.Views.SearchPanel.textSearchResults": "Search results: {0}/{1}", + "Common.Views.SearchPanel.textSearchResultsTable": "Search results", + "Common.Views.SearchPanel.textTooManyResults": "There are too many results to show here", + "Common.Views.SearchPanel.textWholeWords": "Whole words only", + "Common.Views.SearchPanel.tipNextResult": "Next result", + "Common.Views.SearchPanel.tipPreviousResult": "Previous result", + "Common.Views.SelectFileDlg.textLoading": "Loading", + "Common.Views.SelectFileDlg.textTitle": "Select data source", + "Common.Views.UserNameDialog.textDontShow": "Don't ask me again", + "Common.Views.UserNameDialog.textLabel": "Label:", + "Common.Views.UserNameDialog.textLabelError": "Label must not be empty.", + "VE.Controllers.LeftMenu.leavePageText": "All unsaved changes in this document will be lost.
    Click \"Cancel\" then \"Save\" to save them. Click \"OK\" to discard all the unsaved changes.", + "VE.Controllers.LeftMenu.newDocumentTitle": "Unnamed document", + "VE.Controllers.LeftMenu.notcriticalErrorTitle": "Warning", + "VE.Controllers.LeftMenu.requestEditRightsText": "Requesting editing rights...", + "VE.Controllers.LeftMenu.textNoTextFound": "The data you have been searching for could not be found. Please adjust your search options.", + "VE.Controllers.LeftMenu.textSelectPath": "Enter a new name for saving the file copy", + "VE.Controllers.LeftMenu.txtCompatible": "The document will be saved to the new format. It will allow to use all the editor features, but might affect the document layout.
    Use the 'Compatibility' option of the advanced settings if you want to make the files compatible with older MS Word versions.", + "VE.Controllers.LeftMenu.txtUntitled": "Untitled", + "VE.Controllers.Main.applyChangesTextText": "Loading the changes...", + "VE.Controllers.Main.applyChangesTitleText": "Loading the changes", + "VE.Controllers.Main.convertationTimeoutText": "Conversion timeout exceeded.", + "VE.Controllers.Main.criticalErrorExtText": "Press \"OK\" to return to document list.", + "VE.Controllers.Main.criticalErrorTitle": "Error", + "VE.Controllers.Main.downloadErrorText": "Download failed.", + "VE.Controllers.Main.downloadMergeText": "Downloading...", + "VE.Controllers.Main.downloadMergeTitle": "Downloading", + "VE.Controllers.Main.downloadTextText": "Downloading document...", + "VE.Controllers.Main.downloadTitleText": "Downloading Document", + "VE.Controllers.Main.errorAccessDeny": "You are trying to perform an action you do not have rights for.
    Please contact your Document Server administrator.", + "VE.Controllers.Main.errorBadImageUrl": "Image URL is incorrect", + "VE.Controllers.Main.errorCannotPasteImg": "We can't paste this image from the Clipboard, but you can save it to your device and \ninsert it from there, or you can copy the image without text and paste it into the document.", + "VE.Controllers.Main.errorCoAuthoringDisconnect": "Server connection lost. The document cannot be edited right now.", + "VE.Controllers.Main.errorConnectToServer": "The document could not be saved. Please check connection settings or contact your administrator.
    When you click the 'OK' button, you will be prompted to download the document.", + "VE.Controllers.Main.errorDatabaseConnection": "External error.
    Database connection error. Please contact support in case the error persists.", + "VE.Controllers.Main.errorDataEncrypted": "Encrypted changes have been received, they cannot be deciphered.", + "VE.Controllers.Main.errorDataRange": "Incorrect data range.", + "VE.Controllers.Main.errorDefaultMessage": "Error code: %1", + "VE.Controllers.Main.errorDirectUrl": "Please verify the link to the document.
    This link must be a direct link to the file for downloading.", + "VE.Controllers.Main.errorEditingDownloadas": "An error occurred during the work with the document.
    Use the 'Download as' option to save the file backup copy to a drive.", + "VE.Controllers.Main.errorEditingSaveas": "An error occurred during the work with the document.
    Use the 'Save as...' option to save the file backup copy to a drive.", + "VE.Controllers.Main.errorEmailClient": "No email client could be found.", + "VE.Controllers.Main.errorFilePassProtect": "The file is password protected and cannot be opened.", + "VE.Controllers.Main.errorFileSizeExceed": "The file size exceeds the limitation set for your server.
    Please contact your Document Server administrator for details.", + "VE.Controllers.Main.errorForceSave": "An error occurred while saving the file. Please use the 'Download as' option to save the file to a drive or try again later.", + "VE.Controllers.Main.errorInconsistentExt": "An error has occurred while opening the file.
    The file content does not match the file extension.", + "VE.Controllers.Main.errorInconsistentExtDocx": "An error has occurred while opening the file.
    The file content corresponds to text documents (e.g. docx), but the file has the inconsistent extension: %1.", + "VE.Controllers.Main.errorInconsistentExtPdf": "An error has occurred while opening the file.
    The file content corresponds to one of the following formats: pdf/djvu/xps/oxps, but the file has the inconsistent extension: %1.", + "VE.Controllers.Main.errorInconsistentExtPptx": "An error has occurred while opening the file.
    The file content corresponds to presentations (e.g. pptx), but the file has the inconsistent extension: %1.", + "VE.Controllers.Main.errorInconsistentExtXlsx": "An error has occurred while opening the file.
    The file content corresponds to spreadsheets (e.g. xlsx), but the file has the inconsistent extension: %1.", + "VE.Controllers.Main.errorKeyEncrypt": "Unknown key descriptor", + "VE.Controllers.Main.errorKeyExpire": "Key descriptor expired", + "VE.Controllers.Main.errorLoadingFont": "Fonts are not loaded.
    Please contact your Document Server administrator.", + "VE.Controllers.Main.errorPasswordIsNotCorrect": "The password you supplied is not correct.
    Verify that the CAPS LOCK key is off and be sure to use the correct capitalization.", + "VE.Controllers.Main.errorProcessSaveResult": "Saving failed.", + "VE.Controllers.Main.errorServerVersion": "The editor version has been updated. The page will be reloaded to apply the changes.", + "VE.Controllers.Main.errorSessionAbsolute": "The document editing session has expired. Please reload the page.", + "VE.Controllers.Main.errorSessionIdle": "The document has not been edited for quite a long time. Please reload the page.", + "VE.Controllers.Main.errorSessionToken": "The connection to the server has been interrupted. Please reload the page.", + "VE.Controllers.Main.errorSetPassword": "Password could not be set.", + "VE.Controllers.Main.errorToken": "The document security token is not correctly formed.
    Please contact your Document Server administrator.", + "VE.Controllers.Main.errorTokenExpire": "The document security token has expired.
    Please contact your Document Server administrator.", + "VE.Controllers.Main.errorUpdateVersion": "The file version has been changed. The page will be reloaded.", + "VE.Controllers.Main.errorUpdateVersionOnDisconnect": "Connection has been restored, and the file version has been changed.
    Before you can continue working, you need to download the file or copy its content to make sure nothing is lost, and then reload this page.", + "VE.Controllers.Main.errorUserDrop": "The file cannot be accessed right now.", + "VE.Controllers.Main.errorUsersExceed": "The number of users allowed by the pricing plan was exceeded", + "VE.Controllers.Main.errorViewerDisconnect": "Connection is lost. You can still view the document,
    but will not be able to download or print it until the connection is restored and page is reloaded.", + "VE.Controllers.Main.leavePageText": "You have unsaved changes in this document. Click \"Stay on This Page\", then \"Save\" to save them. Click \"Leave This Page\" to discard all the unsaved changes.", + "VE.Controllers.Main.leavePageTextOnClose": "All unsaved changes in this document will be lost.
    Click \"Cancel\" then \"Save\" to save them. Click \"OK\" to discard all the unsaved changes.", + "VE.Controllers.Main.loadFontsTextText": "Loading data...", + "VE.Controllers.Main.loadFontsTitleText": "Loading data", + "VE.Controllers.Main.loadFontTextText": "Loading data...", + "VE.Controllers.Main.loadFontTitleText": "Loading data", + "VE.Controllers.Main.loadImagesTextText": "Loading images...", + "VE.Controllers.Main.loadImagesTitleText": "Loading Images", + "VE.Controllers.Main.loadImageTextText": "Loading image...", + "VE.Controllers.Main.loadImageTitleText": "Loading Image", + "VE.Controllers.Main.loadingDocumentTextText": "Loading document...", + "VE.Controllers.Main.loadingDocumentTitleText": "Loading document", + "VE.Controllers.Main.notcriticalErrorTitle": "Warning", + "VE.Controllers.Main.openErrorText": "An error has occurred while opening the file.", + "VE.Controllers.Main.openTextText": "Opening document...", + "VE.Controllers.Main.openTitleText": "Opening Document", + "VE.Controllers.Main.printTextText": "Printing document...", + "VE.Controllers.Main.printTitleText": "Printing Document", + "VE.Controllers.Main.reloadButtonText": "Reload Page", + "VE.Controllers.Main.requestEditFailedMessageText": "Someone is editing this document right now. Please try again later.", + "VE.Controllers.Main.requestEditFailedTitleText": "Access denied", + "VE.Controllers.Main.saveErrorText": "An error has occurred while saving the file.", + "VE.Controllers.Main.saveErrorTextDesktop": "This file cannot be saved or created.
    Possible reasons are:
    1. The file is read-only.
    2. The file is being edited by other users.
    3. The disk is full or corrupted.", + "VE.Controllers.Main.saveTextText": "Saving document...", + "VE.Controllers.Main.saveTitleText": "Saving Document", + "VE.Controllers.Main.scriptLoadError": "The connection is too slow, some of the components could not be loaded. Please reload the page.", + "VE.Controllers.Main.textAnonymous": "Anonymous", + "VE.Controllers.Main.textAnyone": "Anyone", + "VE.Controllers.Main.textBuyNow": "Visit website", + "VE.Controllers.Main.textChangesSaved": "All changes saved", + "VE.Controllers.Main.textClose": "Close", + "VE.Controllers.Main.textCloseTip": "Click to close the tip", + "VE.Controllers.Main.textContactUs": "Contact sales", + "VE.Controllers.Main.textContinue": "Continue", + "VE.Controllers.Main.textCustomLoader": "Please note that according to the terms of the license you are not entitled to change the loader.
    Please contact our Sales Department to get a quote.", + "VE.Controllers.Main.textDisconnect": "Connection is lost", + "VE.Controllers.Main.textGuest": "Guest", + "VE.Controllers.Main.textLearnMore": "Learn more", + "VE.Controllers.Main.textLoadingDocument": "Loading document", + "VE.Controllers.Main.textLongName": "Enter a name that is less than 128 characters.", + "VE.Controllers.Main.textNoLicenseTitle": "License limit reached", + "VE.Controllers.Main.textPaidFeature": "Paid feature", + "VE.Controllers.Main.textReconnect": "Connection is restored", + "VE.Controllers.Main.textRemember": "Remember my choice for all files", + "VE.Controllers.Main.textRenameError": "User name must not be empty.", + "VE.Controllers.Main.textRenameLabel": "Enter a name to be used for collaboration", + "VE.Controllers.Main.textShape": "Shape", + "VE.Controllers.Main.textStrict": "Strict mode", + "VE.Controllers.Main.textText": "Text", + "VE.Controllers.Main.textTryQuickPrint": "You have selected Quick print: the entire document will be printed on the last selected or default printer.
    Do you want to continue?", + "VE.Controllers.Main.textTryUndoRedo": "The Undo/Redo functions are disabled for the Fast co-editing mode.
    Click the 'Strict mode' button to switch to the Strict co-editing mode to edit the file without other users interference and send your changes only after you save them. You can switch between the co-editing modes using the editor Advanced settings.", + "VE.Controllers.Main.textTryUndoRedoWarn": "The Undo/Redo functions are disabled for the Fast co-editing mode.", + "VE.Controllers.Main.textUndo": "Undo", + "VE.Controllers.Main.titleLicenseExp": "License expired", + "VE.Controllers.Main.titleLicenseNotActive": "License not active", + "VE.Controllers.Main.titleServerVersion": "Editor updated", + "VE.Controllers.Main.titleUpdateVersion": "Version changed", + "VE.Controllers.Main.txtSaveCopyAsComplete": "The file copy was successfully saved", + "VE.Controllers.Main.txtSecurityWarningLink": "This document is trying to connect to {0}.
    If you trust this site, press \"OK\" while holding down the ctrl key.", + "VE.Controllers.Main.txtSecurityWarningOpenFile": "This document is trying to open file dialog, press \"OK\" to open.", + "VE.Controllers.Main.unknownErrorText": "Unknown error.", + "VE.Controllers.Main.unsupportedBrowserErrorText": "Your browser is not supported.", + "VE.Controllers.Main.uploadDocExtMessage": "Unknown document format.", + "VE.Controllers.Main.uploadDocFileCountMessage": "No documents uploaded.", + "VE.Controllers.Main.uploadDocSizeMessage": "Maximum document size limit exceeded.", + "VE.Controllers.Main.uploadImageExtMessage": "Unknown image format.", + "VE.Controllers.Main.uploadImageFileCountMessage": "No images uploaded.", + "VE.Controllers.Main.uploadImageSizeMessage": "The image is too big. The maximum size is 25 MB.", + "VE.Controllers.Main.uploadImageTextText": "Uploading image...", + "VE.Controllers.Main.uploadImageTitleText": "Uploading Image", + "VE.Controllers.Main.waitText": "Please, wait...", + "VE.Controllers.Main.warnBrowserIE9": "The application has low capabilities on IE9. Use IE10 or higher", + "VE.Controllers.Main.warnBrowserZoom": "Your browser current zoom setting is not fully supported. Please reset to the default zoom by pressing Ctrl+0.", + "VE.Controllers.Main.warnLicenseAnonymous": "Access denied for anonymous users.
    This document will be opened for viewing only.", + "VE.Controllers.Main.warnLicenseBefore": "License not active.
    Please contact your administrator.", + "VE.Controllers.Main.warnLicenseExceeded": "You've reached the limit for simultaneous connections to %1 editors. This document will be opened for viewing only.
    Contact your administrator to learn more.", + "VE.Controllers.Main.warnLicenseExp": "Your license has expired.
    Please update your license and refresh the page.", + "VE.Controllers.Main.warnLicenseLimitedNoAccess": "License expired.
    You have no access to document editing functionality.
    Please contact your administrator.", + "VE.Controllers.Main.warnLicenseLimitedRenewed": "License needs to be renewed.
    You have a limited access to document editing functionality.
    Please contact your administrator to get full access", + "VE.Controllers.Main.warnLicenseUsersExceeded": "You've reached the user limit for %1 editors. Contact your administrator to learn more.", + "VE.Controllers.Main.warnNoLicense": "You've reached the limit for simultaneous connections to %1 editors. This document will be opened for viewing only.
    Contact %1 sales team for personal upgrade terms.", + "VE.Controllers.Main.warnNoLicenseUsers": "You've reached the user limit for %1 editors. Contact %1 sales team for personal upgrade terms.", + "VE.Controllers.Main.warnProcessRightsChange": "You have been denied the right to edit the file.", + "VE.Controllers.Navigation.txtBeginning": "Beginning of document", + "VE.Controllers.Navigation.txtGotoBeginning": "Go to the beginning of the document", + "VE.Controllers.Search.notcriticalErrorTitle": "Warning", + "VE.Controllers.Search.textNoTextFound": "The data you have been searching for could not be found. Please adjust your search options.", + "VE.Controllers.Search.textReplaceSkipped": "The replacement has been made. {0} occurrences were skipped.", + "VE.Controllers.Search.textReplaceSuccess": "Search has been done. {0} occurrences have been replaced", + "VE.Controllers.Search.warnReplaceString": "{0} is not a valid special character for the Replace With box.", + "VE.Controllers.Statusbar.textDisconnect": "Connection is lost
    Trying to connect. Please check connection settings.", + "VE.Controllers.Statusbar.zoomText": "Zoom {0}%", + "VE.Controllers.Toolbar.errorAccessDeny": "You are trying to perform an action you do not have rights for.
    Please contact your Document Server administrator.", + "VE.Controllers.Toolbar.notcriticalErrorTitle": "Warning", + "VE.Controllers.Toolbar.textWarning": "Warning", + "VE.Controllers.Toolbar.txtDownload": "Download", + "VE.Controllers.Toolbar.txtSaveCopy": "Save copy", + "VE.Controllers.Toolbar.txtUntitled": "Untitled", + "VE.Controllers.Viewport.textFitPage": "Fit to Page", + "VE.Controllers.Viewport.textFitWidth": "Fit to Width", + "VE.Controllers.Viewport.txtDarkMode": "Dark mode", + "VE.Views.DocumentHolder.guestText": "Guest", + "VE.Views.DocumentHolder.textCopy": "Copy", + "VE.Views.DocumentHolder.textCut": "Cut", + "VE.Views.DocumentHolder.tipIsLocked": "This element is currently being edited by another user.", + "VE.Views.DocumentHolder.txtPressLink": "Press {0} and click link", + "VE.Views.DocumentHolder.txtPrintSelection": "Print selection", + "VE.Views.DocumentHolder.txtSelectAll": "Select all", + "VE.Views.DocumentHolder.txtWarnUrl": "Clicking this link can be harmful to your device and data.
    Are you sure you want to continue?", + "VE.Views.FileMenu.ariaFileMenu": "File menu", + "VE.Views.FileMenu.btnBackCaption": "Open File Location", + "VE.Views.FileMenu.btnCloseEditor": "Close File", + "VE.Views.FileMenu.btnCloseMenuCaption": "Back", + "VE.Views.FileMenu.btnCreateNewCaption": "Create New", + "VE.Views.FileMenu.btnDownloadCaption": "Download As", + "VE.Views.FileMenu.btnExitCaption": "Close", + "VE.Views.FileMenu.btnFileOpenCaption": "Open", + "VE.Views.FileMenu.btnHelpCaption": "Help", + "VE.Views.FileMenu.btnInfoCaption": "Info", + "VE.Views.FileMenu.btnPrintCaption": "Print", + "VE.Views.FileMenu.btnRecentFilesCaption": "Open Recent", + "VE.Views.FileMenu.btnRenameCaption": "Rename", + "VE.Views.FileMenu.btnReturnCaption": "Back to Document", + "VE.Views.FileMenu.btnRightsCaption": "Access Rights", + "VE.Views.FileMenu.btnSaveAsCaption": "Save As", + "VE.Views.FileMenu.btnSaveCaption": "Save", + "VE.Views.FileMenu.btnSaveCopyAsCaption": "Save Copy As", + "VE.Views.FileMenu.btnSettingsCaption": "Advanced Settings", + "VE.Views.FileMenu.btnToEditCaption": "Edit Document", + "VE.Views.FileMenu.textDownload": "Download", + "VE.Views.FileMenuPanels.CreateNew.txtBlank": "Blank Document", + "VE.Views.FileMenuPanels.CreateNew.txtCreateNew": "Create new", + "VE.Views.FileMenuPanels.DocumentInfo.okButtonText": "Apply", + "VE.Views.FileMenuPanels.DocumentInfo.txtAddAuthor": "Add Author", + "VE.Views.FileMenuPanels.DocumentInfo.txtAddText": "Add Text", + "VE.Views.FileMenuPanels.DocumentInfo.txtAppName": "Application", + "VE.Views.FileMenuPanels.DocumentInfo.txtAuthor": "Author", + "VE.Views.FileMenuPanels.DocumentInfo.txtBtnAccessRights": "Change access rights", + "VE.Views.FileMenuPanels.DocumentInfo.txtComment": "Comment", + "VE.Views.FileMenuPanels.DocumentInfo.txtCommon": "Common", + "VE.Views.FileMenuPanels.DocumentInfo.txtCreated": "Created", + "VE.Views.FileMenuPanels.DocumentInfo.txtDocumentInfo": "Document Info", + "VE.Views.FileMenuPanels.DocumentInfo.txtFastWV": "Fast Web View", + "VE.Views.FileMenuPanels.DocumentInfo.txtLoading": "Loading...", + "VE.Views.FileMenuPanels.DocumentInfo.txtModifyBy": "Last modified by", + "VE.Views.FileMenuPanels.DocumentInfo.txtModifyDate": "Last modified", + "VE.Views.FileMenuPanels.DocumentInfo.txtNo": "No", + "VE.Views.FileMenuPanels.DocumentInfo.txtOwner": "Owner", + "VE.Views.FileMenuPanels.DocumentInfo.txtPlacement": "Location", + "VE.Views.FileMenuPanels.DocumentInfo.txtRights": "Persons who have rights", + "VE.Views.FileMenuPanels.DocumentInfo.txtSubject": "Subject", + "VE.Views.FileMenuPanels.DocumentInfo.txtTags": "Tags", + "VE.Views.FileMenuPanels.DocumentInfo.txtTitle": "Title", + "VE.Views.FileMenuPanels.DocumentInfo.txtUploaded": "Uploaded", + "VE.Views.FileMenuPanels.DocumentInfo.txtYes": "Yes", + "VE.Views.FileMenuPanels.DocumentRights.txtAccessRights": "Access Rights", + "VE.Views.FileMenuPanels.DocumentRights.txtBtnAccessRights": "Change access rights", + "VE.Views.FileMenuPanels.DocumentRights.txtRights": "Persons who have rights", + "VE.Views.FileMenuPanels.Settings.okButtonText": "Apply", + "VE.Views.FileMenuPanels.Settings.strFontRender": "Font hinting", + "VE.Views.FileMenuPanels.Settings.strShowComments": "Show comments in text", + "VE.Views.FileMenuPanels.Settings.strShowResolvedComments": "Show resolved comments", + "VE.Views.FileMenuPanels.Settings.strTabStyle": "Tab style", + "VE.Views.FileMenuPanels.Settings.strTheme": "Interface theme", + "VE.Views.FileMenuPanels.Settings.strZoom": "Default Zoom Value", + "VE.Views.FileMenuPanels.Settings.textDisabled": "Disabled", + "VE.Views.FileMenuPanels.Settings.textFill": "Fill", + "VE.Views.FileMenuPanels.Settings.textLine": "Line", + "VE.Views.FileMenuPanels.Settings.txtAdvancedSettings": "Advanced Settings", + "VE.Views.FileMenuPanels.Settings.txtAppearance": "Appearance", + "VE.Views.FileMenuPanels.Settings.txtCacheMode": "Default cache mode", + "VE.Views.FileMenuPanels.Settings.txtDarkMode": "Turn on document dark mode", + "VE.Views.FileMenuPanels.Settings.txtFitPage": "Fit to Page", + "VE.Views.FileMenuPanels.Settings.txtFitWidth": "Fit to Width", + "VE.Views.FileMenuPanels.Settings.txtHieroglyphs": "Hieroglyphs", + "VE.Views.FileMenuPanels.Settings.txtLastUsed": "Last used", + "VE.Views.FileMenuPanels.Settings.txtMac": "as OS X", + "VE.Views.FileMenuPanels.Settings.txtNative": "Native", + "VE.Views.FileMenuPanels.Settings.txtQuickPrintTip": "The document will be printed on the last selected or default printer", + "VE.Views.FileMenuPanels.Settings.txtScreenReader": "Turn on screen reader support", + "VE.Views.FileMenuPanels.Settings.txtTabBack": "Use toolbar color as tabs background", + "VE.Views.FileMenuPanels.Settings.txtUseAltKey": "Use Alt key to navigate the user interface using the keyboard", + "VE.Views.FileMenuPanels.Settings.txtUseOptionKey": "Use Option key to navigate the user interface using the keyboard", + "VE.Views.FileMenuPanels.Settings.txtWin": "as Windows", + "VE.Views.FileMenuPanels.Settings.txtWorkspace": "Workspace", + "VE.Views.FileMenuPanels.ViewSaveAs.textDownloadAs": "Download as", + "VE.Views.FileMenuPanels.ViewSaveCopy.textSaveCopyAs": "Save Copy as", + "VE.Views.LeftMenu.ariaLeftMenu": "Left menu", + "VE.Views.LeftMenu.tipAbout": "About", + "VE.Views.LeftMenu.tipChat": "Chat", + "VE.Views.LeftMenu.tipComments": "Comments", + "VE.Views.LeftMenu.tipOutline": "Headings", + "VE.Views.LeftMenu.tipSlides": "Pages", + "VE.Views.LeftMenu.tipPlugins": "Plugins", + "VE.Views.LeftMenu.tipSearch": "Find", + "VE.Views.LeftMenu.tipSupport": "Feedback & Support", + "VE.Views.LeftMenu.tipTitles": "Titles", + "VE.Views.LeftMenu.txtDeveloper": "DEVELOPER MODE", + "VE.Views.LeftMenu.txtEditor": "Visio Editor", + "VE.Views.LeftMenu.txtLimit": "Limit Access", + "VE.Views.LeftMenu.txtTrial": "TRIAL MODE", + "VE.Views.LeftMenu.txtTrialDev": "Trial Developer Mode", + "VE.Views.Statusbar.tipFitToSlide": "Fit to page", + "VE.Views.Statusbar.tipFitToWidth": "Fit to width", + "VE.Views.Statusbar.tipZoomFactor": "Zoom", + "VE.Views.Statusbar.tipZoomIn": "Zoom in", + "VE.Views.Statusbar.tipZoomOut": "Zoom out", + "VE.Views.Toolbar.textTabFile": "File", + "VE.Views.Toolbar.textTabView": "View", + "VE.Views.ViewTab.textAlwaysShowToolbar": "Always Show Toolbar", + "VE.Views.ViewTab.textDarkDocument": "Dark Document", + "VE.Views.ViewTab.textFill": "Fill", + "VE.Views.ViewTab.textFitToSlide": "Fit To Page", + "VE.Views.ViewTab.textFitToWidth": "Fit To Width", + "VE.Views.ViewTab.textInterfaceTheme": "Interface Theme", + "VE.Views.ViewTab.textLeftMenu": "Left Panel", + "VE.Views.ViewTab.textLine": "Line", + "VE.Views.ViewTab.textStatusBar": "Status Bar", + "VE.Views.ViewTab.textTabStyle": "Tab style", + "VE.Views.ViewTab.textZoom": "Zoom", + "VE.Views.ViewTab.tipDarkDocument": "Dark document", + "VE.Views.ViewTab.tipFitToPage": "Fit to page", + "VE.Views.ViewTab.tipFitToWidth": "Fit to width", + "VE.Views.ViewTab.tipInterfaceTheme": "Interface theme" +} \ No newline at end of file diff --git a/apps/visioeditor/main/resources/img/favicon.ico b/apps/visioeditor/main/resources/img/favicon.ico new file mode 100644 index 0000000000..96d08b595b Binary files /dev/null and b/apps/visioeditor/main/resources/img/favicon.ico differ diff --git a/apps/visioeditor/main/resources/img/file-template.svg b/apps/visioeditor/main/resources/img/file-template.svg new file mode 100644 index 0000000000..94c499c0f4 --- /dev/null +++ b/apps/visioeditor/main/resources/img/file-template.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/visioeditor/main/resources/img/recent-file.svg b/apps/visioeditor/main/resources/img/recent-file.svg new file mode 100644 index 0000000000..8ecae21f56 --- /dev/null +++ b/apps/visioeditor/main/resources/img/recent-file.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/visioeditor/main/resources/img/toolbar/1.25x/btn-ic-zoomtoslide.png b/apps/visioeditor/main/resources/img/toolbar/1.25x/btn-ic-zoomtoslide.png new file mode 100644 index 0000000000..fbb0342f2b Binary files /dev/null and b/apps/visioeditor/main/resources/img/toolbar/1.25x/btn-ic-zoomtoslide.png differ diff --git a/apps/visioeditor/main/resources/img/toolbar/1.25x/btn-menu-thumbs.png b/apps/visioeditor/main/resources/img/toolbar/1.25x/btn-menu-thumbs.png new file mode 100644 index 0000000000..d80e8bcb32 Binary files /dev/null and b/apps/visioeditor/main/resources/img/toolbar/1.25x/btn-menu-thumbs.png differ diff --git a/apps/visioeditor/main/resources/img/toolbar/1.5x/btn-ic-zoomtoslide.png b/apps/visioeditor/main/resources/img/toolbar/1.5x/btn-ic-zoomtoslide.png new file mode 100644 index 0000000000..a983f370c4 Binary files /dev/null and b/apps/visioeditor/main/resources/img/toolbar/1.5x/btn-ic-zoomtoslide.png differ diff --git a/apps/visioeditor/main/resources/img/toolbar/1.5x/btn-menu-thumbs.png b/apps/visioeditor/main/resources/img/toolbar/1.5x/btn-menu-thumbs.png new file mode 100644 index 0000000000..b589a998d9 Binary files /dev/null and b/apps/visioeditor/main/resources/img/toolbar/1.5x/btn-menu-thumbs.png differ diff --git a/apps/visioeditor/main/resources/img/toolbar/1.75x/btn-ic-zoomtoslide.png b/apps/visioeditor/main/resources/img/toolbar/1.75x/btn-ic-zoomtoslide.png new file mode 100644 index 0000000000..8f9f48d876 Binary files /dev/null and b/apps/visioeditor/main/resources/img/toolbar/1.75x/btn-ic-zoomtoslide.png differ diff --git a/apps/visioeditor/main/resources/img/toolbar/1.75x/btn-menu-thumbs.png b/apps/visioeditor/main/resources/img/toolbar/1.75x/btn-menu-thumbs.png new file mode 100644 index 0000000000..68dcbd4c5e Binary files /dev/null and b/apps/visioeditor/main/resources/img/toolbar/1.75x/btn-menu-thumbs.png differ diff --git a/apps/visioeditor/main/resources/img/toolbar/1x/btn-ic-zoomtoslide.png b/apps/visioeditor/main/resources/img/toolbar/1x/btn-ic-zoomtoslide.png new file mode 100644 index 0000000000..597389f5ad Binary files /dev/null and b/apps/visioeditor/main/resources/img/toolbar/1x/btn-ic-zoomtoslide.png differ diff --git a/apps/visioeditor/main/resources/img/toolbar/1x/btn-menu-thumbs.png b/apps/visioeditor/main/resources/img/toolbar/1x/btn-menu-thumbs.png new file mode 100644 index 0000000000..d825e39f0c Binary files /dev/null and b/apps/visioeditor/main/resources/img/toolbar/1x/btn-menu-thumbs.png differ diff --git a/apps/visioeditor/main/resources/img/toolbar/2.5x/btn-ic-zoomtoslide.svg b/apps/visioeditor/main/resources/img/toolbar/2.5x/btn-ic-zoomtoslide.svg new file mode 100644 index 0000000000..e0fec8c254 --- /dev/null +++ b/apps/visioeditor/main/resources/img/toolbar/2.5x/btn-ic-zoomtoslide.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/visioeditor/main/resources/img/toolbar/2.5x/btn-menu-thumbs.svg b/apps/visioeditor/main/resources/img/toolbar/2.5x/btn-menu-thumbs.svg new file mode 100644 index 0000000000..b321c73aa2 --- /dev/null +++ b/apps/visioeditor/main/resources/img/toolbar/2.5x/btn-menu-thumbs.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/visioeditor/main/resources/img/toolbar/2x/btn-ic-zoomtoslide.png b/apps/visioeditor/main/resources/img/toolbar/2x/btn-ic-zoomtoslide.png new file mode 100644 index 0000000000..36abd30a90 Binary files /dev/null and b/apps/visioeditor/main/resources/img/toolbar/2x/btn-ic-zoomtoslide.png differ diff --git a/apps/visioeditor/main/resources/img/toolbar/2x/btn-menu-thumbs.png b/apps/visioeditor/main/resources/img/toolbar/2x/btn-menu-thumbs.png new file mode 100644 index 0000000000..77c9145bac Binary files /dev/null and b/apps/visioeditor/main/resources/img/toolbar/2x/btn-menu-thumbs.png differ diff --git a/apps/visioeditor/main/resources/less/app.less b/apps/visioeditor/main/resources/less/app.less new file mode 100644 index 0000000000..1e27d474e9 --- /dev/null +++ b/apps/visioeditor/main/resources/less/app.less @@ -0,0 +1,213 @@ +// +// Common +// -------------------------------------------------- + +// App variables +@import "variables.less"; + +@import "../../../../common/main/resources/less/asc-mixins.less"; + +// Bootstrap overwrite +@import "../../../../common/main/resources/less/variables.less"; +@import "../../../../common/main/resources/less/colors-table.less"; +@import "../../../../common/main/resources/less/colors-table-classic.less"; +@import "../../../../common/main/resources/less/colors-table-dark.less"; +@import "../../../../common/main/resources/less/colors-table-dark-contrast.less"; +@import "../../../../common/main/resources/less/colors-table-gray.less"; +// +// Bootstrap +// -------------------------------------------------- + +// Core variables and mixins +@import "../../../../common/main/resources/mods/less/mixins.less"; + +// Reset +@import "../../../../common/main/resources/mods/less/normalize.less"; + +// Core CSS +@import "../../../../common/main/resources/mods/less/scaffolding.less"; +@import "../../../../common/main/resources/mods/less/type.less"; +@import "../../../../common/main/resources/mods/less/forms.less"; +@import "../../../../common/main/resources/mods/less/buttons.less"; + +// Components +@import "../../../../common/main/resources/mods/less/component-animations.less"; +@import "../../../../common/main/resources/mods/less/dropdowns.less"; +@import "../../../../common/main/resources/mods/less/button-groups.less"; +@import "../../../../common/main/resources/mods/less/input-groups.less"; + +// Components w/ JavaScript +@import "../../../../common/main/resources/mods/less/tooltip.less"; + +// Utility classes +@import "../../../../common/main/resources/mods/less/utilities.less"; +@import "../../../../common/main/resources/mods/less/responsive-utilities.less"; + +// +// Perfect scrollbar +// -------------------------------------------------- + +@import (inline) "../../../../../vendor/perfect-scrollbar/src/perfect-scrollbar.css"; + +// +// Common +// -------------------------------------------------- + +@import "../../../../common/main/resources/less/header.less"; +@import "../../../../common/main/resources/less/buttons.less"; +@import "../../../../common/main/resources/less/dropdown-menu.less"; +@import "../../../../common/main/resources/less/dropdown-submenu.less"; +@import "../../../../common/main/resources/less/separator.less"; +@import "../../../../common/main/resources/less/input.less"; +@import "../../../../common/main/resources/less/combobox.less"; +@import "../../../../common/main/resources/less/window.less"; +@import "../../../../common/main/resources/less/spinner.less"; +@import "../../../../common/main/resources/less/loadmask.less"; +@import "../../../../common/main/resources/less/checkbox.less"; +@import "../../../../common/main/resources/less/radiobox.less"; +@import "../../../../common/main/resources/less/dataview.less"; +@import "../../../../common/main/resources/less/listview.less"; +@import "../../../../common/main/resources/less/treeview.less"; +@import "../../../../common/main/resources/less/colorpalette.less"; +@import "../../../../common/main/resources/less/theme-colorpalette.less"; +@import "../../../../common/main/resources/less/hsb-colorpicker.less"; +@import "../../../../common/main/resources/less/masked-field.less"; +@import "../../../../common/main/resources/less/extended-color-picker.less"; +@import "../../../../common/main/resources/less/layout.less"; +@import "../../../../common/main/resources/less/combo-border-size.less"; +//@import "../../../../common/main/resources/less/combo-dataview.less"; +@import "../../../../common/main/resources/less/slider.less"; +@import "../../../../common/main/resources/less/advanced-settings-window.less"; +@import "../../../../common/main/resources/less/chat.less"; +@import "../../../../common/main/resources/less/comments.less"; +@import "../../../../common/main/resources/less/searchdialog.less"; +@import "../../../../common/main/resources/less/about.less"; +@import "../../../../common/main/resources/less/tooltip.less"; +@import "../../../../common/main/resources/less/scroller.less"; +@import "../../../../common/main/resources/less/synchronize-tip.less"; +@import "../../../../common/main/resources/less/common.less"; +@import "../../../../common/main/resources/less/switcher.less"; +@import "../../../../common/main/resources/less/opendialog.less"; +@import "../../../../common/main/resources/less/review-changes.less"; +@import "../../../../common/main/resources/less/plugins.less"; +@import "../../../../common/main/resources/less/toolbar.less"; +@import "../../../../common/main/resources/less/winxp_fix.less"; +@import "../../../../common/main/resources/less/hint-manager.less"; +@import "../../../../common/main/resources/less/bigscaling.less"; +@import "../../../../common/main/resources/less/updown-picker.less"; + +// App +// -------------------------------------------------- + +@import "layout.less"; +@import "toolbar.less"; +@import "statusbar.less"; +@import "leftmenu.less"; +@import "filemenu.less"; + +@import "sprites/iconssmall@1x"; +@import "sprites/iconsbig@1x"; +@import "sprites/iconssmall@2x"; +@import "sprites/iconsbig@2x"; +@import "sprites/iconssmall@1.25x"; +@import "sprites/iconsbig@1.25x"; +@import "sprites/iconssmall@1.5x"; +@import "sprites/iconsbig@1.5x"; +@import "sprites/iconssmall@1.75x"; +@import "sprites/iconsbig@1.75x"; + +.font-size-tiny { + .fontsize(9px); // 9px + .fontsize(calc(@font-size-base-app - 2px)); // 9px +} + +.font-size-small { + .fontsize(10px); // 10px + .fontsize(calc(@font-size-base-app - 1px)); // 10px +} + +.font-size-normal { + .fontsize(11px); // 11px + .fontsize(@font-size-base-app); // 11px +} + +.font-size-medium { + .fontsize(12px); // 12px + .fontsize(calc(@font-size-base-app + 1px)); // 12px +} + +.font-size-large { + .fontsize(13px); // 13px + .fontsize(calc(@font-size-base-app + 2px)); // 13px +} + +.font-size-huge { + .fontsize(14px); // 14px + .fontsize(calc(@font-size-base-app + 3px)); // 14px +} + +.font-size-very-huge { + .fontsize(16px); // 16px + .fontsize(calc(@font-size-base-app + 5px)); // 16px +} + +// Skeleton of document + +.doc-placeholder { + display: flex; + flex-direction: column; + height: 100%; + padding: 0 100px; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: @canvas-background; + + .slide-h { + display: flex; + flex-direction: column; + justify-content: center; + flex-grow: 1; + max-width: 1350px; + width: 100%; + margin: 0 auto; + } + + .slide-v { + display: flex; + position: relative; + flex-direction: column; + padding-bottom: 56.1333%; + } + + .slide-container { + position: absolute; + height: 100%; + width: 100%; + background: #fbfbfb; + border: 1px solid #dfdfdf; + + > .line { + height: 20%; + margin: 0 120px; + border-radius: 6px; + background: #f5f5f5; + + //-webkit-animation: flickerAnimation 2s infinite ease-in-out; + //-moz-animation: flickerAnimation 2s infinite ease-in-out; + //-o-animation: flickerAnimation 2s infinite ease-in-out; + //animation: flickerAnimation 2s infinite ease-in-out; + + &:nth-child(1) { + height: 30%; + margin: 10% 80px 0; + } + + &.empty { + background: transparent; + } + } + } +} diff --git a/apps/visioeditor/main/resources/less/filemenu.less b/apps/visioeditor/main/resources/less/filemenu.less new file mode 100644 index 0000000000..d73ee86029 --- /dev/null +++ b/apps/visioeditor/main/resources/less/filemenu.less @@ -0,0 +1,693 @@ + +#file-menu-panel { + .panel-context { + width: 100%; + padding-left: 260px; + background-color: @background-normal-ie; + background-color: @background-normal; + + .rtl & { + padding-left: 0; + padding-right: 260px; + } + + .content-box { + height: 100%; + padding: 0 20px; + + label.empty { + position: absolute; + top: 45%; + left: 50%; + } + + position: relative; + overflow: hidden; + } + } +} + +#id-help-frame { + position: absolute; + left: 220px; + top: 0; + right: 0; + bottom: 0; + + .rtl & { + left: 0; + right: 220px; + } +} + +#file-menu-panel .panel-context { + #panel-saveas, #panel-savecopy { + &.content-box { + padding: 0 0 0 20px; + + .rtl & { + padding: 0 20px 0 0; + } + } + + .content-container { + margin: 30px 0 0 10px; + + .rtl & { + margin: 30px 10px 0 0; + } + + .header { + .font-size-very-huge(); + margin-bottom: 30px; + } + + .format-items { + .format-item { + margin: 0 24px 34px 0; + + .rtl & { + margin: 0 0 34px 24px; + } + + .btn-doc-format { + width: 70px; + height: 90px; + } + } + + .divider { + float: left; + width: 0; + height: 0; + } + &:last-of-type { + float: none; + clear: both; + } + } + } + } +} + +.btn-doc-format { + display: block; + width: 98px; + height: 125px; + cursor: pointer; + + .svg-format- { + &vsdx { + background: ~"url('@{common-image-const-path}/doc-formats/vsdx.svg') no-repeat center"; + } + &pdf { + background: ~"url('@{common-image-const-path}/doc-formats/pdf.svg') no-repeat center"; + } + &pdfa { + background: ~"url('@{common-image-const-path}/doc-formats/pdfa.svg') no-repeat center"; + } + &png { + background: ~"url('@{common-image-const-path}/doc-formats/png.svg') no-repeat center"; + } + &jpg { + background: ~"url('@{common-image-const-path}/doc-formats/jpg.svg') no-repeat center"; + } + } + + div { + display: block; + height: 100%; + width: 100%; + &:hover { + opacity: 0.85; + } + } +} + +.btn-blank-format { + display: block; + width: 96px; + height: 96px; + cursor: pointer; + + .svg-format-blank { + background: ~"url(@{app-image-const-path}/blank.svg) no-repeat center" ; + } + .svg-file-template{ + background: ~"url(@{app-image-const-path}/file-template.svg) no-repeat center" ; + } + + div { + display: block; + height: 100%; + width: 100%; + } + + +} + +#panel-settings { + #file-menu-panel & { + padding: 0; + display: flex; + flex-direction: column; + } +} + +#panel-settings { + .header { + margin: 30px 0 18px 30px; + .font-size-very-huge(); + .rtl & { + margin: 30px 30px 18px 0; + } + } + + .flex-settings { + table { + margin: 0 14px 0 20px; + .rtl & { + margin: 0 20px 0 14px; + } + } + } + + table { + width: auto !important; + tr { + td { + label{ + .font-size-normal(); + } + + padding: 6px 10px; + &.group-name label { + .font-size-huge(); + .font-weight-bold(); + } + + &.subgroup-name label{ + .font-weight-bold(); + } + + .comment-text{ + opacity: 0.45; + } + } + + &.left { + text-align: right; + width: 30%; + label { + .font-weight-bold(); + .font-size-medium(); + } + } + + &.right { + width: 70%; + } + + &.divider { + height: 10px; + } + &.divider-group { + height: 12px; + } + &.divider-subgroup{ + height: 4px; + } + } + } + + #fms-cmb-theme { + display: inline-block; + .margin-right-15(); + vertical-align: middle; + } + + #fms-chb-dark-mode { + display: inline-block; + vertical-align: middle; + margin-top: 2px; + } + + #fms-cmb-macros { + display: inline-block; + .margin-right-15(); + vertical-align: middle; + } +} + +#panel-createnew { + .header { + .font-size-very-huge(); + padding: 0 0 0 10px; + white-space: nowrap; + margin-top: 30px; + margin-bottom: 30px; + + .rtl & { + padding: 0 10px 10px 0; + } + } + + hr { + margin: 0; + border-bottom: none; + border-top: @scaled-one-px-value-ie solid @border-divider-ie; + border-top: @scaled-one-px-value solid @border-divider; + } + + .thumb-list { + max-width: 600px; + .thumb-wrap, .blank-document { + display: inline-block; + text-align: center; + width: auto; + cursor: pointer; + vertical-align: top; + .border-radius(@border-radius-small); + + .thumb, .blank-document-btn { + width: 96px; + height: 96px; + background-repeat: no-repeat; + background-position: center; + margin: 12px 12px 0px 12px; + background-size: contain; + } + + .title { + width: 104px; + .font-size-medium(); + line-height: 14px; + height: 28px; + margin: 8px 8px 12px 8px; + word-break: break-word; + word-wrap: break-word; + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + } + &:hover{ + background-color: @highlight-button-hover-ie; + background-color: @highlight-button-hover; + + } + &:active{ + color: @text-normal-pressed-ie; + color: @text-normal-pressed; + background-color: @highlight-button-pressed-ie; + background-color: @highlight-button-pressed; + } + } + } +} + +#panel-recentfiles { + #id-recent-view { + margin: 0 0 20px 10px; + } + + .header { + margin: 30px 0 20px 10px; + .font-size-very-huge(); + } + + .item { + border: none; + .margin-left-4; + width: 100%; + .box-shadow(none); + } + + .recent-wrap { + padding: 5px 10px; + cursor: pointer; + .font-size-medium(); + + &:hover, + &.over { + background-color: @background-toolbar-ie; + background-color: @background-toolbar; + } + + .recent-icon { + display: inline-block; + .float-left(); + width: 24px; + height: 30px; + margin-top: 1px; + div { + width: 100%; + height: 100%; + div{ + background: ~"url(@{common-image-const-path}/doc-formats/formats.png)"; + background-size: 1032px 30px; + &:not(.svg-file-recent) { + .pixel-ratio__1_25 & { + background-image: ~"url(@{common-image-const-path}/doc-formats/formats@1.25x.png)"; + } + + .pixel-ratio__1_5 & { + background-image: ~"url(@{common-image-const-path}/doc-formats/formats@1.5x.png)"; + } + + .pixel-ratio__1_75 & { + background-image: ~"url(@{common-image-const-path}/doc-formats/formats@1.75x.png)"; + } + + .pixel-ratio__2 & { + background-image: ~"url(@{common-image-const-path}/doc-formats/formats@2x.png)"; + } + } + } + .format-from-index(@index) { + background-position: -24px*@index 0; + } + .img-format- { + &pdf, &pdfa { + .format-from-index(13); + } + &xps { + .format-from-index(15); + } + &djvu { + .format-from-index(14); + } + } + .svg-file-recent { + background: ~"url(@{app-image-const-path}/recent-file.svg) no-repeat top"; + } + } + } + + > div:not(:first-child) { + display: block; + .padding-left-10(); + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + .file-info { + color: @text-secondary-ie; + color: @text-secondary; + } + } +} + +#panel-help { + #file-menu-panel & { + padding: 0; + overflow-y: hidden; + } + + .no-padding { + padding: 0; + vertical-align: top; + } + + .dataview { + border-right: @scaled-one-px-value-ie solid @border-toolbar-ie; + border-right: @scaled-one-px-value solid @border-toolbar; + + .rtl & { + border-right: none; + border-left: @scaled-one-px-value-ie solid @border-toolbar-ie; + border-left: @scaled-one-px-value solid @border-toolbar; + } + + & > .item { + display: block; + border: none; + width: 100%; + .box-shadow(none); + margin: 0; + .font-size-medium(); + float: none; + + &:not(.header-name) { + &:hover, + &.over { + background-color: @background-toolbar-ie; + background-color: @background-toolbar; + } + + &.selected { + background-color: @highlight-button-pressed-ie; + background-color: @highlight-button-pressed; + color: @text-normal-pressed-ie; + color: @text-normal-pressed; + } + } + } + + .help-item-wrap { + padding: 4px 2px 4px 20px; + + .rtl & { + padding: 4px 20px 4px 2px; + } + } + + .header-name { + padding: 16px 2px 4px 10px; + .font-size-medium(); + + .rtl & { + padding: 16px 10px 4px 2px; + } + } + } +} + +#panel-rights { + #file-menu-panel & { + padding: 0 30px; + } + + .header { + margin: 30px 0 20px 0; + .font-size-very-huge(); + } +} + +#panel-info { + #file-menu-panel & { + padding: 0 30px; + } + + .header { + .font-size-very-huge(); + height: unset; + line-height: unset; + } + + table.main { + margin: 30px 0 18px; + } + + table { + display: flex; + flex-direction: column; + + tr { + display: flex; + margin-bottom: 12px; + + td { + .font-size-normal(); + line-height: 16px; + + &.title { + line-height: 20px; + + label { + .font-size-huge(); + font-weight: 700; + } + } + + &.left { + display: block; + width: 140px; + flex-shrink: 0; + .margin-right(24px); + } + + &.right { + flex-grow: 1; + } + } + + &.divider { + height: 10px; + } + } + + tbody { + display: flex; + flex-direction: column; + + &:not(:last-of-type) { + margin-bottom: 12px; + } + + &.properties-tab { + margin-bottom: 0; + + tr { + margin-bottom: 10px; + } + + td { + height: unset; + } + + td.left { + display: flex; + align-items: center; + .margin-right-20(); + + label { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } + } + } + } + + tr.author-info { + align-items: flex-start; + + td { + &.left { + height: 22px; + } + + display: flex; + align-items: center; + & > *:not(:last-child) { + .margin-right-5(); + } + } + } + + .author-info tbody tr:last-child { + margin-bottom: 20px; + } + + &.main { + width: 100%; + } + } + + #fms-flex-add-property { + margin-top: 10px; + td { + height: unset; + } + } + + #fminfo-btn-add-property { + padding: 0; + border: 0; + background-color: transparent; + height: 24px; + + span { + border-bottom: 1px dotted currentColor; + padding-bottom: 2px; + } + } + + .custom-property-wrapper { + display: flex; + align-items: center; + & > *:not(:last-child) { + .margin-right-5(); + } + } + + .tool.close:before, .tool.close:after { + margin-top: 2px; + } +} + +#panel-rights { + table { + tr { + td { + padding: 0 20px 5px 0; + + .rtl & { + padding: 0 0 5px 20px; + } + + &.left { + padding: 5px 10px; + text-align: right; + width: 200px; + + .rtl & { + text-align: left; + } + + label { + .font-weight-bold(); + } + } + + &.right { + padding: 5px 10px; + width: calc(100% - 200px); + } + } + + &.divider { + height: 10px; + } + } + + &.main { + width: 100%; + } + } + + .userLink { + background-position: -81px -234px; + padding: 0 0 0 17px; + width: 16px; + height: 16px; + + &.sharedLink { + background-position: -24px -273px; + } + } + + label, span { + .font-size-medium(); + } + + .tool { + .margin-left-4(); + background-image: none; + &.close{ + &:before, &:after { + height: 12px; + left: 8px; + width: 2px; + width: @scaled-two-px-value; + } + &.disabled { + opacity: 0.4; + } + } + } +} + diff --git a/apps/visioeditor/main/resources/less/layout.less b/apps/visioeditor/main/resources/less/layout.less new file mode 100644 index 0000000000..b8bcca3c3e --- /dev/null +++ b/apps/visioeditor/main/resources/less/layout.less @@ -0,0 +1,77 @@ +body { + width: 100%; + height: 100%; + .user-select(none); + color: @text-normal-ie; + color: @text-normal; + + &.safari { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + overflow: scroll; + + &::-webkit-scrollbar { + width: 0; + height: 0; + } + + #viewport { + &::-webkit-scrollbar { + width: 0; + height: 0; + } + } + } +} + +label { + margin-bottom: 0; + font-weight: normal; +} + +#viewport { + position: absolute; + left: 0; + top:0; + right: 0; + bottom: 0; + background-color: @background-toolbar-ie; + background-color: @background-toolbar; + overflow: hidden; + scroll-behavior: smooth; // chromium bug890248 (Bug 39614) +} + +.layout-region { + width: 100%; + height: 100%; + border-collapse: collapse; + table-layout: fixed; + + .row { + display: table-row; + } + + .cell { + display: table-cell; + } + + .layout-resizer { + background-color: transparent; + } +} + +.tooltip.main-info { + z-index: @zindex-popover; + + .tooltip-inner { + max-width: none; + } +} + +#editor_sdk { + width: 100%; + height: 100%; +} \ No newline at end of file diff --git a/apps/visioeditor/main/resources/less/leftmenu.less b/apps/visioeditor/main/resources/less/leftmenu.less new file mode 100644 index 0000000000..57a8353a61 --- /dev/null +++ b/apps/visioeditor/main/resources/less/leftmenu.less @@ -0,0 +1,63 @@ +#left-menu { + &+.layout-resizer { + border-left: 0 none; + border-right: 0 none; + + &.move { + border-left: @scaled-one-px-value-ie solid @border-toolbar-ie; + border-left: @scaled-one-px-value solid @border-toolbar; + border-right: @scaled-one-px-value-ie solid @border-toolbar-ie; + border-right: @scaled-one-px-value solid @border-toolbar; + opacity: 0.4; + } + } +} + +.left-menu-full-ct { + width: 100%; + height: 100%; + left: 40px; + padding-right: 40px; + top: 0; + position: absolute; + z-index: @zindex-dropdown - 5; + background-color: @background-toolbar-ie; + background-color: @background-toolbar; + overflow: hidden; + + .rtl & { + left: 0; + right: 40px; + } +} + +#developer-hint, #beta-hint, #limit-hint { + position: absolute; + left: 0; + padding: 12px 0; + background-color: #ffb400; + color: #6e4e00 !important; + white-space: pre; + line-height: 20px; + writing-mode: tb-rl; + -moz-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -webkit-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); + cursor: default; + .rtl & { + right: 0; + left: auto; + -moz-transform: rotate(0); + -ms-transform: rotate(0); + -webkit-transform: rotate(0); + -o-transform: rotate(0); + transform: rotate(0); + } +} + +#search-results { + background-color: @background-normal-ie; + background-color: @background-normal; +} diff --git a/apps/visioeditor/main/resources/less/statusbar.less b/apps/visioeditor/main/resources/less/statusbar.less new file mode 100644 index 0000000000..8d76c8c622 --- /dev/null +++ b/apps/visioeditor/main/resources/less/statusbar.less @@ -0,0 +1,115 @@ +.statusbar { + display: table; + padding: 2px; + + .status-label { + position: relative; + } + + #label-pages { + .margin-left(40px); + } + + #btn-zoom-up { + .margin-right(40px); + } + + #label-pages, #label-zoom { + cursor: pointer; + } + + #label-zoom { + text-align: center; + } + + #btn-zoom-topage, #btn-zoom-towidth { + .margin-right-8(); + } + + #slot-status-btn-prev, #slot-status-btn-next { + .margin-left-4(); + } + + .status-group { + display: table-cell; + white-space: nowrap; + vertical-align: top; + &.dropup { + position: static; + } + + .status-label.margin-top-large { + margin-top: 6px; + } + + button.margin-top-small, + .margin-top-small > button, + .margin-top-small > .btn-group { + margin-top: 3px; + } + } + + .separator { + margin: 0px 6px; + + &.short { + height: 25px; + } + + &.space { + margin: 0px 2px; + border: none; + } + } + + .cnt-zoom { + display: inline-block; + vertical-align: middle; + margin-top: 4px; + .dropdown-menu { + min-width: 80px; + .margin-left(-4px); + + li { + > a { + text-align: center; + padding-left: 15px; + padding-right: 15px; + } + } + } + } + + .dropdown-menu { + margin-bottom: 6px; + + li { + text-align: left; + .rtl & { + text-align: right; + } + } + } + + #status-goto-box { + padding: 10px; + .margin-left(40px); + margin-bottom: 2px; + min-width: 130px; + + > label { + display: inline-block; + .margin-right-10(); + line-height:22px; + } + + > input[type=text] { + width: 50px; + display: inline-block; + } + } + + .hide-select-tools { + display: none; + } +} diff --git a/apps/visioeditor/main/resources/less/toolbar.less b/apps/visioeditor/main/resources/less/toolbar.less new file mode 100644 index 0000000000..f6aa3ba0d9 --- /dev/null +++ b/apps/visioeditor/main/resources/less/toolbar.less @@ -0,0 +1,62 @@ + +.toolbar { + &.masked { + button.disabled .icon:not(.no-mask) { + } + .group:not(.no-mask) { + opacity: 0.4; + } + } +} + +.toolbar-group-mask { + position: absolute; + top: 0; + left: 0; + width: 0; + height: 0; + background-color: transparent; +} + +// menu zoom +.dropdown-menu .menu-zoom { + line-height: @line-height-base; + .title { + padding: 5px 5px 5px 20px; + //max-width: 95px; + overflow: hidden; + text-overflow: ellipsis; + + .rtl & { + padding: 5px 20px 5px 5px; + } + } + + .btn.next { + margin: 2px 5px 0 0; + .rtl & { + margin: 2px 0 0 0 !important; + } + } + + .btn.prev { + margin-top: 2px; + .rtl & { + margin: 2px 0 0 5px; + } + } +} + + +.username-tip { + background-color: #ee3525; + border: none; + border-radius: 0; + padding: 3px 10px; + color: #ffffff; + .font-size-normal(); + white-space: nowrap; + letter-spacing: 1px; + overflow: hidden; + text-overflow: ellipsis; +} diff --git a/apps/visioeditor/main/resources/less/variables.less b/apps/visioeditor/main/resources/less/variables.less new file mode 100644 index 0000000000..577daa9553 --- /dev/null +++ b/apps/visioeditor/main/resources/less/variables.less @@ -0,0 +1,12 @@ +// +// Variables +// -------------------------------------------------- +@header-background-color-ie: @toolbar-header-visio-ie; +@header-background-color: var(--toolbar-header-visio); +@toolbar-header-text-on-background-ie: @text-toolbar-header-on-background-visio-ie; +@toolbar-header-text-on-background: var(--text-toolbar-header-on-background-visio); +@tab-header-ie: @tab-header-visio-ie; +@tab-header: var(--highlight-header-tab-underline-visio); +@tab-toolbar-ie: @tab-toolbar-visio-ie; +@tab-toolbar: var(--highlight-toolbar-tab-underline-visio); + diff --git a/build/sprites/Gruntfile.js b/build/sprites/Gruntfile.js index 5534f1dea9..d3bd9300fa 100644 --- a/build/sprites/Gruntfile.js +++ b/build/sprites/Gruntfile.js @@ -361,6 +361,64 @@ module.exports = function (grunt, rootpathprefix) { scale: '1.75x', extpath: 'huge' }), + + 'draw-1x': configTemplate({ + editor:'visioeditor', + spritename: sprite_name, + scale: '1x' + }), + 'draw-big-1x': configTemplate({ + editor:'visioeditor', + spritename: sprite_name_big, + scale: '1x', + extpath: 'big' + }), + 'draw-2x': configTemplate({ + editor:'visioeditor', + spritename: sprite_name, + scale: '2x' + }), + 'draw-big-2x': configTemplate({ + editor:'visioeditor', + spritename: sprite_name_big, + scale: '2x', + extpath: 'big' + }), + 'draw-1.5x': configTemplate({ + editor:'visioeditor', + spritename: sprite_name, + scale: '1.5x' + }), + 'draw-big-1.5x': configTemplate({ + editor:'visioeditor', + spritename: sprite_name_big, + scale: '1.5x', + extpath: 'big' + }), + + 'draw-1.25x': configTemplate({ + editor:'visioeditor', + spritename: sprite_name, + scale: '1.25x' + }), + 'draw-big-1.25x': configTemplate({ + editor:'visioeditor', + spritename: sprite_name_big, + scale: '1.25x', + extpath: 'big' + }), + + 'draw-1.75x': configTemplate({ + editor:'visioeditor', + spritename: sprite_name, + scale: '1.75x' + }), + 'draw-big-1.75x': configTemplate({ + editor:'visioeditor', + spritename: sprite_name_big, + scale: '1.75x', + extpath: 'big' + }), }, svg_sprite: { options: { @@ -560,6 +618,48 @@ module.exports = function (grunt, rootpathprefix) { }, } }, + veiconssmall: { + src: [`${_prefix}apps/common/main/resources/img/toolbar/2.5x/*.svg`, + `${_prefix}apps/visioeditor/main/resources/img/toolbar/2.5x/*.svg`], + dest: `${_prefix}apps/visioeditor/main/resources/img/`, + options: { + mode: { + symbol: { + inline: true, + dest: './', + sprite: `iconssmall@2.5x.svg`, + }, + }, + } + }, + veiconsbig: { + src: [`${_prefix}apps/common/main/resources/img/toolbar/2.5x/big/*.svg`, + `${_prefix}apps/visioeditor/main/resources/img/toolbar/2.5x/big/*.svg`], + dest: `${_prefix}apps/visioeditor/main/resources/img/`, + options: { + mode: { + symbol: { + inline: true, + dest: './', + sprite: `iconsbig@2.5x.svg`, + }, + }, + } + }, + veiconshuge: { + src: [`${_prefix}apps/common/main/resources/img/toolbar/2.5x/huge/*.svg`, + `${_prefix}apps/visioeditor/main/resources/img/toolbar/2.5x/huge/*.svg`], + dest: `${_prefix}apps/visioeditor/main/resources/img/`, + options: { + mode: { + symbol: { + inline: true, + dest: './', + sprite: `iconshuge@2.5x.svg`, + }, + }, + } + }, }, }); @@ -584,6 +684,11 @@ module.exports = function (grunt, rootpathprefix) { 'sprite:pdf1.5x', 'sprite:pdf-big-1.5x', 'sprite:pdf-huge-1.5x', 'sprite:pdf1.75x', 'sprite:pdf-big-1.75x', 'sprite:pdf-huge-1.75x']); - grunt.registerTask('all-icons-sprite', ['word-icons','slide-icons','cell-icons','pdf-icons','svg_sprite']); + grunt.registerTask('draw-icons', ['sprite:draw-1x', 'sprite:draw-big-1x', 'sprite:draw-2x', 'sprite:draw-big-2x', + 'sprite:draw-1.25x', 'sprite:draw-big-1.25x', + 'sprite:draw-1.5x', 'sprite:draw-big-1.5x', + 'sprite:draw-1.75x', 'sprite:draw-big-1.75x']); + + grunt.registerTask('all-icons-sprite', ['word-icons','slide-icons','cell-icons','pdf-icons','draw-icons','svg_sprite']); grunt.registerTask('default', ['all-icons-sprite']); }; \ No newline at end of file