| 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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 _orientation = orientation; | 76 _orientation = orientation; |
| 77 _isVertical = | 77 _isVertical = |
| 78 _orientation == ORIENTATION_LEFT || _orientation == ORIENTATION_RIGHT; | 78 _orientation == ORIENTATION_LEFT || _orientation == ORIENTATION_RIGHT; |
| 79 | 79 |
| 80 var layout = _area.layout.chartArea; | 80 var layout = _area.layout.chartArea; |
| 81 size = _isVertical | 81 size = _isVertical |
| 82 ? new MutableRect.size(_theme.verticalAxisWidth, layout.width) | 82 ? new MutableRect.size(_theme.verticalAxisWidth, layout.width) |
| 83 : new MutableRect.size(layout.height, _theme.horizontalAxisHeight); | 83 : new MutableRect.size(layout.height, _theme.horizontalAxisHeight); |
| 84 | 84 |
| 85 // Handle auto re-sizing of horizontal axis. | 85 // Handle auto re-sizing of horizontal axis. |
| 86 var ticks = (_config != null && !isNullOrEmpty(_config.tickValues)) |
| 87 ? _config.tickValues |
| 88 : scale.ticks, |
| 89 formatter = _columnSpec.formatter == null |
| 90 ? scale.createTickFormatter() |
| 91 : _columnSpec.formatter, |
| 92 textMetrics = new TextMetrics(fontStyle: _theme.ticksFont), |
| 93 formattedTicks = ticks.map((x) => formatter(x)).toList(), |
| 94 shortenedTicks = formattedTicks; |
| 86 if (_isVertical) { | 95 if (_isVertical) { |
| 87 var ticks = (_config != null && !isNullOrEmpty(_config.tickValues)) | |
| 88 ? _config.tickValues | |
| 89 : scale.ticks, | |
| 90 formatter = _columnSpec.formatter == null | |
| 91 ? scale.createTickFormatter() | |
| 92 : _columnSpec.formatter, | |
| 93 textMetrics = new TextMetrics(fontStyle: _theme.ticksFont), | |
| 94 formattedTicks = ticks.map((x) => formatter(x)).toList(), | |
| 95 shortenedTicks = formattedTicks; | |
| 96 | |
| 97 var width = textMetrics.getLongestTextWidth(formattedTicks).ceil(); | 96 var width = textMetrics.getLongestTextWidth(formattedTicks).ceil(); |
| 98 if (width > _theme.verticalAxisWidth) { | 97 if (width > _theme.verticalAxisWidth) { |
| 99 width = _theme.verticalAxisWidth; | 98 width = _theme.verticalAxisWidth; |
| 100 shortenedTicks = formattedTicks | 99 shortenedTicks = formattedTicks |
| 101 .map((x) => textMetrics.ellipsizeText(x, width)) | 100 .map((x) => textMetrics.ellipsizeText(x, width)) |
| 102 .toList(); | 101 .toList(); |
| 103 } | 102 } |
| 104 if (_theme.verticalAxisAutoResize) { | 103 if (_theme.verticalAxisAutoResize) { |
| 105 size.width = | 104 size.width = |
| 106 width + _theme.axisTickPadding + math.max(_theme.axisTickSize, 0); | 105 width + _theme.axisTickPadding + math.max(_theme.axisTickSize, 0); |
| 107 } | 106 } |
| 107 |
| 108 _axisTicksPlacement = | 108 _axisTicksPlacement = |
| 109 new PrecomputedAxisTicks(ticks, formattedTicks, shortenedTicks); | 109 new PrecomputedAxisTicks(ticks, formattedTicks, shortenedTicks); |
| 110 } else { |
| 111 // Precompute if extra room is needed for rotated label. |
| 112 var width = layout.width - |
| 113 _area.layout.axes[ORIENTATION_LEFT].width - |
| 114 _area.layout.axes[ORIENTATION_RIGHT].width; |
| 115 var allowedWidth = width ~/ ticks.length, |
| 116 maxLabelWidth = textMetrics.getLongestTextWidth(formattedTicks); |
| 117 if (!RotateHorizontalAxisTicks.needsLabelRotation( |
| 118 allowedWidth, maxLabelWidth)) { |
| 119 size.height = textMetrics.fontSize * 2; |
| 120 } |
| 110 } | 121 } |
| 111 } | 122 } |
| 112 | 123 |
| 113 void draw(Element element, SelectionScope scope, {bool preRender: false}) { | 124 void draw(Element element, SelectionScope scope, {bool preRender: false}) { |
| 114 assert(element != null && element is GElement); | 125 assert(element != null && element is GElement); |
| 115 assert(scale != null); | 126 assert(scale != null); |
| 116 | 127 |
| 117 var rect = _area.layout.axes[_orientation], | 128 var rect = _area.layout.axes[_orientation], |
| 118 renderAreaRect = _area.layout.renderArea, | 129 renderAreaRect = _area.layout.renderArea, |
| 119 range = _isVertical ? [rect.height, 0] : [0, rect.width], | 130 range = _isVertical ? [rect.height, 0] : [0, rect.width], |
| (...skipping 24 matching lines...) Expand all Loading... |
| 144 axis.create(element, scope, | 155 axis.create(element, scope, |
| 145 axisTicksBuilder: _axisTicksPlacement, isRTL: _area.config.isRTL); | 156 axisTicksBuilder: _axisTicksPlacement, isRTL: _area.config.isRTL); |
| 146 } | 157 } |
| 147 | 158 |
| 148 void clear() {} | 159 void clear() {} |
| 149 | 160 |
| 150 // Scale passed through configuration takes precedence | 161 // Scale passed through configuration takes precedence |
| 151 Scale get scale => | 162 Scale get scale => |
| 152 (_config != null && _config.scale != null) ? _config.scale : _scale; | 163 (_config != null && _config.scale != null) ? _config.scale : _scale; |
| 153 | 164 |
| 154 set scale(Scale value) => _scale = value; | 165 set scale(Scale value) { |
| 166 _scale = value; |
| 167 } |
| 155 } | 168 } |
| 156 | 169 |
| 157 class PrecomputedAxisTicks implements SvgAxisTicks { | 170 class PrecomputedAxisTicks implements SvgAxisTicks { |
| 158 final int rotation = 0; | 171 final int rotation = 0; |
| 159 final Iterable ticks; | 172 final Iterable ticks; |
| 160 final Iterable formattedTicks; | 173 final Iterable formattedTicks; |
| 161 final Iterable shortenedTicks; | 174 final Iterable shortenedTicks; |
| 162 const PrecomputedAxisTicks( | 175 const PrecomputedAxisTicks( |
| 163 this.ticks, this.formattedTicks, this.shortenedTicks); | 176 this.ticks, this.formattedTicks, this.shortenedTicks); |
| 164 void init(SvgAxis axis) {} | 177 void init(SvgAxis axis) {} |
| 165 } | 178 } |
| 166 | 179 |
| 167 class RotateHorizontalAxisTicks implements SvgAxisTicks { | 180 class RotateHorizontalAxisTicks implements SvgAxisTicks { |
| 168 final Rect rect; | 181 final Rect rect; |
| 169 final String ticksFont; | 182 final String ticksFont; |
| 170 final int tickLineLength; | 183 final int tickLineLength; |
| 171 | 184 |
| 172 int rotation = 0; | 185 int rotation = 0; |
| 173 Iterable ticks; | 186 Iterable ticks; |
| 174 Iterable formattedTicks; | 187 Iterable<String> formattedTicks; |
| 175 Iterable shortenedTicks; | 188 Iterable shortenedTicks; |
| 176 | 189 |
| 177 RotateHorizontalAxisTicks(this.rect, this.ticksFont, this.tickLineLength); | 190 RotateHorizontalAxisTicks(this.rect, this.ticksFont, this.tickLineLength); |
| 178 | 191 |
| 192 static bool needsLabelRotation(num allowedWidth, num maxLabelWidth) => |
| 193 0.90 * allowedWidth < maxLabelWidth; |
| 194 |
| 179 void init(SvgAxis axis) { | 195 void init(SvgAxis axis) { |
| 180 assert(axis.orientation == ORIENTATION_BOTTOM || | 196 assert(axis.orientation == ORIENTATION_BOTTOM || |
| 181 axis.orientation == ORIENTATION_TOP); | 197 axis.orientation == ORIENTATION_TOP); |
| 182 assert(ticksFont != null); | 198 assert(ticksFont != null); |
| 183 ticks = axis.tickValues; | 199 ticks = axis.tickValues; |
| 184 formattedTicks = ticks.map((x) => axis.tickFormat(x)).toList(); | 200 formattedTicks = ticks.map((x) => axis.tickFormat(x)).toList(); |
| 185 shortenedTicks = formattedTicks; | 201 shortenedTicks = formattedTicks; |
| 186 | 202 |
| 187 var range = axis.scale.rangeExtent, | 203 var range = axis.scale.rangeExtent, |
| 188 textMetrics = new TextMetrics(fontStyle: ticksFont), | 204 textMetrics = new TextMetrics(fontStyle: ticksFont), |
| 189 allowedWidth = (range.max - range.min) ~/ ticks.length, | 205 allowedWidth = (range.max - range.min) ~/ ticks.length, |
| 190 maxLabelWidth = textMetrics.getLongestTextWidth(formattedTicks); | 206 maxLabelWidth = textMetrics.getLongestTextWidth(formattedTicks); |
| 191 | 207 |
| 192 // Check if we need rotation | 208 // Check if we need rotation |
| 193 if (0.90 * allowedWidth < maxLabelWidth) { | 209 if (needsLabelRotation(allowedWidth, maxLabelWidth)) { |
| 194 var rectHeight = | 210 var rectHeight = |
| 195 tickLineLength > 0 ? rect.height - tickLineLength : rect.height; | 211 tickLineLength > 0 ? rect.height - tickLineLength : rect.height; |
| 196 rotation = 45; | 212 rotation = 45; |
| 197 | 213 |
| 198 // Check if we have enough space to render full chart | 214 // Check if we have enough space to render full chart |
| 199 allowedWidth = (1.4142 * (rectHeight)) - (textMetrics.fontSize / 1.4142); | 215 allowedWidth = (1.4142 * (rectHeight)) - (textMetrics.fontSize / 1.4142); |
| 200 if (maxLabelWidth > allowedWidth) { | 216 if (maxLabelWidth > allowedWidth) { |
| 201 shortenedTicks = formattedTicks | 217 shortenedTicks = formattedTicks |
| 202 .map((x) => textMetrics.ellipsizeText(x, allowedWidth)) | 218 .map((x) => textMetrics.ellipsizeText(x, allowedWidth)) |
| 203 .toList(); | 219 .toList(); |
| 204 } | 220 } |
| 205 } | 221 } |
| 206 } | 222 } |
| 207 } | 223 } |
| OLD | NEW |