From b226c5ea5762fce1db87e25364b7080dcc713db4 Mon Sep 17 00:00:00 2001 From: entronad Date: Wed, 27 Oct 2021 20:17:32 +0800 Subject: [PATCH] v0.4.1 --- CHANGELOG.md | 7 + DEVLOG.md | 8 + lib/graphic.dart | 151 ++++++++++++++++--- lib/src/aes/aes.dart | 3 +- lib/src/algebra/varset.dart | 22 ++- lib/src/chart/chart.dart | 148 ++++++++++++------ lib/src/chart/size.dart | 4 +- lib/src/chart/view.dart | 7 +- lib/src/coord/coord.dart | 4 +- lib/src/data/data_set.dart | 8 +- lib/src/geom/element.dart | 4 +- lib/src/guide/axis/axis.dart | 4 +- lib/src/guide/guide.dart | 4 +- lib/src/guide/interaction/crosshair.dart | 4 +- lib/src/guide/interaction/tooltip.dart | 4 +- lib/src/interaction/gesture.dart | 4 +- lib/src/interaction/selection/selection.dart | 4 +- lib/src/interaction/signal.dart | 4 +- lib/src/parse/parse.dart | 5 +- lib/src/parse/spec.dart | 123 --------------- lib/src/scale/scale.dart | 4 +- lib/src/variable/variable.dart | 8 +- pubspec.yaml | 2 +- 23 files changed, 301 insertions(+), 235 deletions(-) delete mode 100644 lib/src/parse/spec.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index d434419..f808280 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.4.1 + +**2021-10-27** + +- Optimize the documentation. +- Move specifications to Chart class. + ## 0.4.0 **2021-10-26** diff --git a/DEVLOG.md b/DEVLOG.md index e7c3f43..0247fe7 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -3746,7 +3746,15 @@ bigdata 避免label-text的设置过长,将核心参数设为位置参数,将lebel syle设为可选位置参数 +``` + variable scale aesthetic shape + | | | | +data --> tuples --> scaled tuples --> aesthetic attributes --> figures +``` + + +将所有的spec都放到chart中,移除spec类,这样做文档最简洁。 ## TODO diff --git a/lib/graphic.dart b/lib/graphic.dart index 5108cd3..5cb0ef2 100644 --- a/lib/graphic.dart +++ b/lib/graphic.dart @@ -1,24 +1,116 @@ -/// This library includes a [Chart] Flutter widget for data visualization and classes -/// for it's specification. Besids, it also provides some util classes and functions +/// Graphic provides a Flutter charting library for data visualization. it has a +/// chart widget, calsses for specification, and some util classes and funtions /// for customization. /// -/// There are some basic conccepts for this data visualization, most of witch derive -/// from the Grammar of Graphics. they compose the parameters of the [Chart]'s constructor: -/// -/// - **data**, the input data list, can be of any item type. -/// - **variable**, defines the fields of **tuple**, which is the real datum object -/// inside the chart. -/// - **scale**, to scale and normalize the values. -/// - **aesthetic**, to assign values to certain attributes for rendering. -/// - **element**, the graphics visualizing data tuples. -/// - **coordinate**, to locate abstract position values on the canvas. -/// - **shape**, decide how to render the elements. -/// - **signal**, a event that may cause a value changing. -/// - **selection**, the state whether a tuple is selected. -/// - **figure**, which is generated by chart evaluation and carries graphic information -/// for rendering engine to paint. -/// -/// See details and others in the class documents below. +/// To use this charting library, you only need to do one thing: to create a [Chart] +/// widget. This widget will evaluate and paint automatically in initial and on +/// update. +/// +/// A start example of bar chart is as below: +/// +/// ```dart +/// Chart( +/// data: [ +/// { 'genre': 'Sports', 'sold': 275 }, +/// { 'genre': 'Strategy', 'sold': 115 }, +/// { 'genre': 'Action', 'sold': 120 }, +/// { 'genre': 'Shooter', 'sold': 350 }, +/// { 'genre': 'Other', 'sold': 150 }, +/// ], +/// variables: { +/// 'genre': Variable( +/// accessor: (Map map) => map['genre'] as String, +/// ), +/// 'sold': Variable( +/// accessor: (Map map) => map['sold'] as num, +/// ), +/// }, +/// elements: [IntervalElement()], +/// axes: [ +/// Defaults.horizontalAxis, +/// Defaults.verticalAxis, +/// ], +/// ) +/// ``` +/// +/// All specifications of data visualization are set by parameters of [Chart]'s +/// constructor as class properties. +/// +/// The main processing flow of charting and some important concepts are as below. +/// Most concepts derive form the Grammar of Graphics. They will help to take full +/// advantage of this library. These are brif introcuction, and details see into +/// the Classes and [Chart] properties. +/// +/// ``` +/// variable scale aesthetic shape +/// | | | | +/// data --> tuples --> scaled tuples --> aesthetic attributes --> figures +/// ``` +/// +/// ## Variable +/// +/// Variables define the fields of [Tuple]s. The input data of the chart is a [List] +/// of any generic type. Yet they are not used directly inside the chart, instead, +/// the data are converted to [Tuple]s. +/// +/// They are specified by [Chart.variables] or [Chart.transforms] with [Variable] or +/// [VariableTransform]. +/// +/// ## Algebra +/// +/// The graphic algebra determins how variable values are assigned to position dimensions. +/// +/// It is specified by [GeomElement.position] with [Varset]. See details of the algebra +/// rules in [Varset]. +/// +/// ## Scale +/// +/// Scales convert [Tuple] values to to scaled values, which is easier to prosess +/// for aesthetic [Attr]s. +/// +/// They are specified by [Variable.scale] with [Scale]. +/// +/// ## Coordinate +/// +/// The coordinate determins how abstract positions are located on the canvas in +/// painting. The same element may look quite different in [RectCoord] and [PolarCoord]. +/// +/// It is specified by [Chart.coord] with [Coord]. +/// +/// ## Aesthetic +/// +/// Aesthetic means to make [Tuple]s percivable. That is to give them aesthetic attributes +/// from the scaled values. +/// +/// Aesthetic attributes are specified in [GeomElement] with [Attr]. And attributes +/// values are stored in [Aes]. +/// +/// ## Shape +/// +/// Shapes render [Tuple]s with [Aes] attributes. Rendering means to get [Figure]s, +/// which carry the painting information for the rendering engine. Extending a shape +/// subclass is the way to custom charts. +/// +/// Shape is also a aesthetic attribute is self. It is defined with [Shape], and +/// generated by [ShapeAttr] wich is defined by [GeomElement.shape]. The [Shape] +/// type should corresponds to [GeomElement] type. +/// +/// ## Interaction +/// +/// There are two kinds of interactions: [Signal] and [Selection]. Signal means +/// a certain specification value changes to [GestureSignal], [ResizeSignal], or +/// [ChangeDataSignal]. Selection means a tuple aesthetic attribute values change +/// when it is selected or not. +/// +/// Signals are used by properties named in "on...Signal" with [SignalUpdate]. Selections +/// are specified by [Chart.selections] and used by [Attr.onSelection] with [SelectionUpdate]. +/// +/// ## Guide +/// +/// Guides are various components that helps to read the chart. +/// +/// They include [Axis] specified by [Chart.axes], [Tooltip] specified by [Chart.tooltip], +/// [Crosshair] specified by [Chart.crosshair], and [Annotation]s specified by [Chart.annotations], library graphic; export 'src/chart/chart.dart' show Chart; @@ -27,26 +119,36 @@ export 'src/chart/size.dart' show ResizeSignal; export 'src/data/data_set.dart' show ChangeDataSignal; export 'src/variable/variable.dart' show Variable; +export 'src/variable/transform/transform.dart' show VariableTransform; export 'src/variable/transform/filter.dart' show Filter; export 'src/variable/transform/map.dart' show MapTrans; export 'src/variable/transform/proportion.dart' show Proportion; export 'src/variable/transform/sort.dart' show Sort; +export 'src/scale/scale.dart' show Scale; +export 'src/scale/discrete.dart' show DiscreteScale; +export 'src/scale/continuous.dart' show ContinuousScale; export 'src/scale/linear.dart' show LinearScale; export 'src/scale/ordinal.dart' show OrdinalScale; export 'src/scale/time.dart' show TimeScale; +export 'src/geom/element.dart' show GeomElement; +export 'src/geom/function.dart' show FunctionElement; +export 'src/geom/partition.dart' show PartitionElement; export 'src/geom/area.dart' show AreaElement; export 'src/geom/custom.dart' show CustomElement; export 'src/geom/interval.dart' show IntervalElement; export 'src/geom/line.dart' show LineElement; export 'src/geom/point.dart' show PointElement; export 'src/geom/polygon.dart' show PolygonElement; +export 'src/geom/modifier/modifier.dart' show Modifier; export 'src/geom/modifier/dodge.dart' show DodgeModifier; export 'src/geom/modifier/stack.dart' show StackModifier; export 'src/geom/modifier/jitter.dart' show JitterModifier; export 'src/geom/modifier/symmetric.dart' show SymmetricModifier; +export 'src/aes/aes.dart' show Attr; +export 'src/aes/channel.dart' show ChannelAttr; export 'src/aes/color.dart' show ColorAttr; export 'src/aes/elevation.dart' show ElevationAttr; export 'src/aes/gradient.dart' show GradientAttr; @@ -54,8 +156,11 @@ export 'src/aes/label.dart' show LabelAttr; export 'src/aes/shape.dart' show ShapeAttr; export 'src/aes/size.dart' show SizeAttr; -export 'src/algebra/varset.dart' show Varset; +export 'src/algebra/varset.dart' show Varset, AlgForm, AlgTerm; +export 'src/shape/shape.dart' show Shape; +export 'src/shape/function.dart' show FunctionShape; +export 'src/shape/partition.dart' show PartitionShape; export 'src/shape/area.dart' show AreaShape, BasicAreaShape; export 'src/shape/custom.dart' show CustomShape, CandlestickShape; export 'src/shape/interval.dart' show IntervalShape, RectShape, FunnelShape; @@ -67,7 +172,7 @@ export 'src/shape/util/render_basic_item.dart' show renderBasicItem; export 'src/graffiti/figure.dart' show Figure, PathFigure, ShadowFigure, TextFigure, RotatedTextFigure; -export 'src/coord/coord.dart' show CoordConv; +export 'src/coord/coord.dart' show Coord, CoordConv; export 'src/coord/polar.dart' show PolarCoord, PolarCoordConv; export 'src/coord/rect.dart' show RectCoord, RectCoordConv; @@ -75,6 +180,8 @@ export 'src/guide/axis/axis.dart' show TickLine, TickLineMapper, LabelMapper, GridMapper, AxisGuide; export 'src/guide/interaction/tooltip.dart' show TooltipGuide, RenderTooltip; export 'src/guide/interaction/crosshair.dart' show CrosshairGuide; +export 'src/guide/annotation/annotation.dart' show Annotation; +export 'src/guide/annotation/figure.dart' show FigureAnnotation; export 'src/guide/annotation/line.dart' show LineAnnotation; export 'src/guide/annotation/region.dart' show RegionAnnotation; export 'src/guide/annotation/mark.dart' show MarkAnnotation; @@ -83,7 +190,7 @@ export 'src/guide/annotation/custom.dart' show CustomAnnotation; export 'src/interaction/signal.dart' show Signal, SignalType, SignalUpdate; export 'src/interaction/gesture.dart' show GestureType, Gesture, GestureSignal; -export 'src/interaction/selection/selection.dart' show SelectionUpdate; +export 'src/interaction/selection/selection.dart' show Selection, SelectionUpdate; export 'src/interaction/selection/interval.dart' show IntervalSelection; export 'src/interaction/selection/point.dart' show PointSelection; diff --git a/lib/src/aes/aes.dart b/lib/src/aes/aes.dart index c90efe5..76bf6b3 100644 --- a/lib/src/aes/aes.dart +++ b/lib/src/aes/aes.dart @@ -9,7 +9,6 @@ import 'package:graphic/src/dataflow/operator.dart'; import 'package:graphic/src/geom/element.dart'; import 'package:graphic/src/interaction/selection/selection.dart'; import 'package:graphic/src/parse/parse.dart'; -import 'package:graphic/src/parse/spec.dart'; import 'package:graphic/src/shape/shape.dart'; import 'package:graphic/src/util/assert.dart'; import 'package:graphic/src/common/converter.dart'; @@ -141,7 +140,7 @@ class AesOp extends Operator> { } void parseAes( - Spec spec, + Chart spec, View view, Scope scope, ) { diff --git a/lib/src/algebra/varset.dart b/lib/src/algebra/varset.dart index fa24578..641b117 100644 --- a/lib/src/algebra/varset.dart +++ b/lib/src/algebra/varset.dart @@ -18,13 +18,25 @@ Varset _normalize(Varset varset) { return varset; } -/// To store the tags. -/// The term is directly composed of tags, whitch are numerators of factors. -/// Nesting denominators is not supported now. +/// The term composing algebracal forms. +/// +/// The list items are tags representing the factor variables. +/// +/// See also: +/// +/// - [AlgForm], composed of terms. typedef AlgTerm = List; -/// Expressions(monomial or polynomial) will be automatically convert to forms when calculated. -/// tag -> term -> form +/// The algebracal form storing the expression of a varset. +/// +/// A form is an algebra expression whose all items have same orders. Operators +/// of [Varset] guarantee the results are forms. +/// +/// List wrapping is `form[term[tag]]]`. +/// +/// See also: +/// +/// - [Varset], which uses a form to store its expression. typedef AlgForm = List; extension AlgFormExt on AlgForm { diff --git a/lib/src/chart/chart.dart b/lib/src/chart/chart.dart index 30eb787..afff04d 100644 --- a/lib/src/chart/chart.dart +++ b/lib/src/chart/chart.dart @@ -1,7 +1,11 @@ import 'dart:ui'; +import 'package:collection/collection.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/widgets.dart'; +import 'package:graphic/src/coord/polar.dart'; +import 'package:graphic/src/coord/rect.dart'; +import 'package:graphic/src/data/data_set.dart'; import 'package:graphic/src/guide/interaction/crosshair.dart'; import 'package:graphic/src/guide/interaction/tooltip.dart'; import 'package:graphic/src/interaction/gesture.dart'; @@ -10,7 +14,6 @@ import 'package:graphic/src/guide/annotation/annotation.dart'; import 'package:graphic/src/guide/axis/axis.dart'; import 'package:graphic/src/coord/coord.dart'; import 'package:graphic/src/geom/element.dart'; -import 'package:graphic/src/parse/spec.dart'; import 'package:graphic/src/variable/transform/transform.dart'; import 'package:graphic/src/variable/variable.dart'; @@ -18,64 +21,117 @@ import 'view.dart'; /// A widget to display the chart. /// -/// All specification properties are declared in the constructor and then collected -/// by a [spec] property to build the chart. See details in [Spec] class. +/// Specifications details of data visualization are seen in this class properties. +/// The are set in the constructor[new Chart]. /// /// Usually, if any specification or data is changed, the chart will rebuild or /// reevaluate automatically. Some subtle setting is controlled by [rebuild] and -/// [Spec.changeData]. +/// [changeData]. /// -/// The generic [D] is the type of datum in [Spec.data] list. -/// -/// See also: -/// -/// - [Spec], to see the specification property details. +/// The generic [D] is the type of datum in [data] list. class Chart extends StatefulWidget { /// Creates a chart widget. Chart({ - required List data, - bool? changeData, - required Map> variables, - List? transforms, - required List elements, - Coord? coord, - EdgeInsets? padding, - List? axes, - TooltipGuide? tooltip, - CrosshairGuide? crosshair, - List? annotations, - Map? selections, + required this.data, + this.changeData, + required this.variables, + this.transforms, + required this.elements, + this.coord, + this.padding, + this.axes, + this.tooltip, + this.crosshair, + this.annotations, + this.selections, this.rebuild, - }) : spec = Spec( - data: data, - changeData: changeData, - variables: variables, - transforms: transforms, - elements: elements, - coord: coord, - padding: padding, - axes: axes, - tooltip: tooltip, - crosshair: crosshair, - annotations: annotations, - selections: selections, - ); - - /// Specification of the chart. + }); + + /// The data list to visualize. + final List data; + + /// The behavior of data reevaluation when widget is updated. + /// + /// If null, new [data] will be compared with the old one, a [ChangeDataSignal] + /// will be emitted and the chart will be reevaluated only when they are not the + /// same instance. + /// + /// If true, a [ChangeDataSignal] will always be emitted and the chart will always + /// be reevaluated. + /// + /// If false, a [ChangeDataSignal] will never be emitted and the chart will never + /// be reevaluated. + final bool? changeData; + + /// Name identifiers and specifications of variables. + /// + /// The name identifier string will represent the variable in other specifications. + final Map> variables; + + /// Specifications of transforms applied to variable data. + final List? transforms; + + /// Specifications of geometory elements. + final List elements; + + /// Specification of the coordinate. + /// + /// If null, a default [RectCoord] is set. + final Coord? coord; + + /// The padding from coordinate region to the widget border. /// - /// Properties are collected from the [Chart] constructor. - final Spec spec; + /// Usually, the [axes] is attached to the border of coordinate region (See details + /// in [Coord]), and in the [padding] space. + /// + /// If null, a default `EdgeInsets.fromLTRB(40, 5, 10, 20)` for [RectCoord] and + /// `EdgeInsets.all(10)` for [PolarCoord] is set. + final EdgeInsets? padding; + + /// Specifications of axes. + final List? axes; + + /// Specification of tooltip on [selections]. + final TooltipGuide? tooltip; + + /// Specification of pointer crosshair on [selections]. + final CrosshairGuide? crosshair; + + /// Specifications of annotations. + final List? annotations; + + /// Name identifiers and specifications of selection definitions. + /// + /// The name identifier string will represent the selection in other specifications. + final Map? selections; /// The behavior when widget is updated. /// - /// If null, new [spec] will be compared with the old one, and chart will rebuild - /// only when [spec] is changed. + /// If null, new [Chart] will be compared with the old one, and chart will rebuild + /// only when specifications are changed. /// /// If true, chart will always rebuild. /// /// If false, chart will never rebuild. final bool? rebuild; + /// Checks the equlity of two chart specifications. + bool equalSpecTo(Object other) => + other is Chart && + // data are checked by changeData. + changeData == other.changeData && + DeepCollectionEquality().equals(variables, other.variables) && + DeepCollectionEquality().equals(transforms, other.transforms) && + DeepCollectionEquality().equals(elements, other.elements) && + coord == other.coord && + padding == other.padding && + DeepCollectionEquality().equals(axes, other.axes) && + tooltip == other.tooltip && + crosshair == other.crosshair && + DeepCollectionEquality().equals(annotations, other.annotations) && + DeepCollectionEquality().equals(selections, other.selections) && + rebuild == other.rebuild; + @override _ChartState createState() => _ChartState(); } @@ -102,13 +158,13 @@ class _ChartState extends State> { void didUpdateWidget(covariant Chart oldWidget) { super.didUpdateWidget(oldWidget); - if (widget.rebuild ?? widget.spec != oldWidget.spec) { + if (widget.rebuild ?? !widget.equalSpecTo(oldWidget)) { view = null; } else if ( - widget.spec.changeData == true || - (widget.spec.changeData == null && widget.spec.data != oldWidget.spec.data) + widget.changeData == true || + (widget.changeData == null && widget.data != oldWidget.data) ) { - view!.changeData(widget.spec.data); + view!.changeData(widget.data); } } @@ -589,7 +645,7 @@ class _ChartLayoutDelegate extends SingleChildLayoutDelegate { if (state.view == null) { state.view = View( - state.widget.spec, + state.widget, size, state.repaint, ); diff --git a/lib/src/chart/size.dart b/lib/src/chart/size.dart index 3259b5a..47d0ea8 100644 --- a/lib/src/chart/size.dart +++ b/lib/src/chart/size.dart @@ -1,11 +1,11 @@ import 'dart:ui'; import 'package:flutter/painting.dart'; +import 'package:graphic/src/chart/chart.dart'; import 'package:graphic/src/chart/view.dart'; import 'package:graphic/src/common/operators/value.dart'; import 'package:graphic/src/interaction/signal.dart'; import 'package:graphic/src/parse/parse.dart'; -import 'package:graphic/src/parse/spec.dart'; /// The signal emitted when chart size changes. class ResizeSignal extends Signal { @@ -24,7 +24,7 @@ class SizeOp extends Value { } void parseSize( - Spec spec, + Chart spec, View view, Scope scope, ) { diff --git a/lib/src/chart/view.dart b/lib/src/chart/view.dart index cac6d15..2239542 100644 --- a/lib/src/chart/view.dart +++ b/lib/src/chart/view.dart @@ -1,17 +1,18 @@ import 'dart:ui'; -import 'package:graphic/src/chart/size.dart'; import 'package:graphic/src/data/data_set.dart'; import 'package:graphic/src/dataflow/dataflow.dart'; import 'package:graphic/src/graffiti/graffiti.dart'; import 'package:graphic/src/interaction/signal.dart'; import 'package:graphic/src/interaction/gesture.dart'; import 'package:graphic/src/parse/parse.dart'; -import 'package:graphic/src/parse/spec.dart'; + +import 'chart.dart'; +import 'size.dart'; class View extends Dataflow { View( - Spec spec, + Chart spec, this.size, this.repaint, ) diff --git a/lib/src/coord/coord.dart b/lib/src/coord/coord.dart index c69465c..953f21b 100644 --- a/lib/src/coord/coord.dart +++ b/lib/src/coord/coord.dart @@ -2,6 +2,7 @@ import 'dart:ui'; import 'dart:math'; import 'package:flutter/painting.dart'; +import 'package:graphic/src/chart/chart.dart'; import 'package:graphic/src/chart/view.dart'; import 'package:graphic/src/common/converter.dart'; import 'package:graphic/src/common/operators/value.dart'; @@ -9,7 +10,6 @@ import 'package:graphic/src/dataflow/operator.dart'; import 'package:graphic/src/dataflow/tuple.dart'; import 'package:graphic/src/interaction/signal.dart'; import 'package:graphic/src/parse/parse.dart'; -import 'package:graphic/src/parse/spec.dart'; import 'rect.dart'; import 'polar.dart'; @@ -121,7 +121,7 @@ class RegionOp extends Operator { } void parseCoord( - Spec spec, + Chart spec, View view, Scope scope, ) { diff --git a/lib/src/data/data_set.dart b/lib/src/data/data_set.dart index 7d704a9..7b31e24 100644 --- a/lib/src/data/data_set.dart +++ b/lib/src/data/data_set.dart @@ -1,16 +1,16 @@ +import 'package:graphic/src/chart/chart.dart'; import 'package:graphic/src/chart/view.dart'; import 'package:graphic/src/common/operators/value.dart'; import 'package:graphic/src/interaction/signal.dart'; import 'package:graphic/src/parse/parse.dart'; -import 'package:graphic/src/parse/spec.dart'; /// The signal that may be emitted when data changes. /// -/// Whether to emit a change data signal is also affected by [Spec.changeData]. +/// Whether to emit a change data signal is also affected by [Chart.changeData]. /// /// See also: /// -/// - [Spec.changeData], The behavior of whether to emit this signal when data changes. +/// - [Chart.changeData], The behavior of whether to emit this signal when data changes. class ChangeDataSignal extends Signal { /// Creates a change data signal. ChangeDataSignal(this.data); @@ -27,7 +27,7 @@ class DataOp extends Value> { } void parseData( - Spec spec, + Chart spec, View view, Scope scope, ) { diff --git a/lib/src/geom/element.dart b/lib/src/geom/element.dart index b7d03f5..67238bb 100644 --- a/lib/src/geom/element.dart +++ b/lib/src/geom/element.dart @@ -9,6 +9,7 @@ import 'package:graphic/src/aes/label.dart'; import 'package:graphic/src/algebra/varset.dart'; import 'package:graphic/src/aes/shape.dart'; import 'package:graphic/src/aes/size.dart'; +import 'package:graphic/src/chart/chart.dart'; import 'package:graphic/src/chart/view.dart'; import 'package:graphic/src/common/layers.dart'; import 'package:graphic/src/common/operators/render.dart'; @@ -18,7 +19,6 @@ import 'package:graphic/src/dataflow/tuple.dart'; import 'package:graphic/src/graffiti/figure.dart'; import 'package:graphic/src/graffiti/scene.dart'; import 'package:graphic/src/parse/parse.dart'; -import 'package:graphic/src/parse/spec.dart'; import 'package:graphic/src/scale/discrete.dart'; import 'package:graphic/src/scale/scale.dart'; import 'package:graphic/src/shape/area.dart'; @@ -240,7 +240,7 @@ Shape getDefaultShape(GeomElement spec) => throw UnimplementedError('No such geom $spec.'); void parseGeom( - Spec spec, + Chart spec, View view, Scope scope, ) { diff --git a/lib/src/guide/axis/axis.dart b/lib/src/guide/axis/axis.dart index 7985d02..91f47c4 100644 --- a/lib/src/guide/axis/axis.dart +++ b/lib/src/guide/axis/axis.dart @@ -1,3 +1,4 @@ +import 'package:graphic/src/chart/chart.dart'; import 'package:graphic/src/chart/view.dart'; import 'package:graphic/src/common/label.dart'; import 'package:graphic/src/common/layers.dart'; @@ -12,7 +13,6 @@ import 'package:graphic/src/guide/axis/circular.dart'; import 'package:graphic/src/guide/axis/horizontal.dart'; import 'package:graphic/src/guide/axis/radial.dart'; import 'package:graphic/src/guide/axis/vertical.dart'; -import 'package:graphic/src/parse/spec.dart'; import 'package:graphic/src/scale/scale.dart'; import 'package:graphic/src/util/assert.dart'; @@ -78,7 +78,7 @@ class AxisGuide { /// The dimension where this axis lies. /// - /// If null, the index of this axis in the [Spec.axes] list plus 1 is set by + /// If null, the index of this axis in the [Chart.axes] list plus 1 is set by /// default. int? dim; diff --git a/lib/src/guide/guide.dart b/lib/src/guide/guide.dart index 1b80d49..a2af256 100644 --- a/lib/src/guide/guide.dart +++ b/lib/src/guide/guide.dart @@ -1,10 +1,10 @@ import 'package:flutter/painting.dart'; +import 'package:graphic/src/chart/chart.dart'; import 'package:graphic/src/chart/view.dart'; import 'package:graphic/src/common/styles.dart'; import 'package:graphic/src/guide/annotation/custom.dart'; import 'package:graphic/src/interaction/selection/point.dart'; import 'package:graphic/src/parse/parse.dart'; -import 'package:graphic/src/parse/spec.dart'; import 'axis/axis.dart'; import 'annotation/line.dart'; @@ -16,7 +16,7 @@ import 'interaction/crosshair.dart'; import 'interaction/tooltip.dart'; void parseGuide( - Spec spec, + Chart spec, View view, Scope scope, ) { diff --git a/lib/src/guide/interaction/crosshair.dart b/lib/src/guide/interaction/crosshair.dart index 13fb294..1bc9df4 100644 --- a/lib/src/guide/interaction/crosshair.dart +++ b/lib/src/guide/interaction/crosshair.dart @@ -1,6 +1,7 @@ import 'dart:ui'; import 'package:collection/collection.dart'; +import 'package:graphic/src/chart/chart.dart'; import 'package:graphic/src/chart/view.dart'; import 'package:graphic/src/common/layers.dart'; import 'package:graphic/src/common/operators/render.dart'; @@ -12,7 +13,6 @@ import 'package:graphic/src/dataflow/tuple.dart'; import 'package:graphic/src/graffiti/figure.dart'; import 'package:graphic/src/graffiti/scene.dart'; import 'package:graphic/src/interaction/selection/selection.dart'; -import 'package:graphic/src/parse/spec.dart'; import 'package:graphic/src/util/path.dart'; /// The specification of a crosshair @@ -52,7 +52,7 @@ class CrosshairGuide { /// Which element series this crosshair reacts to. /// - /// This is an index in [Spec.elements]. + /// This is an index in [Chart.elements]. /// /// The crosshair can only reacts to one element series. /// diff --git a/lib/src/guide/interaction/tooltip.dart b/lib/src/guide/interaction/tooltip.dart index 295b53c..0c1805d 100644 --- a/lib/src/guide/interaction/tooltip.dart +++ b/lib/src/guide/interaction/tooltip.dart @@ -2,6 +2,7 @@ import 'dart:ui'; import 'package:collection/collection.dart'; import 'package:flutter/painting.dart'; +import 'package:graphic/src/chart/chart.dart'; import 'package:graphic/src/chart/view.dart'; import 'package:graphic/src/common/label.dart'; import 'package:graphic/src/common/layers.dart'; @@ -13,7 +14,6 @@ import 'package:graphic/src/graffiti/scene.dart'; import 'package:graphic/src/interaction/selection/interval.dart'; import 'package:graphic/src/interaction/selection/point.dart'; import 'package:graphic/src/interaction/selection/selection.dart'; -import 'package:graphic/src/parse/spec.dart'; import 'package:graphic/src/scale/scale.dart'; import 'package:graphic/src/util/assert.dart'; @@ -84,7 +84,7 @@ class TooltipGuide { /// Which element series this tooltip reacts to. /// - /// This is an index in [Spec.elements]. + /// This is an index in [Chart.elements]. /// /// The crosshair can only reacts to one element series. /// diff --git a/lib/src/interaction/gesture.dart b/lib/src/interaction/gesture.dart index 8421067..506b386 100644 --- a/lib/src/interaction/gesture.dart +++ b/lib/src/interaction/gesture.dart @@ -2,10 +2,10 @@ import 'dart:ui'; import 'package:flutter/gestures.dart'; import 'package:flutter/widgets.dart'; +import 'package:graphic/src/chart/chart.dart'; import 'package:graphic/src/chart/view.dart'; import 'package:graphic/src/common/operators/value.dart'; import 'package:graphic/src/parse/parse.dart'; -import 'package:graphic/src/parse/spec.dart'; import 'signal.dart'; @@ -534,7 +534,7 @@ class GestureOp extends Value { } void parseGesture( - Spec spec, + Chart spec, View view, Scope scope, ) { diff --git a/lib/src/interaction/selection/selection.dart b/lib/src/interaction/selection/selection.dart index ea35398..90d22a8 100644 --- a/lib/src/interaction/selection/selection.dart +++ b/lib/src/interaction/selection/selection.dart @@ -3,6 +3,7 @@ import 'dart:ui'; import 'package:flutter/gestures.dart'; import 'package:flutter/painting.dart'; import 'package:graphic/src/aes/aes.dart'; +import 'package:graphic/src/chart/chart.dart'; import 'package:graphic/src/chart/view.dart'; import 'package:graphic/src/common/label.dart'; import 'package:graphic/src/common/layers.dart'; @@ -15,7 +16,6 @@ import 'package:graphic/src/geom/element.dart'; import 'package:graphic/src/graffiti/scene.dart'; import 'package:graphic/src/interaction/gesture.dart'; import 'package:graphic/src/parse/parse.dart'; -import 'package:graphic/src/parse/spec.dart'; import 'package:graphic/src/shape/shape.dart'; import 'package:collection/collection.dart'; @@ -357,7 +357,7 @@ class SelectionUpdateOp extends Operator { } void parseSelect( - Spec spec, + Chart spec, View view, Scope scope, ) { diff --git a/lib/src/interaction/signal.dart b/lib/src/interaction/signal.dart index 8a53eec..f317cb0 100644 --- a/lib/src/interaction/signal.dart +++ b/lib/src/interaction/signal.dart @@ -1,3 +1,4 @@ +import 'package:graphic/src/chart/chart.dart'; import 'package:graphic/src/chart/size.dart'; import 'package:graphic/src/chart/view.dart'; import 'package:graphic/src/common/operators/value.dart'; @@ -6,7 +7,6 @@ import 'package:graphic/src/dataflow/operator.dart'; import 'package:graphic/src/interaction/gesture.dart'; import 'package:graphic/src/interaction/selection/selection.dart'; import 'package:graphic/src/parse/parse.dart'; -import 'package:graphic/src/parse/spec.dart'; /// Types of [Signal]s. enum SignalType { @@ -93,7 +93,7 @@ class SignalUpdateOp extends Operator { } void parseSignal( - Spec spec, + Chart spec, View view, Scope scope, ) { diff --git a/lib/src/parse/parse.dart b/lib/src/parse/parse.dart index 3657c77..31d77da 100644 --- a/lib/src/parse/parse.dart +++ b/lib/src/parse/parse.dart @@ -1,6 +1,7 @@ import 'package:graphic/src/aes/aes.dart'; import 'package:graphic/src/aes/position.dart'; import 'package:graphic/src/algebra/varset.dart'; +import 'package:graphic/src/chart/chart.dart'; import 'package:graphic/src/chart/size.dart'; import 'package:graphic/src/chart/view.dart'; import 'package:graphic/src/coord/coord.dart'; @@ -15,8 +16,6 @@ import 'package:graphic/src/scale/scale.dart'; import 'package:graphic/src/dataflow/tuple.dart'; import 'package:graphic/src/variable/variable.dart'; -import 'spec.dart'; - class Scope { Map scaleSpecs = {}; @@ -49,7 +48,7 @@ class Scope { List selectsList = []; } -void parse(Spec spec, View view) { +void parse(Chart spec, View view) { final scope = Scope(); parseSize(spec, view, scope); parseGesture(spec, view, scope); diff --git a/lib/src/parse/spec.dart b/lib/src/parse/spec.dart deleted file mode 100644 index 80130d4..0000000 --- a/lib/src/parse/spec.dart +++ /dev/null @@ -1,123 +0,0 @@ -import 'package:collection/collection.dart'; -import 'package:flutter/painting.dart'; -import 'package:graphic/src/chart/chart.dart'; -import 'package:graphic/src/coord/polar.dart'; -import 'package:graphic/src/coord/rect.dart'; -import 'package:graphic/src/data/data_set.dart'; -import 'package:graphic/src/guide/interaction/crosshair.dart'; -import 'package:graphic/src/guide/interaction/tooltip.dart'; -import 'package:graphic/src/interaction/selection/selection.dart'; -import 'package:graphic/src/guide/annotation/annotation.dart'; -import 'package:graphic/src/guide/axis/axis.dart'; -import 'package:graphic/src/coord/coord.dart'; -import 'package:graphic/src/geom/element.dart'; -import 'package:graphic/src/variable/transform/transform.dart'; -import 'package:graphic/src/variable/variable.dart'; - -/// The specification of a chart. -/// -/// The generic [D] is the type of datum in [data] list. -/// -/// See also: -/// -/// - [Chart], the widget where the specification is declared. -/// - [Variable], variable specification. -/// - [VariableTransform], variable transform specification. -/// - [GeomElement], geometory element specification. -/// - [Coord], coordinate specification. -/// - [AxisGuide], axis specification. -/// - [TooltipGuide], tooltip specification. -/// - [CrosshairGuide], crosshair specification. -/// - [Annotation], annotation specification. -/// - [Selection], selection specification. -class Spec { - /// Creates a chart specification. - Spec({ - required this.data, - this.changeData, - required this.variables, - this.transforms, - required this.elements, - this.coord, - this.padding, - this.axes, - this.tooltip, - this.crosshair, - this.annotations, - this.selections, - }); - - /// The data list to visualize. - final List data; - - /// The behavior of data reevaluation when widget is updated. - /// - /// If null, new [data] will be compared with the old one, a [ChangeDataSignal] - /// will be emitted and the chart will be reevaluated only when they are not the - /// same instance. - /// - /// If true, a [ChangeDataSignal] will always be emitted and the chart will always - /// be reevaluated. - /// - /// If false, a [ChangeDataSignal] will never be emitted and the chart will never - /// be reevaluated. - final bool? changeData; - - /// Name identifiers and specifications of variables. - /// - /// The name identifier string will represent the variable in other specifications. - final Map> variables; - - /// Specifications of transforms applied to variable data. - final List? transforms; - - /// Specifications of geometory elements. - final List elements; - - /// Specification of the coordinate. - /// - /// If null, a default [RectCoord] is set. - final Coord? coord; - - /// The padding from coordinate region to the widget border. - /// - /// Usually, the [axes] is attached to the border of coordinate region (See details - /// in [Coord]), and in the [padding] space. - /// - /// If null, a default `EdgeInsets.fromLTRB(40, 5, 10, 20)` for [RectCoord] and - /// `EdgeInsets.all(10)` for [PolarCoord] is set. - final EdgeInsets? padding; - - /// Specifications of axes. - final List? axes; - - /// Specification of tooltip on [selections]. - final TooltipGuide? tooltip; - - /// Specification of pointer crosshair on [selections]. - final CrosshairGuide? crosshair; - - /// Specifications of annotations. - final List? annotations; - - /// Name identifiers and specifications of selection definitions. - /// - /// The name identifier string will represent the selection in other specifications. - final Map? selections; - - @override - bool operator ==(Object other) => - other is Spec && - DeepCollectionEquality().equals(data, other.data) && - changeData == other.changeData && - DeepCollectionEquality().equals(variables, other.variables) && - DeepCollectionEquality().equals(transforms, other.transforms) && - DeepCollectionEquality().equals(elements, other.elements) && - coord == other.coord && - padding == other.padding && - DeepCollectionEquality().equals(axes, other.axes) && - tooltip == other.tooltip && - crosshair == other.crosshair && - DeepCollectionEquality().equals(annotations, other.annotations) && - DeepCollectionEquality().equals(selections, other.selections); -} diff --git a/lib/src/scale/scale.dart b/lib/src/scale/scale.dart index d602b8c..1b3c54d 100644 --- a/lib/src/scale/scale.dart +++ b/lib/src/scale/scale.dart @@ -1,10 +1,10 @@ import 'package:collection/collection.dart'; +import 'package:graphic/src/chart/chart.dart'; import 'package:graphic/src/chart/view.dart'; import 'package:graphic/src/dataflow/operator.dart'; import 'package:graphic/src/guide/axis/axis.dart'; import 'package:graphic/src/guide/interaction/tooltip.dart'; import 'package:graphic/src/parse/parse.dart'; -import 'package:graphic/src/parse/spec.dart'; import 'package:graphic/src/util/assert.dart'; import 'package:flutter/foundation.dart'; import 'package:graphic/src/common/converter.dart'; @@ -176,7 +176,7 @@ class ScaleOp extends Operator> { } void parseScale( - Spec spec, + Chart spec, View view, Scope scope, ) { diff --git a/lib/src/variable/variable.dart b/lib/src/variable/variable.dart index 68c13d6..4fd12d4 100644 --- a/lib/src/variable/variable.dart +++ b/lib/src/variable/variable.dart @@ -1,9 +1,9 @@ +import 'package:graphic/src/chart/chart.dart'; import 'package:graphic/src/chart/view.dart'; import 'package:graphic/src/common/reserveds.dart'; import 'package:graphic/src/dataflow/operator.dart'; import 'package:graphic/src/dataflow/tuple.dart'; import 'package:graphic/src/parse/parse.dart'; -import 'package:graphic/src/parse/spec.dart'; import 'package:graphic/src/scale/linear.dart'; import 'package:graphic/src/scale/ordinal.dart'; import 'package:graphic/src/scale/scale.dart'; @@ -23,12 +23,12 @@ typedef Accessor = V Function(D); /// The specification of a variable. /// -/// Instead of raw [Spec.data], the chart reorgnize datum to "original value tuple" +/// Instead of raw [Chart.data], the chart reorgnize datum to "original value tuple" /// (See details in [Tuple]) for internal usage. The variable defines how to create /// a field in original value tuple form input datum, and the scale specification /// of the field. /// -/// The generic [D] is the type of datum in [Spec.data] list, and [V] is the type +/// The generic [D] is the type of datum in [Chart.data] list, and [V] is the type /// of field value. [V] can only be [String], [num] or [DateTime]. /// /// See also: @@ -89,7 +89,7 @@ class VariableOp extends Operator> { } void parseVariable( - Spec spec, + Chart spec, View view, Scope scope, ) { diff --git a/pubspec.yaml b/pubspec.yaml index 8c1d9e8..189bca1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: graphic description: A declarative, interactive grammar of data visualization. It provides a Flutter charting library. -version: 0.4.0 +version: 0.4.1 homepage: https://github.com/entronad/graphic environment: