| // 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 Row( |
| 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; |
| |
| void _handleSave() { |
| double parsedWeight; |
| try { |
| parsedWeight = double.parse(_weight); |
| } on FormatException catch(e) { |
| print("Exception $e"); |
| setState(() { |
| _errorMessage = "Save failed"; |
| }); |
| } |
| onCreated(new Measurement(when: _when, weight: parsedWeight)); |
| navigator.pop(); |
| } |
| |
| Widget buildToolBar() { |
| return new ToolBar( |
| left: new IconButton( |
| icon: "navigation/close", |
| onPressed: navigator.pop), |
| center: new Text('New Measurement'), |
| right: [new InkWell( |
| child: new GestureDetector( |
| onTap: _handleSave, |
| child: new Text('SAVE') |
| ) |
| )] |
| ); |
| } |
| |
| void _handleWeightChanged(String weight) { |
| setState(() { |
| _weight = weight; |
| }); |
| } |
| |
| static final GlobalKey weightKey = new GlobalKey(); |
| |
| void _handleDatePressed() { |
| showDialog(navigator, (navigator) { |
| return new MeasurementDateDialog(navigator: navigator, previousDate: _when); |
| }).then((DateTime value) { |
| if (value == null) |
| return; |
| setState(() { |
| _when = value; |
| }); |
| }); |
| } |
| |
| 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 GestureDetector( |
| onTap: _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() |
| ); |
| } |
| } |