Index: charted/lib/charts/src/layout_area_impl.dart |
diff --git a/charted/lib/charts/src/layout_area_impl.dart b/charted/lib/charts/src/layout_area_impl.dart |
deleted file mode 100644 |
index cc4de21cee92f6be3c71b0f09b8d765fd9d65d8c..0000000000000000000000000000000000000000 |
--- a/charted/lib/charts/src/layout_area_impl.dart |
+++ /dev/null |
@@ -1,331 +0,0 @@ |
-// |
-// Copyright 2014 Google Inc. All rights reserved. |
-// |
-// Use of this source code is governed by a BSD-style |
-// license that can be found in the LICENSE file or at |
-// https://developers.google.com/open-source/licenses/bsd |
-// |
- |
-part of charted.charts; |
- |
-/// Creates an empty area and provides generic API for interaction with layout |
-/// based charts. |
-class DefaultLayoutAreaImpl implements LayoutArea { |
- /// Disposer for all change stream subscriptions related to data. |
- final _dataEventsDisposer = new SubscriptionsDisposer(); |
- |
- /// Disposer for all change stream subscriptions related to config. |
- final _configEventsDisposer = new SubscriptionsDisposer(); |
- |
- @override |
- final Element host; |
- |
- @override |
- final bool useRowColoring = true; |
- |
- @override |
- final ChartState state; |
- |
- @override |
- _ChartAreaLayout layout = new _ChartAreaLayout(); |
- |
- @override |
- Selection upperBehaviorPane; |
- |
- @override |
- Selection lowerBehaviorPane; |
- |
- @override |
- bool isReady = false; |
- |
- @override |
- ChartTheme theme; |
- |
- ChartData _data; |
- ChartConfig _config; |
- bool _autoUpdate = false; |
- |
- SelectionScope _scope; |
- Selection _svg; |
- Selection visualization; |
- |
- ChartSeries _series; |
- LayoutRenderer _renderer; |
- |
- bool _pendingLegendUpdate = false; |
- List<ChartBehavior> _behaviors = new List<ChartBehavior>(); |
- |
- SubscriptionsDisposer _rendererDisposer = new SubscriptionsDisposer(); |
- StreamController<ChartEvent> _valueMouseOverController; |
- StreamController<ChartEvent> _valueMouseOutController; |
- StreamController<ChartEvent> _valueMouseClickController; |
- |
- DefaultLayoutAreaImpl( |
- this.host, |
- ChartData data, |
- ChartConfig config, |
- this._autoUpdate, |
- this.state) { |
- assert(host != null); |
- assert(isNotInline(host)); |
- |
- this.data = data; |
- this.config = config; |
- theme = new QuantumChartTheme(); |
- |
- Transition.defaultEasingType = theme.transitionEasingType; |
- Transition.defaultEasingMode = theme.transitionEasingMode; |
- Transition.defaultDurationMilliseconds = |
- theme.transitionDurationMilliseconds; |
- } |
- |
- void dispose() { |
- _configEventsDisposer.dispose(); |
- _dataEventsDisposer.dispose(); |
- _config.legend.dispose(); |
- } |
- |
- static bool isNotInline(Element e) => |
- e != null && e.getComputedStyle().display != 'inline'; |
- |
- /// Set new data for this chart. If [value] is [Observable], subscribes to |
- /// changes and updates the chart when data changes. |
- @override |
- set data(ChartData value) { |
- _data = value; |
- _dataEventsDisposer.dispose(); |
- |
- if (autoUpdate && _data != null && _data is Observable) { |
- _dataEventsDisposer.add((_data as Observable).changes.listen((_) { |
- draw(); |
- })); |
- } |
- } |
- |
- @override |
- ChartData get data => _data; |
- |
- /// Set new config for this chart. If [value] is [Observable], subscribes to |
- /// changes and updates the chart when series or dimensions change. |
- @override |
- set config(ChartConfig value) { |
- _config = value; |
- _configEventsDisposer.dispose(); |
- _pendingLegendUpdate = true; |
- |
- if (_config != null && _config is Observable) { |
- _configEventsDisposer.add((_config as Observable).changes.listen((_) { |
- _pendingLegendUpdate = true; |
- draw(); |
- })); |
- } |
- } |
- |
- @override |
- ChartConfig get config => _config; |
- |
- @override |
- set autoUpdate(bool value) { |
- if (_autoUpdate != value) { |
- _autoUpdate = value; |
- this.data = _data; |
- this.config = _config; |
- } |
- } |
- |
- @override |
- bool get autoUpdate => _autoUpdate; |
- |
- /// Computes the size of chart and if changed from the previous time |
- /// size was computed, sets attributes on svg element |
- Rect _computeChartSize() { |
- int width = host.clientWidth, |
- height = host.clientHeight; |
- |
- if (config.minimumSize != null) { |
- width = max([width, config.minimumSize.width]); |
- height = max([height, config.minimumSize.height]); |
- } |
- |
- AbsoluteRect padding = theme.padding; |
- num paddingLeft = config.isRTL ? padding.end : padding.start; |
- Rect current = new Rect(paddingLeft, padding.top, |
- width - (padding.start + padding.end), |
- height - (padding.top + padding.bottom)); |
- if (layout.chartArea == null || layout.chartArea != current) { |
- var transform = 'translate(${paddingLeft},${padding.top})'; |
- |
- visualization.first.attributes['transform'] = transform; |
- lowerBehaviorPane.first.attributes['transform'] = transform; |
- upperBehaviorPane.first.attributes['transform'] = transform; |
- |
- _svg.attr('width', width.toString()); |
- _svg.attr('height', height.toString()); |
- layout.chartArea = current; |
- layout.renderArea = current; |
- layout._axes.clear(); |
- } |
- |
- return layout.chartArea; |
- } |
- |
- @override |
- draw({bool preRender:false, Future schedulePostRender}) { |
- assert(data != null && config != null); |
- assert(config.series != null && config.series.isNotEmpty); |
- |
- // One time initialization. |
- // Each [ChartArea] has it's own [SelectionScope] |
- if (_scope == null) { |
- _scope = new SelectionScope.element(host); |
- _svg = _scope.append('svg:svg')..classed('chart-canvas'); |
- |
- lowerBehaviorPane = _svg.append('g')..classed('lower-render-pane'); |
- visualization = _svg.append('g')..classed('chart-render-pane'); |
- upperBehaviorPane = _svg.append('g')..classed('upper-render-pane'); |
- |
- if (_behaviors.isNotEmpty) { |
- _behaviors.forEach( |
- (b) => b.init(this, upperBehaviorPane, lowerBehaviorPane)); |
- } |
- } |
- |
- // Compute chart sizes and filter out unsupported series |
- _computeChartSize(); |
- var series = config.series.firstWhere( |
- (s) => s.renderer.prepare(this, s), orElse: () => null), |
- group = visualization.first.querySelector('.series-group'); |
- |
- // We need atleast one matching series. |
- assert(series != null); |
- |
- // Create a group for rendering, if it was not already done. |
- if (group == null) { |
- group = Namespace.createChildElement('g', visualization.first) |
- ..classes.add('series-group'); |
- visualization.first.append(group); |
- } |
- |
- // If we previously displayed a series, verify that we are |
- // still using the same renderer. Otherwise, dispose the older one. |
- if (_renderer != null && series.renderer != _renderer) { |
- _rendererDisposer.dispose(); |
- } |
- |
- // Save and subscribe to events on the the current renderer. |
- _renderer = series.renderer; |
- if (_renderer is ChartRendererBehaviorSource) { |
- _rendererDisposer.addAll([ |
- _renderer.onValueClick.listen((ChartEvent e) { |
- if (state != null) { |
- if (state.isSelected(e.row)) { |
- state.unselect(e.row); |
- } else { |
- state.select(e.row); |
- } |
- } |
- if (_valueMouseClickController != null) { |
- _valueMouseClickController.add(e); |
- } |
- }), |
- _renderer.onValueMouseOver.listen((ChartEvent e) { |
- if (state != null) { |
- state.preview = e.row; |
- } |
- if (_valueMouseOverController != null) { |
- _valueMouseOverController.add(e); |
- } |
- }), |
- _renderer.onValueMouseOut.listen((ChartEvent e) { |
- if (state != null) { |
- if (e.row == state.preview) { |
- state.hovered = null; |
- } |
- } |
- if (_valueMouseOutController != null) { |
- _valueMouseOutController.add(e); |
- } |
- }) |
- ]); |
- } |
- |
- Iterable<ChartLegendItem> legend = |
- _renderer.layout(group, schedulePostRender:schedulePostRender); |
- |
- // Notify on the stream that the chart has been updated. |
- isReady = true; |
- |
- // Save the list of valid series and initialize axes. |
- _series = series; |
- |
- // Updates the legend if required. |
- _config.legend.update(legend, this); |
- } |
- |
- @override |
- Stream<ChartEvent> get onMouseUp => |
- host.onMouseUp |
- .map((MouseEvent e) => new DefaultChartEventImpl(e, this)); |
- |
- @override |
- Stream<ChartEvent> get onMouseDown => |
- host.onMouseDown |
- .map((MouseEvent e) => new DefaultChartEventImpl(e, this)); |
- |
- @override |
- Stream<ChartEvent> get onMouseOver => |
- host.onMouseOver |
- .map((MouseEvent e) => new DefaultChartEventImpl(e, this)); |
- |
- @override |
- Stream<ChartEvent> get onMouseOut => |
- host.onMouseOut |
- .map((MouseEvent e) => new DefaultChartEventImpl(e, this)); |
- |
- @override |
- Stream<ChartEvent> get onMouseMove => |
- host.onMouseMove |
- .map((MouseEvent e) => new DefaultChartEventImpl(e, this)); |
- |
- @override |
- Stream<ChartEvent> get onValueClick { |
- if (_valueMouseClickController == null) { |
- _valueMouseClickController = new StreamController.broadcast(sync: true); |
- } |
- return _valueMouseClickController.stream; |
- } |
- |
- @override |
- Stream<ChartEvent> get onValueMouseOver { |
- if (_valueMouseOverController == null) { |
- _valueMouseOverController = new StreamController.broadcast(sync: true); |
- } |
- return _valueMouseOverController.stream; |
- } |
- |
- @override |
- Stream<ChartEvent> get onValueMouseOut { |
- if (_valueMouseOutController == null) { |
- _valueMouseOutController = new StreamController.broadcast(sync: true); |
- } |
- return _valueMouseOutController.stream; |
- } |
- |
- @override |
- void addChartBehavior(ChartBehavior behavior) { |
- if (behavior == null || _behaviors.contains(behavior)) return; |
- _behaviors.add(behavior); |
- if (upperBehaviorPane != null && lowerBehaviorPane != null) { |
- behavior.init(this, upperBehaviorPane, lowerBehaviorPane); |
- } |
- } |
- |
- @override |
- void removeChartBehavior(ChartBehavior behavior) { |
- if (behavior == null || !_behaviors.contains(behavior)) return; |
- if (upperBehaviorPane != null && lowerBehaviorPane != null) { |
- behavior.dispose(); |
- } |
- _behaviors.remove(behavior); |
- } |
-} |