diff --git a/web/charts/example/README.md b/web/charts/README.md
similarity index 100%
rename from web/charts/example/README.md
rename to web/charts/README.md
diff --git a/web/charts/example/web/preview.png b/web/charts/assets/preview.png
similarity index 100%
rename from web/charts/example/web/preview.png
rename to web/charts/assets/preview.png
diff --git a/web/charts/common/.gitignore b/web/charts/common/.gitignore
deleted file mode 100644
index d16386367..000000000
--- a/web/charts/common/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-build/
\ No newline at end of file
diff --git a/web/charts/common/CHANGELOG.md b/web/charts/common/CHANGELOG.md
deleted file mode 100644
index f5597bf94..000000000
--- a/web/charts/common/CHANGELOG.md
+++ /dev/null
@@ -1,48 +0,0 @@
-# 0.6.0
-* Bars can now be rendered on line charts.
-* Negative measure values will now be rendered on bar charts as a separate stack from the positive
-values.
-* Added a Datum Legend, which displays one entry per value in the first series on the chart. This is
- useful for pie and scatter plot charts.
-* The AxisPosition enum in RTLSpec was refactored to AxisDirection to better reflect its effect on
-swapping the positions of all start and end components, and not just positioning the measure axes.
-* Added custom colors for line renderer area skirts and confidence intervals. A new "areaColorFn"
-has been added to Series, and corresponding data to the datum. We could not use the fillColorFn for
-these elements, because that color is already applied to the internal section of points on line
-charts (including highlighter behaviors).
-
-# 0.5.0
-* SelectionModelConfig's listener parameter has been renamed to "changeListener". This is a breaking
-change. Please rename any existing uses of the "listener" parameter to "changeListener". This was
-named in order to add an additional listener "updateListener" that listens to any update requests,
-regardless if the selection model has changed.
-* CartesianChart's method getMeasureAxis(String axisId) has been changed to
-getMeasureAxis({String axisId) so that getting the primary measure axis will not need passing any id
-that does not match the secondary measure axis id. This affects users implementing custom behaviors
-using the existing method.
-
-# 0.4.0
-* Declare compatibility with Dart 2.
-* BasicNumericTickFormatterSpec now takes in a callback instead of NumberFormat as the default constructor. Use named constructor withNumberFormat instead. This is a breaking change.
-* BarRendererConfig is no longer default of type String, please change current usage to BarRendererConfig
. This is a breaking change.
-* BarTargetLineRendererConfig is no longer default of type String, please change current usage to BarTargetLineRendererConfig. This is a breaking change.
-
-
-# 0.3.0
-* Simplified API by removing the requirement for specifying the datum type when creating a chart.
-For example, previously to construct a bar chart the syntax was 'new BarChart()'.
-The syntax is now cleaned up to be 'new BarChart()'. Please refer to the
-[online gallery](https://google.github.io/charts/flutter/gallery.html) for the correct syntax.
-* Added scatter plot charts
-* Added tap to hide for legends
-* Added support for rendering area skirts to line charts
-* Added support for configurable fill colors to bar charts
-
-# 0.2.0
-
-* Update color palette. Please use MaterialPalette instead of QuantumPalette.
-* Dart2 fixes
-
-# 0.1.0
-
-Initial release.
diff --git a/web/charts/common/LICENSE b/web/charts/common/LICENSE
deleted file mode 100644
index d64569567..000000000
--- a/web/charts/common/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/web/charts/common/README.md b/web/charts/common/README.md
deleted file mode 100644
index f7e5eee6d..000000000
--- a/web/charts/common/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Common Charting library
-
-[](https://pub.dartlang.org/packages/charts_common)
-
-Common componnets for charting libraries.
diff --git a/web/charts/common/analysis_options.yaml b/web/charts/common/analysis_options.yaml
deleted file mode 100644
index 08b772347..000000000
--- a/web/charts/common/analysis_options.yaml
+++ /dev/null
@@ -1,32 +0,0 @@
-include: package:pedantic/analysis_options.yaml
-
-analyzer:
- # strong-mode:
- # implicit-casts: false
- # implicit-dynamic: false
-
-linter:
- rules:
- - avoid_types_on_closure_parameters
- - avoid_void_async
- - await_only_futures
- - camel_case_types
- - cancel_subscriptions
- - close_sinks
- # TODO(domesticmouse): rename constants
- # - constant_identifier_names
- - control_flow_in_finally
- - empty_statements
- # TODO(domesticmouse): implement hashCode methods
- # - hash_and_equals
- - implementation_imports
- - non_constant_identifier_names
- - package_api_docs
- - package_names
- - package_prefixed_library_names
- - test_types_in_equals
- - throw_in_finally
- - unnecessary_brace_in_string_interps
- - unnecessary_getters_setters
- - unnecessary_new
- - unnecessary_statements
diff --git a/web/charts/common/lib/common.dart b/web/charts/common/lib/common.dart
deleted file mode 100644
index 12de87b2b..000000000
--- a/web/charts/common/lib/common.dart
+++ /dev/null
@@ -1,240 +0,0 @@
-// Copyright 2018 the Charts project authors. Please see the AUTHORS file
-// for details.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-export 'src/chart/bar/bar_chart.dart' show BarChart;
-export 'src/chart/bar/bar_label_decorator.dart'
- show BarLabelAnchor, BarLabelDecorator, BarLabelPosition;
-export 'src/chart/bar/bar_lane_renderer_config.dart' show BarLaneRendererConfig;
-export 'src/chart/bar/bar_renderer.dart'
- show BarRenderer, ImmutableBarRendererElement;
-export 'src/chart/bar/bar_renderer_config.dart'
- show
- BarRendererConfig,
- CornerStrategy,
- ConstCornerStrategy,
- NoCornerStrategy;
-export 'src/chart/bar/bar_renderer_decorator.dart' show BarRendererDecorator;
-export 'src/chart/bar/bar_target_line_renderer.dart' show BarTargetLineRenderer;
-export 'src/chart/bar/bar_target_line_renderer_config.dart'
- show BarTargetLineRendererConfig;
-export 'src/chart/bar/base_bar_renderer_config.dart'
- show BarGroupingType, BaseBarRendererConfig;
-export 'src/chart/cartesian/axis/axis.dart'
- show
- domainAxisKey,
- measureAxisIdKey,
- measureAxisKey,
- Axis,
- NumericAxis,
- OrdinalAxis,
- OrdinalViewport;
-export 'src/chart/cartesian/axis/numeric_extents.dart' show NumericExtents;
-export 'src/chart/cartesian/axis/draw_strategy/gridline_draw_strategy.dart'
- show GridlineRendererSpec;
-export 'src/chart/cartesian/axis/draw_strategy/none_draw_strategy.dart'
- show NoneRenderSpec;
-export 'src/chart/cartesian/axis/draw_strategy/small_tick_draw_strategy.dart'
- show SmallTickRendererSpec;
-export 'src/chart/cartesian/axis/tick_formatter.dart'
- show SimpleTickFormatterBase, TickFormatter;
-export 'src/chart/cartesian/axis/spec/axis_spec.dart'
- show
- AxisSpec,
- LineStyleSpec,
- RenderSpec,
- TextStyleSpec,
- TickLabelAnchor,
- TickLabelJustification,
- TickFormatterSpec;
-export 'src/chart/cartesian/axis/spec/bucketing_axis_spec.dart'
- show BucketingAxisSpec, BucketingNumericTickProviderSpec;
-export 'src/chart/cartesian/axis/spec/date_time_axis_spec.dart'
- show
- DateTimeAxisSpec,
- DayTickProviderSpec,
- AutoDateTimeTickFormatterSpec,
- AutoDateTimeTickProviderSpec,
- DateTimeEndPointsTickProviderSpec,
- DateTimeTickFormatterSpec,
- DateTimeTickProviderSpec,
- TimeFormatterSpec,
- StaticDateTimeTickProviderSpec;
-export 'src/chart/cartesian/axis/spec/end_points_time_axis_spec.dart'
- show EndPointsTimeAxisSpec;
-export 'src/chart/cartesian/axis/spec/numeric_axis_spec.dart'
- show
- NumericAxisSpec,
- NumericEndPointsTickProviderSpec,
- NumericTickProviderSpec,
- NumericTickFormatterSpec,
- BasicNumericTickFormatterSpec,
- BasicNumericTickProviderSpec,
- StaticNumericTickProviderSpec;
-export 'src/chart/cartesian/axis/spec/ordinal_axis_spec.dart'
- show
- BasicOrdinalTickProviderSpec,
- BasicOrdinalTickFormatterSpec,
- OrdinalAxisSpec,
- OrdinalTickFormatterSpec,
- OrdinalTickProviderSpec,
- StaticOrdinalTickProviderSpec;
-export 'src/chart/cartesian/axis/spec/percent_axis_spec.dart'
- show PercentAxisSpec;
-export 'src/chart/cartesian/axis/time/date_time_extents.dart'
- show DateTimeExtents;
-export 'src/chart/cartesian/axis/time/date_time_tick_formatter.dart'
- show DateTimeTickFormatter;
-export 'src/chart/cartesian/axis/spec/tick_spec.dart' show TickSpec;
-export 'src/chart/cartesian/cartesian_chart.dart'
- show CartesianChart, NumericCartesianChart, OrdinalCartesianChart;
-export 'src/chart/cartesian/cartesian_renderer.dart' show BaseCartesianRenderer;
-export 'src/chart/common/base_chart.dart' show BaseChart, LifecycleListener;
-export 'src/chart/common/behavior/a11y/a11y_explore_behavior.dart'
- show ExploreModeTrigger;
-export 'src/chart/common/behavior/a11y/a11y_node.dart' show A11yNode;
-export 'src/chart/common/behavior/a11y/domain_a11y_explore_behavior.dart'
- show DomainA11yExploreBehavior, VocalizationCallback;
-export 'src/chart/common/behavior/chart_behavior.dart'
- show
- BehaviorPosition,
- ChartBehavior,
- InsideJustification,
- OutsideJustification;
-export 'src/chart/common/behavior/calculation/percent_injector.dart'
- show PercentInjector, PercentInjectorTotalType;
-export 'src/chart/common/behavior/domain_highlighter.dart'
- show DomainHighlighter;
-export 'src/chart/common/behavior/initial_selection.dart' show InitialSelection;
-export 'src/chart/common/behavior/legend/legend.dart'
- show Legend, LegendCellPadding, LegendState, LegendTapHandling;
-export 'src/chart/common/behavior/legend/legend_entry.dart' show LegendEntry;
-export 'src/chart/common/behavior/legend/legend_entry_generator.dart'
- show LegendEntryGenerator, LegendDefaultMeasure;
-export 'src/chart/common/behavior/legend/datum_legend.dart' show DatumLegend;
-export 'src/chart/common/behavior/legend/series_legend.dart' show SeriesLegend;
-export 'src/chart/common/behavior/line_point_highlighter.dart'
- show LinePointHighlighter, LinePointHighlighterFollowLineType;
-export 'src/chart/common/behavior/range_annotation.dart'
- show
- AnnotationLabelAnchor,
- AnnotationLabelDirection,
- AnnotationLabelPosition,
- AnnotationSegment,
- LineAnnotationSegment,
- RangeAnnotation,
- RangeAnnotationAxisType,
- RangeAnnotationSegment;
-export 'src/chart/common/behavior/sliding_viewport.dart' show SlidingViewport;
-export 'src/chart/common/behavior/chart_title/chart_title.dart'
- show ChartTitle, ChartTitleDirection;
-export 'src/chart/common/behavior/selection/lock_selection.dart'
- show LockSelection;
-export 'src/chart/common/behavior/selection/select_nearest.dart'
- show SelectNearest;
-export 'src/chart/common/behavior/selection/selection_trigger.dart'
- show SelectionTrigger;
-export 'src/chart/common/behavior/slider/slider.dart'
- show
- Slider,
- SliderHandlePosition,
- SliderListenerCallback,
- SliderListenerDragState,
- SliderStyle;
-export 'src/chart/common/behavior/zoom/initial_hint_behavior.dart'
- show InitialHintBehavior;
-export 'src/chart/common/behavior/zoom/pan_and_zoom_behavior.dart'
- show PanAndZoomBehavior;
-export 'src/chart/common/behavior/zoom/pan_behavior.dart'
- show PanBehavior, PanningCompletedCallback;
-export 'src/chart/common/behavior/zoom/panning_tick_provider.dart'
- show PanningTickProviderMode;
-export 'src/chart/common/canvas_shapes.dart'
- show CanvasBarStack, CanvasPie, CanvasPieSlice, CanvasRect;
-export 'src/chart/common/chart_canvas.dart' show ChartCanvas, FillPatternType;
-export 'src/chart/common/chart_context.dart' show ChartContext;
-export 'src/chart/common/datum_details.dart'
- show DatumDetails, DomainFormatter, MeasureFormatter;
-export 'src/chart/common/processed_series.dart'
- show ImmutableSeries, MutableSeries;
-export 'src/chart/common/series_datum.dart' show SeriesDatum, SeriesDatumConfig;
-export 'src/chart/common/selection_model/selection_model.dart'
- show SelectionModel, SelectionModelType, SelectionModelListener;
-export 'src/chart/common/series_renderer.dart'
- show rendererIdKey, rendererKey, SeriesRenderer;
-export 'src/chart/common/series_renderer_config.dart'
- show RendererAttributeKey, SeriesRendererConfig;
-export 'src/chart/layout/layout_config.dart' show LayoutConfig, MarginSpec;
-export 'src/chart/layout/layout_view.dart'
- show
- LayoutPosition,
- LayoutView,
- LayoutViewConfig,
- LayoutViewPaintOrder,
- LayoutViewPositionOrder,
- ViewMargin,
- ViewMeasuredSizes;
-export 'src/chart/line/line_chart.dart' show LineChart;
-export 'src/chart/line/line_renderer.dart' show LineRenderer;
-export 'src/chart/line/line_renderer_config.dart' show LineRendererConfig;
-export 'src/chart/pie/arc_label_decorator.dart'
- show ArcLabelDecorator, ArcLabelLeaderLineStyleSpec, ArcLabelPosition;
-export 'src/chart/pie/arc_renderer.dart' show ArcRenderer;
-export 'src/chart/pie/arc_renderer_config.dart' show ArcRendererConfig;
-export 'src/chart/pie/pie_chart.dart' show PieChart;
-export 'src/chart/scatter_plot/comparison_points_decorator.dart'
- show ComparisonPointsDecorator;
-export 'src/chart/scatter_plot/point_renderer.dart'
- show
- boundsLineRadiusPxKey,
- boundsLineRadiusPxFnKey,
- pointSymbolRendererFnKey,
- pointSymbolRendererIdKey,
- PointRenderer;
-export 'src/chart/scatter_plot/point_renderer_config.dart'
- show PointRendererConfig;
-export 'src/chart/scatter_plot/point_renderer_decorator.dart'
- show PointRendererDecorator;
-export 'src/chart/scatter_plot/scatter_plot_chart.dart' show ScatterPlotChart;
-export 'src/chart/scatter_plot/symbol_annotation_renderer.dart'
- show SymbolAnnotationRenderer;
-export 'src/chart/scatter_plot/symbol_annotation_renderer_config.dart'
- show SymbolAnnotationRendererConfig;
-export 'src/chart/time_series/time_series_chart.dart' show TimeSeriesChart;
-export 'src/common/color.dart' show Color;
-export 'src/common/date_time_factory.dart'
- show DateTimeFactory, LocalDateTimeFactory, UTCDateTimeFactory;
-export 'src/common/gesture_listener.dart' show GestureListener;
-export 'src/common/graphics_factory.dart' show GraphicsFactory;
-export 'src/common/line_style.dart' show LineStyle;
-export 'src/common/material_palette.dart' show MaterialPalette;
-export 'src/common/performance.dart' show Performance;
-export 'src/common/proxy_gesture_listener.dart' show ProxyGestureListener;
-export 'src/common/rtl_spec.dart' show AxisDirection, RTLSpec;
-export 'src/common/style/material_style.dart' show MaterialStyle;
-export 'src/common/style/style_factory.dart' show StyleFactory;
-export 'src/common/symbol_renderer.dart'
- show
- CircleSymbolRenderer,
- CylinderSymbolRenderer,
- LineSymbolRenderer,
- PointSymbolRenderer,
- RectSymbolRenderer,
- RoundedRectSymbolRenderer,
- SymbolRenderer;
-export 'src/common/text_element.dart'
- show TextElement, TextDirection, MaxWidthStrategy;
-export 'src/common/text_measurement.dart' show TextMeasurement;
-export 'src/common/text_style.dart' show TextStyle;
-export 'src/data/series.dart' show Series, TypedAccessorFn;
diff --git a/web/charts/common/lib/src/chart/bar/bar_chart.dart b/web/charts/common/lib/src/chart/bar/bar_chart.dart
deleted file mode 100644
index a9810c6c1..000000000
--- a/web/charts/common/lib/src/chart/bar/bar_chart.dart
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2018 the Charts project authors. Please see the AUTHORS file
-// for details.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import 'dart:collection' show LinkedHashMap;
-
-import '../bar/bar_renderer.dart' show BarRenderer;
-import '../cartesian/axis/axis.dart' show NumericAxis;
-import '../cartesian/cartesian_chart.dart' show OrdinalCartesianChart;
-import '../common/series_renderer.dart' show SeriesRenderer;
-import '../layout/layout_config.dart' show LayoutConfig;
-
-class BarChart extends OrdinalCartesianChart {
- BarChart(
- {bool vertical,
- LayoutConfig layoutConfig,
- NumericAxis primaryMeasureAxis,
- NumericAxis secondaryMeasureAxis,
- LinkedHashMap disjointMeasureAxes})
- : super(
- vertical: vertical,
- layoutConfig: layoutConfig,
- primaryMeasureAxis: primaryMeasureAxis,
- secondaryMeasureAxis: secondaryMeasureAxis,
- disjointMeasureAxes: disjointMeasureAxes);
-
- @override
- SeriesRenderer makeDefaultRenderer() {
- return BarRenderer()..rendererId = SeriesRenderer.defaultRendererId;
- }
-}
diff --git a/web/charts/common/lib/src/chart/bar/bar_label_decorator.dart b/web/charts/common/lib/src/chart/bar/bar_label_decorator.dart
deleted file mode 100644
index 5202e02d0..000000000
--- a/web/charts/common/lib/src/chart/bar/bar_label_decorator.dart
+++ /dev/null
@@ -1,234 +0,0 @@
-// Copyright 2018 the Charts project authors. Please see the AUTHORS file
-// for details.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import 'dart:math' show Rectangle;
-
-import 'package:meta/meta.dart' show required;
-
-import '../../common/color.dart' show Color;
-import '../../common/graphics_factory.dart' show GraphicsFactory;
-import '../../common/text_element.dart' show TextDirection;
-import '../../common/text_style.dart' show TextStyle;
-import '../../data/series.dart' show AccessorFn;
-import '../cartesian/axis/spec/axis_spec.dart' show TextStyleSpec;
-import '../common/chart_canvas.dart' show ChartCanvas;
-import 'bar_renderer.dart' show ImmutableBarRendererElement;
-import 'bar_renderer_decorator.dart' show BarRendererDecorator;
-
-class BarLabelDecorator extends BarRendererDecorator {
- // Default configuration
- static const _defaultLabelPosition = BarLabelPosition.auto;
- static const _defaultLabelPadding = 5;
- static const _defaultLabelAnchor = BarLabelAnchor.start;
- static final _defaultInsideLabelStyle =
- TextStyleSpec(fontSize: 12, color: Color.white);
- static final _defaultOutsideLabelStyle =
- TextStyleSpec(fontSize: 12, color: Color.black);
-
- /// Configures [TextStyleSpec] for labels placed inside the bars.
- final TextStyleSpec insideLabelStyleSpec;
-
- /// Configures [TextStyleSpec] for labels placed outside the bars.
- final TextStyleSpec outsideLabelStyleSpec;
-
- /// Configures where to place the label relative to the bars.
- final BarLabelPosition labelPosition;
-
- /// For labels drawn inside the bar, configures label anchor position.
- final BarLabelAnchor labelAnchor;
-
- /// Space before and after the label text.
- final int labelPadding;
-
- BarLabelDecorator(
- {TextStyleSpec insideLabelStyleSpec,
- TextStyleSpec outsideLabelStyleSpec,
- this.labelPosition = _defaultLabelPosition,
- this.labelPadding = _defaultLabelPadding,
- this.labelAnchor = _defaultLabelAnchor})
- : insideLabelStyleSpec = insideLabelStyleSpec ?? _defaultInsideLabelStyle,
- outsideLabelStyleSpec =
- outsideLabelStyleSpec ?? _defaultOutsideLabelStyle;
-
- @override
- void decorate(Iterable> barElements,
- ChartCanvas canvas, GraphicsFactory graphicsFactory,
- {@required Rectangle drawBounds,
- @required double animationPercent,
- @required bool renderingVertically,
- bool rtl = false}) {
- // TODO: Decorator not yet available for vertical charts.
- assert(renderingVertically == false);
-
- // Only decorate the bars when animation is at 100%.
- if (animationPercent != 1.0) {
- return;
- }
-
- // Create [TextStyle] from [TextStyleSpec] to be used by all the elements.
- // The [GraphicsFactory] is needed so it can't be created earlier.
- final insideLabelStyle =
- _getTextStyle(graphicsFactory, insideLabelStyleSpec);
- final outsideLabelStyle =
- _getTextStyle(graphicsFactory, outsideLabelStyleSpec);
-
- for (var element in barElements) {
- final labelFn = element.series.labelAccessorFn;
- final datumIndex = element.index;
- final label = (labelFn != null) ? labelFn(datumIndex) : null;
-
- // If there are custom styles, use that instead of the default or the
- // style defined for the entire decorator.
- final datumInsideLabelStyle = _getDatumStyle(
- element.series.insideLabelStyleAccessorFn,
- datumIndex,
- graphicsFactory,
- defaultStyle: insideLabelStyle);
- final datumOutsideLabelStyle = _getDatumStyle(
- element.series.outsideLabelStyleAccessorFn,
- datumIndex,
- graphicsFactory,
- defaultStyle: outsideLabelStyle);
-
- // Skip calculation and drawing for this element if no label.
- if (label == null || label.isEmpty) {
- continue;
- }
-
- final bounds = element.bounds;
-
- // Get space available inside and outside the bar.
- final totalPadding = labelPadding * 2;
- final insideBarWidth = bounds.width - totalPadding;
- final outsideBarWidth = drawBounds.width - bounds.width - totalPadding;
-
- final labelElement = graphicsFactory.createTextElement(label);
- var calculatedLabelPosition = labelPosition;
- if (calculatedLabelPosition == BarLabelPosition.auto) {
- // For auto, first try to fit the text inside the bar.
- labelElement.textStyle = datumInsideLabelStyle;
-
- // A label fits if the space inside the bar is >= outside bar or if the
- // length of the text fits and the space. This is because if the bar has
- // more space than the outside, it makes more sense to place the label
- // inside the bar, even if the entire label does not fit.
- calculatedLabelPosition = (insideBarWidth >= outsideBarWidth ||
- labelElement.measurement.horizontalSliceWidth < insideBarWidth)
- ? BarLabelPosition.inside
- : BarLabelPosition.outside;
- }
-
- // Set the max width and text style.
- if (calculatedLabelPosition == BarLabelPosition.inside) {
- labelElement.textStyle = datumInsideLabelStyle;
- labelElement.maxWidth = insideBarWidth;
- } else {
- // calculatedLabelPosition == LabelPosition.outside
- labelElement.textStyle = datumOutsideLabelStyle;
- labelElement.maxWidth = outsideBarWidth;
- }
-
- // Only calculate and draw label if there's actually space for the label.
- if (labelElement.maxWidth > 0) {
- // Calculate the start position of label based on [labelAnchor].
- int labelX;
- if (calculatedLabelPosition == BarLabelPosition.inside) {
- switch (labelAnchor) {
- case BarLabelAnchor.middle:
- labelX = (bounds.left +
- bounds.width / 2 -
- labelElement.measurement.horizontalSliceWidth / 2)
- .round();
- labelElement.textDirection =
- rtl ? TextDirection.rtl : TextDirection.ltr;
- break;
-
- case BarLabelAnchor.end:
- case BarLabelAnchor.start:
- final alignLeft = rtl
- ? (labelAnchor == BarLabelAnchor.end)
- : (labelAnchor == BarLabelAnchor.start);
-
- if (alignLeft) {
- labelX = bounds.left + labelPadding;
- labelElement.textDirection = TextDirection.ltr;
- } else {
- labelX = bounds.right - labelPadding;
- labelElement.textDirection = TextDirection.rtl;
- }
- break;
- }
- } else {
- // calculatedLabelPosition == LabelPosition.outside
- labelX = bounds.right + labelPadding;
- labelElement.textDirection = TextDirection.ltr;
- }
-
- // Center the label inside the bar.
- final labelY = (bounds.top +
- (bounds.bottom - bounds.top) / 2 -
- labelElement.measurement.verticalSliceWidth / 2)
- .round();
-
- canvas.drawText(labelElement, labelX, labelY);
- }
- }
- }
-
- // Helper function that converts [TextStyleSpec] to [TextStyle].
- TextStyle _getTextStyle(
- GraphicsFactory graphicsFactory, TextStyleSpec labelSpec) {
- return graphicsFactory.createTextPaint()
- ..color = labelSpec?.color ?? Color.black
- ..fontFamily = labelSpec?.fontFamily
- ..fontSize = labelSpec?.fontSize ?? 12;
- }
-
- /// Helper function to get datum specific style
- TextStyle _getDatumStyle(AccessorFn labelFn, int datumIndex,
- GraphicsFactory graphicsFactory,
- {TextStyle defaultStyle}) {
- final styleSpec = (labelFn != null) ? labelFn(datumIndex) : null;
- return (styleSpec != null)
- ? _getTextStyle(graphicsFactory, styleSpec)
- : defaultStyle;
- }
-}
-
-/// Configures where to place the label relative to the bars.
-enum BarLabelPosition {
- /// Automatically try to place the label inside the bar first and place it on
- /// the outside of the space available outside the bar is greater than space
- /// available inside the bar.
- auto,
-
- /// Always place label on the outside.
- outside,
-
- /// Always place label on the inside.
- inside,
-}
-
-/// Configures where to anchor the label for labels drawn inside the bars.
-enum BarLabelAnchor {
- /// Anchor to the measure start.
- start,
-
- /// Anchor to the middle of the measure range.
- middle,
-
- /// Anchor to the measure end.
- end,
-}
diff --git a/web/charts/common/lib/src/chart/bar/bar_lane_renderer.dart b/web/charts/common/lib/src/chart/bar/bar_lane_renderer.dart
deleted file mode 100644
index c4b9fe9cb..000000000
--- a/web/charts/common/lib/src/chart/bar/bar_lane_renderer.dart
+++ /dev/null
@@ -1,365 +0,0 @@
-// Copyright 2018 the Charts project authors. Please see the AUTHORS file
-// for details.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import 'dart:collection' show LinkedHashMap;
-
-import '../../data/series.dart' show AttributeKey;
-import '../cartesian/axis/axis.dart'
- show ImmutableAxis, domainAxisKey, measureAxisKey;
-import '../cartesian/cartesian_chart.dart' show CartesianChart;
-import '../common/chart_canvas.dart' show ChartCanvas;
-import '../common/processed_series.dart' show ImmutableSeries, MutableSeries;
-import 'bar_lane_renderer_config.dart' show BarLaneRendererConfig;
-import 'bar_renderer.dart' show AnimatedBar, BarRenderer, BarRendererElement;
-import 'bar_renderer_decorator.dart' show BarRendererDecorator;
-import 'base_bar_renderer.dart'
- show
- barGroupCountKey,
- barGroupIndexKey,
- barGroupWeightKey,
- previousBarGroupWeightKey,
- stackKeyKey;
-import 'base_bar_renderer_element.dart' show BaseBarRendererElement;
-
-/// Key for storing a list of all domain values that exist in the series data.
-///
-/// In grouped stacked mode, this list will contain a combination of domain
-/// value and series category.
-const domainValuesKey = AttributeKey('BarLaneRenderer.domainValues');
-
-/// Renders series data as a series of bars with lanes.
-///
-/// Every stack of bars will have a swim lane rendered underneath the series
-/// data, in a gray color by default. The swim lane occupies the same width as
-/// the bar elements, and will be completely covered up if the bar stack happens
-/// to take up the entire measure domain range.
-///
-/// If every bar that shares a domain value has a null measure value, then the
-/// swim lanes may optionally be merged together into one wide lane that covers
-/// the full domain range band width.
-class BarLaneRenderer extends BarRenderer {
- final BarRendererDecorator barRendererDecorator;
-
- /// Store a map of domain+barGroupIndex+category index to bar lanes in a
- /// stack.
- ///
- /// This map is used to render all the bars in a stack together, to account
- /// for rendering effects that need to take the full stack into account (e.g.
- /// corner rounding).
- ///
- /// [LinkedHashMap] is used to render the bars on the canvas in the same order
- /// as the data was given to the chart. For the case where both grouping and
- /// stacking are disabled, this means that bars for data later in the series
- /// will be drawn "on top of" bars earlier in the series.
- final _barLaneStackMap = LinkedHashMap>>();
-
- /// Store a map of flags to track whether all measure values for a given
- /// domain value are null, for every series on the chart.
- final _allMeasuresForDomainNullMap = LinkedHashMap();
-
- factory BarLaneRenderer({BarLaneRendererConfig config, String rendererId}) {
- rendererId ??= 'bar';
- config ??= BarLaneRendererConfig();
- return BarLaneRenderer._internal(config: config, rendererId: rendererId);
- }
-
- BarLaneRenderer._internal({BarLaneRendererConfig config, String rendererId})
- : barRendererDecorator = config.barRendererDecorator,
- super.internal(config: config, rendererId: rendererId);
-
- @override
- void preprocessSeries(List> seriesList) {
- super.preprocessSeries(seriesList);
-
- _allMeasuresForDomainNullMap.clear();
-
- seriesList.forEach((series) {
- final domainFn = series.domainFn;
- final measureFn = series.rawMeasureFn;
-
- final domainValues = Set();
-
- for (var barIndex = 0; barIndex < series.data.length; barIndex++) {
- final domain = domainFn(barIndex);
- final measure = measureFn(barIndex);
-
- domainValues.add(domain);
-
- // Update the "all measure null" tracking for bars that have the
- // current domain value.
- if ((config as BarLaneRendererConfig).mergeEmptyLanes) {
- final allNull = _allMeasuresForDomainNullMap[domain];
- final isNull = measure == null;
-
- _allMeasuresForDomainNullMap[domain] =
- allNull != null ? allNull && isNull : isNull;
- }
- }
-
- series.setAttr(domainValuesKey, domainValues);
- });
- }
-
- @override
- void update(List> seriesList, bool isAnimatingThisDraw) {
- super.update(seriesList, isAnimatingThisDraw);
-
- // Add gray bars to render under every bar stack.
- seriesList.forEach((series) {
- Set domainValues = series.getAttr(domainValuesKey) as Set;
-
- final domainAxis = series.getAttr(domainAxisKey) as ImmutableAxis;
- final measureAxis = series.getAttr(measureAxisKey) as ImmutableAxis;
- final seriesStackKey = series.getAttr(stackKeyKey);
- final barGroupCount = series.getAttr(barGroupCountKey);
- final barGroupIndex = series.getAttr(barGroupIndexKey);
- final previousBarGroupWeight = series.getAttr(previousBarGroupWeightKey);
- final barGroupWeight = series.getAttr(barGroupWeightKey);
- final measureAxisPosition = measureAxis.getLocation(0.0);
- final maxMeasureValue = _getMaxMeasureValue(measureAxis);
-
- // Create a fake series for [BarLabelDecorator] to use when looking up the
- // index of each datum.
- final laneSeries = MutableSeries.clone(seriesList[0]);
- laneSeries.data = [];
-
- // Don't render any labels on the swim lanes.
- laneSeries.labelAccessorFn = (index) => '';
-
- var laneSeriesIndex = 0;
- domainValues.forEach((domainValue) {
- // Skip adding any background bars if they will be covered up by the
- // domain-spanning null bar.
- if (_allMeasuresForDomainNullMap[domainValue] == true) {
- return;
- }
-
- // Add a fake datum to the series for [BarLabelDecorator].
- final datum = {'index': laneSeriesIndex};
- laneSeries.data.add(datum);
-
- // Each bar should be stored in barStackMap in a structure that mirrors
- // the visual rendering of the bars. Thus, they should be grouped by
- // domain value, series category (by way of the stack keys that were
- // generated for each series in the preprocess step), and bar group
- // index to account for all combinations of grouping and stacking.
- final barStackMapKey = domainValue.toString() +
- '__' +
- seriesStackKey +
- '__' +
- barGroupIndex.toString();
-
- final barKey = barStackMapKey + '0';
-
- final barStackList = _barLaneStackMap.putIfAbsent(
- barStackMapKey, () => >[]);
-
- // If we already have an AnimatingBar for that index, use it.
- var animatingBar = barStackList.firstWhere((bar) => bar.key == barKey,
- orElse: () => null);
-
- // If we don't have any existing bar element, create a new bar and have
- // it animate in from the domain axis.
- if (animatingBar == null) {
- animatingBar = makeAnimatedBar(
- key: barKey,
- series: laneSeries,
- datum: datum,
- barGroupIndex: barGroupIndex,
- previousBarGroupWeight: previousBarGroupWeight,
- barGroupWeight: barGroupWeight,
- color: (config as BarLaneRendererConfig).backgroundBarColor,
- details: BarRendererElement(),
- domainValue: domainValue,
- domainAxis: domainAxis,
- domainWidth: domainAxis.rangeBand.round(),
- fillColor: (config as BarLaneRendererConfig).backgroundBarColor,
- measureValue: maxMeasureValue,
- measureOffsetValue: 0.0,
- measureAxisPosition: measureAxisPosition,
- measureAxis: measureAxis,
- numBarGroups: barGroupCount,
- strokeWidthPx: config.strokeWidthPx,
- measureIsNull: false,
- measureIsNegative: false);
-
- barStackList.add(animatingBar);
- } else {
- animatingBar
- ..datum = datum
- ..series = laneSeries
- ..domainValue = domainValue;
- }
-
- // Get the barElement we are going to setup.
- // Optimization to prevent allocation in non-animating case.
- BaseBarRendererElement barElement = makeBarRendererElement(
- barGroupIndex: barGroupIndex,
- previousBarGroupWeight: previousBarGroupWeight,
- barGroupWeight: barGroupWeight,
- color: (config as BarLaneRendererConfig).backgroundBarColor,
- details: BarRendererElement(),
- domainValue: domainValue,
- domainAxis: domainAxis,
- domainWidth: domainAxis.rangeBand.round(),
- fillColor: (config as BarLaneRendererConfig).backgroundBarColor,
- measureValue: maxMeasureValue,
- measureOffsetValue: 0.0,
- measureAxisPosition: measureAxisPosition,
- measureAxis: measureAxis,
- numBarGroups: barGroupCount,
- strokeWidthPx: config.strokeWidthPx,
- measureIsNull: false,
- measureIsNegative: false);
-
- animatingBar.setNewTarget(barElement);
-
- laneSeriesIndex++;
- });
- });
-
- // Add domain-spanning bars to render when every measure value for every
- // datum of a given domain is null.
- if ((config as BarLaneRendererConfig).mergeEmptyLanes) {
- // Use the axes from the first series.
- final domainAxis =
- seriesList[0].getAttr(domainAxisKey) as ImmutableAxis;
- final measureAxis =
- seriesList[0].getAttr(measureAxisKey) as ImmutableAxis;
-
- final measureAxisPosition = measureAxis.getLocation(0.0);
- final maxMeasureValue = _getMaxMeasureValue(measureAxis);
-
- final barGroupIndex = 0;
- final previousBarGroupWeight = 0.0;
- final barGroupWeight = 1.0;
- final barGroupCount = 1;
-
- // Create a fake series for [BarLabelDecorator] to use when looking up the
- // index of each datum. We don't care about any other series values for
- // the merged lanes, so just clone the first series.
- final mergedSeries = MutableSeries.clone(seriesList[0]);
- mergedSeries.data = [];
-
- // Add a label accessor that returns the empty lane label.
- mergedSeries.labelAccessorFn =
- (index) => (config as BarLaneRendererConfig).emptyLaneLabel;
-
- var mergedSeriesIndex = 0;
- _allMeasuresForDomainNullMap.forEach((domainValue, allNull) {
- if (allNull) {
- // Add a fake datum to the series for [BarLabelDecorator].
- final datum = {'index': mergedSeriesIndex};
- mergedSeries.data.add(datum);
-
- final barStackMapKey = domainValue.toString() + '__allNull__';
-
- final barKey = barStackMapKey + '0';
-
- final barStackList = _barLaneStackMap.putIfAbsent(
- barStackMapKey, () => >[]);
-
- // If we already have an AnimatingBar for that index, use it.
- var animatingBar = barStackList.firstWhere((bar) => bar.key == barKey,
- orElse: () => null);
-
- // If we don't have any existing bar element, create a new bar and have
- // it animate in from the domain axis.
- if (animatingBar == null) {
- animatingBar = makeAnimatedBar(
- key: barKey,
- series: mergedSeries,
- datum: datum,
- barGroupIndex: barGroupIndex,
- previousBarGroupWeight: previousBarGroupWeight,
- barGroupWeight: barGroupWeight,
- color: (config as BarLaneRendererConfig).backgroundBarColor,
- details: BarRendererElement(),
- domainValue: domainValue,
- domainAxis: domainAxis,
- domainWidth: domainAxis.rangeBand.round(),
- fillColor: (config as BarLaneRendererConfig).backgroundBarColor,
- measureValue: maxMeasureValue,
- measureOffsetValue: 0.0,
- measureAxisPosition: measureAxisPosition,
- measureAxis: measureAxis,
- numBarGroups: barGroupCount,
- strokeWidthPx: config.strokeWidthPx,
- measureIsNull: false,
- measureIsNegative: false);
-
- barStackList.add(animatingBar);
- } else {
- animatingBar
- ..datum = datum
- ..series = mergedSeries
- ..domainValue = domainValue;
- }
-
- // Get the barElement we are going to setup.
- // Optimization to prevent allocation in non-animating case.
- BaseBarRendererElement barElement = makeBarRendererElement(
- barGroupIndex: barGroupIndex,
- previousBarGroupWeight: previousBarGroupWeight,
- barGroupWeight: barGroupWeight,
- color: (config as BarLaneRendererConfig).backgroundBarColor,
- details: BarRendererElement(),
- domainValue: domainValue,
- domainAxis: domainAxis,
- domainWidth: domainAxis.rangeBand.round(),
- fillColor: (config as BarLaneRendererConfig).backgroundBarColor,
- measureValue: maxMeasureValue,
- measureOffsetValue: 0.0,
- measureAxisPosition: measureAxisPosition,
- measureAxis: measureAxis,
- numBarGroups: barGroupCount,
- strokeWidthPx: config.strokeWidthPx,
- measureIsNull: false,
- measureIsNegative: false);
-
- animatingBar.setNewTarget(barElement);
-
- mergedSeriesIndex++;
- }
- });
- }
- }
-
- /// Gets the maximum measure value that will fit in the draw area.
- num _getMaxMeasureValue(ImmutableAxis measureAxis) {
- final pos = (chart as CartesianChart).vertical
- ? chart.drawAreaBounds.top
- : isRtl ? chart.drawAreaBounds.left : chart.drawAreaBounds.right;
-
- return measureAxis.getDomain(pos.toDouble());
- }
-
- /// Paints the current bar data on the canvas.
- @override
- void paint(ChartCanvas canvas, double animationPercent) {
- _barLaneStackMap.forEach((stackKey, barStack) {
- // Turn this into a list so that the getCurrentBar isn't called more than
- // once for each animationPercent if the barElements are iterated more
- // than once.
- List> barElements = barStack
- .map((animatingBar) => animatingBar.getCurrentBar(animationPercent))
- .toList();
-
- paintBar(canvas, animationPercent, barElements);
- });
-
- super.paint(canvas, animationPercent);
- }
-}
diff --git a/web/charts/common/lib/src/chart/bar/bar_lane_renderer_config.dart b/web/charts/common/lib/src/chart/bar/bar_lane_renderer_config.dart
deleted file mode 100644
index 436eb46e9..000000000
--- a/web/charts/common/lib/src/chart/bar/bar_lane_renderer_config.dart
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2018 the Charts project authors. Please see the AUTHORS file
-// for details.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import '../../common/color.dart' show Color;
-import '../../common/style/style_factory.dart' show StyleFactory;
-import '../../common/symbol_renderer.dart';
-import '../common/chart_canvas.dart' show FillPatternType;
-import '../layout/layout_view.dart' show LayoutViewPaintOrder;
-import 'bar_label_decorator.dart' show BarLabelDecorator;
-import 'bar_lane_renderer.dart' show BarLaneRenderer;
-import 'bar_renderer_config.dart' show BarRendererConfig, CornerStrategy;
-import 'bar_renderer_decorator.dart' show BarRendererDecorator;
-import 'base_bar_renderer_config.dart' show BarGroupingType;
-
-/// Configuration for a bar lane renderer.
-class BarLaneRendererConfig extends BarRendererConfig {
- /// The color of background bars.
- final Color backgroundBarColor;
-
- /// Label text to draw on a merged empty lane.
- ///
- /// This will only be drawn if all of the measures for a domain are null, and
- /// [mergeEmptyLanes] is enabled.
- ///
- /// The renderer must be configured with a [BarLabelDecorator] for this label
- /// to be drawn.
- final String emptyLaneLabel;
-
- /// Whether or not all lanes for a given domain value should be merged into
- /// one wide lane if all measure values for said domain are null.
- final bool mergeEmptyLanes;
-
- BarLaneRendererConfig({
- String customRendererId,
- CornerStrategy cornerStrategy,
- this.emptyLaneLabel = 'No data',
- FillPatternType fillPattern,
- BarGroupingType groupingType,
- int layoutPaintOrder = LayoutViewPaintOrder.bar,
- this.mergeEmptyLanes = false,
- int minBarLengthPx = 0,
- double stackHorizontalSeparator,
- double strokeWidthPx = 0.0,
- BarRendererDecorator barRendererDecorator,
- SymbolRenderer symbolRenderer,
- Color backgroundBarColor,
- List weightPattern,
- }) : backgroundBarColor =
- backgroundBarColor ?? StyleFactory.style.noDataColor,
- super(
- barRendererDecorator: barRendererDecorator,
- cornerStrategy: cornerStrategy,
- customRendererId: customRendererId,
- groupingType: groupingType ?? BarGroupingType.grouped,
- layoutPaintOrder: layoutPaintOrder,
- minBarLengthPx: minBarLengthPx,
- fillPattern: fillPattern,
- stackHorizontalSeparator: stackHorizontalSeparator,
- strokeWidthPx: strokeWidthPx,
- symbolRenderer: symbolRenderer,
- weightPattern: weightPattern,
- );
-
- @override
- BarLaneRenderer build() {
- return BarLaneRenderer(config: this, rendererId: customRendererId);
- }
-
- @override
- bool operator ==(other) {
- if (identical(this, other)) {
- return true;
- }
- if (!(other is BarLaneRendererConfig)) {
- return false;
- }
- return other.backgroundBarColor == backgroundBarColor &&
- other.emptyLaneLabel == emptyLaneLabel &&
- other.mergeEmptyLanes == mergeEmptyLanes &&
- super == (other);
- }
-
- @override
- int get hashCode {
- var hash = super.hashCode;
- hash = hash * 31 + (backgroundBarColor?.hashCode ?? 0);
- hash = hash * 31 + (emptyLaneLabel?.hashCode ?? 0);
- hash = hash * 31 + (mergeEmptyLanes?.hashCode ?? 0);
- return hash;
- }
-}
diff --git a/web/charts/common/lib/src/chart/bar/bar_renderer.dart b/web/charts/common/lib/src/chart/bar/bar_renderer.dart
deleted file mode 100644
index 61b922c16..000000000
--- a/web/charts/common/lib/src/chart/bar/bar_renderer.dart
+++ /dev/null
@@ -1,556 +0,0 @@
-// Copyright 2018 the Charts project authors. Please see the AUTHORS file
-// for details.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import 'dart:math' show max, min, Point, Rectangle;
-
-import 'package:meta/meta.dart' show protected, required;
-
-import '../../common/color.dart' show Color;
-import '../cartesian/axis/axis.dart'
- show ImmutableAxis, domainAxisKey, measureAxisKey;
-import '../common/canvas_shapes.dart' show CanvasBarStack, CanvasRect;
-import '../common/chart_canvas.dart' show ChartCanvas, FillPatternType;
-import '../common/datum_details.dart' show DatumDetails;
-import '../common/processed_series.dart' show ImmutableSeries, MutableSeries;
-import '../common/series_datum.dart' show SeriesDatum;
-import 'bar_renderer_config.dart' show BarRendererConfig, CornerStrategy;
-import 'bar_renderer_decorator.dart' show BarRendererDecorator;
-import 'base_bar_renderer.dart'
- show
- BaseBarRenderer,
- barGroupCountKey,
- barGroupIndexKey,
- previousBarGroupWeightKey,
- barGroupWeightKey;
-import 'base_bar_renderer_element.dart'
- show BaseAnimatedBar, BaseBarRendererElement;
-
-/// Renders series data as a series of bars.
-class BarRenderer
- extends BaseBarRenderer, AnimatedBar> {
- /// If we are grouped, use this spacing between the bars in a group.
- final _barGroupInnerPadding = 2;
-
- /// The padding between bar stacks.
- ///
- /// The padding comes out of the bottom of the bar.
- final _stackedBarPadding = 1;
-
- final BarRendererDecorator barRendererDecorator;
-
- factory BarRenderer({BarRendererConfig config, String rendererId}) {
- rendererId ??= 'bar';
- config ??= BarRendererConfig();
- return BarRenderer.internal(config: config, rendererId: rendererId);
- }
-
- /// This constructor is protected because it is used by child classes, which
- /// cannot call the factory in their own constructors.
- @protected
- BarRenderer.internal({BarRendererConfig config, String rendererId})
- : barRendererDecorator = config.barRendererDecorator,
- super(
- config: config,
- rendererId: rendererId,
- layoutPaintOrder: config.layoutPaintOrder);
-
- @override
- void configureSeries(List> seriesList) {
- assignMissingColors(getOrderedSeriesList(seriesList),
- emptyCategoryUsesSinglePalette: true);
- }
-
- DatumDetails addPositionToDetailsForSeriesDatum(
- DatumDetails details, SeriesDatum seriesDatum) {
- final series = details.series;
-
- final domainAxis = series.getAttr(domainAxisKey) as ImmutableAxis;
- final measureAxis = series.getAttr(measureAxisKey) as ImmutableAxis;
-
- final barGroupIndex = series.getAttr(barGroupIndexKey);
- final previousBarGroupWeight = series.getAttr(previousBarGroupWeightKey);
- final barGroupWeight = series.getAttr(barGroupWeightKey);
- final numBarGroups = series.getAttr(barGroupCountKey);
-
- final bounds = _getBarBounds(
- details.domain,
- domainAxis,
- domainAxis.rangeBand.round(),
- details.measure,
- details.measureOffset,
- measureAxis,
- barGroupIndex,
- previousBarGroupWeight,
- barGroupWeight,
- numBarGroups);
-
- Point chartPosition;
-
- if (renderingVertically) {
- chartPosition = Point(
- (bounds.left + (bounds.width / 2)).toDouble(), bounds.top.toDouble());
- } else {
- chartPosition = Point(
- isRtl ? bounds.left.toDouble() : bounds.right.toDouble(),
- (bounds.top + (bounds.height / 2)).toDouble());
- }
-
- return DatumDetails.from(details, chartPosition: chartPosition);
- }
-
- @override
- BarRendererElement getBaseDetails(dynamic datum, int index) {
- return BarRendererElement();
- }
-
- CornerStrategy get cornerStrategy {
- return (config as BarRendererConfig).cornerStrategy;
- }
-
- /// Generates an [AnimatedBar] to represent the previous and current state
- /// of one bar on the chart.
- @override
- AnimatedBar makeAnimatedBar(
- {String key,
- ImmutableSeries series,
- List dashPattern,
- dynamic datum,
- Color color,
- BarRendererElement details,
- D domainValue,
- ImmutableAxis domainAxis,
- int domainWidth,
- num measureValue,
- num measureOffsetValue,
- ImmutableAxis measureAxis,
- double measureAxisPosition,
- Color fillColor,
- FillPatternType fillPattern,
- double strokeWidthPx,
- int barGroupIndex,
- double previousBarGroupWeight,
- double barGroupWeight,
- int numBarGroups,
- bool measureIsNull,
- bool measureIsNegative}) {
- return AnimatedBar(
- key: key, datum: datum, series: series, domainValue: domainValue)
- ..setNewTarget(makeBarRendererElement(
- color: color,
- dashPattern: dashPattern,
- details: details,
- domainValue: domainValue,
- domainAxis: domainAxis,
- domainWidth: domainWidth,
- measureValue: measureValue,
- measureOffsetValue: measureOffsetValue,
- measureAxisPosition: measureAxisPosition,
- measureAxis: measureAxis,
- fillColor: fillColor,
- fillPattern: fillPattern,
- strokeWidthPx: strokeWidthPx,
- barGroupIndex: barGroupIndex,
- previousBarGroupWeight: previousBarGroupWeight,
- barGroupWeight: barGroupWeight,
- numBarGroups: numBarGroups,
- measureIsNull: measureIsNull,
- measureIsNegative: measureIsNegative));
- }
-
- /// Generates a [BarRendererElement] to represent the rendering data for one
- /// bar on the chart.
- @override
- BarRendererElement makeBarRendererElement(
- {Color color,
- List dashPattern,
- BarRendererElement details,
- D domainValue,
- ImmutableAxis domainAxis,
- int domainWidth,
- num measureValue,
- num measureOffsetValue,
- ImmutableAxis measureAxis,
- double measureAxisPosition,
- Color fillColor,
- FillPatternType fillPattern,
- double strokeWidthPx,
- int barGroupIndex,
- double previousBarGroupWeight,
- double barGroupWeight,
- int numBarGroups,
- bool measureIsNull,
- bool measureIsNegative}) {
- return BarRendererElement()
- ..color = color
- ..dashPattern = dashPattern
- ..fillColor = fillColor
- ..fillPattern = fillPattern
- ..measureAxisPosition = measureAxisPosition
- ..roundPx = details.roundPx
- ..strokeWidthPx = strokeWidthPx
- ..measureIsNull = measureIsNull
- ..measureIsNegative = measureIsNegative
- ..bounds = _getBarBounds(
- domainValue,
- domainAxis,
- domainWidth,
- measureValue,
- measureOffsetValue,
- measureAxis,
- barGroupIndex,
- previousBarGroupWeight,
- barGroupWeight,
- numBarGroups);
- }
-
- @override
- void paintBar(ChartCanvas canvas, double animationPercent,
- Iterable> barElements) {
- final bars = [];
-
- // When adjusting bars for stacked bar padding, do not modify the first bar
- // if rendering vertically and do not modify the last bar if rendering
- // horizontally.
- final unmodifiedBar =
- renderingVertically ? barElements.first : barElements.last;
-
- // Find the max bar width from each segment to calculate corner radius.
- int maxBarWidth = 0;
-
- var measureIsNegative = false;
-
- for (var bar in barElements) {
- var bounds = bar.bounds;
-
- measureIsNegative = measureIsNegative || bar.measureIsNegative;
-
- if (bar != unmodifiedBar) {
- bounds = renderingVertically
- ? Rectangle(
- bar.bounds.left,
- max(
- 0,
- bar.bounds.top +
- (measureIsNegative ? _stackedBarPadding : 0)),
- bar.bounds.width,
- max(0, bar.bounds.height - _stackedBarPadding),
- )
- : Rectangle(
- max(
- 0,
- bar.bounds.left +
- (measureIsNegative ? _stackedBarPadding : 0)),
- bar.bounds.top,
- max(0, bar.bounds.width - _stackedBarPadding),
- bar.bounds.height,
- );
- }
-
- bars.add(CanvasRect(bounds,
- dashPattern: bar.dashPattern,
- fill: bar.fillColor,
- pattern: bar.fillPattern,
- stroke: bar.color,
- strokeWidthPx: bar.strokeWidthPx));
-
- maxBarWidth = max(
- maxBarWidth, (renderingVertically ? bounds.width : bounds.height));
- }
-
- bool roundTopLeft;
- bool roundTopRight;
- bool roundBottomLeft;
- bool roundBottomRight;
-
- if (measureIsNegative) {
- // Negative bars should be rounded towards the negative axis direction.
- // In vertical mode, this is the bottom. In horizontal mode, this is the
- // left side of the chart for LTR, or the right side for RTL.
- roundTopLeft = !renderingVertically && !isRtl ? true : false;
- roundTopRight = !renderingVertically && isRtl ? true : false;
- roundBottomLeft = renderingVertically || !isRtl ? true : false;
- roundBottomRight = renderingVertically || isRtl ? true : false;
- } else {
- // Positive bars should be rounded towards the positive axis direction.
- // In vertical mode, this is the top. In horizontal mode, this is the
- // right side of the chart for LTR, or the left side for RTL.
- roundTopLeft = renderingVertically || isRtl ? true : false;
- roundTopRight = isRtl ? false : true;
- roundBottomLeft = isRtl ? true : false;
- roundBottomRight = renderingVertically || isRtl ? false : true;
- }
-
- final barStack = CanvasBarStack(
- bars,
- radius: cornerStrategy.getRadius(maxBarWidth),
- stackedBarPadding: _stackedBarPadding,
- roundTopLeft: roundTopLeft,
- roundTopRight: roundTopRight,
- roundBottomLeft: roundBottomLeft,
- roundBottomRight: roundBottomRight,
- );
-
- // If bar stack's range width is:
- // * Within the component bounds, then draw the bar stack.
- // * Partially out of component bounds, then clip the stack where it is out
- // of bounds.
- // * Fully out of component bounds, do not draw.
-
- final barOutsideBounds = renderingVertically
- ? barStack.fullStackRect.left < componentBounds.left ||
- barStack.fullStackRect.right > componentBounds.right
- : barStack.fullStackRect.top < componentBounds.top ||
- barStack.fullStackRect.bottom > componentBounds.bottom;
-
- // TODO: When we have initial viewport, add image test for
- // clipping.
- if (barOutsideBounds) {
- final clipBounds = _getBarStackBounds(barStack.fullStackRect);
-
- // Do not draw the bar stack if it is completely outside of the component
- // bounds.
- if (clipBounds.width <= 0 || clipBounds.height <= 0) {
- return;
- }
-
- canvas.setClipBounds(clipBounds);
- }
-
- canvas.drawBarStack(barStack, drawAreaBounds: componentBounds);
-
- if (barOutsideBounds) {
- canvas.resetClipBounds();
- }
-
- // Decorate the bar segments if there is a decorator.
- barRendererDecorator?.decorate(barElements, canvas, graphicsFactory,
- drawBounds: drawBounds,
- animationPercent: animationPercent,
- renderingVertically: renderingVertically,
- rtl: isRtl);
- }
-
- /// Calculate the clipping region for a rectangle that represents the full bar
- /// stack.
- Rectangle _getBarStackBounds(Rectangle barStackRect) {
- int left;
- int right;
- int top;
- int bottom;
-
- if (renderingVertically) {
- // Only clip at the start and end so that the bar's width stays within
- // the viewport, but any bar decorations above the bar can still show.
- left = max(componentBounds.left, barStackRect.left);
- right = min(componentBounds.right, barStackRect.right);
- top = barStackRect.top;
- bottom = barStackRect.bottom;
- } else {
- // Only clip at the top and bottom so that the bar's height stays within
- // the viewport, but any bar decorations to the right of the bar can still
- // show.
- left = barStackRect.left;
- right = barStackRect.right;
- top = max(componentBounds.top, barStackRect.top);
- bottom = min(componentBounds.bottom, barStackRect.bottom);
- }
-
- final width = right - left;
- final height = bottom - top;
-
- return Rectangle(left, top, width, height);
- }
-
- /// Generates a set of bounds that describe a bar.
- Rectangle _getBarBounds(
- D domainValue,
- ImmutableAxis domainAxis,
- int domainWidth,
- num measureValue,
- num measureOffsetValue,
- ImmutableAxis measureAxis,
- int barGroupIndex,
- double previousBarGroupWeight,
- double barGroupWeight,
- int numBarGroups) {
- // If no weights were passed in, default to equal weight per bar.
- if (barGroupWeight == null) {
- barGroupWeight = 1 / numBarGroups;
- previousBarGroupWeight = barGroupIndex * barGroupWeight;
- }
-
- // Calculate how wide each bar should be within the group of bars. If we
- // only have one series, or are stacked, then barWidth should equal
- // domainWidth.
- int spacingLoss = (_barGroupInnerPadding * (numBarGroups - 1));
- int barWidth = ((domainWidth - spacingLoss) * barGroupWeight).round();
-
- // Make sure that bars are at least one pixel wide, so that they will always
- // be visible on the chart. Ideally we should do something clever with the
- // size of the chart, and the density and periodicity of the data, but this
- // at least ensures that dense charts still have visible data.
- barWidth = max(1, barWidth);
-
- // Flip bar group index for calculating location on the domain axis if RTL.
- final adjustedBarGroupIndex =
- isRtl ? numBarGroups - barGroupIndex - 1 : barGroupIndex;
-
- // Calculate the start and end of the bar, taking into account accumulated
- // padding for grouped bars.
- int previousAverageWidth = adjustedBarGroupIndex > 0
- ? ((domainWidth - spacingLoss) *
- (previousBarGroupWeight / adjustedBarGroupIndex))
- .round()
- : 0;
-
- int domainStart = (domainAxis.getLocation(domainValue) -
- (domainWidth / 2) +
- (previousAverageWidth + _barGroupInnerPadding) *
- adjustedBarGroupIndex)
- .round();
-
- int domainEnd = domainStart + barWidth;
-
- measureValue = measureValue != null ? measureValue : 0;
-
- // Calculate measure locations. Stacked bars should have their
- // offset calculated previously.
- int measureStart;
- int measureEnd;
- if (measureValue < 0) {
- measureEnd = measureAxis.getLocation(measureOffsetValue).round();
- measureStart =
- measureAxis.getLocation(measureValue + measureOffsetValue).round();
- } else {
- measureStart = measureAxis.getLocation(measureOffsetValue).round();
- measureEnd =
- measureAxis.getLocation(measureValue + measureOffsetValue).round();
- }
-
- Rectangle bounds;
- if (this.renderingVertically) {
- // Rectangle clamps to zero width/height
- bounds = Rectangle(domainStart, measureEnd, domainEnd - domainStart,
- measureStart - measureEnd);
- } else {
- // Rectangle clamps to zero width/height
- bounds = Rectangle(min(measureStart, measureEnd), domainStart,
- (measureEnd - measureStart).abs(), domainEnd - domainStart);
- }
- return bounds;
- }
-
- @override
- Rectangle getBoundsForBar(BarRendererElement bar) => bar.bounds;
-}
-
-abstract class ImmutableBarRendererElement {
- ImmutableSeries get series;
-
- dynamic get datum;
-
- int get index;
-
- Rectangle get bounds;
-}
-
-class BarRendererElement extends BaseBarRendererElement
- implements ImmutableBarRendererElement {
- ImmutableSeries series;
- Rectangle bounds;
- int roundPx;
- int index;
- dynamic _datum;
-
- dynamic get datum => _datum;
-
- set datum(dynamic datum) {
- _datum = datum;
- index = series?.data?.indexOf(datum);
- }
-
- BarRendererElement();
-
- BarRendererElement.clone(BarRendererElement other) : super.clone(other) {
- series = other.series;
- bounds = other.bounds;
- roundPx = other.roundPx;
- index = other.index;
- _datum = other._datum;
- }
-
- @override
- void updateAnimationPercent(BaseBarRendererElement previous,
- BaseBarRendererElement target, double animationPercent) {
- final BarRendererElement localPrevious = previous;
- final BarRendererElement localTarget = target;
-
- final previousBounds = localPrevious.bounds;
- final targetBounds = localTarget.bounds;
-
- var top = ((targetBounds.top - previousBounds.top) * animationPercent) +
- previousBounds.top;
- var right =
- ((targetBounds.right - previousBounds.right) * animationPercent) +
- previousBounds.right;
- var bottom =
- ((targetBounds.bottom - previousBounds.bottom) * animationPercent) +
- previousBounds.bottom;
- var left = ((targetBounds.left - previousBounds.left) * animationPercent) +
- previousBounds.left;
-
- bounds = Rectangle(left.round(), top.round(), (right - left).round(),
- (bottom - top).round());
-
- roundPx = localTarget.roundPx;
-
- super.updateAnimationPercent(previous, target, animationPercent);
- }
-}
-
-class AnimatedBar extends BaseAnimatedBar> {
- AnimatedBar(
- {@required String key,
- @required dynamic datum,
- @required ImmutableSeries series,
- @required D domainValue})
- : super(key: key, datum: datum, series: series, domainValue: domainValue);
-
- @override
- animateElementToMeasureAxisPosition(BaseBarRendererElement target) {
- final BarRendererElement localTarget = target;
-
- // TODO: Animate out bars in the middle of a stack.
- localTarget.bounds = Rectangle(
- localTarget.bounds.left + (localTarget.bounds.width / 2).round(),
- localTarget.measureAxisPosition.round(),
- 0,
- 0);
- }
-
- BarRendererElement getCurrentBar(double animationPercent) {
- final BarRendererElement bar = super.getCurrentBar(animationPercent);
-
- // Update with series and datum information to pass to bar decorator.
- bar.series = series;
- bar.datum = datum;
-
- return bar;
- }
-
- @override
- BarRendererElement clone(BarRendererElement bar) =>
- BarRendererElement.clone(bar);
-}
diff --git a/web/charts/common/lib/src/chart/bar/bar_renderer_config.dart b/web/charts/common/lib/src/chart/bar/bar_renderer_config.dart
deleted file mode 100644
index 123a83ae7..000000000
--- a/web/charts/common/lib/src/chart/bar/bar_renderer_config.dart
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2018 the Charts project authors. Please see the AUTHORS file
-// for details.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import '../../common/symbol_renderer.dart';
-import '../common/chart_canvas.dart' show FillPatternType;
-import '../layout/layout_view.dart' show LayoutViewPaintOrder;
-import 'bar_renderer.dart' show BarRenderer;
-import 'bar_renderer_decorator.dart' show BarRendererDecorator;
-import 'base_bar_renderer_config.dart'
- show BarGroupingType, BaseBarRendererConfig;
-
-/// Configuration for a bar renderer.
-class BarRendererConfig extends BaseBarRendererConfig {
- /// Strategy for determining the corner radius of a bar.
- final CornerStrategy cornerStrategy;
-
- /// Decorator for optionally decorating painted bars.
- final BarRendererDecorator barRendererDecorator;
-
- BarRendererConfig({
- String customRendererId,
- CornerStrategy cornerStrategy,
- FillPatternType fillPattern,
- BarGroupingType groupingType,
- int layoutPaintOrder = LayoutViewPaintOrder.bar,
- int minBarLengthPx = 0,
- double stackHorizontalSeparator,
- double strokeWidthPx = 0.0,
- this.barRendererDecorator,
- SymbolRenderer symbolRenderer,
- List weightPattern,
- }) : cornerStrategy = cornerStrategy ?? const ConstCornerStrategy(2),
- super(
- customRendererId: customRendererId,
- groupingType: groupingType ?? BarGroupingType.grouped,
- layoutPaintOrder: layoutPaintOrder,
- minBarLengthPx: minBarLengthPx,
- fillPattern: fillPattern,
- stackHorizontalSeparator: stackHorizontalSeparator,
- strokeWidthPx: strokeWidthPx,
- symbolRenderer: symbolRenderer,
- weightPattern: weightPattern,
- );
-
- @override
- BarRenderer build() {
- return BarRenderer(config: this, rendererId: customRendererId);
- }
-
- @override
- bool operator ==(other) {
- if (identical(this, other)) {
- return true;
- }
- if (!(other is BarRendererConfig)) {
- return false;
- }
- return other.cornerStrategy == cornerStrategy && super == (other);
- }
-
- @override
- int get hashCode {
- var hash = super.hashCode;
- hash = hash * 31 + (cornerStrategy?.hashCode ?? 0);
- return hash;
- }
-}
-
-abstract class CornerStrategy {
- /// Returns the radius of the rounded corners in pixels.
- int getRadius(int barWidth);
-}
-
-/// Strategy for constant corner radius.
-class ConstCornerStrategy implements CornerStrategy {
- final int radius;
-
- const ConstCornerStrategy(this.radius);
-
- @override
- int getRadius(_) => radius;
-}
-
-/// Strategy for no corner radius.
-class NoCornerStrategy extends ConstCornerStrategy {
- const NoCornerStrategy() : super(0);
-}
diff --git a/web/charts/common/lib/src/chart/bar/bar_renderer_decorator.dart b/web/charts/common/lib/src/chart/bar/bar_renderer_decorator.dart
deleted file mode 100644
index ecf551528..000000000
--- a/web/charts/common/lib/src/chart/bar/bar_renderer_decorator.dart
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2018 the Charts project authors. Please see the AUTHORS file
-// for details.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import 'dart:math' show Rectangle;
-
-import 'package:meta/meta.dart' show required;
-
-import '../../common/graphics_factory.dart' show GraphicsFactory;
-import '../common/chart_canvas.dart' show ChartCanvas;
-import 'bar_renderer.dart' show ImmutableBarRendererElement;
-
-/// Decorates bars after the bars have already been painted.
-abstract class BarRendererDecorator {
- const BarRendererDecorator();
-
- void decorate(Iterable> barElements,
- ChartCanvas canvas, GraphicsFactory graphicsFactory,
- {@required Rectangle drawBounds,
- @required double animationPercent,
- @required bool renderingVertically,
- bool rtl = false});
-}
diff --git a/web/charts/common/lib/src/chart/bar/bar_target_line_renderer.dart b/web/charts/common/lib/src/chart/bar/bar_target_line_renderer.dart
deleted file mode 100644
index 77103e87a..000000000
--- a/web/charts/common/lib/src/chart/bar/bar_target_line_renderer.dart
+++ /dev/null
@@ -1,422 +0,0 @@
-// Copyright 2018 the Charts project authors. Please see the AUTHORS file
-// for details.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import 'dart:math' show Point, Rectangle, max, min;
-
-import 'package:meta/meta.dart' show required;
-
-import '../../common/color.dart' show Color;
-import '../cartesian/axis/axis.dart'
- show ImmutableAxis, domainAxisKey, measureAxisKey;
-import '../common/chart_canvas.dart' show ChartCanvas, FillPatternType;
-import '../common/datum_details.dart' show DatumDetails;
-import '../common/processed_series.dart' show ImmutableSeries, MutableSeries;
-import '../common/series_datum.dart' show SeriesDatum;
-import 'bar_target_line_renderer_config.dart' show BarTargetLineRendererConfig;
-import 'base_bar_renderer.dart'
- show
- BaseBarRenderer,
- barGroupCountKey,
- barGroupIndexKey,
- previousBarGroupWeightKey,
- barGroupWeightKey;
-import 'base_bar_renderer_element.dart'
- show BaseAnimatedBar, BaseBarRendererElement;
-
-/// Renders series data as a series of bar target lines.
-///
-/// Usually paired with a BarRenderer to display target metrics alongside actual
-/// metrics.
-class BarTargetLineRenderer extends BaseBarRenderer> {
- /// If we are grouped, use this spacing between the bars in a group.
- final _barGroupInnerPadding = 2;
-
- /// Standard color for all bar target lines.
- final _color = Color(r: 0, g: 0, b: 0, a: 153);
-
- factory BarTargetLineRenderer(
- {BarTargetLineRendererConfig config,
- String rendererId = 'barTargetLine'}) {
- config ??= BarTargetLineRendererConfig();
- return BarTargetLineRenderer._internal(
- config: config, rendererId: rendererId);
- }
-
- BarTargetLineRenderer._internal(
- {BarTargetLineRendererConfig config, String rendererId})
- : super(
- config: config,
- rendererId: rendererId,
- layoutPaintOrder: config.layoutPaintOrder);
-
- @override
- void configureSeries(List> seriesList) {
- seriesList.forEach((series) {
- series.colorFn ??= (_) => _color;
- series.fillColorFn ??= (_) => _color;
- });
- }
-
- DatumDetails addPositionToDetailsForSeriesDatum(
- DatumDetails details, SeriesDatum seriesDatum) {
- final series = details.series;
-
- final domainAxis = series.getAttr(domainAxisKey) as ImmutableAxis;
- final measureAxis = series.getAttr(measureAxisKey) as ImmutableAxis;
-
- final barGroupIndex = series.getAttr(barGroupIndexKey);
- final previousBarGroupWeight = series.getAttr(previousBarGroupWeightKey);
- final barGroupWeight = series.getAttr(barGroupWeightKey);
- final numBarGroups = series.getAttr(barGroupCountKey);
-
- final points = _getTargetLinePoints(
- details.domain,
- domainAxis,
- domainAxis.rangeBand.round(),
- details.measure,
- details.measureOffset,
- measureAxis,
- barGroupIndex,
- previousBarGroupWeight,
- barGroupWeight,
- numBarGroups);
-
- Point chartPosition;
-
- if (renderingVertically) {
- chartPosition = Point(
- (points[0].x + (points[1].x - points[0].x) / 2).toDouble(),
- points[0].y.toDouble());
- } else {
- chartPosition = Point(points[0].x.toDouble(),
- (points[0].y + (points[1].y - points[0].y) / 2).toDouble());
- }
-
- return DatumDetails.from(details, chartPosition: chartPosition);
- }
-
- @override
- _BarTargetLineRendererElement getBaseDetails(dynamic datum, int index) {
- final BarTargetLineRendererConfig localConfig = config;
- return _BarTargetLineRendererElement()
- ..roundEndCaps = localConfig.roundEndCaps;
- }
-
- /// Generates an [_AnimatedBarTargetLine] to represent the previous and
- /// current state of one bar target line on the chart.
- @override
- _AnimatedBarTargetLine makeAnimatedBar(
- {String key,
- ImmutableSeries series,
- dynamic datum,
- Color color,
- List dashPattern,
- _BarTargetLineRendererElement details,
- D domainValue,
- ImmutableAxis domainAxis,
- int domainWidth,
- num measureValue,
- num measureOffsetValue,
- ImmutableAxis measureAxis,
- double measureAxisPosition,
- Color fillColor,
- FillPatternType fillPattern,
- int barGroupIndex,
- double previousBarGroupWeight,
- double barGroupWeight,
- int numBarGroups,
- double strokeWidthPx,
- bool measureIsNull,
- bool measureIsNegative}) {
- return _AnimatedBarTargetLine(
- key: key, datum: datum, series: series, domainValue: domainValue)
- ..setNewTarget(makeBarRendererElement(
- color: color,
- details: details,
- dashPattern: dashPattern,
- domainValue: domainValue,
- domainAxis: domainAxis,
- domainWidth: domainWidth,
- measureValue: measureValue,
- measureOffsetValue: measureOffsetValue,
- measureAxisPosition: measureAxisPosition,
- measureAxis: measureAxis,
- fillColor: fillColor,
- fillPattern: fillPattern,
- strokeWidthPx: strokeWidthPx,
- barGroupIndex: barGroupIndex,
- previousBarGroupWeight: previousBarGroupWeight,
- barGroupWeight: barGroupWeight,
- numBarGroups: numBarGroups,
- measureIsNull: measureIsNull,
- measureIsNegative: measureIsNegative));
- }
-
- /// Generates a [_BarTargetLineRendererElement] to represent the rendering
- /// data for one bar target line on the chart.
- @override
- _BarTargetLineRendererElement makeBarRendererElement(
- {Color color,
- List dashPattern,
- _BarTargetLineRendererElement details,
- D domainValue,
- ImmutableAxis domainAxis,
- int domainWidth,
- num measureValue,
- num measureOffsetValue,
- ImmutableAxis measureAxis,
- double measureAxisPosition,
- Color fillColor,
- FillPatternType fillPattern,
- double strokeWidthPx,
- int barGroupIndex,
- double previousBarGroupWeight,
- double barGroupWeight,
- int numBarGroups,
- bool measureIsNull,
- bool measureIsNegative}) {
- return _BarTargetLineRendererElement()
- ..color = color
- ..dashPattern = dashPattern
- ..fillColor = fillColor
- ..fillPattern = fillPattern
- ..measureAxisPosition = measureAxisPosition
- ..roundEndCaps = details.roundEndCaps
- ..strokeWidthPx = strokeWidthPx
- ..measureIsNull = measureIsNull
- ..measureIsNegative = measureIsNegative
- ..points = _getTargetLinePoints(
- domainValue,
- domainAxis,
- domainWidth,
- measureValue,
- measureOffsetValue,
- measureAxis,
- barGroupIndex,
- previousBarGroupWeight,
- barGroupWeight,
- numBarGroups);
- }
-
- @override
- void paintBar(
- ChartCanvas canvas,
- double animationPercent,
- Iterable<_BarTargetLineRendererElement> barElements,
- ) {
- barElements.forEach((bar) {
- // TODO: Combine common line attributes into
- // GraphicsFactory.lineStyle or similar.
- canvas.drawLine(
- clipBounds: drawBounds,
- points: bar.points,
- stroke: bar.color,
- roundEndCaps: bar.roundEndCaps,
- strokeWidthPx: bar.strokeWidthPx);
- });
- }
-
- /// Generates a set of points that describe a bar target line.
- List> _getTargetLinePoints(
- D domainValue,
- ImmutableAxis domainAxis,
- int domainWidth,
- num measureValue,
- num measureOffsetValue,
- ImmutableAxis measureAxis,
- int barGroupIndex,
- double previousBarGroupWeight,
- double barGroupWeight,
- int numBarGroups) {
- // If no weights were passed in, default to equal weight per bar.
- if (barGroupWeight == null) {
- barGroupWeight = 1 / numBarGroups;
- previousBarGroupWeight = barGroupIndex * barGroupWeight;
- }
-
- final BarTargetLineRendererConfig localConfig = config;
-
- // Calculate how wide each bar target line should be within the group of
- // bar target lines. If we only have one series, or are stacked, then
- // barWidth should equal domainWidth.
- int spacingLoss = (_barGroupInnerPadding * (numBarGroups - 1));
- int barWidth = ((domainWidth - spacingLoss) * barGroupWeight).round();
-
- // Get the overdraw boundaries.
- var overDrawOuterPx = localConfig.overDrawOuterPx;
- var overDrawPx = localConfig.overDrawPx;
-
- int overDrawStartPx = (barGroupIndex == 0) && overDrawOuterPx != null
- ? overDrawOuterPx
- : overDrawPx;
-
- int overDrawEndPx =
- (barGroupIndex == numBarGroups - 1) && overDrawOuterPx != null
- ? overDrawOuterPx
- : overDrawPx;
-
- // Flip bar group index for calculating location on the domain axis if RTL.
- final adjustedBarGroupIndex =
- isRtl ? numBarGroups - barGroupIndex - 1 : barGroupIndex;
-
- // Calculate the start and end of the bar target line, taking into account
- // accumulated padding for grouped bars.
- num previousAverageWidth = adjustedBarGroupIndex > 0
- ? ((domainWidth - spacingLoss) *
- (previousBarGroupWeight / adjustedBarGroupIndex))
- .round()
- : 0;
-
- int domainStart = (domainAxis.getLocation(domainValue) -
- (domainWidth / 2) +
- (previousAverageWidth + _barGroupInnerPadding) *
- adjustedBarGroupIndex -
- overDrawStartPx)
- .round();
-
- int domainEnd = domainStart + barWidth + overDrawStartPx + overDrawEndPx;
-
- measureValue = measureValue != null ? measureValue : 0;
-
- // Calculate measure locations. Stacked bars should have their
- // offset calculated previously.
- int measureStart =
- measureAxis.getLocation(measureValue + measureOffsetValue).round();
-
- List> points;
- if (renderingVertically) {
- points = [
- Point(domainStart, measureStart),
- Point(domainEnd, measureStart)
- ];
- } else {
- points = [
- Point(measureStart, domainStart),
- Point(measureStart, domainEnd)
- ];
- }
- return points;
- }
-
- @override
- Rectangle getBoundsForBar(_BarTargetLineRendererElement bar) {
- final points = bar.points;
- int top;
- int bottom;
- int left;
- int right;
- points.forEach((p) {
- top = top != null ? min(top, p.y) : p.y;
- left = left != null ? min(left, p.x) : p.x;
- bottom = bottom != null ? max(bottom, p.y) : p.y;
- right = right != null ? max(right, p.x) : p.x;
- });
- return Rectangle(left, top, right - left, bottom - top);
- }
-}
-
-class _BarTargetLineRendererElement extends BaseBarRendererElement {
- List> points;
- bool roundEndCaps;
-
- _BarTargetLineRendererElement();
-
- _BarTargetLineRendererElement.clone(_BarTargetLineRendererElement other)
- : super.clone(other) {
- points = List>.from(other.points);
- roundEndCaps = other.roundEndCaps;
- }
-
- @override
- void updateAnimationPercent(BaseBarRendererElement previous,
- BaseBarRendererElement target, double animationPercent) {
- final _BarTargetLineRendererElement localPrevious = previous;
- final _BarTargetLineRendererElement localTarget = target;
-
- final previousPoints = localPrevious.points;
- final targetPoints = localTarget.points;
-
- Point lastPoint;
-
- int pointIndex;
- for (pointIndex = 0; pointIndex < targetPoints.length; pointIndex++) {
- var targetPoint = targetPoints[pointIndex];
-
- // If we have more points than the previous line, animate in the new point
- // by starting its measure position at the last known official point.
- Point previousPoint;
- if (previousPoints.length - 1 >= pointIndex) {
- previousPoint = previousPoints[pointIndex];
- lastPoint = previousPoint;
- } else {
- previousPoint = Point(targetPoint.x, lastPoint.y);
- }
-
- var x = ((targetPoint.x - previousPoint.x) * animationPercent) +
- previousPoint.x;
-
- var y = ((targetPoint.y - previousPoint.y) * animationPercent) +
- previousPoint.y;
-
- if (points.length - 1 >= pointIndex) {
- points[pointIndex] = Point(x.round(), y.round());
- } else {
- points.add(Point(x.round(), y.round()));
- }
- }
-
- // Removing extra points that don't exist anymore.
- if (pointIndex < points.length) {
- points.removeRange(pointIndex, points.length);
- }
-
- strokeWidthPx = ((localTarget.strokeWidthPx - localPrevious.strokeWidthPx) *
- animationPercent) +
- localPrevious.strokeWidthPx;
-
- roundEndCaps = localTarget.roundEndCaps;
-
- super.updateAnimationPercent(previous, target, animationPercent);
- }
-}
-
-class _AnimatedBarTargetLine
- extends BaseAnimatedBar {
- _AnimatedBarTargetLine(
- {@required String key,
- @required dynamic datum,
- @required ImmutableSeries series,
- @required D domainValue})
- : super(key: key, datum: datum, series: series, domainValue: domainValue);
-
- @override
- animateElementToMeasureAxisPosition(BaseBarRendererElement target) {
- final _BarTargetLineRendererElement localTarget = target;
-
- final newPoints = >[];
- for (var index = 0; index < localTarget.points.length; index++) {
- final targetPoint = localTarget.points[index];
-
- newPoints.add(
- Point(targetPoint.x, localTarget.measureAxisPosition.round()));
- }
- localTarget.points = newPoints;
- }
-
- @override
- _BarTargetLineRendererElement clone(_BarTargetLineRendererElement bar) =>
- _BarTargetLineRendererElement.clone(bar);
-}
diff --git a/web/charts/common/lib/src/chart/bar/bar_target_line_renderer_config.dart b/web/charts/common/lib/src/chart/bar/bar_target_line_renderer_config.dart
deleted file mode 100644
index 293d07cb3..000000000
--- a/web/charts/common/lib/src/chart/bar/bar_target_line_renderer_config.dart
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2018 the Charts project authors. Please see the AUTHORS file
-// for details.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import '../../common/symbol_renderer.dart'
- show SymbolRenderer, LineSymbolRenderer;
-import '../layout/layout_view.dart' show LayoutViewPaintOrder;
-import 'bar_target_line_renderer.dart' show BarTargetLineRenderer;
-import 'base_bar_renderer_config.dart'
- show BarGroupingType, BaseBarRendererConfig;
-
-/// Configuration for a bar target line renderer.
-class BarTargetLineRendererConfig extends BaseBarRendererConfig {
- /// The number of pixels that the line will extend beyond the bandwidth at the
- /// edges of the bar group.
- ///
- /// If set, this overrides overDrawPx for the beginning side of the first bar
- /// target line in the group, and the ending side of the last bar target line.
- /// overDrawPx will be used for overdrawing the target lines for interior
- /// sides of the bars.
- final int overDrawOuterPx;
-
- /// The number of pixels that the line will extend beyond the bandwidth for
- /// every bar in a group.
- final int overDrawPx;
-
- /// Whether target lines should have round end caps, or square if false.
- final bool roundEndCaps;
-
- BarTargetLineRendererConfig(
- {String customRendererId,
- List dashPattern,
- groupingType = BarGroupingType.grouped,
- int layoutPaintOrder = LayoutViewPaintOrder.barTargetLine,
- int minBarLengthPx = 0,
- this.overDrawOuterPx,
- this.overDrawPx = 0,
- this.roundEndCaps = true,
- double strokeWidthPx = 3.0,
- SymbolRenderer symbolRenderer,
- List weightPattern})
- : super(
- customRendererId: customRendererId,
- dashPattern: dashPattern,
- groupingType: groupingType,
- layoutPaintOrder: layoutPaintOrder,
- minBarLengthPx: minBarLengthPx,
- strokeWidthPx: strokeWidthPx,
- symbolRenderer: symbolRenderer ?? LineSymbolRenderer(),
- weightPattern: weightPattern,
- );
-
- @override
- BarTargetLineRenderer build() {
- return BarTargetLineRenderer(config: this, rendererId: customRendererId);
- }
-
- @override
- bool operator ==(other) {
- if (identical(this, other)) {
- return true;
- }
- if (!(other is BarTargetLineRendererConfig)) {
- return false;
- }
- return other.overDrawOuterPx == overDrawOuterPx &&
- other.overDrawPx == overDrawPx &&
- other.roundEndCaps == roundEndCaps &&
- super == (other);
- }
-
- @override
- int get hashCode {
- var hash = 1;
- hash = hash * 31 + (overDrawOuterPx?.hashCode ?? 0);
- hash = hash * 31 + (overDrawPx?.hashCode ?? 0);
- hash = hash * 31 + (roundEndCaps?.hashCode ?? 0);
- return hash;
- }
-}
diff --git a/web/charts/common/lib/src/chart/bar/base_bar_renderer.dart b/web/charts/common/lib/src/chart/bar/base_bar_renderer.dart
deleted file mode 100644
index ff44af57a..000000000
--- a/web/charts/common/lib/src/chart/bar/base_bar_renderer.dart
+++ /dev/null
@@ -1,797 +0,0 @@
-// Copyright 2018 the Charts project authors. Please see the AUTHORS file
-// for details.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import 'dart:collection' show LinkedHashMap, HashSet;
-import 'dart:math' show Point, Rectangle, max;
-
-import 'package:meta/meta.dart' show protected, required;
-
-import '../../common/color.dart' show Color;
-import '../../common/math.dart' show clamp;
-import '../../common/symbol_renderer.dart' show RoundedRectSymbolRenderer;
-import '../../data/series.dart' show AttributeKey;
-import '../cartesian/axis/axis.dart'
- show ImmutableAxis, OrdinalAxis, domainAxisKey, measureAxisKey;
-import '../cartesian/axis/scale.dart' show RangeBandConfig;
-import '../cartesian/cartesian_renderer.dart' show BaseCartesianRenderer;
-import '../common/base_chart.dart' show BaseChart;
-import '../common/chart_canvas.dart' show ChartCanvas, FillPatternType;
-import '../common/datum_details.dart' show DatumDetails;
-import '../common/processed_series.dart' show ImmutableSeries, MutableSeries;
-import 'base_bar_renderer_config.dart' show BaseBarRendererConfig;
-import 'base_bar_renderer_element.dart'
- show BaseAnimatedBar, BaseBarRendererElement;
-
-const barGroupIndexKey = AttributeKey('BarRenderer.barGroupIndex');
-
-const barGroupCountKey = AttributeKey('BarRenderer.barGroupCount');
-
-const barGroupWeightKey = AttributeKey('BarRenderer.barGroupWeight');
-
-const previousBarGroupWeightKey =
- AttributeKey('BarRenderer.previousBarGroupWeight');
-
-const stackKeyKey = AttributeKey('BarRenderer.stackKey');
-
-const barElementsKey =
- AttributeKey>('BarRenderer.elements');
-
-/// Base class for bar renderers that implements common stacking and grouping
-/// logic.
-///
-/// Bar renderers support 4 different modes of rendering multiple series on the
-/// chart, configured by the grouped and stacked flags.
-/// * grouped - Render bars for each series that shares a domain value
-/// side-by-side.
-/// * stacked - Render bars for each series that shares a domain value in a
-/// stack, ordered in the same order as the series list.
-/// * grouped-stacked: Render bars for each series that shares a domain value in
-/// a group of bar stacks. Each stack will contain all the series that share a
-/// series category.
-/// * floating style - When grouped and stacked are both false, all bars that
-/// share a domain value will be rendered in the same domain space. Each datum
-/// should be configured with a measure offset to position its bar along the
-/// measure axis. Bars will freely overlap if their measure values and measure
-/// offsets overlap. Note that bars for each series will be rendered in order,
-/// such that bars from the last series will be "on top" of bars from previous
-/// series.
-abstract class BaseBarRenderer> extends BaseCartesianRenderer {
- final BaseBarRendererConfig config;
-
- @protected
- BaseChart chart;
-
- /// Store a map of domain+barGroupIndex+category index to bars in a stack.
- ///
- /// This map is used to render all the bars in a stack together, to account
- /// for rendering effects that need to take the full stack into account (e.g.
- /// corner rounding).
- ///
- /// [LinkedHashMap] is used to render the bars on the canvas in the same order
- /// as the data was given to the chart. For the case where both grouping and
- /// stacking are disabled, this means that bars for data later in the series
- /// will be drawn "on top of" bars earlier in the series.
- final _barStackMap = LinkedHashMap>();
-
- // Store a list of bar stacks that exist in the series data.
- //
- // This list will be used to remove any AnimatingBars that were rendered in
- // previous draw cycles, but no longer have a corresponding datum in the new
- // data.
- final _currentKeys = [];
-
- /// Stores a list of stack keys for each group key.
- final _currentGroupsStackKeys = LinkedHashMap>();
-
- /// Optimization for getNearest to avoid scanning all data if possible.
- ImmutableAxis _prevDomainAxis;
-
- BaseBarRenderer(
- {@required this.config, String rendererId, int layoutPaintOrder})
- : super(
- rendererId: rendererId,
- layoutPaintOrder: layoutPaintOrder,
- symbolRenderer: config?.symbolRenderer ?? RoundedRectSymbolRenderer(),
- );
-
- @override
- void preprocessSeries(List> seriesList) {
- var barGroupIndex = 0;
-
- // Maps used to store the final measure offset of the previous series, for
- // each domain value.
- final posDomainToStackKeyToDetailsMap = {};
- final negDomainToStackKeyToDetailsMap = {};
- final categoryToIndexMap = {};
-
- // Keep track of the largest bar stack size. This should be 1 for grouped
- // bars, and it should be the size of the tallest stack for stacked or
- // grouped stacked bars.
- var maxBarStackSize = 0;
-
- final orderedSeriesList = getOrderedSeriesList(seriesList);
-
- orderedSeriesList.forEach((series) {
- var elements = [];
-
- var domainFn = series.domainFn;
- var measureFn = series.measureFn;
- var measureOffsetFn = series.measureOffsetFn;
- var fillPatternFn = series.fillPatternFn;
- var strokeWidthPxFn = series.strokeWidthPxFn;
-
- series.dashPatternFn ??= (_) => config.dashPattern;
-
- // Identifies which stack the series will go in, by default a single
- // stack.
- var stackKey = '__defaultKey__';
-
- // Override the stackKey with seriesCategory if we are GROUPED_STACKED
- // so we have a way to choose which series go into which stacks.
- if (config.grouped && config.stacked) {
- if (series.seriesCategory != null) {
- stackKey = series.seriesCategory;
- }
-
- barGroupIndex = categoryToIndexMap[stackKey];
- if (barGroupIndex == null) {
- barGroupIndex = categoryToIndexMap.length;
- categoryToIndexMap[stackKey] = barGroupIndex;
- }
- }
-
- var needsMeasureOffset = false;
-
- for (var barIndex = 0; barIndex < series.data.length; barIndex++) {
- dynamic datum = series.data[barIndex];
- final details = getBaseDetails(datum, barIndex);
-
- details.barStackIndex = 0;
- details.measureOffset = 0;
-
- if (fillPatternFn != null) {
- details.fillPattern = fillPatternFn(barIndex);
- } else {
- details.fillPattern = config.fillPattern;
- }
-
- if (strokeWidthPxFn != null) {
- details.strokeWidthPx = strokeWidthPxFn(barIndex).toDouble();
- } else {
- details.strokeWidthPx = config.strokeWidthPx;
- }
-
- // When stacking is enabled, adjust the measure offset for each domain
- // value in each series by adding up the measures and offsets of lower
- // series.
- if (config.stacked) {
- needsMeasureOffset = true;
- var domain = domainFn(barIndex);
- var measure = measureFn(barIndex);
-
- // We will render positive bars in one stack, and negative bars in a
- // separate stack. Keep track of the measure offsets for these stacks
- // independently.
- var domainToCategoryToDetailsMap = measure == null || measure >= 0
- ? posDomainToStackKeyToDetailsMap
- : negDomainToStackKeyToDetailsMap;
-
- var categoryToDetailsMap =
- domainToCategoryToDetailsMap.putIfAbsent(domain, () => {});
-
- var prevDetail = categoryToDetailsMap[stackKey];
-
- if (prevDetail != null) {
- details.barStackIndex = prevDetail.barStackIndex + 1;
- }
-
- details.cumulativeTotal = measure != null ? measure : 0;
-
- // Get the previous series' measure offset.
- var measureOffset = measureOffsetFn(barIndex);
- if (prevDetail != null) {
- measureOffset += prevDetail.measureOffsetPlusMeasure;
-
- details.cumulativeTotal += prevDetail.cumulativeTotal;
- }
-
- // And overwrite the details measure offset.
- details.measureOffset = measureOffset;
- var measureValue = (measure != null ? measure : 0);
- details.measureOffsetPlusMeasure = measureOffset + measureValue;
-
- categoryToDetailsMap[stackKey] = details;
- }
-
- maxBarStackSize = max(maxBarStackSize, details.barStackIndex + 1);
-
- elements.add(details);
- }
-
- if (needsMeasureOffset) {
- // Override the measure offset function to return the measure offset we
- // calculated for each datum. This already includes any measure offset
- // that was configured in the series data.
- series.measureOffsetFn = (index) => elements[index].measureOffset;
- }
-
- series.setAttr(barGroupIndexKey, barGroupIndex);
- series.setAttr(stackKeyKey, stackKey);
- series.setAttr(barElementsKey, elements);
-
- if (config.grouped) {
- barGroupIndex++;
- }
- });
-
- // Compute number of bar groups. This must be done after we have processed
- // all of the series once, so that we know how many categories we have.
- var numBarGroups = 0;
- if (config.grouped && config.stacked) {
- // For grouped stacked bars, categoryToIndexMap effectively one list per
- // group of stacked bars.
- numBarGroups = categoryToIndexMap.length;
- } else if (config.stacked) {
- numBarGroups = 1;
- } else {
- numBarGroups = seriesList.length;
- }
-
- // Compute bar group weights.
- final barWeights = _calculateBarWeights(numBarGroups);
-
- seriesList.forEach((series) {
- series.setAttr(barGroupCountKey, numBarGroups);
-
- if (barWeights.isNotEmpty) {
- final barGroupIndex = series.getAttr(barGroupIndexKey);
- final barWeight = barWeights[barGroupIndex];
-
- // In RTL mode, we need to grab the weights for the bars that follow
- // this datum in the series (instead of precede it). The first datum is
- // physically positioned on the canvas to the right of all the rest of
- // the bar group data that follows it.
- final previousBarWeights = isRtl
- ? barWeights.getRange(barGroupIndex + 1, numBarGroups)
- : barWeights.getRange(0, barGroupIndex);
-
- final previousBarWeight = previousBarWeights.isNotEmpty
- ? previousBarWeights.reduce((a, b) => a + b)
- : 0.0;
-
- series.setAttr(barGroupWeightKey, barWeight);
- series.setAttr(previousBarGroupWeightKey, previousBarWeight);
- }
- });
- }
-
- /// Calculates bar weights for a list of series from [config.weightPattern].
- ///
- /// If [config.weightPattern] is not set, then this will assign a weight
- /// proportional to the number of bar groups for every series.
- List _calculateBarWeights(int numBarGroups) {
- // Set up bar weights for each series as a ratio of the total weight.
- final weights = [];
-
- if (config.weightPattern != null) {
- if (numBarGroups > config.weightPattern.length) {
- throw ArgumentError('Number of series exceeds length of weight '
- 'pattern ${config.weightPattern}');
- }
-
- var totalBarWeight = 0;
-
- for (var i = 0; i < numBarGroups; i++) {
- totalBarWeight += config.weightPattern[i];
- }
-
- for (var i = 0; i < numBarGroups; i++) {
- weights.add(config.weightPattern[i] / totalBarWeight);
- }
- } else {
- for (var i = 0; i < numBarGroups; i++) {
- weights.add(1 / numBarGroups);
- }
- }
-
- return weights;
- }
-
- /// Construct a base details element for a given datum.
- ///
- /// This is intended to be overridden by child classes that need to add
- /// customized rendering properties.
- R getBaseDetails(dynamic datum, int index);
-
- @override
- void configureDomainAxes(List> seriesList) {
- super.configureDomainAxes(seriesList);
-
- // Configure the domain axis to use a range band configuration.
- if (seriesList.isNotEmpty) {
- // Given that charts can only have one domain axis, just grab it from the
- // first series.
- final domainAxis = seriesList.first.getAttr(domainAxisKey);
- domainAxis.setRangeBandConfig(RangeBandConfig.styleAssignedPercent());
- }
- }
-
- void update(List> seriesList, bool isAnimatingThisDraw) {
- _currentKeys.clear();
- _currentGroupsStackKeys.clear();
-
- final orderedSeriesList = getOrderedSeriesList(seriesList);
-
- orderedSeriesList.forEach((final series) {
- final domainAxis = series.getAttr(domainAxisKey) as ImmutableAxis;
- final domainFn = series.domainFn;
- final measureAxis = series.getAttr(measureAxisKey) as ImmutableAxis;
- final measureFn = series.measureFn;
- final colorFn = series.colorFn;
- final dashPatternFn = series.dashPatternFn;
- final fillColorFn = series.fillColorFn;
- final seriesStackKey = series.getAttr(stackKeyKey);
- final barGroupCount = series.getAttr(barGroupCountKey);
- final barGroupIndex = series.getAttr(barGroupIndexKey);
- final previousBarGroupWeight = series.getAttr(previousBarGroupWeightKey);
- final barGroupWeight = series.getAttr(barGroupWeightKey);
- final measureAxisPosition = measureAxis.getLocation(0.0);
-
- var elementsList = series.getAttr(barElementsKey);
-
- // Save off domainAxis for getNearest.
- _prevDomainAxis = domainAxis;
-
- for (var barIndex = 0; barIndex < series.data.length; barIndex++) {
- final datum = series.data[barIndex];
- BaseBarRendererElement details = elementsList[barIndex];
- D domainValue = domainFn(barIndex);
-
- final measureValue = measureFn(barIndex);
- final measureIsNull = measureValue == null;
- final measureIsNegative = !measureIsNull && measureValue < 0;
-
- // Each bar should be stored in barStackMap in a structure that mirrors
- // the visual rendering of the bars. Thus, they should be grouped by
- // domain value, series category (by way of the stack keys that were
- // generated for each series in the preprocess step), and bar group
- // index to account for all combinations of grouping and stacking.
- var barStackMapKey = domainValue.toString() +
- '__' +
- seriesStackKey +
- '__' +
- (measureIsNegative ? 'pos' : 'neg') +
- '__' +
- barGroupIndex.toString();
-
- var barKey = barStackMapKey + details.barStackIndex.toString();
-
- var barStackList = _barStackMap.putIfAbsent(barStackMapKey, () => []);
-
- // If we already have an AnimatingBarfor that index, use it.
- var animatingBar = barStackList.firstWhere((bar) => bar.key == barKey,
- orElse: () => null);
-
- // If we don't have any existing bar element, create a new bar and have
- // it animate in from the domain axis.
- // TODO: Animate bars in the middle of a stack from their
- // nearest neighbors, instead of the measure axis.
- if (animatingBar == null) {
- // If the measure is null and there was no existing animating bar, it
- // means we don't need to draw this bar at all.
- if (!measureIsNull) {
- animatingBar = makeAnimatedBar(
- key: barKey,
- series: series,
- datum: datum,
- barGroupIndex: barGroupIndex,
- previousBarGroupWeight: previousBarGroupWeight,
- barGroupWeight: barGroupWeight,
- color: colorFn(barIndex),
- dashPattern: dashPatternFn(barIndex),
- details: details,
- domainValue: domainFn(barIndex),
- domainAxis: domainAxis,
- domainWidth: domainAxis.rangeBand.round(),
- fillColor: fillColorFn(barIndex),
- fillPattern: details.fillPattern,
- measureValue: 0.0,
- measureOffsetValue: 0.0,
- measureAxisPosition: measureAxisPosition,
- measureAxis: measureAxis,
- numBarGroups: barGroupCount,
- strokeWidthPx: details.strokeWidthPx,
- measureIsNull: measureIsNull,
- measureIsNegative: measureIsNegative);
-
- barStackList.add(animatingBar);
- }
- } else {
- animatingBar
- ..datum = datum
- ..series = series
- ..domainValue = domainValue;
- }
-
- if (animatingBar == null) {
- continue;
- }
-
- // Update the set of bars that still exist in the series data.
- _currentKeys.add(barKey);
-
- // Store off stack keys for each bar group to help getNearest identify
- // groups of stacks.
- _currentGroupsStackKeys
- .putIfAbsent(domainValue, () => {})
- .add(barStackMapKey);
-
- // Get the barElement we are going to setup.
- // Optimization to prevent allocation in non-animating case.
- BaseBarRendererElement barElement = makeBarRendererElement(
- barGroupIndex: barGroupIndex,
- previousBarGroupWeight: previousBarGroupWeight,
- barGroupWeight: barGroupWeight,
- color: colorFn(barIndex),
- dashPattern: dashPatternFn(barIndex),
- details: details,
- domainValue: domainFn(barIndex),
- domainAxis: domainAxis,
- domainWidth: domainAxis.rangeBand.round(),
- fillColor: fillColorFn(barIndex),
- fillPattern: details.fillPattern,
- measureValue: measureValue,
- measureOffsetValue: details.measureOffset,
- measureAxisPosition: measureAxisPosition,
- measureAxis: measureAxis,
- numBarGroups: barGroupCount,
- strokeWidthPx: details.strokeWidthPx,
- measureIsNull: measureIsNull,
- measureIsNegative: measureIsNegative);
-
- animatingBar.setNewTarget(barElement);
- }
- });
-
- // Animate out bars that don't exist anymore.
- _barStackMap.forEach((key, barStackList) {
- for (var barIndex = 0; barIndex < barStackList.length; barIndex++) {
- final bar = barStackList[barIndex];
- if (_currentKeys.contains(bar.key) != true) {
- bar.animateOut();
- }
- }
- });
- }
-
- /// Generates a [BaseAnimatedBar] to represent the previous and current state
- /// of one bar on the chart.
- B makeAnimatedBar(
- {String key,
- ImmutableSeries series,
- dynamic datum,
- int barGroupIndex,
- double previousBarGroupWeight,
- double barGroupWeight,
- Color color,
- List dashPattern,
- R details,
- D domainValue,
- ImmutableAxis domainAxis,
- int domainWidth,
- num measureValue,
- num measureOffsetValue,
- ImmutableAxis measureAxis,
- double measureAxisPosition,
- int numBarGroups,
- Color fillColor,
- FillPatternType fillPattern,
- double strokeWidthPx,
- bool measureIsNull,
- bool measureIsNegative});
-
- /// Generates a [BaseBarRendererElement] to represent the rendering data for
- /// one bar on the chart.
- R makeBarRendererElement(
- {int barGroupIndex,
- double previousBarGroupWeight,
- double barGroupWeight,
- Color color,
- List dashPattern,
- R details,
- D domainValue,
- ImmutableAxis domainAxis,
- int domainWidth,
- num measureValue,
- num measureOffsetValue,
- ImmutableAxis measureAxis,
- double measureAxisPosition,
- int numBarGroups,
- Color fillColor,
- FillPatternType fillPattern,
- double strokeWidthPx,
- bool measureIsNull,
- bool measureIsNegative});
-
- @override
- void onAttach(BaseChart chart) {
- super.onAttach(chart);
- // We only need the chart.context.isRtl setting, but context is not yet
- // available when the default renderer is attached to the chart on chart
- // creation time, since chart onInit is called after the chart is created.
- this.chart = chart;
- }
-
- /// Paints the current bar data on the canvas.
- void paint(ChartCanvas canvas, double animationPercent) {
- // Clean up the bars that no longer exist.
- if (animationPercent == 1.0) {
- final keysToRemove = HashSet();
-
- _barStackMap.forEach((key, barStackList) {
- barStackList.retainWhere(
- (bar) => !bar.animatingOut && !bar.targetBar.measureIsNull);
-
- if (barStackList.isEmpty) {
- keysToRemove.add(key);
- }
- });
-
- // When cleaning up the animation, also clean up the keys used to lookup
- // if a bar is selected.
- for (String key in keysToRemove) {
- _barStackMap.remove(key);
- _currentKeys.remove(key);
- }
- _currentGroupsStackKeys.forEach((domain, keys) {
- keys.removeWhere(keysToRemove.contains);
- });
- }
-
- _barStackMap.forEach((stackKey, barStack) {
- // Turn this into a list so that the getCurrentBar isn't called more than
- // once for each animationPercent if the barElements are iterated more
- // than once.
- final barElements = barStack
- .map((animatingBar) => animatingBar.getCurrentBar(animationPercent))
- .toList();
-
- if (barElements.isNotEmpty) {
- paintBar(canvas, animationPercent, barElements);
- }
- });
- }
-
- /// Paints a stack of bar elements on the canvas.
- void paintBar(
- ChartCanvas canvas, double animationPercent, Iterable barElements);
-
- @override
- List> getNearestDatumDetailPerSeries(
- Point chartPoint, bool byDomain, Rectangle boundsOverride) {
- var nearest = >[];
-
- // Was it even in the component bounds?
- if (!isPointWithinBounds(chartPoint, boundsOverride)) {
- return nearest;
- }
-
- if (_prevDomainAxis is OrdinalAxis) {
- final domainValue = _prevDomainAxis
- .getDomain(renderingVertically ? chartPoint.x : chartPoint.y);
-
- // If we have a domainValue for the event point, then find all segments
- // that match it.
- if (domainValue != null) {
- if (renderingVertically) {
- nearest = _getVerticalDetailsForDomainValue(domainValue, chartPoint);
- } else {
- nearest =
- _getHorizontalDetailsForDomainValue(domainValue, chartPoint);
- }
- }
- } else {
- if (renderingVertically) {
- nearest = _getVerticalDetailsForDomainValue(null, chartPoint);
- } else {
- nearest = _getHorizontalDetailsForDomainValue(null, chartPoint);
- }
-
- // Find the closest domain and only keep values that match the domain.
- var minRelativeDistance = double.maxFinite;
- var minDomainDistance = double.maxFinite;
- var minMeasureDistance = double.maxFinite;
- D nearestDomain;
-
- // TODO: Optimize this with a binary search based on chartX.
- for (DatumDetails detail in nearest) {
- if (byDomain) {
- if (detail.domainDistance < minDomainDistance ||
- (detail.domainDistance == minDomainDistance &&
- detail.measureDistance < minMeasureDistance)) {
- minDomainDistance = detail.domainDistance;
- minMeasureDistance = detail.measureDistance;
- nearestDomain = detail.domain;
- }
- } else {
- if (detail.relativeDistance < minRelativeDistance) {
- minRelativeDistance = detail.relativeDistance;
- nearestDomain = detail.domain;
- }
- }
- }
-
- nearest.retainWhere((d) => d.domain == nearestDomain);
- }
-
- // If we didn't find anything, then keep an empty list.
- nearest ??= >[];
-
- // Note: the details are already sorted by domain & measure distance in
- // base chart.
- return nearest;
- }
-
- Rectangle getBoundsForBar(R bar);
-
- @protected
- List> _getSegmentsForDomainValue(D domainValue,
- {bool where(BaseAnimatedBar bar)}) {
- final matchingSegments = >[];
-
- // [domainValue] is null only when the bar renderer is being used with in
- // a non ordinal axis (ex. date time axis).
- //
- // In the case of null [domainValue] return all values to be compared, since
- // we can't use the optimized comparison for [OrdinalAxis].
- final stackKeys = (domainValue != null)
- ? _currentGroupsStackKeys[domainValue]
- : _currentGroupsStackKeys.values
- .reduce((allKeys, keys) => allKeys..addAll(keys));
- stackKeys?.forEach((stackKey) {
- if (where != null) {
- matchingSegments.addAll(_barStackMap[stackKey].where(where));
- } else {
- matchingSegments.addAll(_barStackMap[stackKey]);
- }
- });
-
- return matchingSegments;
- }
-
- // In the case of null [domainValue] return all values to be compared, since
- // we can't use the optimized comparison for [OrdinalAxis].
- List> _getVerticalDetailsForDomainValue(
- D domainValue, Point chartPoint) {
- return List>.from(_getSegmentsForDomainValue(domainValue,
- where: (bar) => !bar.series.overlaySeries).map>((bar) {
- final barBounds = getBoundsForBar(bar.currentBar);
- final segmentDomainDistance =
- _getDistance(chartPoint.x.round(), barBounds.left, barBounds.right);
- final segmentMeasureDistance =
- _getDistance(chartPoint.y.round(), barBounds.top, barBounds.bottom);
-
- final nearestPoint = Point(
- clamp(chartPoint.x, barBounds.left, barBounds.right).toDouble(),
- clamp(chartPoint.y, barBounds.top, barBounds.bottom).toDouble());
-
- final relativeDistance = chartPoint.distanceTo(nearestPoint);
-
- return DatumDetails(
- series: bar.series,
- datum: bar.datum,
- domain: bar.domainValue,
- domainDistance: segmentDomainDistance,
- measureDistance: segmentMeasureDistance,
- relativeDistance: relativeDistance,
- );
- }));
- }
-
- List> _getHorizontalDetailsForDomainValue(
- D domainValue, Point chartPoint) {
- return List>.from(_getSegmentsForDomainValue(domainValue,
- where: (bar) => !bar.series.overlaySeries).map((bar) {
- final barBounds = getBoundsForBar(bar.currentBar);
- final segmentDomainDistance =
- _getDistance(chartPoint.y.round(), barBounds.top, barBounds.bottom);
- final segmentMeasureDistance =
- _getDistance(chartPoint.x.round(), barBounds.left, barBounds.right);
-
- return DatumDetails(
- series: bar.series,
- datum: bar.datum,
- domain: bar.domainValue,
- domainDistance: segmentDomainDistance,
- measureDistance: segmentMeasureDistance,
- );
- }));
- }
-
- double _getDistance(int point, int min, int max) {
- if (max >= point && min <= point) {
- return 0.0;
- }
- return (point > max ? (point - max) : (min - point)).toDouble();
- }
-
- /// Gets the iterator for the series based grouped/stacked and orientation.
- ///
- /// For vertical stacked bars:
- /// * If grouped, return the iterator that keeps the category order but
- /// reverse the order of the series so the first series is on the top of the
- /// stack.
- /// * Otherwise, return iterator of the reversed list
- ///
- /// All other types, use the in order iterator.
- @protected
- Iterable getOrderedSeriesList(
- List seriesList) {
- return (renderingVertically && config.stacked)
- ? config.grouped
- ? _ReversedSeriesIterable(seriesList)
- : seriesList.reversed
- : seriesList;
- }
-
- bool get isRtl => chart.context.isRtl;
-}
-
-/// Iterable wrapping the seriesList that returns the ReversedSeriesItertor.
-class _ReversedSeriesIterable extends Iterable {
- final List seriesList;
-
- _ReversedSeriesIterable(this.seriesList);
-
- @override
- Iterator get iterator => _ReversedSeriesIterator(seriesList);
-}
-
-/// Iterator that keeps reverse series order but keeps category order.
-///
-/// This is needed because for grouped stacked bars, the category stays in the
-/// order it was passed in for the grouping, but the series is flipped so that
-/// the first series of that category is on the top of the stack.
-class _ReversedSeriesIterator extends Iterator {
- final List _list;
- final _visitIndex = [];
- int _current;
-
- _ReversedSeriesIterator(List list) : _list = list {
- // In the order of the list, save the category and the indices of the series
- // with the same category.
- final categoryAndSeriesIndexMap = >{};
- for (var i = 0; i < list.length; i++) {
- categoryAndSeriesIndexMap
- .putIfAbsent(list[i].seriesCategory, () => [])
- .add(i);
- }
-
- // Creates a visit that is categories in order, but the series is reversed.
- categoryAndSeriesIndexMap
- .forEach((_, indices) => _visitIndex.addAll(indices.reversed));
- }
-
- @override
- bool moveNext() {
- _current = (_current == null) ? 0 : _current + 1;
-
- return _current < _list.length;
- }
-
- @override
- S get current => _list[_visitIndex[_current]];
-}
diff --git a/web/charts/common/lib/src/chart/bar/base_bar_renderer_config.dart b/web/charts/common/lib/src/chart/bar/base_bar_renderer_config.dart
deleted file mode 100644
index 6cbd9611e..000000000
--- a/web/charts/common/lib/src/chart/bar/base_bar_renderer_config.dart
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2018 the Charts project authors. Please see the AUTHORS file
-// for details.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import 'package:collection/collection.dart' show ListEquality;
-
-import '../../common/symbol_renderer.dart'
- show SymbolRenderer, RoundedRectSymbolRenderer;
-import '../common/chart_canvas.dart' show FillPatternType;
-import '../common/series_renderer_config.dart'
- show RendererAttributes, SeriesRendererConfig;
-import '../layout/layout_view.dart' show LayoutViewConfig;
-
-/// Shared configuration for bar chart renderers.
-///
-/// Bar renderers support 4 different modes of rendering multiple series on the
-/// chart, configured by the grouped and stacked flags.
-/// * grouped - Render bars for each series that shares a domain value
-/// side-by-side.
-/// * stacked - Render bars for each series that shares a domain value in a
-/// stack, ordered in the same order as the series list.
-/// * grouped-stacked: Render bars for each series that shares a domain value in
-/// a group of bar stacks. Each stack will contain all the series that share a
-/// series category.
-/// * floating style - When grouped and stacked are both false, all bars that
-/// share a domain value will be rendered in the same domain space. Each datum
-/// should be configured with a measure offset to position its bar along the
-/// measure axis. Bars will freely overlap if their measure values and measure
-/// offsets overlap. Note that bars for each series will be rendered in order,
-/// such that bars from the last series will be "on top" of bars from previous
-/// series.
-abstract class BaseBarRendererConfig extends LayoutViewConfig
- implements SeriesRendererConfig {
- final String customRendererId;
-
- final SymbolRenderer symbolRenderer;
-
- /// Dash pattern for the stroke line around the edges of the bar.
- final List dashPattern;
-
- /// Defines the way multiple series of bars are rendered per domain.
- final BarGroupingType groupingType;
-
- /// The order to paint this renderer on the canvas.
- final int layoutPaintOrder;
-
- final int minBarLengthPx;
-
- final FillPatternType fillPattern;
-
- final double stackHorizontalSeparator;
-
- /// Stroke width of the target line.
- final double strokeWidthPx;
-
- /// Sets the series weight pattern. This is a pattern of weights used to
- /// calculate the width of bars within a bar group. If not specified, each bar
- /// in the group will have an equal width.
- ///
- /// The pattern will not repeat. If more series are assigned to the renderer
- /// than there are segments in the weight pattern, an error will be thrown.
- ///
- /// e.g. For the pattern [2, 1], the first bar in a group should be rendered
- /// twice as wide as the second bar.
- ///
- /// If the expected bar width of the chart is 12px, then the first bar will
- /// render at 16px and the second will render at 8px. The default weight
- /// pattern of null means that all bars should be the same width, or 12px in
- /// this case.
- ///
- /// Not used for stacked bars.
- final List weightPattern;
-
- final rendererAttributes = RendererAttributes();
-
- BaseBarRendererConfig(
- {this.customRendererId,
- this.dashPattern,
- this.groupingType = BarGroupingType.grouped,
- this.layoutPaintOrder,
- this.minBarLengthPx = 0,
- this.fillPattern,
- this.stackHorizontalSeparator,
- this.strokeWidthPx = 0.0,
- SymbolRenderer symbolRenderer,
- this.weightPattern})
- : this.symbolRenderer = symbolRenderer ?? RoundedRectSymbolRenderer();
-
- /// Whether or not the bars should be organized into groups.
- bool get grouped =>
- groupingType == BarGroupingType.grouped ||
- groupingType == BarGroupingType.groupedStacked;
-
- /// Whether or not the bars should be organized into stacks.
- bool get stacked =>
- groupingType == BarGroupingType.stacked ||
- groupingType == BarGroupingType.groupedStacked;
-
- @override
- bool operator ==(other) {
- if (identical(this, other)) {
- return true;
- }
- return other is BaseBarRendererConfig &&
- other.customRendererId == customRendererId &&
- other.dashPattern == dashPattern &&
- other.fillPattern == fillPattern &&
- other.groupingType == groupingType &&
- other.minBarLengthPx == minBarLengthPx &&
- other.stackHorizontalSeparator == stackHorizontalSeparator &&
- other.strokeWidthPx == strokeWidthPx &&
- other.symbolRenderer == symbolRenderer &&
- ListEquality().equals(other.weightPattern, weightPattern);
- }
-
- int get hashcode {
- var hash = 1;
- hash = hash * 31 + (customRendererId?.hashCode ?? 0);
- hash = hash * 31 + (dashPattern?.hashCode ?? 0);
- hash = hash * 31 + (fillPattern?.hashCode ?? 0);
- hash = hash * 31 + (groupingType?.hashCode ?? 0);
- hash = hash * 31 + (minBarLengthPx?.hashCode ?? 0);
- hash = hash * 31 + (stackHorizontalSeparator?.hashCode ?? 0);
- hash = hash * 31 + (strokeWidthPx?.hashCode ?? 0);
- hash = hash * 31 + (symbolRenderer?.hashCode ?? 0);
- hash = hash * 31 + (weightPattern?.hashCode ?? 0);
- return hash;
- }
-}
-
-/// Defines the way multiple series of bars are renderered per domain.
-///
-/// * [grouped] - Render bars for each series that shares a domain value
-/// side-by-side.
-/// * [stacked] - Render bars for each series that shares a domain value in a
-/// stack, ordered in the same order as the series list.
-/// * [groupedStacked]: Render bars for each series that shares a domain value
-/// in a group of bar stacks. Each stack will contain all the series that
-/// share a series category.
-enum BarGroupingType { grouped, groupedStacked, stacked }
diff --git a/web/charts/common/lib/src/chart/bar/base_bar_renderer_element.dart b/web/charts/common/lib/src/chart/bar/base_bar_renderer_element.dart
deleted file mode 100644
index bfa5fb16a..000000000
--- a/web/charts/common/lib/src/chart/bar/base_bar_renderer_element.dart
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2018 the Charts project authors. Please see the AUTHORS file
-// for details.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import '../../common/color.dart' show Color;
-import '../common/chart_canvas.dart' show getAnimatedColor, FillPatternType;
-import '../common/processed_series.dart' show ImmutableSeries;
-
-abstract class BaseBarRendererElement {
- int barStackIndex;
- Color color;
- num cumulativeTotal;
- List dashPattern;
- Color fillColor;
- FillPatternType fillPattern;
- double measureAxisPosition;
- num measureOffset;
- num measureOffsetPlusMeasure;
- double strokeWidthPx;
- bool measureIsNull;
- bool measureIsNegative;
-
- BaseBarRendererElement();
-
- BaseBarRendererElement.clone(BaseBarRendererElement other) {
- barStackIndex = other.barStackIndex;
- color = other.color != null ? Color.fromOther(color: other.color) : null;
- cumulativeTotal = other.cumulativeTotal;
- dashPattern = other.dashPattern;
- fillColor = other.fillColor != null
- ? Color.fromOther(color: other.fillColor)
- : null;
- fillPattern = other.fillPattern;
- measureAxisPosition = other.measureAxisPosition;
- measureOffset = other.measureOffset;
- measureOffsetPlusMeasure = other.measureOffsetPlusMeasure;
- strokeWidthPx = other.strokeWidthPx;
- measureIsNull = other.measureIsNull;
- measureIsNegative = other.measureIsNegative;
- }
-
- void updateAnimationPercent(BaseBarRendererElement previous,
- BaseBarRendererElement target, double animationPercent) {
- color = getAnimatedColor(previous.color, target.color, animationPercent);
- fillColor = getAnimatedColor(
- previous.fillColor, target.fillColor, animationPercent);
- measureIsNull = target.measureIsNull;
- measureIsNegative = target.measureIsNegative;
- }
-}
-
-abstract class BaseAnimatedBar {
- final String key;
- dynamic datum;
- ImmutableSeries series;
- D domainValue;
-
- R _previousBar;
- R _targetBar;
- R _currentBar;
-
- // Flag indicating whether this bar is being animated out of the chart.
- bool animatingOut = false;
-
- BaseAnimatedBar({this.key, this.datum, this.series, this.domainValue});
-
- /// Animates a bar that was removed from the series out of the view.
- ///
- /// This should be called in place of "setNewTarget" for bars that represent
- /// data that has been removed from the series.
- ///
- /// Animates the height of the bar down to the measure axis position (position
- /// of 0). Animates the width of the bar down to 0, centered in the middle of
- /// the original bar width.
- void animateOut() {
- var newTarget = clone(_currentBar);
-
- animateElementToMeasureAxisPosition(newTarget);
-
- setNewTarget(newTarget);
- animatingOut = true;
- }
-
- /// Sets the bounds for the target to the measure axis position.
- void animateElementToMeasureAxisPosition(R target);
-
- /// Sets a new element to render.
- void setNewTarget(R newTarget) {
- animatingOut = false;
- _currentBar ??= clone(newTarget);
- _previousBar = clone(_currentBar);
- _targetBar = newTarget;
- }
-
- R get currentBar => _currentBar;
-
- R get previousBar => _previousBar;
-
- R get targetBar => _targetBar;
-
- /// Gets the new state of the bar element for painting, updated for a
- /// transition between the previous state and the new animationPercent.
- R getCurrentBar(double animationPercent) {
- if (animationPercent == 1.0 || _previousBar == null) {
- _currentBar = _targetBar;
- _previousBar = _targetBar;
- return _currentBar;
- }
-
- _currentBar.updateAnimationPercent(
- _previousBar, _targetBar, animationPercent);
-
- return _currentBar;
- }
-
- R clone(R bar);
-}
diff --git a/web/charts/common/lib/src/chart/cartesian/axis/axis.dart b/web/charts/common/lib/src/chart/cartesian/axis/axis.dart
deleted file mode 100644
index 5203224ee..000000000
--- a/web/charts/common/lib/src/chart/cartesian/axis/axis.dart
+++ /dev/null
@@ -1,572 +0,0 @@
-// Copyright 2018 the Charts project authors. Please see the AUTHORS file
-// for details.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import 'dart:math' show Rectangle, min, max;
-
-import 'package:meta/meta.dart' show protected, visibleForTesting;
-
-import '../../../common/graphics_factory.dart' show GraphicsFactory;
-import '../../../common/text_element.dart' show TextElement;
-import '../../../data/series.dart' show AttributeKey;
-import '../../common/chart_canvas.dart' show ChartCanvas;
-import '../../common/chart_context.dart' show ChartContext;
-import '../../layout/layout_view.dart'
- show
- LayoutPosition,
- LayoutView,
- LayoutViewConfig,
- LayoutViewPaintOrder,
- LayoutViewPositionOrder,
- ViewMeasuredSizes;
-import 'axis_tick.dart' show AxisTicks;
-import 'draw_strategy/small_tick_draw_strategy.dart' show SmallTickDrawStrategy;
-import 'draw_strategy/tick_draw_strategy.dart' show TickDrawStrategy;
-import 'linear/linear_scale.dart' show LinearScale;
-import 'numeric_extents.dart' show NumericExtents;
-import 'numeric_scale.dart' show NumericScale;
-import 'numeric_tick_provider.dart' show NumericTickProvider;
-import 'ordinal_tick_provider.dart' show OrdinalTickProvider;
-import 'scale.dart'
- show MutableScale, RangeBandConfig, ScaleOutputExtent, Scale;
-import 'simple_ordinal_scale.dart' show SimpleOrdinalScale;
-import 'tick.dart' show Tick;
-import 'tick_formatter.dart'
- show TickFormatter, OrdinalTickFormatter, NumericTickFormatter;
-import 'tick_provider.dart' show TickProvider;
-
-const measureAxisIdKey = AttributeKey('Axis.measureAxisId');
-const measureAxisKey = AttributeKey('Axis.measureAxis');
-const domainAxisKey = AttributeKey('Axis.domainAxis');
-
-/// Orientation of an Axis.
-enum AxisOrientation { top, right, bottom, left }
-
-abstract class ImmutableAxis {
- /// Compare domain to the viewport.
- ///
- /// 0 if the domain is in the viewport.
- /// 1 if the domain is to the right of the viewport.
- /// -1 if the domain is to the left of the viewport.
- int compareDomainValueToViewport(D domain);
-
- /// Get location for the domain.
- double getLocation(D domain);
-
- D getDomain(double location);
-
- /// Rangeband for this axis.
- double get rangeBand;
-
- /// Step size for this axis.
- double get stepSize;
-
- /// Output range for this axis.
- ScaleOutputExtent get range;
-}
-
-abstract class Axis extends ImmutableAxis implements LayoutView {
- static const primaryMeasureAxisId = 'primaryMeasureAxisId';
- static const secondaryMeasureAxisId = 'secondaryMeasureAxisId';
-
- final MutableScale _scale;
-
- /// [Scale] of this axis.
- @protected
- MutableScale get scale => _scale;
-
- /// Previous [Scale] of this axis, used to calculate tick animation.
- MutableScale _previousScale;
-
- /// [TickProvider] for this axis.
- TickProvider tickProvider;
-
- /// [TickFormatter] for this axis.
- TickFormatter _tickFormatter;
-
- set tickFormatter(TickFormatter formatter) {
- if (_tickFormatter != formatter) {
- _tickFormatter = formatter;
- _formatterValueCache.clear();
- }
- }
-
- TickFormatter get tickFormatter => _tickFormatter;
- final _formatterValueCache = {};
-
- /// [TickDrawStrategy] for this axis.
- TickDrawStrategy tickDrawStrategy;
-
- /// [AxisOrientation] for this axis.
- AxisOrientation axisOrientation;
-
- ChartContext context;
-
- /// If the output range should be reversed.
- bool reverseOutputRange = false;
-
- /// Configures whether the viewport should be reset back to default values
- /// when the domain is reset.
- ///
- /// This should generally be disabled when the viewport will be managed
- /// externally, e.g. from pan and zoom behaviors.
- bool autoViewport = true;
-
- /// If the axis line should always be drawn.
- bool forceDrawAxisLine;
-
- /// If true, do not allow axis to be modified.
- ///
- /// Ticks (including their location) are not updated.
- /// Viewport changes not allowed.
- bool lockAxis = false;
-
- /// Ticks provided by the tick provider.
- List _providedTicks;
-
- /// Ticks used by the axis for drawing.
- final _axisTicks = >[];
-
- Rectangle _componentBounds;
- Rectangle _drawAreaBounds;
- GraphicsFactory graphicsFactory;
-
- /// Order for chart layout painting.
- ///
- /// In general, domain axes should be drawn on top of measure axes to ensure
- /// that the domain axis line appears on top of any measure axis grid lines.
- int layoutPaintOrder = LayoutViewPaintOrder.measureAxis;
-
- Axis(
- {TickProvider tickProvider,
- TickFormatter tickFormatter,
- MutableScale scale})
- : this._scale = scale,
- this.tickProvider = tickProvider,
- this._tickFormatter = tickFormatter;
-
- @protected
- MutableScale get mutableScale => _scale;
-
- /// Rangeband for this axis.
- @override
- double get rangeBand => _scale.rangeBand;
-
- @override
- double get stepSize => _scale.stepSize;
-
- @override
- ScaleOutputExtent get range => _scale.range;
-
- void setRangeBandConfig(RangeBandConfig rangeBandConfig) {
- mutableScale.rangeBandConfig = rangeBandConfig;
- }
-
- void addDomainValue(D domain) {
- if (lockAxis) {
- return;
- }
-
- _scale.addDomain(domain);
- }
-
- void resetDomains() {
- if (lockAxis) {
- return;
- }
-
- // If the series list changes, clear the cache.
- //
- // There are cases where tick formatter has not "changed", but if measure
- // formatter provided to the tick formatter uses a closure value, the
- // formatter cache needs to be cleared.
- //
- // This type of use case for the measure formatter surfaced where the series
- // list also changes. So this is a round about way to also clear the
- // tick formatter cache.
- //
- // TODO: Measure formatter should be changed from a typedef to
- // a concrete class to force users to create a new tick formatter when
- // formatting is different, so we can recognize when the tick formatter is
- // changed and then clear cache accordingly.
- //
- // Remove this when bug above is fixed, and verify it did not cause
- // regression for b/110371453.
- _formatterValueCache.clear();
-
- _scale.resetDomain();
- reverseOutputRange = false;
-
- if (autoViewport) {
- _scale.resetViewportSettings();
- }
-
- // TODO: Reset rangeband and step size when we port over config
- //scale.rangeBandConfig = get range band config
- //scale.stepSizeConfig = get step size config
- }
-
- @override
- double getLocation(D domain) => domain != null ? _scale[domain] : null;
-
- @override
- D getDomain(double location) => _scale.reverse(location);
-
- @override
- int compareDomainValueToViewport(D domain) {
- return _scale.compareDomainValueToViewport(domain);
- }
-
- void setOutputRange(int start, int end) {
- _scale.range = ScaleOutputExtent(start, end);
- }
-
- /// Request update ticks from tick provider and update the painted ticks.
- void updateTicks() {
- _updateProvidedTicks();
- _updateAxisTicks();
- }
-
- /// Request ticks from tick provider.
- void _updateProvidedTicks() {
- if (lockAxis) {
- return;
- }
-
- // TODO: Ensure that tick providers take manually configured
- // viewport settings into account, so that we still get the right number.
- _providedTicks = tickProvider.getTicks(
- context: context,
- graphicsFactory: graphicsFactory,
- scale: _scale,
- formatter: tickFormatter,
- formatterValueCache: _formatterValueCache,
- tickDrawStrategy: tickDrawStrategy,
- orientation: axisOrientation,
- viewportExtensionEnabled: autoViewport);
- }
-
- /// Updates the ticks that are actually used for drawing.
- void _updateAxisTicks() {
- if (lockAxis) {
- return;
- }
-
- final providedTicks = List.from(_providedTicks ?? []);
-
- for (AxisTicks animatedTick in _axisTicks) {
- final tick = providedTicks?.firstWhere(
- (t) => t.value == animatedTick.value,
- orElse: () => null);
-
- if (tick != null) {
- // Swap out the text element only if the settings are different.
- // This prevents a costly new TextPainter in Flutter.
- if (!TextElement.elementSettingsSame(
- animatedTick.textElement, tick.textElement)) {
- animatedTick.textElement = tick.textElement;
- }
- // Update target for all existing ticks
- animatedTick.setNewTarget(_scale[tick.value]);
- providedTicks.remove(tick);
- } else {
- // Animate out ticks that do not exist any more.
- animatedTick.animateOut(_scale[animatedTick.value].toDouble());
- }
- }
-
- // Add new ticks
- providedTicks?.forEach((tick) {
- final animatedTick = AxisTicks(tick);
- if (_previousScale != null) {
- animatedTick.animateInFrom(_previousScale[tick.value].toDouble());
- }
- _axisTicks.add(animatedTick);
- });
-
- _axisTicks.sort();
-
- // Save a copy of the current scale to be used as the previous scale when
- // ticks are updated.
- _previousScale = _scale.copy();
- }
-
- /// Configures the zoom and translate.
- ///
- /// [viewportScale] is the zoom factor to use, likely >= 1.0 where 1.0 maps
- /// the complete data extents to the output range, and 2.0 only maps half the
- /// data to the output range.
- ///
- /// [viewportTranslatePx] is the translate/pan to use in pixel units,
- /// likely <= 0 which shifts the start of the data before the edge of the
- /// chart giving us a pan.
- ///
- /// [drawAreaWidth] is the width of the draw area for the series data in pixel
- /// units, at minimum viewport scale level (1.0). When provided,
- /// [viewportTranslatePx] will be clamped such that the axis cannot be panned
- /// beyond the bounds of the data.
- void setViewportSettings(double viewportScale, double viewportTranslatePx,
- {int drawAreaWidth}) {
- // Don't let the viewport be panned beyond the bounds of the data.
- viewportTranslatePx = _clampTranslatePx(viewportScale, viewportTranslatePx,
- drawAreaWidth: drawAreaWidth);
-
- _scale.setViewportSettings(viewportScale, viewportTranslatePx);
- }
-
- /// Returns the current viewport scale.
- ///
- /// A scale of 1.0 would map the data directly to the output range, while a
- /// value of 2.0 would map the data to an output of double the range so you
- /// only see half the data in the viewport. This is the equivalent to
- /// zooming. Its value is likely >= 1.0.
- double get viewportScalingFactor => _scale.viewportScalingFactor;
-
- /// Returns the current pixel viewport offset
- ///
- /// The translate is used by the scale function when it applies the scale.
- /// This is the equivalent to panning. Its value is likely <= 0 to pan the
- /// data to the left.
- double get viewportTranslatePx => _scale?.viewportTranslatePx;
-
- /// Clamps a possible change in domain translation to fit within the range of
- /// the data.
- double _clampTranslatePx(
- double viewportScalingFactor, double viewportTranslatePx,
- {int drawAreaWidth}) {
- if (drawAreaWidth == null) {
- return viewportTranslatePx;
- }
-
- // Bound the viewport translate to the range of the data.
- final maxNegativeTranslate =
- -1.0 * ((drawAreaWidth * viewportScalingFactor) - drawAreaWidth);
-
- viewportTranslatePx =
- min(max(viewportTranslatePx, maxNegativeTranslate), 0.0);
-
- return viewportTranslatePx;
- }
-
- //
- // LayoutView methods.
- //
-
- @override
- LayoutViewConfig get layoutConfig => LayoutViewConfig(
- paintOrder: layoutPaintOrder,
- position: _layoutPosition,
- positionOrder: LayoutViewPositionOrder.axis);
-
- /// Get layout position from axis orientation.
- LayoutPosition get _layoutPosition {
- LayoutPosition position;
- switch (axisOrientation) {
- case AxisOrientation.top:
- position = LayoutPosition.Top;
- break;
- case AxisOrientation.right:
- position = LayoutPosition.Right;
- break;
- case AxisOrientation.bottom:
- position = LayoutPosition.Bottom;
- break;
- case AxisOrientation.left:
- position = LayoutPosition.Left;
- break;
- }
-
- return position;
- }
-
- /// The axis is rendered vertically.
- bool get isVertical =>
- axisOrientation == AxisOrientation.left ||
- axisOrientation == AxisOrientation.right;
-
- @override
- ViewMeasuredSizes measure(int maxWidth, int maxHeight) {
- return isVertical
- ? _measureVerticalAxis(maxWidth, maxHeight)
- : _measureHorizontalAxis(maxWidth, maxHeight);
- }
-
- ViewMeasuredSizes _measureVerticalAxis(int maxWidth, int maxHeight) {
- setOutputRange(maxHeight, 0);
- _updateProvidedTicks();
-
- return tickDrawStrategy.measureVerticallyDrawnTicks(
- _providedTicks, maxWidth, maxHeight);
- }
-
- ViewMeasuredSizes _measureHorizontalAxis(int maxWidth, int maxHeight) {
- setOutputRange(0, maxWidth);
- _updateProvidedTicks();
-
- return tickDrawStrategy.measureHorizontallyDrawnTicks(
- _providedTicks, maxWidth, maxHeight);
- }
-
- /// Layout this component.
- @override
- void layout(Rectangle componentBounds, Rectangle drawAreaBounds) {
- _componentBounds = componentBounds;
- _drawAreaBounds = drawAreaBounds;
-
- // Update the output range if it is different than the current one.
- // This is necessary because during the measure cycle, the output range is
- // set between zero and the max range available. On layout, the output range
- // needs to be updated to account of the offset of the axis view.
-
- final outputStart =
- isVertical ? _componentBounds.bottom : _componentBounds.left;
- final outputEnd =
- isVertical ? _componentBounds.top : _componentBounds.right;
-
- final outputRange = reverseOutputRange
- ? ScaleOutputExtent(outputEnd, outputStart)
- : ScaleOutputExtent(outputStart, outputEnd);
-
- if (_scale.range != outputRange) {
- _scale.range = outputRange;
- }
-
- _updateProvidedTicks();
- // Update animated ticks in layout, because updateTicks are called during
- // measure and we don't want to update the animation at that time.
- _updateAxisTicks();
- }
-
- @override
- bool get isSeriesRenderer => false;
-
- @override
- Rectangle