blob: 6e210a8d5e8b3485d0fe84bb08e5c47bc220dad7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import * as echarts from '../../echarts';
import * as zrUtil from 'zrender/src/core/util';
import * as textContain from 'zrender/src/contain/text';
import * as featureManager from './featureManager';
import * as graphic from '../../util/graphic';
import Model from '../../model/Model';
import DataDiffer from '../../data/DataDiffer';
import * as listComponentHelper from '../helper/listComponent';
export default echarts.extendComponentView({
type: 'toolbox',
render: function (toolboxModel, ecModel, api, payload) {
var group = this.group;
group.removeAll();
if (!toolboxModel.get('show')) {
return;
}
var itemSize = +toolboxModel.get('itemSize');
var featureOpts = toolboxModel.get('feature') || {};
var features = this._features || (this._features = {});
var featureNames = [];
zrUtil.each(featureOpts, function (opt, name) {
featureNames.push(name);
});
new DataDiffer(this._featureNames || [], featureNames).add(processFeature).update(processFeature).remove(zrUtil.curry(processFeature, null)).execute(); // Keep for diff.
this._featureNames = featureNames;
function processFeature(newIndex, oldIndex) {
var featureName = featureNames[newIndex];
var oldName = featureNames[oldIndex];
var featureOpt = featureOpts[featureName];
var featureModel = new Model(featureOpt, toolboxModel, toolboxModel.ecModel);
var feature;
if (featureName && !oldName) {
// Create
if (isUserFeatureName(featureName)) {
feature = {
model: featureModel,
onclick: featureModel.option.onclick,
featureName: featureName
};
} else {
var Feature = featureManager.get(featureName);
if (!Feature) {
return;
}
feature = new Feature(featureModel, ecModel, api);
}
features[featureName] = feature;
} else {
feature = features[oldName]; // If feature does not exsit.
if (!feature) {
return;
}
feature.model = featureModel;
feature.ecModel = ecModel;
feature.api = api;
}
if (!featureName && oldName) {
feature.dispose && feature.dispose(ecModel, api);
return;
}
if (!featureModel.get('show') || feature.unusable) {
feature.remove && feature.remove(ecModel, api);
return;
}
createIconPaths(featureModel, feature, featureName);
featureModel.setIconStatus = function (iconName, status) {
var option = this.option;
var iconPaths = this.iconPaths;
option.iconStatus = option.iconStatus || {};
option.iconStatus[iconName] = status; // FIXME
iconPaths[iconName] && iconPaths[iconName].trigger(status);
};
if (feature.render) {
feature.render(featureModel, ecModel, api, payload);
}
}
function createIconPaths(featureModel, feature, featureName) {
var iconStyleModel = featureModel.getModel('iconStyle');
var iconStyleEmphasisModel = featureModel.getModel('emphasis.iconStyle'); // If one feature has mutiple icon. they are orginaized as
// {
// icon: {
// foo: '',
// bar: ''
// },
// title: {
// foo: '',
// bar: ''
// }
// }
var icons = feature.getIcons ? feature.getIcons() : featureModel.get('icon');
var titles = featureModel.get('title') || {};
if (typeof icons === 'string') {
var icon = icons;
var title = titles;
icons = {};
titles = {};
icons[featureName] = icon;
titles[featureName] = title;
}
var iconPaths = featureModel.iconPaths = {};
zrUtil.each(icons, function (iconStr, iconName) {
var path = graphic.createIcon(iconStr, {}, {
x: -itemSize / 2,
y: -itemSize / 2,
width: itemSize,
height: itemSize
});
path.setStyle(iconStyleModel.getItemStyle());
path.hoverStyle = iconStyleEmphasisModel.getItemStyle();
var tooltipModel = toolboxModel.getModel('tooltip');
if (tooltipModel && tooltipModel.get('show')) {
path.attr('tooltip', zrUtil.extend({
content: titles[iconName],
formatter: tooltipModel.get('formatter', true) || function () {
return titles[iconName];
},
formatterParams: {
componentType: 'toolbox',
name: iconName,
title: titles[iconName],
$vars: ['name', 'title']
},
position: tooltipModel.get('position', true) || 'bottom'
}, tooltipModel.option));
}
graphic.setHoverStyle(path);
if (toolboxModel.get('showTitle')) {
path.__title = titles[iconName];
path.on('mouseover', function () {
// Should not reuse above hoverStyle, which might be modified.
var hoverStyle = iconStyleEmphasisModel.getItemStyle();
path.setStyle({
text: titles[iconName],
textPosition: iconStyleEmphasisModel.get('textPosition') || 'bottom',
textFill: iconStyleEmphasisModel.get('textFill') || hoverStyle.fill || hoverStyle.stroke || '#000',
textAlign: iconStyleEmphasisModel.get('textAlign') || 'center',
textBackgroundColor: iconStyleEmphasisModel.get('textBackgroundColor'),
textBorderRadius: iconStyleEmphasisModel.get('textBorderRadius'),
textPadding: iconStyleEmphasisModel.get('textPadding')
});
}).on('mouseout', function () {
path.setStyle({
textFill: null,
textBackgroundColor: null
});
});
}
path.trigger(featureModel.get('iconStatus.' + iconName) || 'normal');
group.add(path);
path.on('click', zrUtil.bind(feature.onclick, feature, ecModel, api, iconName));
iconPaths[iconName] = path;
});
}
listComponentHelper.layout(group, toolboxModel, api); // Render background after group is layout
// FIXME
group.add(listComponentHelper.makeBackground(group.getBoundingRect(), toolboxModel)); // Adjust icon title positions to avoid them out of screen
group.eachChild(function (icon) {
var titleText = icon.__title;
var hoverStyle = icon.hoverStyle; // May be background element
if (hoverStyle && titleText) {
var rect = textContain.getBoundingRect(titleText, textContain.makeFont(hoverStyle));
var offsetX = icon.position[0] + group.position[0];
var offsetY = icon.position[1] + group.position[1] + itemSize;
var needPutOnTop = false;
if (offsetY + rect.height > api.getHeight()) {
hoverStyle.textPosition = 'top';
needPutOnTop = true;
}
var topOffset = needPutOnTop ? -5 - rect.height : itemSize + 8;
if (offsetX + rect.width / 2 > api.getWidth()) {
hoverStyle.textPosition = ['100%', topOffset];
hoverStyle.textAlign = 'right';
} else if (offsetX - rect.width / 2 < 0) {
hoverStyle.textPosition = [0, topOffset];
hoverStyle.textAlign = 'left';
}
}
});
},
updateView: function (toolboxModel, ecModel, api, payload) {
zrUtil.each(this._features, function (feature) {
feature.updateView && feature.updateView(feature.model, ecModel, api, payload);
});
},
// updateLayout: function (toolboxModel, ecModel, api, payload) {
// zrUtil.each(this._features, function (feature) {
// feature.updateLayout && feature.updateLayout(feature.model, ecModel, api, payload);
// });
// },
remove: function (ecModel, api) {
zrUtil.each(this._features, function (feature) {
feature.remove && feature.remove(ecModel, api);
});
this.group.removeAll();
},
dispose: function (ecModel, api) {
zrUtil.each(this._features, function (feature) {
feature.dispose && feature.dispose(ecModel, api);
});
}
});
function isUserFeatureName(featureName) {
return featureName.indexOf('my') === 0;
}