Skip to content

Commit cb75ada

Browse files
Gauge: skip core rerender on title change with same height (T1288122) (#29904)
1 parent 28dcc3f commit cb75ada

File tree

4 files changed

+149
-2
lines changed

4 files changed

+149
-2
lines changed

packages/devextreme/js/viz/gauges/bar_gauge.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,13 @@ export const dxBarGauge = BaseGauge.inherit({
520520

521521
_initialChanges: ['VALUES'],
522522

523+
_getChangesRequireCoreUpdate: function() {
524+
return [
525+
...this.callBase(),
526+
'LEGEND',
527+
];
528+
},
529+
523530
_change_NODES() {
524531
this._buildNodes();
525532
},

packages/devextreme/js/viz/gauges/base_gauge.js

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ export const BaseGauge = BaseWidget.inherit({
1919

2020
_themeSection: 'gauge',
2121

22+
_titleBBoxCache: null,
23+
2224
_createThemeManager: function() {
2325
return new themeManagerModule.ThemeManager(this._getThemeManagerOptions());
2426
},
@@ -118,6 +120,33 @@ export const BaseGauge = BaseWidget.inherit({
118120
that.callBase.apply(that, arguments);
119121
},
120122

123+
_getChangesRequireCoreUpdate: function() {
124+
return ['DOMAIN', 'MOSTLY_TOTAL', 'EXPORT'];
125+
},
126+
127+
_isTitleBBoxChanged: function() {
128+
const titleBBox = this._title.getLayoutOptions();
129+
const hasTitleHeightChanged = titleBBox.height !== this._titleBBoxCache?.height;
130+
const hasTitleYChanged = titleBBox.y !== this._titleBBoxCache?.y;
131+
const hasVerticalAlignmentChanged = titleBBox.verticalAlignment !== this._titleBBoxCache?.verticalAlignment;
132+
133+
this._titleBBoxCache = null;
134+
135+
return hasTitleHeightChanged || hasTitleYChanged || hasVerticalAlignmentChanged;
136+
},
137+
138+
_forceCoreUpdate: function() {
139+
const isTriggeredByTitleOnly =
140+
this._changes.has('TITLE')
141+
&& !this._getChangesRequireCoreUpdate().some((change) => this._changes.has(change));
142+
143+
if(isTriggeredByTitleOnly) {
144+
return this._isTitleBBoxChanged();
145+
}
146+
147+
return true;
148+
},
149+
121150
_applySize: function(rect) {
122151
const that = this;
123152
///#DEBUG
@@ -131,8 +160,12 @@ export const BaseGauge = BaseWidget.inherit({
131160
// The appropriate solution is to remove heavy rendering from "_applySize" - it should be done later during some other change processing.
132161
// It would be even better to somehow defer any inside option changes - so they all are applied after all changes are processed.
133162
const layoutCache = that._layout._cache;
134-
that._cleanCore();
135-
that._renderCore();
163+
164+
if(that._forceCoreUpdate()) {
165+
that._cleanCore();
166+
that._renderCore();
167+
}
168+
136169
that._layout._cache = that._layout._cache || layoutCache;
137170
return [rect[0], that._innerRect.top, rect[2], that._innerRect.bottom];
138171
},
@@ -284,3 +317,14 @@ BaseGauge.prototype._setTooltipOptions = function() {
284317
_setTooltipOptions.apply(this, arguments);
285318
this._tracker && this._tracker.setTooltipState(this._tooltip.isEnabled());
286319
};
320+
321+
const { _change_TITLE } = BaseGauge.prototype;
322+
BaseGauge.prototype._change_TITLE = function() {
323+
this._titleBBoxCache = { ...this._title.getLayoutOptions() };
324+
325+
_change_TITLE.apply(this, arguments);
326+
327+
///#DEBUG
328+
this._DEBUG_change_title && this._DEBUG_change_title();
329+
///#ENDDEBUG
330+
};

packages/devextreme/testing/tests/DevExpress.viz.gauges/barGauge_new.tests.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import rendererModule from 'viz/core/renderers/renderer';
55
import titleModule from 'viz/core/title';
66
import tooltipModule from 'viz/core/tooltip';
77
import loadingIndicatorModule from 'viz/core/loading_indicator';
8+
import dxBarGauge from 'viz/bar_gauge';
89

910
import 'viz/gauges/bar_gauge';
1011

@@ -166,6 +167,11 @@ QUnit.module('Legend', {
166167
return this.renderer;
167168
});
168169

170+
dxBarGauge.prototype._debug_rendered = function() {
171+
this.renderCount = (this.renderCount || 0) + 1;
172+
this.rendered && this.rendered();
173+
};
174+
169175
legendModule._setLegend(sinon.spy(
170176
() => {
171177
const stub = new stubLegend();
@@ -184,6 +190,7 @@ QUnit.module('Legend', {
184190
afterEach() {
185191
legendModule._setLegend(Legend);
186192
rendererModule.Renderer.restore();
193+
delete dxBarGauge.prototype._debug_rendered;
187194
},
188195

189196
createGauge(options) {
@@ -317,6 +324,21 @@ QUnit.test('Format legend with custom type', function(assert) {
317324
assert.deepEqual(passedItems[0].text, '6K');
318325
});
319326

327+
QUnit.test('Legend update should call trigger core content rerender', function(assert) {
328+
const gauge = this.createGauge({
329+
values: [1, 2],
330+
legend: { visible: true }
331+
});
332+
333+
gauge._legend.stub('update').returns(true);
334+
335+
const initialRenderCount = gauge.renderCount;
336+
337+
gauge.values([10]);
338+
339+
assert.strictEqual(gauge.renderCount, initialRenderCount + 1);
340+
});
341+
320342
QUnit.module('Center Template', environment);
321343

322344
QUnit.test('Should create group for center template on widget creating', function(assert) {

packages/devextreme/testing/tests/DevExpress.viz.gauges/baseGauge.tests.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import registerComponent from 'core/component_registrator';
66
import resizeCallbacks from 'core/utils/resize_callbacks';
77
import { BaseGauge, formatValue, getSampleText } from 'viz/gauges/base_gauge';
88
import titleModule from 'viz/core/title';
9+
import exportModule from 'viz/core/export';
910
import loadingIndicatorModule from 'viz/core/loading_indicator';
1011
import rendererModule from 'viz/core/renderers/renderer';
1112
import tooltipModule from 'viz/core/tooltip';
@@ -584,3 +585,76 @@ QUnit.test('Should dispose graphic objects on container remove', function(assert
584585

585586
assert.strictEqual(gauge._graphicObjects, null);
586587
});
588+
589+
QUnit.module('Render content on LAYOUT change', {
590+
beforeEach: function() {
591+
environment.beforeEach.apply(this, arguments);
592+
const that = this;
593+
594+
this.export = new vizMocks.ExportMenu();
595+
exportModule.DEBUG_set_ExportMenu(sinon.spy(function() {
596+
return that.export;
597+
}));
598+
599+
this.title.stub('update').returns(true);
600+
},
601+
createGauge: environment.createGauge,
602+
afterEach: function() {
603+
this.export = null;
604+
delete BaseGauge.prototype._DEBUG_change_title;
605+
environment.afterEach.apply(this, arguments);
606+
}
607+
}, function() {
608+
[
609+
{ code: 'EXPORT', optionName: 'export.enabled', optionValue: true },
610+
{ code: 'DOMAIN', optionName: 'startValue', optionValue: 10 },
611+
{ code: 'MOSTLY_TOTAL', optionName: 'geometry.startAngle', optionValue: 180 },
612+
].forEach(({ code, optionName, optionValue }) => {
613+
QUnit.test(`Should call _renderContent method if '${code}' trigger layout change`, function(assert) {
614+
const gauge = this.createGauge();
615+
616+
const _renderContent = this.abstractMethods._renderContent;
617+
const initialRenderCount = _renderContent.callCount;
618+
619+
gauge.option(optionName, optionValue);
620+
621+
assert.strictEqual(_renderContent.callCount, initialRenderCount + 1);
622+
});
623+
});
624+
625+
const initialTitleBBox = {
626+
x: 1,
627+
y: 2,
628+
width: 20,
629+
height: 10,
630+
verticalAlignment: 'top',
631+
};
632+
633+
[
634+
{ update: true, changes: { verticalAlignment: 'bottom' } },
635+
{ update: true, changes: { y: 5 } },
636+
{ update: true, changes: { height: 20 } },
637+
{ update: false, changes: { width: 10 } },
638+
].forEach(({ update, changes }) => {
639+
QUnit.test(`Should ${update ? 'call' : 'not call' } _renderContent method if 'TITLE' trigger layout change and '${Object.keys(changes).join(', ')}' changed (T1288122)`, function(assert) {
640+
this.title.stub('getLayoutOptions').returns(initialTitleBBox);
641+
642+
const gauge = this.createGauge();
643+
644+
BaseGauge.prototype._DEBUG_change_title = ()=> {
645+
this.title.stub('getLayoutOptions').returns({
646+
...initialTitleBBox,
647+
...changes,
648+
});
649+
};
650+
651+
const _renderContent = this.abstractMethods._renderContent;
652+
const initialRenderCount = _renderContent.callCount;
653+
const expectedRenderCount = update ? initialRenderCount + 1 : initialRenderCount;
654+
655+
gauge.option('title.text', 'test');
656+
657+
assert.strictEqual(_renderContent.callCount, expectedRenderCount);
658+
});
659+
});
660+
});

0 commit comments

Comments
 (0)