// 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() ); } }