/** * RightAxisLayout contains algorithms for rendering a right axis. * * @class RightAxisLayout * @constructor * @submodule axis */ RightAxisLayout = function(){}; RightAxisLayout.prototype = { /** * Default margins for text fields. * * @private * @method _getDefaultMargins * @return Object */ _getDefaultMargins: function() { return { top: 0, left: 4, right: 0, bottom: 0 }; }, /** * Sets the length of the tick on either side of the axis line. * * @method setTickOffset * @protected */ setTickOffsets: function() { var host = this, majorTicks = host.get("styles").majorTicks, tickLength = majorTicks.length, halfTick = tickLength * 0.5, display = majorTicks.display; host.set("topTickOffset", 0); host.set("bottomTickOffset", 0); switch(display) { case "inside" : host.set("leftTickOffset", tickLength); host.set("rightTickOffset", 0); break; case "outside" : host.set("leftTickOffset", 0); host.set("rightTickOffset", tickLength); break; case "cross" : host.set("rightTickOffset", halfTick); host.set("leftTickOffset", halfTick); break; default: host.set("leftTickOffset", 0); host.set("rightTickOffset", 0); break; } }, /** * Draws a tick * * @method drawTick * @param {Path} path reference to the path `Path` element in which to draw the tick. * @param {Object} pt Point on the axis in which the tick will intersect. * @param {Object} tickStyle Hash of properties to apply to the tick. * @protected */ drawTick: function(path, pt, tickStyles) { var host = this, style = host.get("styles"), padding = style.padding, tickLength = tickStyles.length, start = {x:padding.left, y:pt.y}, end = {x:padding.left + tickLength, y:pt.y}; host.drawLine(path, start, end); }, /** * Calculates the coordinates for the first point on an axis. * * @method getLineStart * @return {Object} * @protected */ getLineStart: function() { var host = this, style = host.get("styles"), padding = style.padding, majorTicks = style.majorTicks, tickLength = majorTicks.length, display = majorTicks.display, pt = {x:padding.left, y:padding.top}; if(display === "inside") { pt.x += tickLength; } else if(display === "cross") { pt.x += tickLength/2; } return pt; }, /** * Calculates the point for a label. * * @method getLabelPoint * @param {Object} point Point on the axis in which the tick will intersect. * @return {Object} * @protected */ getLabelPoint: function(point) { return {x:point.x + this.get("rightTickOffset"), y:point.y}; }, /** * Updates the value for the `maxLabelSize` for use in calculating total size. * * @method updateMaxLabelSize * @param {HTMLElement} label to measure * @protected */ updateMaxLabelSize: function(labelWidth, labelHeight) { var host = this, props = this._labelRotationProps, rot = props.rot, absRot = props.absRot, sinRadians = props.sinRadians, cosRadians = props.cosRadians, max; if(rot === 0) { max = labelWidth; } else if(absRot === 90) { max = labelHeight; } else { max = (cosRadians * labelWidth) + (sinRadians * labelHeight); } host._maxLabelSize = Math.max(host._maxLabelSize, max); }, /** * Determines the available label width when the axis width has been explicitly set. * * @method getExplicitlySized * @return Boolean * @protected */ getExplicitlySized: function(styles) { if(this._explicitWidth) { var host = this, w = host._explicitWidth, totalTitleSize = this._totalTitleSize, rightTickOffset = host.get("rightTickOffset"), margin = styles.label.margin.right; host._maxLabelSize = w - (rightTickOffset + margin + totalTitleSize); return true; } return false; }, /** * Rotate and position title. * * @method positionTitle * @param {HTMLElement} label to rotate position * @protected */ positionTitle: function(label) { var host = this, bounds = host._titleBounds, margin = host.get("styles").title.margin, props = host._titleRotationProps, labelWidth = label.offsetWidth, labelHeight = label.offsetHeight, w = bounds.right - bounds.left, x = this.get("width") - (labelWidth * 0.5) - (w * 0.5), y = (host.get("height") * 0.5) - (labelHeight * 0.5); props.labelWidth = labelWidth; props.labelHeight = labelHeight; if(margin && margin.right) { x -= margin.left; } props.x = x; props.y = y; props.transformOrigin = [0.5, 0.5]; host._rotate(label, props); }, /** * Rotate and position labels. * * @method positionLabel * @param {HTMLElement} label to rotate position * @param {Object} pt hash containing the x and y coordinates in which the label will be positioned * against. * @protected */ positionLabel: function(label, pt, styles, i) { var host = this, offset = parseFloat(styles.label.offset), tickOffset = host.get("rightTickOffset"), labelStyles = styles.label, margin = 0, leftOffset = pt.x, topOffset = pt.y, props = this._labelRotationProps, rot = props.rot, absRot = props.absRot, labelWidth = this._labelWidths[i], labelHeight = this._labelHeights[i]; if(labelStyles.margin && labelStyles.margin.left) { margin = labelStyles.margin.left; } if(rot === 0) { topOffset -= labelHeight * offset; } else if(rot === 90) { leftOffset -= labelWidth * 0.5; topOffset = topOffset - labelHeight + labelWidth/2 - (labelWidth * offset); } else if(rot === -90) { topOffset = topOffset + labelWidth/2 - (labelWidth * offset); leftOffset -= labelWidth * 0.5; } else { topOffset -= labelHeight * offset; leftOffset += labelHeight/2 * absRot/90; } leftOffset += margin; leftOffset += tickOffset; props.labelWidth = labelWidth; props.labelHeight = labelHeight; props.x = Math.round(leftOffset); props.y = Math.round(topOffset); this._rotate(label, props); }, /** * Adjusts the coordinates of an axis label based on the rotation. * * @method _setRotationCoords * @param {Object} props Coordinates, dimension and rotation properties of the label. * @protected */ _setRotationCoords: function(props) { var rot = props.rot, absRot = props.absRot, leftOffset = 0, topOffset = 0, labelWidth = props.labelWidth, labelHeight = props.labelHeight; if(rot === 0) { topOffset = labelHeight * 0.5; } else if(rot === 90) { leftOffset = labelWidth * 0.5; topOffset = labelHeight; } else if(rot === -90) { leftOffset = labelWidth * 0.5; } else { topOffset = labelHeight * 0.5; leftOffset = labelHeight/2 * absRot/90; } props.x -= leftOffset; props.y -= topOffset; }, /** * Returns the transformOrigin to use for an axis label based on the position of the axis * and the rotation of the label. * * @method _getTransformOrigin * @param {Number} rot The rotation (in degrees) of the label. * @return Array * @protected */ _getTransformOrigin: function(rot) { var transformOrigin; if(rot === 0) { transformOrigin = [0, 0]; } else if(rot === 90) { transformOrigin = [0.5, 1]; } else if(rot === -90) { transformOrigin = [0.5, 0]; } else { transformOrigin = [0, 0.5]; } return transformOrigin; }, /** * Adjusts position for inner ticks. * * @method offsetNodeForTick * @param {Node} cb contentBox of the axis * @protected */ offsetNodeForTick: function(cb) { var host = this, tickOffset = host.get("leftTickOffset"), offset = 0 - tickOffset; cb.setStyle("left", offset); }, /** * Assigns a height based on the size of the contents. * * @method setCalculatedSize * @protected */ setCalculatedSize: function() { var host = this, styles = host.get("styles"), labelStyle = styles.label, totalTitleSize = this._totalTitleSize, ttl = Math.round(host.get("rightTickOffset") + host._maxLabelSize + totalTitleSize + labelStyle.margin.left); if(this._explicitWidth) { ttl = this._explicitWidth; } host.set("calculatedWidth", ttl); host.get("contentBox").setStyle("width", ttl); } }; Y.RightAxisLayout = RightAxisLayout;