From 1f04c908134a5efdea426ef519c807676050de06 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Mon, 28 Sep 2020 19:06:12 +0300
Subject: [PATCH 01/33] [DE] Add form control settings to the right panel

---
 apps/common/main/lib/util/utils.js            |   3 +-
 .../main/app/controller/RightMenu.js          |   4 +
 .../main/app/template/FormSettings.template   |  57 +++
 .../main/app/template/RightMenu.template      |   3 +
 .../main/app/view/FormSettings.js             | 388 ++++++++++++++++++
 .../documenteditor/main/app/view/RightMenu.js |  21 +-
 6 files changed, 474 insertions(+), 2 deletions(-)
 create mode 100644 apps/documenteditor/main/app/template/FormSettings.template
 create mode 100644 apps/documenteditor/main/app/view/FormSettings.js

diff --git a/apps/common/main/lib/util/utils.js b/apps/common/main/lib/util/utils.js
index e00a3b8b7..68b5f826d 100644
--- a/apps/common/main/lib/util/utils.js
+++ b/apps/common/main/lib/util/utils.js
@@ -106,7 +106,8 @@ Common.Utils = _.extend(new(function() {
             Signature  : 9,
             Pivot      : 10,
             Cell       : 11,
-            Slicer     : 12
+            Slicer     : 12,
+            Form       : 13
         },
         importTextType = {
             DRM: 0,
diff --git a/apps/documenteditor/main/app/controller/RightMenu.js b/apps/documenteditor/main/app/controller/RightMenu.js
index f33f7e4cf..dc8842090 100644
--- a/apps/documenteditor/main/app/controller/RightMenu.js
+++ b/apps/documenteditor/main/app/controller/RightMenu.js
@@ -80,6 +80,7 @@ define([
             this._settings[Common.Utils.documentSettingsType.Chart] = {panelId: "id-chart-settings",          panel: rightMenu.chartSettings,    btn: rightMenu.btnChart,       hidden: 1, locked: false};
             this._settings[Common.Utils.documentSettingsType.MailMerge] = {panelId: "id-mail-merge-settings", panel: rightMenu.mergeSettings,    btn: rightMenu.btnMailMerge,   hidden: 1, props: {}, locked: false};
             this._settings[Common.Utils.documentSettingsType.Signature] = {panelId: "id-signature-settings",  panel: rightMenu.signatureSettings, btn: rightMenu.btnSignature,  hidden: 1, props: {}, locked: false};
+            this._settings[Common.Utils.documentSettingsType.Form] = {panelId: "id-form-settings",  panel: rightMenu.formSettings, btn: rightMenu.btnForm,  hidden: 1, props: {}, locked: false};
         },
 
         setApi: function(api) {
@@ -262,6 +263,7 @@ define([
             this.rightmenu.chartSettings.updateMetricUnit();
             this.rightmenu.imageSettings.updateMetricUnit();
             this.rightmenu.tableSettings.updateMetricUnit();
+            this.rightmenu.formSettings && this.rightmenu.formSettings.updateMetricUnit();
         },
 
         createDelayedElements: function() {
@@ -347,6 +349,7 @@ define([
                 this.rightmenu.headerSettings.disableControls(disabled);
                 this.rightmenu.tableSettings.disableControls(disabled);
                 this.rightmenu.imageSettings.disableControls(disabled);
+                this.rightmenu.formSettings && this.rightmenu.formSettings.disableControls(disabled);
                 if (!allowMerge && this.rightmenu.mergeSettings) {
                     this.rightmenu.mergeSettings.disableControls(disabled);
                     disabled && this.rightmenu.btnMailMerge.setDisabled(disabled);
@@ -365,6 +368,7 @@ define([
                     this.rightmenu.btnShape.setDisabled(disabled);
                     this.rightmenu.btnTextArt.setDisabled(disabled);
                     this.rightmenu.btnChart.setDisabled(disabled);
+                    this.rightmenu.btnForm && this.rightmenu.btnForm.setDisabled(disabled);
                 } else {
                     var selectedElements = this.api.getSelectedElements();
                     if (selectedElements.length > 0)
diff --git a/apps/documenteditor/main/app/template/FormSettings.template b/apps/documenteditor/main/app/template/FormSettings.template
new file mode 100644
index 000000000..603b4d701
--- /dev/null
+++ b/apps/documenteditor/main/app/template/FormSettings.template
@@ -0,0 +1,57 @@
+<table cols="1">
+    <tr>
+        <td>
+            <label class="header" id="form-settings-name"><%= scope.textField %></label>
+        </td>
+    </tr>
+    <tr>
+        <td class="padding-small">
+            <label class="input-label"><%= scope.textKey %></label>
+            <div id="form-combo-key" style="width: 100%;"></div>
+        </td>
+    </tr>
+    <tr>
+        <td class="padding-small">
+            <label class="input-label"><%= scope.textPlaceholder %></label>
+            <div id="form-txt-pholder"></div>
+        </td>
+    </tr>
+    <tr>
+        <td class="padding-large">
+            <label class="input-label"><%= scope.textTip %></label>
+            <textarea id="form-txt-help" class="form-control" style="width: 100%; height: 90px;"></textarea>
+        </td>
+    </tr>
+    <tr>
+        <td class="padding-small">
+            <div id="form-chb-max-chars" style="display: inline-block;margin-right: 10px;"></div>
+            <div id="form-spin-max-chars" style="display: inline-block;"></div>
+        </td>
+    </tr>
+    <tr>
+        <td class="padding-small">
+            <div id="form-chb-comb"></div>
+        </td>
+    </tr>
+    <tr>
+        <td class="padding-small" colspan="2">
+            <label class="input-label" style="margin-right: 10px;"><%= scope.textWidth %></label>
+            <div id="form-spin-width" style=""></div>
+        </td>
+    </tr>
+    <tr>
+        <td class="padding-small">
+            <div class="separator horizontal"></div>
+        </td>
+    </tr>
+    <tr>
+        <td class="padding-small">
+            <div id="form-btn-delete" style="width:100%;"></div>
+        </td>
+    </tr>
+    <tr>
+        <td class="padding-small">
+            <div id="form-btn-lock" style="width:100%;"></div>
+        </td>
+    </tr>
+</table>
\ No newline at end of file
diff --git a/apps/documenteditor/main/app/template/RightMenu.template b/apps/documenteditor/main/app/template/RightMenu.template
index 7b4bb1ba8..0af6d1dda 100644
--- a/apps/documenteditor/main/app/template/RightMenu.template
+++ b/apps/documenteditor/main/app/template/RightMenu.template
@@ -18,6 +18,8 @@
         </div>
         <div id="id-signature-settings" class="settings-panel">
         </div>
+        <div id="id-form-settings" class="settings-panel">
+        </div>
     </div>
     <div class="tool-menu-btns">
         <div class="ct-btn-category arrow-left"></div>
@@ -30,5 +32,6 @@
         <button id="id-right-menu-textart" class="btn btn-category arrow-left" content-target="id-textart-settings"><i class="icon toolbar__icon btn-menu-textart">&nbsp;</i></button>
         <button id="id-right-menu-mail-merge" class="btn btn-category arrow-left hidden" content-target="id-mail-merge-settings"><i class="icon toolbar__icon btn-mailmerge">&nbsp;</i></button>
         <button id="id-right-menu-signature" class="btn btn-category arrow-left hidden" content-target="id-signature-settings"><i class="icon toolbar__icon btn-menu-signature">&nbsp;</i></button>
+        <button id="id-right-menu-form" class="btn btn-category arrow-left hidden" content-target="id-form-settings"><i class="icon toolbar__icon btn-menu-signature">&nbsp;</i></button>
     </div>
 </div>
\ No newline at end of file
diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
new file mode 100644
index 000000000..49f67fa2a
--- /dev/null
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -0,0 +1,388 @@
+/*
+ *
+ * (c) Copyright Ascensio System SIA 2010-2020
+ *
+ * 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-12 Ernesta Birznieka-Upisha
+ * 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
+ *
+ */
+/**
+ *  FormSettings.js
+ *
+ *  Created by Julia Radzhabova on 28/09/20
+ *  Copyright (c) 2020 Ascensio System SIA. All rights reserved.
+ *
+ */
+
+define([
+    'text!documenteditor/main/app/template/FormSettings.template',
+    'jquery',
+    'underscore',
+    'backbone',
+    'common/main/lib/component/ComboBox',
+    'common/main/lib/component/MetricSpinner',
+    'common/main/lib/component/CheckBox'
+], function (menuTemplate, $, _, Backbone) {
+    'use strict';
+
+    DE.Views.FormSettings = Backbone.View.extend(_.extend({
+        el: '#id-form-settings',
+
+        // Compile our stats template
+        template: _.template(menuTemplate),
+
+        // Delegated events for creating new items, and clearing completed ones.
+        events: {
+        },
+
+        options: {
+            alias: 'FormSettings'
+        },
+
+        initialize: function () {
+            this._initSettings = true;
+
+            this._state = {
+                DisabledControls: true
+            };
+            this.spinners = [];
+            this.lockedControls = [];
+            this._locked = true;
+
+            this.render();
+        },
+
+        render: function () {
+            var el = this.$el || $(this.el);
+            el.html(this.template({
+                scope: this
+            }));
+
+            this.FillColorContainer = $('#shape-panel-color-fill');
+            this.FillImageContainer = $('#shape-panel-image-fill');
+            this.FillPatternContainer = $('#shape-panel-pattern-fill');
+            this.FillGradientContainer = $('#shape-panel-gradient-fill');
+            this.TransparencyContainer = $('#shape-panel-transparent-fill');
+            this.ShapeOnlySettings = $('.shape-only');
+            this.CanChangeType = $('.change-type');
+        },
+
+        createDelayedElements: function() {
+            var $markup = this.$el || $(this.el);
+
+            var me = this;
+
+            this.labelFormName = $markup.findById('#form-settings-name');
+
+            // Short Size
+            this.cmbKey = new Common.UI.ComboBox({
+                el: $markup.findById('#form-combo-key'),
+                cls: 'input-group-nr',
+                menuStyle: 'min-width: 85px;',
+                editable: true,
+                data: [],
+                disabled: this._locked
+            });
+            this.cmbKey.setValue('');
+            this.lockedControls.push(this.cmbKey);
+            this.cmbKey.on('selected', this.onKeySelect.bind(this));
+            this.cmbKey.on('changed:after', this.onKeyChanged.bind(this));
+            this.cmbKey.on('hide:after', this.onHideMenus.bind(this));
+
+            this.txtPlaceholder = new Common.UI.InputField({
+                el          : $markup.findById('#form-txt-pholder'),
+                allowBlank  : true,
+                validateOnChange: false,
+                validateOnBlur: false,
+                style       : 'width: 100%;',
+                value       : ''
+            });
+            this.lockedControls.push(this.txtPlaceholder);
+            this.txtPlaceholder.on('changed:after', this.onPlaceholderChanged.bind(this));
+
+            this.textareaHelp = $markup.findById('#form-txt-help');
+            this.textareaHelp.keydown(function (event) {
+                if (event.keyCode == Common.UI.Keys.RETURN) {
+                    event.stopPropagation();
+                }
+                me.isHelpChanged = true;
+            });
+
+            this.chMaxChars = new Common.UI.CheckBox({
+                el: $markup.findById('#form-chb-max-chars'),
+                labelText: this.textMaxChars
+            });
+            this.chMaxChars.on('change', this.onChMaxCharsChanged.bind(this));
+            this.lockedControls.push(this.chMaxChars);
+
+            this.spnMaxChars = new Common.UI.MetricSpinner({
+                el: $markup.findById('#form-spin-max-chars'),
+                step: 1,
+                width: 53,
+                defaultUnit : "",
+                value: '10',
+                maxValue: 1000000,
+                minValue: 1
+            });
+            this.lockedControls.push(this.spnMaxChars);
+            this.spnMaxChars.on('change', this.onMaxCharsChange.bind(this));
+            this.spnMaxChars.on('inputleave', function(){ me.fireEvent('editcomplete', me);});
+
+            this.chComb = new Common.UI.CheckBox({
+                el: $markup.findById('#form-chb-comb'),
+                labelText: this.textComb
+            });
+            this.chComb.on('change', this.onChCombChanged.bind(this));
+            this.lockedControls.push(this.chComb);
+
+            this.spnWidth = new Common.UI.MetricSpinner({
+                el: $markup.findById('#form-spin-width'),
+                step: .1,
+                width: 80,
+                defaultUnit : "cm",
+                value: '3 cm',
+                maxValue: 55.88,
+                minValue: 0.1
+            });
+            this.lockedControls.push(this.spnWidth);
+            this.spnWidth.on('change', this.onWidthChange.bind(this));
+            this.spnWidth.on('inputleave', function(){ me.fireEvent('editcomplete', me);});
+
+            this.updateMetricUnit();
+        },
+
+        setApi: function(api) {
+            this.api = api;
+            if (this.api) {
+                // this.api.asc_registerCallback('asc_onParaSpacingLine', _.bind(this._onLineSpacing, this));
+            }
+            return this;
+        },
+
+        onKeySelect: function(combo, record) {
+            if (this.api)
+                this.api.put_PrLineSpacing(record.value, record.defaultValue);
+            this.numLineHeight.setDefaultUnit(this._arrLineRule[record.value].defaultUnit);
+            this.numLineHeight.setMinValue(this._arrLineRule[record.value].minValue);
+            this.numLineHeight.setStep(this._arrLineRule[record.value].step);
+            this.fireEvent('editcomplete', this);
+        },
+
+        onKeyChanged: function(combo, record) {
+            if (me._changedProps) {
+                me._changedProps.put_XAlign(undefined);
+                me._changedProps.put_X(Common.Utils.Metric.fnRecalcToMM(Common.Utils.String.parseFloat(record.value)));
+            }
+            this.fireEvent('editcomplete', this);
+        },
+
+        onPlaceholderChanged: function(input, newValue, oldValue, e) {
+            var val = parseInt(me.txtFieldNum.getValue());
+            if (val !== parseInt(oldValue)) {
+                me.api.asc_PreviewMailMergeResult(val-1);
+                me.fireEvent('editcomplete', me);
+            }
+        },
+
+        onChMaxCharsChanged: function(field, newValue, oldValue, eOpts){
+            this.spnMaxChars.setDisabled(field.getValue()!='checked');
+        },
+
+        onMaxCharsChange: function(field, newValue, oldValue, eOpts){
+            if ( this.cmbLineRule.getRawValue() === '' )
+                return;
+            var type = c_paragraphLinerule.LINERULE_AUTO;
+            if (this.api)
+                this.api.put_PrLineSpacing(this.cmbLineRule.getValue(), (this.cmbLineRule.getValue()==c_paragraphLinerule.LINERULE_AUTO) ? field.getNumberValue() : Common.Utils.Metric.fnRecalcToMM(field.getNumberValue()));
+        },
+
+        onChCombChanged: function(field, newValue, oldValue, eOpts){
+            var checked = (field.getValue()=='checked');
+            if (checked) {
+                this.chMaxChars.setValue(true);
+            }
+            this.spnWidth.setDisabled(!checked);
+            if (this.api)
+                this.api.put_AddSpaceBetweenPrg((field.getValue()=='checked'));
+            this.fireEvent('editcomplete', this);
+        },
+
+        onNumSpacingBeforeChange: function(field, newValue, oldValue, eOpts){
+            if (this.api)  {
+                var num = field.getNumberValue();
+                this._state.LineSpacingBefore = (num<0) ? -1 : Common.Utils.Metric.fnRecalcToMM(num);
+                this.api.put_LineSpacingBeforeAfter(0, this._state.LineSpacingBefore);
+            }
+        },
+
+        onNumSpacingAfterChange: function(field, newValue, oldValue, eOpts){
+            if (this.api){
+                var num = field.getNumberValue();
+                this._state.LineSpacingAfter = (num<0) ? -1 : Common.Utils.Metric.fnRecalcToMM(num);
+                this.api.put_LineSpacingBeforeAfter(1, this._state.LineSpacingAfter);
+            }
+        },
+
+        onAddIntervalChange: function(field, newValue, oldValue, eOpts){
+            if (this.api)
+                this.api.put_AddSpaceBetweenPrg((field.getValue()=='checked'));
+            this.fireEvent('editcomplete', this);
+        },
+
+        ChangeSettings: function(props) {
+            if (this._initSettings)
+                this.createDelayedElements();
+
+            this.disableControls(this._locked);
+
+            if (props) {
+                var val = props.get_PlaceholderText();
+                this.txtPlaceholder.setValue(val ? val : '');
+
+                val = props.get_Lock();
+                (val===undefined) && (val = Asc.c_oAscSdtLockType.Unlocked);
+                // this.btnLock.setValue(val==Asc.c_oAscSdtLockType.SdtContentLocked || val==Asc.c_oAscSdtLockType.SdtLocked || val==Asc.c_oAscSdtLockType.ContentLocked);
+
+                var type = props.get_SpecificType();
+                var specProps;
+                //for list controls
+                if (type == Asc.c_oAscContentControlSpecificType.ComboBox || type == Asc.c_oAscContentControlSpecificType.DropDownList) {
+                    this.labelFormName.text(type == Asc.c_oAscContentControlSpecificType.ComboBox ? this.textCombobox : this.textDropDown);
+                    specProps = (type == Asc.c_oAscContentControlSpecificType.ComboBox) ? props.get_ComboBoxPr() : props.get_DropDownListPr();
+                    if (specProps) {
+                        var count = specProps.get_ItemsCount();
+                        var arr = [];
+                        for (var i=0; i<count; i++) {
+                            arr.push({
+                                value: specProps.get_ItemValue(i),
+                                name: specProps.get_ItemDisplayText(i)
+                            });
+                        }
+                        this.list.store.reset(arr);
+                    }
+                    this.disableListButtons();
+                }
+
+                if (type == Asc.c_oAscContentControlSpecificType.CheckBox) {
+                    specProps = props.get_CheckBoxPr();
+                }
+
+                this.type = type;
+
+                // form settings
+                var formPr = props.get_FormPr();
+                if (formPr) {
+                    val = formPr.get_Key();
+                    this.cmbKey.setValue(val ? val : '');
+
+                    val = formPr.get_HelpText();
+                    this.textareaHelp.val(val ? val : '');
+
+                    var hidden = true;
+                    if (type == Asc.c_oAscContentControlSpecificType.CheckBox && specProps) {
+                        val = specProps.get_GroupKey();
+                        this.txtGroupKey.setValue(val ? val : '');
+                        hidden = (typeof val !== 'string');
+                        this.labelFormName.text(hidden ? this.textCheckBox : this.textRadiobox);
+                    }
+                    this.$el.find('.group-key').toggleClass('hidden', hidden);
+                }
+
+                var formTextPr = props.get_TextFormPr();
+                if (formTextPr) {
+                    this.labelFormName.text(this.textField);
+                    val = formTextPr.get_Comb();
+                    if ( this._state.Comb!==val ) {
+                        this.chComb.setValue(!!val, true);
+                        this._state.Comb=val;
+                    }
+
+                    this.spnWidth.setDisabled(!val);
+                    val = formTextPr.get_Width();
+                    if ( Math.abs(this._state.Width-val)>0.1) {
+                        this.spnWidth.setValue(val ? val : '', true);
+                        this._state.Width=val;
+                    }
+
+                    val = formTextPr.get_MaxCharacters();
+                    if ( Math.abs(this._state.MaxChars-val)>0.1) {
+                        this.chMaxChars.setValue(val && val>=0, true);
+                        this.spnMaxChars.setDisabled(!val || val<0);
+                        this.spnMaxChars.setValue(val && val>=0 ? val : 10, true);
+                        this._state.MaxChars=val;
+                    }
+                }
+            }
+        },
+
+        updateMetricUnit: function() {
+            if (this.spinners) {
+                for (var i=0; i<this.spinners.length; i++) {
+                    var spinner = this.spinners[i];
+                    spinner.setDefaultUnit(Common.Utils.Metric.getCurrentMetricName());
+                    spinner.setStep(Common.Utils.Metric.getCurrentMetric()==Common.Utils.Metric.c_MetricUnits.pt ? 1 : 0.01);
+                }
+            }
+        },
+
+        onHideMenus: function(menu, e, isFromInputControl){
+            if (!isFromInputControl) this.fireEvent('editcomplete', this);
+        },
+
+        setLocked: function (locked) {
+            this._locked = locked;
+        },
+
+        disableControls: function(disable) {
+            if (this._state.DisabledControls!==disable) {
+                this._state.DisabledControls = disable;
+                _.each(this.lockedControls, function(item) {
+                    item.setDisabled(disable);
+                });
+                this.textTip.toggleClass('disabled', disable);
+            }
+        },
+
+        hideTextOnlySettings: function(value) {
+            if (this._state.HideTextOnlySettings !== value) {
+                this._state.HideTextOnlySettings = value;
+                this.TextOnlySettings.toggleClass('hidden', value==true);
+            }
+        },
+
+        textField: 'Text field',
+        textKey: 'Key',
+        textPlaceholder: 'Placeholder',
+        textTip: 'Tip',
+        textMaxChars: 'Characters limit',
+        textComb: 'Comb of characters',
+        textWidth: 'Width',
+        textDelete: 'Delete',
+        textLock: 'Lock'
+
+    }, DE.Views.FormSettings || {}));
+});
\ No newline at end of file
diff --git a/apps/documenteditor/main/app/view/RightMenu.js b/apps/documenteditor/main/app/view/RightMenu.js
index a56cdb917..aa08e0d73 100644
--- a/apps/documenteditor/main/app/view/RightMenu.js
+++ b/apps/documenteditor/main/app/view/RightMenu.js
@@ -58,6 +58,7 @@ define([
     'documenteditor/main/app/view/MailMergeSettings',
     'documenteditor/main/app/view/TextArtSettings',
     'documenteditor/main/app/view/SignatureSettings',
+    'documenteditor/main/app/view/FormSettings',
     'common/main/lib/component/Scroller'
 ], function (menuTemplate, $, _, Backbone) {
     'use strict';
@@ -210,6 +211,22 @@ define([
                 this.signatureSettings = new DE.Views.SignatureSettings();
             }
 
+            if (mode && mode.canFeatureContentControl && mode.canEditContentControl) {
+                this.btnForm = new Common.UI.Button({
+                    hint: this.txtFormSettings,
+                    asctype: Common.Utils.documentSettingsType.Form,
+                    enableToggle: true,
+                    disabled: true,
+                    toggleGroup: 'tabpanelbtnsGroup',
+                    allowMouseEventsOnDisabled: true
+                });
+                this._settings[Common.Utils.documentSettingsType.Form]   = {panel: "id-form-settings",      btn: this.btnForm};
+                this.btnForm.setElement($markup.findById('#id-right-menu-form'), false); this.btnForm.render().setVisible(true);
+                this.btnForm.on('click', this.onBtnMenuClick.bind(this));
+                this.formSettings = new DE.Views.FormSettings();
+            }
+
+
             if (_.isUndefined(this.scroller)) {
                 this.scroller = new Common.UI.Scroller({
                     el: $(this.el).find('.right-panel'),
@@ -242,6 +259,7 @@ define([
             this.textartSettings.setApi(api).on('editcomplete', _fire_editcomplete);
             if (this.mergeSettings) this.mergeSettings.setApi(api).on('editcomplete', _fire_editcomplete);
             if (this.signatureSettings) this.signatureSettings.setApi(api).on('editcomplete', _fire_editcomplete);
+            if (this.formSettings) this.formSettings.setApi(api).on('editcomplete', _fire_editcomplete);
         },
 
         setMode: function(mode) {
@@ -326,6 +344,7 @@ define([
         txtTextArtSettings:         'Text Art Settings',
         txtChartSettings:           'Chart Settings',
         txtMailMergeSettings:       'Mail Merge Settings',
-        txtSignatureSettings:       'Signature Settings'
+        txtSignatureSettings:       'Signature Settings',
+        txtFormSettings:            'Form Settings'
     }, DE.Views.RightMenu || {}));
 });
\ No newline at end of file

From 8170eb0a22841ee403f1c5daface6e7f7e7e60e1 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Mon, 28 Sep 2020 19:52:48 +0300
Subject: [PATCH 02/33] [DE] Debug form settings

---
 .../main/app/controller/RightMenu.js          | 11 +++++++--
 .../main/app/view/FormSettings.js             | 24 +++++++++++++++++++
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/apps/documenteditor/main/app/controller/RightMenu.js b/apps/documenteditor/main/app/controller/RightMenu.js
index dc8842090..0686c3460 100644
--- a/apps/documenteditor/main/app/controller/RightMenu.js
+++ b/apps/documenteditor/main/app/controller/RightMenu.js
@@ -125,6 +125,7 @@ define([
             this._settings[Common.Utils.documentSettingsType.Signature].locked = false;
 
             var isChart = false;
+            var control_props = this.api.asc_IsContentControl() ? this.api.asc_GetContentControlProperties() : null;
             for (i=0; i<SelectedObjects.length; i++)
             {
                 var content_locked = false;
@@ -138,8 +139,7 @@ define([
 
                 var value = SelectedObjects[i].get_ObjectValue();
                 if (settingsType == Common.Utils.documentSettingsType.Image) {
-                    var control_props = this.api.asc_IsContentControl() ? this.api.asc_GetContentControlProperties() : null,
-                        lock_type = (control_props) ? control_props.get_Lock() : Asc.c_oAscSdtLockType.Unlocked;
+                    var lock_type = (control_props) ? control_props.get_Lock() : Asc.c_oAscSdtLockType.Unlocked;
                     content_locked = lock_type==Asc.c_oAscSdtLockType.SdtContentLocked || lock_type==Asc.c_oAscSdtLockType.ContentLocked;
 
                     if (value.get_ChartProperties() !== null) {
@@ -167,6 +167,13 @@ define([
                     this._settings[Common.Utils.documentSettingsType.Signature].locked = value.get_Locked();
             }
 
+            if (control_props) {
+                settingsType = Common.Utils.documentSettingsType.Form;
+                this._settings[settingsType].props = control_props;
+                this._settings[settingsType].locked = false;
+                this._settings[settingsType].hidden = 0;
+            }
+
             if ( this._settings[Common.Utils.documentSettingsType.Header].locked ) { // если находимся в locked header/footer, то считаем, что все элементы в нем тоже недоступны
                 for (i=0; i<this._settings.length; i++)  {
                     if (this._settings[i])
diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index 49f67fa2a..dd281f841 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -172,6 +172,30 @@ define([
             this.spnWidth.on('change', this.onWidthChange.bind(this));
             this.spnWidth.on('inputleave', function(){ me.fireEvent('editcomplete', me);});
 
+            this.btnRemForm = new Common.UI.Button({
+                parentEl: $markup.findById('#form-btn-delete'),
+                cls         : 'btn-toolbar',
+                iconCls     : 'toolbar__icon btn-remove-duplicates',
+                caption     : this.textDelete,
+                style       : 'width: 100%;text-align: left;'
+            });
+            this.btnRemForm.on('click', _.bind(function(btn){
+                this.api.asc_RemoveContentControlWrapper(this._state.id);
+            }, this));
+            this.lockedControls.push(this.btnRemForm);
+
+            this.btnLockForm = new Common.UI.Button({
+                parentEl: $markup.findById('#form-btn-lock'),
+                cls         : 'btn-toolbar',
+                iconCls     : 'toolbar__icon btn-remove-duplicates',
+                caption     : this.textLock,
+                style       : 'width: 100%;text-align: left;'
+            });
+            this.btnLockForm.on('click', _.bind(function(btn){
+
+            }, this));
+            this.lockedControls.push(this.btnLockForm);
+
             this.updateMetricUnit();
         },
 

From 16d9a78d8f80acbe646f41ca7f7bfc4b2e6ae8c8 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Wed, 30 Sep 2020 10:24:52 +0300
Subject: [PATCH 03/33] [Common] Add textarea component. Refactoring input

---
 apps/common/main/lib/component/InputField.js  |   4 +
 .../main/lib/component/TextareaField.js       | 201 ++++++++++++++++++
 2 files changed, 205 insertions(+)
 create mode 100644 apps/common/main/lib/component/TextareaField.js

diff --git a/apps/common/main/lib/component/InputField.js b/apps/common/main/lib/component/InputField.js
index df8164441..4a669e241 100644
--- a/apps/common/main/lib/component/InputField.js
+++ b/apps/common/main/lib/component/InputField.js
@@ -246,6 +246,10 @@ define([
 
                 if (e.keyCode === Common.UI.Keys.RETURN)
                     this._doChange(e);
+                if (e.keyCode == Common.UI.Keys.ESC)
+                    this.setValue(this.value);
+                if (e.keyCode==Common.UI.Keys.RETURN || e.keyCode==Common.UI.Keys.ESC)
+                    this.trigger('inputleave', this);
             },
 
             onKeyUp: function(e) {
diff --git a/apps/common/main/lib/component/TextareaField.js b/apps/common/main/lib/component/TextareaField.js
new file mode 100644
index 000000000..757642483
--- /dev/null
+++ b/apps/common/main/lib/component/TextareaField.js
@@ -0,0 +1,201 @@
+/*
+ *
+ * (c) Copyright Ascensio System SIA 2010-2020
+ *
+ * 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-12 Ernesta Birznieka-Upisha
+ * 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
+ *
+ */
+/**
+ *  TextareaField.js
+ *
+ *  Created by Julia Radzhabova on 29/09/20
+ *  Copyright (c) 2020 Ascensio System SIA. All rights reserved.
+ *
+ */
+
+if (Common === undefined)
+    var Common = {};
+
+define([
+    'common/main/lib/component/BaseView',
+    'common/main/lib/component/Tooltip'
+], function () { 'use strict';
+
+    Common.UI.TextareaField = Common.UI.BaseView.extend((function() {
+        return {
+            options : {
+                id          : null,
+                cls         : '',
+                style       : '',
+                value       : '',
+                maxlength   : undefined,
+                placeHolder : '',
+                spellcheck  : false,
+                disabled: false
+            },
+
+            template: _.template([
+                '<div class="textarea-field" style="<%= style %>">',
+                    '<textarea ',
+                    'spellcheck="<%= spellcheck %>" ',
+                    'class="form-control <%= cls %>" ',
+                    'placeholder="<%= placeHolder %>" ',
+                    '></textarea>',
+                '</div>'
+            ].join('')),
+
+            initialize : function(options) {
+                Common.UI.BaseView.prototype.initialize.call(this, options);
+
+                var me = this;
+
+                this.id             = me.options.id || Common.UI.getId();
+                this.cls            = me.options.cls;
+                this.style          = me.options.style;
+                this.value          = me.options.value;
+                this.placeHolder    = me.options.placeHolder;
+                this.template       = me.options.template || me.template;
+                this.disabled       = me.options.disabled;
+                this.spellcheck     = me.options.spellcheck;
+                this.maxLength      = me.options.maxLength;
+
+                me.rendered         = me.options.rendered || false;
+
+                if (me.options.el) {
+                    me.render();
+                }
+            },
+
+            render : function(parentEl) {
+                var me = this;
+
+                if (!me.rendered) {
+                    this.cmpEl = $(this.template({
+                        id          : this.id,
+                        cls         : this.cls,
+                        style       : this.style,
+                        placeHolder : this.placeHolder,
+                        spellcheck  : this.spellcheck,
+                        scope       : me
+                    }));
+
+                    if (parentEl) {
+                        this.setElement(parentEl, false);
+                        parentEl.html(this.cmpEl);
+                    } else {
+                        this.$el.html(this.cmpEl);
+                    }
+                } else {
+                    this.cmpEl = this.$el;
+                }
+
+                if (!me.rendered) {
+                    var el = this.cmpEl;
+
+                    this._input = this.cmpEl.find('textarea').addBack().filter('textarea');
+                    this._input.on('blur',   _.bind(this.onInputChanged, this));
+                    this._input.on('keydown',    _.bind(this.onKeyDown, this));
+                    if (this.maxLength) this._input.attr('maxlength', this.maxLength);
+
+                    if (this.disabled)
+                        this.setDisabled(this.disabled);
+                }
+
+                me.rendered = true;
+
+                return this;
+            },
+
+            _doChange: function(e, extra) {
+                // skip processing for internally-generated synthetic event
+                // to avoid double processing
+                if (extra && extra.synthetic)
+                    return;
+
+                var newValue = $(e.target).val(),
+                    oldValue = this.value;
+
+                this.trigger('changed:before', this, newValue, oldValue, e);
+
+                if (e.isDefaultPrevented())
+                    return;
+
+                this.value = newValue;
+
+                // trigger changed event
+                this.trigger('changed:after', this, newValue, oldValue, e);
+            },
+
+            onInputChanged: function(e, extra) {
+                this._doChange(e, extra);
+            },
+
+            onKeyDown: function(e) {
+                this.trigger('keydown:before', this, e);
+
+                if (e.isDefaultPrevented())
+                    return;
+
+                if (e.keyCode === Common.UI.Keys.RETURN)
+                    this._doChange(e);
+                if (e.keyCode == Common.UI.Keys.ESC)
+                    this.setValue(this.value);
+                if (e.keyCode==Common.UI.Keys.RETURN || e.keyCode==Common.UI.Keys.ESC)
+                    this.trigger('inputleave', this);
+            },
+
+            setDisabled: function(disabled) {
+                this.disabled = disabled;
+                $(this.el).toggleClass('disabled', disabled);
+                disabled
+                    ? this._input.attr('disabled', true)
+                    : this._input.removeAttr('disabled');
+            },
+
+            isDisabled: function() {
+                return this.disabled;
+            },
+
+            setValue: function(value) {
+                this.value = value;
+
+                if (this.rendered){
+                    this._input.val(value);
+                }
+            },
+
+            getValue: function() {
+                return this.value;
+            },
+
+            focus: function() {
+                this._input.focus();
+            }
+        }
+    })());
+});

From 3234492cccf84cf1e32d2a0e85d1735e30ba4300 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Wed, 30 Sep 2020 10:33:38 +0300
Subject: [PATCH 04/33] [DE] Refactoring form settings

---
 .../main/app/controller/RightMenu.js          |  14 +-
 .../main/app/template/FormSettings.template   |  25 +-
 .../main/app/view/ControlSettingsDialog.js    |  15 +-
 .../main/app/view/FormSettings.js             | 234 +++++++++++-------
 4 files changed, 182 insertions(+), 106 deletions(-)

diff --git a/apps/documenteditor/main/app/controller/RightMenu.js b/apps/documenteditor/main/app/controller/RightMenu.js
index 0686c3460..7f4d50648 100644
--- a/apps/documenteditor/main/app/controller/RightMenu.js
+++ b/apps/documenteditor/main/app/controller/RightMenu.js
@@ -167,11 +167,15 @@ define([
                     this._settings[Common.Utils.documentSettingsType.Signature].locked = value.get_Locked();
             }
 
-            if (control_props) {
-                settingsType = Common.Utils.documentSettingsType.Form;
-                this._settings[settingsType].props = control_props;
-                this._settings[settingsType].locked = false;
-                this._settings[settingsType].hidden = 0;
+            if (control_props && control_props.get_FormPr()) {
+                var spectype = control_props.get_SpecificType();
+                if (spectype==Asc.c_oAscContentControlSpecificType.CheckBox || spectype==Asc.c_oAscContentControlSpecificType.Picture ||
+                    spectype==Asc.c_oAscContentControlSpecificType.ComboBox || spectype==Asc.c_oAscContentControlSpecificType.DropDownList || spectype==Asc.c_oAscContentControlSpecificType.None) {
+                    settingsType = Common.Utils.documentSettingsType.Form;
+                    this._settings[settingsType].props = control_props;
+                    this._settings[settingsType].locked = false;
+                    this._settings[settingsType].hidden = 0;
+                }
             }
 
             if ( this._settings[Common.Utils.documentSettingsType.Header].locked ) { // если находимся в locked header/footer, то считаем, что все элементы в нем тоже недоступны
diff --git a/apps/documenteditor/main/app/template/FormSettings.template b/apps/documenteditor/main/app/template/FormSettings.template
index 603b4d701..346845393 100644
--- a/apps/documenteditor/main/app/template/FormSettings.template
+++ b/apps/documenteditor/main/app/template/FormSettings.template
@@ -1,7 +1,7 @@
 <table cols="1">
     <tr>
         <td>
-            <label class="header" id="form-settings-name"><%= scope.textField %></label>
+            <label class="header padding-small" id="form-settings-name"><%= scope.textField %></label>
         </td>
     </tr>
     <tr>
@@ -10,7 +10,7 @@
             <div id="form-combo-key" style="width: 100%;"></div>
         </td>
     </tr>
-    <tr>
+    <tr class="form-panel-textfield">
         <td class="padding-small">
             <label class="input-label"><%= scope.textPlaceholder %></label>
             <div id="form-txt-pholder"></div>
@@ -19,24 +19,24 @@
     <tr>
         <td class="padding-large">
             <label class="input-label"><%= scope.textTip %></label>
-            <textarea id="form-txt-help" class="form-control" style="width: 100%; height: 90px;"></textarea>
+            <div id="form-txt-help"></div>
         </td>
     </tr>
-    <tr>
+    <tr class="form-panel-textfield">
         <td class="padding-small">
-            <div id="form-chb-max-chars" style="display: inline-block;margin-right: 10px;"></div>
-            <div id="form-spin-max-chars" style="display: inline-block;"></div>
+            <div id="form-chb-max-chars" style="display: inline-block;margin-top: 4px;"></div>
+            <div id="form-spin-max-chars" style="display: inline-block;float: right;"></div>
         </td>
     </tr>
-    <tr>
+    <tr class="form-panel-textfield">
         <td class="padding-small">
             <div id="form-chb-comb"></div>
         </td>
     </tr>
-    <tr>
+    <tr class="form-panel-textfield">
         <td class="padding-small" colspan="2">
-            <label class="input-label" style="margin-right: 10px;"><%= scope.textWidth %></label>
-            <div id="form-spin-width" style=""></div>
+            <label class="input-label" style="margin-left: 22px;margin-top: 4px;"><%= scope.textWidth %></label>
+            <div id="form-spin-width" style="display: inline-block; float: right;"></div>
         </td>
     </tr>
     <tr>
@@ -46,12 +46,13 @@
     </tr>
     <tr>
         <td class="padding-small">
-            <div id="form-btn-delete" style="width:100%;"></div>
+            <div id="form-btn-delete"></div>
         </td>
     </tr>
     <tr>
         <td class="padding-small">
-            <div id="form-btn-lock" style="width:100%;"></div>
+            <div id="form-btn-lock"></div>
         </td>
     </tr>
+    <tr class="finish-cell"></tr>
 </table>
\ No newline at end of file
diff --git a/apps/documenteditor/main/app/view/ControlSettingsDialog.js b/apps/documenteditor/main/app/view/ControlSettingsDialog.js
index 5b4d78bee..c24ff3024 100644
--- a/apps/documenteditor/main/app/view/ControlSettingsDialog.js
+++ b/apps/documenteditor/main/app/view/ControlSettingsDialog.js
@@ -307,7 +307,8 @@ define([ 'text!documenteditor/main/app/template/ControlSettingsDialog.template',
                 step: .1,
                 width: 80,
                 defaultUnit : "cm",
-                value: '3 cm',
+                value: 'Auto',
+                allowAuto: true,
                 maxValue: 55.88,
                 minValue: 0.1
             });
@@ -522,7 +523,7 @@ define([ 'text!documenteditor/main/app/template/ControlSettingsDialog.template',
                     this.spnMaxChars.setValue(val && val>=0 ? val : 10);
 
                     val = formTextPr.get_Width();
-                    this.spnWidth.setValue(val ? val : '', true);
+                    this.spnWidth.setValue(val!==0 && val!==undefined ? Common.Utils.Metric.fnRecalcFromMM(val * 25.4 / 20 / 72.0) : -1, true);
                 }
             }
         },
@@ -607,8 +608,12 @@ define([ 'text!documenteditor/main/app/template/ControlSettingsDialog.template',
 
             if (this.btnsCategory[5].isVisible()) {
                 var formTextPr = new AscCommon.CSdtTextFormPr();
-                if (this.spnWidth.getValue())
-                    formTextPr.put_Width(this.spnWidth.getNumberValue());
+                if (this.spnWidth.getValue()) {
+                    var value = this.spnWidth.getNumberValue();
+                    formTextPr.put_Width(value<=0 ? 0 : parseInt(Common.Utils.Metric.fnRecalcToMM(value) * 72 * 20 / 25.4));
+                } else
+                    formTextPr.put_Width(0);
+
                 if (this.placeholder && this.placeholder.changed) {
                     formTextPr.put_PlaceHolderSymbol(this.placeholder.code);
                     formTextPr.put_PlaceHolderFont(this.placeholder.font);
@@ -618,7 +623,7 @@ define([ 'text!documenteditor/main/app/template/ControlSettingsDialog.template',
                 var checked = (this.chMaxChars.getValue()=='checked' || this.chComb.getValue()=='checked');
                 formTextPr.put_MaxCharacters(checked);
                 if (checked)
-                    formTextPr.put_MaxCharacters(this.spnMaxChars.getNumberValue() || 12);
+                    formTextPr.put_MaxCharacters(this.spnMaxChars.getNumberValue() || 10);
 
                 props.put_TextFormPr(formTextPr);
             }
diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index dd281f841..7cd239b05 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -45,6 +45,7 @@ define([
     'backbone',
     'common/main/lib/component/ComboBox',
     'common/main/lib/component/MetricSpinner',
+    'common/main/lib/component/TextareaField',
     'common/main/lib/component/CheckBox'
 ], function (menuTemplate, $, _, Backbone) {
     'use strict';
@@ -71,7 +72,12 @@ define([
             };
             this.spinners = [];
             this.lockedControls = [];
+            this.internalId = null;
             this._locked = true;
+            this._originalTextFormProps = null;
+            this._originalFormProps = null;
+            this._originalProps = null;
+            this._lockedControl = false;
 
             this.render();
         },
@@ -82,16 +88,12 @@ define([
                 scope: this
             }));
 
-            this.FillColorContainer = $('#shape-panel-color-fill');
-            this.FillImageContainer = $('#shape-panel-image-fill');
-            this.FillPatternContainer = $('#shape-panel-pattern-fill');
-            this.FillGradientContainer = $('#shape-panel-gradient-fill');
-            this.TransparencyContainer = $('#shape-panel-transparent-fill');
-            this.ShapeOnlySettings = $('.shape-only');
-            this.CanChangeType = $('.change-type');
+            this.textFieldContainer = el.find('.form-panel-textfield');
         },
 
         createDelayedElements: function() {
+            this._initSettings = false;
+
             var $markup = this.$el || $(this.el);
 
             var me = this;
@@ -102,14 +104,14 @@ define([
             this.cmbKey = new Common.UI.ComboBox({
                 el: $markup.findById('#form-combo-key'),
                 cls: 'input-group-nr',
-                menuStyle: 'min-width: 85px;',
+                menuStyle: 'min-width: 100%;',
                 editable: true,
                 data: [],
                 disabled: this._locked
             });
             this.cmbKey.setValue('');
             this.lockedControls.push(this.cmbKey);
-            this.cmbKey.on('selected', this.onKeySelect.bind(this));
+            this.cmbKey.on('selected', this.onKeyChanged.bind(this));
             this.cmbKey.on('changed:after', this.onKeyChanged.bind(this));
             this.cmbKey.on('hide:after', this.onHideMenus.bind(this));
 
@@ -123,14 +125,16 @@ define([
             });
             this.lockedControls.push(this.txtPlaceholder);
             this.txtPlaceholder.on('changed:after', this.onPlaceholderChanged.bind(this));
+            this.txtPlaceholder.on('inputleave', function(){ me.fireEvent('editcomplete', me);});
 
-            this.textareaHelp = $markup.findById('#form-txt-help');
-            this.textareaHelp.keydown(function (event) {
-                if (event.keyCode == Common.UI.Keys.RETURN) {
-                    event.stopPropagation();
-                }
-                me.isHelpChanged = true;
+            this.textareaHelp = new Common.UI.TextareaField({
+                el          : $markup.findById('#form-txt-help'),
+                style       : 'width: 100%; height: 90px;',
+                value       : ''
             });
+            this.lockedControls.push(this.textareaHelp);
+            this.textareaHelp.on('changed:after', this.onHelpChanged.bind(this));
+            this.textareaHelp.on('inputleave', function(){ me.fireEvent('editcomplete', me);});
 
             this.chMaxChars = new Common.UI.CheckBox({
                 el: $markup.findById('#form-chb-max-chars'),
@@ -142,7 +146,7 @@ define([
             this.spnMaxChars = new Common.UI.MetricSpinner({
                 el: $markup.findById('#form-spin-max-chars'),
                 step: 1,
-                width: 53,
+                width: 48,
                 defaultUnit : "",
                 value: '10',
                 maxValue: 1000000,
@@ -162,9 +166,10 @@ define([
             this.spnWidth = new Common.UI.MetricSpinner({
                 el: $markup.findById('#form-spin-width'),
                 step: .1,
-                width: 80,
+                width: 64,
                 defaultUnit : "cm",
-                value: '3 cm',
+                value: 'Auto',
+                allowAuto: true,
                 maxValue: 55.88,
                 minValue: 0.1
             });
@@ -177,7 +182,7 @@ define([
                 cls         : 'btn-toolbar',
                 iconCls     : 'toolbar__icon btn-remove-duplicates',
                 caption     : this.textDelete,
-                style       : 'width: 100%;text-align: left;'
+                style       : 'text-align: left;'
             });
             this.btnRemForm.on('click', _.bind(function(btn){
                 this.api.asc_RemoveContentControlWrapper(this._state.id);
@@ -189,10 +194,14 @@ define([
                 cls         : 'btn-toolbar',
                 iconCls     : 'toolbar__icon btn-remove-duplicates',
                 caption     : this.textLock,
-                style       : 'width: 100%;text-align: left;'
+                style       : 'text-align: left;'
             });
             this.btnLockForm.on('click', _.bind(function(btn){
-
+                if (this.api  && !this._noApply) {
+                    var props   = this._originalProps || new AscCommon.CContentControlPr();
+                    props.put_Lock(!this._lockedControl ? Asc.c_oAscSdtLockType.SdtContentLocked : Asc.c_oAscSdtLockType.Unlocked);
+                    this.api.asc_SetContentControlProperties(props, this.internalId);
+                }
             }, this));
             this.lockedControls.push(this.btnLockForm);
 
@@ -207,74 +216,101 @@ define([
             return this;
         },
 
-        onKeySelect: function(combo, record) {
-            if (this.api)
-                this.api.put_PrLineSpacing(record.value, record.defaultValue);
-            this.numLineHeight.setDefaultUnit(this._arrLineRule[record.value].defaultUnit);
-            this.numLineHeight.setMinValue(this._arrLineRule[record.value].minValue);
-            this.numLineHeight.setStep(this._arrLineRule[record.value].step);
-            this.fireEvent('editcomplete', this);
-        },
-
         onKeyChanged: function(combo, record) {
-            if (me._changedProps) {
-                me._changedProps.put_XAlign(undefined);
-                me._changedProps.put_X(Common.Utils.Metric.fnRecalcToMM(Common.Utils.String.parseFloat(record.value)));
+            if (this.api && !this._noApply) {
+                var props   = this._originalProps || new AscCommon.CContentControlPr();
+                var formPr = this._originalFormProps || new AscCommon.CSdtFormPr();
+                formPr.put_Key(record.value);
+                props.put_FormPr(formPr);
+                this.api.asc_SetContentControlProperties(props, this.internalId);
+                this.fireEvent('editcomplete', this);
             }
-            this.fireEvent('editcomplete', this);
         },
 
         onPlaceholderChanged: function(input, newValue, oldValue, e) {
-            var val = parseInt(me.txtFieldNum.getValue());
-            if (val !== parseInt(oldValue)) {
-                me.api.asc_PreviewMailMergeResult(val-1);
-                me.fireEvent('editcomplete', me);
+            if (this.api && !this._noApply) {
+                var props   = this._originalProps || new AscCommon.CContentControlPr();
+                props.put_PlaceholderText(newValue);
+                this.api.asc_SetContentControlProperties(props, this.internalId);
+                this.fireEvent('editcomplete', this);
+            }
+        },
+
+        onHelpChanged: function(input, newValue, oldValue, e) {
+            if (this.api && !this._noApply) {
+                var props   = this._originalProps || new AscCommon.CContentControlPr();
+                var formPr = this._originalFormProps || new AscCommon.CSdtFormPr();
+                formPr.put_HelpText(newValue);
+                props.put_FormPr(formPr);
+                this.api.asc_SetContentControlProperties(props, this.internalId);
+                this.fireEvent('editcomplete', this);
             }
         },
 
         onChMaxCharsChanged: function(field, newValue, oldValue, eOpts){
             this.spnMaxChars.setDisabled(field.getValue()!='checked');
+            if (this.api && !this._noApply) {
+                var props   = this._originalProps || new AscCommon.CContentControlPr();
+                var formTextPr = this._originalTextFormProps || new AscCommon.CSdtTextFormPr();
+                var checked = (field.getValue()=='checked' || this.chComb.getValue()=='checked');
+                formTextPr.put_MaxCharacters(checked ? (this.spnMaxChars.getNumberValue() || 10) : checked);
+                props.put_TextFormPr(formTextPr);
+                this.api.asc_SetContentControlProperties(props, this.internalId);
+                this.fireEvent('editcomplete', this);
+            }
         },
 
         onMaxCharsChange: function(field, newValue, oldValue, eOpts){
-            if ( this.cmbLineRule.getRawValue() === '' )
-                return;
-            var type = c_paragraphLinerule.LINERULE_AUTO;
-            if (this.api)
-                this.api.put_PrLineSpacing(this.cmbLineRule.getValue(), (this.cmbLineRule.getValue()==c_paragraphLinerule.LINERULE_AUTO) ? field.getNumberValue() : Common.Utils.Metric.fnRecalcToMM(field.getNumberValue()));
+            if (this.api && !this._noApply) {
+                var props   = this._originalProps || new AscCommon.CContentControlPr();
+                var formTextPr = this._originalTextFormProps || new AscCommon.CSdtTextFormPr();
+                var checked = (this.chMaxChars.getValue()=='checked' || this.chComb.getValue()=='checked');
+                formTextPr.put_MaxCharacters(checked ? (field.getNumberValue() || 10) : checked);
+                props.put_TextFormPr(formTextPr);
+                this.api.asc_SetContentControlProperties(props, this.internalId);
+                this.fireEvent('editcomplete', this);
+            }
         },
 
         onChCombChanged: function(field, newValue, oldValue, eOpts){
             var checked = (field.getValue()=='checked');
             if (checked) {
-                this.chMaxChars.setValue(true);
+                this.chMaxChars.setValue(true, true);
+                this.spnMaxChars.setDisabled(false);
             }
             this.spnWidth.setDisabled(!checked);
-            if (this.api)
-                this.api.put_AddSpaceBetweenPrg((field.getValue()=='checked'));
-            this.fireEvent('editcomplete', this);
-        },
-
-        onNumSpacingBeforeChange: function(field, newValue, oldValue, eOpts){
-            if (this.api)  {
-                var num = field.getNumberValue();
-                this._state.LineSpacingBefore = (num<0) ? -1 : Common.Utils.Metric.fnRecalcToMM(num);
-                this.api.put_LineSpacingBeforeAfter(0, this._state.LineSpacingBefore);
+            if (this.api && !this._noApply) {
+                var props   = this._originalProps || new AscCommon.CContentControlPr();
+                var formTextPr = this._originalTextFormProps || new AscCommon.CSdtTextFormPr();
+                formTextPr.put_Comb(checked);
+                if (checked) {
+                    formTextPr.put_MaxCharacters(this.spnMaxChars.getNumberValue() || 10);
+                    if (this.spnWidth.getValue()) {
+                        var value = this.spnWidth.getNumberValue();
+                        formTextPr.put_Width(value<=0 ? 0 : parseInt(Common.Utils.Metric.fnRecalcToMM(value) * 72 * 20 / 25.4));
+                    } else
+                        formTextPr.put_Width(0);
+                }
+                props.put_TextFormPr(formTextPr);
+                this.api.asc_SetContentControlProperties(props, this.internalId);
+                this.fireEvent('editcomplete', this);
             }
         },
 
-        onNumSpacingAfterChange: function(field, newValue, oldValue, eOpts){
-            if (this.api){
-                var num = field.getNumberValue();
-                this._state.LineSpacingAfter = (num<0) ? -1 : Common.Utils.Metric.fnRecalcToMM(num);
-                this.api.put_LineSpacingBeforeAfter(1, this._state.LineSpacingAfter);
-            }
-        },
+        onWidthChange: function(field, newValue, oldValue, eOpts){
+            if (this.api && !this._noApply) {
+                var props   = this._originalProps || new AscCommon.CContentControlPr();
+                var formTextPr = this._originalTextFormProps || new AscCommon.CSdtTextFormPr();
+                if (this.spnWidth.getValue()) {
+                    var value = this.spnWidth.getNumberValue();
+                    formTextPr.put_Width(value<=0 ? 0 : parseInt(Common.Utils.Metric.fnRecalcToMM(value) * 72 * 20 / 25.4));
+                } else
+                    formTextPr.put_Width(0);
 
-        onAddIntervalChange: function(field, newValue, oldValue, eOpts){
-            if (this.api)
-                this.api.put_AddSpaceBetweenPrg((field.getValue()=='checked'));
-            this.fireEvent('editcomplete', this);
+                props.put_TextFormPr(formTextPr);
+                this.api.asc_SetContentControlProperties(props, this.internalId);
+                this.fireEvent('editcomplete', this);
+            }
         },
 
         ChangeSettings: function(props) {
@@ -284,12 +320,25 @@ define([
             this.disableControls(this._locked);
 
             if (props) {
+                this._originalProps = props;
+
+                this._noApply = true;
+
+                this.internalId = props.get_InternalId();
+
                 var val = props.get_PlaceholderText();
-                this.txtPlaceholder.setValue(val ? val : '');
+                if (this._state.placeholder !== val) {
+                    this.txtPlaceholder.setValue(val ? val : '');
+                    this._state.placeholder = val;
+                }
 
                 val = props.get_Lock();
                 (val===undefined) && (val = Asc.c_oAscSdtLockType.Unlocked);
-                // this.btnLock.setValue(val==Asc.c_oAscSdtLockType.SdtContentLocked || val==Asc.c_oAscSdtLockType.SdtLocked || val==Asc.c_oAscSdtLockType.ContentLocked);
+                if (this._lockedControl !== val) {
+                    this._lockedControl = (val==Asc.c_oAscSdtLockType.SdtContentLocked || val==Asc.c_oAscSdtLockType.SdtLocked || val==Asc.c_oAscSdtLockType.ContentLocked);
+                    this.btnLockForm.setCaption(this._lockedControl ? this.textUnlock : this.textLock);
+                    this.btnRemForm.setDisabled(this._lockedControl || this._locked);
+                }
 
                 var type = props.get_SpecificType();
                 var specProps;
@@ -298,6 +347,7 @@ define([
                     this.labelFormName.text(type == Asc.c_oAscContentControlSpecificType.ComboBox ? this.textCombobox : this.textDropDown);
                     specProps = (type == Asc.c_oAscContentControlSpecificType.ComboBox) ? props.get_ComboBoxPr() : props.get_DropDownListPr();
                     if (specProps) {
+                        this._originalListProps = specProps;
                         var count = specProps.get_ItemsCount();
                         var arr = [];
                         for (var i=0; i<count; i++) {
@@ -309,10 +359,9 @@ define([
                         this.list.store.reset(arr);
                     }
                     this.disableListButtons();
-                }
-
-                if (type == Asc.c_oAscContentControlSpecificType.CheckBox) {
+                } else if (type == Asc.c_oAscContentControlSpecificType.CheckBox) {
                     specProps = props.get_CheckBoxPr();
+                    this._originalCheckProps = specProps;
                 }
 
                 this.type = type;
@@ -320,24 +369,37 @@ define([
                 // form settings
                 var formPr = props.get_FormPr();
                 if (formPr) {
+                    this._originalFormProps = formPr;
+
                     val = formPr.get_Key();
-                    this.cmbKey.setValue(val ? val : '');
+                    if (this._state.key!==val) {
+                        this.cmbKey.setValue(val ? val : '');
+                        this._state.key = val;
+                    }
 
                     val = formPr.get_HelpText();
-                    this.textareaHelp.val(val ? val : '');
+                    if (this._state.help!==val) {
+                        this.textareaHelp.setValue(val ? val : '');
+                        this._state.help=val;
+                    }
 
                     var hidden = true;
                     if (type == Asc.c_oAscContentControlSpecificType.CheckBox && specProps) {
                         val = specProps.get_GroupKey();
-                        this.txtGroupKey.setValue(val ? val : '');
+                        if (this._state.groupkey!==val) {
+                            this.txtGroupKey.setValue(val ? val : '');
+                            this._state.groupkey=val;
+                        }
                         hidden = (typeof val !== 'string');
-                        this.labelFormName.text(hidden ? this.textCheckBox : this.textRadiobox);
+                        this.labelFormName.text(hidden ? this.textCheckbox : this.textRadiobox);
                     }
                     this.$el.find('.group-key').toggleClass('hidden', hidden);
                 }
 
                 var formTextPr = props.get_TextFormPr();
                 if (formTextPr) {
+                    this._originalTextFormProps = formTextPr;
+
                     this.labelFormName.text(this.textField);
                     val = formTextPr.get_Comb();
                     if ( this._state.Comb!==val ) {
@@ -347,19 +409,17 @@ define([
 
                     this.spnWidth.setDisabled(!val);
                     val = formTextPr.get_Width();
-                    if ( Math.abs(this._state.Width-val)>0.1) {
-                        this.spnWidth.setValue(val ? val : '', true);
+                    if ( (val===undefined || this._state.Width===undefined)&&(this._state.Width!==val) || Math.abs(this._state.Width-val)>0.1) {
+                        this.spnWidth.setValue(val!==0 && val!==undefined ? Common.Utils.Metric.fnRecalcFromMM(val * 25.4 / 20 / 72.0) : -1, true);
                         this._state.Width=val;
                     }
 
                     val = formTextPr.get_MaxCharacters();
-                    if ( Math.abs(this._state.MaxChars-val)>0.1) {
-                        this.chMaxChars.setValue(val && val>=0, true);
-                        this.spnMaxChars.setDisabled(!val || val<0);
-                        this.spnMaxChars.setValue(val && val>=0 ? val : 10, true);
-                        this._state.MaxChars=val;
-                    }
+                    this.chMaxChars.setValue(val && val>=0);
+                    this.spnMaxChars.setDisabled(!val || val<0);
+                    this.spnMaxChars.setValue(val && val>=0 ? val : 10);
                 }
+                this._noApply = false;
             }
         },
 
@@ -387,8 +447,8 @@ define([
                 _.each(this.lockedControls, function(item) {
                     item.setDisabled(disable);
                 });
-                this.textTip.toggleClass('disabled', disable);
             }
+            this.btnRemForm.setDisabled(this._lockedControl || disable);
         },
 
         hideTextOnlySettings: function(value) {
@@ -406,7 +466,13 @@ define([
         textComb: 'Comb of characters',
         textWidth: 'Width',
         textDelete: 'Delete',
-        textLock: 'Lock'
+        textLock: 'Lock',
+        textUnlock: 'Unlock',
+        textRadiobox: 'Radio button',
+        textCheckbox: 'Checkbox',
+        textCombobox: 'Combo box',
+        textDropDown: 'Dropdown',
+        textImage: 'Image'
 
     }, DE.Views.FormSettings || {}));
 });
\ No newline at end of file

From b46ab4e0bd62179902dcb8981424a18bfebac9b0 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Wed, 30 Sep 2020 13:25:18 +0300
Subject: [PATCH 05/33] [DE] Add check/radio form settings

---
 .../main/app/template/FormSettings.template   |  23 +++-
 .../main/app/view/FormSettings.js             | 120 ++++++++++++++++--
 2 files changed, 126 insertions(+), 17 deletions(-)

diff --git a/apps/documenteditor/main/app/template/FormSettings.template b/apps/documenteditor/main/app/template/FormSettings.template
index 346845393..af0bc4c96 100644
--- a/apps/documenteditor/main/app/template/FormSettings.template
+++ b/apps/documenteditor/main/app/template/FormSettings.template
@@ -4,13 +4,19 @@
             <label class="header padding-small" id="form-settings-name"><%= scope.textField %></label>
         </td>
     </tr>
-    <tr>
+    <tr class="form-textfield form-checkbox form-list form-image">
         <td class="padding-small">
             <label class="input-label"><%= scope.textKey %></label>
             <div id="form-combo-key" style="width: 100%;"></div>
         </td>
     </tr>
-    <tr class="form-panel-textfield">
+    <tr class="form-radiobox">
+        <td class="padding-small">
+            <label class="input-label"><%= scope.textGroupKey %></label>
+            <div id="form-combo-group-key" style="width: 100%;"></div>
+        </td>
+    </tr>
+    <tr class="form-placeholder">
         <td class="padding-small">
             <label class="input-label"><%= scope.textPlaceholder %></label>
             <div id="form-txt-pholder"></div>
@@ -22,23 +28,28 @@
             <div id="form-txt-help"></div>
         </td>
     </tr>
-    <tr class="form-panel-textfield">
+    <tr class="form-textfield">
         <td class="padding-small">
             <div id="form-chb-max-chars" style="display: inline-block;margin-top: 4px;"></div>
             <div id="form-spin-max-chars" style="display: inline-block;float: right;"></div>
         </td>
     </tr>
-    <tr class="form-panel-textfield">
+    <tr class="form-textfield">
         <td class="padding-small">
             <div id="form-chb-comb"></div>
         </td>
     </tr>
-    <tr class="form-panel-textfield">
-        <td class="padding-small" colspan="2">
+    <tr class="form-textfield">
+        <td class="padding-large" colspan="2">
             <label class="input-label" style="margin-left: 22px;margin-top: 4px;"><%= scope.textWidth %></label>
             <div id="form-spin-width" style="display: inline-block; float: right;"></div>
         </td>
     </tr>
+    <tr class="form-checkbox form-radiobox">
+        <td class="padding-large" colspan=2>
+            <div id="form-chb-selected"></div>
+        </td>
+    </tr>
     <tr>
         <td class="padding-small">
             <div class="separator horizontal"></div>
diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index 7cd239b05..fb4b225c1 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -88,7 +88,12 @@ define([
                 scope: this
             }));
 
-            this.textFieldContainer = el.find('.form-panel-textfield');
+            this.TextOnlySettings = el.find('.form-textfield');
+            this.PlaceholderSettings = el.find('.form-placeholder');
+            this.CheckOnlySettings = el.find('.form-checkbox');
+            this.RadioOnlySettings = el.find('.form-radiobox');
+            this.ListOnlySettings = el.find('.form-list');
+            this.ImageOnlySettings = el.find('.form-image');
         },
 
         createDelayedElements: function() {
@@ -100,7 +105,7 @@ define([
 
             this.labelFormName = $markup.findById('#form-settings-name');
 
-            // Short Size
+            // Common props
             this.cmbKey = new Common.UI.ComboBox({
                 el: $markup.findById('#form-combo-key'),
                 cls: 'input-group-nr',
@@ -129,13 +134,14 @@ define([
 
             this.textareaHelp = new Common.UI.TextareaField({
                 el          : $markup.findById('#form-txt-help'),
-                style       : 'width: 100%; height: 90px;',
+                style       : 'width: 100%; height: 60px;',
                 value       : ''
             });
             this.lockedControls.push(this.textareaHelp);
             this.textareaHelp.on('changed:after', this.onHelpChanged.bind(this));
             this.textareaHelp.on('inputleave', function(){ me.fireEvent('editcomplete', me);});
 
+            // Text props
             this.chMaxChars = new Common.UI.CheckBox({
                 el: $markup.findById('#form-chb-max-chars'),
                 labelText: this.textMaxChars
@@ -177,6 +183,29 @@ define([
             this.spnWidth.on('change', this.onWidthChange.bind(this));
             this.spnWidth.on('inputleave', function(){ me.fireEvent('editcomplete', me);});
 
+            // Check/Radio props
+            this.chSelected = new Common.UI.CheckBox({
+                el: $markup.findById('#form-chb-selected'),
+                labelText: this.textChecked
+            });
+            this.chSelected.on('change', this.onChSelectedChanged.bind(this));
+            this.lockedControls.push(this.chSelected);
+
+            // Radio props
+            this.cmbGroupKey = new Common.UI.ComboBox({
+                el: $markup.findById('#form-combo-group-key'),
+                cls: 'input-group-nr',
+                menuStyle: 'min-width: 100%;',
+                editable: true,
+                data: [],
+                disabled: this._locked
+            });
+            this.cmbGroupKey.setValue('');
+            this.lockedControls.push(this.cmbGroupKey);
+            this.cmbGroupKey.on('selected', this.onGroupKeyChanged.bind(this));
+            this.cmbGroupKey.on('changed:after', this.onGroupKeyChanged.bind(this));
+            this.cmbGroupKey.on('hide:after', this.onHideMenus.bind(this));
+
             this.btnRemForm = new Common.UI.Button({
                 parentEl: $markup.findById('#form-btn-delete'),
                 cls         : 'btn-toolbar',
@@ -313,6 +342,28 @@ define([
             }
         },
 
+        onChSelectedChanged: function(field, newValue, oldValue, eOpts){
+            if (this.api && !this._noApply) {
+                var props   = this._originalProps || new AscCommon.CContentControlPr();
+                var specProps = this._originalCheckProps || new AscCommon.CSdtCheckBoxPr();
+                // specProps.put_Selected(field.getValue()=='checked');
+                props.put_CheckBoxPr(specProps);
+                this.api.asc_SetContentControlProperties(props, this.internalId);
+                this.fireEvent('editcomplete', this);
+            }
+        },
+
+        onGroupKeyChanged: function(combo, record) {
+            if (this.api && !this._noApply) {
+                var props   = this._originalProps || new AscCommon.CContentControlPr();
+                var specProps = this._originalCheckProps || new AscCommon.CSdtCheckBoxPr();
+                specProps.put_GroupKey(record.value);
+                props.put_CheckBoxPr(specProps);
+                this.api.asc_SetContentControlProperties(props, this.internalId);
+                this.fireEvent('editcomplete', this);
+            }
+        },
+
         ChangeSettings: function(props) {
             if (this._initSettings)
                 this.createDelayedElements();
@@ -363,7 +414,6 @@ define([
                     specProps = props.get_CheckBoxPr();
                     this._originalCheckProps = specProps;
                 }
-
                 this.type = type;
 
                 // form settings
@@ -387,13 +437,18 @@ define([
                     if (type == Asc.c_oAscContentControlSpecificType.CheckBox && specProps) {
                         val = specProps.get_GroupKey();
                         if (this._state.groupkey!==val) {
-                            this.txtGroupKey.setValue(val ? val : '');
+                            this.cmbGroupKey.setValue(val ? val : '');
                             this._state.groupkey=val;
                         }
                         hidden = (typeof val !== 'string');
                         this.labelFormName.text(hidden ? this.textCheckbox : this.textRadiobox);
+                        this.chSelected.setCaption(hidden ? this.textChecked : this.textSelected);
+                        // val = formTextPr.get_Selected();
+                        // if ( this._state.Selected!==val ) {
+                        //     this.chSelected.setValue(!!val, true);
+                        //     this._state.Selected=val;
+                        // }
                     }
-                    this.$el.find('.group-key').toggleClass('hidden', hidden);
                 }
 
                 var formTextPr = props.get_TextFormPr();
@@ -420,6 +475,8 @@ define([
                     this.spnMaxChars.setValue(val && val>=0 ? val : 10);
                 }
                 this._noApply = false;
+
+                this.showHideControls(formTextPr, specProps);
             }
         },
 
@@ -451,10 +508,48 @@ define([
             this.btnRemForm.setDisabled(this._lockedControl || disable);
         },
 
-        hideTextOnlySettings: function(value) {
-            if (this._state.HideTextOnlySettings !== value) {
-                this._state.HideTextOnlySettings = value;
-                this.TextOnlySettings.toggleClass('hidden', value==true);
+        showHideControls: function(textProps, specProps) {
+            var textOnly = false,
+                checkboxOnly = false,
+                radioboxOnly = false,
+                listOnly = false,
+                imageOnly = false;
+            if (this.type == Asc.c_oAscContentControlSpecificType.ComboBox || this.type == Asc.c_oAscContentControlSpecificType.DropDownList) {
+                listOnly = !!specProps;
+            } else if (this.type == Asc.c_oAscContentControlSpecificType.CheckBox) {
+                if (specProps) {
+                    checkboxOnly = (typeof specProps.get_GroupKey() !== 'string');
+                    radioboxOnly = !checkboxOnly;
+                }
+            } else if (this.type == Asc.c_oAscContentControlSpecificType.Picture) {
+                imageOnly = true;
+            } else if (this.type == Asc.c_oAscContentControlSpecificType.None) {
+                textOnly = !!textProps;
+            }
+            if (this._state.TextOnlySettings !== textOnly) {
+                this._state.TextOnlySettings = textOnly;
+                this.TextOnlySettings.toggleClass('hidden', !textOnly);
+            }
+            if (this._state.CheckOnlySettings !== checkboxOnly) {
+                this._state.CheckOnlySettings = checkboxOnly;
+                this.CheckOnlySettings.toggleClass('hidden', !checkboxOnly);
+            }
+            if (this._state.RadioOnlySettings !== radioboxOnly) {
+                this._state.RadioOnlySettings = radioboxOnly;
+                this.RadioOnlySettings.toggleClass('hidden', !radioboxOnly);
+            }
+            if (this._state.ListOnlySettings !== listOnly) {
+                this._state.ListOnlySettings = listOnly;
+                this.ListOnlySettings.toggleClass('hidden', !listOnly);
+            }
+            if (this._state.ImageOnlySettings !== imageOnly) {
+                this._state.ImageOnlySettings = imageOnly;
+                this.ImageOnlySettings.toggleClass('hidden', !imageOnly);
+            }
+            var value = !(checkboxOnly || radioboxOnly);
+            if (this._state.PlaceholderSettings !== value) {
+                this._state.PlaceholderSettings = value;
+                this.PlaceholderSettings.toggleClass('hidden', !value);
             }
         },
 
@@ -472,7 +567,10 @@ define([
         textCheckbox: 'Checkbox',
         textCombobox: 'Combo box',
         textDropDown: 'Dropdown',
-        textImage: 'Image'
+        textImage: 'Image',
+        textChecked: 'Checked by default',
+        textSelected: 'Selected by default',
+        textGroupKey: 'Group key'
 
     }, DE.Views.FormSettings || {}));
 });
\ No newline at end of file

From 701f505be94b18077748e8174e5e72e6a2c4a9ed Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Wed, 30 Sep 2020 15:46:19 +0300
Subject: [PATCH 06/33] [DE] Add settings for list controls

---
 .../main/app/template/FormSettings.template   |  35 +++-
 .../main/app/view/FormSettings.js             | 187 ++++++++++++++----
 2 files changed, 178 insertions(+), 44 deletions(-)

diff --git a/apps/documenteditor/main/app/template/FormSettings.template b/apps/documenteditor/main/app/template/FormSettings.template
index af0bc4c96..08d55f291 100644
--- a/apps/documenteditor/main/app/template/FormSettings.template
+++ b/apps/documenteditor/main/app/template/FormSettings.template
@@ -4,7 +4,7 @@
             <label class="header padding-small" id="form-settings-name"><%= scope.textField %></label>
         </td>
     </tr>
-    <tr class="form-textfield form-checkbox form-list form-image">
+    <tr class="form-keyfield">
         <td class="padding-small">
             <label class="input-label"><%= scope.textKey %></label>
             <div id="form-combo-key" style="width: 100%;"></div>
@@ -40,16 +40,43 @@
         </td>
     </tr>
     <tr class="form-textfield">
-        <td class="padding-large" colspan="2">
+        <td class="padding-large">
             <label class="input-label" style="margin-left: 22px;margin-top: 4px;"><%= scope.textWidth %></label>
             <div id="form-spin-width" style="display: inline-block; float: right;"></div>
         </td>
     </tr>
-    <tr class="form-checkbox form-radiobox">
-        <td class="padding-large" colspan=2>
+    <tr class="form-checkbox">
+        <td class="padding-large">
             <div id="form-chb-selected"></div>
         </td>
     </tr>
+</table>
+<table cols="2" class="form-list">
+    <tr>
+        <td colspan="2" class="padding-small">
+            <label class="input-label"><%= scope.textValue %></label>
+        </td>
+    </tr>
+    <tr style="vertical-align: top;">
+        <td class="padding-small">
+            <div id="form-txt-new-value" style="margin-right: 5px;"></div>
+        </td>
+        <td class="padding-small">
+            <div id="form-list-add" style="margin-left: 5px;"></div>
+        </td>
+    </tr>
+    <tr style="vertical-align: top;">
+        <td class="padding-large">
+            <div id="form-list-list" style="height: 95px;margin-right: 5px;background-color: #fff;"></div>
+        </td>
+        <td class="padding-large">
+            <div id="form-list-delete" style="margin-bottom: 5px;margin-left: 5px;"></div>
+            <div id="form-list-up" style="margin-bottom: 5px;margin-left: 5px;"></div>
+            <div id="form-list-down" style="margin-left: 5px;"></div>
+        </td>
+    </tr>
+</table>
+<table cols="1">
     <tr>
         <td class="padding-small">
             <div class="separator horizontal"></div>
diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index fb4b225c1..f083d3484 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -90,6 +90,7 @@ define([
 
             this.TextOnlySettings = el.find('.form-textfield');
             this.PlaceholderSettings = el.find('.form-placeholder');
+            this.KeySettings = el.find('.form-keyfield');
             this.CheckOnlySettings = el.find('.form-checkbox');
             this.RadioOnlySettings = el.find('.form-radiobox');
             this.ListOnlySettings = el.find('.form-list');
@@ -206,10 +207,67 @@ define([
             this.cmbGroupKey.on('changed:after', this.onGroupKeyChanged.bind(this));
             this.cmbGroupKey.on('hide:after', this.onHideMenus.bind(this));
 
+            // combobox & dropdown list
+            this.txtNewValue = new Common.UI.InputField({
+                el          : $markup.findById('#form-txt-new-value'),
+                allowBlank  : true,
+                validateOnChange: false,
+                validateOnBlur: false,
+                style       : 'width: 100%;',
+                value       : ''
+            });
+            this.lockedControls.push(this.txtNewValue);
+
+            this.list = new Common.UI.ListView({
+                el: $markup.findById('#form-list-list'),
+                store: new Common.UI.DataViewStore(),
+                emptyText: '',
+                template: _.template(['<div class="listview inner" style=""></div>'].join('')),
+                itemTemplate: _.template([
+                    '<div id="<%= id %>" class="list-item" style="width: 100%;display:inline-block;">',
+                    // '<div style="width:65px;display: inline-block;vertical-align: middle; overflow: hidden; text-overflow: ellipsis;white-space: pre;margin-right: 5px;"><%= name %></div>',
+                    '<div style="width:65px;display: inline-block;vertical-align: middle; overflow: hidden; text-overflow: ellipsis;white-space: pre;"><%= value %></div>',
+                    '</div>'
+                ].join(''))
+            });
+            this.list.on('item:select', _.bind(this.onSelectItem, this));
+
+            this.btnListAdd = new Common.UI.Button({
+                parentEl: $markup.findById('#form-list-add'),
+                cls: 'btn-toolbar',
+                iconCls: 'toolbar__icon btn-add',
+                hint: this.textTipAdd
+            });
+            this.btnListAdd.on('click', _.bind(this.onAddItem, this));
+
+            this.btnListDelete = new Common.UI.Button({
+                parentEl: $markup.findById('#form-list-delete'),
+                cls: 'btn-toolbar',
+                iconCls: 'toolbar__icon cc-remove',
+                hint: this.textTipDelete
+            });
+            this.btnListDelete.on('click', _.bind(this.onDeleteItem, this));
+
+            this.btnListUp = new Common.UI.Button({
+                parentEl: $markup.findById('#form-list-up'),
+                cls: 'btn-toolbar',
+                iconCls: 'toolbar__icon btn-up',
+                hint: this.textTipUp
+            });
+            this.btnListUp.on('click', _.bind(this.onMoveItem, this, true));
+
+            this.btnListDown = new Common.UI.Button({
+                parentEl: $markup.findById('#form-list-down'),
+                cls: 'btn-toolbar',
+                iconCls: 'toolbar__icon btn-down',
+                hint: this.textTipDown
+            });
+            this.btnListDown.on('click', _.bind(this.onMoveItem, this, false));
+
             this.btnRemForm = new Common.UI.Button({
                 parentEl: $markup.findById('#form-btn-delete'),
                 cls         : 'btn-toolbar',
-                iconCls     : 'toolbar__icon btn-remove-duplicates',
+                iconCls     : 'toolbar__icon cc-remove',
                 caption     : this.textDelete,
                 style       : 'text-align: left;'
             });
@@ -346,7 +404,7 @@ define([
             if (this.api && !this._noApply) {
                 var props   = this._originalProps || new AscCommon.CContentControlPr();
                 var specProps = this._originalCheckProps || new AscCommon.CSdtCheckBoxPr();
-                // specProps.put_Selected(field.getValue()=='checked');
+                specProps.put_Checked(field.getValue()=='checked');
                 props.put_CheckBoxPr(specProps);
                 this.api.asc_SetContentControlProperties(props, this.internalId);
                 this.fireEvent('editcomplete', this);
@@ -364,6 +422,54 @@ define([
             }
         },
 
+        fillListProps: function() {
+            if (this.api && !this._noApply) {
+                var props   = this._originalProps || new AscCommon.CContentControlPr();
+                var specProps = this._originalListProps || new AscCommon.CSdtComboBoxPr();
+                specProps.clear();
+                this.list.store.each(function (item, index) {
+                    specProps.add_Item(item.get('name'), item.get('value'));
+                });
+                (this.type == Asc.c_oAscContentControlSpecificType.ComboBox) ? props.put_ComboBoxPr(specProps) : props.put_DropDownListPr(specProps);
+                this.api.asc_SetContentControlProperties(props, this.internalId);
+            }
+        },
+
+        onAddItem: function() {
+            var store = this.list.store,
+                value = this.txtNewValue.getValue();
+            if (value!=='') {
+                var rec = store.findWhere({value: value});
+                if (!rec) {
+                    store.add({value: value, name: value});
+                    this.fillListProps();
+                }
+            }
+            this.fireEvent('editcomplete', this);
+        },
+
+        onDeleteItem: function(btn, eOpts){
+            var rec = this.list.getSelectedRec();
+            if (rec) {
+                var store = this.list.store;
+                store.remove(rec);
+                this.fillListProps();
+            }
+            this.fireEvent('editcomplete', this);
+        },
+
+        onMoveItem: function(up) {
+            var store = this.list.store,
+                length = store.length,
+                rec = this.list.getSelectedRec();
+            if (rec) {
+                var index = store.indexOf(rec);
+                store.add(store.remove(rec), {at: up ? Math.max(0, index-1) : Math.min(length-1, index+1)});
+                this.fillListProps();
+            }
+            this.fireEvent('editcomplete', this);
+        },
+
         ChangeSettings: function(props) {
             if (this._initSettings)
                 this.createDelayedElements();
@@ -414,7 +520,6 @@ define([
                     specProps = props.get_CheckBoxPr();
                     this._originalCheckProps = specProps;
                 }
-                this.type = type;
 
                 // form settings
                 var formPr = props.get_FormPr();
@@ -443,11 +548,11 @@ define([
                         hidden = (typeof val !== 'string');
                         this.labelFormName.text(hidden ? this.textCheckbox : this.textRadiobox);
                         this.chSelected.setCaption(hidden ? this.textChecked : this.textSelected);
-                        // val = formTextPr.get_Selected();
-                        // if ( this._state.Selected!==val ) {
-                        //     this.chSelected.setValue(!!val, true);
-                        //     this._state.Selected=val;
-                        // }
+                        val = specProps.get_Checked();
+                        if ( this._state.Selected!==val ) {
+                            this.chSelected.setValue(!!val, true);
+                            this._state.Selected=val;
+                        }
                     }
                 }
 
@@ -476,7 +581,9 @@ define([
                 }
                 this._noApply = false;
 
-                this.showHideControls(formTextPr, specProps);
+                if (this.type !== type || type == Asc.c_oAscContentControlSpecificType.CheckBox)
+                    this.showHideControls(type, formTextPr, specProps);
+                this.type = type;
             }
         },
 
@@ -508,49 +615,44 @@ define([
             this.btnRemForm.setDisabled(this._lockedControl || disable);
         },
 
-        showHideControls: function(textProps, specProps) {
+        showHideControls: function(type, textProps, specProps) {
             var textOnly = false,
                 checkboxOnly = false,
                 radioboxOnly = false,
                 listOnly = false,
                 imageOnly = false;
-            if (this.type == Asc.c_oAscContentControlSpecificType.ComboBox || this.type == Asc.c_oAscContentControlSpecificType.DropDownList) {
+            if (type == Asc.c_oAscContentControlSpecificType.ComboBox || type == Asc.c_oAscContentControlSpecificType.DropDownList) {
                 listOnly = !!specProps;
-            } else if (this.type == Asc.c_oAscContentControlSpecificType.CheckBox) {
+            } else if (type == Asc.c_oAscContentControlSpecificType.CheckBox) {
                 if (specProps) {
                     checkboxOnly = (typeof specProps.get_GroupKey() !== 'string');
                     radioboxOnly = !checkboxOnly;
                 }
-            } else if (this.type == Asc.c_oAscContentControlSpecificType.Picture) {
+            } else if (type == Asc.c_oAscContentControlSpecificType.Picture) {
                 imageOnly = true;
-            } else if (this.type == Asc.c_oAscContentControlSpecificType.None) {
+            } else if (type == Asc.c_oAscContentControlSpecificType.None) {
                 textOnly = !!textProps;
             }
-            if (this._state.TextOnlySettings !== textOnly) {
-                this._state.TextOnlySettings = textOnly;
-                this.TextOnlySettings.toggleClass('hidden', !textOnly);
-            }
-            if (this._state.CheckOnlySettings !== checkboxOnly) {
-                this._state.CheckOnlySettings = checkboxOnly;
-                this.CheckOnlySettings.toggleClass('hidden', !checkboxOnly);
-            }
-            if (this._state.RadioOnlySettings !== radioboxOnly) {
-                this._state.RadioOnlySettings = radioboxOnly;
-                this.RadioOnlySettings.toggleClass('hidden', !radioboxOnly);
-            }
-            if (this._state.ListOnlySettings !== listOnly) {
-                this._state.ListOnlySettings = listOnly;
-                this.ListOnlySettings.toggleClass('hidden', !listOnly);
-            }
-            if (this._state.ImageOnlySettings !== imageOnly) {
-                this._state.ImageOnlySettings = imageOnly;
-                this.ImageOnlySettings.toggleClass('hidden', !imageOnly);
-            }
-            var value = !(checkboxOnly || radioboxOnly);
-            if (this._state.PlaceholderSettings !== value) {
-                this._state.PlaceholderSettings = value;
-                this.PlaceholderSettings.toggleClass('hidden', !value);
-            }
+            this.TextOnlySettings.toggleClass('hidden', !textOnly);
+            this.ListOnlySettings.toggleClass('hidden', !listOnly);
+            this.ImageOnlySettings.toggleClass('hidden', !imageOnly);
+            this.RadioOnlySettings.toggleClass('hidden', !radioboxOnly);
+            this.KeySettings.toggleClass('hidden', radioboxOnly);
+            var value = (checkboxOnly || radioboxOnly);
+            this.PlaceholderSettings.toggleClass('hidden', value);
+            this.CheckOnlySettings.toggleClass('hidden', !value);
+        },
+
+        onSelectItem: function(listView, itemView, record) {
+            this.disableListButtons(false);
+        },
+
+        disableListButtons: function(disabled) {
+            if (disabled===undefined)
+                disabled = !this.list.getSelectedRec();
+            this.btnListDelete.setDisabled(disabled);
+            this.btnListUp.setDisabled(disabled);
+            this.btnListDown.setDisabled(disabled);
         },
 
         textField: 'Text field',
@@ -570,7 +672,12 @@ define([
         textImage: 'Image',
         textChecked: 'Checked by default',
         textSelected: 'Selected by default',
-        textGroupKey: 'Group key'
+        textGroupKey: 'Group key',
+        textTipAdd: 'Add new value',
+        textTipDelete: 'Delete value',
+        textTipUp: 'Move up',
+        textTipDown: 'Move down',
+        textValue: 'Value Options'
 
     }, DE.Views.FormSettings || {}));
 });
\ No newline at end of file

From 8494d1b752a6acdb83c293270feb64b8264f9d4c Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Wed, 30 Sep 2020 17:26:06 +0300
Subject: [PATCH 07/33] [DE] Support key for fields and group key for radio box

---
 .../main/app/view/FormSettings.js             | 34 +++++++++++++------
 1 file changed, 24 insertions(+), 10 deletions(-)

diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index f083d3484..1915771f4 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -526,11 +526,21 @@ define([
                 if (formPr) {
                     this._originalFormProps = formPr;
 
+                    var data = [];
+                    if (type == Asc.c_oAscContentControlSpecificType.CheckBox)
+                        data = this.api.asc_GetCheckBoxFormKeys();
+                    else if (type == Asc.c_oAscContentControlSpecificType.Picture)
+                        data = this.api.asc_GetPictureFormKeys();
+                    else
+                        data = this.api.asc_GetTextFormKeys();
+                    var arr = [];
+                    data.forEach(function(item) {
+                        arr.push({ displayValue: item,  value: item });
+                    });
+                    this.cmbKey.setData(arr);
+
                     val = formPr.get_Key();
-                    if (this._state.key!==val) {
-                        this.cmbKey.setValue(val ? val : '');
-                        this._state.key = val;
-                    }
+                    this.cmbKey.setValue(val ? val : '');
 
                     val = formPr.get_HelpText();
                     if (this._state.help!==val) {
@@ -538,16 +548,20 @@ define([
                         this._state.help=val;
                     }
 
-                    var hidden = true;
                     if (type == Asc.c_oAscContentControlSpecificType.CheckBox && specProps) {
                         val = specProps.get_GroupKey();
-                        if (this._state.groupkey!==val) {
+                        var ischeckbox = (typeof val !== 'string');
+                        if (!ischeckbox) {
+                            var arr = [];
+                            this.api.asc_GetRadioButtonGroupKeys().forEach(function(item) {
+                                arr.push({ displayValue: item,  value: item });
+                            });
+                            this.cmbGroupKey.setData(arr);
                             this.cmbGroupKey.setValue(val ? val : '');
-                            this._state.groupkey=val;
                         }
-                        hidden = (typeof val !== 'string');
-                        this.labelFormName.text(hidden ? this.textCheckbox : this.textRadiobox);
-                        this.chSelected.setCaption(hidden ? this.textChecked : this.textSelected);
+
+                        this.labelFormName.text(ischeckbox ? this.textCheckbox : this.textRadiobox);
+                        this.chSelected.setCaption(ischeckbox ? this.textChecked : this.textSelected);
                         val = specProps.get_Checked();
                         if ( this._state.Selected!==val ) {
                             this.chSelected.setValue(!!val, true);

From 7016660299ff48392d3192a326f1c3a4b820eef8 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Wed, 30 Sep 2020 18:52:11 +0300
Subject: [PATCH 08/33] [DE] Open content control settings after it's creating

---
 apps/documenteditor/main/app/controller/Main.js      | 5 +++++
 apps/documenteditor/main/app/controller/RightMenu.js | 5 +++++
 apps/documenteditor/main/app/controller/Toolbar.js   | 1 +
 3 files changed, 11 insertions(+)

diff --git a/apps/documenteditor/main/app/controller/Main.js b/apps/documenteditor/main/app/controller/Main.js
index 6d3284d4d..0e40df49c 100644
--- a/apps/documenteditor/main/app/controller/Main.js
+++ b/apps/documenteditor/main/app/controller/Main.js
@@ -1356,6 +1356,7 @@ define([
                         toolbarView.on('insertshape', _.bind(me.onInsertShape, me));
                         toolbarView.on('inserttextart', _.bind(me.onInsertTextArt, me));
                         toolbarView.on('insertchart', _.bind(me.onInsertChart, me));
+                        toolbarView.on('insertcontrol', _.bind(me.onInsertControl, me));
                     }
 
                     var value = Common.localStorage.getItem('de-settings-unit');
@@ -2032,6 +2033,10 @@ define([
                 this.getApplication().getController('RightMenu').onInsertTextArt();
             },
 
+            onInsertControl:  function() {
+                this.getApplication().getController('RightMenu').onInsertControl();
+            },
+
             unitsChanged: function(m) {
                 var value = Common.localStorage.getItem("de-settings-unit");
                 value = (value!==null) ? parseInt(value) : Common.Utils.Metric.getDefaultMetric();
diff --git a/apps/documenteditor/main/app/controller/RightMenu.js b/apps/documenteditor/main/app/controller/RightMenu.js
index 7f4d50648..ded26a120 100644
--- a/apps/documenteditor/main/app/controller/RightMenu.js
+++ b/apps/documenteditor/main/app/controller/RightMenu.js
@@ -261,6 +261,11 @@ define([
             this._settings[Common.Utils.documentSettingsType.TextArt].needShow = true;
         },
 
+        onInsertControl:  function() {
+            if (this._settings[Common.Utils.documentSettingsType.Form])
+                this._settings[Common.Utils.documentSettingsType.Form].needShow = true;
+        },
+
         UpdateThemeColors:  function() {
             this.rightmenu.paragraphSettings.UpdateThemeColors();
             this.rightmenu.tableSettings.UpdateThemeColors();
diff --git a/apps/documenteditor/main/app/controller/Toolbar.js b/apps/documenteditor/main/app/controller/Toolbar.js
index b2b2974bf..c4a38d633 100644
--- a/apps/documenteditor/main/app/controller/Toolbar.js
+++ b/apps/documenteditor/main/app/controller/Toolbar.js
@@ -1835,6 +1835,7 @@ define([
                     oPr, oFormPr;
                 if (isnew) {
                     oFormPr = new AscCommon.CSdtFormPr();
+                    this.toolbar.fireEvent('insertcontrol', this.toolbar);
                 }
                 if (item.value == 'plain' || item.value == 'rich')
                     this.api.asc_AddContentControl((item.value=='plain') ? Asc.c_oAscSdtLevelType.Inline : Asc.c_oAscSdtLevelType.Block);

From 9a1310bee3961d1bdcf87ce5354d6450dcf1fd25 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Wed, 30 Sep 2020 18:56:18 +0300
Subject: [PATCH 09/33] [DE] Fix list control settings

---
 apps/documenteditor/main/app/view/FormSettings.js | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index 1915771f4..7a1e31012 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -226,7 +226,7 @@ define([
                 itemTemplate: _.template([
                     '<div id="<%= id %>" class="list-item" style="width: 100%;display:inline-block;">',
                     // '<div style="width:65px;display: inline-block;vertical-align: middle; overflow: hidden; text-overflow: ellipsis;white-space: pre;margin-right: 5px;"><%= name %></div>',
-                    '<div style="width:65px;display: inline-block;vertical-align: middle; overflow: hidden; text-overflow: ellipsis;white-space: pre;"><%= value %></div>',
+                    '<div style="width:65px;display: inline-block;vertical-align: middle; overflow: hidden; text-overflow: ellipsis;white-space: pre;"><%= name %></div>',
                     '</div>'
                 ].join(''))
             });
@@ -514,6 +514,7 @@ define([
                             });
                         }
                         this.list.store.reset(arr);
+                        this.txtNewValue.setValue('');
                     }
                     this.disableListButtons();
                 } else if (type == Asc.c_oAscContentControlSpecificType.CheckBox) {

From 80d3f5f0263f2b650db0c0f4644699c77e1c6053 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Tue, 6 Oct 2020 19:25:49 +0300
Subject: [PATCH 10/33] [DE] Add lock property for controls

---
 .../main/app/controller/RightMenu.js          |  7 +-
 .../main/app/template/FormSettings.template   |  5 --
 .../main/app/view/FormSettings.js             | 70 ++++++-------------
 3 files changed, 27 insertions(+), 55 deletions(-)

diff --git a/apps/documenteditor/main/app/controller/RightMenu.js b/apps/documenteditor/main/app/controller/RightMenu.js
index ded26a120..02093c2a9 100644
--- a/apps/documenteditor/main/app/controller/RightMenu.js
+++ b/apps/documenteditor/main/app/controller/RightMenu.js
@@ -125,7 +125,8 @@ define([
             this._settings[Common.Utils.documentSettingsType.Signature].locked = false;
 
             var isChart = false;
-            var control_props = this.api.asc_IsContentControl() ? this.api.asc_GetContentControlProperties() : null;
+            var control_props = this.api.asc_IsContentControl() ? this.api.asc_GetContentControlProperties() : null,
+                control_lock = false;
             for (i=0; i<SelectedObjects.length; i++)
             {
                 var content_locked = false;
@@ -154,9 +155,11 @@ define([
                             this._settings[Common.Utils.documentSettingsType.TextArt].locked = value.get_Locked() || content_locked;
                         }
                     }
+                    control_lock = control_lock || value.get_Locked();
                 } else if (settingsType == Common.Utils.documentSettingsType.Paragraph) {
                     this._settings[settingsType].panel.isChart = isChart;
                     can_add_table = value.get_CanAddTable();
+                    control_lock = control_lock || value.get_Locked();
                 }
                 this._settings[settingsType].props = value;
                 this._settings[settingsType].hidden = 0;
@@ -173,7 +176,7 @@ define([
                     spectype==Asc.c_oAscContentControlSpecificType.ComboBox || spectype==Asc.c_oAscContentControlSpecificType.DropDownList || spectype==Asc.c_oAscContentControlSpecificType.None) {
                     settingsType = Common.Utils.documentSettingsType.Form;
                     this._settings[settingsType].props = control_props;
-                    this._settings[settingsType].locked = false;
+                    this._settings[settingsType].locked = control_lock;
                     this._settings[settingsType].hidden = 0;
                 }
             }
diff --git a/apps/documenteditor/main/app/template/FormSettings.template b/apps/documenteditor/main/app/template/FormSettings.template
index 08d55f291..b1fe6ee35 100644
--- a/apps/documenteditor/main/app/template/FormSettings.template
+++ b/apps/documenteditor/main/app/template/FormSettings.template
@@ -45,11 +45,6 @@
             <div id="form-spin-width" style="display: inline-block; float: right;"></div>
         </td>
     </tr>
-    <tr class="form-checkbox">
-        <td class="padding-large">
-            <div id="form-chb-selected"></div>
-        </td>
-    </tr>
 </table>
 <table cols="2" class="form-list">
     <tr>
diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index 7a1e31012..892c80dab 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -68,7 +68,8 @@ define([
             this._initSettings = true;
 
             this._state = {
-                DisabledControls: true
+                DisabledControls: undefined,
+                LockDelete: undefined
             };
             this.spinners = [];
             this.lockedControls = [];
@@ -77,7 +78,6 @@ define([
             this._originalTextFormProps = null;
             this._originalFormProps = null;
             this._originalProps = null;
-            this._lockedControl = false;
 
             this.render();
         },
@@ -112,8 +112,7 @@ define([
                 cls: 'input-group-nr',
                 menuStyle: 'min-width: 100%;',
                 editable: true,
-                data: [],
-                disabled: this._locked
+                data: []
             });
             this.cmbKey.setValue('');
             this.lockedControls.push(this.cmbKey);
@@ -184,22 +183,13 @@ define([
             this.spnWidth.on('change', this.onWidthChange.bind(this));
             this.spnWidth.on('inputleave', function(){ me.fireEvent('editcomplete', me);});
 
-            // Check/Radio props
-            this.chSelected = new Common.UI.CheckBox({
-                el: $markup.findById('#form-chb-selected'),
-                labelText: this.textChecked
-            });
-            this.chSelected.on('change', this.onChSelectedChanged.bind(this));
-            this.lockedControls.push(this.chSelected);
-
             // Radio props
             this.cmbGroupKey = new Common.UI.ComboBox({
                 el: $markup.findById('#form-combo-group-key'),
                 cls: 'input-group-nr',
                 menuStyle: 'min-width: 100%;',
                 editable: true,
-                data: [],
-                disabled: this._locked
+                data: []
             });
             this.cmbGroupKey.setValue('');
             this.lockedControls.push(this.cmbGroupKey);
@@ -231,6 +221,7 @@ define([
                 ].join(''))
             });
             this.list.on('item:select', _.bind(this.onSelectItem, this));
+            this.lockedControls.push(this.list);
 
             this.btnListAdd = new Common.UI.Button({
                 parentEl: $markup.findById('#form-list-add'),
@@ -239,6 +230,7 @@ define([
                 hint: this.textTipAdd
             });
             this.btnListAdd.on('click', _.bind(this.onAddItem, this));
+            this.lockedControls.push(this.btnListAdd);
 
             this.btnListDelete = new Common.UI.Button({
                 parentEl: $markup.findById('#form-list-delete'),
@@ -247,6 +239,7 @@ define([
                 hint: this.textTipDelete
             });
             this.btnListDelete.on('click', _.bind(this.onDeleteItem, this));
+            this.lockedControls.push(this.btnListDelete);
 
             this.btnListUp = new Common.UI.Button({
                 parentEl: $markup.findById('#form-list-up'),
@@ -255,6 +248,7 @@ define([
                 hint: this.textTipUp
             });
             this.btnListUp.on('click', _.bind(this.onMoveItem, this, true));
+            this.lockedControls.push(this.btnListUp);
 
             this.btnListDown = new Common.UI.Button({
                 parentEl: $markup.findById('#form-list-down'),
@@ -263,6 +257,7 @@ define([
                 hint: this.textTipDown
             });
             this.btnListDown.on('click', _.bind(this.onMoveItem, this, false));
+            this.lockedControls.push(this.btnListDown);
 
             this.btnRemForm = new Common.UI.Button({
                 parentEl: $markup.findById('#form-btn-delete'),
@@ -286,11 +281,10 @@ define([
             this.btnLockForm.on('click', _.bind(function(btn){
                 if (this.api  && !this._noApply) {
                     var props   = this._originalProps || new AscCommon.CContentControlPr();
-                    props.put_Lock(!this._lockedControl ? Asc.c_oAscSdtLockType.SdtContentLocked : Asc.c_oAscSdtLockType.Unlocked);
+                    props.put_Lock(!this._state.LockDelete ? Asc.c_oAscSdtLockType.SdtLocked : Asc.c_oAscSdtLockType.Unlocked);
                     this.api.asc_SetContentControlProperties(props, this.internalId);
                 }
             }, this));
-            this.lockedControls.push(this.btnLockForm);
 
             this.updateMetricUnit();
         },
@@ -400,17 +394,6 @@ define([
             }
         },
 
-        onChSelectedChanged: function(field, newValue, oldValue, eOpts){
-            if (this.api && !this._noApply) {
-                var props   = this._originalProps || new AscCommon.CContentControlPr();
-                var specProps = this._originalCheckProps || new AscCommon.CSdtCheckBoxPr();
-                specProps.put_Checked(field.getValue()=='checked');
-                props.put_CheckBoxPr(specProps);
-                this.api.asc_SetContentControlProperties(props, this.internalId);
-                this.fireEvent('editcomplete', this);
-            }
-        },
-
         onGroupKeyChanged: function(combo, record) {
             if (this.api && !this._noApply) {
                 var props   = this._originalProps || new AscCommon.CContentControlPr();
@@ -474,8 +457,6 @@ define([
             if (this._initSettings)
                 this.createDelayedElements();
 
-            this.disableControls(this._locked);
-
             if (props) {
                 this._originalProps = props;
 
@@ -491,11 +472,11 @@ define([
 
                 val = props.get_Lock();
                 (val===undefined) && (val = Asc.c_oAscSdtLockType.Unlocked);
-                if (this._lockedControl !== val) {
-                    this._lockedControl = (val==Asc.c_oAscSdtLockType.SdtContentLocked || val==Asc.c_oAscSdtLockType.SdtLocked || val==Asc.c_oAscSdtLockType.ContentLocked);
-                    this.btnLockForm.setCaption(this._lockedControl ? this.textUnlock : this.textLock);
-                    this.btnRemForm.setDisabled(this._lockedControl || this._locked);
+                if (this._state.LockDelete !== (val==Asc.c_oAscSdtLockType.SdtContentLocked || val==Asc.c_oAscSdtLockType.SdtLocked)) {
+                    this._state.LockDelete = (val==Asc.c_oAscSdtLockType.SdtContentLocked || val==Asc.c_oAscSdtLockType.SdtLocked);
+                    this.btnLockForm.setCaption(this._state.LockDelete ? this.textUnlock : this.textLock);
                 }
+                this.disableControls(this._locked);
 
                 var type = props.get_SpecificType();
                 var specProps;
@@ -562,12 +543,6 @@ define([
                         }
 
                         this.labelFormName.text(ischeckbox ? this.textCheckbox : this.textRadiobox);
-                        this.chSelected.setCaption(ischeckbox ? this.textChecked : this.textSelected);
-                        val = specProps.get_Checked();
-                        if ( this._state.Selected!==val ) {
-                            this.chSelected.setValue(!!val, true);
-                            this._state.Selected=val;
-                        }
                     }
                 }
 
@@ -621,13 +596,14 @@ define([
         },
 
         disableControls: function(disable) {
-            if (this._state.DisabledControls!==disable) {
-                this._state.DisabledControls = disable;
+            var me = this;
+            if (this._state.DisabledControls!==(this._state.LockDelete || disable)) {
+                this._state.DisabledControls = this._state.LockDelete || disable;
                 _.each(this.lockedControls, function(item) {
-                    item.setDisabled(disable);
+                    item.setDisabled(me._state.DisabledControls);
                 });
             }
-            this.btnRemForm.setDisabled(this._lockedControl || disable);
+            this.btnLockForm.setDisabled(disable);
         },
 
         showHideControls: function(type, textProps, specProps) {
@@ -665,9 +641,9 @@ define([
         disableListButtons: function(disabled) {
             if (disabled===undefined)
                 disabled = !this.list.getSelectedRec();
-            this.btnListDelete.setDisabled(disabled);
-            this.btnListUp.setDisabled(disabled);
-            this.btnListDown.setDisabled(disabled);
+            this.btnListDelete.setDisabled(disabled || this._state.DisabledControls);
+            this.btnListUp.setDisabled(disabled || this._state.DisabledControls);
+            this.btnListDown.setDisabled(disabled || this._state.DisabledControls);
         },
 
         textField: 'Text field',
@@ -685,8 +661,6 @@ define([
         textCombobox: 'Combo box',
         textDropDown: 'Dropdown',
         textImage: 'Image',
-        textChecked: 'Checked by default',
-        textSelected: 'Selected by default',
         textGroupKey: 'Group key',
         textTipAdd: 'Add new value',
         textTipDelete: 'Delete value',

From 71f638619943207bdac477926d228a6b96bc5e1c Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Tue, 6 Oct 2020 20:52:17 +0300
Subject: [PATCH 11/33] [DE] Change image for picture control

---
 .../main/app/template/FormSettings.template   |  5 ++
 .../main/app/view/FormSettings.js             | 70 ++++++++++++++++++-
 .../documenteditor/main/app/view/RightMenu.js |  1 +
 3 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/apps/documenteditor/main/app/template/FormSettings.template b/apps/documenteditor/main/app/template/FormSettings.template
index b1fe6ee35..8a52b6d4b 100644
--- a/apps/documenteditor/main/app/template/FormSettings.template
+++ b/apps/documenteditor/main/app/template/FormSettings.template
@@ -45,6 +45,11 @@
             <div id="form-spin-width" style="display: inline-block; float: right;"></div>
         </td>
     </tr>
+    <tr class="form-image">
+        <td class="padding-large">
+            <div id="form-button-replace" style="width:100%;"></div>
+        </td>
+    </tr>
 </table>
 <table cols="2" class="form-list">
     <tr>
diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index 892c80dab..38a25f135 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -46,7 +46,8 @@ define([
     'common/main/lib/component/ComboBox',
     'common/main/lib/component/MetricSpinner',
     'common/main/lib/component/TextareaField',
-    'common/main/lib/component/CheckBox'
+    'common/main/lib/component/CheckBox',
+    'common/main/lib/view/ImageFromUrlDialog'
 ], function (menuTemplate, $, _, Backbone) {
     'use strict';
 
@@ -259,6 +260,26 @@ define([
             this.btnListDown.on('click', _.bind(this.onMoveItem, this, false));
             this.lockedControls.push(this.btnListDown);
 
+            // image props
+            this.btnSelectImage = new Common.UI.Button({
+                parentEl: $('#form-button-replace'),
+                cls: 'btn-text-menu-default',
+                caption: this.textSelectImage,
+                style: "width:100%;",
+                menu: new Common.UI.Menu({
+                    style: 'min-width: 194px;',
+                    maxHeight: 200,
+                    items: [
+                        {caption: this.textFromFile, value: 0},
+                        {caption: this.textFromUrl, value: 1},
+                        {caption: this.textFromStorage, value: 2}
+                    ]
+                })
+            });
+            this.lockedControls.push(this.btnSelectImage);
+            this.btnSelectImage.menu.on('item:click', _.bind(this.onImageSelect, this));
+            this.btnSelectImage.menu.items[2].setVisible(this.mode.canRequestInsertImage || this.mode.fileChoiceUrl && this.mode.fileChoiceUrl.indexOf("{documentType}")>-1);
+
             this.btnRemForm = new Common.UI.Button({
                 parentEl: $markup.findById('#form-btn-delete'),
                 cls         : 'btn-toolbar',
@@ -297,6 +318,10 @@ define([
             return this;
         },
 
+        setMode: function(mode) {
+            this.mode = mode;
+        },
+
         onKeyChanged: function(combo, record) {
             if (this.api && !this._noApply) {
                 var props   = this._originalProps || new AscCommon.CContentControlPr();
@@ -453,6 +478,43 @@ define([
             this.fireEvent('editcomplete', this);
         },
 
+        setImageUrl: function(url, token) {
+            this.api.AddImageUrl(url, this._originalProps, token);
+        },
+
+        insertImageFromStorage: function(data) {
+            if (data && data.url && data.c=='control') {
+                this.setImageUrl(data.url, data.token);
+            }
+        },
+
+        onImageSelect: function(menu, item) {
+            if (item.value==1) {
+                var me = this;
+                (new Common.Views.ImageFromUrlDialog({
+                    handler: function(result, value) {
+                        if (result == 'ok') {
+                            if (me.api) {
+                                var checkUrl = value.replace(/ /g, '');
+                                if (!_.isEmpty(checkUrl)) {
+                                    me.setImageUrl(checkUrl);
+                                }
+                            }
+                        }
+                        me.fireEvent('editcomplete', me);
+                    }
+                })).show();
+            } else if (item.value==2) {
+                Common.NotificationCenter.trigger('storage:image-load', 'control');
+            } else {
+                if (this._isFromFile) return;
+                this._isFromFile = true;
+                if (this.api) this.api.asc_addImage(this._originalProps);
+                this.fireEvent('editcomplete', this);
+                this._isFromFile = false;
+            }
+        },
+
         ChangeSettings: function(props) {
             if (this._initSettings)
                 this.createDelayedElements();
@@ -666,7 +728,11 @@ define([
         textTipDelete: 'Delete value',
         textTipUp: 'Move up',
         textTipDown: 'Move down',
-        textValue: 'Value Options'
+        textValue: 'Value Options',
+        textSelectImage: 'Select Image',
+        textFromUrl:    'From URL',
+        textFromFile:   'From File',
+        textFromStorage: 'From Storage'
 
     }, DE.Views.FormSettings || {}));
 });
\ No newline at end of file
diff --git a/apps/documenteditor/main/app/view/RightMenu.js b/apps/documenteditor/main/app/view/RightMenu.js
index aa08e0d73..778dbc362 100644
--- a/apps/documenteditor/main/app/view/RightMenu.js
+++ b/apps/documenteditor/main/app/view/RightMenu.js
@@ -266,6 +266,7 @@ define([
             this.mergeSettings && this.mergeSettings.setMode(mode);
             this.imageSettings && this.imageSettings.setMode(mode);
             this.shapeSettings && this.shapeSettings.setMode(mode);
+            this.formSettings && this.formSettings.setMode(mode);
         },
 
         onBtnMenuClick: function(btn, e) {

From bcaa907108acd85fcba4dbdb33e614688e60113d Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Wed, 7 Oct 2020 10:43:12 +0300
Subject: [PATCH 12/33] [DE] Fix picture control settings

---
 apps/documenteditor/main/app/view/FormSettings.js | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index 38a25f135..e2f10d681 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -573,9 +573,10 @@ define([
                     var data = [];
                     if (type == Asc.c_oAscContentControlSpecificType.CheckBox)
                         data = this.api.asc_GetCheckBoxFormKeys();
-                    else if (type == Asc.c_oAscContentControlSpecificType.Picture)
+                    else if (type == Asc.c_oAscContentControlSpecificType.Picture) {
                         data = this.api.asc_GetPictureFormKeys();
-                    else
+                        this.labelFormName.text(this.textImage);
+                    } else
                         data = this.api.asc_GetTextFormKeys();
                     var arr = [];
                     data.forEach(function(item) {

From c35bf4bdcdd7cba88ad211ed44aafb79b2016ae7 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Wed, 7 Oct 2020 10:43:34 +0300
Subject: [PATCH 13/33] [DE] Add Forms tab

---
 apps/documenteditor/main/app.js               |   2 +
 .../main/app/controller/FormsTab.js           | 252 +++++++++++++++++
 .../main/app/controller/Toolbar.js            |   8 +-
 .../main/app/template/Toolbar.template        |  23 ++
 apps/documenteditor/main/app/view/FormsTab.js | 261 ++++++++++++++++++
 apps/documenteditor/main/app/view/Toolbar.js  |   6 +-
 apps/documenteditor/main/app_dev.js           |   2 +
 7 files changed, 550 insertions(+), 4 deletions(-)
 create mode 100644 apps/documenteditor/main/app/controller/FormsTab.js
 create mode 100644 apps/documenteditor/main/app/view/FormsTab.js

diff --git a/apps/documenteditor/main/app.js b/apps/documenteditor/main/app.js
index bd53d3271..87306dd58 100644
--- a/apps/documenteditor/main/app.js
+++ b/apps/documenteditor/main/app.js
@@ -151,6 +151,7 @@ require([
             'Toolbar',
             'Statusbar',
             'Links',
+            'FormsTab',
             'Navigation',
             'RightMenu',
             'LeftMenu',
@@ -176,6 +177,7 @@ require([
                 'documenteditor/main/app/controller/DocumentHolder',
                 'documenteditor/main/app/controller/Toolbar',
                 'documenteditor/main/app/controller/Statusbar',
+                'documenteditor/main/app/controller/FormsTab',
                 'documenteditor/main/app/controller/Links',
                 'documenteditor/main/app/controller/Navigation',
                 'documenteditor/main/app/controller/RightMenu',
diff --git a/apps/documenteditor/main/app/controller/FormsTab.js b/apps/documenteditor/main/app/controller/FormsTab.js
new file mode 100644
index 000000000..3ce0ed8f9
--- /dev/null
+++ b/apps/documenteditor/main/app/controller/FormsTab.js
@@ -0,0 +1,252 @@
+/*
+ *
+ * (c) Copyright Ascensio System SIA 2010-2020
+ *
+ * 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-12 Ernesta Birznieka-Upisha
+ * 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
+ *
+ */
+
+/**
+ *  FormsTab.js
+ *
+ *  Created by Julia Radzhabova on 06.10.2020
+ *  Copyright (c) 2020 Ascensio System SIA. All rights reserved.
+ *
+ */
+
+define([
+    'core',
+    'documenteditor/main/app/view/FormsTab'
+], function () {
+    'use strict';
+
+    DE.Controllers.FormsTab = Backbone.Controller.extend(_.extend({
+        models : [],
+        collections : [
+        ],
+        views : [
+            'FormsTab'
+        ],
+        sdkViewName : '#id_main',
+
+        initialize: function () {
+
+            this.addListeners({
+                'FormsTab': {
+                    'forms:insert': this.onControlsSelect,
+                    'forms:new-color': this.onNewControlsColor,
+                    'forms:clear': this.onClearClick,
+                    'forms:no-color': this.onNoControlsColor,
+                    'forms:select-color': this.onSelectControlsColor,
+                    'forms:mode': this.onModeClick
+                }
+            });
+        },
+        onLaunch: function () {
+            this._state = {
+                prcontrolsdisable:undefined,
+                in_object: false
+            };
+        },
+
+        setApi: function (api) {
+            if (api) {
+                this.api = api;
+                this.api.asc_registerCallback('asc_onFocusObject', this.onApiFocusObject.bind(this));
+                this.api.asc_registerCallback('asc_onCoAuthoringDisconnect',_.bind(this.onCoAuthoringDisconnect, this));
+                Common.NotificationCenter.on('api:disconnect', _.bind(this.onCoAuthoringDisconnect, this));
+                // this.api.asc_registerCallback('asc_onShowContentControlsActions',_.bind(this.onShowContentControlsActions, this));
+                // this.api.asc_registerCallback('asc_onHideContentControlsActions',_.bind(this.onHideContentControlsActions, this));
+            }
+            return this;
+        },
+
+        setConfig: function(config) {
+            this.toolbar = config.toolbar;
+            this.view = this.createView('FormsTab', {
+                toolbar: this.toolbar.toolbar
+            });
+        },
+
+        SetDisabled: function(state) {
+            this.view && this.view.SetDisabled(state);
+        },
+
+        getView: function(name) {
+            return !name && this.view ?
+                this.view : Backbone.Controller.prototype.getView.call(this, name);
+        },
+
+        onCoAuthoringDisconnect: function() {
+            this.SetDisabled(true);
+        },
+
+        onApiFocusObject: function(selectedObjects) {
+            if (!this.toolbar.editMode) return;
+
+            var pr, i = -1, type,
+                paragraph_locked = false,
+                header_locked = false,
+                in_header = false,
+                in_equation = false,
+                in_image = false,
+                in_table = false,
+                frame_pr = null;
+
+            while (++i < selectedObjects.length) {
+                type = selectedObjects[i].get_ObjectType();
+                pr   = selectedObjects[i].get_ObjectValue();
+
+                if (type === Asc.c_oAscTypeSelectElement.Paragraph) {
+                    paragraph_locked = pr.get_Locked();
+                    frame_pr = pr;
+                } else if (type === Asc.c_oAscTypeSelectElement.Header) {
+                    header_locked = pr.get_Locked();
+                    in_header = true;
+                } else if (type === Asc.c_oAscTypeSelectElement.Image) {
+                    in_image = true;
+                } else if (type === Asc.c_oAscTypeSelectElement.Math) {
+                    in_equation = true;
+                } else if (type === Asc.c_oAscTypeSelectElement.Table) {
+                    in_table = true;
+                }
+            }
+            this._state.prcontrolsdisable = paragraph_locked || header_locked;
+            this._state.in_object = in_image || in_table || in_equation;
+
+            var control_props = this.api.asc_IsContentControl() ? this.api.asc_GetContentControlProperties() : null,
+                control_plain = (control_props) ? (control_props.get_ContentControlType()==Asc.c_oAscSdtLevelType.Inline) : false,
+                lock_type = control_props ? control_props.get_Lock() : Asc.c_oAscSdtLockType.Unlocked,
+                content_locked = lock_type==Asc.c_oAscSdtLockType.SdtContentLocked || lock_type==Asc.c_oAscSdtLockType.ContentLocked;
+            var rich_del_lock = (frame_pr) ? !frame_pr.can_DeleteBlockContentControl() : false,
+                rich_edit_lock = (frame_pr) ? !frame_pr.can_EditBlockContentControl() : false,
+                plain_del_lock = (frame_pr) ? !frame_pr.can_DeleteInlineContentControl() : false,
+                plain_edit_lock = (frame_pr) ? !frame_pr.can_EditInlineContentControl() : false;
+
+
+            var need_disable = paragraph_locked || in_equation || in_image || in_header || control_plain || rich_edit_lock || plain_edit_lock;
+        },
+
+        onControlsSelect: function(type) {
+            if (!(this.mode && this.mode.canFeatureContentControl)) return;
+
+            if (item.value == 'settings' || item.value == 'remove') {
+                if (this.api.asc_IsContentControl()) {
+                    var props = this.api.asc_GetContentControlProperties();
+                    if (props) {
+                        var id = props.get_InternalId();
+                        if (item.value == 'settings') {
+                            var me = this;
+                            (new DE.Views.ControlSettingsDialog({
+                                props: props,
+                                api: me.api,
+                                controlLang: me._state.lang,
+                                interfaceLang: me.mode.lang,
+                                handler: function(result, value) {
+                                    if (result == 'ok') {
+                                        me.api.asc_SetContentControlProperties(value, id);
+                                    }
+
+                                    Common.NotificationCenter.trigger('edit:complete', me.toolbar);
+                                }
+                            })).show();
+
+                        } else {
+                            this.api.asc_RemoveContentControlWrapper(id);
+                            Common.component.Analytics.trackEvent('ToolBar', 'Remove Content Control');
+                        }
+                    }
+                }
+            } else {
+                var isnew = (item.value.indexOf('new-')==0),
+                    oPr, oFormPr;
+                if (isnew) {
+                    oFormPr = new AscCommon.CSdtFormPr();
+                    this.toolbar.fireEvent('insertcontrol', this.toolbar);
+                }
+                if (item.value == 'plain' || item.value == 'rich')
+                    this.api.asc_AddContentControl((item.value=='plain') ? Asc.c_oAscSdtLevelType.Inline : Asc.c_oAscSdtLevelType.Block);
+                else if (item.value.indexOf('picture')>=0)
+                    this.api.asc_AddContentControlPicture(oFormPr);
+                else if (item.value.indexOf('checkbox')>=0 || item.value.indexOf('radiobox')>=0) {
+                    if (isnew) {
+                        oPr = new AscCommon.CSdtCheckBoxPr();
+                        (item.value.indexOf('radiobox')>=0) && oPr.put_GroupKey('Group 1');
+                    }
+                    this.api.asc_AddContentControlCheckBox(oPr, oFormPr);
+                } else if (item.value == 'date')
+                    this.api.asc_AddContentControlDatePicker();
+                else if (item.value.indexOf('combobox')>=0 || item.value.indexOf('dropdown')>=0)
+                    this.api.asc_AddContentControlList(item.value.indexOf('combobox')>=0, oPr, oFormPr);
+                else if (item.value == 'new-field') {
+                    oPr = new AscCommon.CSdtTextFormPr();
+                    this.api.asc_AddContentControlTextForm(oPr, oFormPr);
+                }
+
+                Common.component.Analytics.trackEvent('ToolBar', 'Add Content Control');
+            }
+
+            Common.NotificationCenter.trigger('edit:complete', this.toolbar);
+        },
+
+        onModeClick: function(state) {
+            if (this.api) {
+
+            }
+            Common.NotificationCenter.trigger('edit:complete', this.toolbar);
+        },
+
+        onClearClick: function() {
+            if (this.api) {
+                // this.api.asc_ClearControls();
+            }
+            Common.NotificationCenter.trigger('edit:complete', this.toolbar);
+        },
+
+        onNewControlsColor: function() {
+            this.view.mnuControlsColorPicker.addNewColor();
+        },
+
+        onNoControlsColor: function(item) {
+            if (!item.isChecked())
+                this.api.asc_SetGlobalContentControlShowHighlight(true, 220, 220, 220);
+            else
+                this.api.asc_SetGlobalContentControlShowHighlight(false);
+            Common.NotificationCenter.trigger('edit:complete', this.toolbar);
+        },
+
+        onSelectControlsColor: function(color) {
+            var clr = Common.Utils.ThemeColor.getRgbColor(color);
+            if (this.api) {
+                this.api.asc_SetGlobalContentControlShowHighlight(true, clr.get_r(), clr.get_g(), clr.get_b());
+            }
+            Common.NotificationCenter.trigger('edit:complete', this.toolbar);
+        }
+
+    }, DE.Controllers.FormsTab || {}));
+});
\ No newline at end of file
diff --git a/apps/documenteditor/main/app/controller/Toolbar.js b/apps/documenteditor/main/app/controller/Toolbar.js
index c4a38d633..a21c44062 100644
--- a/apps/documenteditor/main/app/controller/Toolbar.js
+++ b/apps/documenteditor/main/app/controller/Toolbar.js
@@ -2981,7 +2981,7 @@ define([
             var tab = {action: 'review', caption: me.toolbar.textTabCollaboration};
             var $panel = me.application.getController('Common.Controllers.ReviewChanges').createToolbarPanel();
             if ( $panel )
-                me.toolbar.addTab(tab, $panel, 4);
+                me.toolbar.addTab(tab, $panel, 5);
 
             if ( config.isEdit ) {
                 me.toolbar.setMode(config);
@@ -3005,13 +3005,17 @@ define([
                         tab = {action: 'protect', caption: me.toolbar.textTabProtect};
                         $panel = me.getApplication().getController('Common.Controllers.Protection').createToolbarPanel();
 
-                        if ($panel) me.toolbar.addTab(tab, $panel, 5);
+                        if ($panel) me.toolbar.addTab(tab, $panel, 6);
                     }
                 }
 
                 var links = me.getApplication().getController('Links');
                 links.setApi(me.api).setConfig({toolbar: me});
                 Array.prototype.push.apply(me.toolbar.toolbarControls, links.getView('Links').getButtons());
+
+                var forms = me.getApplication().getController('FormsTab');
+                forms.setApi(me.api).setConfig({toolbar: me});
+                Array.prototype.push.apply(me.toolbar.toolbarControls, forms.getView('FormsTab').getButtons());
             }
         },
 
diff --git a/apps/documenteditor/main/app/template/Toolbar.template b/apps/documenteditor/main/app/template/Toolbar.template
index ad2a425a7..ffc080110 100644
--- a/apps/documenteditor/main/app/template/Toolbar.template
+++ b/apps/documenteditor/main/app/template/Toolbar.template
@@ -161,6 +161,29 @@
                     <span class="btn-slot text x-huge" id="slot-btn-crossref"></span>
                 </div>
             </section>
+            <section class="panel" data-tab="forms">
+                <div class="group">
+                    <span class="btn-slot text x-huge" id="slot-btn-form-field"></span>
+                    <span class="btn-slot text x-huge" id="slot-btn-form-combobox"></span>
+                    <span class="btn-slot text x-huge" id="slot-btn-form-dropdown"></span>
+                    <span class="btn-slot text x-huge" id="slot-btn-form-checkbox"></span>
+                    <span class="btn-slot text x-huge" id="slot-btn-form-radiobox"></span>
+                    <span class="btn-slot text x-huge" id="slot-btn-form-image"></span>
+                </div>
+                <div class="separator long"></div>
+                <div class="group" style="padding-left: 5px;">
+                    <div class="elset">
+                        <span class="btn-slot text" id="slot-form-clear-fields"></span>
+                    </div>
+                    <div class="elset">
+                        <span class="btn-slot text" id="slot-form-highlight"></span>
+                    </div>
+                </div>
+                <div class="separator long"></div>
+                <div class="group">
+                    <span class="btn-slot text x-huge" id="slot-btn-form-view"></span>
+                </div>
+            </section>
         </section>
     </section>
 </div>
\ No newline at end of file
diff --git a/apps/documenteditor/main/app/view/FormsTab.js b/apps/documenteditor/main/app/view/FormsTab.js
new file mode 100644
index 000000000..1ee02e88f
--- /dev/null
+++ b/apps/documenteditor/main/app/view/FormsTab.js
@@ -0,0 +1,261 @@
+/*
+ *
+ * (c) Copyright Ascensio System SIA 2010-2020
+ *
+ * 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-12 Ernesta Birznieka-Upisha
+ * 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
+ *
+ */
+
+/**
+ *  FormsTab.js
+ *
+ *  Created by Julia Radzhabova on 06.10.2020
+ *  Copyright (c) 2020 Ascensio System SIA. All rights reserved.
+ *
+ */
+
+define([
+    'common/main/lib/util/utils',
+    'common/main/lib/component/BaseView',
+    'common/main/lib/component/Layout'
+], function () {
+    'use strict';
+
+    DE.Views.FormsTab = Common.UI.BaseView.extend(_.extend((function(){
+        function setEvents() {
+            var me = this;
+            this.btnTextField.on('click', function (b, e) {
+                me.fireEvent('forms:insert', ['text']);
+            });
+            this.btnComboBox.on('click', function (b, e) {
+                me.fireEvent('forms:insert', ['combobox']);
+            });
+            this.btnDropDown.on('click', function (b, e) {
+                me.fireEvent('forms:insert', ['dropdown']);
+            });
+            this.btnCheckBox.on('click', function (b, e) {
+                me.fireEvent('forms:insert', ['checkbox']);
+            });
+            this.btnRadioBox.on('click', function (b, e) {
+                me.fireEvent('forms:insert', ['radiobox']);
+            });
+            this.btnImageField.on('click', function (b, e) {
+                me.fireEvent('forms:insert', ['image']);
+            });
+            this.btnViewForm.on('click', function (b, e) {
+                me.fireEvent('forms:mode', [b.pressed]);
+            });
+            this.btnClearFields.on('click', function (b, e) {
+                me.fireEvent('forms:clear');
+            });
+            $('#id-toolbar-menu-new-form-color').on('click', function (b, e) {
+                me.fireEvent('forms:new-color');
+            });
+            this.mnuNoControlsColor.on('click', function (item) {
+                me.fireEvent('forms:no-color', [item]);
+            });
+            this.mnuControlsColorPicker.on('select', function(picker, color) {
+                me.fireEvent('forms:select-color', [color]);
+            });
+        }
+
+        return {
+
+            options: {},
+
+            initialize: function (options) {
+                Common.UI.BaseView.prototype.initialize.call(this);
+                this.toolbar = options.toolbar;
+
+                this.paragraphControls = [];
+
+                var me = this,
+                    $host = me.toolbar.$el;
+
+                this.btnTextField = new Common.UI.Button({
+                    parentEl: $host.find('#slot-btn-form-field'),
+                    cls: 'btn-toolbar x-huge icon-top',
+                    iconCls: 'toolbar__icon btn-update',
+                    caption: this.capBtnText,
+                    disabled: true
+                });
+                this.paragraphControls.push(this.btnTextField);
+
+                this.btnComboBox = new Common.UI.Button({
+                    parentEl: $host.find('#slot-btn-form-combobox'),
+                    cls: 'btn-toolbar x-huge icon-top',
+                    iconCls: 'toolbar__icon btn-update',
+                    caption: this.capBtnComboBox,
+                    disabled: true
+                });
+                this.paragraphControls.push(this.btnComboBox);
+
+                this.btnDropDown = new Common.UI.Button({
+                    parentEl: $host.find('#slot-btn-form-dropdown'),
+                    cls: 'btn-toolbar x-huge icon-top',
+                    iconCls: 'toolbar__icon btn-update',
+                    caption: this.capBtnDropDown,
+                    disabled: true
+                });
+                this.paragraphControls.push(this.btnDropDown);
+
+                this.btnCheckBox = new Common.UI.Button({
+                    parentEl: $host.find('#slot-btn-form-checkbox'),
+                    cls: 'btn-toolbar x-huge icon-top',
+                    iconCls: 'toolbar__icon btn-update',
+                    caption: this.capBtnCheckBox,
+                    disabled: true
+                });
+                this.paragraphControls.push(this.btnCheckBox);
+
+                this.btnRadioBox = new Common.UI.Button({
+                    parentEl: $host.find('#slot-btn-form-radiobox'),
+                    cls: 'btn-toolbar x-huge icon-top',
+                    iconCls: 'toolbar__icon btn-update',
+                    caption: this.capBtnRadioBox,
+                    disabled: true
+                });
+                this.paragraphControls.push(this.btnRadioBox);
+
+                this.btnImageField = new Common.UI.Button({
+                    parentEl: $host.find('#slot-btn-form-image'),
+                    cls: 'btn-toolbar x-huge icon-top',
+                    iconCls: 'toolbar__icon btn-update',
+                    caption: this.capBtnImage,
+                    disabled: true
+                });
+                this.paragraphControls.push(this.btnImageField);
+
+                this.btnViewForm = new Common.UI.Button({
+                    parentEl: $host.find('#slot-btn-form-view'),
+                    cls: 'btn-toolbar x-huge icon-top',
+                    iconCls: 'toolbar__icon btn-update',
+                    caption: this.capBtnView,
+                    enableToggle: true,
+                    disabled: true
+                });
+                this.paragraphControls.push(this.btnViewForm);
+
+                this.btnClearFields = new Common.UI.Button({
+                    parentEl    : $host.find('#slot-form-clear-fields'),
+                    cls         : 'btn-toolbar',
+                    iconCls     : 'toolbar__icon btn-clearstyle',
+                    caption     : this.textClearFields,
+                    disabled: true
+                });
+                this.paragraphControls.push(this.btnClearFields);
+
+                this.btnHighlight = new Common.UI.Button({
+                    parentEl    : $host.find('#slot-form-highlight'),
+                    cls         : 'btn-toolbar',
+                    iconCls     : 'toolbar__icon btn-highlight',
+                    caption     : this.textHighlight,
+                    disabled: true
+                });
+                this.paragraphControls.push(this.btnHighlight);
+
+                this._state = {disabled: false};
+                Common.NotificationCenter.on('app:ready', this.onAppReady.bind(this));
+            },
+
+            render: function (el) {
+                return this;
+            },
+
+            onAppReady: function (config) {
+                var me = this;
+                (new Promise(function (accept, reject) {
+                    accept();
+                })).then(function(){
+                    me.btnHighlight.setMenu(new Common.UI.Menu({
+                        items: [
+                            me.mnuNoControlsColor = new Common.UI.MenuItem({
+                                id: 'id-toolbar-menu-no-highlight-form',
+                                caption: me.textNoHighlight,
+                                checkable: true
+                            }),
+                            {caption: '--'},
+                            {template: _.template('<div id="id-toolbar-menu-form-color" style="width: 169px; height: 220px; margin: 10px;"></div>')},
+                            {template: _.template('<a id="id-toolbar-menu-new-form-color" style="padding-left:12px;">' + me.textNewColor + '</a>')}
+                        ]
+                    }));
+                    me.mnuControlsColorPicker = new Common.UI.ThemeColorPalette({
+                        el: $('#id-toolbar-menu-form-color')
+                    });
+
+                    me.btnTextField.updateHint(me.tipTextField);
+                    me.btnComboBox.updateHint(me.tipComboBox);
+                    me.btnDropDown.updateHint(me.tipDropDown);
+                    me.btnCheckBox.updateHint(me.tipCheckBox);
+                    me.btnRadioBox.updateHint(me.tipRadioBox);
+                    me.btnImageField.updateHint(me.tipImageField);
+                    me.btnViewForm.updateHint(me.tipViewForm);
+
+                    setEvents.call(me);
+                });
+            },
+
+            show: function () {
+                Common.UI.BaseView.prototype.show.call(this);
+                this.fireEvent('show', this);
+            },
+
+            getButtons: function() {
+                return this.paragraphControls;
+            },
+
+            SetDisabled: function (state) {
+                this._state.disabled = state;
+                this.paragraphControls.forEach(function(button) {
+                    if ( button ) {
+                        button.setDisabled(state);
+                    }
+                }, this);
+            },
+
+            capBtnText: 'Text Field',
+            capBtnComboBox: 'Combo Box',
+            capBtnDropDown: 'Dropdown',
+            capBtnCheckBox: 'Checkbox',
+            capBtnRadioBox: 'Radio Button',
+            capBtnImage: 'Image',
+            capBtnView: 'View Form',
+            textClearFields: 'Clear All Fields',
+            textHighlight: 'Highlight Settings',
+            tipTextField: 'Insert text field',
+            tipComboBox: 'Insert combo box',
+            tipDropDown: 'Insert dropdown list',
+            tipCheckBox: 'Insert checkbox',
+            tipRadioBox: 'Insert radio button',
+            tipImageField: 'Insert image',
+            tipViewForm: 'Fill form mode',
+            textNoHighlight: 'No highlighting',
+            textNewColor: 'Add New Custom Color'
+        }
+    }()), DE.Views.FormsTab || {}));
+});
\ No newline at end of file
diff --git a/apps/documenteditor/main/app/view/Toolbar.js b/apps/documenteditor/main/app/view/Toolbar.js
index 029d2ac39..da506268a 100644
--- a/apps/documenteditor/main/app/view/Toolbar.js
+++ b/apps/documenteditor/main/app/view/Toolbar.js
@@ -113,7 +113,8 @@ define([
                                 {caption: me.textTabHome, action: 'home', extcls: 'canedit'},
                                 {caption: me.textTabInsert, action: 'ins', extcls: 'canedit'},
                                 {caption: me.textTabLayout, action: 'layout', extcls: 'canedit'},
-                                {caption: me.textTabLinks, action: 'links', extcls: 'canedit'}
+                                {caption: me.textTabLinks, action: 'links', extcls: 'canedit'},
+                                {caption: me.textTabForms, action: 'forms', extcls: 'canedit'}
                             ]
                         }
                     );
@@ -2362,7 +2363,8 @@ define([
             textNewComboboxControl: 'New combo box',
             textNewCheckboxControl: 'New check box',
             textNewRadioboxControl: 'New radio box',
-            textNewDropdownControl: 'New drop-down list'
+            textNewDropdownControl: 'New drop-down list',
+            textTabForms: 'Forms'
         }
     })(), DE.Views.Toolbar || {}));
 });
diff --git a/apps/documenteditor/main/app_dev.js b/apps/documenteditor/main/app_dev.js
index ea9a07eba..b0333ef3f 100644
--- a/apps/documenteditor/main/app_dev.js
+++ b/apps/documenteditor/main/app_dev.js
@@ -141,6 +141,7 @@ require([
             'Toolbar',
             'Statusbar',
             'Links',
+            'FormsTab',
             'Navigation',
             'RightMenu',
             'LeftMenu',
@@ -166,6 +167,7 @@ require([
                 'documenteditor/main/app/controller/DocumentHolder',
                 'documenteditor/main/app/controller/Toolbar',
                 'documenteditor/main/app/controller/Links',
+                'documenteditor/main/app/controller/FormsTab',
                 'documenteditor/main/app/controller/Navigation',
                 'documenteditor/main/app/controller/Statusbar',
                 'documenteditor/main/app/controller/RightMenu',

From 833f4058e7ffc2d3c2601349400b9091914406f0 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Wed, 7 Oct 2020 14:20:14 +0300
Subject: [PATCH 14/33] [DE] Fix forms tab

---
 .../main/app/controller/FormsTab.js           | 191 +++++++++---------
 .../main/app/controller/Toolbar.js            |  14 +-
 .../main/app/view/FormSettings.js             |   2 +
 apps/documenteditor/main/app/view/FormsTab.js |  66 +++---
 apps/documenteditor/main/app/view/Toolbar.js  |   6 +-
 5 files changed, 148 insertions(+), 131 deletions(-)

diff --git a/apps/documenteditor/main/app/controller/FormsTab.js b/apps/documenteditor/main/app/controller/FormsTab.js
index 3ce0ed8f9..c5988717a 100644
--- a/apps/documenteditor/main/app/controller/FormsTab.js
+++ b/apps/documenteditor/main/app/controller/FormsTab.js
@@ -55,22 +55,10 @@ define([
         sdkViewName : '#id_main',
 
         initialize: function () {
-
-            this.addListeners({
-                'FormsTab': {
-                    'forms:insert': this.onControlsSelect,
-                    'forms:new-color': this.onNewControlsColor,
-                    'forms:clear': this.onClearClick,
-                    'forms:no-color': this.onNoControlsColor,
-                    'forms:select-color': this.onSelectControlsColor,
-                    'forms:mode': this.onModeClick
-                }
-            });
         },
         onLaunch: function () {
             this._state = {
-                prcontrolsdisable:undefined,
-                in_object: false
+                prcontrolsdisable:undefined
             };
         },
 
@@ -80,6 +68,9 @@ define([
                 this.api.asc_registerCallback('asc_onFocusObject', this.onApiFocusObject.bind(this));
                 this.api.asc_registerCallback('asc_onCoAuthoringDisconnect',_.bind(this.onCoAuthoringDisconnect, this));
                 Common.NotificationCenter.on('api:disconnect', _.bind(this.onCoAuthoringDisconnect, this));
+                this.api.asc_registerCallback('asc_onChangeSdtGlobalSettings', _.bind(this.onChangeSdtGlobalSettings, this));
+                this.api.asc_registerCallback('asc_onSendThemeColors', _.bind(this.onSendThemeColors, this));
+
                 // this.api.asc_registerCallback('asc_onShowContentControlsActions',_.bind(this.onShowContentControlsActions, this));
                 // this.api.asc_registerCallback('asc_onHideContentControlsActions',_.bind(this.onHideContentControlsActions, this));
             }
@@ -91,6 +82,17 @@ define([
             this.view = this.createView('FormsTab', {
                 toolbar: this.toolbar.toolbar
             });
+            this.addListeners({
+                'FormsTab': {
+                    'forms:insert': this.onControlsSelect,
+                    'forms:new-color': this.onNewControlsColor,
+                    'forms:clear': this.onClearClick,
+                    'forms:no-color': this.onNoControlsColor,
+                    'forms:select-color': this.onSelectControlsColor,
+                    'forms:open-color': this.onColorsShow,
+                    'forms:mode': this.onModeClick
+                }
+            });
         },
 
         SetDisabled: function(state) {
@@ -111,12 +113,7 @@ define([
 
             var pr, i = -1, type,
                 paragraph_locked = false,
-                header_locked = false,
-                in_header = false,
-                in_equation = false,
-                in_image = false,
-                in_table = false,
-                frame_pr = null;
+                header_locked = false;
 
             while (++i < selectedObjects.length) {
                 type = selectedObjects[i].get_ObjectType();
@@ -124,93 +121,97 @@ define([
 
                 if (type === Asc.c_oAscTypeSelectElement.Paragraph) {
                     paragraph_locked = pr.get_Locked();
-                    frame_pr = pr;
                 } else if (type === Asc.c_oAscTypeSelectElement.Header) {
                     header_locked = pr.get_Locked();
-                    in_header = true;
-                } else if (type === Asc.c_oAscTypeSelectElement.Image) {
-                    in_image = true;
-                } else if (type === Asc.c_oAscTypeSelectElement.Math) {
-                    in_equation = true;
-                } else if (type === Asc.c_oAscTypeSelectElement.Table) {
-                    in_table = true;
                 }
             }
-            this._state.prcontrolsdisable = paragraph_locked || header_locked;
-            this._state.in_object = in_image || in_table || in_equation;
+            var in_control = this.api.asc_IsContentControl();
+            var control_props = in_control ? this.api.asc_GetContentControlProperties() : null,
+                lock_type = (in_control&&control_props) ? control_props.get_Lock() : Asc.c_oAscSdtLockType.Unlocked,
+                control_plain = (in_control&&control_props) ? (control_props.get_ContentControlType()==Asc.c_oAscSdtLevelType.Inline) : false;
+            (lock_type===undefined) && (lock_type = Asc.c_oAscSdtLockType.Unlocked);
+            var content_locked = lock_type==Asc.c_oAscSdtLockType.SdtContentLocked || lock_type==Asc.c_oAscSdtLockType.ContentLocked;
+            var need_disable = (paragraph_locked || header_locked || control_plain || content_locked);
+            if (this._state.prcontrolsdisable !== need_disable) {
+                this.view.btnTextField.setDisabled(need_disable);
+                this.view.btnComboBox.setDisabled(need_disable);
+                this.view.btnDropDown.setDisabled(need_disable);
+                this.view.btnCheckBox.setDisabled(need_disable);
+                this.view.btnRadioBox.setDisabled(need_disable);
+                this.view.btnImageField.setDisabled(need_disable);
+                this.view.btnTextField.setDisabled(need_disable);
+                this._state.prcontrolsdisable = need_disable;
+            }
+        },
 
-            var control_props = this.api.asc_IsContentControl() ? this.api.asc_GetContentControlProperties() : null,
-                control_plain = (control_props) ? (control_props.get_ContentControlType()==Asc.c_oAscSdtLevelType.Inline) : false,
-                lock_type = control_props ? control_props.get_Lock() : Asc.c_oAscSdtLockType.Unlocked,
-                content_locked = lock_type==Asc.c_oAscSdtLockType.SdtContentLocked || lock_type==Asc.c_oAscSdtLockType.ContentLocked;
-            var rich_del_lock = (frame_pr) ? !frame_pr.can_DeleteBlockContentControl() : false,
-                rich_edit_lock = (frame_pr) ? !frame_pr.can_EditBlockContentControl() : false,
-                plain_del_lock = (frame_pr) ? !frame_pr.can_DeleteInlineContentControl() : false,
-                plain_edit_lock = (frame_pr) ? !frame_pr.can_EditInlineContentControl() : false;
+        onSendThemeColors: function() {
+            this._needUpdateColors = true;
+        },
 
+        updateThemeColors: function() {
+            var updateColors = function(picker, defaultColorIndex) {
+                if (picker) {
+                    var clr;
 
-            var need_disable = paragraph_locked || in_equation || in_image || in_header || control_plain || rich_edit_lock || plain_edit_lock;
+                    var effectcolors = Common.Utils.ThemeColor.getEffectColors();
+                    for (var i = 0; i < effectcolors.length; i++) {
+                        if (typeof(picker.currentColor) == 'object' &&
+                            clr === undefined &&
+                            picker.currentColor.effectId == effectcolors[i].effectId)
+                            clr = effectcolors[i];
+                    }
+
+                    picker.updateColors(effectcolors, Common.Utils.ThemeColor.getStandartColors());
+                    if (picker.currentColor === undefined) {
+                        picker.currentColor = effectcolors[defaultColorIndex];
+                    } else if ( clr!==undefined ) {
+                        picker.currentColor = clr;
+                    }
+                }
+            };
+
+            this.view && this.view.mnuFormsColorPicker && updateColors(this.view.mnuFormsColorPicker, 1);
+            this.onChangeSdtGlobalSettings();
+        },
+
+        onChangeSdtGlobalSettings: function() {
+            var show = this.api.asc_GetGlobalContentControlShowHighlight();
+            if (this.view && this.view.mnuFormsColorPicker) {
+                this.view.mnuNoFormsColor.setChecked(!show, true);
+                this.view.mnuFormsColorPicker.clearSelection();
+                if (show){
+                    var clr = this.api.asc_GetGlobalContentControlHighlightColor();
+                    if (clr) {
+                        clr = Common.Utils.ThemeColor.getHexColor(clr.get_r(), clr.get_g(), clr.get_b());
+                        this.view.mnuFormsColorPicker.selectByRGB(clr, true);
+                    }
+                }
+            }
+        },
+
+        onColorsShow: function(menu) {
+            this._needUpdateColors && this.updateThemeColors();
+            this._needUpdateColors = false;
         },
 
         onControlsSelect: function(type) {
-            if (!(this.mode && this.mode.canFeatureContentControl)) return;
+            if (!(this.toolbar.mode && this.toolbar.mode.canFeatureContentControl)) return;
 
-            if (item.value == 'settings' || item.value == 'remove') {
-                if (this.api.asc_IsContentControl()) {
-                    var props = this.api.asc_GetContentControlProperties();
-                    if (props) {
-                        var id = props.get_InternalId();
-                        if (item.value == 'settings') {
-                            var me = this;
-                            (new DE.Views.ControlSettingsDialog({
-                                props: props,
-                                api: me.api,
-                                controlLang: me._state.lang,
-                                interfaceLang: me.mode.lang,
-                                handler: function(result, value) {
-                                    if (result == 'ok') {
-                                        me.api.asc_SetContentControlProperties(value, id);
-                                    }
-
-                                    Common.NotificationCenter.trigger('edit:complete', me.toolbar);
-                                }
-                            })).show();
-
-                        } else {
-                            this.api.asc_RemoveContentControlWrapper(id);
-                            Common.component.Analytics.trackEvent('ToolBar', 'Remove Content Control');
-                        }
-                    }
-                }
-            } else {
-                var isnew = (item.value.indexOf('new-')==0),
-                    oPr, oFormPr;
-                if (isnew) {
-                    oFormPr = new AscCommon.CSdtFormPr();
-                    this.toolbar.fireEvent('insertcontrol', this.toolbar);
-                }
-                if (item.value == 'plain' || item.value == 'rich')
-                    this.api.asc_AddContentControl((item.value=='plain') ? Asc.c_oAscSdtLevelType.Inline : Asc.c_oAscSdtLevelType.Block);
-                else if (item.value.indexOf('picture')>=0)
-                    this.api.asc_AddContentControlPicture(oFormPr);
-                else if (item.value.indexOf('checkbox')>=0 || item.value.indexOf('radiobox')>=0) {
-                    if (isnew) {
-                        oPr = new AscCommon.CSdtCheckBoxPr();
-                        (item.value.indexOf('radiobox')>=0) && oPr.put_GroupKey('Group 1');
-                    }
-                    this.api.asc_AddContentControlCheckBox(oPr, oFormPr);
-                } else if (item.value == 'date')
-                    this.api.asc_AddContentControlDatePicker();
-                else if (item.value.indexOf('combobox')>=0 || item.value.indexOf('dropdown')>=0)
-                    this.api.asc_AddContentControlList(item.value.indexOf('combobox')>=0, oPr, oFormPr);
-                else if (item.value == 'new-field') {
-                    oPr = new AscCommon.CSdtTextFormPr();
-                    this.api.asc_AddContentControlTextForm(oPr, oFormPr);
-                }
-
-                Common.component.Analytics.trackEvent('ToolBar', 'Add Content Control');
+            var oPr,
+                oFormPr = new AscCommon.CSdtFormPr();
+            this.toolbar.toolbar.fireEvent('insertcontrol', this.toolbar.toolbar);
+            if (type == 'picture')
+                this.api.asc_AddContentControlPicture(oFormPr);
+            else if (type == 'checkbox' || type == 'radiobox') {
+                oPr = new AscCommon.CSdtCheckBoxPr();
+                (type == 'radiobox') && oPr.put_GroupKey('Group 1');
+                this.api.asc_AddContentControlCheckBox(oPr, oFormPr);
+            } else if (type == 'combobox' || type == 'dropdown')
+                this.api.asc_AddContentControlList(type == 'combobox', oPr, oFormPr);
+            else if (type == 'text') {
+                oPr = new AscCommon.CSdtTextFormPr();
+                this.api.asc_AddContentControlTextForm(oPr, oFormPr);
             }
-
             Common.NotificationCenter.trigger('edit:complete', this.toolbar);
         },
 
@@ -229,7 +230,7 @@ define([
         },
 
         onNewControlsColor: function() {
-            this.view.mnuControlsColorPicker.addNewColor();
+            this.view.mnuFormsColorPicker.addNewColor();
         },
 
         onNoControlsColor: function(item) {
diff --git a/apps/documenteditor/main/app/controller/Toolbar.js b/apps/documenteditor/main/app/controller/Toolbar.js
index a21c44062..08e49c9a8 100644
--- a/apps/documenteditor/main/app/controller/Toolbar.js
+++ b/apps/documenteditor/main/app/controller/Toolbar.js
@@ -3013,9 +3013,14 @@ define([
                 links.setApi(me.api).setConfig({toolbar: me});
                 Array.prototype.push.apply(me.toolbar.toolbarControls, links.getView('Links').getButtons());
 
-                var forms = me.getApplication().getController('FormsTab');
-                forms.setApi(me.api).setConfig({toolbar: me});
-                Array.prototype.push.apply(me.toolbar.toolbarControls, forms.getView('FormsTab').getButtons());
+                if (config.canFeatureContentControl) {
+                    tab = {caption: me.textTabForms, action: 'forms'};
+                    var forms = me.getApplication().getController('FormsTab');
+                    forms.setApi(me.api).setConfig({toolbar: me});
+                    me.toolbar.addTab(tab, $panel, 4);
+                    me.toolbar.setVisible('forms', true);
+                    Array.prototype.push.apply(me.toolbar.toolbarControls, forms.getView('FormsTab').getButtons());
+                }
             }
         },
 
@@ -3437,7 +3442,8 @@ define([
         notcriticalErrorTitle: 'Warning',
         txtMarginsW: 'Left and right margins are too high for a given page wight',
         txtMarginsH: 'Top and bottom margins are too high for a given page height',
-        textInsert: 'Insert'
+        textInsert: 'Insert',
+        textTabForms: 'Forms'
 
     }, DE.Controllers.Toolbar || {}));
 });
diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index e2f10d681..0a7b79a50 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -659,6 +659,8 @@ define([
         },
 
         disableControls: function(disable) {
+            if (this._initSettings) return;
+            
             var me = this;
             if (this._state.DisabledControls!==(this._state.LockDelete || disable)) {
                 this._state.DisabledControls = this._state.LockDelete || disable;
diff --git a/apps/documenteditor/main/app/view/FormsTab.js b/apps/documenteditor/main/app/view/FormsTab.js
index 1ee02e88f..9febd463a 100644
--- a/apps/documenteditor/main/app/view/FormsTab.js
+++ b/apps/documenteditor/main/app/view/FormsTab.js
@@ -65,23 +65,28 @@ define([
                 me.fireEvent('forms:insert', ['radiobox']);
             });
             this.btnImageField.on('click', function (b, e) {
-                me.fireEvent('forms:insert', ['image']);
+                me.fireEvent('forms:insert', ['picture']);
             });
             this.btnViewForm.on('click', function (b, e) {
                 me.fireEvent('forms:mode', [b.pressed]);
             });
-            this.btnClearFields.on('click', function (b, e) {
-                me.fireEvent('forms:clear');
-            });
-            $('#id-toolbar-menu-new-form-color').on('click', function (b, e) {
-                me.fireEvent('forms:new-color');
-            });
-            this.mnuNoControlsColor.on('click', function (item) {
-                me.fireEvent('forms:no-color', [item]);
-            });
-            this.mnuControlsColorPicker.on('select', function(picker, color) {
-                me.fireEvent('forms:select-color', [color]);
-            });
+            if (this.mnuFormsColorPicker) {
+                this.btnClearFields.on('click', function (b, e) {
+                    me.fireEvent('forms:clear');
+                });
+                $('#id-toolbar-menu-new-form-color').on('click', function (b, e) {
+                    me.fireEvent('forms:new-color');
+                });
+                this.mnuNoFormsColor.on('click', function (item) {
+                    me.fireEvent('forms:no-color', [item]);
+                });
+                this.mnuFormsColorPicker.on('select', function(picker, color) {
+                    me.fireEvent('forms:select-color', [color]);
+                });
+                this.btnHighlight.menu.on('show:after', function(picker, color) {
+                    me.fireEvent('forms:open-color', [color]);
+                });
+            }
         }
 
         return {
@@ -175,6 +180,7 @@ define([
                     cls         : 'btn-toolbar',
                     iconCls     : 'toolbar__icon btn-highlight',
                     caption     : this.textHighlight,
+                    menu        : true,
                     disabled: true
                 });
                 this.paragraphControls.push(this.btnHighlight);
@@ -192,21 +198,25 @@ define([
                 (new Promise(function (accept, reject) {
                     accept();
                 })).then(function(){
-                    me.btnHighlight.setMenu(new Common.UI.Menu({
-                        items: [
-                            me.mnuNoControlsColor = new Common.UI.MenuItem({
-                                id: 'id-toolbar-menu-no-highlight-form',
-                                caption: me.textNoHighlight,
-                                checkable: true
-                            }),
-                            {caption: '--'},
-                            {template: _.template('<div id="id-toolbar-menu-form-color" style="width: 169px; height: 220px; margin: 10px;"></div>')},
-                            {template: _.template('<a id="id-toolbar-menu-new-form-color" style="padding-left:12px;">' + me.textNewColor + '</a>')}
-                        ]
-                    }));
-                    me.mnuControlsColorPicker = new Common.UI.ThemeColorPalette({
-                        el: $('#id-toolbar-menu-form-color')
-                    });
+                    if (config.canEditContentControl) {
+                        me.btnHighlight.setMenu(new Common.UI.Menu({
+                            items: [
+                                me.mnuNoFormsColor = new Common.UI.MenuItem({
+                                    id: 'id-toolbar-menu-no-highlight-form',
+                                    caption: me.textNoHighlight,
+                                    checkable: true
+                                }),
+                                {caption: '--'},
+                                {template: _.template('<div id="id-toolbar-menu-form-color" style="width: 169px; height: 220px; margin: 10px;"></div>')},
+                                {template: _.template('<a id="id-toolbar-menu-new-form-color" style="padding-left:12px;">' + me.textNewColor + '</a>')}
+                            ]
+                        }));
+                        me.mnuFormsColorPicker = new Common.UI.ThemeColorPalette({
+                            el: $('#id-toolbar-menu-form-color')
+                        });
+                    } else {
+                        me.btnHighlight.cmpEl.parents('.group').hide().prev('.separator').hide();
+                    }
 
                     me.btnTextField.updateHint(me.tipTextField);
                     me.btnComboBox.updateHint(me.tipComboBox);
diff --git a/apps/documenteditor/main/app/view/Toolbar.js b/apps/documenteditor/main/app/view/Toolbar.js
index da506268a..029d2ac39 100644
--- a/apps/documenteditor/main/app/view/Toolbar.js
+++ b/apps/documenteditor/main/app/view/Toolbar.js
@@ -113,8 +113,7 @@ define([
                                 {caption: me.textTabHome, action: 'home', extcls: 'canedit'},
                                 {caption: me.textTabInsert, action: 'ins', extcls: 'canedit'},
                                 {caption: me.textTabLayout, action: 'layout', extcls: 'canedit'},
-                                {caption: me.textTabLinks, action: 'links', extcls: 'canedit'},
-                                {caption: me.textTabForms, action: 'forms', extcls: 'canedit'}
+                                {caption: me.textTabLinks, action: 'links', extcls: 'canedit'}
                             ]
                         }
                     );
@@ -2363,8 +2362,7 @@ define([
             textNewComboboxControl: 'New combo box',
             textNewCheckboxControl: 'New check box',
             textNewRadioboxControl: 'New radio box',
-            textNewDropdownControl: 'New drop-down list',
-            textTabForms: 'Forms'
+            textNewDropdownControl: 'New drop-down list'
         }
     })(), DE.Views.Toolbar || {}));
 });

From b357198994b0d7adeb8390f88513ad25c5b7493e Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Wed, 7 Oct 2020 15:44:36 +0300
Subject: [PATCH 15/33] [DE] Add icons

---
 .../img/toolbar/1.25x/big/btn-sheet-view.png     | Bin
 .../img/toolbar/1.5x/big/btn-sheet-view.png      | Bin
 .../img/toolbar/1.75x/big/btn-sheet-view.png     | Bin
 .../img/toolbar/1x/big/btn-sheet-view.png        | Bin
 .../img/toolbar/2x/big/btn-sheet-view.png        | Bin
 .../main/app/template/RightMenu.template         |   2 +-
 .../documenteditor/main/app/view/FormSettings.js |   4 ++--
 apps/documenteditor/main/app/view/FormsTab.js    |  14 +++++++-------
 .../img/toolbar/1x/big/btn-checkbox.png          | Bin 0 -> 413 bytes
 .../img/toolbar/1x/big/btn-combo-box.png         | Bin 0 -> 334 bytes
 .../img/toolbar/1x/big/btn-dropdown.png          | Bin 0 -> 326 bytes
 .../img/toolbar/1x/big/btn-radio-button.png      | Bin 0 -> 1004 bytes
 .../img/toolbar/1x/big/btn-text-field.png        | Bin 0 -> 246 bytes
 .../main/resources/img/toolbar/1x/btn-field.png  | Bin 0 -> 226 bytes
 .../main/resources/img/toolbar/1x/btn-lock.png   | Bin 0 -> 477 bytes
 .../img/toolbar/2x/big/btn-checkbox.png          | Bin 0 -> 576 bytes
 .../img/toolbar/2x/big/btn-combo-box.png         | Bin 0 -> 525 bytes
 .../img/toolbar/2x/big/btn-dropdown.png          | Bin 0 -> 512 bytes
 .../img/toolbar/2x/big/btn-radio-button.png      | Bin 0 -> 2146 bytes
 .../img/toolbar/2x/big/btn-text-field.png        | Bin 0 -> 321 bytes
 .../main/resources/img/toolbar/2x/btn-field.png  | Bin 0 -> 279 bytes
 .../main/resources/img/toolbar/2x/btn-lock.png   | Bin 0 -> 909 bytes
 22 files changed, 10 insertions(+), 10 deletions(-)
 rename apps/{spreadsheeteditor => common}/main/resources/img/toolbar/1.25x/big/btn-sheet-view.png (100%)
 rename apps/{spreadsheeteditor => common}/main/resources/img/toolbar/1.5x/big/btn-sheet-view.png (100%)
 rename apps/{spreadsheeteditor => common}/main/resources/img/toolbar/1.75x/big/btn-sheet-view.png (100%)
 rename apps/{spreadsheeteditor => common}/main/resources/img/toolbar/1x/big/btn-sheet-view.png (100%)
 rename apps/{spreadsheeteditor => common}/main/resources/img/toolbar/2x/big/btn-sheet-view.png (100%)
 create mode 100644 apps/documenteditor/main/resources/img/toolbar/1x/big/btn-checkbox.png
 create mode 100644 apps/documenteditor/main/resources/img/toolbar/1x/big/btn-combo-box.png
 create mode 100644 apps/documenteditor/main/resources/img/toolbar/1x/big/btn-dropdown.png
 create mode 100644 apps/documenteditor/main/resources/img/toolbar/1x/big/btn-radio-button.png
 create mode 100644 apps/documenteditor/main/resources/img/toolbar/1x/big/btn-text-field.png
 create mode 100644 apps/documenteditor/main/resources/img/toolbar/1x/btn-field.png
 create mode 100644 apps/documenteditor/main/resources/img/toolbar/1x/btn-lock.png
 create mode 100644 apps/documenteditor/main/resources/img/toolbar/2x/big/btn-checkbox.png
 create mode 100644 apps/documenteditor/main/resources/img/toolbar/2x/big/btn-combo-box.png
 create mode 100644 apps/documenteditor/main/resources/img/toolbar/2x/big/btn-dropdown.png
 create mode 100644 apps/documenteditor/main/resources/img/toolbar/2x/big/btn-radio-button.png
 create mode 100644 apps/documenteditor/main/resources/img/toolbar/2x/big/btn-text-field.png
 create mode 100644 apps/documenteditor/main/resources/img/toolbar/2x/btn-field.png
 create mode 100644 apps/documenteditor/main/resources/img/toolbar/2x/btn-lock.png

diff --git a/apps/spreadsheeteditor/main/resources/img/toolbar/1.25x/big/btn-sheet-view.png b/apps/common/main/resources/img/toolbar/1.25x/big/btn-sheet-view.png
similarity index 100%
rename from apps/spreadsheeteditor/main/resources/img/toolbar/1.25x/big/btn-sheet-view.png
rename to apps/common/main/resources/img/toolbar/1.25x/big/btn-sheet-view.png
diff --git a/apps/spreadsheeteditor/main/resources/img/toolbar/1.5x/big/btn-sheet-view.png b/apps/common/main/resources/img/toolbar/1.5x/big/btn-sheet-view.png
similarity index 100%
rename from apps/spreadsheeteditor/main/resources/img/toolbar/1.5x/big/btn-sheet-view.png
rename to apps/common/main/resources/img/toolbar/1.5x/big/btn-sheet-view.png
diff --git a/apps/spreadsheeteditor/main/resources/img/toolbar/1.75x/big/btn-sheet-view.png b/apps/common/main/resources/img/toolbar/1.75x/big/btn-sheet-view.png
similarity index 100%
rename from apps/spreadsheeteditor/main/resources/img/toolbar/1.75x/big/btn-sheet-view.png
rename to apps/common/main/resources/img/toolbar/1.75x/big/btn-sheet-view.png
diff --git a/apps/spreadsheeteditor/main/resources/img/toolbar/1x/big/btn-sheet-view.png b/apps/common/main/resources/img/toolbar/1x/big/btn-sheet-view.png
similarity index 100%
rename from apps/spreadsheeteditor/main/resources/img/toolbar/1x/big/btn-sheet-view.png
rename to apps/common/main/resources/img/toolbar/1x/big/btn-sheet-view.png
diff --git a/apps/spreadsheeteditor/main/resources/img/toolbar/2x/big/btn-sheet-view.png b/apps/common/main/resources/img/toolbar/2x/big/btn-sheet-view.png
similarity index 100%
rename from apps/spreadsheeteditor/main/resources/img/toolbar/2x/big/btn-sheet-view.png
rename to apps/common/main/resources/img/toolbar/2x/big/btn-sheet-view.png
diff --git a/apps/documenteditor/main/app/template/RightMenu.template b/apps/documenteditor/main/app/template/RightMenu.template
index 0af6d1dda..a42d7b2f8 100644
--- a/apps/documenteditor/main/app/template/RightMenu.template
+++ b/apps/documenteditor/main/app/template/RightMenu.template
@@ -32,6 +32,6 @@
         <button id="id-right-menu-textart" class="btn btn-category arrow-left" content-target="id-textart-settings"><i class="icon toolbar__icon btn-menu-textart">&nbsp;</i></button>
         <button id="id-right-menu-mail-merge" class="btn btn-category arrow-left hidden" content-target="id-mail-merge-settings"><i class="icon toolbar__icon btn-mailmerge">&nbsp;</i></button>
         <button id="id-right-menu-signature" class="btn btn-category arrow-left hidden" content-target="id-signature-settings"><i class="icon toolbar__icon btn-menu-signature">&nbsp;</i></button>
-        <button id="id-right-menu-form" class="btn btn-category arrow-left hidden" content-target="id-form-settings"><i class="icon toolbar__icon btn-menu-signature">&nbsp;</i></button>
+        <button id="id-right-menu-form" class="btn btn-category arrow-left hidden" content-target="id-form-settings"><i class="icon toolbar__icon btn-field">&nbsp;</i></button>
     </div>
 </div>
\ No newline at end of file
diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index 0a7b79a50..b840cf295 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -295,7 +295,7 @@ define([
             this.btnLockForm = new Common.UI.Button({
                 parentEl: $markup.findById('#form-btn-lock'),
                 cls         : 'btn-toolbar',
-                iconCls     : 'toolbar__icon btn-remove-duplicates',
+                iconCls     : 'toolbar__icon btn-lock',
                 caption     : this.textLock,
                 style       : 'text-align: left;'
             });
@@ -660,7 +660,7 @@ define([
 
         disableControls: function(disable) {
             if (this._initSettings) return;
-            
+
             var me = this;
             if (this._state.DisabledControls!==(this._state.LockDelete || disable)) {
                 this._state.DisabledControls = this._state.LockDelete || disable;
diff --git a/apps/documenteditor/main/app/view/FormsTab.js b/apps/documenteditor/main/app/view/FormsTab.js
index 9febd463a..fabea0b9f 100644
--- a/apps/documenteditor/main/app/view/FormsTab.js
+++ b/apps/documenteditor/main/app/view/FormsTab.js
@@ -105,7 +105,7 @@ define([
                 this.btnTextField = new Common.UI.Button({
                     parentEl: $host.find('#slot-btn-form-field'),
                     cls: 'btn-toolbar x-huge icon-top',
-                    iconCls: 'toolbar__icon btn-update',
+                    iconCls: 'toolbar__icon btn-text-field',
                     caption: this.capBtnText,
                     disabled: true
                 });
@@ -114,7 +114,7 @@ define([
                 this.btnComboBox = new Common.UI.Button({
                     parentEl: $host.find('#slot-btn-form-combobox'),
                     cls: 'btn-toolbar x-huge icon-top',
-                    iconCls: 'toolbar__icon btn-update',
+                    iconCls: 'toolbar__icon btn-combo-box',
                     caption: this.capBtnComboBox,
                     disabled: true
                 });
@@ -123,7 +123,7 @@ define([
                 this.btnDropDown = new Common.UI.Button({
                     parentEl: $host.find('#slot-btn-form-dropdown'),
                     cls: 'btn-toolbar x-huge icon-top',
-                    iconCls: 'toolbar__icon btn-update',
+                    iconCls: 'toolbar__icon btn-dropdown',
                     caption: this.capBtnDropDown,
                     disabled: true
                 });
@@ -132,7 +132,7 @@ define([
                 this.btnCheckBox = new Common.UI.Button({
                     parentEl: $host.find('#slot-btn-form-checkbox'),
                     cls: 'btn-toolbar x-huge icon-top',
-                    iconCls: 'toolbar__icon btn-update',
+                    iconCls: 'toolbar__icon btn-checkbox',
                     caption: this.capBtnCheckBox,
                     disabled: true
                 });
@@ -141,7 +141,7 @@ define([
                 this.btnRadioBox = new Common.UI.Button({
                     parentEl: $host.find('#slot-btn-form-radiobox'),
                     cls: 'btn-toolbar x-huge icon-top',
-                    iconCls: 'toolbar__icon btn-update',
+                    iconCls: 'toolbar__icon btn-radio-button',
                     caption: this.capBtnRadioBox,
                     disabled: true
                 });
@@ -150,7 +150,7 @@ define([
                 this.btnImageField = new Common.UI.Button({
                     parentEl: $host.find('#slot-btn-form-image'),
                     cls: 'btn-toolbar x-huge icon-top',
-                    iconCls: 'toolbar__icon btn-update',
+                    iconCls: 'toolbar__icon btn-insertimage',
                     caption: this.capBtnImage,
                     disabled: true
                 });
@@ -159,7 +159,7 @@ define([
                 this.btnViewForm = new Common.UI.Button({
                     parentEl: $host.find('#slot-btn-form-view'),
                     cls: 'btn-toolbar x-huge icon-top',
-                    iconCls: 'toolbar__icon btn-update',
+                    iconCls: 'toolbar__icon btn-sheet-view',
                     caption: this.capBtnView,
                     enableToggle: true,
                     disabled: true
diff --git a/apps/documenteditor/main/resources/img/toolbar/1x/big/btn-checkbox.png b/apps/documenteditor/main/resources/img/toolbar/1x/big/btn-checkbox.png
new file mode 100644
index 0000000000000000000000000000000000000000..b69f2d9a49fe8afc3e84334c4e812796e74e0cb8
GIT binary patch
literal 413
zcmeAS@N?(olHy`uVBq!ia0vp^7C<b+!3HEvcGuVeDb50q$YKTtZeb8+WSBKa0w~B>
z9OUlAu<o49OCX0O-O<;Pfnj4m_n$;opq!DXi(^Oy<J%i|Ihzdx4txx@c5p9f>3h)J
zwBGMlxZ}dS3w;*^cQxFy_EhLPw%&V{YQ2Wj)Ft*=my{Y#KmC<@??bOeUv$D69dG~g
zeMcJ%`7g&E;EXX6Q!mKTk^g7IZd3i{fQhg31_{000p;^VXQ-T9yY98Sh->%;fk$~2
z6%PuF?93D%ekeE|9u|6)okzXkZq1L=2A1;N0Y^n$KQbNWEx7fwjJdyOaa!Z9uPIE+
zqy4iBr-*r2Cke3lGrmma5P$SgQ{iy&YM|hZ=Ra?M|GOr0*6uEo(&$I*^_ORuZ0owy
zwOFrMT!6t*XlCd3-nEuY3LZ+;pVuA@>^75ZI*~7=lcT|ONimVVFKSP>mrBGfUC}3L
zGN#qtt8O-|eA{^P&iuEV&8xbL?6=M6{=KpF^iwOp`1QXwcP1@iiUfuxgQu&X%Q~lo
FCIC_Ur2PN@

literal 0
HcmV?d00001

diff --git a/apps/documenteditor/main/resources/img/toolbar/1x/big/btn-combo-box.png b/apps/documenteditor/main/resources/img/toolbar/1x/big/btn-combo-box.png
new file mode 100644
index 0000000000000000000000000000000000000000..e834d58e9a4853bd08ea040bffdb47609c493cd9
GIT binary patch
literal 334
zcmeAS@N?(olHy`uVBq!ia0vp^7C<b+!3HEvcGuVeDb50q$YKTtZeb8+WSBKa0w~B>
z9OUlAu<o49OCX0O-O<;Pfnj4m_n$;oApfzai(^Oy<J)U*Ihzdx*dBPFWaxXK(e$r?
zC%k~^W!$?<u1qgkqcs$FZuz*b<KAa&3Hyq(bJ-j;m$J<Kaln8_ZpPZzSw+QijK<BI
zCYv&@%=Y@en$sgz`25|5!0V-Ft8My{xepn5e>ThuejbsKvNrbDzI>-ni|29`FZec1
z3qKJs>E!c`>lD7-$}y8We(9mp`m-BaKU?_O^_Q|T^Ozl!Pu$QsD?Rq0@}>Jn%)jjs
zd3WFC%@@_GUkyjsXRQ0PV&5(0@Vb<E!7j$7O;4_{oxCV?RVa0t>aWGw-xeGx>s8tq
e8|)=}Sa{|CRMRvK<{qGT89ZJ6T-G@yGywn!qlN_l

literal 0
HcmV?d00001

diff --git a/apps/documenteditor/main/resources/img/toolbar/1x/big/btn-dropdown.png b/apps/documenteditor/main/resources/img/toolbar/1x/big/btn-dropdown.png
new file mode 100644
index 0000000000000000000000000000000000000000..0e66a01b14b0594d600927038541cbb14007c62c
GIT binary patch
literal 326
zcmeAS@N?(olHy`uVBq!ia0vp^7C<b+!3HEvcGuVeDb50q$YKTtZeb8+WSBKa0w~B>
z9OUlAu<o49OCX0O-O<;Pfnj4m_n$;oApf?fi(^Oy<J)T&IS(rcuszsp;ox>cqsh*~
zE$jr#!s?yg;(~8Hqc~Knrp~)`>GwR9i8JK=Z5R|=UU=-aD>$c`AmS9T^*bk{a_cH#
z3+8>Fb<Z`V-`~X`oP6esO!fQp7d)GN+CRq3THe@st!nc%znv~gJ?1qft^2mQpNN@s
z^y`f>f%CUkm2n>5d-&<*ZHMIa9`4v7cbhLwBB!y@;D*!L#M=k+OLsNj31@Bny=ujz
z>_^A{JeRb|(v4hYx_HYpovX7ZGTQ%r7?z@c)59yoYs$<i8OoVg-6U?U;#6$g#XRdv
Wti}1Kg>!-4WbkzLb6Mw<&;$S|)`9;3

literal 0
HcmV?d00001

diff --git a/apps/documenteditor/main/resources/img/toolbar/1x/big/btn-radio-button.png b/apps/documenteditor/main/resources/img/toolbar/1x/big/btn-radio-button.png
new file mode 100644
index 0000000000000000000000000000000000000000..7886bc624d392eb4ca917bf1074b0d8a9e4f01b4
GIT binary patch
literal 1004
zcmV<I0~7p-P)<h;3K|Lk000e1NJLTq001}u000~a1^@s6G`oC000009a7bBm000XU
z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP<VFdsH1A$3IK~#7F?O4lE
z<3JE?8Mu?d4jGsT5WgyJuo1Y30EoaQf?Xn55dm<c3aTteU}s<v0o?g`-$QMXWwkW2
zeBj_$)n$;TyQjOSKO>P9R`}5fd=`aaxVf>h(V0vpVGsmu{JKx(AV~0c(rUFL(BS_5
zK9MB=GB@$lp=wYY<n&dd6oCfRUnQ$m_L7Dj931pu+)#~*-rwKD$H&Kjg#Uko{_@$|
z+uN9Hr2%LdsE0p?k{T6p8-Ze~Pg29jy0#Q%1doo695&vEkP$Y28prXAlmO0fYiny=
zL^8zhZry0A1N)#6=oI$6c&zVAYV590G`~RO4i68<pfjlnM6pX=%JAjkW<iWdZGGVB
zDzEcq;s&`<SrB`Bd*_tFBkr?aH@L7q@SdxTYJJS3{r&xa(h!hy<Krae5vZ{~$hawT
z(o7EWSg}}uwvcm)GytQATpS{gx2^ouV>JeC)ykn_S&SZw({?t0XR0WxAr?lKadZHp
z(g!_*CXAAmYcvXqZrNVMMhJ>5<1{x}=$<DjZme8Wqi!W_FH&eAm^<8*7{(#8L*3N$
zte^0iWhCSc*gM5WM>kc(>m-dxnAOK;B?V=m>%TB#AdGXMry@=m@+YGxi%q;M%ppW?
zgw3?Yh66nr?@WClD`(kaX7uGF=pG&(Mh5eV*eEoDy^u~T;iE&BrcaN$%RVceWO68L
zyk6~~CYGWve?$}XuwTYn%hN<*9-$X<ZcR$~ILj_gpQb~SeU?9>BaB*w;pey}#a?~E
zyNe>8kB<*mQU2$0CIeF+=)&M}Qf44F6HBfNO~KXyL$>AHdsGzjnblU{tYfwvu@PJP
z)G>4VB<*vFA@5ky0sUJ}_8*_-><gcv!D`Nnz#1B6BB;$dT3=spJUYQi9GiM&6OkGf
ziCy;V;8S1aM8qg!7Ui&gE(=2E*|E=By#sPkURa;bvxWNR+61Er@9*;Jvd9INj^RW^
z89wVZid=i<bAio69n(=6^YSf5y}<TSC}R9xR$X8jc^+++Y8qE}SkGK|W6)*QQPce8
z(PkAkFT9oCWc13zvmK%A-@)KyI_;<v+IY7EI$^~`QMqbTp!CYqlQcK)K*@C4Q76!#
z9Z4r0uDL2JP`)3X96v>XIE=g8N2d|n%j@gwb<@f_g~|^lJ$g=NKRVIa7<ApV@~*JL
a55Rxi>nmtX4g%)@0000<MNUMnLSTYD6VT@X

literal 0
HcmV?d00001

diff --git a/apps/documenteditor/main/resources/img/toolbar/1x/big/btn-text-field.png b/apps/documenteditor/main/resources/img/toolbar/1x/big/btn-text-field.png
new file mode 100644
index 0000000000000000000000000000000000000000..ea4a208e35e71e7b64a225eb725f9a995ee8ce3f
GIT binary patch
literal 246
zcmeAS@N?(olHy`uVBq!ia0vp^7C<b+!3HEvcGuVeDb50q$YKTtZeb8+WSBKa0w~B>
z9OUlAu<o49OCX0O-O<;Pfnj4m_n$;oAivww#WAFU@$Gd-z6J#zmIFyOQs<xLbG7@f
z`lh1CxuZCUPlekz>Wqualf5ndb3P}!ES>V?fB&hDpwh?$ww`ZkY+tJLx9zZv`l4Q^
zugg~dsQ=O{k$VbGy&TsSu3UdO>#27LWBT%j&A|t5wlZFPar3k0f{Vt-wiis2y!xQ=
p;)93rn_sM$#PV&jr;AI~-0Du_O`B)Wt^hiV!PC{xWt~$(69BqXT*CkW

literal 0
HcmV?d00001

diff --git a/apps/documenteditor/main/resources/img/toolbar/1x/btn-field.png b/apps/documenteditor/main/resources/img/toolbar/1x/btn-field.png
new file mode 100644
index 0000000000000000000000000000000000000000..a94a87e5494afd97640db1bfbc4da3367a506269
GIT binary patch
literal 226
zcmeAS@N?(olHy`uVBq!ia0vp^8bB<<!3HG%yVdUoQk(@Ik;M!Q+`=Ht$S`Y;1W=H%
zILO_JVcj{Imp~3nx}&cn1H;CC?mvmFKz_NWi(^Oy<J&9NTnvf=%ohT`Wysy$y)#en
z!{&||nmV7fM2{E<oOMajOqdv?<#xidy)0f!xn-4g0@J^{sZ86-=U+{J9CG9MvXwa<
zj~SgRTQ;j*@!a9R<+P?kHdn`_4fpvLs4QPQFX~MwpM@@a3FF>nY;V$am89dEVvLss
TL?&DZI)TB{)z4*}Q$iB}29Qet

literal 0
HcmV?d00001

diff --git a/apps/documenteditor/main/resources/img/toolbar/1x/btn-lock.png b/apps/documenteditor/main/resources/img/toolbar/1x/btn-lock.png
new file mode 100644
index 0000000000000000000000000000000000000000..e29b72f4d76869c1ec317849f61d8865b2527903
GIT binary patch
literal 477
zcmV<30V4j1P)<h;3K|Lk000e1NJLTq001Ze000yS1^@s6|3-hi00009a7bBm000XU
z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP<VFdsH0dh%1K~#7F?N-}u
zgFq0x!zloFaHSv~5})qCbdaQiTn9-BqzxW&I>8+z|GYBm5Q%{A0sL5zM_S!+y9~p5
z_6%cpYy;ONgCIC?&L1)LhNTb3andZy-q{NDeSg64hYykB8A?7!l?cO7VtB>PvT2%q
zQ52l!ZQDxZp4f76lK2ob?ul%eOXL>wu_%fv&-27|oz@`mlPv^9R0wfpT_6_o(GK=&
zaw<SXzb2>riEjn7Ch>hgK_ie?T<wjVpS!M;Wm#$)2Ah+xAMa`TfHOks8s-9(_olG*
zqRM+$>g>EY^%w0Z2_fM)c8<DQ#e@6FbwWZ0;YVF9!RW!=Zuf%0r8mU(zp?GO@F4`k
z$Y&G?VeV-D#kOPYMI)b4Aa?C}bSc?(EaEc?%=0|`otrw=26*9gG&l0y{5d!Sb!;5R
z!c<2!=<3Q;H*~D9sH0<M#`iE?AkWoxeS%QIG{6T08QkVio;-K55NXSI$N$1Ng#Wu&
ThO6(!00000NkvXXu0mjf)q&C_

literal 0
HcmV?d00001

diff --git a/apps/documenteditor/main/resources/img/toolbar/2x/big/btn-checkbox.png b/apps/documenteditor/main/resources/img/toolbar/2x/big/btn-checkbox.png
new file mode 100644
index 0000000000000000000000000000000000000000..0701af7071d56d3a8ce52cadfdb8bc12d6eca905
GIT binary patch
literal 576
zcmeAS@N?(olHy`uVBq!ia0vp^1wd@U!3HE%U)Oj6Db50q$YKTtF;x&|^bAt@02E{_
z4sv&5Sa(k5C6L3C?&#~tz_78O`%fY(Q0}Uyi(^Oy<J&uLJDVK@j(t2?*m|Su0sHBl
zemSbF92-Tr1NY3F)6{XS_VV4E)&CT@JQbcTKNjoMA>hQJ*a9T}E|*L9U$H7{QA_si
zZzb|}riD`q_}^WA9N!Z1J@=Q(eP!E{h3k3J-GAMk87Eo5rp4cIih02&h7~ppaOR#T
zjIVd;Rb2SzJoDJ&uTA35|9VRWd^lEE^D%9*@}dVHU+t}5*KsU3vwZu5v+fz^Z~LEG
zAv$kOb=;h9`X`MG*w??=wQjl3t%KT?THDmyCo!|ki}hq=I=?T4q49Z`P{V;@eJh0z
zf4aChZ2s?IOl{B=NSP^SBbjhsVB31_7fCiJxeMmWX0jY&3lx@HFBKPO)=~b@Gp^yV
zfeov}y$za+Hl1E}rtixa_QaM7^?6TNHRSg&%uveueQvh>k4Zd&?~hI1v!B^laO=Gd
zGn9@UnA~)yb)I6@{@XUrJ+11j(rz+}&x}GWoO(LdS!LPZDLykfciVYMM@7(w#y?_)
z;(M0L9%)i~=sEq&ksN`|vlDMB?AxCFz;n9qQr(W74|UfHEC$N`TcYH?qtx)>v=5t|
zo-zhhGK9!6Ol5a?DtW(k*}r_zeZHOlqmKq!FbhIsMA7vx)6zK;Y{mC>fg+s2)78&q
Iol`;+0Bk<>A^-pY

literal 0
HcmV?d00001

diff --git a/apps/documenteditor/main/resources/img/toolbar/2x/big/btn-combo-box.png b/apps/documenteditor/main/resources/img/toolbar/2x/big/btn-combo-box.png
new file mode 100644
index 0000000000000000000000000000000000000000..ca0e29b04eb72f279b5460d939e2838d3adce264
GIT binary patch
literal 525
zcmeAS@N?(olHy`uVBq!ia0vp^1wd@U!3HE%U)Oj6Db50q$YKTtF;x&|^bAt@02E{_
z4sv&5Sa(k5C6L3C?&#~tz_78O`%fY(P;QZ@i(^Oy<J((-U55-rS|3`RaoRPtiT|Bj
z`6HcFF@+aFy9AEzyzV(8NM=^ZTFa;Z7nm$-YPo!S$u>oxVL*@|w|b-gn(ME#1qv)=
z+>RHWzska>UA+Fkvcs+PcjC+EJ=__zbo#$@o7V~apZoCqB(1$)%8#uR2w7mkBobcQ
zP*!;-*KD?0?YC{;TU$4*etd4*vhO=T?h8<;=9?4ElU2VnW}8^d>)LB}x6V0#+4)JE
zqucRq?(L}Ey?3{N{JAAPIQ80(RcjA?{`n`D`Q@KAUmnzSr)NAr-ef25oE|M)*KB>P
zOuRpJrP+bYFRw&q<Z>CdKCi9Q>DbKmI_LS+=fBndv|c}!9Jy*9GrOXm+MX1FM{8q+
z=B=(1o#hl0RpF_B<k5$it=%*Bsj^)+SKZO_+o6y}qi?yOP45BgllHw8)1v0P^(<sM
zDhTq7d&47+fIEllmrlK>zAt;KW$4S=N2|j(JBKXT(XJh^c9GZF*ubSLz$P#p-N+?-
zP)kJrs8$Kf>VQ2Wj9to5iPZH@q4)e|dp&)-MNvxt9Kee9YFlrAik#`R4#f3z^>bP0
Hl+XkKVSwX$

literal 0
HcmV?d00001

diff --git a/apps/documenteditor/main/resources/img/toolbar/2x/big/btn-dropdown.png b/apps/documenteditor/main/resources/img/toolbar/2x/big/btn-dropdown.png
new file mode 100644
index 0000000000000000000000000000000000000000..e50cb92cba2c5dcf30398c164a6cb44ca875cae8
GIT binary patch
literal 512
zcmeAS@N?(olHy`uVBq!ia0vp^1wd@U!3HE%U)Oj6Db50q$YKTtF;x&|^bAt@02E{_
z4sv&5Sa(k5C6L3C?&#~tz_78O`%fY(P;RQHi(^Oy<J((zbDIrB+7g$)QdrY8g?pQ)
znWy_p29HD$ekQN;p1Gomrhg<l_^aeOAKuux(e97<BN?D!K=7?l>i40aHFZ0Bu9n)~
zY7dt?l=?;`Zfm{8jBl1-yI1=Ex^-=y<gs~Q_WI71lxRFAxS%kSP2=+8t*cfk)m__k
zZD;d@n;*5pFaD0nm>Zq&NovP*fh%iY@9Jg=&zd{sebHrsQr&+=ZLJIPiei_<w7p9I
zUvhKu(u%PEo1`0aZ`XOd@3EUIH7D*N=hs`$-dwh;*va)>`i||C+Kkz%yBTIL`zRD8
z>D==$bM7|F$0;q9J71o-T>bFhA#LZ|I+5!dn+5oV<4ia{M#c%vJ5?qw<!lpG5vYIU
z=);w7%nWPYdDiKx?&v69P{@*T=ZU7t_w7O}i|VyM%DXKn+|$cZA>FuL!QnB-1q&vV
zK89ZJf10_kKR?`EzCU_Ce{lK!9*4)1+!OMiAKv=3%uXhWMasPa<o7pD?i;v|F1yj%
xmmuEd3lw0<kYNPLeO$k#p?)bNC`231{$+?gaK8E2wgvqlzNf37%Q~loCIC9D+WY_j

literal 0
HcmV?d00001

diff --git a/apps/documenteditor/main/resources/img/toolbar/2x/big/btn-radio-button.png b/apps/documenteditor/main/resources/img/toolbar/2x/big/btn-radio-button.png
new file mode 100644
index 0000000000000000000000000000000000000000..7a7bfbf96104a2a31dd77a0ba630b9e9c92af06d
GIT binary patch
literal 2146
zcmV-o2%YzdP)<h;3K|Lk000e1NJLTq003|R001}$1^@s6CF^`j00009a7bBm000&x
z000&x0ZCFM@Bjb+0drDELIAGL9O(c600d`2O+f$vv5yP<VFdsH2lq)tK~#7F?OaQ8
z+c*$?bewEQbAn+`F!l+;d|Z`XoD+<4g0W6u>I8O9FwP0=*`@L`b%H1-2<HS*cB%Y4
z{fLIdI1<GMsZXl-su0i$LE@p&jRw#l(4j+z4jnpl=+L3Vx)EUoNRp&?<Hn67ilRI6
zXDs>N)zwu`u6ugRL{hH#SpIMH?c29ZFu^YX<&sD$_(|G><2IL{q>-dd+M#uRtqSnL
zg9nLZ$Cwea;zAnd+3VM@FR+D>x+Q4HPtr3HWNZ9d5#as%_YZe=c20y~T>3eK>wVex
z@88FgK6(wKhTgn+GnV`RfNP9IldDt|<&x4DFJ3&u7C`EGDA@^|ws~Ywewu&u8m1b`
zd*||l)6P`xZ_KZe03SYl7=Qix^&iYCM*^qv+f%DK6rsk_321hYCB;SMqG&9p`0?}S
z&vR@5+97}9C+Vrx9O|<YI1P^VXA1r?J1hbbEI=`rM_L*7wh1-n<;#~((E{$>yVoxX
zk_|O{_3G6r)(C0vANav(Oe_54*?r6eS@4r*2k{FMpa?J33J}z|VcQM}HBz*XLhS2L
z6k>`sKpHqji62}8x5`g7lJDs2Pkcv;RfEElbj5UVaPT))4AI6T|32+FD+PsjHN(pJ
zQPWHBOJRgb1527mlX)m6bA&ZOItr&DmvH86Wtv#hJZjsaa9j&Nc`qHEDL;!Q))t_S
zc_&4oDB2g{jj=}P6y;L?9JD<q>X>(;f9}(P!WyAdlqtWuV`41<s<-)8E_?FeqqdwC
zD`-wRU6ISl?(Xh>Ti&UTM+HAgM{PMP0rl{mh!$YKj(56)8W7=~OV*PYoNY>Y#G5y7
z*ejWOI(=yi1wTn=n-U(OT37Ico4zc?QUS{N)0d26P%g_|Lu?rIc;R|z!UY60gu3(`
zgK|k5=Lc7Zf}buRRHBXsdUraNsX~qogVPmR)hQZU&1q9i`8AnPw*{T9_>Q!cU*#Cc
z9xe|&r}oME<ZWyb#HslJXKL<>Lz5u@+QVr+xpcQx{G@JEep0t=(S5sB50Qd@>1B#Q
zsQ37Y(~i<w=~$P^h7BB%Q>_;@C_@+;^HcBfktBA8SbrXC8aB}CTKpDjAQzm)(_=5-
zxO3ZTK6OipW~p*AEN1ZZ^XJdQfVER!zlqk*x;Dw){Xze{ZEa{RpGsOb*$-ODDb;VH
z^_yFM;TXvMJiW|9geQ%AxlDM3jAuu@mt|mp3M`Yvcin*<iGNg}@Hl6yvr@yU!KId|
z4HZ}hXGRzD+o^bfFO<OuY95?tR~LJ?ZrwVD9e%Q%z>Z*kaGGc0hncfv!BT!ZOI})j
zNG)*EUq|z<gPN%0Wo>XLUoT_W5yVf&@sKsrBONa-Sjw+TfQ8D7F#dx9GFJ@gX&#R(
zH_N7Q(fGQSXoWXvCVmLhBo7lm%sSUXepLdD`OlXxUvd}_*qFYoX=48A)2Cu!mriCH
zUlg(CIcx~#2j{6;;2oER{FZ89z&>9vLBA7U7p1y|2+&)Ywef?|)R*cOB)|^80ICEy
z4M2hc4VR-#4n?VMRxO&AvAXxLo7^(24%1S8Rnv%~kW93HgYBgk2!xb15oBbWUgogF
zH;RcLTxeh@O#Dz|oL(qE-<TpmtIhuxfw1m&$kZd&%McA*>ftRwFhAILJ7Uf48i<+H
z6BwWi%crp8)Vks$R^m^+wDxQw*F1p%y09F?FJO3C%CAZT{Up-tb?Kg+rBTOP#)?Gq
z40Z(bgVQ7vKZNZyCYoo9ZdfQlo>hQuEQYL8ia_q7UQcCM;$7=>g)2T#f>J&t_$b3{
z<1}QQvNk`sEg|b-c8r+-7xG&uKyA>Xm&szWdFhDd#hebfQ@~IRlzOb15}K5R_k_fh
zN(W2y@*<?XHmI+YnIFqb8ptL05zp|WM&@vWW2E^Y3X3UCG{2}SU%8=MiUgxDe#aK!
z;NalB_R>SCTaaT>iUgxDwu+zB?LC|m!%g*t{3<8%bV#@xFPA+HE8Ge&PKUx{-9m*&
zs6&#&1#E2%KaJCg;UWbp`PEs88EAfN9Sc_h9s8znENG4?zko@7>nMfX6X~-1mkLnN
z>SdC8fqQnXg1a3`ax8Ugemu*a)yv@48#m4mvqLZAI>*oI#)UqSY@&O18#6V0x0)Av
zxsTBv3Vv{Vb{pfT@9t||YVoTjKu)lID4*cOy7Afucs>HN(Ee6K9MvnH@(b8_Z4BLp
z^I?RwLmX@GMrc%Ys(+qqgRTYaFnYL!NLLXZu2Ipc{(0VHU(<?f=ORq!5KY@j;_<PU
zrf^={+jW>zeTP4}lWHAS0%^D@KS^)bVNUfOQ+`^9+K3PUX;cohY4Lz4I%^o;ITv%n
z5?3m`GNe(b{NN_(!>Hw`?KxqIX5kS*0wnaLP;msg?T-?y^7wXLTsvZ&qot1$%z5?%
z4UTUI3y|P3Xjx`sXnHYTctMI_M^=s0SW*&WkM#4gj2`f&&SdCxWy%jKNJ*o>Skj;P
zNqVx8j~tY7?V|)98Ix4}od`5%a8&s-Ba+cX?rHof8z}Jwb@gYkE#Hf|_E7?lOw&6!
z!RFUKGr~k(Kk?K12T=>(i)lrG9%A|!HrIze`idwPm(^T`>@KVvBACYf;LK%f{8|;D
zhnhq7yacna8pSAmii*8ecl~oXQ#ty@KDAZJ4>N(~aGE*_+?D9ip+kob9XfRA&|%B)
YKY*t6d_r6eCIA2c07*qoM6N<$f{$tc*#H0l

literal 0
HcmV?d00001

diff --git a/apps/documenteditor/main/resources/img/toolbar/2x/big/btn-text-field.png b/apps/documenteditor/main/resources/img/toolbar/2x/big/btn-text-field.png
new file mode 100644
index 0000000000000000000000000000000000000000..ac66fd2e339fd7f1edad3469bb5dfb5803109519
GIT binary patch
literal 321
zcmeAS@N?(olHy`uVBq!ia0vp^1wd@U!3HE%U)Oj6Db50q$YKTtF;x&|^bAt@02E{_
z4sv&5Sa(k5C6L3C?&#~tz_78O`%fY(kblk7#WAFU@$GF#u4V@TmIJ0wGVN~fm(*u=
zys^SES3h*SOMb5Pp^R*xQU-?4(dX*dyxz4v;r2G&{eAD-#d0ib{@0l<+FQ-OZrziM
zHhYWbtbcOx>pK}K3BQJiEE4Z(zaP2R<2ie(?OsXaUu&)$DA+C?;k#Px+@(E1Kx&!I
z(yRmv#x`LB#E$*upEkc`Jum%p%H9QRZPj}w&JVp+y~vgMFsH#BhQp=l3BSU<!Y}O)
f(vso;IrG2=y8w0zpHsf)vp`%=S3j3^P6<r_d?j@Z

literal 0
HcmV?d00001

diff --git a/apps/documenteditor/main/resources/img/toolbar/2x/btn-field.png b/apps/documenteditor/main/resources/img/toolbar/2x/btn-field.png
new file mode 100644
index 0000000000000000000000000000000000000000..54cfa8845f40a2ffcb0b39d05c120ee167c1c087
GIT binary patch
literal 279
zcmeAS@N?(olHy`uVBq!ia0vp^0YI$5!3HEV6KWZO6lZ})WHAGSm?{V}dIqU{017e|
z2e~^jtUD+363Agmcl32+VA$Bt{U?zX$Y0~>;uuoF`1Xb)SBn9U+ryF%8MbBbpY7n}
zY4w>Jf0^t3?abKL_ARE&K(!4yOX~x(@8&ML7WH%cKKYzQML%l)NvK3`G0=LL7k>J^
zcSTf)9c$ONi|m1tH(T8n8ExWP>Tq#`gZ^3Xn58z)msWP({O`skV(1{qj6}rRb*|Ya
z|HfbG=5I$Xk-0#g*6$}57dr$-Ja{wv<;0ujm;0DNetS^5FM7X)NoeHhS3n+vr>mdK
II;Vst0PuWcA^-pY

literal 0
HcmV?d00001

diff --git a/apps/documenteditor/main/resources/img/toolbar/2x/btn-lock.png b/apps/documenteditor/main/resources/img/toolbar/2x/btn-lock.png
new file mode 100644
index 0000000000000000000000000000000000000000..656f7406e958609b6d1fd75cac23d80072f71913
GIT binary patch
literal 909
zcmV;819JR{P)<h;3K|Lk000e1NJLTq002+`001Zm1^@s6X<&T;00009a7bBm000&x
z000&x0ZCFM@Bjb+0drDELIAGL9O(c600d`2O+f$vv5yP<VFdsH10qR8K~#7F?U~Jy
z+CUJ6Tm0N{25bf>1Mzd<NCw~t3=vov;EljIg5^j7MJWRl0vVV)6!^6?+ETf+Gm@qS
zuG;ykW;K!q>FrZ9>K=$34u|9O;*kYG5Omt@_Vj+g2cGBku<gbd^}G}M$3~;E-fp+Q
z=t)3B2b(ENMeCt;)u|KO5p4~vR{AO%I2a6OFldQxM|%U9i55QENSHUn#;A`HGsCJz
zHmCxl(I|v@KPeFxp+CFbZr%NU?{Nb@_P^rXk)sm*6@P{v1nwDP^R5qVhSv2I==*4~
zK1!l;r9M-d(h)cu4kys?7Ju0D=DXeQRW}}yI#-d(^kHyBH3B0h*u1ITIW)c+#?L8<
zRHl#d5tX2H1mXtYR5vu4#~coaA3Rp=ey93**Jm=1!5AxjRldRj|G8eTMsX>bu|2Av
zKy3@_%Zx3puhJaIL{W6EFxE7oi-E{0tS>XRw7$v)Iue|LmN)|~DU`;H$Kx(u1e{m#
zBr7qGty`_uVzb$tNB~s<iRwdJa1me{Xf#ln_nYKj0B4x!+nT7%t3@B0Z!)n(24G%X
z4&g$p%jL2t^Y+aH^>Y`-h3HOIRQJh_v|L+J5;a!()B_1AsiBSfj1h<u?9N;KvoA33
zL;~<41Wf#c?irQI7qS5V@LhFZihSh?UXve4tPj`J>N7@Qiq5>8IZ`{vaTMdh5D9+m
zbmryEk=i+qqgXu`qdx1maAuASGB=#?F+N96CNoC{l+nk>(&aZBtPM=($edFh6_wBC
zLw%G)r4<r+;6!uo5w)+0TJ=d7sC(-@toGGVt3C+>kD7C9dOo%4lb8c}WjF6BpK)$M
z&*wvZXx93y4dnC&M*069=VMZNqYWxm@pDf35_zM@VnUu#|ATocc}7Vk-EK9;5@(<#
z&Ol3w)WZC>>hJ=9ZY73)52k{s@{fdw_3;9LZY4(j9$bhrC0>yTjPs~wv$>S0ZTUgK
zyin~*<cVpXx0I-D)k;jLc8&UsPerZY)v{nIk?K5qLDd+6nLJObs$gM}RGyg0^F;NL
jP@d>;I2;a#qb~jeqCI9il-UU&00000NkvXXu0mjftoNN5

literal 0
HcmV?d00001


From fa3b68e21216a58b733ac9d1c79a8330399edb3f Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Wed, 7 Oct 2020 16:22:31 +0300
Subject: [PATCH 16/33] [DE] Remove adding forms from insert tab

---
 .../main/app/controller/Toolbar.js            |  6 ++--
 apps/documenteditor/main/app/view/Toolbar.js  | 35 ++-----------------
 2 files changed, 5 insertions(+), 36 deletions(-)

diff --git a/apps/documenteditor/main/app/controller/Toolbar.js b/apps/documenteditor/main/app/controller/Toolbar.js
index 08e49c9a8..336edee30 100644
--- a/apps/documenteditor/main/app/controller/Toolbar.js
+++ b/apps/documenteditor/main/app/controller/Toolbar.js
@@ -786,10 +786,10 @@ define([
             toolbar.btnContentControls.setDisabled(paragraph_locked || header_locked);
             if (!(paragraph_locked || header_locked)) {
                 var control_disable = control_plain || content_locked;
-                for (var i=0; i<14; i++)
+                for (var i=0; i<7; i++)
                     toolbar.btnContentControls.menu.items[i].setDisabled(control_disable);
-                toolbar.btnContentControls.menu.items[15].setDisabled(!in_control || lock_type==Asc.c_oAscSdtLockType.SdtContentLocked || lock_type==Asc.c_oAscSdtLockType.SdtLocked);
-                toolbar.btnContentControls.menu.items[17].setDisabled(!in_control);
+                toolbar.btnContentControls.menu.items[8].setDisabled(!in_control || lock_type==Asc.c_oAscSdtLockType.SdtContentLocked || lock_type==Asc.c_oAscSdtLockType.SdtLocked);
+                toolbar.btnContentControls.menu.items[10].setDisabled(!in_control);
             }
 
             var need_text_disable = paragraph_locked || header_locked || in_chart || rich_edit_lock || plain_edit_lock;
diff --git a/apps/documenteditor/main/app/view/Toolbar.js b/apps/documenteditor/main/app/view/Toolbar.js
index 029d2ac39..a24a21045 100644
--- a/apps/documenteditor/main/app/view/Toolbar.js
+++ b/apps/documenteditor/main/app/view/Toolbar.js
@@ -645,31 +645,6 @@ define([
                                     value: 'checkbox'
                                 },
                                 {caption: '--'},
-                                {
-                                    caption: this.textNewFieldControl,
-                                    value: 'new-field'
-                                },
-                                {
-                                    caption: this.textNewPictureControl,
-                                    value: 'new-picture'
-                                },
-                                {
-                                    caption: this.textNewComboboxControl,
-                                    value: 'new-combobox'
-                                },
-                                {
-                                    caption: this.textNewDropdownControl,
-                                    value: 'new-dropdown'
-                                },
-                                {
-                                    caption: this.textNewCheckboxControl,
-                                    value: 'new-checkbox'
-                                },
-                                {
-                                    caption: this.textNewRadioboxControl,
-                                    value: 'new-radiobox'
-                                },
-                                {caption: '--'},
                                 {
                                     caption: this.textRemoveControl,
                                     iconCls: 'menu__icon cc-remove',
@@ -1991,7 +1966,7 @@ define([
 
                 this.btnMailRecepients.setVisible(mode.canCoAuthoring == true && mode.canUseMailMerge);
                 this.listStylesAdditionalMenuItem.setVisible(mode.canEditStyles);
-                this.btnContentControls.menu.items[17].setVisible(mode.canEditContentControl);
+                this.btnContentControls.menu.items[10].setVisible(mode.canEditContentControl);
                 this.mnuInsertImage.items[2].setVisible(this.mode.canRequestInsertImage || this.mode.fileChoiceUrl && this.mode.fileChoiceUrl.indexOf("{documentType}")>-1);
             },
 
@@ -2356,13 +2331,7 @@ define([
             mniEraseTable: 'Erase Table',
             textListSettings: 'List Settings',
             capBtnDateTime: 'Date & Time',
-            tipDateTime: 'Insert current date and time',
-            textNewFieldControl: 'New text field',
-            textNewPictureControl: 'New picture',
-            textNewComboboxControl: 'New combo box',
-            textNewCheckboxControl: 'New check box',
-            textNewRadioboxControl: 'New radio box',
-            textNewDropdownControl: 'New drop-down list'
+            tipDateTime: 'Insert current date and time'
         }
     })(), DE.Views.Toolbar || {}));
 });

From 31b4d48f45c4fcf6abdd40914cabe1c67cd5551b Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Wed, 7 Oct 2020 16:22:59 +0300
Subject: [PATCH 17/33] [DE] Fix forms highlight color

---
 apps/documenteditor/main/app/controller/FormsTab.js | 7 +++++--
 apps/documenteditor/main/app/view/FormsTab.js       | 3 +++
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/apps/documenteditor/main/app/controller/FormsTab.js b/apps/documenteditor/main/app/controller/FormsTab.js
index c5988717a..9de955849 100644
--- a/apps/documenteditor/main/app/controller/FormsTab.js
+++ b/apps/documenteditor/main/app/controller/FormsTab.js
@@ -175,17 +175,20 @@ define([
         },
 
         onChangeSdtGlobalSettings: function() {
-            var show = this.api.asc_GetGlobalContentControlShowHighlight();
             if (this.view && this.view.mnuFormsColorPicker) {
+                var show = this.api.asc_GetGlobalContentControlShowHighlight(),
+                    clr;
                 this.view.mnuNoFormsColor.setChecked(!show, true);
                 this.view.mnuFormsColorPicker.clearSelection();
                 if (show){
-                    var clr = this.api.asc_GetGlobalContentControlHighlightColor();
+                    clr = this.api.asc_GetGlobalContentControlHighlightColor();
                     if (clr) {
                         clr = Common.Utils.ThemeColor.getHexColor(clr.get_r(), clr.get_g(), clr.get_b());
                         this.view.mnuFormsColorPicker.selectByRGB(clr, true);
                     }
                 }
+                this.view.btnHighlight.currentColor = clr;
+                $('.btn-color-value-line', this.view.btnHighlight.cmpEl).css('background-color', clr ? '#' + clr : 'transparent');
             }
         },
 
diff --git a/apps/documenteditor/main/app/view/FormsTab.js b/apps/documenteditor/main/app/view/FormsTab.js
index fabea0b9f..9d00c1380 100644
--- a/apps/documenteditor/main/app/view/FormsTab.js
+++ b/apps/documenteditor/main/app/view/FormsTab.js
@@ -214,6 +214,9 @@ define([
                         me.mnuFormsColorPicker = new Common.UI.ThemeColorPalette({
                             el: $('#id-toolbar-menu-form-color')
                         });
+                        var colorVal = $('<div class="btn-color-value-line"></div>');
+                        $('button:first-child', me.btnHighlight.cmpEl).append(colorVal);
+                        colorVal.css('background-color', me.btnHighlight.currentColor || 'transparent');
                     } else {
                         me.btnHighlight.cmpEl.parents('.group').hide().prev('.separator').hide();
                     }

From d5875737ba99be7e42887f183ed336641cbaf0f6 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Wed, 7 Oct 2020 19:13:24 +0300
Subject: [PATCH 18/33] [DE] Fix context menu for forms

---
 .../main/app/controller/Toolbar.js            |  7 +--
 .../main/app/view/DocumentHolder.js           | 50 +++++++++++++++----
 .../main/app/view/FormSettings.js             |  8 +--
 3 files changed, 48 insertions(+), 17 deletions(-)

diff --git a/apps/documenteditor/main/app/controller/Toolbar.js b/apps/documenteditor/main/app/controller/Toolbar.js
index 336edee30..dba578ebd 100644
--- a/apps/documenteditor/main/app/controller/Toolbar.js
+++ b/apps/documenteditor/main/app/controller/Toolbar.js
@@ -785,11 +785,12 @@ define([
 
             toolbar.btnContentControls.setDisabled(paragraph_locked || header_locked);
             if (!(paragraph_locked || header_locked)) {
-                var control_disable = control_plain || content_locked;
+                var control_disable = control_plain || content_locked,
+                    if_form = control_props && control_props.get_FormPr();
                 for (var i=0; i<7; i++)
                     toolbar.btnContentControls.menu.items[i].setDisabled(control_disable);
-                toolbar.btnContentControls.menu.items[8].setDisabled(!in_control || lock_type==Asc.c_oAscSdtLockType.SdtContentLocked || lock_type==Asc.c_oAscSdtLockType.SdtLocked);
-                toolbar.btnContentControls.menu.items[10].setDisabled(!in_control);
+                toolbar.btnContentControls.menu.items[8].setDisabled(!in_control || lock_type==Asc.c_oAscSdtLockType.SdtContentLocked || lock_type==Asc.c_oAscSdtLockType.SdtLocked || if_form);
+                toolbar.btnContentControls.menu.items[10].setDisabled(!in_control || if_form);
             }
 
             var need_text_disable = paragraph_locked || header_locked || in_chart || rich_edit_lock || plain_edit_lock;
diff --git a/apps/documenteditor/main/app/view/DocumentHolder.js b/apps/documenteditor/main/app/view/DocumentHolder.js
index c986e8257..c32c50b79 100644
--- a/apps/documenteditor/main/app/view/DocumentHolder.js
+++ b/apps/documenteditor/main/app/view/DocumentHolder.js
@@ -2786,13 +2786,14 @@ define([
             });
 
             var menuTableRemoveControl = new Common.UI.MenuItem({
+                iconCls: 'menu__icon cc-remove',
                 caption: me.textRemove,
                 value: 'remove'
             }).on('click', _.bind(me.onControlsSelect, me));
 
             var menuTableControlSettings = new Common.UI.MenuItem({
-                    caption: me.textSettings,
-                    value: 'settings'
+                caption: me.textSettings,
+                value: 'settings'
             }).on('click', _.bind(me.onControlsSelect, me));
 
             var menuTableControl = new Common.UI.MenuItem({
@@ -3222,9 +3223,11 @@ define([
                     menuTableControl.setVisible(in_control);
                     if (in_control) {
                         var control_props = me.api.asc_GetContentControlProperties(),
-                            lock_type = (control_props) ? control_props.get_Lock() : Asc.c_oAscSdtLockType.Unlocked;
+                            lock_type = (control_props) ? control_props.get_Lock() : Asc.c_oAscSdtLockType.Unlocked,
+                            is_form = control_props && control_props.get_FormPr();
                         menuTableRemoveControl.setDisabled(lock_type==Asc.c_oAscSdtLockType.SdtContentLocked || lock_type==Asc.c_oAscSdtLockType.SdtLocked);
-                        menuTableControlSettings.setVisible(me.mode.canEditContentControl);
+                        menuTableRemoveControl.setCaption(is_form ? me.getControlLabel(control_props) : me.textRemoveControl);
+                        menuTableControlSettings.setVisible(me.mode.canEditContentControl && !is_form);
 
                         var spectype = control_props ? control_props.get_SpecificType() : Asc.c_oAscContentControlSpecificType.None;
                         control_lock = control_lock || spectype==Asc.c_oAscContentControlSpecificType.CheckBox || spectype==Asc.c_oAscContentControlSpecificType.Picture ||
@@ -3669,6 +3672,7 @@ define([
             });
 
             var menuParaRemoveControl = new Common.UI.MenuItem({
+                iconCls: 'menu__icon cc-remove',
                 caption: me.textRemoveControl,
                 value: 'remove'
             }).on('click', _.bind(me.onControlsSelect, me));
@@ -3901,14 +3905,16 @@ define([
                                                             !value.paraProps.value.can_DeleteInlineContentControl() || !value.paraProps.value.can_EditInlineContentControl()) : false;
 
                     var in_toc = me.api.asc_GetTableOfContentsPr(true),
-                        in_control = !in_toc && me.api.asc_IsContentControl() ;
+                        in_control = !in_toc && me.api.asc_IsContentControl(),
+                        control_props = in_control ? me.api.asc_GetContentControlProperties() : null,
+                        is_form = control_props && control_props.get_FormPr();
                     menuParaRemoveControl.setVisible(in_control);
-                    menuParaControlSettings.setVisible(in_control && me.mode.canEditContentControl);
+                    menuParaControlSettings.setVisible(in_control && me.mode.canEditContentControl && !is_form);
                     menuParaControlSeparator.setVisible(in_control);
                     if (in_control) {
-                        var control_props = me.api.asc_GetContentControlProperties(),
-                            lock_type = (control_props) ? control_props.get_Lock() : Asc.c_oAscSdtLockType.Unlocked;
+                        var lock_type = (control_props) ? control_props.get_Lock() : Asc.c_oAscSdtLockType.Unlocked;
                         menuParaRemoveControl.setDisabled(lock_type==Asc.c_oAscSdtLockType.SdtContentLocked || lock_type==Asc.c_oAscSdtLockType.SdtLocked);
+                        menuParaRemoveControl.setCaption(is_form ? me.getControlLabel(control_props) : me.textRemoveControl);
 
                         var spectype = control_props ? control_props.get_SpecificType() : Asc.c_oAscContentControlSpecificType.None;
                         control_lock = control_lock || spectype==Asc.c_oAscContentControlSpecificType.CheckBox || spectype==Asc.c_oAscContentControlSpecificType.Picture ||
@@ -4320,6 +4326,23 @@ define([
             this._state.lock_doc = false;
         },
 
+        getControlLabel: function(props) {
+            var type = props ? props.get_SpecificType() : Asc.c_oAscContentControlSpecificType.None;
+            switch (type) {
+                case Asc.c_oAscContentControlSpecificType.CheckBox:
+                    var specProps = props.get_CheckBoxPr();
+                    return (typeof specProps.get_GroupKey() !== 'string') ? this.textRemCheckBox : this.textRemRadioBox;
+                case Asc.c_oAscContentControlSpecificType.ComboBox:
+                    return this.textRemComboBox;
+                case Asc.c_oAscContentControlSpecificType.DropDownList:
+                    return this.textRemDropdown;
+                case Asc.c_oAscContentControlSpecificType.Picture:
+                    return this.textRemPicture;
+                default:
+                    return this.textRemField;
+            }
+        },
+
         focus: function() {
             var me = this;
             _.defer(function(){  me.cmpEl.focus(); }, 50);
@@ -4546,7 +4569,14 @@ define([
         txtInsertCaption: 'Insert Caption',
         txtEmpty: '(Empty)',
         textFromStorage: 'From Storage',
-        advancedDropCapText: 'Drop Cap Settings'
+        advancedDropCapText: 'Drop Cap Settings',
+        textRemCheckBox: 'Remove Checkbox',
+        textRemRadioBox: 'Remove Radio Button',
+        textRemComboBox: 'Remove Combo Box',
+        textRemDropdown: 'Remove Dropdown',
+        textRemPicture: 'Remove Image',
+        textRemField: 'Remove Text Field'
 
-    }, DE.Views.DocumentHolder || {}));
+
+}, DE.Views.DocumentHolder || {}));
 });
\ No newline at end of file
diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index b840cf295..e2cfe59fd 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -227,7 +227,7 @@ define([
             this.btnListAdd = new Common.UI.Button({
                 parentEl: $markup.findById('#form-list-add'),
                 cls: 'btn-toolbar',
-                iconCls: 'toolbar__icon btn-add',
+                iconCls: 'toolbar__icon btn-zoomup',
                 hint: this.textTipAdd
             });
             this.btnListAdd.on('click', _.bind(this.onAddItem, this));
@@ -711,7 +711,7 @@ define([
             this.btnListDown.setDisabled(disabled || this._state.DisabledControls);
         },
 
-        textField: 'Text field',
+        textField: 'Text Field',
         textKey: 'Key',
         textPlaceholder: 'Placeholder',
         textTip: 'Tip',
@@ -721,9 +721,9 @@ define([
         textDelete: 'Delete',
         textLock: 'Lock',
         textUnlock: 'Unlock',
-        textRadiobox: 'Radio button',
+        textRadiobox: 'Radio Button',
         textCheckbox: 'Checkbox',
-        textCombobox: 'Combo box',
+        textCombobox: 'Combo Box',
         textDropDown: 'Dropdown',
         textImage: 'Image',
         textGroupKey: 'Group key',

From 0a9d8773cdf5a2ad4db3f9a50665827998a8a536 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Thu, 8 Oct 2020 11:11:34 +0300
Subject: [PATCH 19/33] [DE] Turn on/off fill form mode from Forms tab

---
 .../main/lib/controller/ReviewChanges.js      |  2 +-
 apps/common/main/lib/view/ReviewChanges.js    |  8 +++---
 .../main/app/controller/FormsTab.js           | 25 ++++++++++++++++++-
 .../main/app/controller/Toolbar.js            | 19 ++++++++++----
 .../main/app/template/Toolbar.template        |  2 +-
 5 files changed, 44 insertions(+), 12 deletions(-)

diff --git a/apps/common/main/lib/controller/ReviewChanges.js b/apps/common/main/lib/controller/ReviewChanges.js
index 3018058b3..13ef732cf 100644
--- a/apps/common/main/lib/controller/ReviewChanges.js
+++ b/apps/common/main/lib/controller/ReviewChanges.js
@@ -739,7 +739,7 @@ define([
             leftMenu.setPreviewMode(disable);
 
             if (this.view) {
-                this.view.$el.find('.no-group-mask').css('opacity', 1);
+                this.view.$el.find('.no-group-mask.review').css('opacity', 1);
 
                 this.view.btnsDocLang && this.view.btnsDocLang.forEach(function(button) {
                     if ( button ) {
diff --git a/apps/common/main/lib/view/ReviewChanges.js b/apps/common/main/lib/view/ReviewChanges.js
index 570356601..2116415f8 100644
--- a/apps/common/main/lib/view/ReviewChanges.js
+++ b/apps/common/main/lib/view/ReviewChanges.js
@@ -57,7 +57,7 @@ define([
     Common.Views.ReviewChanges = Common.UI.BaseView.extend(_.extend((function(){
         var template =
             '<section id="review-changes-panel" class="panel" data-tab="review">' +
-                '<div class="group no-group-mask">' +
+                '<div class="group no-group-mask review">' +
                     '<span id="slot-btn-sharing" class="btn-slot text x-huge"></span>' +
                     '<span id="slot-btn-coauthmode" class="btn-slot text x-huge"></span>' +
                 '</div>' +
@@ -70,7 +70,7 @@ define([
                 '<div class="group">' +
                     '<span id="btn-review-on" class="btn-slot text x-huge"></span>' +
                 '</div>' +
-                '<div class="group no-group-mask" style="padding-left: 0;">' +
+                '<div class="group no-group-mask review" style="padding-left: 0;">' +
                     '<span id="btn-review-view" class="btn-slot text x-huge"></span>' +
                 '</div>' +
                 '<div class="group move-changes" style="padding-left: 0;">' +
@@ -84,11 +84,11 @@ define([
                     '<span id="btn-compare" class="btn-slot text x-huge"></span>' +
                 '</div>' +
                 '<div class="separator long compare"></div>' +
-                '<div class="group no-group-mask">' +
+                '<div class="group no-group-mask review form-view">' +
                     '<span id="slot-btn-chat" class="btn-slot text x-huge"></span>' +
                 '</div>' +
                 '<div class="separator long chat"></div>' +
-                '<div class="group no-group-mask">' +
+                '<div class="group no-group-mask review form-view">' +
                     '<span id="slot-btn-history" class="btn-slot text x-huge"></span>' +
                 '</div>' +
             '</section>';
diff --git a/apps/documenteditor/main/app/controller/FormsTab.js b/apps/documenteditor/main/app/controller/FormsTab.js
index 9de955849..8d41dbd5f 100644
--- a/apps/documenteditor/main/app/controller/FormsTab.js
+++ b/apps/documenteditor/main/app/controller/FormsTab.js
@@ -220,7 +220,8 @@ define([
 
         onModeClick: function(state) {
             if (this.api) {
-
+                this.disableEditing(state);
+                this.api.asc_setRestriction(state ? Asc.c_oAscRestrictionType.OnlyForms : Asc.c_oAscRestrictionType.None);
             }
             Common.NotificationCenter.trigger('edit:complete', this.toolbar);
         },
@@ -250,6 +251,28 @@ define([
                 this.api.asc_SetGlobalContentControlShowHighlight(true, clr.get_r(), clr.get_g(), clr.get_b());
             }
             Common.NotificationCenter.trigger('edit:complete', this.toolbar);
+        },
+
+        disableEditing: function(disable) {
+            if (this._state.DisabledEditing != disable) {
+                this._state.DisabledEditing = disable;
+
+                var app = this.getApplication();
+                var rightMenuController = app.getController('RightMenu');
+                rightMenuController.getView('RightMenu').clearSelection();
+                rightMenuController.SetDisabled(disable);
+                app.getController('Toolbar').DisableToolbar(disable, false, false, true);
+                app.getController('Statusbar').getView('Statusbar').SetDisabled(disable);
+                app.getController('Common.Controllers.ReviewChanges').SetDisabled(disable);
+                app.getController('DocumentHolder').getView().SetDisabled(disable);
+                app.getController('Navigation') && app.getController('Navigation').SetDisabled(disable);
+                app.getController('LeftMenu').setPreviewMode(disable);
+                var comments = app.getController('Common.Controllers.Comments');
+                if (comments)
+                    comments.setPreviewMode(disable);
+                if (this.view)
+                    this.view.$el.find('.no-group-mask.form-view').css('opacity', 1);
+            }
         }
 
     }, DE.Controllers.FormsTab || {}));
diff --git a/apps/documenteditor/main/app/controller/Toolbar.js b/apps/documenteditor/main/app/controller/Toolbar.js
index dba578ebd..8fe5ab22f 100644
--- a/apps/documenteditor/main/app/controller/Toolbar.js
+++ b/apps/documenteditor/main/app/controller/Toolbar.js
@@ -2896,27 +2896,36 @@ define([
             this.DisableToolbar(true, true);
         },
 
-        DisableToolbar: function(disable, viewMode, reviewmode) {
+        DisableToolbar: function(disable, viewMode, reviewmode, fillformmode) {
             if (viewMode!==undefined) this.editMode = !viewMode;
             disable = disable || !this.editMode;
 
             var toolbar_mask = $('.toolbar-mask'),
                 group_mask = $('.toolbar-group-mask'),
-                mask = reviewmode ? group_mask : toolbar_mask;
+                mask = (reviewmode || fillformmode) ? group_mask : toolbar_mask;
             if (disable && mask.length>0 || !disable && mask.length==0) return;
 
             var toolbar = this.toolbar;
             if(disable) {
                 if (reviewmode) {
-                    mask = $("<div class='toolbar-group-mask'>").appendTo(toolbar.$el.find('.toolbar section.panel .group:not(.no-mask):not(.no-group-mask)'));
+                    mask = $("<div class='toolbar-group-mask'>").appendTo(toolbar.$el.find('.toolbar section.panel .group:not(.no-mask):not(.no-group-mask.review)'));
+                } else if (fillformmode) {
+                    mask = $("<div class='toolbar-group-mask'>").appendTo(toolbar.$el.find('.toolbar section.panel .group:not(.no-mask):not(.no-group-mask.form-view)'));
                 } else
                     mask = $("<div class='toolbar-mask'>").appendTo(toolbar.$el.find('.toolbar'));
             } else {
                 mask.remove();
             }
-            $('.no-group-mask').css('opacity', (reviewmode || !disable) ? 1 : 0.4);
+            $('.no-group-mask').each(function(index, item){
+                var $el = $(item);
+                if ($el.find('.toolbar-group-mask').length>0)
+                    $el.css('opacity', 0.4);
+                else {
+                    $el.css('opacity', reviewmode || fillformmode || !disable ? 1 : 0.4);
+                }
+            });
 
-            disable = disable || (reviewmode ? toolbar_mask.length>0 : group_mask.length>0);
+            disable = disable || ((reviewmode || fillformmode) ? toolbar_mask.length>0 : group_mask.length>0);
             toolbar.$el.find('.toolbar').toggleClass('masked', disable);
             if ( toolbar.synchTooltip )
                 toolbar.synchTooltip.hide();
diff --git a/apps/documenteditor/main/app/template/Toolbar.template b/apps/documenteditor/main/app/template/Toolbar.template
index ffc080110..1fff3ec2c 100644
--- a/apps/documenteditor/main/app/template/Toolbar.template
+++ b/apps/documenteditor/main/app/template/Toolbar.template
@@ -180,7 +180,7 @@
                     </div>
                 </div>
                 <div class="separator long"></div>
-                <div class="group">
+                <div class="group no-group-mask form-view">
                     <span class="btn-slot text x-huge" id="slot-btn-form-view"></span>
                 </div>
             </section>

From 51b1cedb4245e648f31bd037b45c1869bb16589a Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Thu, 8 Oct 2020 15:19:45 +0300
Subject: [PATCH 20/33] [DE] Enable chat button in preview modes

---
 apps/common/main/lib/view/ReviewChanges.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/apps/common/main/lib/view/ReviewChanges.js b/apps/common/main/lib/view/ReviewChanges.js
index 2116415f8..33cf281dd 100644
--- a/apps/common/main/lib/view/ReviewChanges.js
+++ b/apps/common/main/lib/view/ReviewChanges.js
@@ -647,7 +647,7 @@ define([
                         button.setDisabled(state);
                     }
                 }, this);
-                this.btnChat && this.btnChat.setDisabled(state);
+                // this.btnChat && this.btnChat.setDisabled(state);
 
                 this.btnCommentRemove && this.btnCommentRemove.setDisabled(state || !Common.Utils.InternalSettings.get(this.appPrefix + "settings-livecomment"));
             },

From e9f9aa1c16df6cccf0affec3a489d3385962a20d Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Mon, 12 Oct 2020 14:58:13 +0300
Subject: [PATCH 21/33] [DE] Show help tooltip for new forms

---
 .../documenteditor/main/app/view/DocumentHolder.js | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/apps/documenteditor/main/app/view/DocumentHolder.js b/apps/documenteditor/main/app/view/DocumentHolder.js
index c32c50b79..ce3cf6ba1 100644
--- a/apps/documenteditor/main/app/view/DocumentHolder.js
+++ b/apps/documenteditor/main/app/view/DocumentHolder.js
@@ -491,20 +491,24 @@ define([
                     var showPoint, ToolTip,
                         type = moveData.get_Type();
 
-                    if (type==1 || type==3) { // 1 - hyperlink, 3 - footnote
+                    if (type==Asc.c_oAscMouseMoveDataTypes.Hyperlink || type==Asc.c_oAscMouseMoveDataTypes.Footnote || type==Asc.c_oAscMouseMoveDataTypes.Form) { // 1 - hyperlink, 3 - footnote
                         if (isTooltipHiding) {
                             mouseMoveData = moveData;
                             return;
                         }
 
-                        if (type==1) {
+                        if (type==Asc.c_oAscMouseMoveDataTypes.Hyperlink) {
                             var hyperProps = moveData.get_Hyperlink();
                             if (!hyperProps) return;
                             ToolTip = (_.isEmpty(hyperProps.get_ToolTip())) ? hyperProps.get_Value() : hyperProps.get_ToolTip();
-                        } else {
+                        } else if (type == Asc.c_oAscMouseMoveDataTypes.Footnote) {
                             ToolTip = moveData.get_FootnoteText();
                             if (ToolTip.length>1000)
                                 ToolTip = ToolTip.substr(0, 1000) + '...';
+                        } else if (type==Asc.c_oAscMouseMoveDataTypes.Form) {
+                            ToolTip = moveData.get_FormHelpText();
+                            if (ToolTip.length>1000)
+                                ToolTip = ToolTip.substr(0, 1000) + '...';
                         }
 
                         var recalc = false;
@@ -513,7 +517,7 @@ define([
                         ToolTip = Common.Utils.String.htmlEncode(ToolTip);
 
                         if (screenTip.tipType !== type || screenTip.tipLength !== ToolTip.length || screenTip.strTip.indexOf(ToolTip)<0 ) {
-                            screenTip.toolTip.setTitle((type==1) ? (ToolTip + '<br><b>' + me.txtPressLink + '</b>') : ToolTip);
+                            screenTip.toolTip.setTitle((type==Asc.c_oAscMouseMoveDataTypes.Hyperlink) ? (ToolTip + '<br><b>' + me.txtPressLink + '</b>') : ToolTip);
                             screenTip.tipLength = ToolTip.length;
                             screenTip.strTip = ToolTip;
                             screenTip.tipType = type;
@@ -547,7 +551,7 @@ define([
                         screenTip.toolTip.getBSTip().$tip.css({top: showPoint[1] + 'px', left: showPoint[0] + 'px'});
                     }
                     /** coauthoring begin **/
-                    else if (moveData.get_Type()==2 && me.mode.isEdit) { // 2 - locked object
+                    else if (moveData.get_Type()==Asc.c_oAscMouseMoveDataTypes.LockedObject && me.mode.isEdit) { // 2 - locked object
                         var src;
                         if (me.usertipcount >= me.usertips.length) {
                             src = $(document.createElement("div"));

From 41c082ad44b8ff6a8f8b8b294bfb48ebbed4b905 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Tue, 13 Oct 2020 15:27:32 +0300
Subject: [PATCH 22/33] [DE] Add icons

---
 .../resources/img/toolbar/1x/btn-arrow-down.png   | Bin 0 -> 287 bytes
 .../resources/img/toolbar/1x/btn-arrow-up.png     | Bin 0 -> 268 bytes
 .../resources/img/toolbar/2x/btn-arrow-down.png   | Bin 0 -> 427 bytes
 .../resources/img/toolbar/2x/btn-arrow-up.png     | Bin 0 -> 414 bytes
 apps/documenteditor/main/app/view/FormSettings.js |   4 ++--
 5 files changed, 2 insertions(+), 2 deletions(-)
 create mode 100644 apps/common/main/resources/img/toolbar/1x/btn-arrow-down.png
 create mode 100644 apps/common/main/resources/img/toolbar/1x/btn-arrow-up.png
 create mode 100644 apps/common/main/resources/img/toolbar/2x/btn-arrow-down.png
 create mode 100644 apps/common/main/resources/img/toolbar/2x/btn-arrow-up.png

diff --git a/apps/common/main/resources/img/toolbar/1x/btn-arrow-down.png b/apps/common/main/resources/img/toolbar/1x/btn-arrow-down.png
new file mode 100644
index 0000000000000000000000000000000000000000..77b1c0c6492cc79ece53632d718dfd4a3ea16f9e
GIT binary patch
literal 287
zcmeAS@N?(olHy`uVBq!ia0vp^8bB<<!3HG%yVdUoQk(@Ik;M!Q+`=Ht$S`Y;1W=H%
zILO_JVcj{Imp~3nx}&cn1H;CC?mvmFK>ij_7srqa#<vqMavo9OaabI?K)Ix)Pod*M
zzWQ5+x{{VMX7xaSe#^eYS+8W>?LR4Scy{QsG$?R9`p=<wEUf=p6_bi$i{M4$sh?!H
z<oOS8&|aEmp?Gypv2@zRKOg1p@4PfQ3&@<_Fy+!Tm0-QLwYmX99f{tPw%$rTDYtVL
zhg+Yc^QG$jMdzl^iAvTvHiOyfgwlD*_n#$_-KRfjSE*4BpU^T*W>(Fu)9JR#^S`Bk
e=4jes%)hIs%JBG~$mu}$GkCiCxvX<aXaWEh5NCe?

literal 0
HcmV?d00001

diff --git a/apps/common/main/resources/img/toolbar/1x/btn-arrow-up.png b/apps/common/main/resources/img/toolbar/1x/btn-arrow-up.png
new file mode 100644
index 0000000000000000000000000000000000000000..8b08b1fb8b7b53f90b76b14dd3a71d959362a4b0
GIT binary patch
literal 268
zcmeAS@N?(olHy`uVBq!ia0vp^8bB<<!3HG%yVdUoQk(@Ik;M!Q+`=Ht$S`Y;1W=H%
zILO_JVcj{Imp~3nx}&cn1H;CC?mvmFK>k8c7srqa#<vr1a~@UTaab&D(WG3$;wW>#
zQ}%%BJGQ(<+ckeqxODA{WBn}VMu{dlVFpJ5I|q)$Lk;a2Ykei=#Mx#kYz)cv_4k+*
zap-}ER>Fz1f**S(MZKO;{O_RcPLHLk;a+q1_g{<pwKDPDUj1-2&urblSGHwMfBMct
zu5-?`l5;a{cW!-hCp%Fm-HmDP64qr)Qol$f9IBMCXKGU5c>kF_ZAJsblGk5O0v*fX
M>FVdQ&MBb@0GwT6$p8QV

literal 0
HcmV?d00001

diff --git a/apps/common/main/resources/img/toolbar/2x/btn-arrow-down.png b/apps/common/main/resources/img/toolbar/2x/btn-arrow-down.png
new file mode 100644
index 0000000000000000000000000000000000000000..c01427ae73af6c9df36e9908d76770f3be91e8fe
GIT binary patch
literal 427
zcmeAS@N?(olHy`uVBq!ia0vp^0YI$5!3HEV6KWZO6lZ})WHAGSm?{V}dIqU{017e|
z2e~^jtUD+363Agmcl32+VA$Bt{U?zXDCgkm;uuoF`1VR*SF?dg>%-SOChE8zWS@R{
zZi)8i7qj(LxdZ3SQDhX<y#8dHm!&+*8q@8+#6=X9px~EX>~-5;`^tkjj19bd*1rD5
zaoSVy%mJOZU+rggKVr6@o+|0Bl%$`QFfH}Sj|1m79Glcp`2PRjOyyNf=RW_DW~=(+
zkat8x|KDLb<D-0OKR3)tal3P*xNzF5e_DZAvyNRYwG9h>dg#-`9kOi)v%kH2-1@j|
zmfF?0wapB=?>^tHzRIYm{z(0is->dWqk}6O3e+B{KUPg|nsTi9GNYsL$F7P_wH{ZS
z6I>kYmEt7zD@9Le$)&KjEbg$VFWvJ*BjnF16*&>smRgrNyPfwuQCQRwXrsZ$al7M3
z&Gd?sdP)_B9qek1impdK&V8ghyCXs9yo^%PN#CR4-NI1spZdmLEt~qZ|8=)NFl-q-
MUHx3vIVCg!06QA0%m4rY

literal 0
HcmV?d00001

diff --git a/apps/common/main/resources/img/toolbar/2x/btn-arrow-up.png b/apps/common/main/resources/img/toolbar/2x/btn-arrow-up.png
new file mode 100644
index 0000000000000000000000000000000000000000..7de6f592ee1494fbdf6eb16e916dea84d2863e8e
GIT binary patch
literal 414
zcmeAS@N?(olHy`uVBq!ia0vp^0YI$5!3HEV6KWZO6lZ})WHAGSm?{V}dIqU{017e|
z2e~^jtUD+363Agmcl32+VA$Bt{U?zXC}-^H;uuoF`1ZQvsb&L#wudL*yB3LT7P#|w
zujl&be*Ke*Ig*TXnQ|viN?B&w{l3vb%5y@vx27P_BoGLZK7R4j0=Kun^C~AOIeS^$
z*_La3e)qcK%O;gs9z5p9`_D-{_H6VzAfj&@yKm<-CA*`W3r|iCaw$CUydv?(?}f*1
zgemPi`nk~Z>`_5i#`}+3cRv0qke8?U$k9ezfA1Pkr7(7zuI)PA&$Daq-`=b&chq~K
zU95Jf=!f7vPtJ5$Hf~W8V?Wb5eU9Kpl^(YviyBlvPKtM1!>QCeLw18&+^6o2NdlAh
zMlu40^WCoe(7HD7qr2p_(!Cy!4DTJT{>fvfedfRC`PL=&Z2h)+^AZnV*kivaQDWU6
yv55ln52jDt^dVrK)c@kg-HYn#A^ruDygL{_3uP{@?qzKPiFvyExvX<aXaWFiBc&Ap

literal 0
HcmV?d00001

diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index e2cfe59fd..e44a0d956 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -245,7 +245,7 @@ define([
             this.btnListUp = new Common.UI.Button({
                 parentEl: $markup.findById('#form-list-up'),
                 cls: 'btn-toolbar',
-                iconCls: 'toolbar__icon btn-up',
+                iconCls: 'toolbar__icon btn-arrow-up',
                 hint: this.textTipUp
             });
             this.btnListUp.on('click', _.bind(this.onMoveItem, this, true));
@@ -254,7 +254,7 @@ define([
             this.btnListDown = new Common.UI.Button({
                 parentEl: $markup.findById('#form-list-down'),
                 cls: 'btn-toolbar',
-                iconCls: 'toolbar__icon btn-down',
+                iconCls: 'toolbar__icon btn-arrow-down',
                 hint: this.textTipDown
             });
             this.btnListDown.on('click', _.bind(this.onMoveItem, this, false));

From fde9320fdf2382daa9765903cc413694518e0bde Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Tue, 13 Oct 2020 15:28:02 +0300
Subject: [PATCH 23/33] [DE] Use clear forms function

---
 apps/documenteditor/main/app/controller/FormsTab.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/apps/documenteditor/main/app/controller/FormsTab.js b/apps/documenteditor/main/app/controller/FormsTab.js
index 8d41dbd5f..d4ef8eb8b 100644
--- a/apps/documenteditor/main/app/controller/FormsTab.js
+++ b/apps/documenteditor/main/app/controller/FormsTab.js
@@ -228,7 +228,7 @@ define([
 
         onClearClick: function() {
             if (this.api) {
-                // this.api.asc_ClearControls();
+                this.api.asc_ClearAllSpecialForms();
             }
             Common.NotificationCenter.trigger('edit:complete', this.toolbar);
         },

From def0acd55c31ffffb66d5fde94cc63d233c00e0a Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Thu, 15 Oct 2020 12:17:34 +0300
Subject: [PATCH 24/33] [DE] Load image for picture forms

---
 apps/documenteditor/main/app/view/FormSettings.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index e44a0d956..ba02b14ac 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -479,7 +479,7 @@ define([
         },
 
         setImageUrl: function(url, token) {
-            this.api.AddImageUrl(url, this._originalProps, token);
+            this.api.asc_SetContentControlPictureUrl(url, this.internalId, token);
         },
 
         insertImageFromStorage: function(data) {

From 52a1999267b189dafa4a761c6183dbcfc18c0c83 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Thu, 15 Oct 2020 23:42:48 +0300
Subject: [PATCH 25/33] [DE] Change highlight color for new forms

---
 .../main/app/controller/FormsTab.js           | 39 ++++++++++++-------
 apps/documenteditor/main/app/view/FormsTab.js |  2 +-
 2 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/apps/documenteditor/main/app/controller/FormsTab.js b/apps/documenteditor/main/app/controller/FormsTab.js
index d4ef8eb8b..91d7b619d 100644
--- a/apps/documenteditor/main/app/controller/FormsTab.js
+++ b/apps/documenteditor/main/app/controller/FormsTab.js
@@ -68,8 +68,9 @@ define([
                 this.api.asc_registerCallback('asc_onFocusObject', this.onApiFocusObject.bind(this));
                 this.api.asc_registerCallback('asc_onCoAuthoringDisconnect',_.bind(this.onCoAuthoringDisconnect, this));
                 Common.NotificationCenter.on('api:disconnect', _.bind(this.onCoAuthoringDisconnect, this));
-                this.api.asc_registerCallback('asc_onChangeSdtGlobalSettings', _.bind(this.onChangeSdtGlobalSettings, this));
+                this.api.asc_registerCallback('asc_onChangeSpecialFormsGlobalSettings', _.bind(this.onChangeSpecialFormsGlobalSettings, this));
                 this.api.asc_registerCallback('asc_onSendThemeColors', _.bind(this.onSendThemeColors, this));
+                Common.NotificationCenter.on('app:ready', this.onAppReady.bind(this));
 
                 // this.api.asc_registerCallback('asc_onShowContentControlsActions',_.bind(this.onShowContentControlsActions, this));
                 // this.api.asc_registerCallback('asc_onHideContentControlsActions',_.bind(this.onHideContentControlsActions, this));
@@ -171,21 +172,18 @@ define([
             };
 
             this.view && this.view.mnuFormsColorPicker && updateColors(this.view.mnuFormsColorPicker, 1);
-            this.onChangeSdtGlobalSettings();
+            this.onChangeSpecialFormsGlobalSettings();
         },
 
-        onChangeSdtGlobalSettings: function() {
+        onChangeSpecialFormsGlobalSettings: function() {
             if (this.view && this.view.mnuFormsColorPicker) {
-                var show = this.api.asc_GetGlobalContentControlShowHighlight(),
-                    clr;
+                var clr = this.api.asc_GetSpecialFormsHighlightColor(),
+                    show = !!clr;
                 this.view.mnuNoFormsColor.setChecked(!show, true);
                 this.view.mnuFormsColorPicker.clearSelection();
-                if (show){
-                    clr = this.api.asc_GetGlobalContentControlHighlightColor();
-                    if (clr) {
-                        clr = Common.Utils.ThemeColor.getHexColor(clr.get_r(), clr.get_g(), clr.get_b());
-                        this.view.mnuFormsColorPicker.selectByRGB(clr, true);
-                    }
+                if (clr) {
+                    clr = Common.Utils.ThemeColor.getHexColor(clr.get_r(), clr.get_g(), clr.get_b());
+                    this.view.mnuFormsColorPicker.selectByRGB(clr, true);
                 }
                 this.view.btnHighlight.currentColor = clr;
                 $('.btn-color-value-line', this.view.btnHighlight.cmpEl).css('background-color', clr ? '#' + clr : 'transparent');
@@ -239,16 +237,16 @@ define([
 
         onNoControlsColor: function(item) {
             if (!item.isChecked())
-                this.api.asc_SetGlobalContentControlShowHighlight(true, 220, 220, 220);
+                this.api.asc_SetSpecialFormsHighlightColor(255, 192, 0);
             else
-                this.api.asc_SetGlobalContentControlShowHighlight(false);
+                this.api.asc_SetSpecialFormsHighlightColor();
             Common.NotificationCenter.trigger('edit:complete', this.toolbar);
         },
 
         onSelectControlsColor: function(color) {
             var clr = Common.Utils.ThemeColor.getRgbColor(color);
             if (this.api) {
-                this.api.asc_SetGlobalContentControlShowHighlight(true, clr.get_r(), clr.get_g(), clr.get_b());
+                this.api.asc_SetSpecialFormsHighlightColor(clr.get_r(), clr.get_g(), clr.get_b());
             }
             Common.NotificationCenter.trigger('edit:complete', this.toolbar);
         },
@@ -273,6 +271,19 @@ define([
                 if (this.view)
                     this.view.$el.find('.no-group-mask.form-view').css('opacity', 1);
             }
+        },
+
+        onAppReady: function (config) {
+            var me = this;
+            (new Promise(function (accept, reject) {
+                accept();
+            })).then(function(){
+                if (config.canEditContentControl) {
+                    var clr = me.api.asc_GetSpecialFormsHighlightColor();
+                    clr && (clr = Common.Utils.ThemeColor.getHexColor(clr.get_r(), clr.get_g(), clr.get_b()));
+                    me.view.btnHighlight.currentColor = clr;
+                }
+            });
         }
 
     }, DE.Controllers.FormsTab || {}));
diff --git a/apps/documenteditor/main/app/view/FormsTab.js b/apps/documenteditor/main/app/view/FormsTab.js
index 9d00c1380..37b5ab1ac 100644
--- a/apps/documenteditor/main/app/view/FormsTab.js
+++ b/apps/documenteditor/main/app/view/FormsTab.js
@@ -216,7 +216,7 @@ define([
                         });
                         var colorVal = $('<div class="btn-color-value-line"></div>');
                         $('button:first-child', me.btnHighlight.cmpEl).append(colorVal);
-                        colorVal.css('background-color', me.btnHighlight.currentColor || 'transparent');
+                        colorVal.css('background-color', me.btnHighlight.currentColor ? '#' + me.btnHighlight.currentColor : 'transparent');
                     } else {
                         me.btnHighlight.cmpEl.parents('.group').hide().prev('.separator').hide();
                     }

From 7ae4da5f7e7c373b4b6e38096b3174e612acc484 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Tue, 20 Oct 2020 19:26:31 +0300
Subject: [PATCH 26/33] [DE] Add border for new text form

---
 .../main/app/controller/RightMenu.js          |  1 +
 .../main/app/template/FormSettings.template   |  8 +-
 .../main/app/view/FormSettings.js             | 78 ++++++++++++++++++-
 3 files changed, 84 insertions(+), 3 deletions(-)

diff --git a/apps/documenteditor/main/app/controller/RightMenu.js b/apps/documenteditor/main/app/controller/RightMenu.js
index 02093c2a9..d15dec586 100644
--- a/apps/documenteditor/main/app/controller/RightMenu.js
+++ b/apps/documenteditor/main/app/controller/RightMenu.js
@@ -274,6 +274,7 @@ define([
             this.rightmenu.tableSettings.UpdateThemeColors();
             this.rightmenu.shapeSettings.UpdateThemeColors();
             this.rightmenu.textartSettings.UpdateThemeColors();
+            this.rightmenu.formSettings && this.rightmenu.formSettings.UpdateThemeColors();
         },
 
         updateMetricUnit: function() {
diff --git a/apps/documenteditor/main/app/template/FormSettings.template b/apps/documenteditor/main/app/template/FormSettings.template
index 8a52b6d4b..414110449 100644
--- a/apps/documenteditor/main/app/template/FormSettings.template
+++ b/apps/documenteditor/main/app/template/FormSettings.template
@@ -40,11 +40,17 @@
         </td>
     </tr>
     <tr class="form-textfield">
-        <td class="padding-large">
+        <td class="padding-small">
             <label class="input-label" style="margin-left: 22px;margin-top: 4px;"><%= scope.textWidth %></label>
             <div id="form-spin-width" style="display: inline-block; float: right;"></div>
         </td>
     </tr>
+    <tr class="form-textfield">
+        <td class="padding-large">
+            <label class="input-label" style="margin-left: 22px;margin-top: 4px;"><%= scope.textColor %></label>
+            <div id="form-color-btn" style="display: inline-block; float: right;"></div>
+        </td>
+    </tr>
     <tr class="form-image">
         <td class="padding-large">
             <div id="form-button-replace" style="width:100%;"></div>
diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index ba02b14ac..61e290de4 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -153,7 +153,7 @@ define([
             this.spnMaxChars = new Common.UI.MetricSpinner({
                 el: $markup.findById('#form-spin-max-chars'),
                 step: 1,
-                width: 48,
+                width: 45,
                 defaultUnit : "",
                 value: '10',
                 maxValue: 1000000,
@@ -308,6 +308,7 @@ define([
             }, this));
 
             this.updateMetricUnit();
+            this.UpdateThemeColors();
         },
 
         setApi: function(api) {
@@ -515,6 +516,29 @@ define([
             }
         },
 
+        onColorPickerSelect: function(btn, color) {
+            this.BorderColor = color;
+            this._state.BorderColor = this.BorderColor;
+
+            if (this.api && !this._noApply) {
+                var props   = this._originalProps || new AscCommon.CContentControlPr();
+                var formTextPr = this._originalTextFormProps || new AscCommon.CSdtTextFormPr();
+                if (color == 'transparent') {
+                    formTextPr.put_CombBorder();
+                } else {
+                    var brd = formTextPr.get_CombBorder();
+                    if (!brd)
+                        brd = new Asc.asc_CTextBorder();
+                    brd.put_Value(1);
+                    brd.put_Color(Common.Utils.ThemeColor.getRgbColor(color));
+                    formTextPr.put_CombBorder(brd);
+                }
+                props.put_TextFormPr(formTextPr);
+                this.api.asc_SetContentControlProperties(props, this.internalId);
+                this.fireEvent('editcomplete', this);
+            }
+        },
+
         ChangeSettings: function(props) {
             if (this._initSettings)
                 this.createDelayedElements();
@@ -620,6 +644,8 @@ define([
                         this._state.Comb=val;
                     }
 
+                    this.btnColor.setDisabled(!val);
+
                     this.spnWidth.setDisabled(!val);
                     val = formTextPr.get_Width();
                     if ( (val===undefined || this._state.Width===undefined)&&(this._state.Width!==val) || Math.abs(this._state.Width-val)>0.1) {
@@ -631,7 +657,34 @@ define([
                     this.chMaxChars.setValue(val && val>=0);
                     this.spnMaxChars.setDisabled(!val || val<0);
                     this.spnMaxChars.setValue(val && val>=0 ? val : 10);
+
+                    var brd = formTextPr.get_CombBorder();
+                    if (brd) {
+                        var color = brd.get_Color();
+                        if (color) {
+                            if (color.get_type() == Asc.c_oAscColor.COLOR_TYPE_SCHEME) {
+                                this.BorderColor = {color: Common.Utils.ThemeColor.getHexColor(color.get_r(), color.get_g(), color.get_b()), effectValue: color.get_value() };
+                            } else {
+                                this.BorderColor = Common.Utils.ThemeColor.getHexColor(color.get_r(), color.get_g(), color.get_b());
+                            }
+                        } else
+                            this.BorderColor = 'transparent';
+                    } else
+                        this.BorderColor = 'transparent';
+
+                    var type1 = typeof(this.BorderColor),
+                        type2 = typeof(this._state.BorderColor);
+                    if ( (type1 !== type2) || (type1=='object' &&
+                        (this.BorderColor.effectValue!==this._state.BorderColor.effectValue || this._state.BorderColor.color.indexOf(this.BorderColor.color)<0)) ||
+                        (type1!='object' && this._state.BorderColor.indexOf(this.BorderColor)<0 )) {
+
+                        this.btnColor.setColor(this.BorderColor);
+                        this.mnuColorPicker.clearSelection();
+                        this.mnuColorPicker.selectByRGB(typeof(this.BorderColor) == 'object' ? this.BorderColor.color : this.BorderColor,true);
+                        this._state.BorderColor = this.BorderColor;
+                    }
                 }
+
                 this._noApply = false;
 
                 if (this.type !== type || type == Asc.c_oAscContentControlSpecificType.CheckBox)
@@ -650,6 +703,26 @@ define([
             }
         },
 
+        UpdateThemeColors: function() {
+            if (this._initSettings) return;
+
+            if (!this.btnColor) {
+                this.btnColor = new Common.UI.ColorButton({
+                    parentEl: (this.$el || $(this.el)).findById('#form-color-btn'),
+                    transparent: true,
+                    menu        : true
+                });
+                this.lockedControls.push(this.btnColor);
+                this.btnColor.on('color:select', this.onColorPickerSelect.bind(this));
+                this.btnColor.setMenu();
+                this.mnuColorPicker = this.btnColor.getPicker();
+            }
+
+            this.mnuColorPicker.updateColors(Common.Utils.ThemeColor.getEffectColors(), Common.Utils.ThemeColor.getStandartColors());
+            this.mnuColorPicker.clearSelection();
+            this.BorderColor && this.mnuColorPicker.selectByRGB(typeof(this.BorderColor) == 'object' ? this.BorderColor.color : this.BorderColor,true);
+        },
+        
         onHideMenus: function(menu, e, isFromInputControl){
             if (!isFromInputControl) this.fireEvent('editcomplete', this);
         },
@@ -735,7 +808,8 @@ define([
         textSelectImage: 'Select Image',
         textFromUrl:    'From URL',
         textFromFile:   'From File',
-        textFromStorage: 'From Storage'
+        textFromStorage: 'From Storage',
+        textColor: 'Border color'
 
     }, DE.Views.FormSettings || {}));
 });
\ No newline at end of file

From 1ddd5b23d5327480bbbe1be97f2b71c8000c7a52 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Fri, 30 Oct 2020 20:15:50 +0300
Subject: [PATCH 27/33] MetricSpinner: fix check auto value

---
 .../main/lib/component/MetricSpinner.js       | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/apps/common/main/lib/component/MetricSpinner.js b/apps/common/main/lib/component/MetricSpinner.js
index b90673569..6f69c9217 100644
--- a/apps/common/main/lib/component/MetricSpinner.js
+++ b/apps/common/main/lib/component/MetricSpinner.js
@@ -234,10 +234,7 @@ define([
         },
 
         getNumberValue: function(){
-            if (this.options.allowAuto && this.value==this.options.autoText)
-                return -1;
-            else
-                return parseFloat(this.value);
+            return this.checkAutoText(this.value) ? -1 : parseFloat(this.value);
         },
 
         getUnitValue: function(){
@@ -262,7 +259,7 @@ define([
             this.lastValue = this.value;
             if ( typeof value === 'undefined' || value === ''){
                 this.value = '';
-            } else if (this.options.allowAuto && (Math.abs(Common.Utils.String.parseFloat(value)+1.)<0.0001 || value==this.options.autoText)) {
+            } else if (this.options.allowAuto && (Math.abs(Common.Utils.String.parseFloat(value)+1.)<0.0001 || this.checkAutoText(value))) {
                 this.value = this.options.autoText;
             } else {
                 var number = this._add(Common.Utils.String.parseFloat(value), 0, (this.options.allowDecimal) ? 3 : 0);
@@ -450,7 +447,7 @@ define([
                     val = this.getRawValue();
                     val = _.isEmpty(val) ? me.oldValue : Common.Utils.String.parseFloat(val);
                 } else if(me.getValue() !== '') {
-                    if (me.options.allowAuto && me.getValue()==me.options.autoText) {
+                    if (me.checkAutoText(me.getValue())) {
                         val = me.options.minValue-me.options.step;
                     } else
                         val = Common.Utils.String.parseFloat(me.getValue());
@@ -471,7 +468,7 @@ define([
                     val = this.getRawValue();
                     val = _.isEmpty(val) ? me.oldValue : Common.Utils.String.parseFloat(val);
                 } else if(me.getValue() !== '') {
-                    if (me.options.allowAuto && me.getValue()==me.options.autoText) {
+                    if (me.checkAutoText(me.getValue())) {
                         val = me.options.minValue;
                     } else
                         val = Common.Utils.String.parseFloat(me.getValue());
@@ -537,6 +534,14 @@ define([
                 v_out = parseFloat((v_out * 6.0 / 25.4).toFixed(6));
 
             return v_out;
+        },
+
+        checkAutoText: function(value) {
+            if (this.options.allowAuto && typeof value == 'string') {
+                var val = value.toLowerCase();
+                return (val==this.options.autoText.toLowerCase() || val=='auto');
+            }
+            return false;
         }
     });
 

From 5c8231afd9971799fecf02c8180c9c499d7babd9 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Fri, 30 Oct 2020 21:55:58 +0300
Subject: [PATCH 28/33] [DE] Form settings: use auto size of cell width

---
 apps/common/main/lib/component/MetricSpinner.js   | 6 +++++-
 apps/documenteditor/main/app/view/FormSettings.js | 6 ++++++
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/apps/common/main/lib/component/MetricSpinner.js b/apps/common/main/lib/component/MetricSpinner.js
index 6f69c9217..777f74416 100644
--- a/apps/common/main/lib/component/MetricSpinner.js
+++ b/apps/common/main/lib/component/MetricSpinner.js
@@ -448,7 +448,7 @@ define([
                     val = _.isEmpty(val) ? me.oldValue : Common.Utils.String.parseFloat(val);
                 } else if(me.getValue() !== '') {
                     if (me.checkAutoText(me.getValue())) {
-                        val = me.options.minValue-me.options.step;
+                        val = me.options.defaultValue-me.options.step;
                     } else
                         val = Common.Utils.String.parseFloat(me.getValue());
                     if (isNaN(val))
@@ -536,6 +536,10 @@ define([
             return v_out;
         },
 
+        setDefaultValue: function(value) {
+            this.options.defaultValue = value;
+        },
+
         checkAutoText: function(value) {
             if (this.options.allowAuto && typeof value == 'string') {
                 var val = value.toLowerCase();
diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index 61e290de4..96484361b 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -653,6 +653,12 @@ define([
                         this._state.Width=val;
                     }
 
+                    val = this.api.asc_GetTextFormAutoWidth();
+                    if ( (this._state.WidthPlaceholder!==val) || Math.abs(this._state.WidthPlaceholder-val)>0.01) {
+                        this.spnWidth.setDefaultValue(val!==undefined && val!==null ? Common.Utils.Metric.fnRecalcFromMM(val) : this.spnWidth.options.minValue);
+                        this._state.WidthPlaceholder=val;
+                    }
+
                     val = formTextPr.get_MaxCharacters();
                     this.chMaxChars.setValue(val && val>=0);
                     this.spnMaxChars.setDisabled(!val || val<0);

From 0ab40b01d425a2f08e06d25a74542f389c0f338d Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Fri, 30 Oct 2020 22:00:22 +0300
Subject: [PATCH 29/33] Fix translation

---
 apps/documenteditor/main/app/view/FormSettings.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index 96484361b..df0f84541 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -796,7 +796,7 @@ define([
         textTip: 'Tip',
         textMaxChars: 'Characters limit',
         textComb: 'Comb of characters',
-        textWidth: 'Width',
+        textWidth: 'Cell width',
         textDelete: 'Delete',
         textLock: 'Lock',
         textUnlock: 'Unlock',

From 74d9fb121a171313ff673a026271f9b45d05b015 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Fri, 30 Oct 2020 22:19:10 +0300
Subject: [PATCH 30/33] [DE] Form settings: disable comb of chars when chars
 limit is disabled

---
 apps/documenteditor/main/app/view/FormSettings.js | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index df0f84541..01457f003 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -355,11 +355,16 @@ define([
         },
 
         onChMaxCharsChanged: function(field, newValue, oldValue, eOpts){
-            this.spnMaxChars.setDisabled(field.getValue()!='checked');
+            var checked = (field.getValue()=='checked');
+            this.spnMaxChars.setDisabled(!checked);
+            if (!checked) {
+                this.chComb.setValue(false, true);
+                this.spnWidth.setDisabled(true);
+            }
             if (this.api && !this._noApply) {
                 var props   = this._originalProps || new AscCommon.CContentControlPr();
                 var formTextPr = this._originalTextFormProps || new AscCommon.CSdtTextFormPr();
-                var checked = (field.getValue()=='checked' || this.chComb.getValue()=='checked');
+                (!checked) && formTextPr.put_Comb(checked);
                 formTextPr.put_MaxCharacters(checked ? (this.spnMaxChars.getNumberValue() || 10) : checked);
                 props.put_TextFormPr(formTextPr);
                 this.api.asc_SetContentControlProperties(props, this.internalId);

From 13c54668b7e8786927be63e2eced38372960b9e3 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Fri, 30 Oct 2020 22:38:52 +0300
Subject: [PATCH 31/33] [DE] Fix empty placeholder for form controls

---
 apps/documenteditor/main/app/view/ControlSettingsDialog.js | 2 +-
 apps/documenteditor/main/app/view/FormSettings.js          | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/apps/documenteditor/main/app/view/ControlSettingsDialog.js b/apps/documenteditor/main/app/view/ControlSettingsDialog.js
index c24ff3024..b731f1735 100644
--- a/apps/documenteditor/main/app/view/ControlSettingsDialog.js
+++ b/apps/documenteditor/main/app/view/ControlSettingsDialog.js
@@ -532,7 +532,7 @@ define([ 'text!documenteditor/main/app/template/ControlSettingsDialog.template',
             var props   = new AscCommon.CContentControlPr();
             props.put_Alias(this.txtName.getValue());
             props.put_Tag(this.txtTag.getValue());
-            props.put_PlaceholderText(this.txtPlaceholder.getValue());
+            props.put_PlaceholderText(this.txtPlaceholder.getValue() || '    ');
             props.put_Appearance(this.cmbShow.getValue());
 
             if (this.isSystemColor) {
diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index 01457f003..b323bea2a 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -337,7 +337,7 @@ define([
         onPlaceholderChanged: function(input, newValue, oldValue, e) {
             if (this.api && !this._noApply) {
                 var props   = this._originalProps || new AscCommon.CContentControlPr();
-                props.put_PlaceholderText(newValue);
+                props.put_PlaceholderText(newValue || '    ');
                 this.api.asc_SetContentControlProperties(props, this.internalId);
                 this.fireEvent('editcomplete', this);
             }

From 63c6b519e82e2706b0fead4ff7bbf4b617d9bc8e Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Sat, 31 Oct 2020 18:31:41 +0300
Subject: [PATCH 32/33] [DE] Form settings: add empty placeholder item to
 combobox and dropdown

---
 .../main/app/view/DocumentHolder.js              | 16 ++++++++++++++--
 .../documenteditor/main/app/view/FormSettings.js |  2 +-
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/apps/documenteditor/main/app/view/DocumentHolder.js b/apps/documenteditor/main/app/view/DocumentHolder.js
index ce3cf6ba1..6a6d8965f 100644
--- a/apps/documenteditor/main/app/view/DocumentHolder.js
+++ b/apps/documenteditor/main/app/view/DocumentHolder.js
@@ -4239,6 +4239,7 @@ define([
             var type = obj.type,
                 props = obj.pr,
                 specProps = (type == Asc.c_oAscContentControlSpecificType.ComboBox) ? props.get_ComboBoxPr() : props.get_DropDownListPr(),
+                isForm = !!props.get_FormPr(),
                 menu = this.listControlMenu,
                 menuContainer = menu ? this.cmpEl.find(Common.Utils.String.format('#menu-container-{0}', menu.id)) : null,
                 me = this;
@@ -4275,14 +4276,25 @@ define([
                 });
             }
             if (specProps) {
+                if (isForm){ // for dropdown and combobox form control always add placeholder item
+                    menu.addItem(new Common.UI.MenuItem({
+                        caption     : props.get_PlaceholderText(),
+                        value       : '',
+                        template    : _.template([
+                            '<a id="<%= id %>" tabindex="-1" type="menuitem" style="<% if (options.value=="") { %> opacity: 0.6 <% } %>">',
+                            '<%= caption %>',
+                            '</a>'
+                        ].join(''))
+                    }));
+                }
                 var count = specProps.get_ItemsCount();
                 for (var i=0; i<count; i++) {
-                    menu.addItem(new Common.UI.MenuItem({
+                    (specProps.get_ItemValue(i)!=='' || !isForm) && menu.addItem(new Common.UI.MenuItem({
                         caption     : specProps.get_ItemDisplayText(i),
                         value       : specProps.get_ItemValue(i)
                     }));
                 }
-                if (count<1) {
+                if (!isForm && menu.items.length<1) {
                     menu.addItem(new Common.UI.MenuItem({
                         caption     : this.txtEmpty,
                         value       : -1
diff --git a/apps/documenteditor/main/app/view/FormSettings.js b/apps/documenteditor/main/app/view/FormSettings.js
index b323bea2a..d41dbedf0 100644
--- a/apps/documenteditor/main/app/view/FormSettings.js
+++ b/apps/documenteditor/main/app/view/FormSettings.js
@@ -580,7 +580,7 @@ define([
                         var count = specProps.get_ItemsCount();
                         var arr = [];
                         for (var i=0; i<count; i++) {
-                            arr.push({
+                            (specProps.get_ItemValue(i)!=='') && arr.push({
                                 value: specProps.get_ItemValue(i),
                                 name: specProps.get_ItemDisplayText(i)
                             });

From 7115adc51423621078f20f1eacf1c057a5365445 Mon Sep 17 00:00:00 2001
From: Julia Radzhabova <julia.radzhabova@onlyoffice.com>
Date: Sat, 31 Oct 2020 18:32:19 +0300
Subject: [PATCH 33/33] Refactoring

---
 apps/documenteditor/main/app/template/Toolbar.template | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/apps/documenteditor/main/app/template/Toolbar.template b/apps/documenteditor/main/app/template/Toolbar.template
index 1fff3ec2c..d31d858c8 100644
--- a/apps/documenteditor/main/app/template/Toolbar.template
+++ b/apps/documenteditor/main/app/template/Toolbar.template
@@ -171,7 +171,7 @@
                     <span class="btn-slot text x-huge" id="slot-btn-form-image"></span>
                 </div>
                 <div class="separator long"></div>
-                <div class="group" style="padding-left: 5px;">
+                <div class="group">
                     <div class="elset">
                         <span class="btn-slot text" id="slot-form-clear-fields"></span>
                     </div>