import Ember from 'ember';
import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
import RequiresScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
import { normalizeScale } from 'ember-nf-graph/utils/nf/scale-utils';
import SelectableGraphic from 'ember-nf-graph/mixins/graph-selectable-graphic';
/**
A rectangle that plots using domain values from the graph. Uses an SVGPathElement
to plot the rectangle, to allow for rectangles with "negative" heights.
@namespace components
@class nf-svg-rect
@extends Ember.Component
@uses mixins.graph-has-graph-parent
@uses mixins.graph-requires-scale-source
@uses mixins.graph-selectable-graphic
*/
export default Ember.Component.extend(HasGraphParent, RequiresScaleSource, SelectableGraphic, {
tagName: 'path',
attributeBindings: ['d'],
classNameBindings: [':nf-svg-rect', 'selectable', 'selected'],
/**
The domain x value to place the rect at.
@property x
@default null
*/
x: null,
/**
The domain y value to place the rect at.
@property y
@default null
*/
y: null,
_width: 0,
/**
The width as a domain value. If xScale is ordinal,
then this value is the indice offset to which to draw the
rectangle. In other words, if it's `2`, then draw the rectangle
to two ordinals past whatever `x` is set to.
@property width
@type Number
@default 0
*/
width: Ember.computed(function(key, value) {
if(arguments.length > 1) {
this._width = +value;
}
return this._width;
}),
_height: 0,
/**
The height as a domain value. If the yScale is ordinal,
this value is the indice offset to which to draw the rectangle.
For example, if the height is `3` then draw the rectangle
to two ordinals passed whatever `y` is set to.
@property height
@type Number
@default 0
*/
height: Ember.computed(function(key, value) {
if(arguments.length > 1) {
this._height = +value;
}
return this._height;
}),
/**
The x value of the bottom right corner of the rectangle.
@property x1
@type Number
*/
x1: Ember.computed('width', 'x', 'xScale', function(){
var xScale = this.get('xScale');
var w = this.get('width');
var x = this.get('x');
if(xScale.rangeBands) {
var domain = xScale.domain();
var fromIndex = domain.indexOf(x);
var toIndex = fromIndex + w;
return normalizeScale(xScale, domain[toIndex]);
} else {
x = +x || 0;
return normalizeScale(xScale, w + x);
}
}),
/**
The y value of the bottom right corner of the rectangle
@property y1
@type Number
*/
y1: Ember.computed('height', 'y', 'yScale', function(){
var yScale = this.get('yScale');
var h = this.get('height');
var y = this.get('y');
if(yScale.rangeBands) {
var domain = yScale.domain();
var fromIndex = domain.indexOf(y);
var toIndex = fromIndex + h;
return normalizeScale(yScale, domain[toIndex]);
} else {
y = +y || 0;
return normalizeScale(yScale, h + y);
}
}),
/**
The x value of the top right corner of the rectangle
@property x0
@type Number
*/
x0: Ember.computed('x', 'xScale', function(){
return normalizeScale(this.get('xScale'), this.get('x'));
}),
/**
The y value of the top right corner of the rectangle.
@property y0
@type Number
*/
y0: Ember.computed('y', 'yScale', function() {
return normalizeScale(this.get('yScale'), this.get('y'));
}),
/**
The SVG path data for the rectangle
@property d
@type String
*/
d: Ember.computed('x0', 'y0', 'x1', 'y1', function(){
var x0 = this.get('x0');
var y0 = this.get('y0');
var x1 = this.get('x1');
var y1 = this.get('y1');
return `M${x0},${y0} L${x0},${y1} L${x1},${y1} L${x1},${y0} L${x0},${y0}`;
}),
/**
Click event handler. Toggles selected if selectable.
@method click
*/
click: function(){
if(this.get('selectable')) {
this.toggleProperty('selected');
}
}
});