/**
* The Navigator Container is a component used to lay out the chart and its
* {@link Ext.chart.navigator.Navigator navigator}, where the navigator is docked
* to the top/bottom, and the chart fills the rest of the container's space.
*
* For example:
*
* @example
* Ext.create({
* xtype: 'chartnavigator',
* renderTo: Ext.getBody(),
* width: 600,
* height: 400,
*
* chart: {
* xtype: 'cartesian',
*
* store: {
* data: (function () {
* var data = [];
* for (var i = 0; i < 360; i++) {
* data.push({
* x: i,
* y: Math.sin(i / 45 * Math.PI)
* });
* }
* return data;
* })()
* },
* axes: [
* {
* id: 'navigable-axis',
*
* type: 'numeric',
* position: 'bottom'
* },
* {
* type: 'numeric',
* position: 'left'
* }
* ],
* series: {
* type: 'line',
* xField: 'x',
* yField: 'y'
* }
* },
*
* navigator: {
* axis: 'navigable-axis'
* }
* });
*
*/
Ext.define('Ext.chart.navigator.Container', {
// We are interested in the docking functionality that's available in
// the Container in Modern and in the Panel in Classic.
extend: 'Ext.chart.navigator.ContainerBase',
requires: [
'Ext.chart.CartesianChart',
'Ext.chart.navigator.Navigator'
],
xtype: 'chartnavigator',
config: {
/**
* @cfg {Ext.chart.CartesianChart} chart
* The chart to make navigable.
*/
chart: null,
/**
* @cfg {Ext.chart.navigator.Navigator} navigator
*/
navigator: {}
},
layout: 'fit',
applyChart: function(chart, oldChart) {
if (oldChart) {
oldChart.destroy();
}
if (chart) {
if (chart.isCartesian) {
Ext.raise('Only cartesian charts are supported.');
}
if (!chart.isChart) {
chart.$initParent = this;
chart = new Ext.chart.CartesianChart(chart);
delete chart.$initParent;
}
}
return chart;
},
legendStore: null,
surfaceRects: null,
updateChart: function(chart, oldChart) {
var me = this;
if (chart) {
me.legendStore = chart.getLegendStore();
if (!me.items && me.initItems) {
me.initItems();
}
me.add(chart);
}
},
applyNavigator: function(navigator, oldNavigator) {
var instance;
if (oldNavigator) {
oldNavigator.destroy();
}
if (navigator) {
navigator.navigatorContainer = navigator.parent = this;
instance = new Ext.chart.navigator.Navigator(navigator);
}
return instance;
},
preview: function() {
this.getNavigator().preview(this.getImage());
},
download: function(config) {
config = config || {};
config.data = this.getImage().data;
this.getNavigator().download(config);
},
setVisibleRange: function(visibleRange) {
this.getNavigator().setVisibleRange(visibleRange);
},
getImage: function(format) {
var me = this,
chart = me.getChart(),
navigator = me.getNavigator(),
docked = navigator.getDocked(),
chartImageSize = chart.bodyElement.getSize(),
navigatorImageSize = navigator.bodyElement.getSize(),
chartSurfaces = chart.getSurfaces(true),
navigatorSurfaces = navigator.getSurfaces(true),
size = {
width: chartImageSize.width,
height: chartImageSize.height + navigatorImageSize.height
},
image, imageElement,
surfaces, surface;
if (docked === 'top') {
me.shiftSurfaces(chartSurfaces, 0, navigatorImageSize.height);
}
else {
me.shiftSurfaces(navigatorSurfaces, 0, chartImageSize.height);
}
surfaces = chartSurfaces.concat(navigatorSurfaces);
surface = surfaces[0];
if ((Ext.isIE || Ext.isEdge) && surface.isSVG) {
// SVG data URLs don't work in IE/Edge as a source for an 'img' element,
// so we need to render SVG the usual way.
image = {
data: surface.toSVG(size, surfaces),
type: 'svg-markup'
};
}
else {
image = surface.flatten(size, surfaces);
if (format === 'image') {
imageElement = new Image();
imageElement.src = image.data;
image.data = imageElement;
return image;
}
if (format === 'stream') {
image.data = image.data.replace(/^data:image\/[^;]+/, 'data:application/octet-stream');
return image;
}
}
me.unshiftSurfaces(surfaces);
return image;
},
shiftSurfaces: function(surfaces, x, y) {
var ln = surfaces.length,
i = 0,
surface;
this.surfaceRects = {};
for (; i < ln; i++) {
surface = surfaces[i];
this.shiftSurface(surface, x, y);
}
},
shiftSurface: function(surface, x, y) {
var rect = surface.getRect();
this.surfaceRects[surface.getId()] = rect.slice();
rect[0] += x;
rect[1] += y;
},
unshiftSurfaces: function(surfaces) {
var rects = this.surfaceRects,
ln = surfaces.length,
i = 0,
surface, rect, oldRect;
if (rects) {
for (; i < ln; i++) {
surface = surfaces[i];
rect = surface.getRect();
oldRect = rects[surface.getId()];
if (oldRect) {
rect[0] = oldRect[0];
rect[1] = oldRect[1];
}
}
}
this.surfaceRects = null;
}
});