jui.define("chart.grid.core", [ "util.base", "util.math", "chart.grid.draw2d", "chart.grid.draw3d" ],
function(_, math, Draw2D, Draw3D) {
/**
* @class chart.grid.core
* Grid Core 객체
* @extends chart.draw
* @abstract
*/
var CoreGrid = function() {
/**
* @method wrapper
* scale wrapper
*
* grid 의 x 좌표 값을 같은 형태로 가지고 오기 위한 wrapper 함수
*
* grid 속성에 key 가 있다면 key 의 속성값으로 실제 값을 처리
*
* @example
* // 그리드 속성에 키가 없을 때
* scale(0); // 0 인덱스에 대한 값 (block, radar)
* // grid 속성에 key 가 있을 때
* grid { key : "field" }
* scale(0) // field 값으로 scale 설정 (range, date)
*
* @protected
*/
this.wrapper = function(scale, key) {
return scale;
}
/**
* @method line
* theme 이 적용된 line 리턴
* @protected
* @param {ChartBuilder} chart
* @param {Object} attr
*/
this.line = function(attr) {
return this.chart.svg.line(_.extend({
x1 : 0,
y1 : 0,
x2 : 0,
y2 : 0,
stroke : this.color("gridBorderColor"),
"stroke-width" : this.chart.theme("gridBorderWidth"),
"stroke-dasharray" : this.chart.theme("gridBorderDashArray"),
"stroke-opacity" : this.chart.theme("gridBorderOpacity")
}, attr));
}
/**
* @method color
* grid 에서 color 를 위한 유틸리티 함수
* @param theme
* @return {Mixed}
*/
this.color = function(theme) {
var color = this.grid.color;
if (arguments.length == 3) {
return (color != null) ? this.chart.color(color) : this.chart.theme.apply(this.chart, arguments);
}
return (color != null) ? this.chart.color(color) : this.chart.theme(theme);
}
/**
* @method data
* get data for axis
* @protected
* @param {Number} index
* @param {String} field
*/
this.data = function(index, field) {
if(this.axis.data && this.axis.data[index]) {
return this.axis.data[index][field] || this.axis.data[index];
}
return this.axis.data || [];
}
this.getGridSize = function() {
var orient = this.grid.orient,
depth = this.axis.depth,
degree = this.axis.degree,
axis = (orient == "left" || orient == "right") ? this.axis.area("y") : this.axis.area("x"),
max = (orient == "left" || orient == "right") ? this.axis.area("height") : this.axis.area("width"),
start = axis,
size = max,
end = start + size;
var result = {
start: start,
size: size,
end: end
};
if(!this.axis.isFull3D()) {
if(depth > 0 || degree > 0) {
var radian = math.radian(360 - degree),
x2 = Math.cos(radian) * depth,
y2 = Math.sin(radian) * depth;
if(orient == "left") {
result.start = result.start - y2;
result.size = result.size - y2;
} else if(orient == "bottom") {
result.end = result.end - x2;
result.size = result.size - x2;
}
}
} else {
if(orient == "center") { // z축
result.start = 0;
result.size = depth;
result.end = depth;
}
}
return result;
}
/**
* @method getDefaultOffset
*
* get real size of grid
*
* @param {chart.builder} chart
* @param {Strng} orient
* @param {Object} grid 그리드 옵션
* @return {Object}
* @return {Number} return.start 시작 지점
* @return {Number} return.size 그리드 넓이 또는 높이
* @return {Number} return.end 마지막 지점
*/
this.getDefaultOffset = function() {
var orient = this.grid.orient,
area = this.axis.area();
var width = area.width,
height = area.height,
axis = (orient == "left" || orient == "right") ? area.y : area.x,
max = (orient == "left" || orient == "right") ? height : width,
start = axis,
size = max,
end = start + size;
return {
start: start,
size: size,
end: end
};
}
/**
* @method getTextRotate
* implement text rotate in grid text
* @protected
* @param {SVGElement} textElement
*/
this.getTextRotate = function(textElement) {
var rotate = this.grid.textRotate;
if (rotate == null) {
return textElement;
}
if (_.typeCheck("function", rotate)) {
rotate = rotate.apply(this.chart, [ textElement ]);
}
var x = textElement.attr("x");
var y = textElement.attr("y");
textElement.rotate(rotate, x, y);
return textElement;
}
this.getLineOption = function() {
var line = this.grid.line;
if (typeof line === "string") {
line = { type : line || "solid"}
} else if (typeof line === "number") {
line = { type : "solid", "stroke-width" : line }
} else if (typeof line !== "object") {
line = !!line;
if (line) {
line = { type : "solid" }
}
}
if (line && !line.type == "string") {
line.type = line.type.split(/ /g);
}
return line;
}
this.checkDrawLineY = function(index, isLast) {
var y = this.axis.get("y");
if(!y.hide) {
if (y.orient == "left" && index == 0 && !this.grid.realtime) {
return false;
} else if (y.orient == "right" && isLast) {
return false;
}
}
return true;
}
this.checkDrawLineX = function(index, isLast) {
var x = this.axis.get("x");
if (!x.hide) {
if (x.orient == "top" && index == 0) {
return false;
} else if (x.orient == "bottom" && isLast && !this.grid.realtime ) {
return false;
}
}
return true;
}
/**
* @method top
*
* draw top
*
* @param {chart.util.svg} g
* @param {Array} ticks
* @param {Array} values
* @param {Number} min
* @param {Function} checkActive
*/
this.drawTop = function(g, ticks, values, checkActive, moveX) {
for (var i = 0, len = ticks.length; i < len; i++) {
var domain = this.format(ticks[i], i),
x = values[i] - moveX,
isLast = (i == len - 1) && this.grid.type != "block",
isActive = false;
// 그리드 이미지 그리기
this.drawImage("top", g, ticks[i], i, x, 0);
// 도메인이 없으면 그리지 않음
if (!domain && domain !== 0) {
continue;
}
// 액티브 라인 체크
if (_.typeCheck("function", checkActive)) {
isActive = checkActive(ticks[i]);
}
var axis = this.createGridX("top", i, x, isActive, isLast);
this.drawValueText("top", axis, i, values[i], domain, moveX, isActive);
g.append(axis);
}
}
this.drawBottom = function(g, ticks, values, checkActive, moveX) {
for (var i = 0, len = ticks.length; i < len; i++) {
var domain = this.format(ticks[i], i),
x = values[i] - moveX,
isLast = (i == len - 1) && this.grid.type != "block",
isActive = false;
// 그리드 이미지 그리기
this.drawImage("bottom", g, ticks[i], i, x, 0);
// 도메인이 없으면 그리지 않음
if (!domain && domain !== 0) {
continue;
}
// 액티브 라인 체크
if (_.typeCheck("function", checkActive)) {
isActive = checkActive(ticks[i]);
}
var axis = this.createGridX("bottom", i, x, isActive, isLast);
this.drawValueText("bottom", axis, i, values[i], domain, moveX, isActive);
g.append(axis);
}
}
this.drawLeft = function(g, ticks, values, checkActive, moveY) {
for (var i = 0, len = ticks.length; i < len; i++) {
var domain = this.format(ticks[i], i),
y = values[i] - moveY,
isLast = (i == len - 1) && this.grid.type != "block",
isActive = false;
// 그리드 이미지 그리기
this.drawImage("left", g, ticks[i], i, 0, y);
// 도메인이 없으면 그리지 않음
if (!domain && domain !== 0) {
continue;
}
// 액티브 라인 체크
if (_.typeCheck("function", checkActive)) {
isActive = checkActive(ticks[i]);
}
var axis = this.createGridY("left", i, y, isActive, isLast);
this.drawValueText("left", axis, i, values[i], domain, moveY, isActive);
g.append(axis);
}
}
this.drawRight = function(g, ticks, values, checkActive, moveY) {
for (var i = 0, len = ticks.length; i < len; i++) {
var domain = this.format(ticks[i], i),
y = values[i] - moveY,
isLast = (i == len - 1) && this.grid.type != "block",
isActive = false;
// 그리드 이미지 그리기
this.drawImage("right", g, ticks[i], i, 0, y);
// 도메인이 없으면 그리지 않음
if (!domain && domain !== 0) {
continue;
}
// 액티브 라인 체크
if (_.typeCheck("function", checkActive)) {
isActive = checkActive(ticks[i]);
}
var axis = this.createGridY("right", i, y, isActive, isLast);
this.drawValueText("right", axis, i, values[i], domain, moveY, isActive);
g.append(axis);
}
}
/**
* @method drawGrid
* draw base grid structure
* @protected
* @param {chart.builder} chart
* @param {String} orient
* @param {String} cls
* @param {Grid} grid
*/
this.drawGrid = function() {
// create group
var root = this.chart.svg.group(),
func = this[this.grid.orient],
draw = (this.axis.isFull3D()) ? Draw3D : Draw2D;
// wrapped scale
this.scale = this.wrapper(this.scale, this.grid.key);
// render axis
if(_.typeCheck("function", func)) {
draw.call(this);
func.call(this, root);
}
// hide grid
if(this.grid.hide) {
root.attr({ display : "none" })
}
return {
root : root,
scale : this.scale
};
}
/**
* @method drawAfter
*
* @param {Object} obj
* @protected
*/
this.drawAfter = function(obj) {
obj.root.attr({ "class" : "grid-" + this.grid.type });
obj.root.translate(this.chart.area("x") , this.chart.area("y"));
}
}
CoreGrid.setup = function() {
/** @property {chart.builder} chart */
/** @property {chart.axis} axis */
/** @property {Object} grid */
return {
/** @cfg {Number} [dist=0] Able to change the locatn of an axis. */
dist: 0,
/** @cfg {"top"/"left"/"bottom"/"right"} [orient=null] Specifies the direction in which an axis is shown (top, bottom, left or right). */
orient: null,
/** @cfg {Boolean} [hide=false] Determines whether to display an applicable grid. */
hide: false,
/** @cfg {String/Object/Number} [color=null] Specifies the color of a grid. */
color: null,
/** @cfg {String} [title=null] Specifies the text shown on a grid.*/
title: null,
/** @cfg {Boolean} [hide=false] Determines whether to display a line on the axis background. */
line: false,
/** @cfg {Function} [format=null] Determines whether to format the value on an axis. */
format: null,
/** @cfg {Function} [image=null] Determines whether to image the value on an axis. */
image: null,
/** @cfg {Number} [textRotate=null] Specifies the slope of text displayed on a grid. */
textRotate : null
};
}
return CoreGrid;
}, "chart.draw");