| OLD | NEW |
| 1 // | 1 // |
| 2 // Copyright 2014 Google Inc. All rights reserved. | 2 // Copyright 2014 Google Inc. All rights reserved. |
| 3 // | 3 // |
| 4 // Use of this source code is governed by a BSD-style | 4 // Use of this source code is governed by a BSD-style |
| 5 // license that can be found in the LICENSE file or at | 5 // license that can be found in the LICENSE file or at |
| 6 // https://developers.google.com/open-source/licenses/bsd | 6 // https://developers.google.com/open-source/licenses/bsd |
| 7 // | 7 // |
| 8 | 8 |
| 9 part of charted.charts; | 9 part of charted.charts; |
| 10 | 10 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 scale.domain = domain; | 48 scale.domain = domain; |
| 49 scale.nice = !_isDimension; | 49 scale.nice = !_isDimension; |
| 50 } | 50 } |
| 51 } | 51 } |
| 52 | 52 |
| 53 void initAxisScale(Iterable range) { | 53 void initAxisScale(Iterable range) { |
| 54 assert(scale != null); | 54 assert(scale != null); |
| 55 if (scale is OrdinalScale) { | 55 if (scale is OrdinalScale) { |
| 56 var usingBands = _area.dimensionsUsingBands.contains(_column), | 56 var usingBands = _area.dimensionsUsingBands.contains(_column), |
| 57 innerPadding = usingBands ? _theme.axisBandInnerPadding : 1.0, | 57 innerPadding = usingBands ? _theme.axisBandInnerPadding : 1.0, |
| 58 outerPadding = usingBands ? | 58 outerPadding = |
| 59 _theme.axisBandOuterPadding : _theme.axisOuterPadding; | 59 usingBands ? _theme.axisBandOuterPadding : _theme.axisOuterPadding; |
| 60 | 60 |
| 61 // This is because when left axis is primary the first data row should | 61 // This is because when left axis is primary the first data row should |
| 62 // appear on top of the y-axis instead of on bottom. | 62 // appear on top of the y-axis instead of on bottom. |
| 63 if (_area.config.isLeftAxisPrimary) { | 63 if (_area.config.isLeftAxisPrimary) { |
| 64 range = range.toList().reversed; | 64 range = range.toList().reversed; |
| 65 } | 65 } |
| 66 (scale as OrdinalScale). | 66 (scale as OrdinalScale) |
| 67 rangeRoundBands(range, innerPadding, outerPadding); | 67 .rangeRoundBands(range, innerPadding, outerPadding); |
| 68 } else { | 68 } else { |
| 69 scale.range = range; | 69 scale.range = range; |
| 70 scale.ticksCount = _theme.axisTickCount; | 70 scale.ticksCount = _theme.axisTickCount; |
| 71 } | 71 } |
| 72 } | 72 } |
| 73 | 73 |
| 74 void prepareToDraw(String orientation) { | 74 void prepareToDraw(String orientation) { |
| 75 if (orientation == null) orientation = ORIENTATION_BOTTOM; | 75 if (orientation == null) orientation = ORIENTATION_BOTTOM; |
| 76 _orientation = orientation; | 76 _orientation = orientation; |
| 77 _isVertical = | 77 _isVertical = |
| (...skipping 12 matching lines...) Expand all Loading... |
| 90 formatter = _columnSpec.formatter == null | 90 formatter = _columnSpec.formatter == null |
| 91 ? scale.createTickFormatter() | 91 ? scale.createTickFormatter() |
| 92 : _columnSpec.formatter, | 92 : _columnSpec.formatter, |
| 93 textMetrics = new TextMetrics(fontStyle: _theme.ticksFont), | 93 textMetrics = new TextMetrics(fontStyle: _theme.ticksFont), |
| 94 formattedTicks = ticks.map((x) => formatter(x)).toList(), | 94 formattedTicks = ticks.map((x) => formatter(x)).toList(), |
| 95 shortenedTicks = formattedTicks; | 95 shortenedTicks = formattedTicks; |
| 96 | 96 |
| 97 var width = textMetrics.getLongestTextWidth(formattedTicks).ceil(); | 97 var width = textMetrics.getLongestTextWidth(formattedTicks).ceil(); |
| 98 if (width > _theme.verticalAxisWidth) { | 98 if (width > _theme.verticalAxisWidth) { |
| 99 width = _theme.verticalAxisWidth; | 99 width = _theme.verticalAxisWidth; |
| 100 shortenedTicks = formattedTicks.map( | 100 shortenedTicks = formattedTicks |
| 101 (x) => textMetrics.ellipsizeText(x, width)).toList(); | 101 .map((x) => textMetrics.ellipsizeText(x, width)) |
| 102 .toList(); |
| 102 } | 103 } |
| 103 if (_theme.verticalAxisAutoResize) { | 104 if (_theme.verticalAxisAutoResize) { |
| 104 size.width = | 105 size.width = |
| 105 width + _theme.axisTickPadding + math.max(_theme.axisTickSize, 0); | 106 width + _theme.axisTickPadding + math.max(_theme.axisTickSize, 0); |
| 106 } | 107 } |
| 107 _axisTicksPlacement = | 108 _axisTicksPlacement = |
| 108 new PrecomputedAxisTicks(ticks, formattedTicks, shortenedTicks); | 109 new PrecomputedAxisTicks(ticks, formattedTicks, shortenedTicks); |
| 109 } | 110 } |
| 110 } | 111 } |
| 111 | 112 |
| 112 void draw(Element element, SelectionScope scope, {bool preRender: false}) { | 113 void draw(Element element, SelectionScope scope, {bool preRender: false}) { |
| 113 assert(element != null && element is GElement); | 114 assert(element != null && element is GElement); |
| 114 assert(scale != null); | 115 assert(scale != null); |
| 115 | 116 |
| 116 var rect = _area.layout.axes[_orientation], | 117 var rect = _area.layout.axes[_orientation], |
| 117 renderAreaRect = _area.layout.renderArea, | 118 renderAreaRect = _area.layout.renderArea, |
| 118 range = _isVertical ? [rect.height, 0] : [0, rect.width], | 119 range = _isVertical ? [rect.height, 0] : [0, rect.width], |
| 119 innerTickSize = _theme.axisTickSize <= ChartAxisTheme.FILL_RENDER_AREA | 120 innerTickSize = _theme.axisTickSize <= ChartAxisTheme.FILL_RENDER_AREA |
| 120 ? 0 - (_isVertical ? renderAreaRect.width : renderAreaRect.height) | 121 ? 0 - (_isVertical ? renderAreaRect.width : renderAreaRect.height) |
| 121 : _theme.axisTickSize, | 122 : _theme.axisTickSize, |
| 122 tickValues = _config != null && !isNullOrEmpty(_config.tickValues) | 123 tickValues = _config != null && !isNullOrEmpty(_config.tickValues) |
| 123 ? _config.tickValues | 124 ? _config.tickValues |
| 124 : null; | 125 : null; |
| 125 | 126 |
| 126 element.attributes['transform'] = 'translate(${rect.x}, ${rect.y})'; | 127 element.attributes['transform'] = 'translate(${rect.x}, ${rect.y})'; |
| 127 | 128 |
| 128 if (!_isVertical) { | 129 if (!_isVertical) { |
| 129 _axisTicksPlacement = | 130 _axisTicksPlacement = new RotateHorizontalAxisTicks( |
| 130 new RotateHorizontalAxisTicks(rect, | 131 rect, _theme.ticksFont, _theme.axisTickSize + _theme.axisTickPadding); |
| 131 _theme.ticksFont, _theme.axisTickSize + _theme.axisTickPadding); | |
| 132 } | 132 } |
| 133 | 133 |
| 134 initAxisScale(range); | 134 initAxisScale(range); |
| 135 var axis = new SvgAxis(orientation: _orientation, | 135 var axis = new SvgAxis( |
| 136 innerTickSize: innerTickSize, outerTickSize: 0, | 136 orientation: _orientation, |
| 137 innerTickSize: innerTickSize, |
| 138 outerTickSize: 0, |
| 137 tickPadding: _theme.axisTickPadding, | 139 tickPadding: _theme.axisTickPadding, |
| 138 tickFormat: _columnSpec.formatter, tickValues: tickValues, | 140 tickFormat: _columnSpec.formatter, |
| 141 tickValues: tickValues, |
| 139 scale: scale); | 142 scale: scale); |
| 140 | 143 |
| 141 axis.create(element, scope, | 144 axis.create(element, scope, |
| 142 axisTicksBuilder: _axisTicksPlacement, isRTL: _area.config.isRTL); | 145 axisTicksBuilder: _axisTicksPlacement, isRTL: _area.config.isRTL); |
| 143 } | 146 } |
| 144 | 147 |
| 145 void clear() { | 148 void clear() {} |
| 146 } | |
| 147 | 149 |
| 148 // Scale passed through configuration takes precedence | 150 // Scale passed through configuration takes precedence |
| 149 Scale get scale => | 151 Scale get scale => |
| 150 (_config != null && _config.scale != null) ? _config.scale : _scale; | 152 (_config != null && _config.scale != null) ? _config.scale : _scale; |
| 151 | 153 |
| 152 set scale(Scale value) => _scale = value; | 154 set scale(Scale value) => _scale = value; |
| 153 } | 155 } |
| 154 | 156 |
| 155 class PrecomputedAxisTicks implements SvgAxisTicks { | 157 class PrecomputedAxisTicks implements SvgAxisTicks { |
| 156 final int rotation = 0; | 158 final int rotation = 0; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 168 final int tickLineLength; | 170 final int tickLineLength; |
| 169 | 171 |
| 170 int rotation = 0; | 172 int rotation = 0; |
| 171 Iterable ticks; | 173 Iterable ticks; |
| 172 Iterable formattedTicks; | 174 Iterable formattedTicks; |
| 173 Iterable shortenedTicks; | 175 Iterable shortenedTicks; |
| 174 | 176 |
| 175 RotateHorizontalAxisTicks(this.rect, this.ticksFont, this.tickLineLength); | 177 RotateHorizontalAxisTicks(this.rect, this.ticksFont, this.tickLineLength); |
| 176 | 178 |
| 177 void init(SvgAxis axis) { | 179 void init(SvgAxis axis) { |
| 178 assert( | 180 assert(axis.orientation == ORIENTATION_BOTTOM || |
| 179 axis.orientation == ORIENTATION_BOTTOM || | |
| 180 axis.orientation == ORIENTATION_TOP); | 181 axis.orientation == ORIENTATION_TOP); |
| 181 assert(ticksFont != null); | 182 assert(ticksFont != null); |
| 182 ticks = axis.tickValues; | 183 ticks = axis.tickValues; |
| 183 formattedTicks = ticks.map((x) => axis.tickFormat(x)).toList(); | 184 formattedTicks = ticks.map((x) => axis.tickFormat(x)).toList(); |
| 184 shortenedTicks = formattedTicks; | 185 shortenedTicks = formattedTicks; |
| 185 | 186 |
| 186 var range = axis.scale.rangeExtent, | 187 var range = axis.scale.rangeExtent, |
| 187 textMetrics = new TextMetrics(fontStyle: ticksFont), | 188 textMetrics = new TextMetrics(fontStyle: ticksFont), |
| 188 allowedWidth = (range.max - range.min) ~/ ticks.length, | 189 allowedWidth = (range.max - range.min) ~/ ticks.length, |
| 189 maxLabelWidth = textMetrics.getLongestTextWidth(formattedTicks); | 190 maxLabelWidth = textMetrics.getLongestTextWidth(formattedTicks); |
| 190 | 191 |
| 191 // Check if we need rotation | 192 // Check if we need rotation |
| 192 if (0.90 * allowedWidth < maxLabelWidth) { | 193 if (0.90 * allowedWidth < maxLabelWidth) { |
| 193 var rectHeight = tickLineLength > 0 | 194 var rectHeight = |
| 194 ? rect.height - tickLineLength | 195 tickLineLength > 0 ? rect.height - tickLineLength : rect.height; |
| 195 : rect.height; | |
| 196 rotation = 45; | 196 rotation = 45; |
| 197 | 197 |
| 198 // Check if we have enough space to render full chart | 198 // Check if we have enough space to render full chart |
| 199 allowedWidth = (1.4142 * (rectHeight)) - (textMetrics.fontSize / 1.4142); | 199 allowedWidth = (1.4142 * (rectHeight)) - (textMetrics.fontSize / 1.4142); |
| 200 if (maxLabelWidth > allowedWidth) { | 200 if (maxLabelWidth > allowedWidth) { |
| 201 shortenedTicks = formattedTicks.map( | 201 shortenedTicks = formattedTicks |
| 202 (x) => textMetrics.ellipsizeText(x, allowedWidth)).toList(); | 202 .map((x) => textMetrics.ellipsizeText(x, allowedWidth)) |
| 203 .toList(); |
| 203 } | 204 } |
| 204 } | 205 } |
| 205 } | 206 } |
| 206 } | 207 } |
| OLD | NEW |