added chart tab

This commit is contained in:
nikita_bartoshuk
2025-10-15 15:28:47 +03:00
parent 403242c254
commit 6766f26ff1
8 changed files with 1436 additions and 1 deletions

View File

@ -442,6 +442,38 @@
}
.combo-chart-template {
.combo-template(62px);
top: -4px;
position: absolute;
.padding-right-12();
.more-container & {
position: static;
}
.view .dataview, .dropdown-menu {
padding: 1px;
}
.dropdown-menu {
padding: 5px 1px 5px 1px;
.dataview {
.group-description {
padding: 3px 0 3px 10px;
.font-weight-bold();
.rtl & {
padding: 3px 10px 3px 0;
}
}
}
}
}
.combo-slicer-style {
.combo-textart(60px, 4px);
}

View File

@ -146,6 +146,7 @@ require([
'DataTab',
'ViewTab',
'TableDesignTab',
'ChartTab',
'Search',
'WBProtection',
'Common.Controllers.Fonts',
@ -185,6 +186,7 @@ require([
'spreadsheeteditor/main/app/controller/DataTab',
'spreadsheeteditor/main/app/controller/ViewTab',
'spreadsheeteditor/main/app/controller/TableDesignTab',
'spreadsheeteditor/main/app/controller/ChartTab',
'spreadsheeteditor/main/app/controller/Search',
'spreadsheeteditor/main/app/controller/WBProtection',
// 'spreadsheeteditor/main/app/view/ParagraphSettings',

View File

@ -0,0 +1,577 @@
/*
* (c) Copyright Ascensio System SIA 2010-2024
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
/**
* ChartTab.js
*
* Created on 06.10.2025
*
*/
define([
'core',
'spreadsheeteditor/main/app/view/ChartTab'
], function () {
'use strict';
SSE.Controllers.ChartTab = Backbone.Controller.extend(_.extend({
models : [],
collections : [
],
views : [
'ChartTab'
],
sdkViewName : '#id_main',
initialize: function () {
this._state = {
Width: 0,
Height: 0,
ChartStyle: 1,
ChartType: -1,
SeveralCharts: false,
DisabledControls: false,
keepRatio: false,
};
this._nRatio = 1;
this.spinners = [];
this.chPoints = [];
this.lockedControls = [];
this._locked = false;
this.defColor = {color: '4f81bd', effectId: 24};
this.isChart = true;
this._noApply = false;
this._originalProps = null;
this.addListeners({
'ChartTab': {
'charttab:advanced': _.bind(this.openAdvancedSettings, this),
'charttab:type': _.bind(this.onChangeType, this),
'charttab:selectdata': _.bind(this.onSelectData, this),
'charttab:rowscols': _.bind(this.onSwitchRowsCols, this),
'charttab:widthchange': _.bind(this.onWidthChange, this),
'charttab:heightchange': _.bind(this.onHeightChange, this),
'charttab:ratio': _.bind(this.onToggleRatio, this),
},
});
},
onToggleRatio: function (value) {
if (value && this.view.spnHeight.getNumberValue()>0) {
this._nRatio = this.view.spnWidth.getNumberValue()/this.view.spnHeight.getNumberValue();
}
if (this.api) {
var props = new Asc.asc_CImgProperty();
props.asc_putLockAspect(value);
this.api.asc_setGraphicObjectProps(props);
}
},
ChangeSettings: function(props) {
if (this._initSettings) {
this.updateMetricUnit();
this.spinners.push(this.view.spnWidth);
this.spinners.push(this.view.spnHeight);
}
if (this._isEditType) {
this._props = props;
return;
}
var isChart = !!(props && props.asc_getChartProperties && props.asc_getChartProperties()),
chartSettings = isChart ? this.api.asc_getChartSettings(true) : null, // don't lock chart object
props3d = chartSettings ? chartSettings.getView3d() : null;
if ( this.isChart!==isChart || this._state.is3D!==!!props3d ) {
this.ShowHideElem(isChart, !!props3d);
}
this._state.is3D=!!props3d;
this.disableControls(this._locked);
if (this.api && props){
if (isChart) { // chart
this._originalProps = new Asc.asc_CImgProperty(props);
this.isChart = true;
this._noApply = true;
this.chartProps = props.asc_getChartProperties();
var value = props.asc_getSeveralCharts() || this._locked;
if (this._state.SeveralCharts!==value) {
this.view.btnAdvancedSettings.setDisabled(value)
this._state.SeveralCharts=value;
}
value = props.asc_getSeveralChartTypes();
var type = (this._state.SeveralCharts && value) ? null : this.chartProps.getType();
if (this._state.ChartType !== type) {
this.ShowCombinedProps(type);
!(type===null || type==Asc.c_oAscChartTypeSettings.comboBarLine || type==Asc.c_oAscChartTypeSettings.comboBarLineSecondary ||
type==Asc.c_oAscChartTypeSettings.comboAreaBar || type==Asc.c_oAscChartTypeSettings.comboCustom) && this.updateChartStyles(this.api.asc_getChartPreviews(type, undefined, true));
this._state.ChartType = type;
}
if (!(type==Asc.c_oAscChartTypeSettings.comboBarLine || type==Asc.c_oAscChartTypeSettings.comboBarLineSecondary ||
type==Asc.c_oAscChartTypeSettings.comboAreaBar || type==Asc.c_oAscChartTypeSettings.comboCustom)) {
value = props.asc_getSeveralChartStyles();
if (this._state.SeveralCharts && value) {
this.view.chartStyles.fieldPicker.deselectAll();
this.view.chartStyles.menuPicker.deselectAll();
this._state.ChartStyle = null;
} else {
value = this.chartProps.getStyle();
if (this._state.ChartStyle!==value || this._isChartStylesChanged) {
this._state.ChartStyle=value;
var arr = this.selectCurrentChartStyle();
this._isChartStylesChanged && this.api.asc_generateChartPreviews(this._state.ChartType, arr);
}
}
this._isChartStylesChanged = false;
}
this._noApply = false;
value = props.asc_getWidth();
if ( Math.abs(this._state.Width-value)>0.001 ||
(this._state.Width===null || value===null)&&(this._state.Width!==value)) {
this.view.spnWidth.setValue((value!==null) ? Common.Utils.Metric.fnRecalcFromMM(value) : '', true);
this._state.Width = value;
}
value = props.asc_getHeight();
if ( Math.abs(this._state.Height-value)>0.001 ||
(this._state.Height===null || value===null)&&(this._state.Height!==value)) {
this.view.spnHeight.setValue((value!==null) ? Common.Utils.Metric.fnRecalcFromMM(value) : '', true);
this._state.Height = value;
}
if (props.asc_getHeight()>0)
this._nRatio = props.asc_getWidth()/props.asc_getHeight();
value = props.asc_getLockAspect();
if (this._state.keepRatio!==value) {
console.log(this.view.chRatio)
this.view.chRatio.setValue(value, true);
this._state.keepRatio=value;
}
var series = chartSettings ? chartSettings.getSeries() : null;
this.view.btnSwitchRowsCols.setDisabled(this._locked || !series || series.length<1 || !chartSettings || !chartSettings.getRange());
if (props3d) {
value = props3d.asc_getRotX();
if ((this._state.X===undefined || value===undefined)&&(this._state.X!==value) ||
Math.abs(this._state.X-value)>0.001) {
// this.spnX.setValue((value!==null && value !== undefined) ? value : '', true);
this._state.X = value;
}
value = props3d.asc_getRotY();
if ( (this._state.Y===undefined || value===undefined)&&(this._state.Y!==value) ||
Math.abs(this._state.Y-value)>0.001) {
// this.spnY.setValue((value!==null && value !== undefined) ? value : '', true);
this._state.Y = value;
}
value = props3d.asc_getRightAngleAxes();
if ( this._state.RightAngle!==value ) {
// this.chRightAngle.setValue((value !== null && value !== undefined) ? value : 'indeterminate', true);
this._state.RightAngle=value;
}
value = props3d.asc_getPerspective();
if ( (this._state.Perspective===undefined || value===undefined)&&(this._state.Perspective!==value) ||
Math.abs(this._state.Perspective-value)>0.001) {
// this.spnPerspective.setMinValue((value!==null && value !== undefined) ? 0.1 : 0);
// this.spnPerspective.setValue((value!==null && value !== undefined) ? value : 0, true);
this._state.Perspective = value;
}
// this.spnPerspective.setDisabled(this._locked || !!this._state.RightAngle);
// this.btnNarrow.setDisabled(this._locked || !!this._state.RightAngle);
// this.btnWiden.setDisabled(this._locked || !!this._state.RightAngle);
value = props3d.asc_getDepth();
if ( Math.abs(this._state.Depth-value)>0.001 ||
(this._state.Depth===undefined || value===undefined)&&(this._state.Depth!==value)) {
// this.spn3DDepth.setValue((value!==null && value !== undefined) ? value : '', true);
this._state.Depth = value;
}
value = props3d.asc_getHeight();
if ( Math.abs(this._state.Height3d-value)>0.001 ||
(this._state.Height3d===undefined || this._state.Height3d===null || value===null)&&(this._state.Height3d!==value)) {
(value!==null) && this.spn3DHeight.setValue(value, true);
// this.chAutoscale.setValue(value===null, true);
this._state.Height3d = value;
}
// this.spn3DHeight.setDisabled(this._locked || value===null);
}
}
}
},
ShowHideElem: function(isChart, is3D) {
// this.ChartSizeContainer.toggleClass('settings-hidden', !isChart);
// this.ChartTypesContainer.toggleClass('settings-hidden', !isChart);
// this.SparkTypesContainer.toggleClass('settings-hidden', isChart);
// this.SparkPointsContainer.toggleClass('settings-hidden', isChart);
// this.Chart3DContainer.toggleClass('settings-hidden', !isChart || !is3D);
this.fireEvent('updatescroller', this);
},
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.1);
}
this.view.spnWidth && this.view.spnWidth.setValue((this._state.Width!==null) ? Common.Utils.Metric.fnRecalcFromMM(this._state.Width) : '', true);
this.view.spnHeight && this.view.spnHeight.setValue((this._state.Height!==null) ? Common.Utils.Metric.fnRecalcFromMM(this._state.Height) : '', true);
}
},
openAdvancedSettings: function() {
if (this.view.btnAdvancedSettings.isDisabled() || !Common.Controllers.LaunchController.isScriptLoaded()) return;
var me = this;
var win, props;
if (me.api){
props = (me.isChart) ? me.api.asc_getChartSettings() : me._originalProps;
if (props) {
(new SSE.Views.ChartSettingsDlg(
{
chartSettings: props,
imageSettings: (me.isChart) ? me._originalProps : null,
sparklineStyles: me.sparklineStyles,
isChart: me.isChart,
api: me.api,
handler: function(result, value) {
if (result == 'ok') {
if (me.api) {
if (me.isChart) {
if (value.imageSettings) {
value.imageSettings.asc_putChartProperties(value.chartSettings);
me.api.asc_setGraphicObjectProps(value.imageSettings);
} else
me.api.asc_applyChartSettings(value.chartSettings);
}
}
}
Common.NotificationCenter.trigger('edit:complete', me);
}
})).show();
}
}
},
onChangeType: function() {
var me = this;
if (me.api){
me._isEditType = true;
var win = new SSE.Views.ChartWizardDialog({
api: me.api,
props: {recommended: me.api.asc_getRecommendedChartData()},
type: me._state.ChartType,
isEdit: true,
handler: function(result, value) {
if (result == 'ok') {
me._isEditType = false;
me.api && me.api.asc_addChartSpace(value);
}
Common.NotificationCenter.trigger('edit:complete', me.toolbar);
}
}).on('close', function() {
me._isEditType = false;
});
win.show();
}
},
onSelectData: function() {
if (!Common.Controllers.LaunchController.isScriptLoaded()) {
return;
}
var me = this;
var props;
if (me.api){
props = me.api.asc_getChartSettings();
if (props) {
me._isEditRanges = true;
props.startEdit();
var win = new SSE.Views.ChartDataDialog({
chartSettings: props,
api: me.api,
handler: function(result, value) {
if (result == 'ok') {
props.endEdit();
me._isEditRanges = false;
}
Common.NotificationCenter.trigger('edit:complete', me);
}
}).on('close', function() {
me._isEditRanges && props.cancelEdit();
me._isEditRanges = false;
});
win.show();
}
}
},
onSwitchRowsCols: function() {
if (this.api){
var props = this.api.asc_getChartSettings(true);
if (props) {
props.startEdit();
var res = props.switchRowCol();
if (res === Asc.c_oAscError.ID.MaxDataSeriesError) {
props.cancelEdit();
Common.UI.warning({msg: this.errorMaxRows, maxwidth: 600});
} else
props.endEdit();
}
}
},
onWidthChange: function(field, newValue, oldValue, eOpts){
var w = field.getNumberValue();
var h = this.view.spnHeight.getNumberValue();
if (this.view.chRatio.getValue()) {
h = w/this._nRatio;
if (h>this.view.spnHeight.options.maxValue) {
h = this.view.spnHeight.options.maxValue;
w = h * this._nRatio;
this.view.spnWidth.setValue(w, true);
}
this.view.spnHeight.setValue(h, true);
}
if (this.api) {
var props = new Asc.asc_CImgProperty();
props.asc_putWidth(Common.Utils.Metric.fnRecalcToMM(w));
props.asc_putHeight(Common.Utils.Metric.fnRecalcToMM(h));
this.api.asc_setGraphicObjectProps(props);
}
},
onHeightChange: function(field, newValue, oldValue, eOpts){
var h = field.getNumberValue(), w = this.spnWidth.getNumberValue();
if (this.view.chRatio.getValue()) {
w = h * this._nRatio;
if (w>this.view.spnWidth.options.maxValue) {
w = this.view.spnWidth.options.maxValue;
h = w/this._nRatio;
this.view.spnHeight.setValue(h, true);
}
this.view.spnWidth.setValue(w, true);
}
if (this.api) {
var props = new Asc.asc_CImgProperty();
props.asc_putWidth(Common.Utils.Metric.fnRecalcToMM(w));
props.asc_putHeight(Common.Utils.Metric.fnRecalcToMM(h));
this.api.asc_setGraphicObjectProps(props);
}
},
disableControls: function(disable) {
if (this._initSettings) return;
if (this._state.DisabledControls!==disable) {
this._state.DisabledControls = disable;
_.each(this.lockedControls, function(item) {
item.setDisabled(disable);
});
this.view.btnAdvancedSettings.setDisabled(disable);
}
},
ShowCombinedProps: function(type) {
this.view.chartStyles.setVisible(!(type===null || type==Asc.c_oAscChartTypeSettings.comboBarLine || type==Asc.c_oAscChartTypeSettings.comboBarLineSecondary ||
type==Asc.c_oAscChartTypeSettings.comboAreaBar || type==Asc.c_oAscChartTypeSettings.comboCustom));
},
updateChartStyles: function(styles) {
var me = this;
this._isChartStylesChanged = true;
this.view.chartStyles.render($('#chart-combo-style'));
this.view.chartStyles.on('click', _.bind(this.onSelectStyle, this));
this.view.chartStyles.openButton.menu.on('show:after', function () {
me.view.chartStyles.menuPicker.scroller.update({alwaysVisibleY: true});
});
this.lockedControls.push(this.view.chartStyles);
if (styles && styles.length>0){
var stylesStore = this.view.chartStyles.menuPicker.store;
if (stylesStore) {
var stylearray = [];
_.each(styles, function(item, index){
stylearray.push({
imageUrl: item.asc_getImage(),
data : item.asc_getName(),
tip : me.textStyle + ' ' + item.asc_getName()
});
});
stylesStore.reset(stylearray, {silent: false});
}
} else {
this.view.chartStyles.menuPicker.store.reset();
this.view.chartStyles.clearComboView();
}
this.view.chartStyles.setDisabled(!styles || styles.length<1 || this._locked);
},
onSelectStyle: function(combo, record) {
if (this._noApply) return;
if (this.api && !this._noApply && this.chartProps) {
var props = new Asc.asc_CImgProperty();
this.chartProps.putStyle(record.get('data'));
props.asc_putChartProperties(this.chartProps);
this.api.asc_setGraphicObjectProps(props);
}
Common.NotificationCenter.trigger('edit:complete', this);
},
selectCurrentChartStyle: function() {
if (!this.view.chartStyles) return;
this.view.chartStyles.suspendEvents();
var rec = this.view.chartStyles.menuPicker.store.findWhere({data: this._state.ChartStyle});
this.view.chartStyles.menuPicker.selectRecord(rec);
this.view.chartStyles.resumeEvents();
if (this._isChartStylesChanged) {
var currentRecords;
if (rec)
currentRecords = this.view.chartStyles.fillComboView(this.view.chartStyles.menuPicker.getSelectedRec(), true);
else
currentRecords = this.view.chartStyles.fillComboView(this.view.chartStyles.menuPicker.store.at(0), true);
if (currentRecords && currentRecords.length>0) {
var arr = [];
_.each(currentRecords, function(style, index){
arr.push(style.get('data'));
});
return arr;
}
}
},
setApi: function(api) {
if (api) {
this.api = api;
this.api.asc_registerCallback('asc_onCoAuthoringDisconnect',_.bind(this.SetDisabled, this));
Common.NotificationCenter.on('api:disconnect', _.bind(this.SetDisabled, this));
this.api.asc_registerCallback('asc_onSelectionChanged', _.bind(this.onSelectionChanged, this));
this.api.asc_registerCallback('asc_onAddChartStylesPreview', _.bind(this.onAddChartStylesPreview, this));
this.api.asc_registerCallback('asc_onUpdateChartStyles', _.bind(this._onUpdateChartStyles, this));
Common.NotificationCenter.on('cells:range', _.bind(this.onCellsRange, this));
}
return this;
},
onAddChartStylesPreview: function(styles){
if (this._isEditType || !this.view.chartStyles) return;
if (styles && styles.length>0){
var stylesStore = this.view.chartStyles.menuPicker.store;
if (stylesStore) {
_.each(styles, function(item, index){
var rec = stylesStore.findWhere({
data: item.asc_getName()
});
rec && rec.set('imageUrl', item.asc_getImage());
});
}
}
},
_onUpdateChartStyles: function() {
if (this.api && this._state.ChartType!==null && this._state.ChartType>-1 &&
!(this._state.ChartType==Asc.c_oAscChartTypeSettings.comboBarLine || this._state.ChartType==Asc.c_oAscChartTypeSettings.comboBarLineSecondary ||
this._state.ChartType==Asc.c_oAscChartTypeSettings.comboAreaBar || this._state.ChartType==Asc.c_oAscChartTypeSettings.comboCustom)) {
this.updateChartStyles(this.api.asc_getChartPreviews(this._state.ChartType, undefined, true));
this.api.asc_generateChartPreviews(this._state.ChartType, this.selectCurrentChartStyle());
}
},
setMode: function(mode) {
this.appConfig = mode;
return this;
},
setConfig: function(config) {
this.view = this.createView('ChartTab', {
toolbar: config.toolbar.toolbar
});
},
SetDisabled: function(state) {
this.view && this.view.SetDisabled(state);
},
createToolbarPanel: function() {
return this.view.getPanel();
},
getView: function(name) {
return !name && this.view ?
this.view : Backbone.Controller.prototype.getView.call(this, name);
},
onCoAuthoringDisconnect: function() {
this.SetDisabled(true);
},
onSelectionChanged: function(info) {
if (this.rangeSelectionMode || !this.appConfig.isEdit || !this.view) return;
var selectType = info.asc_getSelectionType();
var selectedObjects = this.api.asc_getGraphicObjectProps();
if ((selectType == Asc.c_oAscSelectionType.RangeChart || selectType == Asc.c_oAscSelectionType.RangeChartText) && selectedObjects)
for (var i = 0; i < selectedObjects.length; i++) {
if (selectedObjects[i].asc_getObjectType() == Asc.c_oAscTypeSelectElement.Image) {
var elValue = selectedObjects[i].asc_getObjectValue();
if ( elValue.asc_getChartProperties() ) {
this.ChangeSettings(this.api.asc_getGraphicObjectProps()[i].asc_getObjectValue());
break;
}
}
}
},
onCellsRange: function(status) {
this.rangeSelectionMode = (status != Asc.c_oAscSelectionDialogType.None);
},
}, SSE.Controllers.ChartTab || {}));
});

