Chromium Code Reviews

Side by Side Diff: charted/lib/charts/src/chart_axis_impl.dart

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
OLDNEW
(Empty)
1 //
2 // Copyright 2014 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 //
8
9 part of charted.charts;
10
11 class DefaultChartAxisImpl {
12 CartesianArea _area;
13 ChartAxisConfig _config;
14 ChartAxisTheme _theme;
15 SvgAxisTicks _axisTicksPlacement;
16
17 int _column;
18 bool _isDimension;
19 ChartColumnSpec _columnSpec;
20
21 bool _isVertical;
22 String _orientation;
23 Scale _scale;
24 SelectionScope _scope;
25
26 MutableRect size;
27
28 DefaultChartAxisImpl.withAxisConfig(this._area, this._config);
29 DefaultChartAxisImpl(this._area);
30
31 void initAxisDomain(int column, bool isDimension, Iterable domain) {
32 _columnSpec = _area.data.columns.elementAt(column);
33 _column = column;
34 _isDimension = isDimension;
35
36 // If we don't have a scale yet, create one.
37 if (scale == null) {
38 _scale = _columnSpec.createDefaultScale();
39 }
40
41 // We have the scale, get theme.
42 _theme = isDimension
43 ? _area.theme.getDimensionAxisTheme(scale)
44 : _area.theme.getMeasureAxisTheme(scale);
45
46 // Sets the domain if not using a custom scale.
47 if (_config == null || (_config != null && _config.scale == null)) {
48 scale.domain = domain;
49 scale.nice = !_isDimension;
50 }
51 }
52
53 void initAxisScale(Iterable range) {
54 assert(scale != null);
55 if (scale is OrdinalScale) {
56 var usingBands = _area.dimensionsUsingBands.contains(_column),
57 innerPadding = usingBands ? _theme.axisBandInnerPadding : 1.0,
58 outerPadding = usingBands ?
59 _theme.axisBandOuterPadding : _theme.axisOuterPadding;
60
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.
63 if (_area.config.isLeftAxisPrimary) {
64 range = range.toList().reversed;
65 }
66 (scale as OrdinalScale).
67 rangeRoundBands(range, innerPadding, outerPadding);
68 } else {
69 scale.range = range;
70 scale.ticksCount = _theme.axisTickCount;
71 }
72 }
73
74 void prepareToDraw(String orientation) {
75 if (orientation == null) orientation = ORIENTATION_BOTTOM;
76 _orientation = orientation;
77 _isVertical =
78 _orientation == ORIENTATION_LEFT || _orientation == ORIENTATION_RIGHT;
79
80 var layout = _area.layout.chartArea;
81 size = _isVertical
82 ? new MutableRect.size(_theme.verticalAxisWidth, layout.width)
83 : new MutableRect.size(layout.height, _theme.horizontalAxisHeight);
84
85 // Handle auto re-sizing of horizontal axis.
86 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();
98 if (width > _theme.verticalAxisWidth) {
99 width = _theme.verticalAxisWidth;
100 shortenedTicks = formattedTicks.map(
101 (x) => textMetrics.ellipsizeText(x, width)).toList();
102 }
103 if (_theme.verticalAxisAutoResize) {
104 size.width =
105 width + _theme.axisTickPadding + math.max(_theme.axisTickSize, 0);
106 }
107 _axisTicksPlacement =
108 new PrecomputedAxisTicks(ticks, formattedTicks, shortenedTicks);
109 }
110 }
111
112 void draw(Element element, SelectionScope scope, {bool preRender: false}) {
113 assert(element != null && element is GElement);
114 assert(scale != null);
115
116 var rect = _area.layout.axes[_orientation],
117 renderAreaRect = _area.layout.renderArea,
118 range = _isVertical ? [rect.height, 0] : [0, rect.width],
119 innerTickSize = _theme.axisTickSize <= ChartAxisTheme.FILL_RENDER_AREA
120 ? 0 - (_isVertical ? renderAreaRect.width : renderAreaRect.height)
121 : _theme.axisTickSize,
122 tickValues = _config != null && !isNullOrEmpty(_config.tickValues)
123 ? _config.tickValues
124 : null;
125
126 element.attributes['transform'] = 'translate(${rect.x}, ${rect.y})';
127
128 if (!_isVertical) {
129 _axisTicksPlacement =
130 new RotateHorizontalAxisTicks(rect,
131 _theme.ticksFont, _theme.axisTickSize + _theme.axisTickPadding);
132 }
133
134 initAxisScale(range);
135 var axis = new SvgAxis(orientation: _orientation,
136 innerTickSize: innerTickSize, outerTickSize: 0,
137 tickPadding: _theme.axisTickPadding,
138 tickFormat: _columnSpec.formatter, tickValues: tickValues,
139 scale: scale);
140
141 axis.create(element, scope,
142 axisTicksBuilder: _axisTicksPlacement, isRTL: _area.config.isRTL);
143 }
144
145 void clear() {
146 }
147
148 // Scale passed through configuration takes precedence
149 Scale get scale =>
150 (_config != null && _config.scale != null) ? _config.scale : _scale;
151
152 set scale(Scale value) => _scale = value;
153 }
154
155 class PrecomputedAxisTicks implements SvgAxisTicks {
156 final int rotation = 0;
157 final Iterable ticks;
158 final Iterable formattedTicks;
159 final Iterable shortenedTicks;
160 const PrecomputedAxisTicks(
161 this.ticks, this.formattedTicks, this.shortenedTicks);
162 void init(SvgAxis axis) {}
163 }
164
165 class RotateHorizontalAxisTicks implements SvgAxisTicks {
166 final Rect rect;
167 final String ticksFont;
168 final int tickLineLength;
169
170 int rotation = 0;
171 Iterable ticks;
172 Iterable formattedTicks;
173 Iterable shortenedTicks;
174
175 RotateHorizontalAxisTicks(this.rect, this.ticksFont, this.tickLineLength);
176
177 void init(SvgAxis axis) {
178 assert(
179 axis.orientation == ORIENTATION_BOTTOM ||
180 axis.orientation == ORIENTATION_TOP);
181 assert(ticksFont != null);
182 ticks = axis.tickValues;
183 formattedTicks = ticks.map((x) => axis.tickFormat(x)).toList();
184 shortenedTicks = formattedTicks;
185
186 var range = axis.scale.rangeExtent,
187 textMetrics = new TextMetrics(fontStyle: ticksFont),
188 allowedWidth = (range.max - range.min) ~/ ticks.length,
189 maxLabelWidth = textMetrics.getLongestTextWidth(formattedTicks);
190
191 // Check if we need rotation
192 if (0.90 * allowedWidth < maxLabelWidth) {
193 var rectHeight = tickLineLength > 0
194 ? rect.height - tickLineLength
195 : rect.height;
196 rotation = 45;
197
198 // Check if we have enough space to render full chart
199 allowedWidth = (1.4142 * (rectHeight)) - (textMetrics.fontSize / 1.4142);
200 if (maxLabelWidth > allowedWidth) {
201 shortenedTicks = formattedTicks.map(
202 (x) => textMetrics.ellipsizeText(x, allowedWidth)).toList();
203 }
204 }
205 }
206 }
OLDNEW
« no previous file with comments | « charted/lib/charts/src/cartesian_area_impl.dart ('k') | charted/lib/charts/src/chart_config_impl.dart » ('j') | no next file with comments »

Powered by Google App Engine