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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 LayoutRenderer _renderer; | 53 LayoutRenderer _renderer; |
54 | 54 |
55 bool _pendingLegendUpdate = false; | 55 bool _pendingLegendUpdate = false; |
56 List<ChartBehavior> _behaviors = new List<ChartBehavior>(); | 56 List<ChartBehavior> _behaviors = new List<ChartBehavior>(); |
57 | 57 |
58 SubscriptionsDisposer _rendererDisposer = new SubscriptionsDisposer(); | 58 SubscriptionsDisposer _rendererDisposer = new SubscriptionsDisposer(); |
59 StreamController<ChartEvent> _valueMouseOverController; | 59 StreamController<ChartEvent> _valueMouseOverController; |
60 StreamController<ChartEvent> _valueMouseOutController; | 60 StreamController<ChartEvent> _valueMouseOutController; |
61 StreamController<ChartEvent> _valueMouseClickController; | 61 StreamController<ChartEvent> _valueMouseClickController; |
62 | 62 |
63 DefaultLayoutAreaImpl( | 63 DefaultLayoutAreaImpl(this.host, ChartData data, ChartConfig config, |
64 this.host, | 64 this._autoUpdate, this.state) { |
65 ChartData data, | |
66 ChartConfig config, | |
67 this._autoUpdate, | |
68 this.state) { | |
69 assert(host != null); | 65 assert(host != null); |
70 assert(isNotInline(host)); | 66 assert(isNotInline(host)); |
71 | 67 |
72 this.data = data; | 68 this.data = data; |
73 this.config = config; | 69 this.config = config; |
74 theme = new QuantumChartTheme(); | 70 theme = new QuantumChartTheme(); |
75 | 71 |
76 Transition.defaultEasingType = theme.transitionEasingType; | 72 Transition.defaultEasingType = theme.transitionEasingType; |
77 Transition.defaultEasingMode = theme.transitionEasingMode; | 73 Transition.defaultEasingMode = theme.transitionEasingMode; |
78 Transition.defaultDurationMilliseconds = | 74 Transition.defaultDurationMilliseconds = |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 this.config = _config; | 128 this.config = _config; |
133 } | 129 } |
134 } | 130 } |
135 | 131 |
136 @override | 132 @override |
137 bool get autoUpdate => _autoUpdate; | 133 bool get autoUpdate => _autoUpdate; |
138 | 134 |
139 /// Computes the size of chart and if changed from the previous time | 135 /// Computes the size of chart and if changed from the previous time |
140 /// size was computed, sets attributes on svg element | 136 /// size was computed, sets attributes on svg element |
141 Rect _computeChartSize() { | 137 Rect _computeChartSize() { |
142 int width = host.clientWidth, | 138 int width = host.clientWidth, height = host.clientHeight; |
143 height = host.clientHeight; | |
144 | 139 |
145 if (config.minimumSize != null) { | 140 if (config.minimumSize != null) { |
146 width = max([width, config.minimumSize.width]); | 141 width = max([width, config.minimumSize.width]); |
147 height = max([height, config.minimumSize.height]); | 142 height = max([height, config.minimumSize.height]); |
148 } | 143 } |
149 | 144 |
150 AbsoluteRect padding = theme.padding; | 145 AbsoluteRect padding = theme.padding; |
151 num paddingLeft = config.isRTL ? padding.end : padding.start; | 146 num paddingLeft = config.isRTL ? padding.end : padding.start; |
152 Rect current = new Rect(paddingLeft, padding.top, | 147 Rect current = new Rect( |
| 148 paddingLeft, |
| 149 padding.top, |
153 width - (padding.start + padding.end), | 150 width - (padding.start + padding.end), |
154 height - (padding.top + padding.bottom)); | 151 height - (padding.top + padding.bottom)); |
155 if (layout.chartArea == null || layout.chartArea != current) { | 152 if (layout.chartArea == null || layout.chartArea != current) { |
156 var transform = 'translate(${paddingLeft},${padding.top})'; | 153 var transform = 'translate(${paddingLeft},${padding.top})'; |
157 | 154 |
158 visualization.first.attributes['transform'] = transform; | 155 visualization.first.attributes['transform'] = transform; |
159 lowerBehaviorPane.first.attributes['transform'] = transform; | 156 lowerBehaviorPane.first.attributes['transform'] = transform; |
160 upperBehaviorPane.first.attributes['transform'] = transform; | 157 upperBehaviorPane.first.attributes['transform'] = transform; |
161 | 158 |
162 _svg.attr('width', width.toString()); | 159 _svg.attr('width', width.toString()); |
163 _svg.attr('height', height.toString()); | 160 _svg.attr('height', height.toString()); |
164 layout.chartArea = current; | 161 layout.chartArea = current; |
165 layout.renderArea = current; | 162 layout.renderArea = current; |
166 layout._axes.clear(); | 163 layout._axes.clear(); |
167 } | 164 } |
168 | 165 |
169 return layout.chartArea; | 166 return layout.chartArea; |
170 } | 167 } |
171 | 168 |
172 @override | 169 @override |
173 draw({bool preRender:false, Future schedulePostRender}) { | 170 draw({bool preRender: false, Future schedulePostRender}) { |
174 assert(data != null && config != null); | 171 assert(data != null && config != null); |
175 assert(config.series != null && config.series.isNotEmpty); | 172 assert(config.series != null && config.series.isNotEmpty); |
176 | 173 |
177 // One time initialization. | 174 // One time initialization. |
178 // Each [ChartArea] has it's own [SelectionScope] | 175 // Each [ChartArea] has it's own [SelectionScope] |
179 if (_scope == null) { | 176 if (_scope == null) { |
180 _scope = new SelectionScope.element(host); | 177 _scope = new SelectionScope.element(host); |
181 _svg = _scope.append('svg:svg')..classed('chart-canvas'); | 178 _svg = _scope.append('svg:svg')..classed('chart-canvas'); |
182 | 179 |
183 lowerBehaviorPane = _svg.append('g')..classed('lower-render-pane'); | 180 lowerBehaviorPane = _svg.append('g')..classed('lower-render-pane'); |
184 visualization = _svg.append('g')..classed('chart-render-pane'); | 181 visualization = _svg.append('g')..classed('chart-render-pane'); |
185 upperBehaviorPane = _svg.append('g')..classed('upper-render-pane'); | 182 upperBehaviorPane = _svg.append('g')..classed('upper-render-pane'); |
186 | 183 |
187 if (_behaviors.isNotEmpty) { | 184 if (_behaviors.isNotEmpty) { |
188 _behaviors.forEach( | 185 _behaviors |
189 (b) => b.init(this, upperBehaviorPane, lowerBehaviorPane)); | 186 .forEach((b) => b.init(this, upperBehaviorPane, lowerBehaviorPane)); |
190 } | 187 } |
191 } | 188 } |
192 | 189 |
193 // Compute chart sizes and filter out unsupported series | 190 // Compute chart sizes and filter out unsupported series |
194 _computeChartSize(); | 191 _computeChartSize(); |
195 var series = config.series.firstWhere( | 192 var series = config.series |
196 (s) => s.renderer.prepare(this, s), orElse: () => null), | 193 .firstWhere((s) => s.renderer.prepare(this, s), orElse: () => null), |
197 group = visualization.first.querySelector('.series-group'); | 194 group = visualization.first.querySelector('.series-group'); |
198 | 195 |
199 // We need atleast one matching series. | 196 // We need atleast one matching series. |
200 assert(series != null); | 197 assert(series != null); |
201 | 198 |
202 // Create a group for rendering, if it was not already done. | 199 // Create a group for rendering, if it was not already done. |
203 if (group == null) { | 200 if (group == null) { |
204 group = Namespace.createChildElement('g', visualization.first) | 201 group = Namespace.createChildElement('g', visualization.first) |
205 ..classes.add('series-group'); | 202 ..classes.add('series-group'); |
206 visualization.first.append(group); | 203 visualization.first.append(group); |
207 } | 204 } |
208 | 205 |
209 // If we previously displayed a series, verify that we are | 206 // If we previously displayed a series, verify that we are |
210 // still using the same renderer. Otherwise, dispose the older one. | 207 // still using the same renderer. Otherwise, dispose the older one. |
211 if (_renderer != null && series.renderer != _renderer) { | 208 if (_renderer != null && series.renderer != _renderer) { |
212 _rendererDisposer.dispose(); | 209 _rendererDisposer.dispose(); |
213 } | 210 } |
214 | 211 |
215 // Save and subscribe to events on the the current renderer. | 212 // Save and subscribe to events on the the current renderer. |
(...skipping 27 matching lines...) Expand all Loading... |
243 } | 240 } |
244 } | 241 } |
245 if (_valueMouseOutController != null) { | 242 if (_valueMouseOutController != null) { |
246 _valueMouseOutController.add(e); | 243 _valueMouseOutController.add(e); |
247 } | 244 } |
248 }) | 245 }) |
249 ]); | 246 ]); |
250 } | 247 } |
251 | 248 |
252 Iterable<ChartLegendItem> legend = | 249 Iterable<ChartLegendItem> legend = |
253 _renderer.layout(group, schedulePostRender:schedulePostRender); | 250 _renderer.layout(group, schedulePostRender: schedulePostRender); |
254 | 251 |
255 // Notify on the stream that the chart has been updated. | 252 // Notify on the stream that the chart has been updated. |
256 isReady = true; | 253 isReady = true; |
257 | 254 |
258 // Save the list of valid series and initialize axes. | 255 // Save the list of valid series and initialize axes. |
259 _series = series; | 256 _series = series; |
260 | 257 |
261 // Updates the legend if required. | 258 // Updates the legend if required. |
262 _config.legend.update(legend, this); | 259 if (_config.legend != null) { |
| 260 _config.legend.update(legend, this); |
| 261 } |
263 } | 262 } |
264 | 263 |
265 @override | 264 @override |
266 Stream<ChartEvent> get onMouseUp => | 265 Stream<ChartEvent> get onMouseUp => |
267 host.onMouseUp | 266 host.onMouseUp.map((MouseEvent e) => new DefaultChartEventImpl(e, this)); |
268 .map((MouseEvent e) => new DefaultChartEventImpl(e, this)); | |
269 | 267 |
270 @override | 268 @override |
271 Stream<ChartEvent> get onMouseDown => | 269 Stream<ChartEvent> get onMouseDown => host.onMouseDown |
272 host.onMouseDown | 270 .map((MouseEvent e) => new DefaultChartEventImpl(e, this)); |
273 .map((MouseEvent e) => new DefaultChartEventImpl(e, this)); | |
274 | 271 |
275 @override | 272 @override |
276 Stream<ChartEvent> get onMouseOver => | 273 Stream<ChartEvent> get onMouseOver => host.onMouseOver |
277 host.onMouseOver | 274 .map((MouseEvent e) => new DefaultChartEventImpl(e, this)); |
278 .map((MouseEvent e) => new DefaultChartEventImpl(e, this)); | |
279 | 275 |
280 @override | 276 @override |
281 Stream<ChartEvent> get onMouseOut => | 277 Stream<ChartEvent> get onMouseOut => |
282 host.onMouseOut | 278 host.onMouseOut.map((MouseEvent e) => new DefaultChartEventImpl(e, this)); |
283 .map((MouseEvent e) => new DefaultChartEventImpl(e, this)); | |
284 | 279 |
285 @override | 280 @override |
286 Stream<ChartEvent> get onMouseMove => | 281 Stream<ChartEvent> get onMouseMove => host.onMouseMove |
287 host.onMouseMove | 282 .map((MouseEvent e) => new DefaultChartEventImpl(e, this)); |
288 .map((MouseEvent e) => new DefaultChartEventImpl(e, this)); | |
289 | 283 |
290 @override | 284 @override |
291 Stream<ChartEvent> get onValueClick { | 285 Stream<ChartEvent> get onValueClick { |
292 if (_valueMouseClickController == null) { | 286 if (_valueMouseClickController == null) { |
293 _valueMouseClickController = new StreamController.broadcast(sync: true); | 287 _valueMouseClickController = new StreamController.broadcast(sync: true); |
294 } | 288 } |
295 return _valueMouseClickController.stream; | 289 return _valueMouseClickController.stream; |
296 } | 290 } |
297 | 291 |
298 @override | 292 @override |
(...skipping 23 matching lines...) Expand all Loading... |
322 | 316 |
323 @override | 317 @override |
324 void removeChartBehavior(ChartBehavior behavior) { | 318 void removeChartBehavior(ChartBehavior behavior) { |
325 if (behavior == null || !_behaviors.contains(behavior)) return; | 319 if (behavior == null || !_behaviors.contains(behavior)) return; |
326 if (upperBehaviorPane != null && lowerBehaviorPane != null) { | 320 if (upperBehaviorPane != null && lowerBehaviorPane != null) { |
327 behavior.dispose(); | 321 behavior.dispose(); |
328 } | 322 } |
329 _behaviors.remove(behavior); | 323 _behaviors.remove(behavior); |
330 } | 324 } |
331 } | 325 } |
OLD | NEW |