View File

@ -50,6 +50,17 @@ define([], function () {
'DocumentHolder': {
'createdelayedelements': this.onCreateDelayedElements,
'equation:callback': this.equationCallback
},
'ChartTab': {
'charttab:updatemenu': function (menu) {
me.chartProps = me.getCurrentChartProps();
if (me.chartProps) {
this.updateChartElementMenu(menu, me.chartProps)
}
},
'charttab:elementselected': function (menu, item) {
me.onChartElement(menu, item)
}
}
});

View File

@ -1716,6 +1716,9 @@ define([
if (!me.appOptions.isEditMailMerge && !me.appOptions.isEditDiagram && !me.appOptions.isEditOle && me.appOptions.canFeatureTable)
application.getController('TableDesignTab').setMode(me.appOptions);
if (!me.appOptions.isEditMailMerge && !me.appOptions.isEditDiagram && !me.appOptions.isEditOle && me.appOptions.canFeatureTable)
application.getController('ChartTab').setMode(me.appOptions);
var viewport = this.getApplication().getController('Viewport').getView('Viewport');
viewport.applyEditorMode();
rightmenuController.getView('RightMenu').setMode(me.appOptions).setApi(me.api);

View File

@ -206,7 +206,8 @@ define([
is_lockShape: false,
isUserProtected: false,
showPivotTab: false,
showTableDesignTab: false
showTableDesignTab: false,
showChartTab: false
};
this.binding = {};
@ -3075,6 +3076,14 @@ define([
toolbar.btnInsertChart.updateHint(in_chart ? toolbar.tipChangeChart : toolbar.tipInsertChart);
this._state.in_chart = in_chart;
}
if (this._state.inchart !== in_chart) {
if ( !in_chart && this.toolbar.isTabActive('charttab') )
this.toolbar.setTab('home');
this.toolbar.setVisible('charttab', !!in_chart);
if (in_chart && this._state.showChartTab)
this.toolbar.setTab('charttab');
this._state.inchart = in_chart;
}
if (in_chart) return;
if (!toolbar.mode.isEditDiagram)
@ -4592,6 +4601,18 @@ define([
me.toolbar.btnsTableDesign = tabledesignbuttons;
}
tab = {caption: 'Chart', action: 'charttab', extcls: config.isEdit ? 'canedit' : '', layoutname: 'toolbar-charttab', dataHintTitle: 'V', aux: true};
var charttab = me.getApplication().getController('ChartTab');
charttab.setApi(me.api).setConfig({toolbar: me});
var view = charttab.getView('ChartTab');
var chartbuttons = view.getButtons();
var $panel = charttab.createToolbarPanel();
if ($panel) {
me.toolbar.addTab(tab, $panel);
me._state.inchart && me.toolbar.setVisible('charttab', true);
Array.prototype.push.apply(me.toolbar.lockControls, chartbuttons);
}
if (!config.compactHeader) {
// hide 'print' and 'save' buttons group and next separator
me.toolbar.btnPrint.$el.parents('.group').hide().next().hide();

View File

@ -0,0 +1,787 @@
/*
* (c) Copyright Ascensio System SIA 2010-2024
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
/**
* ChartTab.js
*
* Created on 06.10.2025
*
*/
define([
'common/main/lib/util/utils',
'common/main/lib/component/Button',
'common/main/lib/component/BaseView',
'common/main/lib/component/Layout'
], function () {
'use strict';
SSE.Views.ChartTab = Common.UI.BaseView.extend(_.extend((function(){
var template = '<section id="chart-design-panel" class="panel" data-tab="charttab" role="tabpanel" aria-labelledby="view">' +
'<div class="group">' +
'<span class="btn-slot text x-huge" id="slot-btn-chart-elements"></span>' +
'</div>' +
'<div class="separator long"></div>' +
'<div class="group">' +
'<span class="btn-slot text x-huge" id="slot-btn-chart-type"></span>' +
'</div>' +
'<div class="separator long"></div>' +
'<div class="group">' +
'<span class="btn-slot text x-huge" id="slot-btn-select-data"></span>' +
'<span class="btn-slot text x-huge" id="slot-btn-switch-rowscols"></span>' +
'</div>' +
'<div class="separator long"></div>' +
'<div class="group small">' +
'<div class="elset" style="text-align: center;">' +
'<span class="btn-slot text font-size-normal" id="slot-lbl-width" style="text-align: center;margin-top: 2px;"></span>' +
'</div>' +
'<div class="elset" style="text-align: center;">' +
'<span class="btn-slot text font-size-normal" id="slot-lbl-height" style="text-align: center;margin-top: 2px;"></span>' +
'</div>' +
'</div>' +
'<div class="group small">' +
'<div class="elset">' +
'<div id="chart-spin-width"></div>' +
'</div>' +
'<div class="elset">' +
'<div id="chart-spin-height"></div>' +
'</div>' +
'</div>' +
'<div class="group small">' +
'<div class="elset">' +
'<span class="btn-slot text" id="slot-chk-ratio"></span>' +
'</div>' +
'<div class="elset">' +
'</div>' +
'</div>' +
'<div class="separator long"></div>' +
'<div class="group flex small" id="slot-field-chart-styles" style="width: 100%; min-width: 105px;" data-group-width="100%">' +
'</div>' +
'<div class="separator long"></div>' +
'<div class="group">' +
'<span class="btn-slot text x-huge" id="slot-btn-chart-advanced-settings"></span>' +
'</div>' +
'</section>';
function setEvents() {
var me = this;
me.btnChartElements.on('click', function (btn, e) {
me.fireEvent('charttab:updatemenu', [me.menuChartElement.menu]);
});
me.menuChartElement.menu.items.forEach(item => {
if (item.menu) {
item.menu.items.forEach(item => {
item.on('click', function() {
me.fireEvent('charttab:elementselected', [item.menu, item]);
});
});
}
});
me.btnChartType.on('click', function (btn, e) {
me.fireEvent('charttab:type');
});
me.btnSelectData.on('click', function (btn, e) {
me.fireEvent('charttab:selectdata');
});
me.btnSwitchRowsCols.on('click', function (btn, e) {
me.fireEvent('charttab:rowscols');
});
me.btnAdvancedSettings.on('click', function (btn, e) {
me.fireEvent('charttab:advanced');
});
me.spnWidth.on('change', function () {
me.fireEvent('charttab:widthchange');
});
me.spnHeight.on('change',function () {
me.fireEvent('charttab:heightchange');
});
me.chRatio.on('change',function (field, value) {
me.fireEvent('charttab:ratio', [value === 'checked']);
});
}
return {
initialize: function (options) {
var controller = SSE.getController('ChartTab');
this._state = controller._state;
Common.UI.BaseView.prototype.initialize.call(this);
this.lockedControls = [];
var me = this,
_set = Common.enumLock;
this.menuChartElement = new Common.UI.MenuItem({
menu: new Common.UI.Menu({
items: [
{
caption: 'Axes',
value: 'axes',
disabled: false,
menu: new Common.UI.Menu({
cls: 'shifted-right',
menuAlign: 'tl-tr',
items: [
{
caption: 'Horizontal Axis',
value: 'bShowHorAxis',
stopPropagation: true,
checkable: true
},
{
caption: 'Vertical Axis',
value: 'bShowVertAxis',
stopPropagation: true,
checkable: true
},
{
caption: 'Horizontal Axis Sec',
value: 'bShowHorAxSec',
stopPropagation: true,
checkable: true
},
{
caption: 'Vertical Axis Sec',
value: 'bShowVertAxSec',
stopPropagation: true,
checkable: true
},
{
caption: 'Depth Axes',
value: 'bShowDepthAxes',
stopPropagation: true,
checkable: true
}
]
})
},
{
caption: 'Axis Titles',
value: 'axisTitles',
disabled: false,
menu: new Common.UI.Menu({
cls: 'shifted-right',
menuAlign: 'tl-tr',
items: [
{
caption:'Horizontal Axis',
value: 'bShowHorAxTitle',
stopPropagation: true,
checkable: true
},
{
caption: 'Vertical Axis',
value: 'bShowVertAxTitle',
stopPropagation: true,
checkable: true
},
{
caption: 'Horizontal Axis Sec',
value: 'bShowHorAxTitleSec',
stopPropagation: true,
checkable: true
},
{
caption: 'Vertical Axis Sec',
value: 'bShowVertAxisTitleSec',
stopPropagation: true,
checkable: true
},
{
caption: 'Depth Axis Title',
value: 'bShowDepthAxisTitle',
stopPropagation: true,
checkable: true
}
]
})
},
{
caption: 'Chart Title',
value: 'chartTitle',
disabled: false,
menu: new Common.UI.Menu({
cls: 'shifted-right',
menuAlign: 'tl-tr',
items: [
{
caption: 'None',
value: 'bShowChartTitleNone',
stopPropagation: true,
toggleGroup: 'chartTitle',
checkable: true
},
{
caption: 'No overlay',
value: 'bShowChartTitle',
stopPropagation: true,
toggleGroup: 'chartTitle',
checkable: true
},
{
caption: 'Overlay',
value: 'bOverlayTitle',
stopPropagation: true,
toggleGroup: 'chartTitle',
checkable: true
}
]
})
},
{
caption: 'Data Labels',
value: 'dataLabels',
disabled: false,
menu: new Common.UI.Menu({
cls: 'shifted-right',
menuAlign: 'tl-tr',
items: [
{
caption: 'None',
value: 'bShowDataLabels',
stopPropagation: true,
toggleGroup: 'dataLabels',
checkable: true
},
{
caption: 'Center',
value: 'CenterData',
stopPropagation: true,
toggleGroup: 'dataLabels',
checkable: true
},
{
caption: 'Inner bottom',
value: 'InnerBottomData',
stopPropagation: true,
toggleGroup: 'dataLabels',
checkable: true
},
{
caption: 'Inner top',
value: 'InnerTopData',
stopPropagation: true,
toggleGroup: 'dataLabels',
checkable: true
},
{
caption: 'Outer top',
value: 'OuterTopData',
stopPropagation: true,
toggleGroup: 'dataLabels',
checkable: true
},
{
caption: 'Top',
value: 'TopData',
stopPropagation: true,
toggleGroup: 'dataLabels',
checkable: true
},
{
caption: 'Left',
value: 'LeftData',
stopPropagation: true,
toggleGroup: 'dataLabels',
checkable: true
},
{
caption: 'Right',
value: 'RightData',
stopPropagation: true,
checkable: true
},
{
caption: 'Bottom',
value: 'BottomData',
stopPropagation: true,
toggleGroup: 'dataLabels',
checkable: true
},
{
caption: 'Fit',
value: 'FitWidthData',
stopPropagation: true,
toggleGroup: 'dataLabels',
checkable: true
}
]
})
},
// {
// caption: me.textDataTable,
// value: 'dataTable',
// disabled: false,
// menu: new Common.UI.Menu({
// cls: 'shifted-right',
// menuAlign: 'tl-tr',
// items: [
// {
// caption: me.textNone,
// value: 'bShowDataNone'
// },
// {
// caption: me.textShowDataTable,
// value: 'bShowDataTable'
// },
// {
// caption: me.textShowLegendKeys,
// value: 'bShowLegendKeys'
// }
// ]
// })
// },
{
caption: 'Error bars',
value: 'errorBars',
disabled: false,
menu: new Common.UI.Menu({
cls: 'shifted-right',
menuAlign: 'tl-tr',
items: [
{
caption: 'Standart Error',
value: 'standardError',
stopPropagation: true,
disabled: false
},
{
caption: 'Percentage',
value: 'percentage',
stopPropagation: true,
disabled: false
},
{
caption: 'Standart Deviation',
value: 'standardDeviation',
stopPropagation: true,
disabled: false
}
]
})
},
{
caption: 'Gridlines',
value: 'gridLines',
disabled: false,
menu: new Common.UI.Menu({
cls: 'shifted-right',
menuAlign: 'tl-tr',
items: [
{
caption: 'Horizontal Major',
value: 'bShowHorMajor',
stopPropagation: true,
checkable: true
},
{
caption: 'Vertical Major',
value: 'bShowVerMajor',
stopPropagation: true,
checkable: true
},
{
caption: 'Horizontal Minor',
value: 'bShowHorMinor',
stopPropagation: true,
checkable: true
},
{
caption: 'Vertical Minor',
value: 'bShowVerMinor',
stopPropagation: true,
checkable: true
}
]
})
},
{
caption: 'Legend',
value: 'legend',
disabled: false,
menu: new Common.UI.Menu({
cls: 'shifted-right',
menuAlign: 'tl-tr',
items: [
{
caption: 'Top',
value: 'TopLegend',
stopPropagation: true,
toggleGroup: 'legend',
checkable: true
},
{
caption: 'Left',
value: 'LeftLegend',
stopPropagation: true,
toggleGroup: 'legend',
checkable: true
},
{
caption: 'Right',
value: 'RightLegend',
stopPropagation: true,
toggleGroup: 'legend',
checkable: true
},
{
caption: 'Bottom',
value: 'BottomLegend',
stopPropagation: true,
toggleGroup: 'legend',
checkable: true
},
{
caption: 'Left overlay',
value: 'LeftOverlay',
stopPropagation: true,
toggleGroup: 'legend',
checkable: true
},
{
caption: 'Right overlay',
value: 'RightOverlay',
stopPropagation: true,
toggleGroup: 'legend',
checkable: true
}
]
})
},
{
caption: 'Trendline',
value: 'trendLines',
disabled: false,
menu: new Common.UI.Menu({
cls: 'shifted-right',
menuAlign: 'tl-tr',
items: [
{
caption: 'None',
stopPropagation: true,
value: 'trendLineNone'
},
{
caption: 'Linear',
stopPropagation: true,
value: 'trendLineLinear'
},
{
caption: 'Exponential',
stopPropagation: true,
value: 'trendLineExponential'
},
{
caption: 'Linear Forecast',
stopPropagation: true,
value: 'trendLineForecast'
},
{
caption: 'Moving average',
stopPropagation: true,
value: 'trendLineMovingAverage'
}
]
})
},
// {
// caption: me.textUpDownBars,
// value: 'upDownBars',
// disabled: false,
// menu: new Common.UI.Menu({
// cls: 'shifted-right',
// menuAlign: 'tl-tr',
// items: [
// {
// caption: me.textNone,
// stopPropagation: true,
// value: 'bShowUpDownNone'
// },
// {
// caption: me.textShowUpDown,
// stopPropagation: true,
// value: 'bShowUpDownBars'
// }
// ]
// })
// }
]
})
});
this.btnChartElements = new Common.UI.Button({
cls: 'btn-toolbar x-huge icon-top',
iconCls: 'toolbar__icon btn-freeze-panes',
caption: 'Chart Elements',
lock: [_set.sheetLock, _set.lostConnect, _set.coAuth, _set.editCell],
dataHint: '1',
dataHintDirection: 'bottom',
dataHintOffset: 'small',
menu: true,
menu: this.menuChartElement.menu
});
this.lockedControls.push(this.btnChartElements);
this.btnChartType = new Common.UI.Button({
cls: 'btn-toolbar x-huge icon-top',
iconCls: 'toolbar__icon btn-big-sheet-view',
caption: 'Chart Type',
lock : [_set.lostConnect, _set.coAuth, _set.editCell],
action: 'sheet-view',
dataHint : '1',
dataHintDirection: 'bottom',
dataHintOffset: 'small'
});
this.lockedControls.push(this.btnChartType);
this.btnSelectData = new Common.UI.Button({
cls: 'btn-toolbar x-huge icon-top',
iconCls: 'toolbar__icon btn-big-pivot-sum',
caption: 'Select Data',
lock : [_set.lostConnect, _set.coAuth, _set.editCell],
action: 'sheet-view',
dataHint : '1',
dataHintDirection: 'bottom',
dataHintOffset: 'small'
});
this.lockedControls.push(this.btnSelectData);
this.btnSwitchRowsCols = new Common.UI.Button({
cls: 'btn-toolbar x-huge icon-top',
iconCls: 'toolbar__icon btn-big-slicer',
caption: 'Switch Row / Column',
lock : [_set.lostConnect, _set.coAuth, _set.editCell],
action: 'sheet-view',
dataHint : '1',
dataHintDirection: 'bottom',
dataHintOffset: 'small'
});
this.lockedControls.push(this.btnSwitchRowsCols);
this.chartStyles = new Common.UI.ComboDataView({
cls : 'combo-chart-template',
style : 'min-width: 103px; max-width: 517px;',
enableKeyEvents : true,
itemWidth : 50,
itemHeight : 50,
menuMaxHeight : 300,
groups : new Common.UI.DataViewGroupStore(),
autoWidth : true,
lock: [_set.editCell, _set.selRangeEdit, _set.lostConnect, _set.coAuth, _set.wsLock, _set.cantModifyFilter],
beforeOpenHandler: function(e) {
var cmp = this,
menu = cmp.openButton.menu,
columnCount = 7;
if (menu.cmpEl) {
var itemEl = $(cmp.cmpEl.find('.dataview.inner .style').get(0)).parent();
var itemMargin = 8;
var itemWidth = itemEl.is(':visible') ? parseFloat(itemEl.css('width')) :
(cmp.itemWidth + parseFloat(itemEl.css('padding-left')) + parseFloat(itemEl.css('padding-right')) +
parseFloat(itemEl.css('border-left-width')) + parseFloat(itemEl.css('border-right-width')));
menu.menuAlignEl = cmp.cmpEl;
menu.menuAlign = 'tl-tl';
var menuWidth = columnCount * (itemMargin + itemWidth) + 17, // for scroller
buttonOffsetLeft = Common.Utils.getOffset(cmp.openButton.$el).left;
if (menuWidth>Common.Utils.innerWidth())
menuWidth = Math.max(Math.floor((Common.Utils.innerWidth()-17)/(itemMargin + itemWidth)), 2) * (itemMargin + itemWidth) + 17;
var offset = cmp.cmpEl.width() - cmp.openButton.$el.width() - Math.min(menuWidth, buttonOffsetLeft) - 1;
if (Common.UI.isRTL()) {
offset = cmp.openButton.$el.width() + parseFloat($(cmp.$el.find('.combo-dataview').get(0)).css('padding-left'));
}
menu.setOffset(Common.UI.isRTL() ? offset : Math.min(offset, 0));
menu.cmpEl.css({
'width': menuWidth,
'min-height': cmp.cmpEl.height()
});
}
},
dataHint: '1',
dataHintDirection: 'bottom',
dataHintOffset: '-16, 0'
});
this.lockedControls.push(this.chartStyles);
this.btnAdvancedSettings = new Common.UI.Button({
cls: 'btn-toolbar x-huge icon-top',
iconCls: 'toolbar__icon btn-day',
caption: 'Advanced Settings',
lock : [_set.lostConnect, _set.coAuth, _set.editCell],
action: 'sheet-view',
dataHint : '1',
dataHintDirection: 'bottom',
dataHintOffset: 'small'
});
this.lockedControls.push(this.btnAdvancedSettings);
this.spnWidth = new Common.UI.MetricSpinner({
el: $('#chart-spin-width'),
step: .1,
width: 78,
defaultUnit : "cm",
value: '3 cm',
maxValue: 55.88,
minValue: 0,
dataHint: '1',
dataHintDirection: 'bottom',
dataHintOffset: 'big',
ariaLabel: this.textWidth
});
this.lockedControls.push(this.spnWidth);
this.spnHeight = new Common.UI.MetricSpinner({
el: $('#chart-spin-height'),
step: .1,
width: 78,
defaultUnit : "cm",
value: '3 cm',
maxValue: 55.88,
minValue: 0,
dataHint: '1',
dataHintDirection: 'bottom',
dataHintOffset: 'big',
ariaLabel: this.textHeight
});
this.lockedControls.push(this.spnHeight);
this.chRatio = new Common.UI.CheckBox({
labelText: 'Constant Proportions',
value: true,
lock : [_set.lostConnect, _set.editCell],
dataHint : '1',
dataHintDirection: 'left',
dataHintOffset: 'small'
});
this.lockedControls.push(this.chRatio);
this.spnWidth.on('inputleave', function(){ Common.NotificationCenter.trigger('edit:complete', me);});
this.spnHeight.on('inputleave', function(){ Common.NotificationCenter.trigger('edit:complete', me);});
Common.UI.LayoutManager.addControls(this.lockedControls);
Common.NotificationCenter.on('app:ready', this.onAppReady.bind(this));
},
onCheckStyleChange: function(type, stateName, field, newValue, oldValue, eOpts) {
var me = this;
me.fireEvent('tabledesigntab:stylechange', [type, stateName, newValue]);
},
render: function (el) {
if ( el ) el.html( this.getPanel() );
return this;
},
getPanel: function () {
this.$el = $(_.template(template)( {} ));
var $host = this.$el;
this.btnChartElements && this.btnChartElements.render($host.find('#slot-btn-chart-elements'));
this.btnChartType && this.btnChartType.render($host.find('#slot-btn-chart-type'));
this.btnSelectData && this.btnSelectData.render($host.find('#slot-btn-select-data'));
this.btnSwitchRowsCols && this.btnSwitchRowsCols.render($host.find('#slot-btn-switch-rowscols'));
this.btnAdvancedSettings && this.btnAdvancedSettings.render($host.find('#slot-btn-chart-advanced-settings'));
this.chRatio && this.chRatio.render($host.find('#slot-chk-ratio'));
$host.find('#slot-lbl-width').text('Width');
$host.find('#slot-lbl-height').text('Height');
// this.btnRemDuplicates && this.btnRemDuplicates.render($host.find('#slot-btn-remove-duplicates'));
this.chartStyles.render(this.$el.find('#slot-field-chart-styles'));
return this.$el;
},
onAppReady: function (config) {
var me = this;
(new Promise(function (accept, reject) {
accept();
})).then(function(){
me.btnAdvancedSettings.updateHint('Advanced settings')
setEvents.call(me);
});
},
show: function () {
Common.UI.BaseView.prototype.show.call(this);
this.fireEvent('show', this);
},
getButtons: function(type) {
return this.lockedControls
},
SetDisabled: function (state) {
this.lockedControls && this.lockedControls.forEach(function(button) {
if ( button ) {
button.setDisabled(state);
}
}, this);
},
txtRowsCols: 'Rows & Columns',
tipRowsCols: 'Rows & Columns',
txtGroupTable_Custom: 'Custom',
txtGroupTable_Light: 'Light',
txtGroupTable_Medium: 'Medium',
txtGroupTable_Dark: 'Dark',
tipRemDuplicates: 'Removing duplicate lines from a sheet.',
tipConvertRange: 'Convert this table to a regular range of cells.',
tipInsertSlicer: 'Insert slicer',
tipInsertPivot: 'Insert Pivot Table',
tipHeaderRow: 'Show or hide the header row in a table.',
tipAltText: 'Set alternative title and description for a table.',
selectRowText: 'Select row',
selectColumnText: 'Select entire column',
selectColumnData: 'Select column data',
selectTableText: 'Select table',
insertRowAboveText: 'Insert row above',
insertRowBelowText: 'Insert row below',
insertColumnLeftText: 'Insert column left',
insertColumnRightText: 'Insert column right',
deleteRowText: 'Delete row',
deleteColumnText: 'Delete column',
deleteTableText: 'Delete table',
txtRemDuplicates: 'Remove duplicates',
txtConvertToRange: 'Convert to range',
txtSlicer: 'Slicer',
txtPivot: 'Pivot',
txtHeaderRow: 'Header row',
txtTotalRow: 'Total row',
txtFirstColumn: 'First column',
txtLastColumn: 'Last column',
txtBandedRows: 'Banded rows',
txtBandedColumns: 'Banded columns',
txtFilterButton: 'Filter button',
txtAltText: 'Alt text'
}
}()), SSE.Views.ChartTab || {}));
});

View File

@ -136,6 +136,7 @@ require([
'DataTab',
'ViewTab',
'TableDesignTab',
'ChartTab',
'Search',
'WBProtection',
'Common.Controllers.Fonts',
@ -175,6 +176,7 @@ require([
'spreadsheeteditor/main/app/controller/DataTab',
'spreadsheeteditor/main/app/controller/ViewTab',
'spreadsheeteditor/main/app/controller/TableDesignTab',
'spreadsheeteditor/main/app/controller/ChartTab',
'spreadsheeteditor/main/app/controller/Search',
'spreadsheeteditor/main/app/controller/WBProtection',
// 'spreadsheeteditor/main/app/view/ParagraphSettings',