| 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 |
| 11 /// Displays either one or two dimension axes and zero or more measure axis. | 11 /// Displays either one or two dimension axes and zero or more measure axis. |
| 12 /// The number of measure axes displayed is zero in charts like bubble chart | 12 /// The number of measure axes displayed is zero in charts like bubble chart |
| 13 /// which contain two dimension axes. | 13 /// which contain two dimension axes. |
| 14 class DefaultCartesianAreaImpl implements CartesianArea { | 14 class DefaultCartesianAreaImpl implements CartesianArea { |
| 15 /// Default identifiers used by the measure axes | 15 /// Default identifiers used by the measure axes |
| 16 static const MEASURE_AXIS_IDS = const ['_default']; | 16 static const MEASURE_AXIS_IDS = const <String>['_default']; |
| 17 | 17 |
| 18 /// Orientations used by measure axes. First, when "x" axis is the primary | 18 /// Orientations used by measure axes. First, when "x" axis is the primary |
| 19 /// and the only dimension. Second, when "y" axis is the primary and the only | 19 /// and the only dimension. Second, when "y" axis is the primary and the only |
| 20 /// dimension. | 20 /// dimension. |
| 21 static const MEASURE_AXIS_ORIENTATIONS = const [ | 21 static const MEASURE_AXIS_ORIENTATIONS = const [ |
| 22 const [ORIENTATION_LEFT, ORIENTATION_RIGHT], | 22 const [ORIENTATION_LEFT, ORIENTATION_RIGHT], |
| 23 const [ORIENTATION_BOTTOM, ORIENTATION_TOP] | 23 const [ORIENTATION_BOTTOM, ORIENTATION_TOP] |
| 24 ]; | 24 ]; |
| 25 | 25 |
| 26 /// Orientations used by the dimension axes. First, when "x" is the | 26 /// Orientations used by the dimension axes. First, when "x" is the |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 | 110 |
| 111 Transition.defaultEasingType = theme.transitionEasingType; | 111 Transition.defaultEasingType = theme.transitionEasingType; |
| 112 Transition.defaultEasingMode = theme.transitionEasingMode; | 112 Transition.defaultEasingMode = theme.transitionEasingMode; |
| 113 Transition.defaultDurationMilliseconds = | 113 Transition.defaultDurationMilliseconds = |
| 114 theme.transitionDurationMilliseconds; | 114 theme.transitionDurationMilliseconds; |
| 115 } | 115 } |
| 116 | 116 |
| 117 void dispose() { | 117 void dispose() { |
| 118 _configEventsDisposer.dispose(); | 118 _configEventsDisposer.dispose(); |
| 119 _dataEventsDisposer.dispose(); | 119 _dataEventsDisposer.dispose(); |
| 120 _config.legend.dispose(); | 120 _config?.legend?.dispose(); |
| 121 | 121 |
| 122 if (_valueMouseOverController != null) { | 122 if (_valueMouseOverController != null) { |
| 123 _valueMouseOverController.close(); | 123 _valueMouseOverController.close(); |
| 124 _valueMouseOverController = null; | 124 _valueMouseOverController = null; |
| 125 } | 125 } |
| 126 if (_valueMouseOutController != null) { | 126 if (_valueMouseOutController != null) { |
| 127 _valueMouseOutController.close(); | 127 _valueMouseOutController.close(); |
| 128 _valueMouseOutController = null; | 128 _valueMouseOutController = null; |
| 129 } | 129 } |
| 130 if (_valueMouseClickController != null) { | 130 if (_valueMouseClickController != null) { |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 _initAxes(preRender: preRender); | 342 _initAxes(preRender: preRender); |
| 343 | 343 |
| 344 // Render the chart, now that the axes layer is already in DOM. | 344 // Render the chart, now that the axes layer is already in DOM. |
| 345 axesDomainCompleter.complete(); | 345 axesDomainCompleter.complete(); |
| 346 | 346 |
| 347 // Updates the legend if required. | 347 // Updates the legend if required. |
| 348 _updateLegend(); | 348 _updateLegend(); |
| 349 } | 349 } |
| 350 | 350 |
| 351 String _orientRTL(String orientation) => orientation; | 351 String _orientRTL(String orientation) => orientation; |
| 352 Scale _scaleRTL(Scale scale) => scale; | |
| 353 | 352 |
| 354 /// Initialize the axes - required even if the axes are not being displayed. | 353 /// Initialize the axes - required even if the axes are not being displayed. |
| 355 _initAxes({bool preRender: false}) { | 354 _initAxes({bool preRender: false}) { |
| 356 Map measureAxisUsers = <String, Iterable<ChartSeries>>{}; | 355 Map measureAxisUsers = <String, Iterable<ChartSeries>>{}; |
| 357 | 356 |
| 358 // Create necessary measures axes. | 357 // Create necessary measures axes. |
| 359 // If measure axes were not configured on the series, default is used. | 358 // If measure axes were not configured on the series, default is used. |
| 360 _series.forEach((ChartSeries s) { | 359 _series.forEach((ChartSeries s) { |
| 361 var measureAxisIds = | 360 var measureAxisIds = |
| 362 isNullOrEmpty(s.measureAxisIds) ? MEASURE_AXIS_IDS : s.measureAxisIds; | 361 isNullOrEmpty(s.measureAxisIds) ? MEASURE_AXIS_IDS : s.measureAxisIds; |
| 363 measureAxisIds.forEach((axisId) { | 362 measureAxisIds.forEach((axisId) { |
| 364 _getMeasureAxis(axisId); // Creates axis if required | 363 _getMeasureAxis(axisId); // Creates axis if required |
| 365 var users = measureAxisUsers[axisId]; | 364 var users = measureAxisUsers[axisId]; |
| 366 if (users == null) { | 365 if (users == null) { |
| 367 measureAxisUsers[axisId] = [s]; | 366 measureAxisUsers[axisId] = [s]; |
| 368 } else { | 367 } else { |
| 369 users.add(s); | 368 users.add(s); |
| 370 } | 369 } |
| 371 }); | 370 }); |
| 372 }); | 371 }); |
| 373 | 372 |
| 374 // Now that we know a list of series using each measure axis, configure | 373 // Now that we know a list of series using each measure axis, configure |
| 375 // the input domain of each axis. | 374 // the input domain of each axis. |
| 376 measureAxisUsers.forEach((id, listOfSeries) { | 375 measureAxisUsers.forEach((id, listOfSeries) { |
| 377 var sampleCol = listOfSeries.first.measures.first, | 376 var sampleCol = listOfSeries.first.measures.first, |
| 378 sampleColSpec = data.columns.elementAt(sampleCol), | 377 sampleColSpec = data.columns.elementAt(sampleCol), |
| 379 axis = _getMeasureAxis(id), | 378 axis = _getMeasureAxis(id); |
| 380 domain; | 379 List domain; |
| 381 | 380 |
| 382 if (sampleColSpec.useOrdinalScale) { | 381 if (sampleColSpec.useOrdinalScale) { |
| 383 throw new UnsupportedError( | 382 throw new UnsupportedError( |
| 384 'Ordinal measure axes are not currently supported.'); | 383 'Ordinal measure axes are not currently supported.'); |
| 385 } else { | 384 } else { |
| 386 // Extent is available because [ChartRenderer.prepare] was already | 385 // Extent is available because [ChartRenderer.prepare] was already |
| 387 // called (when checking for valid series in [draw]. | 386 // called (when checking for valid series in [draw]. |
| 388 Iterable extents = listOfSeries.map((s) => s.renderer.extent).toList(); | 387 Iterable extents = listOfSeries.map((s) => s.renderer.extent).toList(); |
| 389 var lowest = min(extents.map((e) => e.min)), | 388 var lowest = min(extents.map((e) => e.min)), |
| 390 highest = max(extents.map((e) => e.max)); | 389 highest = max(extents.map((e) => e.max)); |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 new Rect(left.width, top.height, left.width, renderAreaHeight); | 553 new Rect(left.width, top.height, left.width, renderAreaHeight); |
| 555 } | 554 } |
| 556 | 555 |
| 557 // Updates the legend, if configuration changed since the last | 556 // Updates the legend, if configuration changed since the last |
| 558 // time the legend was updated. | 557 // time the legend was updated. |
| 559 _updateLegend() { | 558 _updateLegend() { |
| 560 if (!_pendingLegendUpdate) return; | 559 if (!_pendingLegendUpdate) return; |
| 561 if (_config == null || _config.legend == null || _series.isEmpty) return; | 560 if (_config == null || _config.legend == null || _series.isEmpty) return; |
| 562 | 561 |
| 563 var legend = <ChartLegendItem>[]; | 562 var legend = <ChartLegendItem>[]; |
| 564 List seriesByColumn = | 563 List<List<ChartSeries>> seriesByColumn = |
| 565 new List.generate(data.columns.length, (_) => new List()); | 564 new List<List<ChartSeries>>.generate( |
| 565 data.columns.length, (_) => <ChartSeries>[]); |
| 566 | 566 |
| 567 _series.forEach((s) => s.measures.forEach((m) => seriesByColumn[m].add(s))); | 567 _series.forEach((s) => s.measures.forEach((m) => seriesByColumn[m].add(s))); |
| 568 | 568 |
| 569 seriesByColumn.asMap().forEach((int i, List s) { | 569 seriesByColumn.asMap().forEach((int i, List<ChartSeries> s) { |
| 570 if (s.length == 0) return; | 570 if (s.length == 0) return; |
| 571 legend.add(new ChartLegendItem( | 571 legend.add(new ChartLegendItem( |
| 572 index: i, | 572 index: i, |
| 573 label: data.columns.elementAt(i).label, | 573 label: data.columns.elementAt(i).label, |
| 574 series: s, | 574 series: s, |
| 575 color: theme.getColorForKey(i))); | 575 color: theme.getColorForKey(i))); |
| 576 }); | 576 }); |
| 577 | 577 |
| 578 _config.legend.update(legend, this); | 578 _config.legend.update(legend, this); |
| 579 _pendingLegendUpdate = false; | 579 _pendingLegendUpdate = false; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 ORIENTATION_TOP: const Rect(), | 657 ORIENTATION_TOP: const Rect(), |
| 658 ORIENTATION_BOTTOM: const Rect() | 658 ORIENTATION_BOTTOM: const Rect() |
| 659 }; | 659 }; |
| 660 | 660 |
| 661 UnmodifiableMapView<String, Rect> _axesView; | 661 UnmodifiableMapView<String, Rect> _axesView; |
| 662 | 662 |
| 663 @override | 663 @override |
| 664 get axes => _axesView; | 664 get axes => _axesView; |
| 665 | 665 |
| 666 @override | 666 @override |
| 667 Rect renderArea; | 667 Rect renderArea = const Rect(); |
| 668 | 668 |
| 669 @override | 669 @override |
| 670 Rect chartArea; | 670 Rect chartArea = const Rect(); |
| 671 | 671 |
| 672 _ChartAreaLayout() { | 672 _ChartAreaLayout() { |
| 673 _axesView = new UnmodifiableMapView(_axes); | 673 _axesView = new UnmodifiableMapView(_axes); |
| 674 } | 674 } |
| 675 } | 675 } |
| 676 | 676 |
| 677 class _ChartSeriesInfo { | 677 class _ChartSeriesInfo { |
| 678 CartesianRenderer _renderer; | 678 CartesianRenderer _renderer; |
| 679 SubscriptionsDisposer _disposer = new SubscriptionsDisposer(); | 679 SubscriptionsDisposer _disposer = new SubscriptionsDisposer(); |
| 680 | 680 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 733 } | 733 } |
| 734 } | 734 } |
| 735 _renderer = _series.renderer; | 735 _renderer = _series.renderer; |
| 736 } | 736 } |
| 737 | 737 |
| 738 dispose() { | 738 dispose() { |
| 739 _renderer?.dispose(); | 739 _renderer?.dispose(); |
| 740 _disposer.dispose(); | 740 _disposer.dispose(); |
| 741 } | 741 } |
| 742 } | 742 } |
| OLD | NEW |