| /* |
| * Copyright 2014 Google Inc. All rights reserved. |
| * |
| * Use of this source code is governed by a BSD-style |
| * license that can be found in the LICENSE file or at |
| * https://developers.google.com/open-source/licenses/bsd |
| */ |
| |
| part of charted.charts; |
| |
| typedef bool FilterFunction(dynamic value); |
| |
| /** |
| * Transforms the ChartData base on the specified FilterDefinitions. Each row |
| * of data will be tested by passing the value at target column to the filter |
| * function. If filter function returns false, the row will be filtered out. |
| * This transformer does not modify the column part of the input ChartData. |
| */ |
| class FilterTransformer extends ChangeNotifier |
| implements ChartDataTransform, ChartData { |
| final SubscriptionsDisposer _dataSubscriptions = new SubscriptionsDisposer(); |
| Iterable<ChartColumnSpec> columns; |
| ObservableList<Iterable> rows = new ObservableList(); |
| List<FilterDefinition> filterFunctions; |
| ChartData _data; |
| |
| FilterTransformer(this.filterFunctions); |
| |
| /** |
| * Transforms the input data with the list of [FilterDefinition] specified in |
| * the constructor. If the rows and columns are ObservableList in the data, |
| * changes in rows and columns in input data will trigger tranform to be |
| * performed again to update the output rows and columns. |
| */ |
| ChartData transform(ChartData data) { |
| _data = data; |
| _registerListeners(); |
| _transform(); |
| return this; |
| } |
| |
| /** Registers listeners if data.rows or data.columns are Observable. */ |
| _registerListeners() { |
| _dataSubscriptions.dispose(); |
| |
| if(_data is Observable) { |
| var observable = (_data as Observable); |
| _dataSubscriptions.add(observable.changes.listen((records) { |
| _transform(); |
| |
| // NOTE: Currently we're only passing the first change because the chart |
| // area just draw with the updated data. When we add partial update |
| // to chart area, we'll need to handle this better. |
| notifyChange(records.first); |
| })); |
| } |
| } |
| |
| /** |
| * Performs the filter transform with _data. This is called on transform and |
| * onChange if the input ChartData is Observable. |
| */ |
| _transform() { |
| columns = _data.columns; |
| rows.clear(); |
| |
| for (var row in _data.rows) { |
| // Add the row if each value in target column passes the filter function. |
| if (filterFunctions.every((e) => |
| e.filterFunc(row.elementAt(e.targetColumn)))) { |
| rows.add(row); |
| } |
| } |
| } |
| } |
| |
| class FilterDefinition { |
| final FilterFunction filterFunc; |
| final int targetColumn; |
| FilterDefinition(this.targetColumn, this.filterFunc); |
| } |