OLD | NEW |
1 // | 1 // |
2 // Copyright 2014 Google Inc. All rights reserved. | 2 // Copyright 2014 Google Inc. All rights reserved. |
3 // | 3 // |
4 // Use of this source code is governed by a BSD-style | 4 // Use of this source code is governed by a BSD-style |
5 // license that can be found in the LICENSE file or at | 5 // license that can be found in the LICENSE file or at |
6 // https://developers.google.com/open-source/licenses/bsd | 6 // https://developers.google.com/open-source/licenses/bsd |
7 // | 7 // |
8 | 8 |
9 part of charted.charts; | 9 part of charted.charts; |
10 | 10 |
11 /// Transforms the ChartData by transposing the columns and rows. A label colum
n | 11 /// Transforms the ChartData by transposing the columns and rows. A label colum
n |
12 /// index in the original data will need to be specified (default to 0), all | 12 /// index in the original data will need to be specified (default to 0), all |
13 /// values in the specified label column will be used as the label for the | 13 /// values in the specified label column will be used as the label for the |
14 /// transformed data, all the labels in the original Chart data columns will be | 14 /// transformed data, all the labels in the original Chart data columns will be |
15 /// populated in the label column as values of that column. | 15 /// populated in the label column as values of that column. |
16 /// | 16 /// |
17 /// All values in the data except for the data in the label column must have the | 17 /// All values in the data except for the data in the label column must have the |
18 /// same type; All columns except for the label column must have the same | 18 /// same type; All columns except for the label column must have the same |
19 /// formatter if a formatter exist for columns. | 19 /// formatter if a formatter exist for columns. |
20 class TransposeTransformer extends ChangeNotifier | 20 class TransposeTransformer extends ChangeNotifier |
21 implements ChartDataTransform, ChartData { | 21 implements ChartDataTransform, ChartData { |
22 final SubscriptionsDisposer _dataSubscriptions = new SubscriptionsDisposer(); | 22 final SubscriptionsDisposer _dataSubscriptions = new SubscriptionsDisposer(); |
23 ObservableList<ChartColumnSpec> columns = new ObservableList(); | 23 ObservableList<ChartColumnSpec> columns = new ObservableList(); |
24 ObservableList<Iterable> rows = new ObservableList(); | 24 ObservableList<List> rows = new ObservableList(); |
25 | 25 |
26 // If specified, this values of this column in the input chart data will be | 26 // If specified, this values of this column in the input chart data will be |
27 // used as labels of the transposed column label. Defaults to first column. | 27 // used as labels of the transposed column label. Defaults to first column. |
28 int _labelColumn; | 28 int _labelColumn; |
29 ChartData _data; | 29 ChartData _data; |
30 | 30 |
31 TransposeTransformer([this._labelColumn = 0]); | 31 TransposeTransformer([this._labelColumn = 0]); |
32 | 32 |
33 /// Transforms the input data with the specified label column in the | 33 /// Transforms the input data with the specified label column in the |
34 /// constructor. If the ChartData is Observable, changes fired by the input | 34 /// constructor. If the ChartData is Observable, changes fired by the input |
(...skipping 22 matching lines...) Expand all Loading... |
57 })); | 57 })); |
58 } | 58 } |
59 } | 59 } |
60 | 60 |
61 /// Performs the transpose transform with _data. This is called on transform | 61 /// Performs the transpose transform with _data. This is called on transform |
62 /// and on changes if ChartData is Observable. | 62 /// and on changes if ChartData is Observable. |
63 _transform() { | 63 _transform() { |
64 // Assert all columns are of the same type and formatter, excluding the | 64 // Assert all columns are of the same type and formatter, excluding the |
65 // label column. | 65 // label column. |
66 var type; | 66 var type; |
67 var formatter; | 67 FormatFunction formatter; |
68 for (var i = 0; i < _data.columns.length; i++) { | 68 for (var i = 0; i < _data.columns.length; i++) { |
69 if (i != _labelColumn) { | 69 if (i != _labelColumn) { |
70 if (type == null) { | 70 if (type == null) { |
71 type = _data.columns.elementAt(i).type; | 71 type = _data.columns.elementAt(i).type; |
72 } else { | 72 } else { |
73 assert(type == _data.columns.elementAt(i).type); | 73 assert(type == _data.columns.elementAt(i).type); |
74 } | 74 } |
75 if (formatter == null) { | 75 if (formatter == null) { |
76 formatter = _data.columns.elementAt(i).formatter; | 76 formatter = _data.columns.elementAt(i).formatter; |
77 } else { | 77 } else { |
78 assert(formatter == _data.columns.elementAt(i).formatter); | 78 assert(formatter == _data.columns.elementAt(i).formatter); |
79 } | 79 } |
80 } | 80 } |
81 } | 81 } |
82 | 82 |
83 columns.clear(); | 83 columns.clear(); |
84 rows.clear(); | 84 rows.clear(); |
85 rows.addAll( | 85 rows.addAll(new List<List>.generate(_data.columns.length - 1, (i) => [])); |
86 new List<Iterable>.generate(_data.columns.length - 1, (i) => [])); | |
87 | 86 |
88 // Populate the transposed rows' data, excluding the label column, visit | 87 // Populate the transposed rows' data, excluding the label column, visit |
89 // each value in the original data once. | 88 // each value in the original data once. |
90 var columnLabels = []; | 89 var columnLabels = []; |
91 for (var row in _data.rows) { | 90 for (var row in _data.rows) { |
92 for (var i = 0; i < row.length; i++) { | 91 for (var i = 0; i < row.length; i++) { |
93 var columnOffset = (i < _labelColumn) ? 0 : 1; | 92 var columnOffset = (i < _labelColumn) ? 0 : 1; |
94 if (i != _labelColumn) { | 93 if (i != _labelColumn) { |
95 (rows.elementAt(i - columnOffset) as List).add(row.elementAt(i)); | 94 rows.elementAt(i - columnOffset).add(row.elementAt(i)); |
96 } else { | 95 } else { |
97 columnLabels.add(row.elementAt(i)); | 96 columnLabels.add(row.elementAt(i)); |
98 } | 97 } |
99 } | 98 } |
100 } | 99 } |
101 | 100 |
102 // Transpose the ColumnSpec's label into the column where the original | 101 // Transpose the ColumnSpec's label into the column where the original |
103 // column that is used as the new label. | 102 // column that is used as the new label. |
104 for (var i = 0; i < rows.length; i++) { | 103 for (var i = 0; i < rows.length; i++) { |
105 var columnOffset = (i < _labelColumn) ? 0 : 1; | 104 var columnOffset = (i < _labelColumn) ? 0 : 1; |
106 (rows.elementAt(i) as List).insert( | 105 rows.elementAt(i).insert( |
107 _labelColumn, _data.columns.elementAt(i + columnOffset).label); | 106 _labelColumn, _data.columns.elementAt(i + columnOffset).label); |
108 } | 107 } |
109 | 108 |
110 // Construct new ColumnSpaces base on the label column. | 109 // Construct new ColumnSpaces base on the label column. |
111 for (var label in columnLabels) { | 110 for (var label in columnLabels) { |
112 columns.add( | 111 columns.add( |
113 new ChartColumnSpec(type: type, label: label, formatter: formatter)); | 112 new ChartColumnSpec(type: type, label: label, formatter: formatter)); |
114 } | 113 } |
115 columns.insert( | 114 columns.insert( |
116 _labelColumn, | 115 _labelColumn, |
117 new ChartColumnSpec( | 116 new ChartColumnSpec( |
118 type: ChartColumnSpec.TYPE_STRING, | 117 type: ChartColumnSpec.TYPE_STRING, |
119 label: _data.columns.elementAt(_labelColumn).label)); | 118 label: _data.columns.elementAt(_labelColumn).label)); |
120 } | 119 } |
121 } | 120 } |
OLD | NEW |