• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * ```
8  *    http://www.apache.org/licenses/LICENSE-2.0
9  * ```
10  *
11  * Unless required by applicable law or agreed to in writing, software distributed under the License
12  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13  * or implied. See the License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 package com.android.healthconnect.testapps.toolbox.fieldviews
17 
18 import android.annotation.SuppressLint
19 import android.content.Context
20 import android.health.connect.datatypes.CyclingPedalingCadenceRecord.CyclingPedalingCadenceRecordSample
21 import android.health.connect.datatypes.ExerciseLap
22 import android.health.connect.datatypes.ExerciseSegment
23 import android.health.connect.datatypes.ExerciseSegmentType
24 import android.health.connect.datatypes.HeartRateRecord.HeartRateSample
25 import android.health.connect.datatypes.PowerRecord.PowerRecordSample
26 import android.health.connect.datatypes.SleepSessionRecord
27 import android.health.connect.datatypes.SpeedRecord.SpeedRecordSample
28 import android.health.connect.datatypes.StepsCadenceRecord.StepsCadenceRecordSample
29 import android.health.connect.datatypes.units.Length
30 import android.health.connect.datatypes.units.Power
31 import android.health.connect.datatypes.units.Velocity
32 import android.widget.LinearLayout
33 import android.widget.TextView
34 import com.android.healthconnect.testapps.toolbox.Constants.INPUT_TYPE_DOUBLE
35 import com.android.healthconnect.testapps.toolbox.Constants.INPUT_TYPE_LONG
36 import com.android.healthconnect.testapps.toolbox.R
37 import com.android.healthconnect.testapps.toolbox.utils.GeneralUtils.Companion.getStaticFieldNamesAndValues
38 import com.google.android.material.floatingactionbutton.FloatingActionButton
39 import java.lang.reflect.ParameterizedType
40 import java.lang.reflect.Type
41 
42 @SuppressLint("ViewConstructor")
43 class ListInputField(context: Context, fieldName: String, inputFieldType: ParameterizedType) :
44     InputFieldView(context) {
45 
46     data class Row(val context: Context) {
47         val startTime = DateTimePicker(context, "Start Time", true)
48         val endTime = DateTimePicker(context, "End Time")
49         lateinit var dataPointField: InputFieldView
50     }
51 
52     private var mLinearLayout: LinearLayout
53     private var mDataTypeClass: Type
54     private var mRowsData: ArrayList<Row>
55 
56     init {
57         inflate(context, R.layout.fragment_list_input_view, this)
58         findViewById<TextView>(R.id.field_name).text = fieldName
59         mLinearLayout = findViewById(R.id.list_input_linear_layout)
60         mDataTypeClass = inputFieldType.actualTypeArguments[0]
61         mRowsData = ArrayList()
62         setupAddRowButtonListener()
63     }
64 
setupAddRowButtonListenernull65     private fun setupAddRowButtonListener() {
66         val buttonView = findViewById<FloatingActionButton>(R.id.add_row)
67 
68         buttonView.setOnClickListener { addRow() }
69     }
70 
addRownull71     private fun addRow() {
72         val rowLayout = LinearLayout(context)
73         rowLayout.orientation = VERTICAL
74 
75         val row = Row(context)
76 
77         rowLayout.addView(row.startTime)
78         val dataPointField: InputFieldView =
79             when (mDataTypeClass) {
80                 SpeedRecordSample::class.java -> {
81                     EditableTextView(context, "Velocity", INPUT_TYPE_DOUBLE)
82                 }
83                 HeartRateSample::class.java -> {
84                     EditableTextView(context, "Beats per minute", INPUT_TYPE_LONG)
85                 }
86                 PowerRecordSample::class.java -> {
87                     EditableTextView(context, "Power", INPUT_TYPE_DOUBLE)
88                 }
89                 CyclingPedalingCadenceRecordSample::class.java -> {
90                     EditableTextView(context, "Revolutions Per Minute", INPUT_TYPE_DOUBLE)
91                 }
92                 SleepSessionRecord.Stage::class.java -> {
93                     rowLayout.addView(row.endTime)
94                     EnumDropDown(
95                         context,
96                         "Sleep Stage",
97                         getStaticFieldNamesAndValues(SleepSessionRecord.StageType::class))
98                 }
99                 StepsCadenceRecordSample::class.java -> {
100                     EditableTextView(context, "Steps Cadence", INPUT_TYPE_DOUBLE)
101                 }
102                 ExerciseSegment::class.java -> {
103                     rowLayout.addView(row.endTime)
104                     EnumDropDown(
105                         context,
106                         "Segment Type",
107                         getStaticFieldNamesAndValues(ExerciseSegmentType::class))
108                 }
109                 ExerciseLap::class.java -> {
110                     rowLayout.addView(row.endTime)
111                     EditableTextView(context, "Length", INPUT_TYPE_DOUBLE)
112                 }
113                 else -> {
114                     return
115                 }
116             }
117         row.dataPointField = dataPointField
118         rowLayout.addView(dataPointField)
119         mRowsData.add(row)
120         mLinearLayout.addView(rowLayout, 0)
121     }
122 
getFieldValuenull123     override fun getFieldValue(): List<Any> {
124         val samples: ArrayList<Any> = ArrayList()
125         for (row in mRowsData) {
126             val dataPoint = row.dataPointField
127             val instant = row.startTime
128             val dataPointString = dataPoint.getFieldValue().toString()
129             when (mDataTypeClass) {
130                 SpeedRecordSample::class.java -> {
131                     samples.add(
132                         SpeedRecordSample(
133                             Velocity.fromMetersPerSecond(dataPointString.toDouble()),
134                             instant.getFieldValue()))
135                 }
136                 HeartRateSample::class.java -> {
137                     samples.add(HeartRateSample(dataPointString.toLong(), instant.getFieldValue()))
138                 }
139                 PowerRecordSample::class.java -> {
140                     samples.add(
141                         PowerRecordSample(
142                             Power.fromWatts(dataPointString.toDouble()), instant.getFieldValue()))
143                 }
144                 CyclingPedalingCadenceRecordSample::class.java -> {
145                     samples.add(
146                         CyclingPedalingCadenceRecordSample(
147                             dataPointString.toDouble(), instant.getFieldValue()))
148                 }
149                 StepsCadenceRecordSample::class.java -> {
150                     samples.add(
151                         StepsCadenceRecordSample(
152                             dataPointString.toDouble(), instant.getFieldValue()))
153                 }
154                 SleepSessionRecord.Stage::class.java -> {
155                     samples.add(
156                         SleepSessionRecord.Stage(
157                             instant.getFieldValue(),
158                             row.endTime.getFieldValue(),
159                             dataPointString.toInt()))
160                 }
161                 ExerciseSegment::class.java -> {
162                     samples.add(
163                         ExerciseSegment.Builder(
164                                 instant.getFieldValue(),
165                                 row.endTime.getFieldValue(),
166                                 dataPointString.toInt())
167                             .build())
168                 }
169                 ExerciseLap::class.java -> {
170                     samples.add(
171                         ExerciseLap.Builder(instant.getFieldValue(), row.endTime.getFieldValue())
172                             .apply {
173                                 if (dataPointString.isNotEmpty()) {
174                                     setLength(Length.fromMeters(dataPointString.toDouble()))
175                                 }
176                             }
177                             .build())
178                 }
179             }
180         }
181         return samples
182     }
183 
isEmptynull184     override fun isEmpty(): Boolean {
185         return getFieldValue().isEmpty()
186     }
187 }
188