WIP #120 Numeric state charts

This commit is contained in:
Yegor Vialov
2018-10-28 20:01:01 +02:00
parent e16338c3f2
commit fcd4ac7292
8 changed files with 221 additions and 30 deletions

View File

@ -1,8 +1,9 @@
part of '../../main.dart';
class EntityHistoryWidgetType {
static const int simplest = 0;
static const int simple = 0;
static const int valueToTime = 1;
static const int randomColors = 2;
}
class EntityHistoryWidget extends StatefulWidget {
@ -69,9 +70,7 @@ class _EntityHistoryWidgetState extends State<EntityHistoryWidget> {
);
} else {
children.add(
SimpleStateHistoryChartWidget(
rawHistory: _history
)
_selectChartWidget()
);
}
children.add(Divider());
@ -83,4 +82,27 @@ class _EntityHistoryWidgetState extends State<EntityHistoryWidget> {
);
}
Widget _selectChartWidget() {
switch (widget.type) {
case EntityHistoryWidgetType.simple: {
return SimpleStateHistoryChartWidget(
rawHistory: _history,
);
}
case EntityHistoryWidgetType.valueToTime: {
return NumericStateHistoryChartWidget(
rawHistory: _history,
);
}
default: {
return SimpleStateHistoryChartWidget(
rawHistory: _history,
);
}
}
}
}

View File

@ -0,0 +1,140 @@
part of '../../main.dart';
class NumericStateHistoryChartWidget extends StatefulWidget {
final rawHistory;
const NumericStateHistoryChartWidget({Key key, this.rawHistory}) : super(key: key);
@override
State<StatefulWidget> createState() {
return new _NumericStateHistoryChartWidgetState();
}
}
class _NumericStateHistoryChartWidgetState extends State<NumericStateHistoryChartWidget> {
int _selectedId = -1;
List<charts.Series<NumericEntityStateHistoryMoment, DateTime>> _parsedHistory;
@override
Widget build(BuildContext context) {
_parsedHistory = _parseHistory();
DateTime selectedTime;
double selectedState;
if ((_selectedId > -1) && (_parsedHistory != null) && (_parsedHistory.first.data.length >= (_selectedId + 1))) {
selectedTime = _parsedHistory.first.data[_selectedId].time;
selectedState = _parsedHistory.first.data[_selectedId].value;
}
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
HistoryControlWidget(
selectedTimeStart: selectedTime,
selectedState: "$selectedState",
onPrevTap: () => _selectPrev(),
onNextTap: () => _selectNext(),
),
SizedBox(
height: 150.0,
child: charts.TimeSeriesChart(
_parsedHistory,
animate: false,
primaryMeasureAxis: new charts.NumericAxisSpec(
tickProviderSpec:
new charts.BasicNumericTickProviderSpec(zeroBound: false)),
dateTimeFactory: const charts.LocalDateTimeFactory(),
defaultRenderer: charts.LineRendererConfig(),
customSeriesRenderers: [
new charts.PointRendererConfig(
// ID used to link series to this renderer.
customRendererId: 'valuePoints')
],
/*primaryMeasureAxis: charts.NumericAxisSpec(
renderSpec: charts.NoneRenderSpec()
),*/
selectionModels: [
new charts.SelectionModelConfig(
type: charts.SelectionModelType.info,
listener: (model) => _onSelectionChanged(model),
)
],
behaviors: [
charts.PanAndZoomBehavior(),
],
),
)
],
);
}
List<charts.Series<NumericEntityStateHistoryMoment, DateTime>> _parseHistory() {
List<NumericEntityStateHistoryMoment> data = [];
DateTime now = DateTime.now();
for (var i = 0; i < widget.rawHistory.length; i++) {
var stateData = widget.rawHistory[i];
DateTime time = DateTime.tryParse(stateData["last_updated"])?.toLocal();
data.add(NumericEntityStateHistoryMoment(double.tryParse(stateData["state"]), time, i));
}
data.add(NumericEntityStateHistoryMoment(data.last.value, now, widget.rawHistory.length));
return [
new charts.Series<NumericEntityStateHistoryMoment, DateTime>(
id: 'State',
colorFn: (NumericEntityStateHistoryMoment historyMoment, __) => EntityColors.historyStateColor("unavailable"),
domainFn: (NumericEntityStateHistoryMoment historyMoment, _) => historyMoment.time,
measureFn: (NumericEntityStateHistoryMoment historyMoment, _) => historyMoment.value,
data: data,
),
new charts.Series<NumericEntityStateHistoryMoment, DateTime>(
id: 'State',
radiusPxFn: (NumericEntityStateHistoryMoment historyMoment, __) => (historyMoment.id == _selectedId) ? 4.0 : 2.0,
colorFn: (NumericEntityStateHistoryMoment historyMoment, __) => (historyMoment.id == _selectedId) ? EntityColors.historyStateColor("on") : EntityColors.historyStateColor("off"),
domainFn: (NumericEntityStateHistoryMoment historyMoment, _) => historyMoment.time,
measureFn: (NumericEntityStateHistoryMoment historyMoment, _) => historyMoment.value,
data: data,
)..setAttribute(charts.rendererIdKey, 'valuePoints')
];
}
void _selectPrev() {
if (_selectedId > 0) {
setState(() {
_selectedId -= 1;
});
}
}
void _selectNext() {
if (_selectedId < (_parsedHistory.first.data.length - 2)) {
setState(() {
_selectedId += 1;
});
}
}
void _onSelectionChanged(charts.SelectionModel model) {
final selectedDatum = model.selectedDatum;
int selectedId;
if (selectedDatum.isNotEmpty) {
selectedId = selectedDatum.first.datum.id;
setState(() {
_selectedId = selectedId;
});
} else {
setState(() {
});
}
}
}
class NumericEntityStateHistoryMoment {
final DateTime time;
final double value;
final int id;
NumericEntityStateHistoryMoment(this.value, this.time, this.id);
}

View File

@ -162,15 +162,7 @@ class HistoryControlWidget extends StatelessWidget {
),
),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("${formatDate(selectedTimeStart, [M, ' ', d, ', ', HH, ':', nn, ':', ss])}", textAlign: TextAlign.left,),
Text("${formatDate(selectedTimeEnd ?? selectedTimeStart, [M, ' ', d, ', ', HH, ':', nn, ':', ss])}", textAlign: TextAlign.left,),
],
),
),
_buildTime(),
IconButton(
icon: Icon(Icons.chevron_right),
padding: EdgeInsets.all(0.0),
@ -185,6 +177,24 @@ class HistoryControlWidget extends StatelessWidget {
}
}
Widget _buildTime() {
List<Widget> children = [];
children.add(
Text("${formatDate(selectedTimeStart, [M, ' ', d, ', ', HH, ':', nn, ':', ss])}", textAlign: TextAlign.left,)
);
if (selectedTimeEnd != null) {
children.add(
Text("${formatDate(selectedTimeEnd, [M, ' ', d, ', ', HH, ':', nn, ':', ss])}", textAlign: TextAlign.left,)
);
}
return Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: children,
),
);
}
}
class SimpleEntityStateHistoryMoment {