flutter/examples/fitness/lib/measurement.dart
Collin Jackson f164e560c3 Add date picker to widgets library and teach fitness app to use it
Also, add an example for the date picker
2015-08-25 16:41:11 -07:00

218 lines
5.5 KiB
Dart

// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
part of fitness;
class Measurement extends FitnessItem {
Measurement({ DateTime when, this.weight }) : super(when: when);
Measurement.fromJson(Map json) : super.fromJson(json), weight = json['weight'];
final double weight;
// TODO(jackson): Internationalize
String get displayWeight => "${weight.toStringAsFixed(1)} lbs";
@override
Map toJson() {
Map json = super.toJson();
json['weight'] = weight;
json['type'] = runtimeType.toString();
return json;
}
FitnessItemRow toRow({ FitnessItemHandler onDismissed }) {
return new MeasurementRow(measurement: this, onDismissed: onDismissed);
}
}
class MeasurementRow extends FitnessItemRow {
MeasurementRow({ Measurement measurement, FitnessItemHandler onDismissed })
: super(item: measurement, onDismissed: onDismissed);
Widget buildContent() {
Measurement measurement = item;
List<Widget> children = [
new Flexible(
child: new Text(
measurement.displayWeight,
style: Theme.of(this).text.subhead
)
),
new Flexible(
child: new Text(
measurement.displayDate,
style: Theme.of(this).text.caption.copyWith(textAlign: TextAlign.right)
)
)
];
return new Flex(
children,
alignItems: FlexAlignItems.baseline,
textBaseline: DefaultTextStyle.of(this).textBaseline
);
}
}
class MeasurementDateDialog extends StatefulComponent {
MeasurementDateDialog({ this.navigator, this.previousDate });
Navigator navigator;
DateTime previousDate;
@override
void initState() {
_selectedDate = previousDate;
}
void syncConstructorArguments(MeasurementDateDialog source) {
navigator = source.navigator;
previousDate = source.previousDate;
}
DateTime _selectedDate;
void _handleDateChanged(DateTime value) {
setState(() {
_selectedDate = value;
});
}
Widget build() {
return new Dialog(
content: new DatePicker(
selectedDate: _selectedDate,
firstDate: new DateTime(2015, 8),
lastDate: new DateTime(2101),
onChanged: _handleDateChanged
),
contentPadding: EdgeDims.zero,
actions: [
new FlatButton(
child: new Text('CANCEL'),
onPressed: navigator.pop
),
new FlatButton(
child: new Text('OK'),
onPressed: () {
navigator.pop(_selectedDate);
}
),
]
);
}
}
class MeasurementFragment extends StatefulComponent {
MeasurementFragment({ this.navigator, this.onCreated });
Navigator navigator;
FitnessItemHandler onCreated;
void syncConstructorArguments(MeasurementFragment source) {
navigator = source.navigator;
onCreated = source.onCreated;
}
String _weight = "";
DateTime _when = new DateTime.now();
String _errorMessage = null;
EventDisposition _handleSave() {
double parsedWeight;
try {
parsedWeight = double.parse(_weight);
} on FormatException catch(e) {
print("Exception $e");
setState(() {
_errorMessage = "Save failed";
});
return EventDisposition.processed;
}
onCreated(new Measurement(when: _when, weight: parsedWeight));
navigator.pop();
return EventDisposition.processed;
}
Widget buildToolBar() {
return new ToolBar(
left: new IconButton(
icon: "navigation/close",
onPressed: navigator.pop),
center: new Text('New Measurement'),
right: [new InkWell(
child: new Listener(
onGestureTap: (_) => _handleSave(),
child: new Text('SAVE')
)
)]
);
}
void _handleWeightChanged(String weight) {
setState(() {
_weight = weight;
});
}
static final GlobalKey weightKey = new GlobalKey();
EventDisposition _handleDatePressed(_) {
showDialog(navigator, (navigator) {
return new MeasurementDateDialog(navigator: navigator, previousDate: _when);
}).then((DateTime value) {
if (value == null)
return;
setState(() {
_when = value;
});
});
return EventDisposition.processed;
}
Widget buildBody() {
Measurement measurement = new Measurement(when: _when);
// TODO(jackson): Revisit the layout of this pane to be more maintainable
return new Material(
type: MaterialType.canvas,
child: new Container(
padding: const EdgeDims.all(20.0),
child: new Column([
new Listener(
onGestureTap: _handleDatePressed,
child: new Container(
height: 50.0,
child: new Column([
new Text('Measurement Date'),
new Text(measurement.displayDate, style: Theme.of(this).text.caption),
], alignItems: FlexAlignItems.start)
)
),
new Input(
key: weightKey,
placeholder: 'Enter weight',
keyboardType: KeyboardType_NUMBER,
onChanged: _handleWeightChanged
),
], alignItems: FlexAlignItems.stretch)
)
);
}
Widget buildSnackBar() {
if (_errorMessage == null)
return null;
// TODO(jackson): This doesn't show up, unclear why.
return new SnackBar(content: new Text(_errorMessage), showing: true);
}
Widget build() {
return new Scaffold(
toolbar: buildToolBar(),
body: buildBody(),
snackBar: buildSnackBar()
);
}
}