diff --git a/opensrp-sdidtk/.gitignore b/opensrp-sdidtk/.gitignore new file mode 100644 index 000000000..796b96d1c --- /dev/null +++ b/opensrp-sdidtk/.gitignore @@ -0,0 +1 @@ +/build diff --git a/opensrp-sdidtk/build.gradle b/opensrp-sdidtk/build.gradle new file mode 100644 index 000000000..ec14b0b34 --- /dev/null +++ b/opensrp-sdidtk/build.gradle @@ -0,0 +1,51 @@ +buildscript { + repositories { + jcenter() + } + dependencies { + classpath "com.android.tools.build:gradle:1.2.3" + classpath 'org.apache.commons:commons-lang3:3.3.2' + classpath 'org.robolectric:robolectric-gradle-plugin:1.1.0' + } +} +apply plugin: 'com.android.application' +dependencies { + compile fileTree(include: ['*.jar'], dir: 'libs') + compile project(':opensrp-app') +} +android { + compileSdkVersion androidCompileSdkVersion + buildToolsVersion androidBuildToolsVersion + + defaultConfig { + applicationId "org.ei.opensrp.sdidtk" + minSdkVersion 16 + targetSdkVersion 21 + versionCode 21 + versionName "21.0" + multiDexEnabled true + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + packagingOptions { + exclude 'META-INF/DEPENDENCIES.txt' + exclude 'META-INF/LICENSE.txt' + exclude 'META-INF/NOTICE.txt' + exclude 'META-INF/NOTICE' + exclude 'META-INF/LICENSE' + exclude 'META-INF/DEPENDENCIES' + exclude 'META-INF/notice.txt' + exclude 'META-INF/license.txt' + exclude 'META-INF/dependencies.txt' + exclude 'META-INF/LGPL2.1' + } + lintOptions { + disable 'MissingTranslation' + } +} + + diff --git a/opensrp-sdidtk/proguard-rules.pro b/opensrp-sdidtk/proguard-rules.pro new file mode 100644 index 000000000..beebe3b36 --- /dev/null +++ b/opensrp-sdidtk/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /home/raihan/Android/Sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/opensrp-sdidtk/src/androidTest/java/org/ei/opensrp/ddtk/ApplicationTest.java b/opensrp-sdidtk/src/androidTest/java/org/ei/opensrp/ddtk/ApplicationTest.java new file mode 100644 index 000000000..be3f76f17 --- /dev/null +++ b/opensrp-sdidtk/src/androidTest/java/org/ei/opensrp/ddtk/ApplicationTest.java @@ -0,0 +1,13 @@ +package org.ei.opensrp.ddtk; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * Testing Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } +} \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/AndroidManifest.xml b/opensrp-sdidtk/src/main/AndroidManifest.xml new file mode 100644 index 000000000..ad88c2581 --- /dev/null +++ b/opensrp-sdidtk/src/main/AndroidManifest.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + diff --git a/opensrp-sdidtk/src/main/assets/app.properties b/opensrp-sdidtk/src/main/assets/app.properties new file mode 100644 index 000000000..7c513df5d --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/app.properties @@ -0,0 +1,4 @@ +DRISHTI_BASE_URL=http://118.91.130.18:8080/opensrp-web +PORT=8080 +SHOULD_VERIFY_CERTIFICATE=false +SYNC_DOWNLOAD_BATCH_SIZE=100 \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/bindtypes.json b/opensrp-sdidtk/src/main/assets/bindtypes.json new file mode 100644 index 000000000..586629007 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/bindtypes.json @@ -0,0 +1,16 @@ +{ + "bindobjects": [ + { + "name": "ibu", + "columns": [ + + ] + }, + { + "name": "anak", + "columns": [ + + ] + } + ] +} \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/antropometri/form.xml b/opensrp-sdidtk/src/main/assets/www/form/antropometri/form.xml new file mode 100644 index 000000000..74fbca787 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/antropometri/form.xml @@ -0,0 +1,195 @@ + +
+ + +

Antropometri

+ + + + + +
+
+ + Berat/Tinggi Badan (BB/TB) + Weight/Height + +
+ + + + +
+
+
+ + + + +
+
+ + Konseling stimulasi bagi ibu: + Stimulation consultation for the mother + +
+ + +
+
+
+ +
+
+ + Apakah anak dirujuk? + Is the child referred to other facility? + +
+ + +
+
+
+ +
+
+ + Ada surat rujukan? + Referral letter + +
+ + +
+
+
+ + +
diff --git a/opensrp-sdidtk/src/main/assets/www/form/antropometri/form_definition.json b/opensrp-sdidtk/src/main/assets/www/form/antropometri/form_definition.json new file mode 100644 index 000000000..67433a54a --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/antropometri/form_definition.json @@ -0,0 +1,86 @@ +{ + "form_data_definition_version": "1", + "form": { + "bind_type": "anak", + "default_bind_path": "/model/instance/antropometri/", + "fields": [ + { + "name": "id", + "shouldLoadValue": true + }, + { + "name": "umur", + "bind": "/model/instance/antropometri/umur", + "shouldLoadValue": true + }, + { + "name": "anthropometry_date", + "bind": "/model/instance/antropometri/anthropometry_date" + }, + { + "name": "berat", + "bind": "/model/instance/antropometri/berat" + }, + { + "name": "tinggi", + "bind": "/model/instance/antropometri/tinggi" + }, + { + "name": "berat_tinggi", + "bind": "/model/instance/antropometri/berat_tinggi" + }, + { + "name": "lingkar_kepala", + "bind": "/model/instance/antropometri/lingkar_kepala" + }, + { + "name": "lkau", + "bind": "/model/instance/antropometri/lkau" + }, + { + "name": "kesimpulan", + "bind": "/model/instance/antropometri/kesimpulan" + }, + { + "name": "tindakan_intervensi", + "bind": "/model/instance/antropometri/tindakan_intervensi" + }, + { + "name": "konseling_stimulasi", + "bind": "/model/instance/antropometri/konseling_stimulasi" + }, + { + "name": "tindakan_lain", + "bind": "/model/instance/antropometri/tindakan_lain" + }, + { + "name": "rujukan", + "bind": "/model/instance/antropometri/rujukan" + }, + { + "name": "dirujuk_ke", + "bind": "/model/instance/antropometri/dirujuk_ke" + }, + { + "name": "surat_rujukan", + "bind": "/model/instance/antropometri/surat_rujukan" + }, + { + "name": "isOutOfArea", + "value": "false" + }, + { + "name": "isClosed", + "value": "false" + }, + { + "name": "reg_date", + "bind": "/model/instance/antropometri/today" + }, + { + "name": "registrationDate", + "bind": "/model/instance/antropometri/reg_date" + } + ] + } +} \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/antropometri/model.xml b/opensrp-sdidtk/src/main/assets/www/form/antropometri/model.xml new file mode 100644 index 000000000..9f3dc6d2a --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/antropometri/model.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/deteksi_dini_autis/form.xml b/opensrp-sdidtk/src/main/assets/www/form/deteksi_dini_autis/form.xml new file mode 100644 index 000000000..76cd33198 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/deteksi_dini_autis/form.xml @@ -0,0 +1,468 @@ + +
+ + +

Ceklis Deteksi Dini Autis Untuk Anak Umur 18-36 Bulan

+ + + + +
+
+ + A1. Apakah anak senang diayun-ayun atau diguncang-guncang naik turun (bounched) di paha Anda? + A1. Does your child enjoy being swung, bounced on your knee, etc? + +
+ + +
+
+
+
+
+ + A2. Apakah anak tertarik (memperhatikan) anak lain? + A2. Does your child take an interest in other children? + +
+ + +
+
+
+
+
+ + A3. Apakah anak suka memanjat-manjat, seperti memanjat tangga? + A3. Does your child like climbing on things, such as stairs? + +
+ + +
+
+
+
+
+ + A4. Apakah anak suka bermain "cilukba" atau "petak umpet"? + A4. Does your child enjoy playing peek-a-boo/hide-and-seek? + +
+ + +
+
+
+
+
+ + A5. Apakah anak pernah bermain-main seolah-olah membuat secangkir teh menggunakan mainan berbentuk cangkir dan teko, atau permainan lain? + A5. Does your child ever PRETEND, for example, to make a cup of tea using a toy and teapot, or pretend other things? + +
+ + +
+
+
+
+
+ + A6. Apakah anak pernah menunjuk atau meminta sesuatu dengan menunjukkan jari? + A6. Does your child ever use his/her index finger to point, to ASK for something? + +
+ + +
+
+
+
+
+ + A7. Apakah anak pernah menggunakan jari untuk menunjuk ke sesuatu agar Anda melihat ke sana? + A7. Does your child ever use his/her index finger to point, to indicate INTEREST in something? + +
+ + +
+
+
+
+
+ + A8. Apakah anak dapat bermain dengan mainan yang kecil (mobil atau kubus)? + A8. Can your child play properly with small toys (e.g. cars or bricks) without just mouthing, fiddling, or dropping them? + +
+ + +
+
+
+
+
+ + A9. Apakah anak pernah memberikan suatu benda untuk menunjukkan sesuatu? + A9. Does your child ever bring objects over to you (parent) to SHOW you something? + +
+ + +
+
+
+ +
+
+ + B1. Selama pemeriksaan apakah anak menatap (kontak mata) dengan pemeriksa? + B1. During the appointment, has the child made eye contact with you? + +
+ + +
+
+
+
+
+ + B2. Usahakan menarik perhatian anak, kemudian pemeriksa menunjuk sesuatu di ruangan pemeriksaan sambil mengatakan: "Lihat itu ada bola (atau mainan lain)!". Perhatikan mata anak, apakah ia melihat ke benda yang ditunjuk, bukan melihat tangan pemeriksa? + B2. Get child's attention, then point across the room at an interesting object and say 'Oh look! There's a (name of toy)!' Watch child's face. Does the child look across to see what you are pointing at? Ensure the child has not simply looked at your hand, but has actually looked at the object you are pointing at. + +
+ + +
+
+
+
+
+ + B3. Usahakan menarik perhatian anak, berikan mainan gelas/cangkir dan teko. Katakan pada anak: "Buatkan secangkir susu buat mama"! + B3. Get child's attention, then give child a miniature toy cup and teapot and say 'Can you make me a cup of tea?' Does the child pretend to pour out tea, drink it, etc.? + +
+ + +
+
+
+
+
+ + B4. Tanyakan pada anak: "Tunjukkan mana gelas!" (gelas dapat diganti dengan nama benda lain yang dikenal anak dan ada di sekitar kita). Apakah anak menunjukkan benda tersebut dengan jarinya? Atau sambil menatap wajah Anda ketika menunjuk ke suatu benda? + B4. Ask the child 'Where's the light?', or "Show me the light'. Does the child POINT with his/her index finger at the light? Repeat this with some other unreachable object, if child does not understand the word light. The child must have looked up at your face around the time of pointing. + +
+ + +
+
+
+
+
+ + B5. Apakah anak dapat menumpuk beberapa kubus/balok menjadi suatu menara? + B5. Can the child build a tower of bricks? + +
+ + +
+
+
+ + + + + + + + +
+
+ + Konseling stimulasi bagi ibu: + Stimulation consultation for the mother + +
+ + +
+
+
+ +
+
+ + Apakah anak dirujuk? + Is the child referred to other facility? + +
+ + +
+
+
+ +
+
+ + Ada surat rujukan? + Referral letter + +
+ + +
+
+
+ + +
diff --git a/opensrp-sdidtk/src/main/assets/www/form/deteksi_dini_autis/form_definition.json b/opensrp-sdidtk/src/main/assets/www/form/deteksi_dini_autis/form_definition.json new file mode 100644 index 000000000..e331cacce --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/deteksi_dini_autis/form_definition.json @@ -0,0 +1,134 @@ +{ + "form_data_definition_version": "1", + "form": { + "bind_type": "anak", + "default_bind_path": "/model/instance/deteksi_dini_autis/", + "fields": [ + { + "name": "id", + "shouldLoadValue": true + }, + { + "name": "umur", + "bind": "/model/instance/deteksi_dini_autis/umur", + "shouldLoadValue": true + }, + { + "name": "autis_test_date", + "bind": "/model/instance/deteksi_dini_autis/autis_test_date" + }, + { + "name": "chat_anamnesis", + "bind": "/model/instance/deteksi_dini_autis/chat_anamnesis" + }, + { + "name": "chat_diayun", + "bind": "/model/instance/deteksi_dini_autis/chat_diayun" + }, + { + "name": "chat_tertarik", + "bind": "/model/instance/deteksi_dini_autis/chat_tertarik" + }, + { + "name": "chat_memanjat", + "bind": "/model/instance/deteksi_dini_autis/chat_memanjat" + }, + { + "name": "chat_cilukba", + "bind": "/model/instance/deteksi_dini_autis/chat_cilukba" + }, + { + "name": "chat_roleplay", + "bind": "/model/instance/deteksi_dini_autis/chat_roleplay" + }, + { + "name": "chat_meminta", + "bind": "/model/instance/deteksi_dini_autis/chat_meminta" + }, + { + "name": "chat_menunjuk", + "bind": "/model/instance/deteksi_dini_autis/chat_menunjuk" + }, + { + "name": "chat_mainan_kecil", + "bind": "/model/instance/deteksi_dini_autis/chat_mainan_kecil" + }, + { + "name": "chat_memberikan_benda", + "bind": "/model/instance/deteksi_dini_autis/chat_memberikan_benda" + }, + { + "name": "chat_pengamatan", + "bind": "/model/instance/deteksi_dini_autis/chat_pengamatan" + }, + { + "name": "chat_kontak_mata", + "bind": "/model/instance/deteksi_dini_autis/chat_kontak_mata" + }, + { + "name": "chat_melihat_benda", + "bind": "/model/instance/deteksi_dini_autis/chat_melihat_benda" + }, + { + "name": "chat_berpura_pura", + "bind": "/model/instance/deteksi_dini_autis/chat_berpura_pura" + }, + { + "name": "chat_menunjuk_dg_jari", + "bind": "/model/instance/deteksi_dini_autis/chat_menunjuk_dg_jari" + }, + { + "name": "chat_menumpuk_kubus", + "bind": "/model/instance/deteksi_dini_autis/chat_menumpuk_kubus" + }, + { + "name": "autis", + "bind": "/model/instance/deteksi_dini_autis/autis" + }, + { + "name": "kesimpulan", + "bind": "/model/instance/deteksi_dini_autis/kesimpulan" + }, + { + "name": "tindakan_intervensi", + "bind": "/model/instance/deteksi_dini_autis/tindakan_intervensi" + }, + { + "name": "konseling_stimulasi", + "bind": "/model/instance/deteksi_dini_autis/konseling_stimulasi" + }, + { + "name": "tindakan_lain", + "bind": "/model/instance/deteksi_dini_autis/tindakan_lain" + }, + { + "name": "rujukan", + "bind": "/model/instance/deteksi_dini_autis/rujukan" + }, + { + "name": "dirujuk_ke", + "bind": "/model/instance/deteksi_dini_autis/dirujuk_ke" + }, + { + "name": "surat_rujukan", + "bind": "/model/instance/deteksi_dini_autis/surat_rujukan" + }, + { + "name": "isOutOfArea", + "value": "false" + }, + { + "name": "isClosed", + "value": "false" + }, + { + "name": "reg_date", + "bind": "/model/instance/deteksi_dini_autis/today" + }, + { + "name": "registrationDate", + "bind": "/model/instance/deteksi_dini_autis/reg_date" + } + ] + } +} \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/deteksi_dini_autis/model.xml b/opensrp-sdidtk/src/main/assets/www/form/deteksi_dini_autis/model.xml new file mode 100644 index 000000000..ba0f0d179 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/deteksi_dini_autis/model.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/entity_relationship.json b/opensrp-sdidtk/src/main/assets/www/form/entity_relationship.json new file mode 100644 index 000000000..72ba2242c --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/entity_relationship.json @@ -0,0 +1,10 @@ +[ + { + "parent":"ibu", + "child":"anak", + "field":"anak_anak", + "kind":"one_to_many", + "from":"ibu.id", + "to":"anak.ibuCaseId" + } +] \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/formulir_ddtk/form.xml b/opensrp-sdidtk/src/main/assets/www/form/formulir_ddtk/form.xml new file mode 100644 index 000000000..dacdf7e57 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/formulir_ddtk/form.xml @@ -0,0 +1,140 @@ + +
+ + +

Formulir Deteksi Dini Tumbuh Kembang Anak

+ + + + + + +
+
+ + Jenis Kelamin + Gender + * + +
+ + +
+
+
+ + + + + + +
diff --git a/opensrp-sdidtk/src/main/assets/www/form/formulir_ddtk/form_definition.json b/opensrp-sdidtk/src/main/assets/www/form/formulir_ddtk/form_definition.json new file mode 100644 index 000000000..891962a31 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/formulir_ddtk/form_definition.json @@ -0,0 +1,111 @@ +{ + "form_data_definition_version": "1", + "form": { + "bind_type": "anak", + "default_bind_path": "/model/instance/formulir_ddtk/", + "fields": [ + { + "name": "id", + "shouldLoadValue": true + }, + { + "name": "Village", + "bind": "/model/instance/formulir_ddtk/existing_Village", + "shouldLoadValue": true + }, + { + "name": "Province", + "bind": "/model/instance/formulir_ddtk/existing_Province", + "shouldLoadValue": true + }, + { + "name": "Sub-district", + "bind": "/model/instance/formulir_ddtk/existing_Sub-district", + "shouldLoadValue": true + }, + { + "name": "District", + "bind": "/model/instance/formulir_ddtk/existing_District", + "shouldLoadValue": true + }, + { + "name": "Sub-village", + "bind": "/model/instance/formulir_ddtk/existing_Sub-village", + "shouldLoadValue": true + }, + { + "name": "dusun", + "bind": "/model/instance/formulir_ddtk/existing_dusun", + "shouldLoadValue": true + }, + { + "name": "provinsi", + "bind": "/model/instance/formulir_ddtk/existing_provinsi", + "shouldLoadValue": true + }, + { + "name": "kabupaten", + "bind": "/model/instance/formulir_ddtk/existing_kabupaten", + "shouldLoadValue": true + }, + { + "name": "kecamatan", + "bind": "/model/instance/formulir_ddtk/existing_kecamatan", + "shouldLoadValue": true + }, + { + "name": "desa", + "bind": "/model/instance/formulir_ddtk/existing_desa", + "shouldLoadValue": true + }, + { + "name": "reg_date", + "bind": "/model/instance/formulir_ddtk/reg_date" + }, + { + "name": "nama_anak", + "bind": "/model/instance/formulir_ddtk/nama_anak" + }, + + { + "name": "jenis_kelamin", + "bind": "/model/instance/formulir_ddtk/jenis_kelamin" + }, + + + { + "name": "nama_ayah", + "bind": "/model/instance/formulir_ddtk/nama_ayah" + }, + + { + "name": "nama_ibu", + "bind": "/model/instance/formulir_ddtk/nama_ibu" + }, + { + "name": "tanggal_lahir", + "bind": "/model/instance/formulir_ddtk/tanggal_lahir" + }, + { + "name": "umur", + "bind": "/model/instance/formulir_ddtk/umur" + }, + { + "name": "isOutOfArea", + "value": "false" + }, + { + "name": "isClosed", + "value": "false" + }, + { + "name": "reg_date", + "bind": "/model/instance/formulir_ddtk/today" + }, + { + "name": "registrationDate", + "bind": "/model/instance/formulir_ddtk/reg_date" + } + ] + } +} diff --git a/opensrp-sdidtk/src/main/assets/www/form/formulir_ddtk/model.xml b/opensrp-sdidtk/src/main/assets/www/form/formulir_ddtk/model.xml new file mode 100644 index 000000000..1c8b6be1e --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/formulir_ddtk/model.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/gangguan_konsentrasi_hiperaktivitas/form.xml b/opensrp-sdidtk/src/main/assets/www/form/gangguan_konsentrasi_hiperaktivitas/form.xml new file mode 100644 index 000000000..e99d81269 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/gangguan_konsentrasi_hiperaktivitas/form.xml @@ -0,0 +1,217 @@ + +
+ + +

Gangguan Pemusatan Perhatian dan Hiperaktivitas (GPPH)

+ + + + + + + + + + + + + + + + + + + + +
+
+ + Konseling stimulasi bagi ibu: + Stimulation consultation for the mother + +
+ + +
+
+
+ +
+
+ + Apakah anak dirujuk? + Is the child referred to other facility? + +
+ + +
+
+
+ +
+
+ + Ada surat rujukan? + Referral letter + +
+ + +
+
+
+ + +
diff --git a/opensrp-sdidtk/src/main/assets/www/form/gangguan_konsentrasi_hiperaktivitas/form_definition.json b/opensrp-sdidtk/src/main/assets/www/form/gangguan_konsentrasi_hiperaktivitas/form_definition.json new file mode 100644 index 000000000..074920b9d --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/gangguan_konsentrasi_hiperaktivitas/form_definition.json @@ -0,0 +1,114 @@ +{ + "form_data_definition_version": "1", + "form": { + "bind_type": "anak", + "default_bind_path": "/model/instance/gangguan_konsentrasi_hiperaktivitas/", + "fields": [ + { + "name": "id", + "shouldLoadValue": true + }, + { + "name": "umur", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/umur", + "shouldLoadValue": true + }, + { + "name": "gpph_test_date", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/gpph_test_date" + }, + { + "name": "gpph_hiperaktif", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/gpph_hiperaktif" + }, + { + "name": "gpph_impulsif", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/gpph_impulsif" + }, + { + "name": "gpph_mengganggu", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/gpph_mengganggu" + }, + { + "name": "gpph_konsentrasi", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/gpph_konsentrasi" + }, + { + "name": "gpph_bergerak_gerak", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/gpph_bergerak_gerak" + }, + { + "name": "gpph_perhatian", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/gpph_perhatian" + }, + { + "name": "gpph_frustasi", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/gpph_frustasi" + }, + { + "name": "gpph_menangis", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/gpph_menangis" + }, + { + "name": "gpph_mood", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/gpph_mood" + }, + { + "name": "gpph_tantrum", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/gpph_tantrum" + }, + { + "name": "gpph_nilai", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/gpph_nilai" + }, + { + "name": "gpph", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/gpph" + }, + { + "name": "kesimpulan", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/kesimpulan" + }, + { + "name": "tindakan_intervensi", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/tindakan_intervensi" + }, + { + "name": "konseling_stimulasi", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/konseling_stimulasi" + }, + { + "name": "tindakan_lain", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/tindakan_lain" + }, + { + "name": "rujukan", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/rujukan" + }, + { + "name": "dirujuk_ke", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/dirujuk_ke" + }, + { + "name": "surat_rujukan", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/surat_rujukan" + }, + { + "name": "isOutOfArea", + "value": "false" + }, + { + "name": "isClosed", + "value": "false" + }, + { + "name": "reg_date", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/today" + }, + { + "name": "registrationDate", + "bind": "/model/instance/gangguan_konsentrasi_hiperaktivitas/reg_date" + } + ] + } +} \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/gangguan_konsentrasi_hiperaktivitas/model.xml b/opensrp-sdidtk/src/main/assets/www/form/gangguan_konsentrasi_hiperaktivitas/model.xml new file mode 100644 index 000000000..97470d3df --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/gangguan_konsentrasi_hiperaktivitas/model.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_2thn/form.xml b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_2thn/form.xml new file mode 100644 index 000000000..c9276c07c --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_2thn/form.xml @@ -0,0 +1,1200 @@ + +
+ + +

KPSP Balita 2 Tahun

+ + + + + + +
+
+ + KPSP Balita 2 Tahun + Pre-Screening Questionnaire of Child Development for 2 Year Toddler + +
+ + + + +
+
+
+
+
+ + 1. Tanpa bantuan, apakah anak dapat mempertemukan dua kubus kecil yang ia pegang? Kerincingan bertangkai dan tutup panci tidak ikut dinilai + 1. Is the baby able to stack two small blocks which he/she holds? A handgripped rattle and a pot lip are not assessed + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 2. Apakah anak dapat berjalan sendiri atau jalan dengan berpegangan? + 2. Is the baby able to walk without help or while holding on something/someone? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 3. Tanpa bantuan, apakah anak dapat bertepuk tangan atau melambai-lambai? Jawab TIDAK bila ia membutuhkan bantuan + 3. Is the baby able to clap or wave without help? Select NO if he/she needs a help + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 4. Apakah anak dapat mengatakan "papa", ketika ia memanggil/melihat ayahnya, atau mengatakan "mama" jika memanggil/melihat ibunya? Jawab YA bila anak mengatakan salah satu di antaranya + 4. Is the baby able to say "father", when calling/seeing his/her father, or to say "mother" when calling/seeing his/her mother? Select YES if the baby says either one + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 5. Dapatkah anak berdiri sendiri tanpa berpegangan selama kira-kira 5 detik? + 5. Is the baby able to stand alone without holding onto something/someone for around 5 seconds? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 6. Dapatkah anak berdiri sendiri tanpa berpegangan selama 30 detik atau lebih? + 6. Is the baby able to stand alone without holding onto something/someone for 30 seconds or more? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 7. Tanpa berpegangan atau menyentuh lantai, apakah anak dapat membungkuk untuk memungut mainan di lantai dan kemudian berdiri kembali? + 7. Is the baby able to bend over to pick up a toy on the floor and then stand back without holding onto something/someone or touching the floor? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 8. Apakah anak dapat menunjukkan apa yang diinginkannya tanpa menangis atau merengek? Jawab YA bila ia menunjuk, menarik atau mengeluarkan suara yang menyenangkan + 8. Is the baby able to show what he/she wants without crying or whining? Select YES if he/she points at or pulls the object or making an exciting sound + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 9. Apakah anak dapat berjalan di sepanjang ruangan tanpa jatuh atau terhuyung-huyung? + 9. Is the baby able to walk around the room without falling or stumbling? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + + 10. Apakah anak dapat mengambil benda kecil seperti kacang, kismis, atau potongan biskuit dengan menggunakan ibu jari dan jari telunjuk seperti pada gambar? + image + + 10. Is the baby able to pick up a small object such as a nut, a raisin, or a piece of biscuit with a thumb and an index finger as seen in the picture? + image + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 1. Tanpa bantuan, apakah anak dapat bertepuk tangan atau melambai-lambai? Jawab TIDAK bila ia membutuhkan bantuan + 1. Is the baby able to clap or wave without help? Select NO if he/she needs a help + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 2. Apakah anak dapat mengatakan "papa", ketika ia memanggil/melihat ayahnya, atau mengatakan "mama" jika memanggil/melihat ibunya? Jawab YA bila anak mengatakan salah satu di antaranya + 2. Is the baby able to say "father", when calling/seeing his/her father, or to say "mother" when calling/seeing his/her mother? Select YES if the baby says either one + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 3. Dapatkah anak berdiri sendiri tanpa berpegangan selama kira-kira 5 detik? + 3. Is the baby able to stand alone without holding onto something/someone for around 5 seconds? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 4. Dapatkah anak berdiri sendiri tanpa berpegangan selama 30 detik atau lebih? + 4. Is the baby able to stand alone without holding onto something/someone for 30 seconds or more? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 5. Tanpa berpegangan atau menyentuh lantai, apakah anak dapat membungkuk untuk memungut mainan di lantai dan kemudian berdiri kembali? + 5. Is the baby able to bend over to pick up a toy on the floor and then stand back without holding onto something/someone or touching the floor? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 6. Apakah anak dapat menunjukkan apa yang diinginkannya tanpa menangis atau merengek? Jawab YA bila ia menunjuk, menarik atau mengeluarkan suara yang menyenangkan + 6. Is the baby able to show what he/she wants without crying or whining? Select YES if he/she points at or pulls the object or making an exciting sound + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 7. Apakah anak dapat berjalan di sepanjang ruangan tanpa jatuh atau terhuyung-huyung? + 7. Is the baby able to walk around the room without falling or stumbling? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + + 8. Apakah anak dapat mengambil benda kecil seperti kacang, kismis, atau potongan biskuit dengan menggunakan ibu jari dan jari telunjuk seperti pada gambar? + image + + 8. Is the baby able to pick up a small object such as a nut, a raisin, or a piece of biscuit with a thumb and an index finger as seen in the picture? + image + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 9. Jika Anda menggelindingkan bola ke anak, apakah ia menggelindingkan/melemparkan kembali bola pada Anda? + 9. If you roll a ball to the child, does he/she roll/throw it back to you? + * + Gerak halus; Sosialisasi dan kemandirian + Fine motor; Sosialisasi dan kemandirian + +
+ + +
+
+
+
+
+ + 10. Apakah anak dapat memegang sendiri cangkir/gelas dan minum dari tempat tersebut tanpa tumpah? + 10. Is the child able to hold a mug/glass without help and drink from it without spilling the water? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 1. Tanpa berpegangan atau menyentuh lantai, apakah anak dapat membungkuk untuk memungut mainan di lantai dan kemudian berdiri kembali? + 1. Is the baby able to bend over to pick up a toy on the floor and then stand back without holding onto something/someone or touching the floor? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 2. Apakah anak dapat menunjukkan apa yang diinginkannya tanpa menangis atau merengek? Jawab YA bila ia menunjuk, menarik atau mengeluarkan suara yang menyenangkan + 2. Is the baby able to show what he/she wants without crying or whining? Select YES if he/she points at or pulls the object or making an exciting sound + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 3. Apakah anak dapat berjalan di sepanjang ruangan tanpa jatuh atau terhuyung-huyung? + 3. Is the baby able to walk around the room without falling or stumbling? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + + 4. Apakah anak dapat mengambil benda kecil seperti kacang, kismis, atau potongan biskuit dengan menggunakan ibu jari dan jari telunjuk seperti pada gambar? + image + + 4. Is the baby able to pick up a small object such as a nut, a raisin, or a piece of biscuit with a thumb and an index finger as seen in the picture? + image + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 5. Jika Anda menggelindingkan bola ke anak, apakah ia menggelindingkan/melemparkan kembali bola pada Anda? + 5. If you roll a ball to the child, does he/she roll/throw it back to you? + * + Gerak halus; Sosialisasi dan kemandirian + Fine motor; Sosialisasi dan kemandirian + +
+ + +
+
+
+
+
+ + 6. Apakah anak dapat memegang sendiri cangkir/gelas dan minum dari tempat tersebut tanpa tumpah? + 6. Is the child able to hold a mug/glass without help and drink from it without spilling the water? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 7. Jika Anda sedang melakukan pekerjaan rumah tangga, apakah anak meniru apa yang Anda lakukan? + 7. When you were doing a housework, did the child imitate what were you doing? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 8. Apakah Anda dapat meletakkan satu kubus di atas kubus yang lain tanpa menjatuhkan kubus itu? Kubus yang digunakan ukuran 2.5-5.0 cm + 8. Is the child able to put one block over another block without dropping it? Use the 2.5-5.0 cm sized blocks + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 9. Apakah anak dapat mengucapkan paling sedikit 3 kata yang mempunyai arti selain "papa" dan "mama"? + 9. Is the child able to say at least 3 words that have meaning other than "father" and "mother"? + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 10. Apakah anak dapat berjalan mundur 5 langkah atau lebih tanpa kehilangan keseimbangan? (Anda mungkin dapat melihatnya ketika anak menarik mainannya) + 10. Is the child able to walk backward 5 steps or more without losing balance? (You may be able to see it when the child pulling his/her toys) + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 1. Jika Anda sedang melakukan pekerjaan rumah tangga, apakah anak meniru apa yang Anda lakukan? + 1. When you were doing a housework, did the child imitate what were you doing? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 2. Apakah Anda dapat meletakkan satu kubus di atas kubus yang lain tanpa menjatuhkan kubus itu? Kubus yang digunakan ukuran 2.5-5.0 cm + 2. Is the child able to put one block over another block without dropping it? Use the 2.5-5.0 cm sized blocks + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 3. Apakah anak dapat mengucapkan paling sedikit 3 kata yang mempunyai arti selain "papa" dan "mama"? + 3. Is the child able to say at least 3 words that have meaning other than "father" and "mother"? + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 4. Apakah anak dapat berjalan mundur 5 langkah atau lebih tanpa kehilangan keseimbangan? (Anda mungkin dapat melihatnya ketika anak menarik mainannya) + 4. Is the child able to walk backward 5 steps or more without losing balance? (You may be able to see it when the child pulling his/her toys) + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 5. Dapatkah anak melepas pakaiannya seperti: baju, rok, atau celananya? (topi dan kaos kaki tidak ikut dinilai) + 5. Is the child able to undress him/herself, either clothes, skirt or pant? (hat and sock are not assessed) + * + Gerak halus; Sosialisasi dan kemandirian + Fine motor; Socialization and independency + +
+ + +
+
+
+
+
+ + 6. Dapatkah anak berjalan naik tangga sendiri? Jawab YA bila ia naik tangga dengan posisi tegak atau berpegangan pada dinding atau pegangan tangga. Jawab TIDAK jika ia naik tangga dengan merangkak atau Anda tidak membolehkan anak naik tangga atau anak harus berpegangan pada seseorang + 6. Is the child able to walk upstairs? Select YES if he/she walks upstairs erectly or holds on to the wall or the banister. Select NO if he/she crawls upstairs or you don't allow him/her to walk upstairs or the child needs to hold onto someone + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 7. Tanpa bimbingan, petunjuk atau bantuan Anda, dapatkah anak menunjuk dengan benar paling sedikit satu bagian badannya (rambut, mata, hidung, mulut, atau bagian badan yang lain)? + 7. Is the child able to point to at least one part of his/her body correctly (hair, eyes, nose, mouth, or other parts) without an aid, a hint, or an assistance. + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 8. Dapatkah anak makan nasi sendiri tanpa banyak tumpah? + 8. Is the child able to eat rice without spilling it too much? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 9. Dapatkah anak membantu memungut mainannya sendiri atau membantu mengangkat piring jika diminta? + 9. Is the child able to help picking up the toys or lifting the plates when he/she is asked to? + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 10. Dapatkah anak menendang bola kecil (sebesar bola tenis) ke depan tanpa berpegangan pada apapun? Mendorong tidak ikut dinilai + 10. Is the child able to kick forward a small ball (such as tennis ball) without holding onto something? Pushing is not assessed + * + Gerak kasar + Gross motor + +
+ + +
+
+
+ + + + + + +
+
+ + Konseling stimulasi bagi ibu: + Stimulation consultation for the mother + +
+ + +
+
+
+ + + +
+
+ + Apakah anak dirujuk? + Is the child referred to other facility? + +
+ + +
+
+
+ +
+
+ + Ada surat rujukan? + Referral letter + +
+ + +
+
+
+ + +
diff --git a/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_2thn/form_definition.json b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_2thn/form_definition.json new file mode 100644 index 000000000..7a1119650 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_2thn/form_definition.json @@ -0,0 +1,254 @@ +{ + "form_data_definition_version": "1", + "form": { + "bind_type": "anak", + "default_bind_path": "/model/instance/kpsp_balita_2thn/", + "fields": [ + { + "name": "id", + "shouldLoadValue": true + }, + { + "name": "umur", + "bind": "/model/instance/kpsp_balita_2thn/umur", + "shouldLoadValue": true + }, + { + "name": "kpsp_test_date2", + "bind": "/model/instance/kpsp_balita_2thn/kpsp_test_date2" + }, + { + "name": "anamnesis", + "bind": "/model/instance/kpsp_balita_2thn/anamnesis" + }, + { + "name": "keluhan", + "bind": "/model/instance/kpsp_balita_2thn/keluhan" + }, + { + "name": "masalah_tumbang", + "bind": "/model/instance/kpsp_balita_2thn/masalah_tumbang" + }, + { + "name": "kpsp_2thn", + "bind": "/model/instance/kpsp_balita_2thn/kpsp_2thn" + }, + { + "name": "_15bln_menyusun_benda", + "bind": "/model/instance/kpsp_balita_2thn/_15bln_menyusun_benda" + }, + { + "name": "_15bln_berjalan_sendiri", + "bind": "/model/instance/kpsp_balita_2thn/_15bln_berjalan_sendiri" + }, + { + "name": "_15bln_bertepuk_tangan", + "bind": "/model/instance/kpsp_balita_2thn/_15bln_bertepuk_tangan" + }, + { + "name": "_15bln_memanggil_ayahibu", + "bind": "/model/instance/kpsp_balita_2thn/_15bln_memanggil_ayahibu" + }, + { + "name": "_15bln_berdiri_sendiri_5detik", + "bind": "/model/instance/kpsp_balita_2thn/_15bln_berdiri_sendiri_5detik" + }, + { + "name": "_15bln_berdiri_sendiri_30detik", + "bind": "/model/instance/kpsp_balita_2thn/_15bln_berdiri_sendiri_30detik" + }, + { + "name": "_15bln_membungkuk_memungut_mainan", + "bind": "/model/instance/kpsp_balita_2thn/_15bln_membungkuk_memungut_mainan" + }, + { + "name": "_15bln_menunjukkan_keinginan", + "bind": "/model/instance/kpsp_balita_2thn/_15bln_menunjukkan_keinginan" + }, + { + "name": "_15bln_berjalan_tanpa_jatuh", + "bind": "/model/instance/kpsp_balita_2thn/_15bln_berjalan_tanpa_jatuh" + }, + { + "name": "_15bln_mengambil_benda_kecil", + "bind": "/model/instance/kpsp_balita_2thn/_15bln_mengambil_benda_kecil" + }, + { + "name": "_18bln_bertepuk_tangan", + "bind": "/model/instance/kpsp_balita_2thn/_18bln_bertepuk_tangan" + }, + { + "name": "_18bln_memanggil_ayahibu", + "bind": "/model/instance/kpsp_balita_2thn/_18bln_memanggil_ayahibu" + }, + { + "name": "_18bln_berdiri_sendiri_5detik", + "bind": "/model/instance/kpsp_balita_2thn/_18bln_berdiri_sendiri_5detik" + }, + { + "name": "_18bln_berdiri_sendiri_30detik", + "bind": "/model/instance/kpsp_balita_2thn/_18bln_berdiri_sendiri_30detik" + }, + { + "name": "_18bln_membungkuk_memungut_mainan", + "bind": "/model/instance/kpsp_balita_2thn/_18bln_membungkuk_memungut_mainan" + }, + { + "name": "_18bln_menunjukkan_keinginan", + "bind": "/model/instance/kpsp_balita_2thn/_18bln_menunjukkan_keinginan" + }, + { + "name": "_18bln_berjalan_tanpa_jatuh", + "bind": "/model/instance/kpsp_balita_2thn/_18bln_berjalan_tanpa_jatuh" + }, + { + "name": "_18bln_mengambil_benda_kecil", + "bind": "/model/instance/kpsp_balita_2thn/_18bln_mengambil_benda_kecil" + }, + { + "name": "_18bln_menggelindingkan_bola", + "bind": "/model/instance/kpsp_balita_2thn/_18bln_menggelindingkan_bola" + }, + { + "name": "_18bln_minum_sendiri", + "bind": "/model/instance/kpsp_balita_2thn/_18bln_minum_sendiri" + }, + { + "name": "_21bln_membungkuk_memungut_mainan", + "bind": "/model/instance/kpsp_balita_2thn/_21bln_membungkuk_memungut_mainan" + }, + { + "name": "_21bln_menunjukkan_keinginan", + "bind": "/model/instance/kpsp_balita_2thn/_21bln_menunjukkan_keinginan" + }, + { + "name": "_21bln_berjalan_tanpa_jatuh", + "bind": "/model/instance/kpsp_balita_2thn/_21bln_berjalan_tanpa_jatuh" + }, + { + "name": "_21bln_mengambil_benda_kecil", + "bind": "/model/instance/kpsp_balita_2thn/_21bln_mengambil_benda_kecil" + }, + { + "name": "_21bln_menggelindingkan_bola", + "bind": "/model/instance/kpsp_balita_2thn/_21bln_menggelindingkan_bola" + }, + { + "name": "_21bln_minum_sendiri", + "bind": "/model/instance/kpsp_balita_2thn/_21bln_minum_sendiri" + }, + { + "name": "_21bln_meniru_pekerjaan", + "bind": "/model/instance/kpsp_balita_2thn/_21bln_meniru_pekerjaan" + }, + { + "name": "_21bln_menyusun_kubus", + "bind": "/model/instance/kpsp_balita_2thn/_21bln_menyusun_kubus" + }, + { + "name": "_21bln_mengucapkan_kata", + "bind": "/model/instance/kpsp_balita_2thn/_21bln_mengucapkan_kata" + }, + { + "name": "_21bln_berjalan_mundur", + "bind": "/model/instance/kpsp_balita_2thn/_21bln_berjalan_mundur" + }, + { + "name": "_24bln_meniru_pekerjaan", + "bind": "/model/instance/kpsp_balita_2thn/_24bln_meniru_pekerjaan" + }, + { + "name": "_24bln_menyusun_kubus", + "bind": "/model/instance/kpsp_balita_2thn/_24bln_menyusun_kubus" + }, + { + "name": "_24bln_mengucapkan_kata", + "bind": "/model/instance/kpsp_balita_2thn/_24bln_mengucapkan_kata" + }, + { + "name": "_24bln_berjalan_mundur", + "bind": "/model/instance/kpsp_balita_2thn/_24bln_berjalan_mundur" + }, + { + "name": "_24bln_melepas_pakaian", + "bind": "/model/instance/kpsp_balita_2thn/_24bln_melepas_pakaian" + }, + { + "name": "_24bln_naik_tangga", + "bind": "/model/instance/kpsp_balita_2thn/_24bln_naik_tangga" + }, + { + "name": "_24bln_menunjuk_bagian_badan", + "bind": "/model/instance/kpsp_balita_2thn/_24bln_menunjuk_bagian_badan" + }, + { + "name": "_24bln_makan_nasi_sendiri", + "bind": "/model/instance/kpsp_balita_2thn/_24bln_makan_nasi_sendiri" + }, + { + "name": "_24bln_membantu", + "bind": "/model/instance/kpsp_balita_2thn/_24bln_membantu" + }, + { + "name": "_24bln_mendendang_bola", + "bind": "/model/instance/kpsp_balita_2thn/_24bln_mendendang_bola" + }, + { + "name": "status_kembang2", + "bind": "/model/instance/kpsp_balita_2thn/status_kembang2" + }, + { + "name": "status_meragukan", + "bind": "/model/instance/kpsp_balita_2thn/status_meragukan" + }, + { + "name": "status_penyimpangan", + "bind": "/model/instance/kpsp_balita_2thn/status_penyimpangan" + }, + { + "name": "kesimpulan", + "bind": "/model/instance/kpsp_balita_2thn/kesimpulan" + }, + { + "name": "tindakan_intervensi", + "bind": "/model/instance/kpsp_balita_2thn/tindakan_intervensi" + }, + { + "name": "konseling_stimulasi", + "bind": "/model/instance/kpsp_balita_2thn/konseling_stimulasi" + }, + { + "name": "tindakan_lain", + "bind": "/model/instance/kpsp_balita_2thn/tindakan_lain" + }, + { + "name": "rujukan", + "bind": "/model/instance/kpsp_balita_2thn/rujukan" + }, + { + "name": "dirujuk_ke", + "bind": "/model/instance/kpsp_balita_2thn/dirujuk_ke" + }, + { + "name": "surat_rujukan", + "bind": "/model/instance/kpsp_balita_2thn/surat_rujukan" + }, + { + "name": "isOutOfArea", + "value": "false" + }, + { + "name": "isClosed", + "value": "false" + }, + { + "name": "reg_date", + "bind": "/model/instance/kpsp_balita_2thn/today" + }, + { + "name": "registrationDate", + "bind": "/model/instance/kpsp_balita_2thn/reg_date" + } + ] + } +} \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_2thn/model.xml b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_2thn/model.xml new file mode 100644 index 000000000..582b86d15 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_2thn/model.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + <_15bln_menyusun_benda/> + <_15bln_berjalan_sendiri/> + <_15bln_bertepuk_tangan/> + <_15bln_memanggil_ayahibu/> + <_15bln_berdiri_sendiri_5detik/> + <_15bln_berdiri_sendiri_30detik/> + <_15bln_membungkuk_memungut_mainan/> + <_15bln_menunjukkan_keinginan/> + <_15bln_berjalan_tanpa_jatuh/> + <_15bln_mengambil_benda_kecil/> + <_18bln_bertepuk_tangan/> + <_18bln_memanggil_ayahibu/> + <_18bln_berdiri_sendiri_5detik/> + <_18bln_berdiri_sendiri_30detik/> + <_18bln_membungkuk_memungut_mainan/> + <_18bln_menunjukkan_keinginan/> + <_18bln_berjalan_tanpa_jatuh/> + <_18bln_mengambil_benda_kecil/> + <_18bln_menggelindingkan_bola/> + <_18bln_minum_sendiri/> + <_21bln_membungkuk_memungut_mainan/> + <_21bln_menunjukkan_keinginan/> + <_21bln_berjalan_tanpa_jatuh/> + <_21bln_mengambil_benda_kecil/> + <_21bln_menggelindingkan_bola/> + <_21bln_minum_sendiri/> + <_21bln_meniru_pekerjaan/> + <_21bln_menyusun_kubus/> + <_21bln_mengucapkan_kata/> + <_21bln_berjalan_mundur/> + <_24bln_meniru_pekerjaan/> + <_24bln_menyusun_kubus/> + <_24bln_mengucapkan_kata/> + <_24bln_berjalan_mundur/> + <_24bln_melepas_pakaian/> + <_24bln_naik_tangga/> + <_24bln_menunjuk_bagian_badan/> + <_24bln_makan_nasi_sendiri/> + <_24bln_membantu/> + <_24bln_mendendang_bola/> + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_3thn/form.xml b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_3thn/form.xml new file mode 100644 index 000000000..29a91e16e --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_3thn/form.xml @@ -0,0 +1,730 @@ + +
+ + +

KPSP Balita 3 Tahun

+ + + + + + +
+
+ + KPSP Balita 3 Tahun + Pre-Screening Questionnaire of Child Development for 3 Year Toddler + +
+ + +
+
+
+
+
+ + 1. Dapatkah anak melepas pakaiannya seperti: baju, rok, atau celananya? (topi dan kaos kaki tidak ikut dinilai) + 1. Is the child able to undress him/herself, either clothes, skirt or pant? (hat and sock are not assessed) + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 2. Dapatkah anak berjalan naik tangga sendiri? Jawab YA bila ia naik tangga dengan posisi tegak atau berpegangan pada dinding atau pegangan tangga. Jawab TIDAK jika ia naik tangga dengan merangkak atau Anda tidak membolehkan anak naik tangga atau anak harus berpegangan pada seseorang + 2. Is the child able to walk upstairs? Select YES if he/she walks upstairs erectly or holds on to the wall or the banister. Select NO if he/she crawls upstairs or you don't allow him/her to walk upstairs or the child needs to hold onto someone + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 3. Tanpa bimbingan, petunjuk atau bantuan Anda, dapatkah anak menunjuk dengan benar paling sedikit satu bagian badannya (rambut, mata, hidung, mulut, atau bagian badan yang lain)? + 3. Is the child able to point to at least one part of his/her body correctly (hair, eyes, nose, mouth, or other parts) without an aid, a hint, or an assistance. + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 4. Dapatkah anak makan nasi sendiri tanpa banyak tumpah? + 4. Is the child able to eat rice without spilling it too much? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 5. Dapatkah anak membantu memungut mainannya sendiri atau membantu mengangkat piring jika diminta? + 5. Is the child able to help picking up the toys or lifting the plates when he/she is asked to? + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 6. Dapatkah anak menendang bola kecil (sebesar bola tenis) ke depan tanpa berpegangan pada apapun? Mendorong tidak ikut dinilai + 6. Is the child able to kick forward a small ball (such as tennis ball) without holding onto something? Pushing is not assessed + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 7. Bila diberi pensil, apakah anak mencoret-coret kertas tanpa bantuan/petunjuk? + 7. When given a pencil, does the child scribble on paper without any help/hint? + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 8. Dapatkah anak meletakkan 4 buah kubus satu per satu di atas kubus yang lain tanpa menjatuhkan kubus itu? Kubus yang digunakan ukuran 2.5-5 cm + 8. Is the child able to stack 4 blocks one by one on top of the other without dropping it? Use 2.5-5 cm sized blocks + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 9. Dapatkah anak menggunakan 2 kata pada saat berbicara seperti "minta minum", "mau tidur"? "Terima kasih" dan "da-da" tidak ikut dinilai + 9. Is the child able to say 2 words when talking such as "want to drink", "want to sleep"? "Thank you" and "bye-bye" are not assessed + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + + 10. Apakah anak dapat menyebut 2 di antara gambar-gambar ini tanpa bantuan? (Menyebut dengan suara binatang tidak ikut dinilai) + image + + 10. Is the child able to name 2 of these pictures without help? (Imitating the animal's sound is not assessed) + image + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 1. Bila diberi pensil, apakah anak mencoret-coret kertas tanpa bantuan/petunjuk? + 1. When given a pencil, does the child scribble on paper without any help/hint? + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 2. Dapatkah anak meletakkan 4 buah kubus satu per satu di atas kubus yang lain tanpa menjatuhkan kubus itu? Kubus yang digunakan ukuran 2.5-5 cm + 2. Is the child able to stack 4 blocks one by one on top of the other without dropping it? Use 2.5-5 cm sized blocks + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 3. Dapatkah anak menggunakan 2 kata pada saat berbicara seperti "minta minum", "mau tidur"? "Terima kasih" dan "da-da" tidak ikut dinilai + 3. Is the child able to say 2 words when talking such as "want to drink", "want to sleep"? "Thank you" and "bye-bye" are not assessed + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + + 4. Apakah anak dapat menyebut 2 di antara gambar-gambar ini tanpa bantuan? (Menyebut dengan suara binatang tidak ikut dinilai) + image + + 4. Is the child able to name 2 of these pictures without help? (Imitating the animal's sound is not assessed) + image + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 5. Dapatkah anak melempar bola lurus ke arah perut atau dada dari jarak 1,5 meter? + 5. Is the child able to throw a straight ball to your stomach or chest from a distance of 1,5 meters? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 6. Ikuti perintah ini dengan seksama. Jangan memberi isyarat dengan telunjuk atau mata pada saat memberikan perintah berikut ini: "Letakkan kertas ini di lantai". "Letakkan kertas ini di kursi". "Berikan kertas ini kepada ibu". Dapatkah anak melaksanakan ketiga perintah tadi? + 6. Follow this instruction carefully. Do not gesture with a n index finger or eyes while giving these commands: "Put this paper on the floor". "Put this paper on the chair". "Give this paper to your mother". Is the child able to carry out those commands? + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + + 7. Buat garis lurus ke bawah sepanjang sekurang-kurangnya 2.5 cm. Suruh anak menggambar garis lain di samping garis ini. Jawab YA bila ia menggambar garis seperti gambar atas. Jawab TIDAK bila ia menggambar garis seperti gambar bawah + image + + 7. Draw down a straight line at least 2.5 cm long. Have the child draw another line next to the one you make. Select YES if the child draws like this: (picture). Select NO if the child draws like this: (gambar) + image + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 8. Letakkan selembar kertas seukuran buku ini di lantai. Apakah anak dapat melompati bagian lebar kertas dengan mengangkat kedua kakinya secara bersamaan tanpa didahului lari? + 8. Put a piece of paper as the size of this book on the floor. Is the child able to jump over the width of the paper by lifting both legs simultaneously without running? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 9. Dapatkah anak mengenakan sepatunya sendiri? + 9. Is the child able to wear his/her own shoes without help? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 10. Dapatkah anak mengayuh sepeda roda tiga sejauh setidaknya 3 meter? + 10. Is the child able to ride a tricycle as far as 3 meters? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+ + + + + + +
+
+ + Konseling stimulasi bagi ibu: + Stimulation consultation for the mother + +
+ + +
+
+
+ + + +
+
+ + Apakah anak dirujuk? + Is the child referred to other facility? + +
+ + +
+
+
+ +
+
+ + Ada surat rujukan? + Referral letter + +
+ + +
+
+
+ + +
diff --git a/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_3thn/form_definition.json b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_3thn/form_definition.json new file mode 100644 index 000000000..35e88e61c --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_3thn/form_definition.json @@ -0,0 +1,174 @@ +{ + "form_data_definition_version": "1", + "form": { + "bind_type": "anak", + "default_bind_path": "/model/instance/kpsp_balita_3thn/", + "fields": [ + { + "name": "id", + "shouldLoadValue": true + }, + { + "name": "umur", + "bind": "/model/instance/kpsp_balita_3thn/umur", + "shouldLoadValue": true + }, + { + "name": "kpsp_test_date3", + "bind": "/model/instance/kpsp_balita_3thn/kpsp_test_date3" + }, + { + "name": "anamnesis", + "bind": "/model/instance/kpsp_balita_3thn/anamnesis" + }, + { + "name": "keluhan", + "bind": "/model/instance/kpsp_balita_3thn/keluhan" + }, + { + "name": "masalah_tumbang", + "bind": "/model/instance/kpsp_balita_3thn/masalah_tumbang" + }, + { + "name": "kpsp_3thn", + "bind": "/model/instance/kpsp_balita_3thn/kpsp_3thn" + }, + { + "name": "_30bln_melepas_pakaian", + "bind": "/model/instance/kpsp_balita_3thn/_30bln_melepas_pakaian" + }, + { + "name": "_30bln_naik_tangga", + "bind": "/model/instance/kpsp_balita_3thn/_30bln_naik_tangga" + }, + { + "name": "_30bln_menunjuk_bagian_badan", + "bind": "/model/instance/kpsp_balita_3thn/_30bln_menunjuk_bagian_badan" + }, + { + "name": "_30bln_makan_nasi_sendiri", + "bind": "/model/instance/kpsp_balita_3thn/_30bln_makan_nasi_sendiri" + }, + { + "name": "_30bln_membantu", + "bind": "/model/instance/kpsp_balita_3thn/_30bln_membantu" + }, + { + "name": "_30bln_mendendang_bola", + "bind": "/model/instance/kpsp_balita_3thn/_30bln_mendendang_bola" + }, + { + "name": "_30bln_mencoret_kertas", + "bind": "/model/instance/kpsp_balita_3thn/_30bln_mencoret_kertas" + }, + { + "name": "_30bln_menyusun_4kubus", + "bind": "/model/instance/kpsp_balita_3thn/_30bln_menyusun_4kubus" + }, + { + "name": "_30bln_menyebut_dua_kata", + "bind": "/model/instance/kpsp_balita_3thn/_30bln_menyebut_dua_kata" + }, + { + "name": "_30bln_menyebut_dua_binatang", + "bind": "/model/instance/kpsp_balita_3thn/_30bln_menyebut_dua_binatang" + }, + { + "name": "_36bln_mencoret_kertas", + "bind": "/model/instance/kpsp_balita_3thn/_36bln_mencoret_kertas" + }, + { + "name": "_36bln_menyusun_4kubus", + "bind": "/model/instance/kpsp_balita_3thn/_36bln_menyusun_4kubus" + }, + { + "name": "_36bln_menyebut_dua_kata", + "bind": "/model/instance/kpsp_balita_3thn/_36bln_menyebut_dua_kata" + }, + { + "name": "_36bln_menyebut_dua_binatang", + "bind": "/model/instance/kpsp_balita_3thn/_36bln_menyebut_dua_binatang" + }, + { + "name": "_36bln_melempar_bola_lurus", + "bind": "/model/instance/kpsp_balita_3thn/_36bln_melempar_bola_lurus" + }, + { + "name": "_36bln_melakukan_perintah", + "bind": "/model/instance/kpsp_balita_3thn/_36bln_melakukan_perintah" + }, + { + "name": "_36bln_menggambar_garis_lurus", + "bind": "/model/instance/kpsp_balita_3thn/_36bln_menggambar_garis_lurus" + }, + { + "name": "_36bln_melompat_dua_kaki", + "bind": "/model/instance/kpsp_balita_3thn/_36bln_melompat_dua_kaki" + }, + { + "name": "_36bln_mengenakan_sepatu", + "bind": "/model/instance/kpsp_balita_3thn/_36bln_mengenakan_sepatu" + }, + { + "name": "_36bln_mengayuh_sepeda", + "bind": "/model/instance/kpsp_balita_3thn/_36bln_mengayuh_sepeda" + }, + { + "name": "status_kembang3", + "bind": "/model/instance/kpsp_balita_3thn/status_kembang3" + }, + { + "name": "status_meragukan", + "bind": "/model/instance/kpsp_balita_3thn/status_meragukan" + }, + { + "name": "status_penyimpangan", + "bind": "/model/instance/kpsp_balita_3thn/status_penyimpangan" + }, + { + "name": "kesimpulan", + "bind": "/model/instance/kpsp_balita_3thn/kesimpulan" + }, + { + "name": "tindakan_intervensi", + "bind": "/model/instance/kpsp_balita_3thn/tindakan_intervensi" + }, + { + "name": "konseling_stimulasi", + "bind": "/model/instance/kpsp_balita_3thn/konseling_stimulasi" + }, + { + "name": "tindakan_lain", + "bind": "/model/instance/kpsp_balita_3thn/tindakan_lain" + }, + { + "name": "rujukan", + "bind": "/model/instance/kpsp_balita_3thn/rujukan" + }, + { + "name": "dirujuk_ke", + "bind": "/model/instance/kpsp_balita_3thn/dirujuk_ke" + }, + { + "name": "surat_rujukan", + "bind": "/model/instance/kpsp_balita_3thn/surat_rujukan" + }, + { + "name": "isOutOfArea", + "value": "false" + }, + { + "name": "isClosed", + "value": "false" + }, + { + "name": "reg_date", + "bind": "/model/instance/kpsp_balita_3thn/today" + }, + { + "name": "registrationDate", + "bind": "/model/instance/kpsp_balita_3thn/reg_date" + } + ] + } +} \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_3thn/model.xml b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_3thn/model.xml new file mode 100644 index 000000000..3b3c8ea75 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_3thn/model.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + <_30bln_melepas_pakaian/> + <_30bln_naik_tangga/> + <_30bln_menunjuk_bagian_badan/> + <_30bln_makan_nasi_sendiri/> + <_30bln_membantu/> + <_30bln_mendendang_bola/> + <_30bln_mencoret_kertas/> + <_30bln_menyusun_4kubus/> + <_30bln_menyebut_dua_kata/> + <_30bln_menyebut_dua_binatang/> + <_36bln_mencoret_kertas/> + <_36bln_menyusun_4kubus/> + <_36bln_menyebut_dua_kata/> + <_36bln_menyebut_dua_binatang/> + <_36bln_melempar_bola_lurus/> + <_36bln_melakukan_perintah/> + <_36bln_menggambar_garis_lurus/> + <_36bln_melompat_dua_kaki/> + <_36bln_mengenakan_sepatu/> + <_36bln_mengayuh_sepeda/> + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_4thn/form.xml b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_4thn/form.xml new file mode 100644 index 000000000..7763b9fda --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_4thn/form.xml @@ -0,0 +1,680 @@ + +
+ + +

KPSP Balita 4 Tahun

+ + + + + + +
+
+ + KPSP Balita 4 Tahun + Pre-Screening Questionnaire of Child Development for 4 Year Toddler + +
+ + +
+
+
+
+
+ + 1. Dapatkah anak mengenakan sepatunya sendiri? + 1. Is the child able to wear his/her own shoes without help? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 2. Dapatkah anak mengayuh sepeda roda tiga sejauh setidaknya 3 meter? + 2. Is the child able to ride a tricycle as far as 3 meters? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 3. Setelah makan, apakah anak mencuci dan mengeringkan tangannya dengan baik sehingga Anda tidak perlu mengulanginya? + 3. After the meal, does the child wash and dry his/her hands properly so you do not need to repeat it? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 4. Suruh anak berdiri satu kaki tanpa berpegangan. Jika perlu tunjukkan caranya dan beri anak Anda kesempatan melakukannya 3 kali. Dapatkah ia mempertahankan keseimbangan dalam waktu 2 detik atau lebih? + 4. Have the child stand on one foot without holding onto anything. If it's necessary, show him/her how to do that and give the child 3 attempts. Is he/she able to maintain his/her balance for 2 seconds or more? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 5. Letakkan selembar kertas seukuran buku ini di lantai. Apakah anak dapat melompati panjang kertas ini dengan mengangkat kedua kakinya secara bersamaan tanpa didahului lari? + 5. Put a piece of paper as the size of this book on the floor. Is the child able to jump over the height size of this paper by lifting both legs simultaneously without running? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + + 6. Jangan membantu anak dan jangan menyebut lingkaran. Suruh anak menggambar seperti contoh ini di kertas kosong yang tersedia. Dapatkah anak menggambar lingkaran? + image + + 6. Don't assist the child and don't mention a circle. Ask the child to draw as below example on a blank piece of paper. Is the child able to draw the circle? + image + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 7. Dapatkah anak meletakkan 8 buah kubus satu per satu di atas yang lain tanpa menjatuhkan kubus tersebut? Kubus yang digunakan ukuran 2.5-5 cm + 7. Is the child able to stack 8 blocks one by one on top of the other without dropping it? Use the 2.5-5.cm sized blocks + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 8. Apakah anak dapat bermain petak umpet, ular naga atau permainan lain di mana ia ikut bermain dan mengikuti aturan bermain? + 8. Does the child play hide and seek, dragon games or other games in which he/she participates and learns to follow the game rule? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 9. Dapatkah anak mengenakan celana panjang, kemeja, baju atau kaos kaki tanpa dibantu? (Tidak termasuk memasang kancing, gester atau ikat pinggang) + 9. Is the child able to wear a trouser, a shirt, a clothes or a pair of socks without help? (buttoning clothes, wearing buckle or belt are not assessed) + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 1. Dapatkah anak mengayuh sepeda roda tiga sejauh setidaknya 3 meter? + 1. Is the child able to ride a tricycle as far as 3 meters? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 2. Setelah makan, apakah anak mencuci dan mengeringkan tangannya dengan baik sehingga Anda tidak perlu mengulanginya? + 2. After the meal, does the child wash and dry his/her hands properly so you do not need to repeat it? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 3. Suruh anak berdiri satu kaki tanpa berpegangan. Jika perlu tunjukkan caranya dan beri anak Anda kesempatan melakukannya 3 kali. Dapatkah ia mempertahankan keseimbangan dalam waktu 2 detik atau lebih? + 3. Have the child stand on one foot without holding onto anything. If it's necessary, show him/her how to do that and give the child 3 attempts. Is he/she able to maintain his/her balance for 2 seconds or more? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 4. Letakkan selembar kertas seukuran buku ini di lantai. Apakah anak dapat melompati panjang kertas ini dengan mengangkat kedua kakinya secara bersamaan tanpa didahului lari? + 4. Put a piece of paper as the size of this book on the floor. Is the child able to jump over the height size of this paper by lifting both legs simultaneously without running? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + + 5. Jangan membantu anak dan jangan menyebut lingkaran. Suruh anak menggambar seperti contoh ini di kertas kosong yang tersedia. Dapatkah anak menggambar lingkaran? + image + + 5. Don't assist the child and don't mention a circle. Ask the child to draw as below example on a blank piece of paper. Is the child able to draw the circle? + image + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 6. Dapatkah anak meletakkan 8 buah kubus satu per satu di atas yang lain tanpa menjatuhkan kubus tersebut? Kubus yang digunakan ukuran 2.5-5 cm + 6. Is the child able to stack 8 blocks one by one on top of the other without dropping it? Use the 2.5-5.cm sized blocks + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 7. Apakah anak dapat bermain petak umpet, ular naga atau permainan lain di mana ia ikut bermain dan mengikuti aturan bermain? + 7. Does the child play hide and seek, dragon games or other games in which he/she participates and learns to follow the game rule? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 8. Dapatkah anak mengenakan celana panjang, kemeja, baju atau kaos kaki tanpa dibantu? (Tidak termasuk memasang kancing, gester atau ikat pinggang) + 8. Is the child able to wear a trouser, a shirt, a clothes or a pair of socks without help? (buttoning clothes, wearing buckle or belt are not assessed) + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 9. Dapatkah anak menyebutkan nama lengkapnya tanpa dibantu? Jawab TIDAK jika ia hanya menyebut sebagian namanya atau ucapannya sulit dimengerti + 9. Is the child able to tell his/her full name without help? Select NO if he/she only tells part of his/her name or his/her words are difficult to understand + * + Bicara dan bahasa + Language + +
+ + +
+
+
+ + + + + + +
+
+ + Konseling stimulasi bagi ibu: + Stimulation consultation for the mother + +
+ + +
+
+
+ + + +
+
+ + Apakah anak dirujuk? + Is the child referred to other facility? + +
+ + +
+
+
+ +
+
+ + Ada surat rujukan? + Referral letter + +
+ + +
+
+
+ + +
diff --git a/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_4thn/form_definition.json b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_4thn/form_definition.json new file mode 100644 index 000000000..d2c46c0df --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_4thn/form_definition.json @@ -0,0 +1,166 @@ +{ + "form_data_definition_version": "1", + "form": { + "bind_type": "anak", + "default_bind_path": "/model/instance/kpsp_balita_4thn/", + "fields": [ + { + "name": "id", + "shouldLoadValue": true + }, + { + "name": "umur", + "bind": "/model/instance/kpsp_balita_4thn/umur", + "shouldLoadValue": true + }, + { + "name": "kpsp_test_date4", + "bind": "/model/instance/kpsp_balita_4thn/kpsp_test_date4" + }, + { + "name": "anamnesis", + "bind": "/model/instance/kpsp_balita_4thn/anamnesis" + }, + { + "name": "keluhan", + "bind": "/model/instance/kpsp_balita_4thn/keluhan" + }, + { + "name": "masalah_tumbang", + "bind": "/model/instance/kpsp_balita_4thn/masalah_tumbang" + }, + { + "name": "kpsp_4thn", + "bind": "/model/instance/kpsp_balita_4thn/kpsp_4thn" + }, + { + "name": "_42bln_mengenakan_sepatu", + "bind": "/model/instance/kpsp_balita_4thn/_42bln_mengenakan_sepatu" + }, + { + "name": "_42bln_mengayuh_sepeda", + "bind": "/model/instance/kpsp_balita_4thn/_42bln_mengayuh_sepeda" + }, + { + "name": "_42bln_mencuci_tangan", + "bind": "/model/instance/kpsp_balita_4thn/_42bln_mencuci_tangan" + }, + { + "name": "_42bln_berdiri_satu_kaki", + "bind": "/model/instance/kpsp_balita_4thn/_42bln_berdiri_satu_kaki" + }, + { + "name": "_42bln_melompati_kertas", + "bind": "/model/instance/kpsp_balita_4thn/_42bln_melompati_kertas" + }, + { + "name": "_42bln_menggambar_lingkaran", + "bind": "/model/instance/kpsp_balita_4thn/_42bln_menggambar_lingkaran" + }, + { + "name": "_42bln_menyusun_balok", + "bind": "/model/instance/kpsp_balita_4thn/_42bln_menyusun_balok" + }, + { + "name": "_42bln_bermain_berkelompok", + "bind": "/model/instance/kpsp_balita_4thn/_42bln_bermain_berkelompok" + }, + { + "name": "_42bln_mengenakan_baju", + "bind": "/model/instance/kpsp_balita_4thn/_42bln_mengenakan_baju" + }, + { + "name": "_48bln_mengayuh_sepeda", + "bind": "/model/instance/kpsp_balita_4thn/_48bln_mengayuh_sepeda" + }, + { + "name": "_48bln_mencuci_tangan", + "bind": "/model/instance/kpsp_balita_4thn/_48bln_mencuci_tangan" + }, + { + "name": "_48bln_berdiri_satu_kaki", + "bind": "/model/instance/kpsp_balita_4thn/_48bln_berdiri_satu_kaki" + }, + { + "name": "_48bln_melompati_kertas", + "bind": "/model/instance/kpsp_balita_4thn/_48bln_melompati_kertas" + }, + { + "name": "_48bln_menggambar_lingkaran", + "bind": "/model/instance/kpsp_balita_4thn/_48bln_menggambar_lingkaran" + }, + { + "name": "_48bln_menyusun_balok", + "bind": "/model/instance/kpsp_balita_4thn/_48bln_menyusun_balok" + }, + { + "name": "_48bln_bermain_berkelompok", + "bind": "/model/instance/kpsp_balita_4thn/_48bln_bermain_berkelompok" + }, + { + "name": "_48bln_mengenakan_baju", + "bind": "/model/instance/kpsp_balita_4thn/_48bln_mengenakan_baju" + }, + { + "name": "_48bln_menyebut_nama_lengkap", + "bind": "/model/instance/kpsp_balita_4thn/_48bln_menyebut_nama_lengkap" + }, + { + "name": "status_kembang4", + "bind": "/model/instance/kpsp_balita_4thn/status_kembang4" + }, + { + "name": "status_meragukan", + "bind": "/model/instance/kpsp_balita_4thn/status_meragukan" + }, + { + "name": "status_penyimpangan", + "bind": "/model/instance/kpsp_balita_4thn/status_penyimpangan" + }, + { + "name": "kesimpulan", + "bind": "/model/instance/kpsp_balita_4thn/kesimpulan" + }, + { + "name": "tindakan_intervensi", + "bind": "/model/instance/kpsp_balita_4thn/tindakan_intervensi" + }, + { + "name": "konseling_stimulasi", + "bind": "/model/instance/kpsp_balita_4thn/konseling_stimulasi" + }, + { + "name": "tindakan_lain", + "bind": "/model/instance/kpsp_balita_4thn/tindakan_lain" + }, + { + "name": "rujukan", + "bind": "/model/instance/kpsp_balita_4thn/rujukan" + }, + { + "name": "dirujuk_ke", + "bind": "/model/instance/kpsp_balita_4thn/dirujuk_ke" + }, + { + "name": "surat_rujukan", + "bind": "/model/instance/kpsp_balita_4thn/surat_rujukan" + }, + { + "name": "isOutOfArea", + "value": "false" + }, + { + "name": "isClosed", + "value": "false" + }, + { + "name": "reg_date", + "bind": "/model/instance/kpsp_balita_4thn/today" + }, + { + "name": "registrationDate", + "bind": "/model/instance/kpsp_balita_4thn/reg_date" + } + ] + } +} \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_4thn/model.xml b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_4thn/model.xml new file mode 100644 index 000000000..4e0df9c53 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_4thn/model.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + <_42bln_mengenakan_sepatu/> + <_42bln_mengayuh_sepeda/> + <_42bln_mencuci_tangan/> + <_42bln_berdiri_satu_kaki/> + <_42bln_melompati_kertas/> + <_42bln_menggambar_lingkaran/> + <_42bln_menyusun_balok/> + <_42bln_bermain_berkelompok/> + <_42bln_mengenakan_baju/> + <_48bln_mengayuh_sepeda/> + <_48bln_mencuci_tangan/> + <_48bln_berdiri_satu_kaki/> + <_48bln_melompati_kertas/> + <_48bln_menggambar_lingkaran/> + <_48bln_menyusun_balok/> + <_48bln_bermain_berkelompok/> + <_48bln_mengenakan_baju/> + <_48bln_menyebut_nama_lengkap/> + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_5thn/form.xml b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_5thn/form.xml new file mode 100644 index 000000000..199683775 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_5thn/form.xml @@ -0,0 +1,933 @@ + +
+ + +

KPSP Balita 5 Tahun

+ + + + + + +
+
+ + KPSP Balita 5 Tahun + Pre-Screening Questionnaire of Child Development for 5 Year Toddler + +
+ + +
+
+
+
+
+ + 1. Dapatkah anak meletakkan 8 buah kubus satu per satu di atas yang lain tanpa menjatuhkan kubus tersebut? Kubus yang digunakan ukuran 2.5-5 cm + 1. Is the child able to stack 8 blocks one by one on top of the other without dropping it? Use the 2.5-5.cm sized blocks + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 2. Apakah anak dapat bermain petak umpet, ular naga atau permainan lain di mana ia ikut bermain dan mengikuti aturan bermain? + 2. Does the child play hide and seek, dragon games or other games in which he/she participates and learns to follow the game rule? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 3. Dapatkah anak mengenakan celana panjang, kemeja, baju atau kaos kaki tanpa dibantu? (Tidak termasuk memasang kancing, gester atau ikat pinggang) + 3. Is the child able to wear a trouser, a shirt, a clothes or a pair of socks without help? (buttoning clothes, wearing buckle or belt are not assessed) + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 4. Dapatkah anak menyebutkan nama lengkapnya tanpa dibantu? Jawab TIDAK jika ia hanya menyebut sebagian namanya atau ucapannya sulit dimengerti + 4. Is the child able to tell his/her full name without help? Select NO if he/she only tells part of his/her name or his/her words are difficult to understand + * + Bicara dan bahasa + Language + +
+ + +
+
+
+ +
+
+ + 5a. "Apa yang kamu lakukan jika kamu kedinginan?" + 5a. "What do you do when you're cold?" + * + +
+ + + + +
+
+
+
+
+ + 5b. "Apa yang kamu lakukan jika kamu lapar?" + 5b. "What do you do when you're hungry?" + * + +
+ + +
+
+
+
+
+ + 5c. "Apa yang kamu lakukan jika kamu lelah?" + 5c. "What do you do when you're tired?" + * + +
+ + + + + + +
+
+
+
+
+ + 5d. Jawab YA bila anak menjawab ke-3 pertanyaan di atas dengan benar, bukan dengan gerakan atau isyarat. + 5d. Choose YES if the child is able to verbally answer all questions correctly, not using a gesture or a hint. + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 6. Apakah anak dapat mengancingkan bajunya atau pakaian boneka? + 6. Is the child able to button his/her or a doll's clothes? + * + +
+ + +
+
+
+
+
+ + 7. Suruh anak berdiri satu kaki tanpa berpegangan. Jika perlu tunjukkan caranya dan beri anak anda kesempatan melakukannya 3 kali. Dapatkah ia memepertahankan keseimbangan dalam waktu 6 detik atau lebih? + 7. Ask the child to stand on one foot without holding on something. Show him/her how, if necessary, and give 3 chances. Is he/she able to maintain balance for 6 seconds or more? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + + 8. Jangan mengoreksi/membantu anak. Jangan menyebut kata" lebih panjang". Perlihatkan gambar kedua garis ini pada anak. Tanyakan:"mana garis yang lebih panjang?" Minta anak menunjukkan garis yang lebih panjang. Setelah anak menunjuk, putar lembar ini dan ulangi pertanyaan tersebut. Setelah anak menunjuk, putar lembar ini lagi dan ulangi pertanyaan tadi. Apakah anak menunjuk garis yang lebih panjang sebanyak 3 kali dengan benar? + image + + 8. Do not rectify/help the child. Do not say the word "longer". Show the child a picture of two lines. Ask: "which line is longer?" Ask the child to point at a longer line. Afterward, rotate this sheet and ask the same question. Rotate the sheet and ask the question once again. Is the child able to point at the longer line 3 times correctly? + image + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + + 9. Jangan membantu anak dan jangan memberitahu nama gambar ini, suruh anak menggambar seperti contoh ini dikertas kosong yang tersedia. Berikan 3 kali kesempatan. Apakah anak dapat menggambar seperti contoh ini? + image + + 9. Do not help nor tell the child about this picture. Ask the child to draw this picture on a piece of blank paper. Give 3 chances. Is the child able to draw the picture? + image + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 10. Ikuti perintah ini dengan seksama. Jangan memberi isyarat dengan telunjuk atau mata pada saat memberikan perintah berikut ini: "Letakkan kertas ini di atas lantai". "Letakkan kertas ini di bawah kursi". "Letakkan kertas ini di depan kamu". "Letakkan kertas ini di belakang kamu". Jawaban YA hanya jika anak mengerti arti "di atas", "di bawah", "di depan", dan " di belakang". + 10. Follow this instruction carefully. Do not give a hint using index finger nor eyes when giving the following commands" "Put this paper on the floor". "Put this paper under the chair". "Put this paper in front of you". "Put this paper behind you". Choose YES if only the child understand the meaning of "on", "under", "in front of", and "behind". + * + Bicara dan bahasa + Language + +
+ + +
+
+
+ +
+
+ + 1a. "Apa yang kamu lakukan jika kamu kedinginan?" + 1a. "What do you do when you're cold?" + * + +
+ + + + +
+
+
+
+
+ + 1b. "Apa yang kamu lakukan jika kamu lapar?" + 1b. "What do you do when you're hungry?" + * + +
+ + +
+
+
+
+
+ + 1c. "Apa yang kamu lakukan jika kamu lelah?" + 1c. "What do you do when you're tired?" + * + +
+ + + + + + +
+
+
+
+
+ + 1d. Jawab YA bila anak menjawab ke-3 pertanyaan di atas dengan benar, bukan dengan gerakan atau isyarat. + 1d. Choose YES if the child is able to verbally answer all questions correctly, not using a gesture or a hint. + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 2. Apakah anak dapat mengancingkan bajunya atau pakaian boneka? + 2. Is the child able to button his/her or a doll's clothes? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 3. Suruh anak berdiri satu kaki tanpa berpegangan. Jika perlu tunjukkan caranya dan beri anak anda kesempatan melakukannya 3 kali. Dapatkah ia memepertahankan keseimbangan dalam waktu 6 detik atau lebih? + 3. Ask the child to stand on one foot without holding on something. Show him/her how, if necessary, and give 3 chances. Is he/she able to maintain balance for 6 seconds or more? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + + 4. Jangan mengoreksi/membantu anak. Jangan menyebut kata" lebih panjang". Perlihatkan gambar kedua garis ini pada anak. Tanyakan:"mana garis yang lebih panjang?" Minta anak menunjukkan garis yang lebih panjang. Setelah anak menunjuk, putar lembar ini dan ulangi pertanyaan tersebut. setelah anak menunjuk, putar lembar ini lagi dan ulangi pertanyaan tadi. apakah anak menunjuk garis yang lebih panjang sebanyak 3 kali dengan benar? + image + + 4. Do not rectify/help the child. Do not say the word "longer". Show the child a picture of two lines. Ask: "which line is longer?" Ask the child to point at a longer line. Afterward, rotate this sheet and ask the same question. Rotate the sheet and ask the question once again. Is the child able to point at the longer line 3 times correctly? + image + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + + 5. Jangan membantu anak dan jangan memberitahu nama gambar ini, suruh anak menggambar seperti contoh ini dikertas kosong yang tersedia. Berikan 3 kali kesempatan. Apakah anak dapat menggambar seperti contoh ini? + image + + 5. Do not help nor tell the child about this picture. Ask the child to draw this picture on a piece of blank paper. Give 3 chances. Is the child able to draw the picture? + image + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 6. Ikuti perintah ini dengan seksama. Jangan memberi isyarat dengan telunjuk atau mata pada saat memberikan perintah berikut ini: "Letakkan kertas ini di atas lantai". "Letakkan kertas ini di bawah kursi". "Letakkan kertas ini di depan kamu". "Letakkan kertas ini di belakang kamu". Jawaban YA hanya jika anak mengerti arti "di atas", "di bawah", "di depan", dan " di belakang". + 6. Follow this instruction carefully. Do not give a hint using index finger nor eyes when giving the following commands" "Put this paper on the floor". "Put this paper under the chair". "Put this paper in front of you". "Put this paper behind you". Choose YES if only the child understand the meaning of "on", "under", "in front of", and "behind". + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 7. Apakah anak bereaksi dengan tenang dan tidak rewel (tanpa menangis atau menggelayut pada Anda) pada saat Anda meninggalkannya? + 7. Is the child acting calmly and not fussy (no crying or clinging on you) when you leave him/her? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + + 8. Jangan menunjuk, membantu atau membetulkan, katakan pada anak: "Tunjukkan segi empat merah". "Tunjukkan segi empat kuning". "Tunjukkan segi empat biru". "Tunjukkan segi empat hijau". Dapatkah anak menunjuk keempat warna itu dengan benar? + image + + 8. Do not point at, assist nor rectify the child, tell him/her: "Show me a red square". "Show me a yellow square". "Show me a blue square". "Show me a green square". Is the child able to point out the four colors correctly? + image + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 9. Suruh anak melompat dengan satu kaki beberapa kali tanpa berpegangan (lompatan dengan dua kaki tidak ikut dinilai). Apakah ia dapat melompat 2-3 kali dengan satu kaki? + 9. Ask the child to jump with one foot a few times without holding on something (jumping with two feet is not assessed). Is the child able to jump 2-3 times with one foot? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 10. Dapatkah anak sepenuhnya berpakaian sendiri tanpa bantuan? + 10. Is the child able to dress up without assistance? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+ + + + + + +
+
+ + Konseling stimulasi bagi ibu: + Stimulation consultation for the mother + +
+ + +
+
+
+ + + +
+
+ + Apakah anak dirujuk? + Is the child referred to other facility? + +
+ + +
+
+
+ +
+
+ + Ada surat rujukan? + Referral letter + +
+ + +
+
+
+ + +
diff --git a/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_5thn/form_definition.json b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_5thn/form_definition.json new file mode 100644 index 000000000..3de9f091e --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_5thn/form_definition.json @@ -0,0 +1,206 @@ +{ + "form_data_definition_version": "1", + "form": { + "bind_type": "anak", + "default_bind_path": "/model/instance/kpsp_balita_5thn/", + "fields": [ + { + "name": "id", + "shouldLoadValue": true + }, + { + "name": "umur", + "bind": "/model/instance/kpsp_balita_5thn/umur", + "shouldLoadValue": true + }, + { + "name": "kpsp_test_date5", + "bind": "/model/instance/kpsp_balita_5thn/kpsp_test_date5" + }, + { + "name": "anamnesis", + "bind": "/model/instance/kpsp_balita_5thn/anamnesis" + }, + { + "name": "keluhan", + "bind": "/model/instance/kpsp_balita_5thn/keluhan" + }, + { + "name": "masalah_tumbang", + "bind": "/model/instance/kpsp_balita_5thn/masalah_tumbang" + }, + { + "name": "kpsp_5thn", + "bind": "/model/instance/kpsp_balita_5thn/kpsp_5thn" + }, + { + "name": "_54bln_menyusun_balok", + "bind": "/model/instance/kpsp_balita_5thn/_54bln_menyusun_balok" + }, + { + "name": "_54bln_bermain_berkelompok", + "bind": "/model/instance/kpsp_balita_5thn/_54bln_bermain_berkelompok" + }, + { + "name": "_54bln_mengenakan_baju", + "bind": "/model/instance/kpsp_balita_5thn/_54bln_mengenakan_baju" + }, + { + "name": "_54bln_menyebut_nama_lengkap", + "bind": "/model/instance/kpsp_balita_5thn/_54bln_menyebut_nama_lengkap" + }, + { + "name": "_54bln_pertanyaan_note", + "bind": "/model/instance/kpsp_balita_5thn/_54bln_pertanyaan_note" + }, + { + "name": "_54bln_jika_kedinginan", + "bind": "/model/instance/kpsp_balita_5thn/_54bln_jika_kedinginan" + }, + { + "name": "_54bln_jika_lapar", + "bind": "/model/instance/kpsp_balita_5thn/_54bln_jika_lapar" + }, + { + "name": "_54bln_jika_lelah", + "bind": "/model/instance/kpsp_balita_5thn/_54bln_jika_lelah" + }, + { + "name": "_54bln_pertanyaan", + "bind": "/model/instance/kpsp_balita_5thn/_54bln_pertanyaan" + }, + { + "name": "_54bln_mengancingkan_baju", + "bind": "/model/instance/kpsp_balita_5thn/_54bln_mengancingkan_baju" + }, + { + "name": "_54bln_berdiri_satu_kaki", + "bind": "/model/instance/kpsp_balita_5thn/_54bln_berdiri_satu_kaki" + }, + { + "name": "_54bln_lebih_panjang", + "bind": "/model/instance/kpsp_balita_5thn/_54bln_lebih_panjang" + }, + { + "name": "_54bln_menggambar_silang", + "bind": "/model/instance/kpsp_balita_5thn/_54bln_menggambar_silang" + }, + { + "name": "_54bln_perintah", + "bind": "/model/instance/kpsp_balita_5thn/_54bln_perintah" + }, + { + "name": "_60bln_pertanyaan_note", + "bind": "/model/instance/kpsp_balita_5thn/_60bln_pertanyaan_note" + }, + { + "name": "_60bln_jika_kedinginan", + "bind": "/model/instance/kpsp_balita_5thn/_60bln_jika_kedinginan" + }, + { + "name": "_60bln_jika_lapar", + "bind": "/model/instance/kpsp_balita_5thn/_60bln_jika_lapar" + }, + { + "name": "_60bln_jika_lelah", + "bind": "/model/instance/kpsp_balita_5thn/_60bln_jika_lelah" + }, + { + "name": "_60bln_pertanyaan", + "bind": "/model/instance/kpsp_balita_5thn/_60bln_pertanyaan" + }, + { + "name": "_60bln_mengancingkan_baju", + "bind": "/model/instance/kpsp_balita_5thn/_60bln_mengancingkan_baju" + }, + { + "name": "_60bln_berdiri_satu_kaki", + "bind": "/model/instance/kpsp_balita_5thn/_60bln_berdiri_satu_kaki" + }, + { + "name": "_60bln_lebih_panjang", + "bind": "/model/instance/kpsp_balita_5thn/_60bln_lebih_panjang" + }, + { + "name": "_60bln_menggambar_silang", + "bind": "/model/instance/kpsp_balita_5thn/_60bln_menggambar_silang" + }, + { + "name": "_60bln_perintah", + "bind": "/model/instance/kpsp_balita_5thn/_60bln_perintah" + }, + { + "name": "_60bln_reaksi_anak", + "bind": "/model/instance/kpsp_balita_5thn/_60bln_reaksi_anak" + }, + { + "name": "_60bln_warna", + "bind": "/model/instance/kpsp_balita_5thn/_60bln_warna" + }, + { + "name": "_60bln_melompat_satu_kaki", + "bind": "/model/instance/kpsp_balita_5thn/_60bln_melompat_satu_kaki" + }, + { + "name": "_60bln_berpakaian_sendiri", + "bind": "/model/instance/kpsp_balita_5thn/_60bln_berpakaian_sendiri" + }, + { + "name": "status_kembang5", + "bind": "/model/instance/kpsp_balita_5thn/status_kembang5" + }, + { + "name": "status_meragukan", + "bind": "/model/instance/kpsp_balita_5thn/status_meragukan" + }, + { + "name": "status_penyimpangan", + "bind": "/model/instance/kpsp_balita_5thn/status_penyimpangan" + }, + { + "name": "kesimpulan", + "bind": "/model/instance/kpsp_balita_5thn/kesimpulan" + }, + { + "name": "tindakan_intervensi", + "bind": "/model/instance/kpsp_balita_5thn/tindakan_intervensi" + }, + { + "name": "konseling_stimulasi", + "bind": "/model/instance/kpsp_balita_5thn/konseling_stimulasi" + }, + { + "name": "tindakan_lain", + "bind": "/model/instance/kpsp_balita_5thn/tindakan_lain" + }, + { + "name": "rujukan", + "bind": "/model/instance/kpsp_balita_5thn/rujukan" + }, + { + "name": "dirujuk_ke", + "bind": "/model/instance/kpsp_balita_5thn/dirujuk_ke" + }, + { + "name": "surat_rujukan", + "bind": "/model/instance/kpsp_balita_5thn/surat_rujukan" + }, + { + "name": "isOutOfArea", + "value": "false" + }, + { + "name": "isClosed", + "value": "false" + }, + { + "name": "reg_date", + "bind": "/model/instance/kpsp_balita_5thn/today" + }, + { + "name": "registrationDate", + "bind": "/model/instance/kpsp_balita_5thn/reg_date" + } + ] + } +} \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_5thn/model.xml b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_5thn/model.xml new file mode 100644 index 000000000..aacfccccc --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_5thn/model.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + <_54bln_menyusun_balok/> + <_54bln_bermain_berkelompok/> + <_54bln_mengenakan_baju/> + <_54bln_menyebut_nama_lengkap/> + <_54bln_pertanyaan_note/> + <_54bln_jika_kedinginan/> + <_54bln_jika_lapar/> + <_54bln_jika_lelah/> + <_54bln_pertanyaan/> + <_54bln_mengancingkan_baju/> + <_54bln_berdiri_satu_kaki/> + <_54bln_lebih_panjang/> + <_54bln_menggambar_silang/> + <_54bln_perintah/> + <_60bln_pertanyaan_note/> + <_60bln_jika_kedinginan/> + <_60bln_jika_lapar/> + <_60bln_jika_lelah/> + <_60bln_pertanyaan/> + <_60bln_mengancingkan_baju/> + <_60bln_berdiri_satu_kaki/> + <_60bln_lebih_panjang/> + <_60bln_menggambar_silang/> + <_60bln_perintah/> + <_60bln_reaksi_anak/> + <_60bln_warna/> + <_60bln_melompat_satu_kaki/> + <_60bln_berpakaian_sendiri/> + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_6thn/form.xml b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_6thn/form.xml new file mode 100644 index 000000000..1046a5176 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_6thn/form.xml @@ -0,0 +1,744 @@ + +
+ + +

KPSP Balita 6 Tahun

+ + + + + + +
+
+ + KPSP Balita 6 Tahun + Pre-Screening Questionnaire of Child Development for 6 Year Toddler + +
+ + +
+
+
+
+
+ + + 1. Jangan membantu anak dan jangan memberitahu nama gambar ini, suruh anak menggambar seperti contoh ini dikertas kosong yang tersedia. Berikan 3 kali kesempatan. Apakah anak dapat menggambar seperti contoh ini? + image + + 1. Do not help nor tell the child about this picture. Ask the child to draw this picture on a piece of blank paper. Give 3 chances. Is the child able to draw the picture? + image + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 2. Ikuti perintah ini dengan seksama. Jangan memberi isyarat dengan telunjuk atau mata pada saat memberikan perintah berikut ini: "Letakkan kertas ini di atas lantai". "Letakkan kertas ini di bawah kursi". "Letakkan kertas ini di depan kamu". "Letakkan kertas ini di belakang kamu". Jawaban YA hanya jika anak mengerti arti "di atas", "di bawah", "di depan", dan " di belakang". + 2. Follow this instruction carefully. Do not give a hint using index finger nor eyes when giving the following commands" "Put this paper on the floor". "Put this paper under the chair". "Put this paper in front of you". "Put this paper behind you". Choose YES if only the child understand the meaning of "on", "under", "in front of", and "behind". + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 3. Apakah anak bereaksi dengan tenang dan tidak rewel (tanpa menangis atau menggelayut pada Anda) pada saat Anda meninggalkannya? + 3. Is the child acting calmly and not fussy (no crying or clinging on you) when you leave him/her? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + + 4. Jangan menunjuk, membantu atau membetulkan, katakan pada anak: "Tunjukkan segi empat merah". "Tunjukkan segi empat kuning". "Tunjukkan segi empat biru". "Tunjukkan segi empat hijau". Dapatkah anak menunjuk keempat warna itu dengan benar? + image + + 4. Do not point at, assist nor rectify the child, tell him/her: "Show me a red square". "Show me a yellow square". "Show me a blue square". "Show me a green square". Is the child able to point out the four colors correctly? + image + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 5. Suruh anak melompat dengan satu kaki beberapa kali tanpa berpegangan (lompatan dengan dua kaki tidak ikut dinilai). Apakah ia dapat melompat 2-3 kali dengan satu kaki? + 5. Ask the child to jump with one foot a few times without holding on something (jumping with two feet is not assessed). Is the child able to jump 2-3 times with one foot? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 6. Dapatkah anak sepenuhnya berpakaian sendiri tanpa bantuan? + 6. Is the child able to dress up without assistance? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 7. Suruh anak menggambar di tempat kosong yang tersedia. Katakan padanya: "Buatlah gambar orang". Jangan memberi perintah lebih dari itu. Jangan bertanya/mengingatkan anak bila ada bagian yang belum tergambar. Dalam memberi nilai, hitunglah berapa bagian tubuh yang tergambar. Untuk bagian tubuh yang berpasangan seperti mata, telinga, lengan dan kaki, setiap pasang dinilai satu bagian. Dapatkah anak menggambar sedikitnya 3 bagian tubuh? + 7. Ask the child to draw on a piece of blank paper. Tell him/her: "Draw a person". Do not give any further command. Do not ask/remind the child of a body part that was not drawned yet. Count how many body parts are drawn. For the paired-body parts like eyes, ears, arms and legs, each pair is counted as one part. Is the child able to draw at least 3 body parts? + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 8. Pada gambar yang dibuat sebelumnya, dapatkah anak menggambar sedikitnya 6 bagian tubuh? + 8. On the previous drawing, is the child able to draw at least 6 body parts? + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 9. Tulis apa yang dikatakan anak pada kalimat-kalimat yang belum selesai ini, jangan membantu kecuali mengulang pertanyaan: "Jika kuda besar maka tikus ........". "Jika api panas maka es .....". "Jika ibu seorang wanita maka ayah seorang ......". Apakah anak menjawab dengan benar (tikus kecil, es dingin, ayah seorang pria)? + 9. Record the child's answers for these incomplete sentences, do not give any help except repeating the question: "If a horse is big then a mouse is ......". "If a fire is hot then an ice is .....". "If a mother is a woman then a father is a .....". Is the child able tp answer them correctly (a mouse is small, an ice is cold, a father is a man)? + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 10. Apakah anak dapat menangkap bola kecil sebesar bola tenis/bola kasti hanya dengan menggunakan kedua tangannya? (Bola besar tidak ikut dinilai) + 10. Is the child able to catch a small ball like tennis/baseball using two hands? (Big balls are not assessed) + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + + 1. Jangan menunjuk, membantu atau membetulkan, katakan pada anak: "Tunjukkan segi empat merah". "Tunjukkan segi empat kuning". "Tunjukkan segi empat biru". "Tunjukkan segi empat hijau". Dapatkah anak menunjuk keempat warna itu dengan benar? + image + + 1. Do not point at, assist nor rectify the child, tell him/her: "Show me a red square". "Show me a yellow square". "Show me a blue square". "Show me a green square". Is the child able to point out the four colors correctly? + image + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 2. Suruh anak melompat dengan satu kaki beberapa kali tanpa berpegangan (lompatan dengan dua kaki tidak ikut dinilai). Apakah ia dapat melompat 2-3 kali dengan satu kaki? + 2. Ask the child to jump with one foot a few times without holding on something (jumping with two feet is not assessed). Is the child able to jump 2-3 times with one foot? + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 3. Dapatkah anak sepenuhnya berpakaian sendiri tanpa bantuan? + 3. Is the child able to dress up without assistance? + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 4. Suruh anak menggambar di tempat kosong yang tersedia. Katakan padanya: "Buatlah gambar orang". Jangan memberi perintah lebih dari itu. Jangan bertanya/mengingatkan anak bila ada bagian yang belum tergambar. Dalam memberi nilai, hitunglah berapa bagian tubuh yang tergambar. Untuk bagian tubuh yang berpasangan seperti mata, telinga, lengan dan kaki, setiap pasang dinilai satu bagian. Dapatkah anak menggambar sedikitnya 3 bagian tubuh? + 4. Ask the child to draw on a piece of blank paper. Tell him/her: "Draw a person". Do not give any further command. Do not ask/remind the child of a body part that was not drawned yet. Count how many body parts are drawn. For the paired-body parts like eyes, ears, arms and legs, each pair is counted as one part. Is the child able to draw at least 3 body parts? + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 5. Pada gambar yang dibuat sebelumnya, dapatkah anak menggambar sedikitnya 6 bagian tubuh? + 5. On the previous drawing, is the child able to draw at least 6 body parts? + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 6. Tulis apa yang dikatakan anak pada kalimat-kalimat yang belum selesai ini, jangan membantu kecuali mengulang pertanyaan: "Jika kuda besar maka tikus ........". "Jika api panas maka es .....". "Jika ibu seorang wanita maka ayah seorang ......". Apakah anak menjawab dengan benar (tikus kecil, es dingin, ayah seorang pria)? + 6. Record the child's answers for these incomplete sentences, do not give any help except repeating the question: "If a horse is big then a mouse is ......". "If a fire is hot then an ice is .....". "If a mother is a woman then a father is a .....". Is the child able tp answer them correctly (a mouse is small, an ice is cold, a father is a man)? + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 7. Apakah anak dapat menangkap bola kecil sebesar bola tenis/bola kasti hanya dengan menggunakan kedua tangannya? (Bola besar tidak ikut dinilai) + 7. Is the child able to catch a small ball like tennis/baseball using two hands? (Big balls are not assessed) + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 8. Suruh anak berdiri satu kaki tanpa berpegangan. Jika perlu tunjukkan caranya dan beri anak Anda kesempatan melakukannya 3 kali. Dapatkah ia mempertahankan keseimbangan dalam waktu 11 detik atau lebih? + 8. Ask the child to stand on one foot without holding on something. Show him/her how, if necessary, and give 3 chances. Is he/she able to maintain balance for 11 seconds or more? + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + + 9. Jangan membantu anak dan jangan memberitahu nama gambar ini, suruh anak menggambar seperti contoh ini di kertas kosong yang tersedia. Berikan 3 kali kesempatan. Apakah anak dapat menggambar seperti contoh ini? + image + + 9. Do not help nor tell the child about this picture. Ask the child to draw this picture on a piece of blank paper. Give 3 chances. Is the child able to draw the picture? + image + Gerak halus + Fine motor + +
+ + +
+
+
+ + + + +
+
+ + 10d. Apakah anak dapat menjawab ketiga pertanyaan di atas dengan benar? + 10d. Is the child able to answer all the questions correctly? + Bicara dan bahasa + Language + +
+ + +
+
+
+ + + + + + +
+
+ + Konseling stimulasi bagi ibu: + Stimulation consultation for the mother + +
+ + +
+
+
+ + + +
+
+ + Apakah anak dirujuk? + Is the child referred to other facility? + +
+ + +
+
+
+ +
+
+ + Ada surat rujukan? + Referral letter + +
+ + +
+
+
+ + +
diff --git a/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_6thn/form_definition.json b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_6thn/form_definition.json new file mode 100644 index 000000000..5ad8423f8 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_6thn/form_definition.json @@ -0,0 +1,190 @@ +{ + "form_data_definition_version": "1", + "form": { + "bind_type": "anak", + "default_bind_path": "/model/instance/kpsp_balita_6thn/", + "fields": [ + { + "name": "id", + "shouldLoadValue": true + }, + { + "name": "umur", + "bind": "/model/instance/kpsp_balita_6thn/umur", + "shouldLoadValue": true + }, + { + "name": "kpsp_test_date6", + "bind": "/model/instance/kpsp_balita_6thn/kpsp_test_date6" + }, + { + "name": "anamnesis", + "bind": "/model/instance/kpsp_balita_6thn/anamnesis" + }, + { + "name": "keluhan", + "bind": "/model/instance/kpsp_balita_6thn/keluhan" + }, + { + "name": "masalah_tumbang", + "bind": "/model/instance/kpsp_balita_6thn/masalah_tumbang" + }, + { + "name": "kpsp_6thn", + "bind": "/model/instance/kpsp_balita_6thn/kpsp_6thn" + }, + { + "name": "_66bln_menggambar_silang", + "bind": "/model/instance/kpsp_balita_6thn/_66bln_menggambar_silang" + }, + { + "name": "_66bln_perintah", + "bind": "/model/instance/kpsp_balita_6thn/_66bln_perintah" + }, + { + "name": "_66bln_reaksi_anak", + "bind": "/model/instance/kpsp_balita_6thn/_66bln_reaksi_anak" + }, + { + "name": "_66bln_warna", + "bind": "/model/instance/kpsp_balita_6thn/_66bln_warna" + }, + { + "name": "_66bln_melompat_satu_kaki", + "bind": "/model/instance/kpsp_balita_6thn/_66bln_melompat_satu_kaki" + }, + { + "name": "_66bln_berpakaian_sendiri", + "bind": "/model/instance/kpsp_balita_6thn/_66bln_berpakaian_sendiri" + }, + { + "name": "_66bln_menggambar_3bagian", + "bind": "/model/instance/kpsp_balita_6thn/_66bln_menggambar_3bagian" + }, + { + "name": "_66bln_menggambar_6bagian", + "bind": "/model/instance/kpsp_balita_6thn/_66bln_menggambar_6bagian" + }, + { + "name": "_66bln_lawan_kata", + "bind": "/model/instance/kpsp_balita_6thn/_66bln_lawan_kata" + }, + { + "name": "_66bln_menangkap_bola", + "bind": "/model/instance/kpsp_balita_6thn/_66bln_menangkap_bola" + }, + { + "name": "_72bln_warna", + "bind": "/model/instance/kpsp_balita_6thn/_72bln_warna" + }, + { + "name": "_72bln_melompat_satu_kaki", + "bind": "/model/instance/kpsp_balita_6thn/_72bln_melompat_satu_kaki" + }, + { + "name": "_72bln_berpakaian_sendiri", + "bind": "/model/instance/kpsp_balita_6thn/_72bln_berpakaian_sendiri" + }, + { + "name": "_72bln_menggambar_3bagian", + "bind": "/model/instance/kpsp_balita_6thn/_72bln_menggambar_3bagian" + }, + { + "name": "_72bln_menggambar_6bagian", + "bind": "/model/instance/kpsp_balita_6thn/_72bln_menggambar_6bagian" + }, + { + "name": "_72bln_lawan_kata", + "bind": "/model/instance/kpsp_balita_6thn/_72bln_lawan_kata" + }, + { + "name": "_72bln_menangkap_bola", + "bind": "/model/instance/kpsp_balita_6thn/_72bln_menangkap_bola" + }, + { + "name": "_72bln_berdiri_1kaki", + "bind": "/model/instance/kpsp_balita_6thn/_72bln_berdiri_1kaki" + }, + { + "name": "_72bln_menggambar", + "bind": "/model/instance/kpsp_balita_6thn/_72bln_menggambar" + }, + { + "name": "_72bln_pertanyaan_note1", + "bind": "/model/instance/kpsp_balita_6thn/_72bln_pertanyaan_note1" + }, + { + "name": "_72bln_pertanyaan_note2", + "bind": "/model/instance/kpsp_balita_6thn/_72bln_pertanyaan_note2" + }, + { + "name": "_72bln_pertanyaan_note3", + "bind": "/model/instance/kpsp_balita_6thn/_72bln_pertanyaan_note3" + }, + { + "name": "_72bln_pertanyaan_note4", + "bind": "/model/instance/kpsp_balita_6thn/_72bln_pertanyaan_note4" + }, + { + "name": "_72bln_pertanyaan", + "bind": "/model/instance/kpsp_balita_6thn/_72bln_pertanyaan" + }, + { + "name": "status_kembang6", + "bind": "/model/instance/kpsp_balita_6thn/status_kembang6" + }, + { + "name": "status_meragukan", + "bind": "/model/instance/kpsp_balita_6thn/status_meragukan" + }, + { + "name": "status_penyimpangan", + "bind": "/model/instance/kpsp_balita_6thn/status_penyimpangan" + }, + { + "name": "kesimpulan", + "bind": "/model/instance/kpsp_balita_6thn/kesimpulan" + }, + { + "name": "tindakan_intervensi", + "bind": "/model/instance/kpsp_balita_6thn/tindakan_intervensi" + }, + { + "name": "konseling_stimulasi", + "bind": "/model/instance/kpsp_balita_6thn/konseling_stimulasi" + }, + { + "name": "tindakan_lain", + "bind": "/model/instance/kpsp_balita_6thn/tindakan_lain" + }, + { + "name": "rujukan", + "bind": "/model/instance/kpsp_balita_6thn/rujukan" + }, + { + "name": "dirujuk_ke", + "bind": "/model/instance/kpsp_balita_6thn/dirujuk_ke" + }, + { + "name": "surat_rujukan", + "bind": "/model/instance/kpsp_balita_6thn/surat_rujukan" + }, + { + "name": "isOutOfArea", + "value": "false" + }, + { + "name": "isClosed", + "value": "false" + }, + { + "name": "reg_date", + "bind": "/model/instance/kpsp_balita_6thn/today" + }, + { + "name": "registrationDate", + "bind": "/model/instance/kpsp_balita_6thn/reg_date" + } + ] + } +} \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_6thn/model.xml b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_6thn/model.xml new file mode 100644 index 000000000..d1ae49687 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/kpsp_balita_6thn/model.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + <_66bln_menggambar_silang/> + <_66bln_perintah/> + <_66bln_reaksi_anak/> + <_66bln_warna/> + <_66bln_melompat_satu_kaki/> + <_66bln_berpakaian_sendiri/> + <_66bln_menggambar_3bagian/> + <_66bln_menggambar_6bagian/> + <_66bln_lawan_kata/> + <_66bln_menangkap_bola/> + <_72bln_warna/> + <_72bln_melompat_satu_kaki/> + <_72bln_berpakaian_sendiri/> + <_72bln_menggambar_3bagian/> + <_72bln_menggambar_6bagian/> + <_72bln_lawan_kata/> + <_72bln_menangkap_bola/> + <_72bln_berdiri_1kaki/> + <_72bln_menggambar/> + <_72bln_pertanyaan_note1/> + <_72bln_pertanyaan_note2/> + <_72bln_pertanyaan_note3/> + <_72bln_pertanyaan_note4/> + <_72bln_pertanyaan/> + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/kpsp_bayi_1thn/form.xml b/opensrp-sdidtk/src/main/assets/www/form/kpsp_bayi_1thn/form.xml new file mode 100644 index 000000000..44936196d --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/kpsp_bayi_1thn/form.xml @@ -0,0 +1,1240 @@ + +
+ + +

KPSP Bayi 1 Tahun

+ + + + + + +
+
+ + KPSP Bayi 1 Tahun + Pre-Screening Questionnaire of Child Development for 1 Year Toddler + +
+ + + + +
+
+
+
+
+ + 1. Pada waktu bayi telentang, apakah masing-masing lengan dan tungkai bergerak dengan mudah? Jawab TIDAK bila salah satu atau kedua tungkai atau lengan bayi bergerak tak terarah/tak terkendali + 1. When the baby is lying down, does both his/her arms and legs move easily? Select NO if either one or both baby's arms or legs move disorderly/uncontrollably + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 2. Pada waktu bayi telentang, apakah ia melihat dan menatap wajah Anda? + 2. When the baby is lying down, does he/she see and look at your face? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 3. Apakah bayi dapat mengeluarkan suara-suara lain (ngoceh) di samping menangis? + 3. Does baby voice other sound (babbling) other than crying? + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + + 4. Pada waktu bayi telentang, apakah ia dapat mengikuti gerakan Anda dengan menggerakkan kepalanya dari kanan/kiri ke tengah? + image + + 4. When the baby is lying down, is he/she able to follow your move by moving his/her head from right/left to the centre (facing you)? + image + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + + 5. Pada waktu bayi telentang, apakah ia dapat mengikuti gerakan Anda dengan menggerakkan kepalanya dari satu sisi hampir sampai pada sisi yang lain? + image + + 5. When the baby is lying down, is he/she able to follow your move by moving his/her head from one side almost to the other side? + image + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 6. Pada waktu Anda mengajak bayi berbicara dan tersenyum, apakah ia tersenyum kembali kepada Anda? + 6. When you are talking and smiling to the baby, does he/she smile back to you? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + + 7. Pada waktu bayi telungkup di alas yang datar, apakah ia dapat mengangkat kepalanya seperti pada gambar ini? + image + + 7. When the baby is facing down on a flat base, is he/she able to lift his/her head as seen in the picture? + image + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + + 8. Pada waktu bayi telungkup di alas yang datar, apakah ia dapat mengangkat kepalanya sehingga membentuk sudut 45 derajat seperti pada gambar? + image + + 8. When the baby is facing down on a flat base, is he/she able to lift his/her head to form an angle of 45 degrees as seen in the picture? + image + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + + 9. Pada waktu bayi telungkup di alas yang datar, apakah ia dapat mengangkat kepalanya dengan tegak seperti pada gambar? + image + + 9. When the baby is facing down on a flat base, is he/she able to lift his/her head erectly as seen in the picture? + image + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 10. Apakah bayi suka tertawa keras walau tidak digelitik atau diraba-raba? + 10. Does the baby like to laugh even he/she is not tickled ot touched? + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + + 1. Pada waktu bayi telentang, apakah ia dapat mengikuti gerakan Anda dengan menggerakkan kepala sepenuhnya dari satu sisi ke sisi yang lain? + image + + 1. When the baby is lying down, is he/she able to follow your move by moving his/her head completely from one side to the other? + image + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 2. Dapatkah bayi mempertahankan posisi kepala dalam keadaan tegak dan stabil? Jawab TIDAK bila kepala bayi cenderung jatuh ke kanan/kiri atau ke dadanya + 2. Is the baby able to maintain his/her head in an upright and stable position? Select NO if the baby's head inclines to the right/left or to the chest + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + + 3. Sentuhkan pensil di punggung tangan atau ujung jari bayi (jangan meletakkan di atas telapak tangan bayi). Apakah bayi dapat menggenggam pensil itu selama beberapa detik? + image + + 3. Put slightly a pencil on the baby's back hand or fingertip (don't put it on the palm). Is the baby able to grasp the pecil for a few seconds? + image + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + + 4. Ketika bayi telungkup di alas datar, apakah ia dapat mengangkat dada dengan kedua lengannya sebagai penyangga seperti pada gambar? + image + + 4. When the baby is facing down, is he/she able to lift his/her chest using both arms as buffer as seen in the picture? + image + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 5. Pernahkah bayi mengeluarkan suara gembira bernada tinggi atau memekik tetapi bukan menangis? + 5. Has the baby made a high-picthed, excited voice or a squeal but not crying? + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 6. Pernahkah bayi berbalik paling sedikit dua kali, dari telentang ke telungkup atau sebaliknya? + 6. Has the baby turned around at least twice, from a facing upward to downward position or vice versa? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 7. Pernahkah Anda melihat bayi tersenyum ketika melihat mainan yang lucu, gambar atau binatang peliharaan saat ia bermain sendiri? + 7. Have you seen the baby smile when seeing a cute toys, pictures, or pets when he/she is playing alone? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 8. Dapatkah bayi mengarahkan matanya pada benda kecil sebesar kacang, kismis atau uang logam? Jawab TIDAK jika ia tidak dapat mengarahkan matanya + 8. Is the baby able to focus his/her sight on a small objects such as a nut, a raisin or a coin? Select NO if he/she is not able to focus his/her sight + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 9. Dapatkah bayi meraih mainan yang diletakkan agak jauh namun masih berada dalam jangkauan tangannya? + 9. Is the baby able to reach a toy which is placed slighlty far but is still within the reach of his/her hand + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + + 10. Pada posisi bayi telentang, pegang kedua tangannya lalu tarik perlahan-lahan ke posisi duduk. Dapatkah bayi mempertahankan lehernya secara kaku seperti pada gambar di sebelah kiri? Jawab TIDAK bila kepala bayi jatuh kembali seperti gambar sebelah kanan + image + + 10. When the baby is lying down, hold his/her hands then pull him/her up slowly into a sitting position. Is the baby able to maintain his/her neck rigidly as seen in the left picture? Select NO if the baby's head falls down as seen in the righ picture? + image + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + + 1. Pada posisi bayi telentang, pegang kedua tangannya lalu tarik perlahan-lahan ke posisi duduk. Dapatkah bayi mempertahankan lehernya secara kaku seperti pada gambar di sebelah kiri? Jawab TIDAK bila kepala bayi jatuh kembali seperti gambar sebelah kanan + image + + 1. When the baby is lying down, hold his/her hands then pull him/her up slowly into a sitting position. Is the baby able to maintain his/her neck rigidly as seen in the left picture? Select NO if the baby's head falls down as seen in the righ picture? + image + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 2. Pernahkan Anda melihat bayi memindahkan mainan atau kue kering dari satu tangan ke tangan yang lain? Benda-benda panjang seperti sendok atau kerincingan bertangkai tidak ikut dinilai + 2. Have you seen the baby move a toy or a cookie from one hand to the other? A long-shaped objects such as spoon or handgripped rattle are not assessed + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 3. Tarik perhatian bayi dengan memperlihatkan selendang, sapu tangan atau serbet, kemudian jatuhkan ke lantai. Apakah bayi mencoba mencarinya? Misalnya mencari di bawah meja atau di belakang kursi? + 3. Attrack baby's attention by showing him/her a scarf, a handerkerchief or a napkin, then drop it to the floor. Does the baby try to look for it, for example looking under the table or behind the chair? + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 4. Apakah bayi dapat memungut dua benda seperti mainan/kue kering, dan masing-masing tangan memegang satu benda pada saat yang sama? Jawab TIDAK bila bayi tidak pernah melakukan perbuatan ini + 4. Is the baby able to pick up two objects such as toys/cookies, and each hand holds one object simultaneously? Select NO if the baby has never done this + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 5. Jika Anda mengangkat bayi melalui ketiaknya ke posisi berdiri, dapatkah ia menyangga sebagian berat badan dengan kedua kakinya? Jawab YA bila ia mencoba berdiri dan sebagian berat badan bertumpu pada kedua kakinya. + 5. If you lift the baby by his/her armpits to a standing position, is he/she able to prop half of his/herweight with both feet? Select YES if he/she tries to stand and props half of his/her weight on both feet. + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + + 6. Dapatkah bayi memungut dengan tangannya benda-benda kecil seperti kismis, kacang-kacangan, potongan biskuit, dengan gerakan miring atau menggerapai seperti gambar? + image + + 6. Is the baby able to pick up small objects such as a raisin, a nut, a piece of biscuit, with a slanted hand movement as seen in the picture? + image + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + + 7. Tanpa disangga oleh bantal, kursi atau dinding, dapatkah bayi duduk sendiri selama 60 detik? + image + + 7. Is the baby able to sit alone for 60 seconds without being propped by a pillow, a chair or a wall? + image + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 8. Apakah bayi dapat makan kue kering sendiri? + 8. Is the baby able to eat a cookie without help? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 9. Pada waktu bayi bermain sendiri dan Anda diam-diam datang berdiri di belakangnya, apakah ia menengok ke belakang seperti mendengar kedatangan Anda? Suara keras tidak ikut dihitung. Jawab YA hanya jika Anda melihat reaksinya terhadap suara yang perlahan atau bisikan + 9. When the baby was playing alone and you quitely stood behind him/her, did he/she look back as if hearing your arrival?. A loud noise is not assessed. Select YES if you saw his/her reaction to a soft sound or a whisper + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 10. Letakkan suatu mainan yang diinginkannya di luar jangkauan bayi, apakah ia mencoba mendapatkannya dengan mengulurkan lengan atau badannya? + 10. Put a toy which the baby wants beyond his/her reach of hand, does she try to get it by reaching out his/her arm or body? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 1. Jika Anda bersembunyi di belakang sesuatu/di pojok, kemudian muncul dan menghilang secara berulang-ulang di hadapan anak, apakah ia mencari Anda atau mengharapkan Anda muncul kembali? + 1. If you're hiding behind someting/in the corner, then appear and disappear time after time in front of the baby, does he/she look for you or expect you to reappear? + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + 2. Letakkan pensil di telapak tangan bayi. Coba ambil pensil tersebut dengan perlahan-lahan. Sulitkah Anda mendapatkan pensil itu kembali? + 2. Put a pencil on the baby's palm. Try to take the pencil slowly. Is it difficult to take it back from the baby? + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 3. Apakah anak dapat berdiri selama 30 detik atau lebih dengan berpegangan pada kursi/meja? + 3. Is the baby able to stand for 30 seconds or more by holding on to a chair/table? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 4. Apakah anak dapat mengatakan 2 suku kata yang sama, misalnya: "ma-ma", "da-da", atau "pa-pa". Jawab YA bila ia mengeluarkan salah satu suara tadi. + 4. Is the baby able to pronounce two identical syllables, such as: "ma-ma", "da-da", or "pa-pa". Select YES if he/she pronounce either one of them + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 5. Apakah anak dapat mengangkat badannya ke posisi berdiri tanpa bantuan Anda? + 5. Is the baby able to lift his/her body to a standing position without your help? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 6. Apakah anak dapat membedakan Anda dengan orang yang belum ia kenal? Ia akan menunjukkan sikap malu-malu atau ragu-ragu pada saat permulaan bertemu dengan orang yang belum dikenalnya + 6. Is the baby able to distinguish you from a stranger? He/she will show shyness or hesitation when meeting a stranger for the first time + * + Sosialisasi dan kemandirian + Socialization and independency + +
+ + +
+
+
+
+
+ + + 7. Apakah anak dapat mengambil benda kecil seperti kacang atau kismis, dengan meremas di antara ibu jari dan jarinya seperti pada gambar? + image + + 7. Is the baby able to pick up small objects such as a nut or a raisin, by squeezing it between a thumb and other fingers as seen in the picture? + image + * + Gerak halus + Fine motor + +
+ + +
+
+
+
+
+ + 8. Apakah anak dapat duduk sendiri tanpa bantuan? + 8. Is the baby able to sit alone without help? + * + Gerak kasar + Gross motor + +
+ + +
+
+
+
+
+ + 9. Sebut 2-3 kata yang dapat ditiru oleh anak (tidak perlu kata-kata yang lengkap). Apakah ia mencoba meniru menyebutkan kata-kata tadi? + 9. Pronounce 2-3 wors that the baby can imitate (not necessarily a complete word). Does he/she try to imitate the words? + * + Bicara dan bahasa + Language + +
+ + +
+
+
+
+
+ + 10. Tanpa bantuan, apakah anak dapat mempertemukan dua kubus kecil yang ia pegang? Kerincingan bertangkai dan tutup panci tidak ikut dinilai + 10. Is the baby able to stack two small blocks which he/she holds? A handgripped rattle and a pot lip are not assessed + * + Gerak halus + Fine motor + +
+ + +
+
+
+ + + + + + +
+
+ + Konseling stimulasi bagi ibu: + Stimulation consultation for the mother + +
+ + +
+
+
+ + + +
+
+ + Apakah anak dirujuk? + Is the child referred to other facility? + +
+ + +
+
+
+ +
+
+ + Ada surat rujukan? + Referral letter + +
+ + +
+
+
+ + +
diff --git a/opensrp-sdidtk/src/main/assets/www/form/kpsp_bayi_1thn/form_definition.json b/opensrp-sdidtk/src/main/assets/www/form/kpsp_bayi_1thn/form_definition.json new file mode 100644 index 000000000..b06a4e9be --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/kpsp_bayi_1thn/form_definition.json @@ -0,0 +1,254 @@ +{ + "form_data_definition_version": "1", + "form": { + "bind_type": "anak", + "default_bind_path": "/model/instance/kpsp_bayi_1thn/", + "fields": [ + { + "name": "id", + "shouldLoadValue": true + }, + { + "name": "umur", + "bind": "/model/instance/kpsp_bayi_1thn/umur", + "shouldLoadValue": true + }, + { + "name": "kpsp_test_date1", + "bind": "/model/instance/kpsp_bayi_1thn/kpsp_test_date1" + }, + { + "name": "anamnesis", + "bind": "/model/instance/kpsp_bayi_1thn/anamnesis" + }, + { + "name": "keluhan", + "bind": "/model/instance/kpsp_bayi_1thn/keluhan" + }, + { + "name": "masalah_tumbang", + "bind": "/model/instance/kpsp_bayi_1thn/masalah_tumbang" + }, + { + "name": "kpsp_1thn", + "bind": "/model/instance/kpsp_bayi_1thn/kpsp_1thn" + }, + { + "name": "_3bln_gerakan_lengan", + "bind": "/model/instance/kpsp_bayi_1thn/_3bln_gerakan_lengan" + }, + { + "name": "_3bln_menatap_wajah", + "bind": "/model/instance/kpsp_bayi_1thn/_3bln_menatap_wajah" + }, + { + "name": "_3bln_mengeluarkan_suara", + "bind": "/model/instance/kpsp_bayi_1thn/_3bln_mengeluarkan_suara" + }, + { + "name": "_3bln_mengikuti_gerakan1", + "bind": "/model/instance/kpsp_bayi_1thn/_3bln_mengikuti_gerakan1" + }, + { + "name": "_3bln_mengikuti_gerakan2", + "bind": "/model/instance/kpsp_bayi_1thn/_3bln_mengikuti_gerakan2" + }, + { + "name": "_3bln_tersenyum_kembali", + "bind": "/model/instance/kpsp_bayi_1thn/_3bln_tersenyum_kembali" + }, + { + "name": "_3bln_mengangkat_kepala1", + "bind": "/model/instance/kpsp_bayi_1thn/_3bln_mengangkat_kepala1" + }, + { + "name": "_3bln_mengangkat_kepala2", + "bind": "/model/instance/kpsp_bayi_1thn/_3bln_mengangkat_kepala2" + }, + { + "name": "_3bln_mengangkat_kepala3", + "bind": "/model/instance/kpsp_bayi_1thn/_3bln_mengangkat_kepala3" + }, + { + "name": "_3bln_tertawa", + "bind": "/model/instance/kpsp_bayi_1thn/_3bln_tertawa" + }, + { + "name": "_6bln_gerakan_kepala", + "bind": "/model/instance/kpsp_bayi_1thn/_6bln_gerakan_kepala" + }, + { + "name": "_6bln_menahan_kepala", + "bind": "/model/instance/kpsp_bayi_1thn/_6bln_menahan_kepala" + }, + { + "name": "_6bln_menggenggam_pensil", + "bind": "/model/instance/kpsp_bayi_1thn/_6bln_menggenggam_pensil" + }, + { + "name": "_6bln_mengangkat_dada", + "bind": "/model/instance/kpsp_bayi_1thn/_6bln_mengangkat_dada" + }, + { + "name": "_6bln_suara_gembira", + "bind": "/model/instance/kpsp_bayi_1thn/_6bln_suara_gembira" + }, + { + "name": "_6bln_berbalik", + "bind": "/model/instance/kpsp_bayi_1thn/_6bln_berbalik" + }, + { + "name": "_6bln_tersenyum", + "bind": "/model/instance/kpsp_bayi_1thn/_6bln_tersenyum" + }, + { + "name": "_6bln_mengarahkan_mata", + "bind": "/model/instance/kpsp_bayi_1thn/_6bln_mengarahkan_mata" + }, + { + "name": "_6bln_meraih_mainan", + "bind": "/model/instance/kpsp_bayi_1thn/_6bln_meraih_mainan" + }, + { + "name": "_6bln_menahan_leher", + "bind": "/model/instance/kpsp_bayi_1thn/_6bln_menahan_leher" + }, + { + "name": "_9bln_menahan_leher", + "bind": "/model/instance/kpsp_bayi_1thn/_9bln_menahan_leher" + }, + { + "name": "_9bln_memindahkan_mainan", + "bind": "/model/instance/kpsp_bayi_1thn/_9bln_memindahkan_mainan" + }, + { + "name": "_9bln_mencari_objek", + "bind": "/model/instance/kpsp_bayi_1thn/_9bln_mencari_objek" + }, + { + "name": "_9bln_memegang_benda", + "bind": "/model/instance/kpsp_bayi_1thn/_9bln_memegang_benda" + }, + { + "name": "_9bln_berdiri_bertumpu", + "bind": "/model/instance/kpsp_bayi_1thn/_9bln_berdiri_bertumpu" + }, + { + "name": "_9bln_memungut_benda", + "bind": "/model/instance/kpsp_bayi_1thn/_9bln_memungut_benda" + }, + { + "name": "_9bln_duduk_sendiri", + "bind": "/model/instance/kpsp_bayi_1thn/_9bln_duduk_sendiri" + }, + { + "name": "_9bln_makan_kue_sendiri", + "bind": "/model/instance/kpsp_bayi_1thn/_9bln_makan_kue_sendiri" + }, + { + "name": "_9bln_menoleh", + "bind": "/model/instance/kpsp_bayi_1thn/_9bln_menoleh" + }, + { + "name": "_9bln_meraih_mainan", + "bind": "/model/instance/kpsp_bayi_1thn/_9bln_meraih_mainan" + }, + { + "name": "_12bln_mencari_orang_bersembunyi", + "bind": "/model/instance/kpsp_bayi_1thn/_12bln_mencari_orang_bersembunyi" + }, + { + "name": "_12bln_menggenggam_benda", + "bind": "/model/instance/kpsp_bayi_1thn/_12bln_menggenggam_benda" + }, + { + "name": "_12bln_berdiri_30detik", + "bind": "/model/instance/kpsp_bayi_1thn/_12bln_berdiri_30detik" + }, + { + "name": "_12bln_menyebut_suku_kata_sama", + "bind": "/model/instance/kpsp_bayi_1thn/_12bln_menyebut_suku_kata_sama" + }, + { + "name": "_12bln_berdiri_tanpa_bantuan", + "bind": "/model/instance/kpsp_bayi_1thn/_12bln_berdiri_tanpa_bantuan" + }, + { + "name": "_12bln_membedakan_orang", + "bind": "/model/instance/kpsp_bayi_1thn/_12bln_membedakan_orang" + }, + { + "name": "_12bln_memungut_dengan_jari", + "bind": "/model/instance/kpsp_bayi_1thn/_12bln_memungut_dengan_jari" + }, + { + "name": "_12bln_duduk_tanpa_bantuan", + "bind": "/model/instance/kpsp_bayi_1thn/_12bln_duduk_tanpa_bantuan" + }, + { + "name": "_12bln_meniru_kata", + "bind": "/model/instance/kpsp_bayi_1thn/_12bln_meniru_kata" + }, + { + "name": "_12bln_menyusun_benda", + "bind": "/model/instance/kpsp_bayi_1thn/_12bln_menyusun_benda" + }, + { + "name": "status_kembang1", + "bind": "/model/instance/kpsp_bayi_1thn/status_kembang1" + }, + { + "name": "status_meragukan", + "bind": "/model/instance/kpsp_bayi_1thn/status_meragukan" + }, + { + "name": "status_penyimpangan", + "bind": "/model/instance/kpsp_bayi_1thn/status_penyimpangan" + }, + { + "name": "kesimpulan", + "bind": "/model/instance/kpsp_bayi_1thn/kesimpulan" + }, + { + "name": "tindakan_intervensi", + "bind": "/model/instance/kpsp_bayi_1thn/tindakan_intervensi" + }, + { + "name": "konseling_stimulasi", + "bind": "/model/instance/kpsp_bayi_1thn/konseling_stimulasi" + }, + { + "name": "tindakan_lain", + "bind": "/model/instance/kpsp_bayi_1thn/tindakan_lain" + }, + { + "name": "rujukan", + "bind": "/model/instance/kpsp_bayi_1thn/rujukan" + }, + { + "name": "dirujuk_ke", + "bind": "/model/instance/kpsp_bayi_1thn/dirujuk_ke" + }, + { + "name": "surat_rujukan", + "bind": "/model/instance/kpsp_bayi_1thn/surat_rujukan" + }, + { + "name": "isOutOfArea", + "value": "false" + }, + { + "name": "isClosed", + "value": "false" + }, + { + "name": "reg_date", + "bind": "/model/instance/kpsp_bayi_1thn/today" + }, + { + "name": "registrationDate", + "bind": "/model/instance/kpsp_bayi_1thn/reg_date" + } + ] + } +} \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/kpsp_bayi_1thn/model.xml b/opensrp-sdidtk/src/main/assets/www/form/kpsp_bayi_1thn/model.xml new file mode 100644 index 000000000..63c461ea0 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/kpsp_bayi_1thn/model.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + <_3bln_gerakan_lengan/> + <_3bln_menatap_wajah/> + <_3bln_mengeluarkan_suara/> + <_3bln_mengikuti_gerakan1/> + <_3bln_mengikuti_gerakan2/> + <_3bln_tersenyum_kembali/> + <_3bln_mengangkat_kepala1/> + <_3bln_mengangkat_kepala2/> + <_3bln_mengangkat_kepala3/> + <_3bln_tertawa/> + <_6bln_gerakan_kepala/> + <_6bln_menahan_kepala/> + <_6bln_menggenggam_pensil/> + <_6bln_mengangkat_dada/> + <_6bln_suara_gembira/> + <_6bln_berbalik/> + <_6bln_tersenyum/> + <_6bln_mengarahkan_mata/> + <_6bln_meraih_mainan/> + <_6bln_menahan_leher/> + <_9bln_menahan_leher/> + <_9bln_memindahkan_mainan/> + <_9bln_mencari_objek/> + <_9bln_memegang_benda/> + <_9bln_berdiri_bertumpu/> + <_9bln_memungut_benda/> + <_9bln_duduk_sendiri/> + <_9bln_makan_kue_sendiri/> + <_9bln_menoleh/> + <_9bln_meraih_mainan/> + <_12bln_mencari_orang_bersembunyi/> + <_12bln_menggenggam_benda/> + <_12bln_berdiri_30detik/> + <_12bln_menyebut_suku_kata_sama/> + <_12bln_berdiri_tanpa_bantuan/> + <_12bln_membedakan_orang/> + <_12bln_memungut_dengan_jari/> + <_12bln_duduk_tanpa_bantuan/> + <_12bln_meniru_kata/> + <_12bln_menyusun_benda/> + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/masalah_mental_emosional/form.xml b/opensrp-sdidtk/src/main/assets/www/form/masalah_mental_emosional/form.xml new file mode 100644 index 000000000..72362e3c4 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/masalah_mental_emosional/form.xml @@ -0,0 +1,397 @@ + +
+ + +

Deteksi Dini Masalah Mental Emosional

+ + + +
+
+ + 1. Apakah anak Anda __seringkali terlihat marah__ tanpa sebab yang jelas (seperti banyak menangis, mudah tersinggung atau bereaksi berlebihan terhadap hal-hal yang sudah biasa dihadapinya) + 1. Does your child often __look angry__ for no apparent reason (such as crying a lot, being irritable or overreacting to common things) + +
+ + +
+
+
+
+
+ + 2. Apakah anak Anda tampak menghindar dari teman-teman atau anggota keluarganya (seperti ingin merasa sendirian, menyendiri atau merasa sedih sepanjang waktu, kehilangan minat terhadap hal-hal yang biasa sangat dinikmati) + 2. Does your child often __shun from his/her friends__ or family members (like want to be alone, withdrawn, or feel sad all the time, lost interest in things he/she usually enjoyed) + +
+ + +
+
+
+
+
+ + 3. Apakah anak Anda terlihat __berperilaku merusak dan menentang__ terhadap lingkungan di sekitarnya? (seperti melanggar peraturan yang ada, mencuri, seringkali melakukan perbuatan yang berbahaya bagi dirinya, atau menyiksa binatang atau anak-anak lainnya) dan tampak tidak perduli dengan nasihat-nasihat yang sudah diberikan kepadanya? + 3. Does your child __behave destructively and oppose the surroundings__? (e.g. Violate the existing rules, steal, often does something harmful to him/herself, or torture animals or other children) and not seem to care the advice he/she received? + +
+ + +
+
+
+
+
+ + 4. Apakah anak Anda memperlihatkan adanya __perasaan ketakutan atau kecemasan yang berlebihan__ yang tidak dapat dijelaskan asalnya dan tidak sebanding dengan anak lain seusianya? + 4. Does your child show __unreasonable fear or anxiety excessively__ more than other children in his/her age? + +
+ + +
+
+
+
+
+ + 5. Apakah anak Anda mengalami keterbatasan oleh karena adanya __konsentasi yang buruk atau mudah teralih perhatiannya__, sehingga mengalami penurunan dalam aktivitas sehari-hari atau prestasi belajarnya? + 5. Does your child have limitation because of __poor concentration or being easily distracted__, that he/she experiences a deterioritation on daily activities or study performances? + +
+ + +
+
+
+
+
+ + 6. Apakah anak Anda menunjukkan __perilaku kebingung__ sehingga mengalami kesulitan dalam berkomunikasi dan membuat keputusan? + 6. Does your child __seem perplexed__ that he/she is unable to communicate and make decision properly? + +
+ + +
+
+
+
+
+ + 7. Apakah anak Anda menunjukkan adanya __perubahan pola tidur__? (seperti sulit tidur sepanjang waktu, terjaga sepanjang hari, sering terbangun di waktu tidur malam oleh karena mimpi buruk, mengigau) + 7. Does your child show any __changes in sleep pattern__? (such as difficult to sleep all the time, stay up all the night, often wake up at night because of nightmare, delirious) + +
+ + +
+
+
+
+
+ + 8. Apakah anak Anda mengalami __perubahan pola makan__? (seperti kehilangan nafsu makan, makan berlebihan atau tidak mau makan sama sekali) + 8. Does your child show any __dietary changes__? (such as loss of appetite, overeating or not eating at all) + +
+ + +
+
+
+
+
+ + 9. Apakah anak Anda seringkali __mengeluh sakit kepala, sakit perut, atau keluhan-keluhan fisik__ lainnya? + 9. Does you child often __complain of headaches, stomachaches, or other physical complaints__? + +
+ + +
+
+
+
+
+ + 10. Apakah anak Anda seringkali __mengeluh putus asa__ atau berkeinginan untuk mengakhiri hidupnya? + 10. Does your child often __complain of despair__ or want to end his/her life? + +
+ + +
+
+
+
+
+ + 11. Apakah anak Anda menunjukkan adanya __kemunduran perilaku__ atau kemampuan yang sudah dimilikinya? (seperti mengompol kembali, menghisap jempol, atau tidak mau berpisah dengan orangtua/pengasuhnya) + 11. Does your child show __deterioritation of behavior__ or ability? (e.g. Bedwetting, thumb-sucking, or being attached to his/her parents/caregivers) + +
+ + +
+
+
+
+
+ + 12. Apakah anak Anda melakukan __perbuatan yang berulang-ulang__ tanpa alasan yang jelas? + 12. Does your child __do things repetitively)__ for no apparent reason? + +
+ + +
+
+
+ +
+
+ + Hasil Tes Mental Emosional + Mental Emotional Assessment Result + +
+ + +
+
+
+ + +
+
+ + Konseling stimulasi bagi ibu: + Stimulation consultation for the mother + +
+ + +
+
+
+ +
+
+ + Apakah anak dirujuk? + Is the child referred to other facility? + +
+ + +
+
+
+ +
+
+ + Ada surat rujukan? + Referral letter + +
+ + +
+
+
+ + +
diff --git a/opensrp-sdidtk/src/main/assets/www/form/masalah_mental_emosional/form_definition.json b/opensrp-sdidtk/src/main/assets/www/form/masalah_mental_emosional/form_definition.json new file mode 100644 index 000000000..3da75f88b --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/masalah_mental_emosional/form_definition.json @@ -0,0 +1,122 @@ +{ + "form_data_definition_version": "1", + "form": { + "bind_type": "anak", + "default_bind_path": "/model/instance/masalah_mental_emosional/", + "fields": [ + { + "name": "id", + "shouldLoadValue": true + }, + { + "name": "umur", + "bind": "/model/instance/masalah_mental_emosional/umur", + "shouldLoadValue": true + }, + { + "name": "mental_test_date", + "bind": "/model/instance/masalah_mental_emosional/mental_test_date" + }, + { + "name": "mme_marah", + "bind": "/model/instance/masalah_mental_emosional/mme_marah" + }, + { + "name": "mme_menghindar", + "bind": "/model/instance/masalah_mental_emosional/mme_menghindar" + }, + { + "name": "mme_merusak", + "bind": "/model/instance/masalah_mental_emosional/mme_merusak" + }, + { + "name": "mme_takut_cemas", + "bind": "/model/instance/masalah_mental_emosional/mme_takut_cemas" + }, + { + "name": "mme_konsentrasi", + "bind": "/model/instance/masalah_mental_emosional/mme_konsentrasi" + }, + { + "name": "mme_bingung", + "bind": "/model/instance/masalah_mental_emosional/mme_bingung" + }, + { + "name": "mme_pola_tidur", + "bind": "/model/instance/masalah_mental_emosional/mme_pola_tidur" + }, + { + "name": "mme_pola_makan", + "bind": "/model/instance/masalah_mental_emosional/mme_pola_makan" + }, + { + "name": "mme_keluhan_fisik", + "bind": "/model/instance/masalah_mental_emosional/mme_keluhan_fisik" + }, + { + "name": "mme_putus_asa", + "bind": "/model/instance/masalah_mental_emosional/mme_putus_asa" + }, + { + "name": "mme_kemunduran_perilaku", + "bind": "/model/instance/masalah_mental_emosional/mme_kemunduran_perilaku" + }, + { + "name": "mme_berulang_ulang", + "bind": "/model/instance/masalah_mental_emosional/mme_berulang_ulang" + }, + { + "name": "hasil_mental_emosional", + "bind": "/model/instance/masalah_mental_emosional/hasil_mental_emosional" + }, + { + "name": "mental_emosional", + "bind": "/model/instance/masalah_mental_emosional/mental_emosional" + }, + { + "name": "kesimpulan", + "bind": "/model/instance/masalah_mental_emosional/kesimpulan" + }, + { + "name": "tindakan_intervensi", + "bind": "/model/instance/masalah_mental_emosional/tindakan_intervensi" + }, + { + "name": "konseling_stimulasi", + "bind": "/model/instance/masalah_mental_emosional/konseling_stimulasi" + }, + { + "name": "tindakan_lain", + "bind": "/model/instance/masalah_mental_emosional/tindakan_lain" + }, + { + "name": "rujukan", + "bind": "/model/instance/masalah_mental_emosional/rujukan" + }, + { + "name": "dirujuk_ke", + "bind": "/model/instance/masalah_mental_emosional/dirujuk_ke" + }, + { + "name": "surat_rujukan", + "bind": "/model/instance/masalah_mental_emosional/surat_rujukan" + }, + { + "name": "isOutOfArea", + "value": "false" + }, + { + "name": "isClosed", + "value": "false" + }, + { + "name": "reg_date", + "bind": "/model/instance/masalah_mental_emosional/today" + }, + { + "name": "registrationDate", + "bind": "/model/instance/masalah_mental_emosional/reg_date" + } + ] + } +} \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/masalah_mental_emosional/model.xml b/opensrp-sdidtk/src/main/assets/www/form/masalah_mental_emosional/model.xml new file mode 100644 index 000000000..c1b01f4e8 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/masalah_mental_emosional/model.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/new_household_registration/form.xml b/opensrp-sdidtk/src/main/assets/www/form/new_household_registration/form.xml new file mode 100644 index 000000000..73e2e6ed2 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/new_household_registration/form.xml @@ -0,0 +1,31 @@ + +
+

নতুন খানা নিবন্ধন ফর্ম

+ + + + + + + +
খানা প্রধানের লিঙ্গHead of Household Gender* +
+ +
এই খানায় কি ১৫ থেকে ৪৯ বছর বয়সের কোন বিবাহিত মহিলা আছেন?Are there any married women between the ages of 15 - 49 live in this household?* +
+

মহিলার তথ্যঃNew Woman Registration

আপনার মাসিক কি চালু আছে?Are you still menstruating?* +
আপনি কি বর্তমানে আপনার স্বামীর সাথে বসবাস করছেন?Are you currently living with your husband?* +
আপনার স্বামী কি জীবিত আছেন?Is the husband alive?* +
আপনার স্বামী কি স্থায়ী জন্মনিয়ন্ত্রন পদ্ধতি গ্রহণ করেছেন?Is the husband sterilized?* +
নিচের কোন পরিচয় পত্রটি মহিলার কাছে আছে?Which of the following IDs does the woman have?*প্রযোজ্য সবগুলো উত্তর নির্বাচন করুনSelect all that apply. +
+
+
+
+ +
XML to HTML transformation for form took 0.09 secondsThis validation is yet not functional.
diff --git a/opensrp-sdidtk/src/main/assets/www/form/new_household_registration/form_definition.json b/opensrp-sdidtk/src/main/assets/www/form/new_household_registration/form_definition.json new file mode 100644 index 000000000..39cda5c80 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/new_household_registration/form_definition.json @@ -0,0 +1,154 @@ +{ + "form_data_definition_version": "15", + "form": { + "default_bind_path": "/model/instance/FWNewHH", + "bind_type": "ibu", + "fields": [ + { + "name": "id", + "shouldLoadValue": true + }, + { + "name": "existing_location", + "bind": "/model/instance/FWNewHH/existing_location" + }, + { + "name": "existing_Country", + "bind": "/model/instance/FWNewHH/existing_Country" + }, + { + "name": "existing_Division", + "bind": "/model/instance/FWNewHH/existing_Division" + }, + { + "name": "existing_District", + "bind": "/model/instance/FWNewHH/existing_District" + }, + { + "name": "existing_Upazilla", + "bind": "/model/instance/FWNewHH/existing_Upazilla" + }, + { + "name": "existing_Union", + "bind": "/model/instance/FWNewHH/existing_Union" + }, + { + "name": "existing_Ward", + "bind": "/model/instance/FWNewHH/existing_Ward" + }, + { + "name": "existing_Subunit", + "bind": "/model/instance/FWNewHH/existing_Subunit" + }, + { + "name": "existing_Mauzapara", + "bind": "/model/instance/FWNewHH/existing_Mauzapara" + }, + { + "name": "form_name", + "bind": "/model/instance/FWNewHH/form_name" + }, + { + "name": "today", + "bind": "/model/instance/FWNewHH/today" + }, + { + "name": "start", + "bind": "/model/instance/FWNewHH/start" + }, + { + "name": "end", + "bind": "/model/instance/FWNewHH/end" + }, + { + "name": "FWNHREGDATE", + "bind": "/model/instance/FWNewHH/FWNHREGDATE" + }, + { + "name": "FWGOBHHID", + "bind": "/model/instance/FWNewHH/FWGOBHHID" + }, + { + "name": "FWJIVHHID", + "bind": "/model/instance/FWNewHH/FWJIVHHID" + }, + { + "name": "FWCOUNTRY", + "bind": "/model/instance/FWNewHH/FWCOUNTRY" + }, + { + "name": "FWDIVISION", + "bind": "/model/instance/FWNewHH/FWDIVISION" + }, + { + "name": "FWDISTRICT", + "bind": "/model/instance/FWNewHH/FWDISTRICT" + }, + { + "name": "FWUPAZILLA", + "bind": "/model/instance/FWNewHH/FWUPAZILLA" + }, + { + "name": "FWUNION", + "bind": "/model/instance/FWNewHH/FWUNION" + }, + { + "name": "FWWARD", + "bind": "/model/instance/FWNewHH/FWWARD" + }, + { + "name": "FWSUBUNIT", + "bind": "/model/instance/FWNewHH/FWSUBUNIT" + }, + { + "name": "FWMAUZA_PARA", + "bind": "/model/instance/FWNewHH/FWMAUZA_PARA" + }, + { + "name": "FWNHHHGPS", + "bind": "/model/instance/FWNewHH/FWNHHHGPS" + }, + { + "name": "FWHOHFNAME", + "bind": "/model/instance/FWNewHH/FWHOHFNAME" + }, + { + "name": "FWHOHLNAME", + "bind": "/model/instance/FWNewHH/FWHOHLNAME" + }, + { + "name": "FWHOHBIRTHDATE", + "bind": "/model/instance/FWNewHH/FWHOHBIRTHDATE" + }, + { + "name": "FWHOHGENDER", + "bind": "/model/instance/FWNewHH/FWHOHGENDER" + }, + { + "name": "FWNHHMBRNUM", + "bind": "/model/instance/FWNewHH/FWNHHMBRNUM" + }, + { + "name": "FWNHHMWRA", + "bind": "/model/instance/FWNewHH/FWNHHMWRA" + }, + { + "name": "ELCO", + "bind": "/model/instance/FWNewHH/ELCO" + }, + { + "name": "current_formStatus", + "bind": "/model/instance/FWNewHH/current_formStatus" + }, + { + "name": "user_type", + "bind": "/model/instance/FWNewHH/user_type" + }, + { + "name": "external_user_ID", + "bind": "/model/instance/FWNewHH/external_user_ID" + } + ] + + } +} \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/new_household_registration/model.xml b/opensrp-sdidtk/src/main/assets/www/form/new_household_registration/model.xml new file mode 100644 index 000000000..50f7fc991 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/new_household_registration/model.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/tes_daya_dengar/form.xml b/opensrp-sdidtk/src/main/assets/www/form/tes_daya_dengar/form.xml new file mode 100644 index 000000000..5a05094e0 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/tes_daya_dengar/form.xml @@ -0,0 +1,638 @@ + +
+ + +

Tes Daya Dengar

+ + + +
+
+ + Tes Daya Dengar + Hearing Test + +
+ + + + + + +
+
+
+
+
+ + 1. Pada waktu bayi tidur kemudian Anda berbicara atau membuat kegaduhan, apakah bayi akan bergerak atau terbangun dari tidurnya? + 1. When the baby is sleeping, then you talk or make some noises, does the baby move or wake up? + * + +
+ + +
+
+
+
+
+ + 2. Pada waktu bayi tidur terlentang dan Anda duduk di dekat kepala bayi pada posisi yang tidak terlihat oleh bayi, kemudian Anda bertepuk tangan dengan keras, apakah bayi terkejut atau mengerdipkan matanya atau menegangkan tubuh sambil mengangkat kaki tangannya ke atas? + 2. When the baby is sleeping on his/her back and you sit next to the baby's head in a position that is unvisible to the baby, then you clap loudly, is the baby surprised or winking or stretching up his/her hands and legs? + * + +
+ + +
+
+
+
+
+ + 3. Apabila ada suara nyaring (misal suara batuk, salak anjing, piring jatuh ke lantai dan lain-lainnya), apakah bayi terkejut atau terlompat? + 3. If there is a loud voice (e.g. A cough, dog's bark, a plate fell to the floor, etc.), is the baby surprised or jumped up? + * + +
+ + +
+
+
+
+
+ + 1. Pada waktu bayi tidur kemudian Anda berbicara atau membuat kegaduhan, apakah bayi akan bergerak atau terbangun dari tidurnya? + 1. When the baby is sleeping, then you talk or make some noises, does the baby move or wake up? + * + +
+ + +
+
+
+
+
+ + 2. Pada waktu bayi tidur terlentang dan Anda duduk di dekat kepala bayi pada posisi yang tidak terlihat oleh bayi, kemudian Anda bertepuk tangan dengan keras, apakah bayi terkejut atau mengerdipkan matanya atau menegangkan tubuh sambil mengangkat kaki tangannya ke atas? + 2. When the baby is sleeping on his/her back and you sit next to the baby's head in a position that is unvisible to the baby, then you clap loudly, is the baby surprised or winking or stretching up his/her hands and legs? + * + +
+ + +
+
+
+
+
+ + 3. Apabila ada suara nyaring (misal suara batuk, salak anjing, piring jatuh ke lantai dan lain-lainnya), apakah bayi terkejut atau terlompat? + 3. If there is a loud voice (e.g. A cough, dog's bark, a plate fell to the floor, etc.), is the baby surprised or jumped up? + * + +
+ + +
+
+
+
+
+ + 4. Anda berada di sisi yang tidak terlihat oleh bayi, sebut namanya atau bunyikan sesuatu, apakah bayi memalingkan kepala mencari sumber suara? + 4. You are in a position unvisible to the baby, call his/her name or make a noise, does the child turn his/her head looking for the source of the sound? + * + +
+ + +
+
+
+
+
+ + 1. Pada waktu bayi tidur kemudian Anda berbicara atau membuat kegaduhan, apakah bayi akan bergerak atau terbangun dari tidurnya? + 1. When the baby is sleeping, then you talk or make some noises, does the baby move or wake up? + * + +
+ + +
+
+
+
+
+ + 2. Pada waktu bayi tidur terlentang dan Anda duduk di dekat kepala bayi pada posisi yang tidak terlihat oleh bayi, kemudian Anda bertepuk tangan dengan keras, apakah bayi terkejut atau mengerdipkan matanya atau menegangkan tubuh sambil mengangkat kaki tangannya ke atas? + 2. When the baby is sleeping on his/her back and you sit next to the baby's head in a position that is unvisible to the baby, then you clap loudly, is the baby surprised or winking or stretching up his/her hands and legs? + * + +
+ + +
+
+
+
+
+ + 3. Apabila ada suara nyaring (misal suara batuk, salak anjing, piring jatuh ke lantai dan lain-lainnya), apakah bayi terkejut atau terlompat? + 3. If there is a loud voice (e.g. A cough, dog's bark, a plate fell to the floor, etc.), is the baby surprised or jumped up? + * + +
+ + +
+
+
+
+
+ + 4. Anda berada di samping atau belakang bayi dan tidak terlihat oleh bayi, sebut namanya atau bunyikan sesuatu, apakah bayi langsung memalingkan kepala ke arah sumber suara tersebut di samping atau belakangnya? + 4. You are beside or behind the baby and unvisible to the baby, call his/her name or make a noise, does the baby turn his/her head toward the source of the sound, beside or behind him/her? + * + +
+ + +
+
+
+
+
+ + 1. Pada waktu bayi tidur kemudian Anda berbicara atau membuat kegaduhan, apakah bayi akan bergerak atau terbangun dari tidurnya? + 1. When the baby is sleeping, then you talk or make some noises, does the baby move or wake up? + * + +
+ + +
+
+
+
+
+ + 2. Pada waktu bayi tidur terlentang dan Anda duduk di dekat kepala bayi pada posisi yang tidak terlihat oleh bayi, kemudian Anda bertepuk tangan dengan keras, apakah bayi terkejut atau mengerdipkan matanya atau menegangkan tubuh sambil mengangkat kaki tangannya ke atas? + 2. When the baby is sleeping on his/her back and you sit next to the baby's head in a position that is unvisible to the baby, then you clap loudly, is the baby surprised or winking or stretching up his/her hands and legs? + * + +
+ + +
+
+
+
+
+ + 3. Apabila ada suara nyaring (misal suara batuk, salak anjing, piring jatuh ke lantai dan lain-lainnya), apakah bayi terkejut atau terlompat? + 3. If there is a loud voice (e.g. A cough, dog's bark, a plate fell to the floor, etc.), is the baby surprised or jumped up? + * + +
+ + +
+
+
+
+
+ + 4. Tanpa terlihat oleh anak, buat suara yang menarik perhatian anak, apakah anak langsung mengetahui posisi Anda sebagai sumber suara yang berpindah-pindah? + 4. Unvisible to the child, make a noise that can attract child's attention, is the child able to locate your position as the source of the sound moves around? + * + +
+ + +
+
+
+
+
+ + 5. Ucapkan kata-kata yang mudah dan sederhana, dapatkah anak menirukan Anda? + 5. Say a few simple and easy words, does the child able to imitate you? + * + +
+ + +
+
+
+
+
+ + 1. Tutup mulut Anda dengan buku/kertas, tanpa melihat gerakan bibir Anda, perintahkan pada anak: "Pegang matamu", "Pegang kakimu". Apakah anak memegang mata dan kakinya dengan benar? + 1. Cover your mouth with a book/paper, without seeing your lip movements, tell the child: "Touch your eye", "Touch your foot". Does the child touch his/her eye and foot correctly? + * + +
+ + +
+
+
+
+
+ + 2. Pilih gambar dari majalah/buku bergambar. Tutup mulut Anda dengan buku/kertas, tanpa melihat gerakan bibir Anda, perintahkan pada anak: "Tunjukkan gambar kucing (atau anjing, kuda, mobil, orang, rumah, bunga, dan sebagainya)?" Dapatkah anak menunjukkan gambar yang dimaksud dengan benar? + 2. Choose a picture from a magazine/picture book. Cover your mouth with a book/paper, without seeing your lip movements, tell the child: "Show me a picture of a cat (or dog, horse, car, people, house, flower, etc.)?" Is the child able to show the picture correctly? + * + +
+ + +
+
+
+
+
+ + 3. Tutup mulut Anda dengan buku/kertas, tanpa melihat gerakan bibir Anda, perintahkan anak untuk mengerjakan sesuatu seperti: "Berikan boneka itu kepada saya", "Taruh kubus-kubus ini di atas meja/kursi", dan sebagainya. Apakah anak dapat mengerjakan perintah tersebut dengan benar? + 3. Cover your mouth with a book/paper, without seeing your lip movements, tell the child to do something such as: "Give me the doll", "Put these bricks on the desk/chair", etc. Does the child do the instructions correctly? + * + +
+ + +
+
+
+
+
+ + 1. Perlihatkan benda-benda yang ada di sekeliling anak seperti sendok, cangkir, bola, bunga, dan sebagainya. Suruh anak menyebutkan nama benda-benda tersebut. Apakah anak dapat menyebutkan nama benda-benda tersebut dengan benar? + 1. Show the objects around the child such as spoons, cups, balls, flowers, etc. Ask the chid to name the objects. Is the child able to name the objects correctly? + * + +
+ + +
+
+
+
+
+ + 2. Suruh anak duduk, Anda duduk dalam jarak 3 meter di depan anak. Suruh anak mengulangi angka-angka yang telah Anda ucapkan: "Empat", "Satu", "Delapan" atau menirukan dengan menggunakan jari tangannya. Kemudian tutup mulut Anda dengan buku/kertas, ucapkan 4 angka yang berlainan. Apakah anak dapat mengulangi atau menirukan ucapan Anda dengan menggunakan jari tangannya? (Anda dapat mengulanginya dengan suara yang lebih keras) + 2. Have the child sit, while you sit within 3 meters in front of the child. Ask the child to repeat numbers you have mentioned: "Four", "One", "Eight" or mimic them using his/her fingers. Then cover your mouth with a book/paper, say 4 different numbers. Is the child able to repeat or mimic your words with fingers? (You can repeat the words with a louder voice) + * + +
+ + +
+
+
+ +
+
+ + Hasil Tes Daya Dengar + Hearing Assessment Result + +
+ + +
+
+
+ + +
+
+ + Konseling stimulasi bagi ibu: + Stimulation consultation for the mother + +
+ + +
+
+
+ +
+
+ + Apakah anak dirujuk? + Is the child referred to other facility? + +
+ + +
+
+
+ +
+
+ + Ada surat rujukan? + Referral letter + +
+ + +
+
+
+ + +
\ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/tes_daya_dengar/form_definition.json b/opensrp-sdidtk/src/main/assets/www/form/tes_daya_dengar/form_definition.json new file mode 100644 index 000000000..0b5032d5d --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/tes_daya_dengar/form_definition.json @@ -0,0 +1,162 @@ +{ + "form_data_definition_version": "1", + "form": { + "bind_type": "anak", + "default_bind_path": "/model/instance/tes_daya_dengar/", + "fields": [ + { + "name": "id", + "shouldLoadValue": true + }, + { + "name": "umur", + "bind": "/model/instance/tes_daya_dengar/umur", + "shouldLoadValue": true + }, + { + "name": "hear_test_date", + "bind": "/model/instance/tes_daya_dengar/hear_test_date" + }, + { + "name": "tdd", + "bind": "/model/instance/tes_daya_dengar/tdd" + }, + { + "name": "tdd_0-6bln1", + "bind": "/model/instance/tes_daya_dengar/tdd_0-6bln1" + }, + { + "name": "tdd_0-6bln2", + "bind": "/model/instance/tes_daya_dengar/tdd_0-6bln2" + }, + { + "name": "tdd_0-6bln3", + "bind": "/model/instance/tes_daya_dengar/tdd_0-6bln3" + }, + { + "name": "tdd_6-9bln1", + "bind": "/model/instance/tes_daya_dengar/tdd_6-9bln1" + }, + { + "name": "tdd_6-9bln2", + "bind": "/model/instance/tes_daya_dengar/tdd_6-9bln2" + }, + { + "name": "tdd_6-9bln3", + "bind": "/model/instance/tes_daya_dengar/tdd_6-9bln3" + }, + { + "name": "tdd_6-9bln4", + "bind": "/model/instance/tes_daya_dengar/tdd_6-9bln4" + }, + { + "name": "tdd_9-12bln1", + "bind": "/model/instance/tes_daya_dengar/tdd_9-12bln1" + }, + { + "name": "tdd_9-12bln2", + "bind": "/model/instance/tes_daya_dengar/tdd_9-12bln2" + }, + { + "name": "tdd_9-12bln3", + "bind": "/model/instance/tes_daya_dengar/tdd_9-12bln3" + }, + { + "name": "tdd_9-12bln4", + "bind": "/model/instance/tes_daya_dengar/tdd_9-12bln4" + }, + { + "name": "tdd_12-24bln1", + "bind": "/model/instance/tes_daya_dengar/tdd_12-24bln1" + }, + { + "name": "tdd_12-24bln2", + "bind": "/model/instance/tes_daya_dengar/tdd_12-24bln2" + }, + { + "name": "tdd_12-24bln3", + "bind": "/model/instance/tes_daya_dengar/tdd_12-24bln3" + }, + { + "name": "tdd_12-24bln4", + "bind": "/model/instance/tes_daya_dengar/tdd_12-24bln4" + }, + { + "name": "tdd_12-24bln5", + "bind": "/model/instance/tes_daya_dengar/tdd_12-24bln5" + }, + { + "name": "tdd_2-3thn1", + "bind": "/model/instance/tes_daya_dengar/tdd_2-3thn1" + }, + { + "name": "tdd_2-3thn2", + "bind": "/model/instance/tes_daya_dengar/tdd_2-3thn2" + }, + { + "name": "tdd_2-3thn3", + "bind": "/model/instance/tes_daya_dengar/tdd_2-3thn3" + }, + { + "name": "tdd_lebih_dari_3thn1", + "bind": "/model/instance/tes_daya_dengar/tdd_lebih_dari_3thn1" + }, + { + "name": "tdd_lebih_dari_3thn2", + "bind": "/model/instance/tes_daya_dengar/tdd_lebih_dari_3thn2" + }, + { + "name": "hasil_daya_dengar", + "bind": "/model/instance/tes_daya_dengar/hasil_daya_dengar" + }, + { + "name": "daya_dengar", + "bind": "/model/instance/tes_daya_dengar/daya_dengar" + }, + { + "name": "kesimpulan", + "bind": "/model/instance/tes_daya_dengar/kesimpulan" + }, + { + "name": "tindakan_intervensi", + "bind": "/model/instance/tes_daya_dengar/tindakan_intervensi" + }, + { + "name": "konseling_stimulasi", + "bind": "/model/instance/tes_daya_dengar/konseling_stimulasi" + }, + { + "name": "tindakan_lain", + "bind": "/model/instance/tes_daya_dengar/tindakan_lain" + }, + { + "name": "rujukan", + "bind": "/model/instance/tes_daya_dengar/rujukan" + }, + { + "name": "dirujuk_ke", + "bind": "/model/instance/tes_daya_dengar/dirujuk_ke" + }, + { + "name": "surat_rujukan", + "bind": "/model/instance/tes_daya_dengar/surat_rujukan" + }, + { + "name": "isOutOfArea", + "value": "false" + }, + { + "name": "isClosed", + "value": "false" + }, + { + "name": "reg_date", + "bind": "/model/instance/tes_daya_dengar/today" + }, + { + "name": "registrationDate", + "bind": "/model/instance/tes_daya_dengar/reg_date" + } + ] + } +} \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/tes_daya_dengar/model.xml b/opensrp-sdidtk/src/main/assets/www/form/tes_daya_dengar/model.xml new file mode 100644 index 000000000..3df3fa684 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/tes_daya_dengar/model.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/tes_daya_lihat/form.xml b/opensrp-sdidtk/src/main/assets/www/form/tes_daya_lihat/form.xml new file mode 100644 index 000000000..01c5018e9 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/tes_daya_lihat/form.xml @@ -0,0 +1,152 @@ + +
+ + +

Tes Daya Lihat

+ + + +
+
+ + Hasil Tes Daya Lihat + Visual Assessment Result + +
+ + +
+
+
+ + +
+
+ + Konseling stimulasi bagi ibu: + Stimulation consultation for the mother + +
+ + +
+
+
+ +
+
+ + Apakah anak dirujuk? + Is the child referred to other facility? + +
+ + +
+
+
+ +
+
+ + Ada surat rujukan? + Referral letter + +
+ + +
+
+
+ + +
diff --git a/opensrp-sdidtk/src/main/assets/www/form/tes_daya_lihat/form_definition.json b/opensrp-sdidtk/src/main/assets/www/form/tes_daya_lihat/form_definition.json new file mode 100644 index 000000000..604034849 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/tes_daya_lihat/form_definition.json @@ -0,0 +1,70 @@ +{ + "form_data_definition_version": "1", + "form": { + "bind_type": "anak", + "default_bind_path": "/model/instance/tes_daya_lihat/", + "fields": [ + { + "name": "id", + "shouldLoadValue": true + }, + { + "name": "umur", + "bind": "/model/instance/tes_daya_lihat/umur", + "shouldLoadValue": true + }, + { + "name": "sight_test_date", + "bind": "/model/instance/tes_daya_lihat/sight_test_date" + }, + { + "name": "daya_lihat", + "bind": "/model/instance/tes_daya_lihat/daya_lihat" + }, + { + "name": "kesimpulan", + "bind": "/model/instance/tes_daya_lihat/kesimpulan" + }, + { + "name": "tindakan_intervensi", + "bind": "/model/instance/tes_daya_lihat/tindakan_intervensi" + }, + { + "name": "konseling_stimulasi", + "bind": "/model/instance/tes_daya_lihat/konseling_stimulasi" + }, + { + "name": "tindakan_lain", + "bind": "/model/instance/tes_daya_lihat/tindakan_lain" + }, + { + "name": "rujukan", + "bind": "/model/instance/tes_daya_lihat/rujukan" + }, + { + "name": "dirujuk_ke", + "bind": "/model/instance/tes_daya_lihat/dirujuk_ke" + }, + { + "name": "surat_rujukan", + "bind": "/model/instance/tes_daya_lihat/surat_rujukan" + }, + { + "name": "isOutOfArea", + "value": "false" + }, + { + "name": "isClosed", + "value": "false" + }, + { + "name": "reg_date", + "bind": "/model/instance/tes_daya_lihat/today" + }, + { + "name": "registrationDate", + "bind": "/model/instance/tes_daya_lihat/reg_date" + } + ] + } +} \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/assets/www/form/tes_daya_lihat/model.xml b/opensrp-sdidtk/src/main/assets/www/form/tes_daya_lihat/model.xml new file mode 100644 index 000000000..178cebb55 --- /dev/null +++ b/opensrp-sdidtk/src/main/assets/www/form/tes_daya_lihat/model.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/LoginActivity.java b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/LoginActivity.java new file mode 100644 index 000000000..51d030835 --- /dev/null +++ b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/LoginActivity.java @@ -0,0 +1,350 @@ +package org.ei.opensrp.ddtk; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.os.Bundle; +import android.text.InputType; +import android.util.DisplayMetrics; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import org.ei.opensrp.Context; +import org.ei.opensrp.domain.LoginResponse; +import org.ei.opensrp.domain.Response; +import org.ei.opensrp.domain.ResponseStatus; +import org.ei.opensrp.event.Listener; +import org.ei.opensrp.repository.AllSharedPreferences; +import org.ei.opensrp.sync.DrishtiSyncScheduler; +import org.ei.opensrp.util.Log; +import org.ei.opensrp.view.BackgroundAction; +import org.ei.opensrp.view.LockingBackgroundTask; +import org.ei.opensrp.view.ProgressIndicator; +import org.ei.opensrp.view.activity.SettingsActivity; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Locale; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import static android.preference.PreferenceManager.getDefaultSharedPreferences; +import static android.view.inputmethod.InputMethodManager.HIDE_NOT_ALWAYS; +import static org.ei.opensrp.domain.LoginResponse.NO_INTERNET_CONNECTIVITY; +import static org.ei.opensrp.domain.LoginResponse.SUCCESS; +import static org.ei.opensrp.domain.LoginResponse.UNAUTHORIZED; +import static org.ei.opensrp.domain.LoginResponse.UNKNOWN_RESPONSE; +import static org.ei.opensrp.util.Log.logError; +import static org.ei.opensrp.util.Log.logVerbose; + +public class LoginActivity extends Activity { + private Context context; + private EditText userNameEditText; + private EditText passwordEditText; + private ProgressDialog progressDialog; + public static final String INDONESIA_LOCALE = "id"; + public static final String ENGLISH_LOCALE = "en"; + public static final String INDONESIA_LANGUAGE = "Bahasa"; + public static final String ENGLISH_LANGUAGE = "English"; + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + logVerbose("Initializing ..."); + try{ + AllSharedPreferences allSharedPreferences = new AllSharedPreferences(getDefaultSharedPreferences(this)); + String preferredLocale = allSharedPreferences.fetchLanguagePreference(); + Resources res = Context.getInstance().applicationContext().getResources(); + // Change locale settings in the app. + DisplayMetrics dm = res.getDisplayMetrics(); + android.content.res.Configuration conf = res.getConfiguration(); + conf.locale = new Locale(preferredLocale); + res.updateConfiguration(conf, dm); + }catch(Exception e){ + + } + setContentView(org.ei.opensrp.R.layout.login); + ImageView loginglogo = (ImageView)findViewById(R.id.login_logo); + loginglogo.setImageDrawable(getResources().getDrawable(R.mipmap.sdidtk_login_logo)); + context = Context.getInstance().updateApplicationContext(this.getApplicationContext()); + initializeLoginFields(); + initializeBuildDetails(); + setDoneActionHandlerOnPasswordField(); + initializeProgressDialog(); + getActionBar().setTitle(""); + getActionBar().setIcon(getResources().getDrawable(org.ei.opensrp.ddtk.R.mipmap.logo)); + getActionBar().setBackgroundDrawable(getResources().getDrawable(org.ei.opensrp.ddtk.R.color.action_bar_background)); + setLanguage(); + + } + @Override + public boolean onCreateOptionsMenu(Menu menu) + { + // Inflate the menu; this adds items to the action bar if it is present. + menu.add("Settings"); + return true; + } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if(item.getTitle().toString().equalsIgnoreCase("Settings")){ + startActivity(new Intent(this,SettingsActivity.class)); + return true; + } + return super.onOptionsItemSelected(item); + } + + private void initializeBuildDetails() { + TextView buildDetailsTextView = (TextView) findViewById(org.ei.opensrp.R.id.login_build); + try { + buildDetailsTextView.setText("Version " + getVersion() + ", Built on: " + getBuildDate()); + } catch (Exception e) { + logError("Error fetching build details: " + e); + } + } + + @Override + protected void onResume() { + super.onResume(); + + if (!context.IsUserLoggedOut()) { + goToHome(); + } + + fillUserIfExists(); + } + + public void login(final View view) { + hideKeyboard(); + view.setClickable(false); + + final String userName = userNameEditText.getText().toString(); + final String password = passwordEditText.getText().toString(); + + if (context.userService().hasARegisteredUser()) { + localLogin(view, userName, password); + } else { + remoteLogin(view, userName, password); + } + } + + private void initializeLoginFields() { + userNameEditText = ((EditText) findViewById(org.ei.opensrp.R.id.login_userNameText)); + userNameEditText.setRawInputType(InputType.TYPE_CLASS_TEXT); + passwordEditText = ((EditText) findViewById(org.ei.opensrp.R.id.login_passwordText)); + passwordEditText.setRawInputType(InputType.TYPE_CLASS_TEXT); + } + + private void setDoneActionHandlerOnPasswordField() { + passwordEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + login(findViewById(org.ei.opensrp.R.id.login_loginButton)); + } + return false; + } + }); + } + + private void initializeProgressDialog() { + progressDialog = new ProgressDialog(this); + progressDialog.setCancelable(false); + progressDialog.setTitle(getString(org.ei.opensrp.R.string.loggin_in_dialog_title)); + progressDialog.setMessage(getString(org.ei.opensrp.R.string.loggin_in_dialog_message)); + } + + private void localLogin(View view, String userName, String password) { + if (context.userService().isValidLocalLogin(userName, password)) { + localLoginWith(userName, password); + } else { + showErrorDialog(getString(org.ei.opensrp.R.string.login_failed_dialog_message)); + view.setClickable(true); + } + } + + private void remoteLogin(final View view, final String userName, final String password) { + tryRemoteLogin(userName, password, new Listener() { + public void onEvent(LoginResponse loginResponse) { + if (loginResponse == SUCCESS) { + remoteLoginWith(userName, password, loginResponse.payload()); + } else { + if (loginResponse == null) { + showErrorDialog("Login failed. Unknown reason. Try Again"); + } else { + if(loginResponse == NO_INTERNET_CONNECTIVITY){ + showErrorDialog(getResources().getString(R.string.no_internet_connectivity)); + }else if (loginResponse == UNKNOWN_RESPONSE){ + showErrorDialog(getResources().getString(R.string.unknown_response)); + }else if (loginResponse == UNAUTHORIZED){ + showErrorDialog(getResources().getString(R.string.unauthorized)); + } +// showErrorDialog(loginResponse.message()); + } + view.setClickable(true); + } + } + }); + } + + private void showErrorDialog(String message) { + AlertDialog dialog = new AlertDialog.Builder(this) + .setTitle(getString(R.string.login_failed_dialog_title)) + .setMessage(message) + .setPositiveButton("OK", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + } + }) + .create(); + dialog.show(); + } + + private void getLocation() { + tryGetLocation(new Listener>() { + @Override + public void onEvent(Response data) { + if (data.status() == ResponseStatus.success) { + context.userService().saveAnmLocation(data.payload()); + } + } + }); + } + + private void tryGetLocation(final Listener> afterGet) { + LockingBackgroundTask task = new LockingBackgroundTask(new ProgressIndicator() { + @Override + public void setVisible() { } + + @Override + public void setInvisible() { Log.logInfo("Successfully get location"); } + }); + + task.doActionInBackground(new BackgroundAction>() { + @Override + public Response actionToDoInBackgroundThread() { + return context.userService().getLocationInformation(); + } + + @Override + public void postExecuteInUIThread(Response result) { + afterGet.onEvent(result); + } + }); + } + + private void tryRemoteLogin(final String userName, final String password, final Listener afterLoginCheck) { + LockingBackgroundTask task = new LockingBackgroundTask(new ProgressIndicator() { + @Override + public void setVisible() { + progressDialog.show(); + } + + @Override + public void setInvisible() { + progressDialog.dismiss(); + } + }); + + task.doActionInBackground(new BackgroundAction() { + public LoginResponse actionToDoInBackgroundThread() { + return context.userService().isValidRemoteLogin(userName, password); + } + + public void postExecuteInUIThread(LoginResponse result) { + afterLoginCheck.onEvent(result); + } + }); + } + + private void fillUserIfExists() { + if (context.userService().hasARegisteredUser()) { + userNameEditText.setText(context.allSharedPreferences().fetchRegisteredANM()); + userNameEditText.setEnabled(false); + } + } + + private void hideKeyboard() { + InputMethodManager inputManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); + inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), HIDE_NOT_ALWAYS); + } + + private void localLoginWith(String userName, String password) { + context.userService().localLogin(userName, password); + goToHome(); + DrishtiSyncScheduler.startOnlyIfConnectedToNetwork(getApplicationContext()); + } + + private void remoteLoginWith(String userName, String password, String userInfo) { + context.userService().remoteLogin(userName, password, userInfo); + goToHome(); + DrishtiSyncScheduler.startOnlyIfConnectedToNetwork(getApplicationContext()); + } + + private void goToHome() { + startActivity(new Intent(this, NativeHomeActivity.class)); + finish(); + } + + private String getVersion() throws PackageManager.NameNotFoundException { + PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0); + return packageInfo.versionName; + } + + private String getBuildDate() throws PackageManager.NameNotFoundException, IOException { + ApplicationInfo applicationInfo = getPackageManager().getApplicationInfo(getPackageName(), 0); + ZipFile zf = new ZipFile(applicationInfo.sourceDir); + ZipEntry ze = zf.getEntry("classes.dex"); + return new SimpleDateFormat("dd MMM yyyy", Locale.getDefault()).format(new java.util.Date(ze.getTime())); + } + + public static void setLanguage(){ + AllSharedPreferences allSharedPreferences = new AllSharedPreferences(getDefaultSharedPreferences(Context.getInstance().applicationContext())); + String preferredLocale = allSharedPreferences.fetchLanguagePreference(); + Resources res = Context.getInstance().applicationContext().getResources(); + // Change locale settings in the app. + DisplayMetrics dm = res.getDisplayMetrics(); + android.content.res.Configuration conf = res.getConfiguration(); + conf.locale = new Locale(preferredLocale); + res.updateConfiguration(conf, dm); + + } + public static String switchLanguagePreference() { + AllSharedPreferences allSharedPreferences = new AllSharedPreferences(getDefaultSharedPreferences(Context.getInstance().applicationContext())); + + String preferredLocale = allSharedPreferences.fetchLanguagePreference(); + if (ENGLISH_LOCALE.equals(preferredLocale)) { + allSharedPreferences.saveLanguagePreference(INDONESIA_LOCALE); + Resources res = Context.getInstance().applicationContext().getResources(); + // Change locale settings in the app. + DisplayMetrics dm = res.getDisplayMetrics(); + android.content.res.Configuration conf = res.getConfiguration(); + conf.locale = new Locale(INDONESIA_LOCALE); + res.updateConfiguration(conf, dm); + return INDONESIA_LANGUAGE; + } else { + allSharedPreferences.saveLanguagePreference(ENGLISH_LOCALE); + Resources res = Context.getInstance().applicationContext().getResources(); + // Change locale settings in the app. + DisplayMetrics dm = res.getDisplayMetrics(); + android.content.res.Configuration conf = res.getConfiguration(); + conf.locale = new Locale(ENGLISH_LOCALE); + res.updateConfiguration(conf, dm); + return ENGLISH_LANGUAGE; + } + } + +} diff --git a/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/NativeHomeActivity.java b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/NativeHomeActivity.java new file mode 100644 index 000000000..a6bbd6f7a --- /dev/null +++ b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/NativeHomeActivity.java @@ -0,0 +1,261 @@ +package org.ei.opensrp.ddtk; + +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import org.ei.opensrp.Context; +import org.ei.opensrp.commonregistry.CommonPersonObjectController; +import org.ei.opensrp.event.Listener; + +import org.ei.opensrp.service.PendingFormSubmissionService; +import org.ei.opensrp.sync.SyncAfterFetchListener; +import org.ei.opensrp.sync.SyncProgressIndicator; +import org.ei.opensrp.sync.UpdateActionsTask; +import org.ei.opensrp.view.activity.SecuredActivity; +import org.ei.opensrp.view.contract.HomeContext; +import org.ei.opensrp.view.controller.NativeAfterANMDetailsFetchListener; +import org.ei.opensrp.view.controller.NativeUpdateANMDetailsTask; +import org.ei.opensrp.view.fragment.DisplayFormFragment; + +import static android.widget.Toast.LENGTH_SHORT; +import static java.lang.String.valueOf; +import static org.ei.opensrp.event.Event.ACTION_HANDLED; +import static org.ei.opensrp.event.Event.FORM_SUBMITTED; +import static org.ei.opensrp.event.Event.SYNC_COMPLETED; +import static org.ei.opensrp.event.Event.SYNC_STARTED; + +public class NativeHomeActivity extends SecuredActivity { + private MenuItem updateMenuItem; + private MenuItem remainingFormsToSyncMenuItem; + private PendingFormSubmissionService pendingFormSubmissionService; + + private Listener onSyncStartListener = new Listener() { + @Override + public void onEvent(Boolean data) { + if (updateMenuItem != null) { + updateMenuItem.setActionView(R.layout.progress); + } + } + }; + + private Listener onSyncCompleteListener = new Listener() { + @Override + public void onEvent(Boolean data) { + //#TODO: RemainingFormsToSyncCount cannot be updated from a back ground thread!! + updateRemainingFormsToSyncCount(); + if (updateMenuItem != null) { + updateMenuItem.setActionView(null); + } + updateRegisterCounts(); + } + }; + + private Listener onFormSubmittedListener = new Listener() { + @Override + public void onEvent(String instanceId) { + updateRegisterCounts(); + } + }; + + private Listener updateANMDetailsListener = new Listener() { + @Override + public void onEvent(String data) { + updateRegisterCounts(); + } + }; + + private TextView ecRegisterClientCountView; + + + @Override + protected void onCreation() { + //home dashboard + setContentView(R.layout.smart_registers_ddtk_home); + navigationController = new TestNavigationController(this,anmController); + setupViews(); + initialize(); + DisplayFormFragment.formInputErrorMessage = getResources().getString(R.string.forminputerror); + DisplayFormFragment.okMessage = getResources().getString(R.string.okforminputerror); + + + } + + private void setupViews() { + findViewById(R.id.btn_test_register).setOnClickListener(onRegisterStartListener); + // findViewById(R.id.btn_test2_register).setOnClickListener(onRegisterStartListener); + + findViewById(R.id.btn_reporting).setOnClickListener(onButtonsClickListener); + + ecRegisterClientCountView = (TextView) findViewById(R.id.txt_child_register_client_count); + + } + + private void initialize() { + pendingFormSubmissionService = context().pendingFormSubmissionService(); + SYNC_STARTED.addListener(onSyncStartListener); + SYNC_COMPLETED.addListener(onSyncCompleteListener); + FORM_SUBMITTED.addListener(onFormSubmittedListener); + ACTION_HANDLED.addListener(updateANMDetailsListener); + getSupportActionBar().setTitle(""); + getSupportActionBar().setIcon(getResources().getDrawable(org.ei.opensrp.ddtk.R.mipmap.logo)); + getSupportActionBar().setLogo(org.ei.opensrp.ddtk.R.mipmap.logo); + getSupportActionBar().setDisplayUseLogoEnabled(true); + getSupportActionBar().setDisplayShowHomeEnabled(true); + LoginActivity.setLanguage(); +// getActionBar().setBackgroundDrawable(getReso +// urces().getDrawable(R.color.action_bar_background)); + } + + @Override + protected void onResumption() { + LoginActivity.setLanguage(); + updateRegisterCounts(); + updateSyncIndicator(); + updateRemainingFormsToSyncCount(); + } + + private void updateRegisterCounts() { + NativeUpdateANMDetailsTask task = new NativeUpdateANMDetailsTask(Context.getInstance().anmController()); + task.fetch(new NativeAfterANMDetailsFetchListener() { + @Override + public void afterFetch(HomeContext anmDetails) { + updateRegisterCounts(anmDetails); + } + }); + } + + private void updateRegisterCounts(HomeContext homeContext) { + CommonPersonObjectController hhcontroller = new CommonPersonObjectController(context().allCommonsRepositoryobjects("anak"), + context().allBeneficiaries(), context().listCache(), + context().personObjectClientsCache(),"nama_anak","Jenis_kelamin","nama_ibu", CommonPersonObjectController.ByColumnAndByDetails.byDetails); + + + + ecRegisterClientCountView.setText(valueOf(hhcontroller.getClients().size())); + + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.menu_main, menu); + return true; + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + super.onPrepareOptionsMenu(menu); + updateMenuItem = menu.findItem(R.id.updateMenuItem); + remainingFormsToSyncMenuItem = menu.findItem(R.id.remainingFormsToSyncMenuItem); + + updateSyncIndicator(); + updateRemainingFormsToSyncCount(); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.updateMenuItem: + updateFromServer(); + return true; + case R.id.switchLanguageMenuItem: + String newLanguagePreference = LoginActivity.switchLanguagePreference(); + LoginActivity.setLanguage(); + Toast.makeText(this, "Language preference set to " + newLanguagePreference + ". Please restart the application.", LENGTH_SHORT).show(); + this.recreate(); + return true; + case R.id.help: + // startActivity(new Intent(this, tutorialCircleViewFlow.class)); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + public void updateFromServer() { + UpdateActionsTask updateActionsTask = new UpdateActionsTask( + this, context().actionService(), context().formSubmissionSyncService(), + new SyncProgressIndicator(), context().allFormVersionSyncService()); + updateActionsTask.updateFromServer(new SyncAfterFetchListener()); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + + SYNC_STARTED.removeListener(onSyncStartListener); + SYNC_COMPLETED.removeListener(onSyncCompleteListener); + FORM_SUBMITTED.removeListener(onFormSubmittedListener); + ACTION_HANDLED.removeListener(updateANMDetailsListener); + } + + private void updateSyncIndicator() { + if (updateMenuItem != null) { + if (context().allSharedPreferences().fetchIsSyncInProgress()) { + updateMenuItem.setActionView(R.layout.progress); + } else + updateMenuItem.setActionView(null); + } + } + + private void updateRemainingFormsToSyncCount() { + if (remainingFormsToSyncMenuItem == null) { + return; + } + + long size = pendingFormSubmissionService.pendingFormSubmissionCount(); + if (size > 0) { + remainingFormsToSyncMenuItem.setTitle(valueOf(size) + " " + getString(R.string.unsynced_forms_count_message)); + remainingFormsToSyncMenuItem.setVisible(true); + } else { + remainingFormsToSyncMenuItem.setVisible(false); + } + } + + private View.OnClickListener onRegisterStartListener = new View.OnClickListener() { + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.btn_test_register: + navigationController.startECSmartRegistry(); + break; + + // case R.id.btn_test2_register: + // navigationController.startANCSmartRegistry(); + // break; +/* + case R.id.btn_pnc_register: +// navigationController.startPNCSmartRegistry(); + break; + + case R.id.btn_child_register: +// navigationController.startChildSmartRegistry(); + break; + + case R.id.btn_fp_register: + // navigationController.startFPSmartRegistry(); + break; */ + } + } + }; + + private View.OnClickListener onButtonsClickListener = new View.OnClickListener() { + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.btn_reporting: +// navigationController.startReports(); + break; + + + } + } + }; +} diff --git a/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/TestNavigationController.java b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/TestNavigationController.java new file mode 100644 index 000000000..5dacc34e8 --- /dev/null +++ b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/TestNavigationController.java @@ -0,0 +1,44 @@ +package org.ei.opensrp.ddtk; + +import android.app.Activity; +import android.content.Intent; +import android.content.SharedPreferences; + + +import org.ei.opensrp.ddtk.ddtk.FormulirDdtkSmartRegisterActivity; +import org.ei.opensrp.view.controller.ANMController; + + +import static android.preference.PreferenceManager.getDefaultSharedPreferences; + +public class TestNavigationController extends org.ei.opensrp.view.controller.NavigationController { + private Activity activity; + private ANMController anmController; + + public TestNavigationController(Activity activity, ANMController anmController) { + super(activity,anmController); + this.activity = activity; + this.anmController = anmController; + } + @Override + public void startECSmartRegistry() { + activity.startActivity(new Intent(activity, FormulirDdtkSmartRegisterActivity.class)); + /// activity.startActivity(new Intent(activity, HouseHoldSmartRegisterActivity.class)); + SharedPreferences sharedPreferences = getDefaultSharedPreferences(this.activity); + + if(sharedPreferences.getBoolean("firstlauch",true)) { + sharedPreferences.edit().putBoolean("firstlauch",false).commit(); + // activity.startActivity(new Intent(activity, tutorialCircleViewFlow.class)); + } + + } + @Override + public void startFPSmartRegistry() { + // activity.startActivity(new Intent(activity, ElcoSmartRegisterActivity.class)); + } + @Override + public void startANCSmartRegistry() { + activity.startActivity(new Intent(activity, FormulirDdtkSmartRegisterActivity.class)); + } + +} diff --git a/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/application/TestApplication.java b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/application/TestApplication.java new file mode 100644 index 000000000..c128f92e8 --- /dev/null +++ b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/application/TestApplication.java @@ -0,0 +1,72 @@ +package org.ei.opensrp.ddtk.application; + +import android.content.Intent; +import android.content.res.Configuration; + +import org.ei.opensrp.Context; +import org.ei.opensrp.ddtk.LoginActivity; +import org.ei.opensrp.sync.DrishtiSyncScheduler; +import org.ei.opensrp.view.activity.DrishtiApplication; +import org.ei.opensrp.view.receiver.SyncBroadcastReceiver; +import static org.ei.opensrp.util.Log.logInfo; + +import java.util.Locale; + +/** + * Created by koros on 1/22/16. + */ + +public class TestApplication extends DrishtiApplication { + + @Override + public void onCreate() { + DrishtiSyncScheduler.setReceiverClass(SyncBroadcastReceiver.class); + super.onCreate(); + // ACRA.init(this); + + DrishtiSyncScheduler.setReceiverClass(SyncBroadcastReceiver.class); + + context = Context.getInstance(); + context.updateApplicationContext(getApplicationContext()); + applyUserLanguagePreference(); + cleanUpSyncState(); + } + + @Override + public void logoutCurrentUser(){ + Intent intent = new Intent(getApplicationContext(), LoginActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + getApplicationContext().startActivity(intent); + context.userService().logoutSession(); + } + + private void cleanUpSyncState() { + DrishtiSyncScheduler.stop(getApplicationContext()); + context.allSharedPreferences().saveIsSyncInProgress(false); + } + + @Override + public void onTerminate() { + super.onTerminate(); + logInfo("Application is terminating. Stopping Dristhi Sync scheduler and resetting isSyncInProgress setting."); + cleanUpSyncState(); + } + + private void applyUserLanguagePreference() { + Configuration config = getBaseContext().getResources().getConfiguration(); + + String lang = context.allSharedPreferences().fetchLanguagePreference(); + if (!"".equals(lang) && !config.locale.getLanguage().equals(lang)) { + locale = new Locale(lang); + updateConfiguration(config); + } + } + + private void updateConfiguration(Configuration config) { + config.locale = locale; + Locale.setDefault(locale); + getBaseContext().getResources().updateConfiguration(config, + getBaseContext().getResources().getDisplayMetrics()); + } + +} diff --git a/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/ddtk/ChildDetailActivity.java b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/ddtk/ChildDetailActivity.java new file mode 100644 index 000000000..ccf1a01dc --- /dev/null +++ b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/ddtk/ChildDetailActivity.java @@ -0,0 +1,274 @@ +package org.ei.opensrp.ddtk.ddtk; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.Bundle; +import android.os.Environment; +import android.provider.MediaStore; +import android.view.View; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.TextView; + +import org.ei.opensrp.Context; +import org.ei.opensrp.commonregistry.CommonPersonObjectClient; +import org.ei.opensrp.ddtk.R; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import util.ImageCache; +import util.ImageFetcher; + +/** + * Created by muhammad.ahmed@ihsinformatics.com on 20-Oct-15. + */ +public class ChildDetailActivity extends Activity { + + //image retrieving + private static final String TAG = "ImageGridFragment"; + private static final String IMAGE_CACHE_DIR = "thumbs"; + + private static int mImageThumbSize; + private static int mImageThumbSpacing; + private static String showbgm; + private static ImageFetcher mImageFetcher; + + + + + //image retrieving + + public static CommonPersonObjectClient childclient; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Context context = Context.getInstance(); + setContentView(R.layout.child_detail_activity); + + + //header + TextView anakName = (TextView) findViewById(R.id.detail_nama_anak); + TextView anakJenisKelamin = (TextView) findViewById(R.id.detail_jenis_kelamin); + TextView anakNamaIbu = (TextView) findViewById(R.id.detail_nama_ibu); + TextView anakUmur = (TextView) findViewById(R.id.detail_umur); + TextView anakBerat = (TextView) findViewById(R.id.childdetail_weight); + TextView anakTinggi = (TextView) findViewById(R.id.childdetail_height); + TextView anakLingKepala = (TextView) findViewById(R.id.childdetail_headcir); + TextView anakKpspDate1 = (TextView) findViewById(R.id.childdetail_kpsptestdate1); + TextView anakKpspResult1 = (TextView) findViewById(R.id.childdetail_kpsptestresult1); + TextView anakKpspDate2 = (TextView) findViewById(R.id.childdetail_kpsptestdate2); + TextView anakKpspResult2 = (TextView) findViewById(R.id.childdetail_kpsptestresult2); + TextView anakKpspDate3 = (TextView) findViewById(R.id.childdetail_kpsptestdate3); + TextView anakKpspResult3 = (TextView) findViewById(R.id.childdetail_kpsptestresult3); + TextView anakKpspDate4 = (TextView) findViewById(R.id.childdetail_kpsptestdate4); + TextView anakKpspResult4 = (TextView) findViewById(R.id.childdetail_kpsptestresult4); + TextView anakKpspDate5 = (TextView) findViewById(R.id.childdetail_kpsptestdate5); + TextView anakKpspResult5 = (TextView) findViewById(R.id.childdetail_kpsptestresult5); + TextView anakKpspDate6 = (TextView) findViewById(R.id.childdetail_kpsptestdate6); + TextView anakKpspResult6 = (TextView) findViewById(R.id.childdetail_kpsptestresult6); + TextView anakHearingDate = (TextView) findViewById(R.id.childdetail_hearingtestdate); + TextView anakHearingResult = (TextView) findViewById(R.id.childdetail_hearingtestresult); + TextView anakVisualDate = (TextView) findViewById(R.id.childdetail_visualtestdate); + TextView anakVisualResult = (TextView) findViewById(R.id.childdetail_visualtestresult); + TextView anakMentalDate = (TextView) findViewById(R.id.childdetail_mentaltestdate); + TextView anakMentalResult = (TextView) findViewById(R.id.childdetail_mentaltestresult); + TextView anakAutistDate = (TextView) findViewById(R.id.childdetail_autisttestdate); + TextView anakAutistResult = (TextView) findViewById(R.id.childdetail_autisttestresult); + TextView anakGgphDate = (TextView) findViewById(R.id.childdetail_ggphtestdate); + TextView anakGgphResult = (TextView) findViewById(R.id.childdetail_ggphtestresult); + + + + ImageButton back = (ImageButton) findViewById(org.ei.opensrp.R.id.btn_back_to_home); + back.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + startActivity(new Intent(ChildDetailActivity.this, FormulirDdtkSmartRegisterActivity.class)); + overridePendingTransition(0, 0); + } + }); + final ImageView childview = (ImageView)findViewById(R.id.childdetailprofileview); + if(childclient.getDetails().get("profilepic")!= null){ + if((childclient.getDetails().get("jenis_kelamin")!=null?childclient.getDetails().get("jenis_kelamin"):"").equalsIgnoreCase("perempuan")) { + setImagetoHolderFromUri(ChildDetailActivity.this, childclient.getDetails().get("profilepic"), childview, R.mipmap.womanimageload); + } else if ((childclient.getDetails().get("jenis_kelamin")!=null?childclient.getDetails().get("jenis_kelamin"):"").equalsIgnoreCase("laki_laki")){ + setImagetoHolderFromUri(ChildDetailActivity.this, childclient.getDetails().get("profilepic"), childview, R.mipmap.householdload); + + } + }else{ + + if((childclient.getDetails().get("jenis_kelamin")!=null?childclient.getDetails().get("jenis_kelamin"):"").equalsIgnoreCase("perempuan")){ + childview.setImageDrawable(getResources().getDrawable(R.drawable.child_girl_infant)); + }else if ((childclient.getDetails().get("jenis_kelamin")!=null?childclient.getDetails().get("jenis_kelamin"):"").equalsIgnoreCase("laki_laki")){ + childview.setImageDrawable(getResources().getDrawable(R.drawable.child_boy_infant)); + } + } + // } + childview.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + bindobject = "anak"; + entityid = childclient.entityId(); + dispatchTakePictureIntent(childview); + + } + }); + anakName.setText(getString(R.string.detailNamaAnak) +": "+ (childclient.getDetails().get("nama_anak") != null ? childclient.getDetails().get("nama_anak").replaceAll("_", " ") : "-")); + anakJenisKelamin.setText(getString(R.string.detailJenisKelamin) +": "+ (childclient.getDetails().get("jenis_kelamin") != null ? childclient.getDetails().get("jenis_kelamin").replaceAll("_", " ") : "-")); + anakNamaIbu.setText(getString(R.string.detailNamaIbu) +": "+ (childclient.getDetails().get("nama_ibu") != null ? childclient.getDetails().get("nama_ibu").replaceAll("_", " ") : "-")); + anakUmur.setText(getString(R.string.detailUmur) +": "+ (childclient.getDetails().get("umur") != null ? childclient.getDetails().get("umur").replaceAll("_", " ")+" Bulan" : "-")); + anakBerat.setText(getString(R.string.detailBerat) +": "+ (childclient.getDetails().get("berat") != null ? childclient.getDetails().get("berat").replaceAll("_", " ") : "-")); + anakTinggi.setText(getString(R.string.detailTinggi) +": "+ (childclient.getDetails().get("tinggi") != null ? childclient.getDetails().get("tinggi").replaceAll("_", " ") : "-")); + anakLingKepala.setText(getString(R.string.detailLingkarKepala) +": "+ (childclient.getDetails().get("lingkar_kepala") != null ? childclient.getDetails().get("lingkar_kepala").replaceAll("_", " ") : "-")); + anakKpspDate1.setText(getString(R.string.kpspdate1) +": "+ (childclient.getDetails().get("kpsp_test_date1") != null ? childclient.getDetails().get("kpsp_test_date1").replaceAll("_", " ") : "-")); + anakKpspResult1.setText(getString(R.string.kpspresult1) +": "+ (childclient.getDetails().get("status_kembang1") != null ? childclient.getDetails().get("status_kembang1").replaceAll("_", " ") : "-")); + anakKpspDate2.setText(getString(R.string.kpspdate2) + ": " + (childclient.getDetails().get("kpsp_test_date2") != null ? childclient.getDetails().get("kpsp_test_date2").replaceAll("_", " ") : "-")); + anakKpspResult2.setText(getString(R.string.kpspresult2) +": "+ (childclient.getDetails().get("status_kembang2") != null ? childclient.getDetails().get("status_kembang2").replaceAll("_", " ") : "-")); + anakKpspDate3.setText(getString(R.string.kpspdate3) +": "+ (childclient.getDetails().get("kpsp_test_date3") != null ? childclient.getDetails().get("kpsp_test_date3").replaceAll("_", " ") : "-")); + anakKpspResult3.setText(getString(R.string.kpspresult3) +": "+ (childclient.getDetails().get("status_kembang3") != null ? childclient.getDetails().get("status_kembang3").replaceAll("_", " ") : "-")); + anakKpspDate4.setText(getString(R.string.kpspdate4) +": "+ (childclient.getDetails().get("kpsp_test_date4") != null ? childclient.getDetails().get("kpsp_test_date4").replaceAll("_", " ") : "-")); + anakKpspResult4.setText(getString(R.string.kpspresult4) +": "+ (childclient.getDetails().get("status_kembang4") != null ? childclient.getDetails().get("status_kembang4").replaceAll("_", " ") : "-")); + anakKpspDate5.setText(getString(R.string.kpspdate5) +": "+ (childclient.getDetails().get("kpsp_test_date5") != null ? childclient.getDetails().get("kpsp_test_date5").replaceAll("_", " ") : "-")); + anakKpspResult5.setText(getString(R.string.kpspresult5) +": "+ (childclient.getDetails().get("status_kembang5") != null ? childclient.getDetails().get("status_kembang5").replaceAll("_", " ") : "-")); + anakKpspDate6.setText(getString(R.string.kpspdate6) +": "+ (childclient.getDetails().get("kpsp_test_date6") != null ? childclient.getDetails().get("kpsp_test_date6").replaceAll("_", " ") : "-")); + anakKpspResult6.setText(getString(R.string.kpspresult6) +": "+ (childclient.getDetails().get("status_kembang6") != null ? childclient.getDetails().get("status_kembang6").replaceAll("_", " ") : "-")); + anakHearingDate.setText(getString(R.string.hearingdate) +": "+ (childclient.getDetails().get("hear_test_date") != null ? childclient.getDetails().get("hear_test_date").replaceAll("_", " ") : "-")); + anakHearingResult.setText(getString(R.string.hearingresult) +": "+ (childclient.getDetails().get("daya_dengar") != null ? childclient.getDetails().get("daya_dengar").replaceAll("_", " ") : "-")); + anakVisualDate.setText(getString(R.string.visualdate) +": "+ (childclient.getDetails().get("sight_test_date") != null ? childclient.getDetails().get("sight_test_date").replaceAll("_", " ") : "-")); + anakVisualResult.setText(getString(R.string.visualresult) +": "+ (childclient.getDetails().get("daya_lihat") != null ? childclient.getDetails().get("daya_lihat").replaceAll("_", " ") : "-")); + anakMentalDate.setText(getString(R.string.mentaldate) +": "+ (childclient.getDetails().get("mental_test_date") != null ? childclient.getDetails().get("mental_test_date").replaceAll("_", " ") : "-")); + anakMentalResult.setText(getString(R.string.mentalresult) +": "+ (childclient.getDetails().get("mental_emosional") != null ? childclient.getDetails().get("mental_emosional").replaceAll("_", " ") : "-")); + anakAutistDate.setText(getString(R.string.autisdate) +": "+ (childclient.getDetails().get("autis_test_date") != null ? childclient.getDetails().get("autis_test_date").replaceAll("_", " ") : "-")); + anakAutistResult.setText(getString(R.string.autisresult) +": "+ (childclient.getDetails().get("autis") != null ? childclient.getDetails().get("autis").replaceAll("_", " ") : "-")); + anakGgphDate.setText(getString(R.string.ggphdate) +": "+ (childclient.getDetails().get("gpph_test_date") != null ? childclient.getDetails().get("gpph_test_date").replaceAll("_", " ") : "-")); + anakGgphResult.setText(getString(R.string.ggphresult) +": "+ (childclient.getDetails().get("gpph") != null ? childclient.getDetails().get("gpph").replaceAll("_", " ") : "-")); + + //KMS calculation + + //Graph + + + + + } + + + // NOT USING PICTURE AT THE MOMENT + String mCurrentPhotoPath; + + private File createImageFile() throws IOException { + // Create an image file name + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); + String imageFileName = "JPEG_" + timeStamp + "_"; + File storageDir = Environment.getExternalStoragePublicDirectory( + Environment.DIRECTORY_PICTURES); + File image = File.createTempFile( + imageFileName, /* prefix */ + ".jpg", /* suffix */ + storageDir /* directory */ + ); + + // Save a file: path for use with ACTION_VIEW intents + mCurrentPhotoPath = "file:" + image.getAbsolutePath(); + return image; + } + static final int REQUEST_TAKE_PHOTO = 1; + static ImageView mImageView; + static File currentfile; + static String bindobject; + static String entityid; + private void dispatchTakePictureIntent(ImageView imageView) { + mImageView = imageView; + Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + // Ensure that there's a camera activity to handle the intent + if (takePictureIntent.resolveActivity(getPackageManager()) != null) { + // Create the File where the photo should go + File photoFile = null; + try { + photoFile = createImageFile(); + } catch (IOException ex) { + // Error occurred while creating the File + + } + // Continue only if the File was successfully created + if (photoFile != null) { + currentfile = photoFile; + takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, + Uri.fromFile(photoFile)); + startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO); + } + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == REQUEST_TAKE_PHOTO && resultCode == RESULT_OK) { +// Bundle extras = data.getExtras(); +// String imageBitmap = (String) extras.get(MediaStore.EXTRA_OUTPUT); +// Toast.makeText(this,imageBitmap,Toast.LENGTH_LONG).show(); + HashMap details = new HashMap(); + details.put("profilepic",currentfile.getAbsolutePath()); + saveimagereference(bindobject,entityid,details); + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inPreferredConfig = Bitmap.Config.ARGB_8888; + Bitmap bitmap = BitmapFactory.decodeFile(currentfile.getPath(), options); + mImageView.setImageBitmap(bitmap); + } + } + public void saveimagereference(String bindobject,String entityid,Map details){ + Context.getInstance().allCommonsRepositoryobjects(bindobject).mergeDetails(entityid,details); +// childclient.entityId(); +// Toast.makeText(this,entityid,Toast.LENGTH_LONG).show(); + } + public static void setImagetoHolder(Activity activity,String file, ImageView view, int placeholder){ + mImageThumbSize = 300; + mImageThumbSpacing = Context.getInstance().applicationContext().getResources().getDimensionPixelSize(R.dimen.image_thumbnail_spacing); + + + ImageCache.ImageCacheParams cacheParams = + new ImageCache.ImageCacheParams(activity, IMAGE_CACHE_DIR); + cacheParams.setMemCacheSizePercent(0.50f); // Set memory cache to 25% of app memory + mImageFetcher = new ImageFetcher(activity, mImageThumbSize); + mImageFetcher.setLoadingImage(placeholder); + mImageFetcher.addImageCache(activity.getFragmentManager(), cacheParams); +// Toast.makeText(activity,file,Toast.LENGTH_LONG).show(); + mImageFetcher.loadImage("file:///"+file,view); + +// Uri.parse(new File("/sdcard/cats.jpg") + + + + + +// BitmapFactory.Options options = new BitmapFactory.Options(); +// options.inPreferredConfig = Bitmap.Config.ARGB_8888; +// Bitmap bitmap = BitmapFactory.decodeFile(file, options); +// view.setImageBitmap(bitmap); + } + public static void setImagetoHolderFromUri(Activity activity,String file, ImageView view, int placeholder){ + view.setImageDrawable(activity.getResources().getDrawable(placeholder)); + File externalFile = new File(file); + Uri external = Uri.fromFile(externalFile); + view.setImageURI(external); + + + } + @Override + public void onBackPressed() { + finish(); + startActivity(new Intent(this, FormulirDdtkSmartRegisterActivity.class)); + overridePendingTransition(0, 0); + + + } +} \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/ddtk/FormulirDdtkDateSort.java b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/ddtk/FormulirDdtkDateSort.java new file mode 100644 index 000000000..44502c68a --- /dev/null +++ b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/ddtk/FormulirDdtkDateSort.java @@ -0,0 +1,72 @@ +package org.ei.opensrp.ddtk.ddtk; + +import org.ei.opensrp.commonregistry.CommonPersonObjectClient; +import org.ei.opensrp.view.contract.SmartRegisterClient; +import org.ei.opensrp.view.contract.SmartRegisterClients; +import org.ei.opensrp.view.dialog.SortOption; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; + +/** + * Created by Iq on 30/03/16. + */ +public class FormulirDdtkDateSort implements SortOption { + String field; + ByColumnAndByDetails byColumnAndByDetails; + + public enum ByColumnAndByDetails{ + byColumn,byDetails; + } + + public FormulirDdtkDateSort() { + + } + + @Override + public String name() { + return "Due Status"; + } + + @Override + public SmartRegisterClients sort(SmartRegisterClients allClients) { + Collections.sort(allClients, commoncomparator); + return allClients; + } + + Comparator commoncomparator = new Comparator() { + @Override + public int compare(SmartRegisterClient oneClient, SmartRegisterClient anotherClient2) { + CommonPersonObjectClient commonPersonObjectClient = (CommonPersonObjectClient)oneClient; + CommonPersonObjectClient commonPersonObjectClient2 = (CommonPersonObjectClient)anotherClient2; + switch (byColumnAndByDetails){ + case byColumn: + try { + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + Date date1 = dateFormat.parse(commonPersonObjectClient.getColumnmaps().get(field)); + Date date2 = dateFormat.parse(commonPersonObjectClient2.getColumnmaps().get(field)); + + return date1.compareTo(date2); + }catch (Exception e){ + break; + } + + + case byDetails: + try { + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + Date date1 = dateFormat.parse(commonPersonObjectClient.getDetails().get(field)); + Date date2 = dateFormat.parse(commonPersonObjectClient2.getDetails().get(field)); + return date1.compareTo(date2); + }catch (Exception e){ + break; + } + + } + return 0; + } + }; +} diff --git a/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/ddtk/FormulirDdtkSearchOption.java b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/ddtk/FormulirDdtkSearchOption.java new file mode 100644 index 000000000..4a4161f26 --- /dev/null +++ b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/ddtk/FormulirDdtkSearchOption.java @@ -0,0 +1,43 @@ +package org.ei.opensrp.ddtk.ddtk; + +import org.ei.opensrp.Context; +import org.ei.opensrp.commonregistry.CommonPersonObjectClient; +import org.ei.opensrp.ddtk.R; +import org.ei.opensrp.view.contract.SmartRegisterClient; +import org.ei.opensrp.view.dialog.FilterOption; + +public class FormulirDdtkSearchOption implements FilterOption { + private final String criteria; + + public FormulirDdtkSearchOption(String criteria) { + this.criteria = criteria; + } + + @Override + public String name() { + return Context.getInstance().applicationContext().getResources().getString(R.string.hh_search_hint); + } + + @Override + public boolean filter(SmartRegisterClient client) { + boolean result = false; + CommonPersonObjectClient currentclient = (CommonPersonObjectClient) client; +// AllCommonsRepository allElcoRepository = new AllCommonsRepository("elco"); + if(!result) { + if(currentclient.getDetails().get("nama_anak") != null) { + if (currentclient.getDetails().get("nama_anak").toLowerCase().contains(criteria.toLowerCase())) { + result = true; + } + } + } + if(!result) { + if(currentclient.getDetails().get("nama_ibu") != null) { + if (currentclient.getDetails().get("nama_ibu").contains(criteria)) { + result = true; + } + } + } + + return result; + } +} diff --git a/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/ddtk/FormulirDdtkServiceModeOption.java b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/ddtk/FormulirDdtkServiceModeOption.java new file mode 100644 index 000000000..ce4300479 --- /dev/null +++ b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/ddtk/FormulirDdtkServiceModeOption.java @@ -0,0 +1,81 @@ +package org.ei.opensrp.ddtk.ddtk; + +import android.view.View; + +import org.ei.opensrp.Context; +import org.ei.opensrp.provider.SmartRegisterClientsProvider; +import org.ei.opensrp.ddtk.R; +import org.ei.opensrp.view.contract.ANCSmartRegisterClient; +import org.ei.opensrp.view.contract.ChildSmartRegisterClient; +import org.ei.opensrp.view.contract.FPSmartRegisterClient; +import org.ei.opensrp.view.contract.pnc.PNCSmartRegisterClient; +import org.ei.opensrp.view.dialog.ServiceModeOption; +import org.ei.opensrp.view.viewHolder.NativeANCSmartRegisterViewHolder; +import org.ei.opensrp.view.viewHolder.NativeChildSmartRegisterViewHolder; +import org.ei.opensrp.view.viewHolder.NativeFPSmartRegisterViewHolder; +import org.ei.opensrp.view.viewHolder.NativePNCSmartRegisterViewHolder; + +import static org.ei.opensrp.view.activity.SecuredNativeSmartRegisterActivity.ClientsHeaderProvider; + +public class FormulirDdtkServiceModeOption extends ServiceModeOption { + + public FormulirDdtkServiceModeOption(SmartRegisterClientsProvider provider) { + super(provider); + } + + @Override + public String name() { + return Context.getInstance().getStringResource(R.string.instrumen_sdidtk); + } + + @Override + public ClientsHeaderProvider getHeaderProvider() { + return new ClientsHeaderProvider() { + @Override + public int count() { + return 6; + } + + @Override + public int weightSum() { + return 52; + } + + @Override + public int[] weights() { + return new int[]{10,7,7,8,8,8}; + } + + @Override + public int[] headerTextResourceIds() { + return new int[]{ + R.string.hh_profile,R.string.hh_antro,R.string.hh_kpsp,R.string.hh_hearing_visual,R.string.hh_mental,R.string.hh_autis_ggph + }; + } + }; + } + + @Override + public void setupListView(ChildSmartRegisterClient client, + NativeChildSmartRegisterViewHolder viewHolder, + View.OnClickListener clientSectionClickListener) { + + } + + @Override + public void setupListView(ANCSmartRegisterClient client, NativeANCSmartRegisterViewHolder viewHolder, View.OnClickListener clientSectionClickListener) { + + } + + @Override + public void setupListView(FPSmartRegisterClient client, NativeFPSmartRegisterViewHolder viewHolder, View.OnClickListener clientSectionClickListener) { + + } + + @Override + public void setupListView(PNCSmartRegisterClient client, NativePNCSmartRegisterViewHolder viewHolder, View.OnClickListener clientSectionClickListener) { + + } + + +} diff --git a/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/ddtk/FormulirDdtkSmartClientsProvider.java b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/ddtk/FormulirDdtkSmartClientsProvider.java new file mode 100644 index 000000000..cf92fbab2 --- /dev/null +++ b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/ddtk/FormulirDdtkSmartClientsProvider.java @@ -0,0 +1,263 @@ +package org.ei.opensrp.ddtk.ddtk; + +import android.app.Activity; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.Button; +import android.widget.FrameLayout; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import org.ei.opensrp.commonregistry.CommonPersonObjectClient; +import org.ei.opensrp.commonregistry.CommonPersonObjectController; +import org.ei.opensrp.provider.SmartRegisterClientsProvider; +import org.ei.opensrp.service.AlertService; +import org.ei.opensrp.ddtk.R; +import org.ei.opensrp.view.contract.SmartRegisterClient; +import org.ei.opensrp.view.contract.SmartRegisterClients; +import org.ei.opensrp.view.dialog.FilterOption; +import org.ei.opensrp.view.dialog.ServiceModeOption; +import org.ei.opensrp.view.dialog.SortOption; +import org.ei.opensrp.view.viewHolder.OnClickFormLauncher; + + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; + +/** + * Created by user on 2/12/15. + */ +public class FormulirDdtkSmartClientsProvider implements SmartRegisterClientsProvider{ + + private final LayoutInflater inflater; + public final Context context; + private final View.OnClickListener onClickListener; + + private final int txtColorBlack; + private final AbsListView.LayoutParams clientViewLayoutParams; + private Drawable iconPencilDrawable; + protected CommonPersonObjectController controller; + + AlertService alertService; + + public FormulirDdtkSmartClientsProvider(Context context, + View.OnClickListener onClickListener, + CommonPersonObjectController controller, AlertService alertService) { + this.onClickListener = onClickListener; + this.controller = controller; + this.context = context; + this.alertService = alertService; + this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + + clientViewLayoutParams = new AbsListView.LayoutParams(MATCH_PARENT, + (int) context.getResources().getDimension(org.ei.opensrp.R.dimen.list_item_height)); + txtColorBlack = context.getResources().getColor(org.ei.opensrp.R.color.text_black); + + } + + @Override + public View getView(SmartRegisterClient smartRegisterClient, View convertView, ViewGroup viewGroup) { + + ViewHolder viewHolder; + ViewGroup itemView = viewGroup; + if (convertView == null){ + convertView = (ViewGroup) inflater().inflate(R.layout.smart_register_ddtk_client, null); + viewHolder = new ViewHolder(); + viewHolder.profilelayout = (LinearLayout)convertView.findViewById(R.id.profile_info_layout); + viewHolder.nama_anak = (TextView)convertView.findViewById(R.id.text_nama_anak); + viewHolder.jenis_kelamin = (TextView)convertView.findViewById(R.id.text_jenis_kelamin); + viewHolder.umur = (TextView)convertView.findViewById(R.id.text_umur); + viewHolder.nama_ibu = (TextView)convertView.findViewById(R.id.text_nama_ibu); + viewHolder.berat = (TextView)convertView.findViewById(R.id.text_berat); + viewHolder.tinggi = (TextView)convertView.findViewById(R.id.text_tinggi); + viewHolder.lingkar_kepala = (TextView)convertView.findViewById(R.id.text_lingkar_kepala); + viewHolder.kpsp_test_date1 = (TextView)convertView.findViewById(R.id.text_kpsp_test_date); + viewHolder.status_kembang1 = (TextView)convertView.findViewById(R.id.text_status_kembang); + viewHolder.status_kembang2 = (TextView)convertView.findViewById(R.id.text_status_kembang); + viewHolder.kpsp_test_date2 = (TextView)convertView.findViewById(R.id.text_kpsp_test_date); + viewHolder.status_kembang3 = (TextView)convertView.findViewById(R.id.text_status_kembang); + viewHolder.kpsp_test_date3 = (TextView)convertView.findViewById(R.id.text_kpsp_test_date); + viewHolder.status_kembang4 = (TextView)convertView.findViewById(R.id.text_status_kembang); + viewHolder.kpsp_test_date4 = (TextView)convertView.findViewById(R.id.text_kpsp_test_date); + viewHolder.status_kembang5 = (TextView)convertView.findViewById(R.id.text_status_kembang); + viewHolder.kpsp_test_date5 = (TextView)convertView.findViewById(R.id.text_kpsp_test_date); + viewHolder.status_kembang6 = (TextView)convertView.findViewById(R.id.text_status_kembang); + viewHolder.kpsp_test_date6 = (TextView)convertView.findViewById(R.id.text_kpsp_test_date); + viewHolder.daya_dengar = (TextView)convertView.findViewById(R.id.text_daya_dengar); + viewHolder.daya_lihat = (TextView)convertView.findViewById(R.id.text_daya_lihat); + viewHolder.mental_emosional = (TextView)convertView.findViewById(R.id.text_mental_emosional); + viewHolder.autis = (TextView)convertView.findViewById(R.id.text_autis); + viewHolder.gpph = (TextView)convertView.findViewById(R.id.text_gpph); + viewHolder.anthropometry_date = (TextView)convertView.findViewById(R.id.text_anthropometry_date); + viewHolder.hear_test_date = (TextView)convertView.findViewById(R.id.text_hear_test_date); + viewHolder.sight_test_date = (TextView)convertView.findViewById(R.id.text_sight_test_date); + viewHolder.mental_test_date = (TextView)convertView.findViewById(R.id.text_mental_test_date); + viewHolder.autis_test_date = (TextView)convertView.findViewById(R.id.text_autis_test_date); + viewHolder.gpph_test_date = (TextView)convertView.findViewById(R.id.text_gpph_test_date); + viewHolder.profilepic =(ImageView)convertView.findViewById(R.id.childdetailprofileview); + viewHolder.follow_up = (ImageButton)convertView.findViewById(R.id.btn_edit); + convertView.setTag(viewHolder); + }else{ + viewHolder = (ViewHolder) convertView.getTag(); + } + + viewHolder.follow_up.setOnClickListener(onClickListener); + viewHolder.follow_up.setTag(smartRegisterClient); + viewHolder.profilelayout.setOnClickListener(onClickListener); + viewHolder.profilelayout.setTag(smartRegisterClient); + CommonPersonObjectClient pc = (CommonPersonObjectClient) smartRegisterClient; + if (iconPencilDrawable == null) { + iconPencilDrawable = context.getResources().getDrawable(R.drawable.ic_pencil); + } + viewHolder.follow_up.setImageDrawable(iconPencilDrawable); + viewHolder.follow_up.setOnClickListener(onClickListener); + // viewHolder.follow_up.setTag(client); + + /* + // List alertlist_for_client = alertService.findByEntityIdAndAlertNames(pc.entityId(), "FW CENSUS"); + +*/ + + //set image picture + final ImageView childview = (ImageView)convertView.findViewById(R.id.childdetailprofileview); + + if (pc.getDetails().get("profilepic") == null) { + if (pc.getDetails().get("jenis_kelamin").equalsIgnoreCase("laki_laki")) { + viewHolder.profilepic.setImageResource(org.ei.opensrp.R.drawable.child_boy_infant); + + } else { + + viewHolder.profilepic.setImageResource(org.ei.opensrp.R.drawable.child_girl_infant); + + } + + } if (pc.getDetails().get("profilepic") != null) { + ChildDetailActivity.setImagetoHolderFromUri((Activity) context, pc.getDetails().get("profilepic"), childview, R.drawable.ic_dristhi_logo); + childview.setTag(smartRegisterClient); + } + + + //viewHolder.profilepic.setImageDrawable(context.getResources().getDrawable(R.drawable.child_boy_infant)); + //viewHolder.village.setText(pc.getDetails().get("village") != null ? pc.getDetails().get("village") : ""); + viewHolder.nama_anak.setText(pc.getDetails().get("nama_anak") != null ? pc.getDetails().get("nama_anak").replaceAll("_", " ") : "-"); + viewHolder.jenis_kelamin.setText(pc.getDetails().get("jenis_kelamin") != null ? pc.getDetails().get("jenis_kelamin").replaceAll("_", " ") : "-"); + viewHolder.umur.setText(pc.getDetails().get("umur")!=null?pc.getDetails().get("umur").replaceAll("_", " ")+" Bulan" :"-"); + viewHolder.nama_ibu.setText(pc.getDetails().get("nama_ibu") != null ? pc.getDetails().get("nama_ibu").replaceAll("_", " ") : "-"); + viewHolder.berat.setText("Berat: "+ (pc.getDetails().get("berat")!=null?pc.getDetails().get("berat").replaceAll("_", " "):"-")); + viewHolder.tinggi.setText("Tinggi: "+ (pc.getDetails().get("tinggi") != null ? pc.getDetails().get("tinggi").replaceAll("_", " ") : "-")); + viewHolder.lingkar_kepala.setText("Lingkar Kepala: "+ (pc.getDetails().get("lingkar_kepala")!=null?pc.getDetails().get("lingkar_kepala").replaceAll("_", " "):"-")); + viewHolder.kpsp_test_date1.setText("Tanggal: "+ (pc.getDetails().get("kpsp_test_date1")!=null?pc.getDetails().get("kpsp_test_date1").replaceAll("_", " "):"-")); + viewHolder.kpsp_test_date2.setText(pc.getDetails().get("kpsp_test_date2")!=null?pc.getDetails().get("kpsp_test_date2").replaceAll("_", " "):"-"); + viewHolder.status_kembang2.setText(pc.getDetails().get("status_kembang2")!=null?pc.getDetails().get("status_kembang2").replaceAll("_", " "):"-"); + viewHolder.kpsp_test_date3.setText(pc.getDetails().get("kpsp_test_date3")!=null?pc.getDetails().get("kpsp_test_date3").replaceAll("_", " "):"-"); + viewHolder.status_kembang3.setText(pc.getDetails().get("status_kembang3")!=null?pc.getDetails().get("status_kembang3").replaceAll("_", " "):"-"); + viewHolder.kpsp_test_date4.setText(pc.getDetails().get("kpsp_test_date4")!=null?pc.getDetails().get("kpsp_test_date4").replaceAll("_", " "):"-"); + viewHolder.status_kembang4.setText(pc.getDetails().get("status_kembang4")!=null?pc.getDetails().get("status_kembang4").replaceAll("_", " "):"-"); + viewHolder.kpsp_test_date5.setText(pc.getDetails().get("kpsp_test_date5")!=null?pc.getDetails().get("kpsp_test_date5").replaceAll("_", " "):"-"); + viewHolder.status_kembang5.setText(pc.getDetails().get("status_kembang5")!=null?pc.getDetails().get("status_kembang5").replaceAll("_", " "):"-"); + viewHolder.kpsp_test_date6.setText(pc.getDetails().get("kpsp_test_date6")!=null?pc.getDetails().get("kpsp_test_date6").replaceAll("_", " "):"-"); + viewHolder.status_kembang6.setText(pc.getDetails().get("status_kembang6")!=null?pc.getDetails().get("status_kembang6").replaceAll("_", " "):"-"); + viewHolder.daya_dengar.setText("Tes Hearing: "+ (pc.getDetails().get("daya_dengar") != null ? pc.getDetails().get("daya_dengar").replaceAll("_", " ") : "-")); + viewHolder.daya_lihat.setText("Tes Visual: "+ (pc.getDetails().get("daya_lihat")!=null?pc.getDetails().get("daya_lihat").replaceAll("_", " "):"-")); + viewHolder.mental_emosional.setText("Tes Mental: "+ (pc.getDetails().get("mental_emosional")!=null?pc.getDetails().get("mental_emosional").replaceAll("_", " "):"-")); + viewHolder.autis.setText("Test Autist: "+ (pc.getDetails().get("autis")!=null ? pc.getDetails().get("autis").replaceAll("_", " "):"-")); + viewHolder.gpph.setText("Tes GGPH: "+ (pc.getDetails().get("gpph")!=null?pc.getDetails().get("gpph").replaceAll("_", " "):"-")); + viewHolder.anthropometry_date.setText("Tanggal: "+ (pc.getDetails().get("anthropometry_date")!=null ? pc.getDetails().get("anthropometry_date").replaceAll("_", " "):"-")); + viewHolder.sight_test_date.setText("Tanggal: "+ (pc.getDetails().get("sight_test_date")!=null?pc.getDetails().get("sight_test_date").replaceAll("_", " "):"-")); + viewHolder.mental_test_date.setText("Tanggal: "+ (pc.getDetails().get("mental_test_date")!=null?pc.getDetails().get("mental_test_date").replaceAll("_", " "):"-")); + viewHolder.autis_test_date.setText("Tanggal: "+ (pc.getDetails().get("autis_test_date")!=null?pc.getDetails().get("autis_test_date").replaceAll("_", " "):"-")); + viewHolder.gpph_test_date.setText("Tanggal: "+ (pc.getDetails().get("gpph_test_date")!=null?pc.getDetails().get("gpph_test_date").replaceAll("_", " "):"-")); + viewHolder.kpsp_test_date1.setText("Tanggal: "+ (pc.getDetails().get("kpsp_test_date1")!=null?pc.getDetails().get("kpsp_test_date1").replaceAll("_", " "):"-")); + viewHolder.status_kembang1.setText("Status Kembang: "+ (pc.getDetails().get("status_kembang1")!=null?pc.getDetails().get("status_kembang1").replaceAll("_", " "):"-")); + viewHolder.hear_test_date.setText("Tanggal: "+ (pc.getDetails().get("hear_test_date")!=null?pc.getDetails().get("hear_test_date").replaceAll("_", " "):"-")); + // viewHolder.headofhouseholdname.setText(pc.getDetails().get("FWHOHFNAME")!=null?pc.getDetails().get("FWHOHFNAME"):""); + // viewHolder.no_of_mwra.setText(pc.getDetails().get("ELCO")!=null?pc.getDetails().get("ELCO"):""); + // Date lastdate = null; + + + + convertView.setLayoutParams(clientViewLayoutParams); + return convertView; + } + CommonPersonObjectController householdelcocontroller; + + + + + + @Override + public SmartRegisterClients getClients() { + return controller.getClients(); + } + + @Override + public SmartRegisterClients updateClients(FilterOption villageFilter, ServiceModeOption serviceModeOption, + FilterOption searchFilter, SortOption sortOption) { + return getClients().applyFilter(villageFilter, serviceModeOption, searchFilter, sortOption); + } + + @Override + public void onServiceModeSelected(ServiceModeOption serviceModeOption) { + // do nothing. + } + + @Override + public OnClickFormLauncher newFormLauncher(String formName, String entityId, String metaData) { + return null; + } + + public LayoutInflater inflater() { + return inflater; + } + + class ViewHolder { + + TextView today ; + TextView umur; + TextView village; + TextView husbandname; + LinearLayout profilelayout; + LinearLayout antrolayout; + ImageView profilepic; + FrameLayout due_date_holder; + Button warnbutton; + ImageButton follow_up; + TextView nama_anak; + TextView jenis_kelamin; + TextView nama_ibu; + TextView berat; + TextView tinggi; + TextView lingkar_kepala; + TextView status_kembang1; + TextView status_kembang2; + TextView status_kembang3; + TextView status_kembang4; + TextView status_kembang5; + TextView status_kembang6; + TextView daya_dengar; + TextView daya_lihat; + TextView mental_emosional; + TextView autis; + TextView gpph; + TextView anthropometry_date; + TextView hear_test_date; + TextView sight_test_date; + TextView mental_test_date; + TextView autis_test_date; + TextView kpsp_test_date1; + TextView kpsp_test_date2; + TextView kpsp_test_date3; + TextView kpsp_test_date4; + TextView kpsp_test_date5; + TextView kpsp_test_date6; + TextView gpph_test_date; + } + + +} + diff --git a/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/ddtk/FormulirDdtkSmartRegisterActivity.java b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/ddtk/FormulirDdtkSmartRegisterActivity.java new file mode 100644 index 000000000..1a6baa58c --- /dev/null +++ b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/ddtk/FormulirDdtkSmartRegisterActivity.java @@ -0,0 +1,321 @@ +package org.ei.opensrp.ddtk.ddtk; + +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.pm.ActivityInfo; +import android.os.Bundle; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.util.Log; + +import org.ei.opensrp.Context; +import org.ei.opensrp.commonregistry.CommonPersonObjectClient; +import org.ei.opensrp.ddtk.LoginActivity; +import org.ei.opensrp.ddtk.fragment.FormulirDdtkSmartRegisterFragment; +import org.ei.opensrp.ddtk.pageradapter.BaseRegisterActivityPagerAdapter; +import org.ei.opensrp.domain.Alert; +import org.ei.opensrp.domain.form.FormSubmission; +import org.ei.opensrp.provider.SmartRegisterClientsProvider; +import org.ei.opensrp.service.ZiggyService; +import org.ei.opensrp.ddtk.R; +//import org.ei.opensrp.test.fragment.HouseHoldSmartRegisterFragment; +import org.ei.opensrp.util.FormUtils; +import org.ei.opensrp.view.activity.SecuredNativeSmartRegisterActivity; +import org.ei.opensrp.view.dialog.DialogOption; +import org.ei.opensrp.view.dialog.OpenFormOption; +import org.ei.opensrp.view.fragment.DisplayFormFragment; +import org.ei.opensrp.view.fragment.SecuredNativeSmartRegisterFragment; +import org.ei.opensrp.view.viewpager.OpenSRPViewPager; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.Bind; +import butterknife.ButterKnife; + +import static org.ei.opensrp.R.string.form_back_confirm_dialog_message; +import static org.ei.opensrp.R.string.form_back_confirm_dialog_title; +import static org.ei.opensrp.R.string.no_button_label; +import static org.ei.opensrp.R.string.yes_button_label; + +public class FormulirDdtkSmartRegisterActivity extends SecuredNativeSmartRegisterActivity { + + public static final String TAG = "TestActivity"; + @Bind(R.id.view_pager) + OpenSRPViewPager mPager; + private FragmentPagerAdapter mPagerAdapter; + private int currentPage; + + private String[] formNames = new String[]{}; + private android.support.v4.app.Fragment mBaseFragment = null; + + + ZiggyService ziggyService; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + ButterKnife.bind(this); + + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + + formNames = this.buildFormNameList(); + mBaseFragment = new FormulirDdtkSmartRegisterFragment(); + + // Instantiate a ViewPager and a PagerAdapter. + mPagerAdapter = new BaseRegisterActivityPagerAdapter(getSupportFragmentManager(), formNames, mBaseFragment); + mPager.setOffscreenPageLimit(formNames.length); + mPager.setAdapter(mPagerAdapter); + mPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { + @Override + public void onPageSelected(int position) { + currentPage = position; + onPageChanged(position); + } + }); + + ziggyService = context().ziggyService(); + } + public void onPageChanged(int page){ + setRequestedOrientation(page == 0 ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + LoginActivity.setLanguage(); + } + + @Override + protected DefaultOptionsProvider getDefaultOptionsProvider() {return null;} + + @Override + protected void setupViews() {} + + @Override + protected void onResumption(){} + + @Override + protected NavBarOptionsProvider getNavBarOptionsProvider() {return null;} + + @Override + protected SmartRegisterClientsProvider clientsProvider() {return null;} + + @Override + protected void onInitialization() {} + + @Override + public void startRegistration() { + } + + public DialogOption[] getEditOptions() { + return new DialogOption[]{ + new OpenFormOption("Antropometri", "antropometri", formController), + new OpenFormOption("Kpsp Bayi 1 Tahun", "kpsp_bayi_1thn", formController), + new OpenFormOption("Kpsp Balita 2 Tahun", "kpsp_balita_2thn", formController), + new OpenFormOption("Kpsp Balita 3 Tahun", "kpsp_balita_3thn", formController), + new OpenFormOption("Kpsp Balita 4 Tahun", "kpsp_balita_4thn", formController), + new OpenFormOption("Kpsp Balita 5 Tahun", "kpsp_balita_5thn", formController), + new OpenFormOption("Kpsp Balita 6 Tahun", "kpsp_balita_6thn", formController), + new OpenFormOption("Tes Daya Dengar", "tes_daya_dengar", formController), + new OpenFormOption("Tes Daya Lihat", "tes_daya_lihat", formController), + new OpenFormOption("Masalah Mental Emosional", "masalah_mental_emosional", formController), + new OpenFormOption("Deteksi Dini Autis", "deteksi_dini_autis", formController), + new OpenFormOption("GPPH", "gangguan_konsentrasi_hiperaktivitas", formController), + + }; + } + + + private String getalertstateforcensus(CommonPersonObjectClient pc) { + try { + List alertlist_for_client = Context.getInstance().alertService().findByEntityIdAndAlertNames(pc.entityId(), "FW CENSUS"); + String alertstate = ""; + if (alertlist_for_client.size() == 0) { + + } else { + for (int i = 0; i < alertlist_for_client.size(); i++) { +// psrfdue.setText(alertlist_for_client.get(i).expiryDate()); + Log.v("printing alertlist", alertlist_for_client.get(i).status().value()); + alertstate = alertlist_for_client.get(i).status().value(); + + } + } + return alertstate; + }catch (Exception e){ + return ""; + } + } + + @Override + public void saveFormSubmission(String formSubmission, String id, String formName, JSONObject fieldOverrides){ + Log.v("fieldoverride", fieldOverrides.toString()); + // save the form + try{ + FormUtils formUtils = FormUtils.getInstance(getApplicationContext()); + FormSubmission submission = formUtils.generateFormSubmisionFromXMLString(id, formSubmission, formName, fieldOverrides); + + ziggyService.saveForm(getParams(submission), submission.instance()); + + //switch to forms list fragment + switchToBaseFragment(formSubmission); // Unnecessary!! passing on data + + }catch (Exception e){ + // TODO: show error dialog on the formfragment if the submission fails + DisplayFormFragment displayFormFragment = getDisplayFormFragmentAtIndex(currentPage); + if (displayFormFragment != null) { + displayFormFragment.hideTranslucentProgressDialog(); + } + e.printStackTrace(); + } + } + + @Override + public void startFormActivity(String formName, String entityId, String metaData) { + // Log.v("fieldoverride", metaData); + try { + int formIndex = FormUtils.getIndexForFormName(formName, formNames) + 1; // add the offset + if (entityId != null || metaData != null){ + String data = null; + //check if there is previously saved data for the form + data = getPreviouslySavedDataForForm(formName, metaData, entityId); + if (data == null){ + data = FormUtils.getInstance(getApplicationContext()).generateXMLInputForFormWithEntityId(entityId, formName, metaData); + } + + DisplayFormFragment displayFormFragment = getDisplayFormFragmentAtIndex(formIndex); + if (displayFormFragment != null) { + displayFormFragment.setFormData(data); + // displayFormFragment.loadFormData(); + displayFormFragment.setRecordId(entityId); + displayFormFragment.setFieldOverides(metaData); + } + } + + mPager.setCurrentItem(formIndex, false); //Don't animate the view on orientation change the view disapears + + }catch (Exception e){ + e.printStackTrace(); + } + + } + + public void switchToBaseFragment(final String data){ + final int prevPageIndex = currentPage; + runOnUiThread(new Runnable() { + @Override + public void run() { + mPager.setCurrentItem(0, false); + SecuredNativeSmartRegisterFragment registerFragment = (SecuredNativeSmartRegisterFragment) findFragmentByPosition(0); + if (registerFragment != null && data != null) { + registerFragment.refreshListView(); + } + + //hack reset the form + DisplayFormFragment displayFormFragment = getDisplayFormFragmentAtIndex(prevPageIndex); + if (displayFormFragment != null) { + displayFormFragment.hideTranslucentProgressDialog(); + displayFormFragment.setFormData(null); + // displayFormFragment.loadFormData(); + } + + displayFormFragment.setRecordId(null); + } + }); + + } + + public android.support.v4.app.Fragment findFragmentByPosition(int position) { + FragmentPagerAdapter fragmentPagerAdapter = mPagerAdapter; + return getSupportFragmentManager().findFragmentByTag("android:switcher:" + mPager.getId() + ":" + fragmentPagerAdapter.getItemId(position)); + } + + public DisplayFormFragment getDisplayFormFragmentAtIndex(int index) { + return (DisplayFormFragment)findFragmentByPosition(index); + } + private void goBack() { + switchToBaseFragment(null); + } + @Override + public void onBackPressed() { + if (currentPage > 1) { + new AlertDialog.Builder(this) + .setMessage(form_back_confirm_dialog_message) + .setTitle(form_back_confirm_dialog_title) + .setCancelable(false) + .setPositiveButton(yes_button_label, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, + int whichButton) { + goBack(); + } + }) + .setNegativeButton(no_button_label, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, + int whichButton) { + } + }) + .show(); + } else if(currentPage == 1) { + new AlertDialog.Builder(this) + .setMessage(form_back_confirm_dialog_message) + .setTitle(form_back_confirm_dialog_title) + .setCancelable(false) + .setPositiveButton(yes_button_label, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, + int whichButton) { + goBack(); + } + }) + .setNegativeButton(no_button_label, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, + int whichButton) { + } + }) + .show(); + } else if (currentPage == 0) { + super.onBackPressed(); // allow back key only if we are + } + } + + private String[] buildFormNameList(){ + List formNames = new ArrayList(); + + formNames.add("formulir_ddtk"); + formNames.add("antropometri"); + formNames.add("kpsp_bayi_1thn"); + formNames.add("kpsp_balita_2thn"); + formNames.add("kpsp_balita_3thn"); + formNames.add("kpsp_balita_4thn"); + formNames.add("kpsp_balita_5thn"); + formNames.add("kpsp_balita_6thn"); + formNames.add("tes_daya_dengar"); + formNames.add("tes_daya_lihat"); + formNames.add("masalah_mental_emosional"); + formNames.add("deteksi_dini_autis"); + formNames.add("gangguan_konsentrasi_hiperaktivitas"); + // formNames.add("census_enrollment_form"); +// DialogOption[] options = getEditOptions(); +// for (int i = 0; i < options.length; i++){ +// formNames.add(((OpenFormOption) options[i]).getFormName()); +// } + return formNames.toArray(new String[formNames.size()]); + } + + @Override + protected void onPause() { + super.onPause(); + retrieveAndSaveUnsubmittedFormData(); + } + + public void retrieveAndSaveUnsubmittedFormData(){ + if (currentActivityIsShowingForm()){ + DisplayFormFragment formFragment = getDisplayFormFragmentAtIndex(currentPage); + formFragment.saveCurrentFormData(); + } + } + + private boolean currentActivityIsShowingForm(){ + return currentPage != 0; + } +} diff --git a/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/fragment/FormulirDdtkSmartRegisterFragment.java b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/fragment/FormulirDdtkSmartRegisterFragment.java new file mode 100644 index 000000000..8f4aeddf7 --- /dev/null +++ b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/fragment/FormulirDdtkSmartRegisterFragment.java @@ -0,0 +1,313 @@ +package org.ei.opensrp.ddtk.fragment; + +import android.app.Fragment; +import android.app.FragmentTransaction; +import android.content.Intent; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; + +import org.ei.opensrp.Context; +import org.ei.opensrp.adapter.SmartRegisterPaginatedAdapter; +import org.ei.opensrp.commonregistry.CommonObjectSort; +import org.ei.opensrp.commonregistry.CommonPersonObjectClient; +import org.ei.opensrp.commonregistry.CommonPersonObjectController; +import org.ei.opensrp.ddtk.LoginActivity; +import org.ei.opensrp.ddtk.ddtk.FormulirDdtkServiceModeOption; +import org.ei.opensrp.provider.SmartRegisterClientsProvider; +import org.ei.opensrp.ddtk.R; + +import org.ei.opensrp.ddtk.ddtk.ChildDetailActivity; +import org.ei.opensrp.ddtk.ddtk.FormulirDdtkSmartRegisterActivity; +import org.ei.opensrp.ddtk.ddtk.FormulirDdtkSearchOption; +import org.ei.opensrp.ddtk.ddtk.FormulirDdtkSmartClientsProvider; +import org.ei.opensrp.view.activity.SecuredNativeSmartRegisterActivity; +import org.ei.opensrp.view.contract.ECClient; +import org.ei.opensrp.view.contract.SmartRegisterClient; +import org.ei.opensrp.view.contract.SmartRegisterClients; +import org.ei.opensrp.view.controller.VillageController; +import org.ei.opensrp.view.dialog.AllClientsFilter; +import org.ei.opensrp.view.dialog.DialogOption; +import org.ei.opensrp.view.dialog.DialogOptionMapper; +import org.ei.opensrp.view.dialog.DialogOptionModel; +import org.ei.opensrp.view.dialog.EditOption; +import org.ei.opensrp.view.dialog.FilterOption; +import org.ei.opensrp.view.dialog.NameSort; +import org.ei.opensrp.view.dialog.ServiceModeOption; +import org.ei.opensrp.view.dialog.SortOption; +import org.ei.opensrp.view.fragment.SecuredNativeSmartRegisterFragment; +import org.opensrp.api.domain.Location; +import org.opensrp.api.util.EntityUtils; +import org.opensrp.api.util.LocationTree; +import org.opensrp.api.util.TreeNode; + +import java.util.ArrayList; +import java.util.Map; + +import util.AsyncTask; + +import static android.view.View.INVISIBLE; +import static android.view.View.VISIBLE; +import static org.apache.commons.lang3.StringUtils.isEmpty; + +/** + * Created by koros on 10/12/15. + */ +public class FormulirDdtkSmartRegisterFragment extends SecuredNativeSmartRegisterFragment { + + private SmartRegisterClientsProvider clientProvider = null; + private CommonPersonObjectController controller; + private VillageController villageController; + private DialogOptionMapper dialogOptionMapper; + + private final ClientActionHandler clientActionHandler = new ClientActionHandler(); + private String locationDialogTAG = "locationDialogTAG"; + + @Override + protected void onCreation() { + // + } + + @Override + protected SmartRegisterPaginatedAdapter adapter() { + return new SmartRegisterPaginatedAdapter(clientsProvider()); + } + + @Override + protected SecuredNativeSmartRegisterActivity.DefaultOptionsProvider getDefaultOptionsProvider() { + return new SecuredNativeSmartRegisterActivity.DefaultOptionsProvider() { + + @Override + public ServiceModeOption serviceMode() { + + return new FormulirDdtkServiceModeOption(clientsProvider()); + } + + @Override + public FilterOption villageFilter() { + return new AllClientsFilter(); + } + + @Override + public SortOption sortOption() { + return new NameSort(); + // return new HouseholdCensusDueDateSort(); + + } + + @Override + public String nameInShortFormForTitle() { + return Context.getInstance().getStringResource(R.string.sdidtk); + } + }; + } + + @Override + protected SecuredNativeSmartRegisterActivity.NavBarOptionsProvider getNavBarOptionsProvider() { + return new SecuredNativeSmartRegisterActivity.NavBarOptionsProvider() { + + @Override + public DialogOption[] filterOptions() { + + ArrayList dialogOptionslist = new ArrayList(); + + dialogOptionslist.add(new AllClientsFilter()); + // dialogOptionslist.add( new NOHHMWRAEXISTFilterOption("0","ELCO", NOHHMWRAEXISTFilterOption.ByColumnAndByDetails.byDetails)); + // dialogOptionslist.add(new HHMWRAEXISTFilterOption("0","ELCO", HHMWRAEXISTFilterOption.ByColumnAndByDetails.byDetails)); + + String locationjson = context().anmLocationController().get(); + LocationTree locationTree = EntityUtils.fromJson(locationjson, LocationTree.class); + + Map> locationMap = + locationTree.getLocationsHierarchy(); + // addChildToList(dialogOptionslist,locationMap); + DialogOption[] dialogOptions = new DialogOption[dialogOptionslist.size()]; + for (int i = 0;i < dialogOptionslist.size();i++){ + dialogOptions[i] = dialogOptionslist.get(i); + } + + return dialogOptions; + } + + @Override + public DialogOption[] serviceModeOptions() { + return new DialogOption[]{}; + } + + @Override + public DialogOption[] sortingOptions() { + return new DialogOption[]{ +// new HouseholdCensusDueDateSort(), + new CommonObjectSort(CommonObjectSort.ByColumnAndByDetails.byDetails, false, "nama_anak", getResources().getString(R.string.child_alphabetical_sort)), + new CommonObjectSort(CommonObjectSort.ByColumnAndByDetails.byDetails, false, "nama_ibu", getResources().getString(R.string.mothername_alphabetical_sort)), + new CommonObjectSort(CommonObjectSort.ByColumnAndByDetails.byDetails, false, "umur", getResources().getString(R.string.age_alphabetical_sort)), + +//"" +// new CommonObjectSort(true,false,true,"age") + }; + } + + @Override + public String searchHint() { + return getResources().getString(R.string.hh_search_hint); + } + }; + } + + @Override + protected SmartRegisterClientsProvider clientsProvider() { + if (clientProvider == null) { + clientProvider = new FormulirDdtkSmartClientsProvider( + getActivity(),clientActionHandler , controller,context().alertService()); + } + return clientProvider; + } + + private DialogOption[] getEditOptions() { + return ((FormulirDdtkSmartRegisterActivity)getActivity()).getEditOptions(); + } + + @Override + protected void onInitialization() { + if (controller == null) { + controller = new CommonPersonObjectController(context().allCommonsRepositoryobjects("anak"), + context().allBeneficiaries(), context().listCache(), + context().personObjectClientsCache(), "nama_anak", "jenis_kelamin", "nama_ibu", + CommonPersonObjectController.ByColumnAndByDetails.byDetails.byDetails); + + } + //controller = new CommonPersonObjectController(context().allCommonsRepositoryobjects("mother"), + // context().allBeneficiaries(), context().listCache(), + // context().personObjectClientsCache(),"nama","mother"); + dialogOptionMapper = new DialogOptionMapper(); + // context().formSubmissionRouter().getHandlerMap().put("census_enrollment_form",new CensusEnrollmentHandler()); + } + + @Override + public void setupViews(View view) { + getDefaultOptionsProvider(); + + super.setupViews(view); + view.findViewById(R.id.btn_report_month).setVisibility(INVISIBLE); + + setServiceModeViewDrawableRight(null); + updateSearchView(); +// checkforNidMissing(view); + } + + @Override + public void startRegistration() { + FragmentTransaction ft = getActivity().getFragmentManager().beginTransaction(); + Fragment prev = getActivity().getFragmentManager().findFragmentByTag(locationDialogTAG); + if (prev != null) { + ft.remove(prev); + } + ft.addToBackStack(null); + TestLocationSelectorDialogFragment + .newInstance((FormulirDdtkSmartRegisterActivity) getActivity(), new EditDialogOptionModel(), context().anmLocationController().get(), "formulir_ddtk") + .show(ft, locationDialogTAG); + } + + private class ClientActionHandler implements View.OnClickListener { + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.profile_info_layout: + ChildDetailActivity.childclient = (CommonPersonObjectClient) view.getTag(); + Intent intent = new Intent(getActivity(), ChildDetailActivity.class); + startActivity(intent); + getActivity().finish(); + break; + //untuk follow up button + case R.id.btn_edit: + showFragmentDialog(new EditDialogOptionModel(), view.getTag()); + break; + } + } + + private void showProfileView(ECClient client) { + navigationController.startEC(client.entityId()); + } + } + + private class EditDialogOptionModel implements DialogOptionModel { + @Override + public DialogOption[] getDialogOptions() { + return getEditOptions(); + } + + @Override + public void onDialogOptionSelection(DialogOption option, Object tag) { + onEditSelection((EditOption) option, (SmartRegisterClient) tag); + } + } + + @Override + protected void onResumption() { + super.onResumption(); + getDefaultOptionsProvider(); + updateSearchView(); + //checkforNidMissing(mView); + + try{ + LoginActivity.setLanguage(); + }catch (Exception e){ + + } + + } + + public void updateSearchView(){ + getSearchView().addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { + } + + @Override + public void onTextChanged(final CharSequence cs, int start, int before, int count) { + (new AsyncTask() { + SmartRegisterClients filteredClients; + + @Override + protected Object doInBackground(Object[] params) { +// currentSearchFilter = + setCurrentSearchFilter(new FormulirDdtkSearchOption(cs.toString())); + filteredClients = getClientsAdapter().getListItemProvider() + .updateClients(getCurrentVillageFilter(), getCurrentServiceModeOption(), + getCurrentSearchFilter(), getCurrentSortOption()); + + + return null; + } + + @Override + protected void onPostExecute(Object o) { +// clientsAdapter +// .refreshList(currentVillageFilter, currentServiceModeOption, +// currentSearchFilter, currentSortOption); + getClientsAdapter().refreshClients(filteredClients); + getClientsAdapter().notifyDataSetChanged(); + getSearchCancelView().setVisibility(isEmpty(cs) ? INVISIBLE : VISIBLE); + super.onPostExecute(o); + } + }).execute(); +// currentSearchFilter = new HHSearchOption(cs.toString()); +// clientsAdapter +// .refreshList(currentVillageFilter, currentServiceModeOption, +// currentSearchFilter, currentSortOption); +// +// searchCancelView.setVisibility(isEmpty(cs) ? INVISIBLE : VISIBLE); + + + } + + @Override + public void afterTextChanged(Editable editable) { + + } + }); + } + + + +} diff --git a/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/fragment/TestLocationSelectorDialogFragment.java b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/fragment/TestLocationSelectorDialogFragment.java new file mode 100644 index 000000000..11e8b59dd --- /dev/null +++ b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/fragment/TestLocationSelectorDialogFragment.java @@ -0,0 +1,176 @@ +package org.ei.opensrp.ddtk.fragment; + +import android.app.DialogFragment; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +import com.google.common.base.Strings; + +import org.ei.opensrp.domain.form.FieldOverrides; +import org.ei.opensrp.view.activity.SecuredNativeSmartRegisterActivity; +import org.ei.opensrp.view.dialog.DialogOption; +import org.ei.opensrp.view.dialog.DialogOptionModel; +import org.json.JSONObject; +import org.opensrp.api.domain.Location; +import org.opensrp.api.util.EntityUtils; +import org.opensrp.api.util.LocationTree; + +import java.util.Map; + +import atv.holder.SelectableItemHolder; +import atv.model.TreeNode; +import atv.view.AndroidTreeView; + +import static org.ei.opensrp.util.StringUtil.humanize; + +/** + * Created by koros on 2/25/16. + */ +public class TestLocationSelectorDialogFragment extends DialogFragment { + + private final SecuredNativeSmartRegisterActivity parentActivity; + private final DialogOption[] options; + private final DialogOptionModel dialogOptionModel; + private final String locationJSONString; + public static String savestate ; + AndroidTreeView tView; + public String formname; + // private final Object tag; + + private TestLocationSelectorDialogFragment(SecuredNativeSmartRegisterActivity activity, + DialogOptionModel dialogOptionModel, + String locationJSONString + , String formname) { + this.formname = formname; + this.parentActivity = activity; + this.options = dialogOptionModel.getDialogOptions(); + this.dialogOptionModel = dialogOptionModel; + this.locationJSONString = locationJSONString; + // this.tag = tag; + } + + public static TestLocationSelectorDialogFragment newInstance( + SecuredNativeSmartRegisterActivity activity, + DialogOptionModel dialogOptionModel, + String locationJSONString,String formname) { + return new TestLocationSelectorDialogFragment(activity, dialogOptionModel, locationJSONString,formname); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setStyle(DialogFragment.STYLE_NO_TITLE, android.R.style.Theme_Holo_Light_Dialog); + } + + @Override + public View onCreateView(final LayoutInflater inflater, final ViewGroup container, + Bundle savedInstanceState) { + ViewGroup dialogView = new LinearLayout(getActivity()); + TreeNode root = TreeNode.root(); + + LocationTree locationTree = EntityUtils.fromJson(locationJSONString, LocationTree.class); + + Map> locationMap = + locationTree.getLocationsHierarchy(); + + // creating the tree + locationTreeToTreNode(root, locationMap); + + tView = new AndroidTreeView(getActivity(), root); + tView.setDefaultContainerStyle(org.ei.opensrp.R.style.TreeNodeStyle); + tView.setSelectionModeEnabled(false); + + if(savestate != null){ + tView.restoreState(savestate); + } + + // tView.getSelected().get(1). + dialogView.addView(tView.getView()); + return dialogView; + } + + public TreeNode createNode(String locationlevel, String locationname){ + TreeNode node = new TreeNode(locationname,locationlevel).setViewHolder(new SelectableItemHolder(getActivity(),locationlevel+": ")); + node.setSelectable(false); + addselectlistener(node, ""); + return node; + } + + public void addChildToParentNode(TreeNode parent,TreeNode [] nodes){ + for (int i = 0;i> location) { + + for(Map.Entry> entry : location.entrySet()) { + String locationTag = entry.getValue().getNode().getTags().iterator().next(); + TreeNode tree = createNode( + Strings.isNullOrEmpty(locationTag)?"-":humanize(locationTag), + humanize(entry.getValue().getLabel())); + node.addChild(tree); + addselectlistener(tree, entry.getValue().getId()); + if(entry.getValue().getChildren() != null) { + locationTreeToTreNode(tree, entry.getValue().getChildren()); + } + } + } + +} diff --git a/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/pageradapter/BaseRegisterActivityPagerAdapter.java b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/pageradapter/BaseRegisterActivityPagerAdapter.java new file mode 100644 index 000000000..abfd3cbbd --- /dev/null +++ b/opensrp-sdidtk/src/main/java/org/ei/opensrp/ddtk/pageradapter/BaseRegisterActivityPagerAdapter.java @@ -0,0 +1,50 @@ +package org.ei.opensrp.ddtk.pageradapter; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; + +import org.ei.opensrp.view.fragment.DisplayFormFragment; + +/** + * Created by koros on 11/2/15. + */ +public class BaseRegisterActivityPagerAdapter extends FragmentPagerAdapter { + public static final String ARG_PAGE = "page"; + String[] dialogOptions; + Fragment mBaseFragment; + + public BaseRegisterActivityPagerAdapter(FragmentManager fragmentManager, String[] dialogOptions, Fragment baseFragment) { + super(fragmentManager); + this.dialogOptions = dialogOptions; + this.mBaseFragment = baseFragment; + } + + @Override + public Fragment getItem(int position) { + Fragment fragment = null; + switch (position) { + case 0: + fragment = mBaseFragment; + break; + + default: + String formName = dialogOptions[position - 1]; // account for the base fragment + DisplayFormFragment f = new DisplayFormFragment(); + f.setFormName(formName); + fragment = f; + break; + } + + Bundle args = new Bundle(); + args.putInt(ARG_PAGE, position); + fragment.setArguments(args); + return fragment; + } + + @Override + public int getCount() { + return dialogOptions.length + 1; // index 0 is always occupied by the base fragment + } +} diff --git a/opensrp-sdidtk/src/main/java/util/AsyncTask.java b/opensrp-sdidtk/src/main/java/util/AsyncTask.java new file mode 100644 index 000000000..061fc91bc --- /dev/null +++ b/opensrp-sdidtk/src/main/java/util/AsyncTask.java @@ -0,0 +1,693 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package util; + +import android.annotation.TargetApi; +import android.os.Handler; +import android.os.Message; +import android.os.Process; + +import java.util.ArrayDeque; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.FutureTask; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * ************************************* + * Copied from JB release framework: + * https://android.googlesource.com/platform/frameworks/base/+/jb-release/core/java/android/os/AsyncTask.java + * + * so that threading behavior on all OS versions is the same and we can tweak behavior by using + * executeOnExecutor() if needed. + * + * There are 3 changes in this copy of AsyncTask: + * -pre-HC a single thread executor is used for serial operation + * (Executors.newSingleThreadExecutor) and is the default + * -the default THREAD_POOL_EXECUTOR was changed to use DiscardOldestPolicy + * -a new fixed thread pool called DUAL_THREAD_EXECUTOR was added + * ************************************* + * + *

AsyncTask enables proper and easy use of the UI thread. This class allows to + * perform background operations and publish results on the UI thread without + * having to manipulate threads and/or handlers.

+ * + *

AsyncTask is designed to be a helper class around {@link Thread} and {@link Handler} + * and does not constitute a generic threading framework. AsyncTasks should ideally be + * used for short operations (a few seconds at the most.) If you need to keep threads + * running for long periods of time, it is highly recommended you use the various APIs + * provided by the java.util.concurrent pacakge such as {@link Executor}, + * {@link ThreadPoolExecutor} and {@link FutureTask}.

+ * + *

An asynchronous task is defined by a computation that runs on a background thread and + * whose result is published on the UI thread. An asynchronous task is defined by 3 generic + * types, called Params, Progress and Result, + * and 4 steps, called onPreExecute, doInBackground, + * onProgressUpdate and onPostExecute.

+ * + *
+ *

Developer Guides

+ *

For more information about using tasks and threads, read the + * Processes and + * Threads developer guide.

+ *
+ * + *

Usage

+ *

AsyncTask must be subclassed to be used. The subclass will override at least + * one method ({@link #doInBackground}), and most often will override a + * second one ({@link #onPostExecute}.)

+ * + *

Here is an example of subclassing:

+ *
+ * private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
+ *     protected Long doInBackground(URL... urls) {
+ *         int count = urls.length;
+ *         long totalSize = 0;
+ *         for (int i = 0; i < count; i++) {
+ *             totalSize += Downloader.downloadFile(urls[i]);
+ *             publishProgress((int) ((i / (float) count) * 100));
+ *             // Escape early if cancel() is called
+ *             if (isCancelled()) break;
+ *         }
+ *         return totalSize;
+ *     }
+ *
+ *     protected void onProgressUpdate(Integer... progress) {
+ *         setProgressPercent(progress[0]);
+ *     }
+ *
+ *     protected void onPostExecute(Long result) {
+ *         showDialog("Downloaded " + result + " bytes");
+ *     }
+ * }
+ * 
+ * + *

Once created, a task is executed very simply:

+ *
+ * new DownloadFilesTask().execute(url1, url2, url3);
+ * 
+ * + *

AsyncTask's generic types

+ *

The three types used by an asynchronous task are the following:

+ *
    + *
  1. Params, the type of the parameters sent to the task upon + * execution.
  2. + *
  3. Progress, the type of the progress units published during + * the background computation.
  4. + *
  5. Result, the type of the result of the background + * computation.
  6. + *
+ *

Not all types are always used by an asynchronous task. To mark a type as unused, + * simply use the type {@link Void}:

+ *
+ * private class MyTask extends AsyncTask<Void, Void, Void> { ... }
+ * 
+ * + *

The 4 steps

+ *

When an asynchronous task is executed, the task goes through 4 steps:

+ *
    + *
  1. {@link #onPreExecute()}, invoked on the UI thread immediately after the task + * is executed. This step is normally used to setup the task, for instance by + * showing a progress bar in the user interface.
  2. + *
  3. {@link #doInBackground}, invoked on the background thread + * immediately after {@link #onPreExecute()} finishes executing. This step is used + * to perform background computation that can take a long time. The parameters + * of the asynchronous task are passed to this step. The result of the computation must + * be returned by this step and will be passed back to the last step. This step + * can also use {@link #publishProgress} to publish one or more units + * of progress. These values are published on the UI thread, in the + * {@link #onProgressUpdate} step.
  4. + *
  5. {@link #onProgressUpdate}, invoked on the UI thread after a + * call to {@link #publishProgress}. The timing of the execution is + * undefined. This method is used to display any form of progress in the user + * interface while the background computation is still executing. For instance, + * it can be used to animate a progress bar or show logs in a text field.
  6. + *
  7. {@link #onPostExecute}, invoked on the UI thread after the background + * computation finishes. The result of the background computation is passed to + * this step as a parameter.
  8. + *
+ * + *

Cancelling a task

+ *

A task can be cancelled at any time by invoking {@link #cancel(boolean)}. Invoking + * this method will cause subsequent calls to {@link #isCancelled()} to return true. + * After invoking this method, {@link #onCancelled(Object)}, instead of + * {@link #onPostExecute(Object)} will be invoked after {@link #doInBackground(Object[])} + * returns. To ensure that a task is cancelled as quickly as possible, you should always + * check the return value of {@link #isCancelled()} periodically from + * {@link #doInBackground(Object[])}, if possible (inside a loop for instance.)

+ * + *

Threading rules

+ *

There are a few threading rules that must be followed for this class to + * work properly:

+ *
    + *
  • The AsyncTask class must be loaded on the UI thread. This is done + * automatically as of {@link android.os.Build.VERSION_CODES#JELLY_BEAN}.
  • + *
  • The task instance must be created on the UI thread.
  • + *
  • {@link #execute} must be invoked on the UI thread.
  • + *
  • Do not call {@link #onPreExecute()}, {@link #onPostExecute}, + * {@link #doInBackground}, {@link #onProgressUpdate} manually.
  • + *
  • The task can be executed only once (an exception will be thrown if + * a second execution is attempted.)
  • + *
+ * + *

Memory observability

+ *

AsyncTask guarantees that all callback calls are synchronized in such a way that the following + * operations are safe without explicit synchronizations.

+ *
    + *
  • Set member fields in the constructor or {@link #onPreExecute}, and refer to them + * in {@link #doInBackground}. + *
  • Set member fields in {@link #doInBackground}, and refer to them in + * {@link #onProgressUpdate} and {@link #onPostExecute}. + *
+ * + *

Order of execution

+ *

When first introduced, AsyncTasks were executed serially on a single background + * thread. Starting with {@link android.os.Build.VERSION_CODES#DONUT}, this was changed + * to a pool of threads allowing multiple tasks to operate in parallel. Starting with + * {@link android.os.Build.VERSION_CODES#HONEYCOMB}, tasks are executed on a single + * thread to avoid common application errors caused by parallel execution.

+ *

If you truly want parallel execution, you can invoke + * {@link #executeOnExecutor(Executor, Object[])} with + * {@link #THREAD_POOL_EXECUTOR}.

+ */ +public abstract class AsyncTask { + private static final String LOG_TAG = "AsyncTask"; + + private static final int CORE_POOL_SIZE = 5; + private static final int MAXIMUM_POOL_SIZE = 128; + private static final int KEEP_ALIVE = 1; + + private static final ThreadFactory sThreadFactory = new ThreadFactory() { + private final AtomicInteger mCount = new AtomicInteger(1); + + public Thread newThread(Runnable r) { + return new Thread(r, "AsyncTask #" + mCount.getAndIncrement()); + } + }; + + private static final BlockingQueue sPoolWorkQueue = + new LinkedBlockingQueue(10); + + /** + * An {@link Executor} that can be used to execute tasks in parallel. + */ + public static final Executor THREAD_POOL_EXECUTOR + = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, + TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory, + new ThreadPoolExecutor.DiscardOldestPolicy()); + + /** + * An {@link Executor} that executes tasks one at a time in serial + * order. This serialization is global to a particular process. + */ + public static final Executor SERIAL_EXECUTOR = Utils.hasHoneycomb() ? new SerialExecutor() : + Executors.newSingleThreadExecutor(sThreadFactory); + + public static final Executor DUAL_THREAD_EXECUTOR = + Executors.newFixedThreadPool(2, sThreadFactory); + + private static final int MESSAGE_POST_RESULT = 0x1; + private static final int MESSAGE_POST_PROGRESS = 0x2; + + private static final InternalHandler sHandler = new InternalHandler(); + + private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; + private final WorkerRunnable mWorker; + private final FutureTask mFuture; + + private volatile Status mStatus = Status.PENDING; + + private final AtomicBoolean mCancelled = new AtomicBoolean(); + private final AtomicBoolean mTaskInvoked = new AtomicBoolean(); + + @TargetApi(11) + private static class SerialExecutor implements Executor { + final ArrayDeque mTasks = new ArrayDeque(); + Runnable mActive; + + public synchronized void execute(final Runnable r) { + mTasks.offer(new Runnable() { + public void run() { + try { + r.run(); + } finally { + scheduleNext(); + } + } + }); + if (mActive == null) { + scheduleNext(); + } + } + + protected synchronized void scheduleNext() { + if ((mActive = mTasks.poll()) != null) { + THREAD_POOL_EXECUTOR.execute(mActive); + } + } + } + + /** + * Indicates the current status of the task. Each status will be set only once + * during the lifetime of a task. + */ + public enum Status { + /** + * Indicates that the task has not been executed yet. + */ + PENDING, + /** + * Indicates that the task is running. + */ + RUNNING, + /** + * Indicates that {@link AsyncTask#onPostExecute} has finished. + */ + FINISHED, + } + + /** @hide Used to force static handler to be created. */ + public static void init() { + sHandler.getLooper(); + } + + /** @hide */ + public static void setDefaultExecutor(Executor exec) { + sDefaultExecutor = exec; + } + + /** + * Creates a new asynchronous task. This constructor must be invoked on the UI thread. + */ + public AsyncTask() { + mWorker = new WorkerRunnable() { + public Result call() throws Exception { + mTaskInvoked.set(true); + + Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); + //noinspection unchecked + return postResult(doInBackground(mParams)); + } + }; + + mFuture = new FutureTask(mWorker) { + @Override + protected void done() { + try { + postResultIfNotInvoked(get()); + } catch (InterruptedException e) { + android.util.Log.w(LOG_TAG, e); + } catch (ExecutionException e) { + throw new RuntimeException("An error occured while executing doInBackground()", + e.getCause()); + } catch (CancellationException e) { + postResultIfNotInvoked(null); + } + } + }; + } + + private void postResultIfNotInvoked(Result result) { + final boolean wasTaskInvoked = mTaskInvoked.get(); + if (!wasTaskInvoked) { + postResult(result); + } + } + + private Result postResult(Result result) { + @SuppressWarnings("unchecked") + Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT, + new AsyncTaskResult(this, result)); + message.sendToTarget(); + return result; + } + + /** + * Returns the current status of this task. + * + * @return The current status. + */ + public final Status getStatus() { + return mStatus; + } + + /** + * Override this method to perform a computation on a background thread. The + * specified parameters are the parameters passed to {@link #execute} + * by the caller of this task. + * + * This method can call {@link #publishProgress} to publish updates + * on the UI thread. + * + * @param params The parameters of the task. + * + * @return A result, defined by the subclass of this task. + * + * @see #onPreExecute() + * @see #onPostExecute + * @see #publishProgress + */ + protected abstract Result doInBackground(Params... params); + + /** + * Runs on the UI thread before {@link #doInBackground}. + * + * @see #onPostExecute + * @see #doInBackground + */ + protected void onPreExecute() { + } + + /** + *

Runs on the UI thread after {@link #doInBackground}. The + * specified result is the value returned by {@link #doInBackground}.

+ * + *

This method won't be invoked if the task was cancelled.

+ * + * @param result The result of the operation computed by {@link #doInBackground}. + * + * @see #onPreExecute + * @see #doInBackground + * @see #onCancelled(Object) + */ + @SuppressWarnings({"UnusedDeclaration"}) + protected void onPostExecute(Result result) { + } + + /** + * Runs on the UI thread after {@link #publishProgress} is invoked. + * The specified values are the values passed to {@link #publishProgress}. + * + * @param values The values indicating progress. + * + * @see #publishProgress + * @see #doInBackground + */ + @SuppressWarnings({"UnusedDeclaration"}) + protected void onProgressUpdate(Progress... values) { + } + + /** + *

Runs on the UI thread after {@link #cancel(boolean)} is invoked and + * {@link #doInBackground(Object[])} has finished.

+ * + *

The default implementation simply invokes {@link #onCancelled()} and + * ignores the result. If you write your own implementation, do not call + * super.onCancelled(result).

+ * + * @param result The result, if any, computed in + * {@link #doInBackground(Object[])}, can be null + * + * @see #cancel(boolean) + * @see #isCancelled() + */ + @SuppressWarnings({"UnusedParameters"}) + protected void onCancelled(Result result) { + onCancelled(); + } + + /** + *

Applications should preferably override {@link #onCancelled(Object)}. + * This method is invoked by the default implementation of + * {@link #onCancelled(Object)}.

+ * + *

Runs on the UI thread after {@link #cancel(boolean)} is invoked and + * {@link #doInBackground(Object[])} has finished.

+ * + * @see #onCancelled(Object) + * @see #cancel(boolean) + * @see #isCancelled() + */ + protected void onCancelled() { + } + + /** + * Returns true if this task was cancelled before it completed + * normally. If you are calling {@link #cancel(boolean)} on the task, + * the value returned by this method should be checked periodically from + * {@link #doInBackground(Object[])} to end the task as soon as possible. + * + * @return true if task was cancelled before it completed + * + * @see #cancel(boolean) + */ + public final boolean isCancelled() { + return mCancelled.get(); + } + + /** + *

Attempts to cancel execution of this task. This attempt will + * fail if the task has already completed, already been cancelled, + * or could not be cancelled for some other reason. If successful, + * and this task has not started when cancel is called, + * this task should never run. If the task has already started, + * then the mayInterruptIfRunning parameter determines + * whether the thread executing this task should be interrupted in + * an attempt to stop the task.

+ * + *

Calling this method will result in {@link #onCancelled(Object)} being + * invoked on the UI thread after {@link #doInBackground(Object[])} + * returns. Calling this method guarantees that {@link #onPostExecute(Object)} + * is never invoked. After invoking this method, you should check the + * value returned by {@link #isCancelled()} periodically from + * {@link #doInBackground(Object[])} to finish the task as early as + * possible.

+ * + * @param mayInterruptIfRunning true if the thread executing this + * task should be interrupted; otherwise, in-progress tasks are allowed + * to complete. + * + * @return false if the task could not be cancelled, + * typically because it has already completed normally; + * true otherwise + * + * @see #isCancelled() + * @see #onCancelled(Object) + */ + public final boolean cancel(boolean mayInterruptIfRunning) { + mCancelled.set(true); + return mFuture.cancel(mayInterruptIfRunning); + } + + /** + * Waits if necessary for the computation to complete, and then + * retrieves its result. + * + * @return The computed result. + * + * @throws CancellationException If the computation was cancelled. + * @throws ExecutionException If the computation threw an exception. + * @throws InterruptedException If the current thread was interrupted + * while waiting. + */ + public final Result get() throws InterruptedException, ExecutionException { + return mFuture.get(); + } + + /** + * Waits if necessary for at most the given time for the computation + * to complete, and then retrieves its result. + * + * @param timeout Time to wait before cancelling the operation. + * @param unit The time unit for the timeout. + * + * @return The computed result. + * + * @throws CancellationException If the computation was cancelled. + * @throws ExecutionException If the computation threw an exception. + * @throws InterruptedException If the current thread was interrupted + * while waiting. + * @throws TimeoutException If the wait timed out. + */ + public final Result get(long timeout, TimeUnit unit) throws InterruptedException, + ExecutionException, TimeoutException { + return mFuture.get(timeout, unit); + } + + /** + * Executes the task with the specified parameters. The task returns + * itself (this) so that the caller can keep a reference to it. + * + *

Note: this function schedules the task on a queue for a single background + * thread or pool of threads depending on the platform version. When first + * introduced, AsyncTasks were executed serially on a single background thread. + * Starting with {@link android.os.Build.VERSION_CODES#DONUT}, this was changed + * to a pool of threads allowing multiple tasks to operate in parallel. Starting + * {@link android.os.Build.VERSION_CODES#HONEYCOMB}, tasks are back to being + * executed on a single thread to avoid common application errors caused + * by parallel execution. If you truly want parallel execution, you can use + * the {@link #executeOnExecutor} version of this method + * with {@link #THREAD_POOL_EXECUTOR}; however, see commentary there for warnings + * on its use. + * + *

This method must be invoked on the UI thread. + * + * @param params The parameters of the task. + * + * @return This instance of AsyncTask. + * + * @throws IllegalStateException If {@link #getStatus()} returns either + * {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}. + * + * @see #executeOnExecutor(Executor, Object[]) + * @see #execute(Runnable) + */ + public final AsyncTask execute(Params... params) { + return executeOnExecutor(sDefaultExecutor, params); + } + + /** + * Executes the task with the specified parameters. The task returns + * itself (this) so that the caller can keep a reference to it. + * + *

This method is typically used with {@link #THREAD_POOL_EXECUTOR} to + * allow multiple tasks to run in parallel on a pool of threads managed by + * AsyncTask, however you can also use your own {@link Executor} for custom + * behavior. + * + *

Warning: Allowing multiple tasks to run in parallel from + * a thread pool is generally not what one wants, because the order + * of their operation is not defined. For example, if these tasks are used + * to modify any state in common (such as writing a file due to a button click), + * there are no guarantees on the order of the modifications. + * Without careful work it is possible in rare cases for the newer version + * of the data to be over-written by an older one, leading to obscure data + * loss and stability issues. Such changes are best + * executed in serial; to guarantee such work is serialized regardless of + * platform version you can use this function with {@link #SERIAL_EXECUTOR}. + * + *

This method must be invoked on the UI thread. + * + * @param exec The executor to use. {@link #THREAD_POOL_EXECUTOR} is available as a + * convenient process-wide thread pool for tasks that are loosely coupled. + * @param params The parameters of the task. + * + * @return This instance of AsyncTask. + * + * @throws IllegalStateException If {@link #getStatus()} returns either + * {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}. + * + * @see #execute(Object[]) + */ + public final AsyncTask executeOnExecutor(Executor exec, + Params... params) { + if (mStatus != Status.PENDING) { + switch (mStatus) { + case RUNNING: + throw new IllegalStateException("Cannot execute task:" + + " the task is already running."); + case FINISHED: + throw new IllegalStateException("Cannot execute task:" + + " the task has already been executed " + + "(a task can be executed only once)"); + } + } + + mStatus = Status.RUNNING; + + onPreExecute(); + + mWorker.mParams = params; + exec.execute(mFuture); + + return this; + } + + /** + * Convenience version of {@link #execute(Object...)} for use with + * a simple Runnable object. See {@link #execute(Object[])} for more + * information on the order of execution. + * + * @see #execute(Object[]) + * @see #executeOnExecutor(Executor, Object[]) + */ + public static void execute(Runnable runnable) { + sDefaultExecutor.execute(runnable); + } + + /** + * This method can be invoked from {@link #doInBackground} to + * publish updates on the UI thread while the background computation is + * still running. Each call to this method will trigger the execution of + * {@link #onProgressUpdate} on the UI thread. + * + * {@link #onProgressUpdate} will note be called if the task has been + * canceled. + * + * @param values The progress values to update the UI with. + * + * @see #onProgressUpdate + * @see #doInBackground + */ + protected final void publishProgress(Progress... values) { + if (!isCancelled()) { + sHandler.obtainMessage(MESSAGE_POST_PROGRESS, + new AsyncTaskResult(this, values)).sendToTarget(); + } + } + + private void finish(Result result) { + if (isCancelled()) { + onCancelled(result); + } else { + onPostExecute(result); + } + mStatus = Status.FINISHED; + } + + private static class InternalHandler extends Handler { + @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"}) + @Override + public void handleMessage(Message msg) { + AsyncTaskResult result = (AsyncTaskResult) msg.obj; + switch (msg.what) { + case MESSAGE_POST_RESULT: + // There is only one result + result.mTask.finish(result.mData[0]); + break; + case MESSAGE_POST_PROGRESS: + result.mTask.onProgressUpdate(result.mData); + break; + } + } + } + + private static abstract class WorkerRunnable implements Callable { + Params[] mParams; + } + + @SuppressWarnings({"RawUseOfParameterizedType"}) + private static class AsyncTaskResult { + final AsyncTask mTask; + final Data[] mData; + + AsyncTaskResult(AsyncTask task, Data... data) { + mTask = task; + mData = data; + } + } +} \ No newline at end of file diff --git a/opensrp-sdidtk/src/main/java/util/DiskLruCache.java b/opensrp-sdidtk/src/main/java/util/DiskLruCache.java new file mode 100644 index 000000000..e460d1eae --- /dev/null +++ b/opensrp-sdidtk/src/main/java/util/DiskLruCache.java @@ -0,0 +1,953 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package util; + +import java.io.BufferedInputStream; +import java.io.BufferedWriter; +import java.io.Closeable; +import java.io.EOFException; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.StringWriter; +import java.io.Writer; +import java.lang.reflect.Array; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + ****************************************************************************** + * Taken from the JB source code, can be found in: + * libcore/luni/src/main/java/libcore/io/DiskLruCache.java + * or direct link: + * https://android.googlesource.com/platform/libcore/+/android-4.1.1_r1/luni/src/main/java/libcore/io/DiskLruCache.java + ****************************************************************************** + * + * A cache that uses a bounded amount of space on a filesystem. Each cache + * entry has a string key and a fixed number of values. Values are byte + * sequences, accessible as streams or files. Each value must be between {@code + * 0} and {@code Integer.MAX_VALUE} bytes in length. + * + *

The cache stores its data in a directory on the filesystem. This + * directory must be exclusive to the cache; the cache may delete or overwrite + * files from its directory. It is an error for multiple processes to use the + * same cache directory at the same time. + * + *

This cache limits the number of bytes that it will store on the + * filesystem. When the number of stored bytes exceeds the limit, the cache will + * remove entries in the background until the limit is satisfied. The limit is + * not strict: the cache may temporarily exceed it while waiting for files to be + * deleted. The limit does not include filesystem overhead or the cache + * journal so space-sensitive applications should set a conservative limit. + * + *

Clients call {@link #edit} to create or update the values of an entry. An + * entry may have only one editor at one time; if a value is not available to be + * edited then {@link #edit} will return null. + *

    + *
  • When an entry is being created it is necessary to + * supply a full set of values; the empty value should be used as a + * placeholder if necessary. + *
  • When an entry is being edited, it is not necessary + * to supply data for every value; values default to their previous + * value. + *
+ * Every {@link #edit} call must be matched by a call to {@link Editor#commit} + * or {@link Editor#abort}. Committing is atomic: a read observes the full set + * of values as they were before or after the commit, but never a mix of values. + * + *

Clients call {@link #get} to read a snapshot of an entry. The read will + * observe the value at the time that {@link #get} was called. Updates and + * removals after the call do not impact ongoing reads. + * + *

This class is tolerant of some I/O errors. If files are missing from the + * filesystem, the corresponding entries will be dropped from the cache. If + * an error occurs while writing a cache value, the edit will fail silently. + * Callers should handle other problems by catching {@code IOException} and + * responding appropriately. + */ +public final class DiskLruCache implements Closeable { + static final String JOURNAL_FILE = "journal"; + static final String JOURNAL_FILE_TMP = "journal.tmp"; + static final String MAGIC = "libcore.io.DiskLruCache"; + static final String VERSION_1 = "1"; + static final long ANY_SEQUENCE_NUMBER = -1; + private static final String CLEAN = "CLEAN"; + private static final String DIRTY = "DIRTY"; + private static final String REMOVE = "REMOVE"; + private static final String READ = "READ"; + + private static final Charset UTF_8 = Charset.forName("UTF-8"); + private static final int IO_BUFFER_SIZE = 8 * 1024; + + /* + * This cache uses a journal file named "journal". A typical journal file + * looks like this: + * libcore.io.DiskLruCache + * 1 + * 100 + * 2 + * + * CLEAN 3400330d1dfc7f3f7f4b8d4d803dfcf6 832 21054 + * DIRTY 335c4c6028171cfddfbaae1a9c313c52 + * CLEAN 335c4c6028171cfddfbaae1a9c313c52 3934 2342 + * REMOVE 335c4c6028171cfddfbaae1a9c313c52 + * DIRTY 1ab96a171faeeee38496d8b330771a7a + * CLEAN 1ab96a171faeeee38496d8b330771a7a 1600 234 + * READ 335c4c6028171cfddfbaae1a9c313c52 + * READ 3400330d1dfc7f3f7f4b8d4d803dfcf6 + * + * The first five lines of the journal form its header. They are the + * constant string "libcore.io.DiskLruCache", the disk cache's version, + * the application's version, the value count, and a blank line. + * + * Each of the subsequent lines in the file is a record of the state of a + * cache entry. Each line contains space-separated values: a state, a key, + * and optional state-specific values. + * o DIRTY lines track that an entry is actively being created or updated. + * Every successful DIRTY action should be followed by a CLEAN or REMOVE + * action. DIRTY lines without a matching CLEAN or REMOVE indicate that + * temporary files may need to be deleted. + * o CLEAN lines track a cache entry that has been successfully published + * and may be read. A publish line is followed by the lengths of each of + * its values. + * o READ lines track accesses for LRU. + * o REMOVE lines track entries that have been deleted. + * + * The journal file is appended to as cache operations occur. The journal may + * occasionally be compacted by dropping redundant lines. A temporary file named + * "journal.tmp" will be used during compaction; that file should be deleted if + * it exists when the cache is opened. + */ + + private final File directory; + private final File journalFile; + private final File journalFileTmp; + private final int appVersion; + private final long maxSize; + private final int valueCount; + private long size = 0; + private Writer journalWriter; + private final LinkedHashMap lruEntries + = new LinkedHashMap(0, 0.75f, true); + private int redundantOpCount; + + /** + * To differentiate between old and current snapshots, each entry is given + * a sequence number each time an edit is committed. A snapshot is stale if + * its sequence number is not equal to its entry's sequence number. + */ + private long nextSequenceNumber = 0; + + /* From java.util.Arrays */ + @SuppressWarnings("unchecked") + private static T[] copyOfRange(T[] original, int start, int end) { + final int originalLength = original.length; // For exception priority compatibility. + if (start > end) { + throw new IllegalArgumentException(); + } + if (start < 0 || start > originalLength) { + throw new ArrayIndexOutOfBoundsException(); + } + final int resultLength = end - start; + final int copyLength = Math.min(resultLength, originalLength - start); + final T[] result = (T[]) Array + .newInstance(original.getClass().getComponentType(), resultLength); + System.arraycopy(original, start, result, 0, copyLength); + return result; + } + + /** + * Returns the remainder of 'reader' as a string, closing it when done. + */ + public static String readFully(Reader reader) throws IOException { + try { + StringWriter writer = new StringWriter(); + char[] buffer = new char[1024]; + int count; + while ((count = reader.read(buffer)) != -1) { + writer.write(buffer, 0, count); + } + return writer.toString(); + } finally { + reader.close(); + } + } + + /** + * Returns the ASCII characters up to but not including the next "\r\n", or + * "\n". + * + * @throws EOFException if the stream is exhausted before the next newline + * character. + */ + public static String readAsciiLine(InputStream in) throws IOException { + // TODO: support UTF-8 here instead + + StringBuilder result = new StringBuilder(80); + while (true) { + int c = in.read(); + if (c == -1) { + throw new EOFException(); + } else if (c == '\n') { + break; + } + + result.append((char) c); + } + int length = result.length(); + if (length > 0 && result.charAt(length - 1) == '\r') { + result.setLength(length - 1); + } + return result.toString(); + } + + /** + * Closes 'closeable', ignoring any checked exceptions. Does nothing if 'closeable' is null. + */ + public static void closeQuietly(Closeable closeable) { + if (closeable != null) { + try { + closeable.close(); + } catch (RuntimeException rethrown) { + throw rethrown; + } catch (Exception ignored) { + } + } + } + + /** + * Recursively delete everything in {@code dir}. + */ + // TODO: this should specify paths as Strings rather than as Files + public static void deleteContents(File dir) throws IOException { + File[] files = dir.listFiles(); + if (files == null) { + throw new IllegalArgumentException("not a directory: " + dir); + } + for (File file : files) { + if (file.isDirectory()) { + deleteContents(file); + } + if (!file.delete()) { + throw new IOException("failed to delete file: " + file); + } + } + } + + /** This cache uses a single background thread to evict entries. */ + private final ExecutorService executorService = new ThreadPoolExecutor(0, 1, + 60L, TimeUnit.SECONDS, new LinkedBlockingQueue()); + private final Callable cleanupCallable = new Callable() { + @Override public Void call() throws Exception { + synchronized (DiskLruCache.this) { + if (journalWriter == null) { + return null; // closed + } + trimToSize(); + if (journalRebuildRequired()) { + rebuildJournal(); + redundantOpCount = 0; + } + } + return null; + } + }; + + private DiskLruCache(File directory, int appVersion, int valueCount, long maxSize) { + this.directory = directory; + this.appVersion = appVersion; + this.journalFile = new File(directory, JOURNAL_FILE); + this.journalFileTmp = new File(directory, JOURNAL_FILE_TMP); + this.valueCount = valueCount; + this.maxSize = maxSize; + } + + /** + * Opens the cache in {@code directory}, creating a cache if none exists + * there. + * + * @param directory a writable directory + * @param appVersion + * @param valueCount the number of values per cache entry. Must be positive. + * @param maxSize the maximum number of bytes this cache should use to store + * @throws IOException if reading or writing the cache directory fails + */ + public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize) + throws IOException { + if (maxSize <= 0) { + throw new IllegalArgumentException("maxSize <= 0"); + } + if (valueCount <= 0) { + throw new IllegalArgumentException("valueCount <= 0"); + } + + // prefer to pick up where we left off + DiskLruCache cache = new DiskLruCache(directory, appVersion, valueCount, maxSize); + if (cache.journalFile.exists()) { + try { + cache.readJournal(); + cache.processJournal(); + cache.journalWriter = new BufferedWriter(new FileWriter(cache.journalFile, true), + IO_BUFFER_SIZE); + return cache; + } catch (IOException journalIsCorrupt) { +// System.logW("DiskLruCache " + directory + " is corrupt: " +// + journalIsCorrupt.getMessage() + ", removing"); + cache.delete(); + } + } + + // create a new empty cache + directory.mkdirs(); + cache = new DiskLruCache(directory, appVersion, valueCount, maxSize); + cache.rebuildJournal(); + return cache; + } + + private void readJournal() throws IOException { + InputStream in = new BufferedInputStream(new FileInputStream(journalFile), IO_BUFFER_SIZE); + try { + String magic = readAsciiLine(in); + String version = readAsciiLine(in); + String appVersionString = readAsciiLine(in); + String valueCountString = readAsciiLine(in); + String blank = readAsciiLine(in); + if (!MAGIC.equals(magic) + || !VERSION_1.equals(version) + || !Integer.toString(appVersion).equals(appVersionString) + || !Integer.toString(valueCount).equals(valueCountString) + || !"".equals(blank)) { + throw new IOException("unexpected journal header: [" + + magic + ", " + version + ", " + valueCountString + ", " + blank + "]"); + } + + while (true) { + try { + readJournalLine(readAsciiLine(in)); + } catch (EOFException endOfJournal) { + break; + } + } + } finally { + closeQuietly(in); + } + } + + private void readJournalLine(String line) throws IOException { + String[] parts = line.split(" "); + if (parts.length < 2) { + throw new IOException("unexpected journal line: " + line); + } + + String key = parts[1]; + if (parts[0].equals(REMOVE) && parts.length == 2) { + lruEntries.remove(key); + return; + } + + Entry entry = lruEntries.get(key); + if (entry == null) { + entry = new Entry(key); + lruEntries.put(key, entry); + } + + if (parts[0].equals(CLEAN) && parts.length == 2 + valueCount) { + entry.readable = true; + entry.currentEditor = null; + entry.setLengths(copyOfRange(parts, 2, parts.length)); + } else if (parts[0].equals(DIRTY) && parts.length == 2) { + entry.currentEditor = new Editor(entry); + } else if (parts[0].equals(READ) && parts.length == 2) { + // this work was already done by calling lruEntries.get() + } else { + throw new IOException("unexpected journal line: " + line); + } + } + + /** + * Computes the initial size and collects garbage as a part of opening the + * cache. Dirty entries are assumed to be inconsistent and will be deleted. + */ + private void processJournal() throws IOException { + deleteIfExists(journalFileTmp); + for (Iterator i = lruEntries.values().iterator(); i.hasNext(); ) { + Entry entry = i.next(); + if (entry.currentEditor == null) { + for (int t = 0; t < valueCount; t++) { + size += entry.lengths[t]; + } + } else { + entry.currentEditor = null; + for (int t = 0; t < valueCount; t++) { + deleteIfExists(entry.getCleanFile(t)); + deleteIfExists(entry.getDirtyFile(t)); + } + i.remove(); + } + } + } + + /** + * Creates a new journal that omits redundant information. This replaces the + * current journal if it exists. + */ + private synchronized void rebuildJournal() throws IOException { + if (journalWriter != null) { + journalWriter.close(); + } + + Writer writer = new BufferedWriter(new FileWriter(journalFileTmp), IO_BUFFER_SIZE); + writer.write(MAGIC); + writer.write("\n"); + writer.write(VERSION_1); + writer.write("\n"); + writer.write(Integer.toString(appVersion)); + writer.write("\n"); + writer.write(Integer.toString(valueCount)); + writer.write("\n"); + writer.write("\n"); + + for (Entry entry : lruEntries.values()) { + if (entry.currentEditor != null) { + writer.write(DIRTY + ' ' + entry.key + '\n'); + } else { + writer.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n'); + } + } + + writer.close(); + journalFileTmp.renameTo(journalFile); + journalWriter = new BufferedWriter(new FileWriter(journalFile, true), IO_BUFFER_SIZE); + } + + private static void deleteIfExists(File file) throws IOException { +// try { +// Libcore.os.remove(file.getPath()); +// } catch (ErrnoException errnoException) { +// if (errnoException.errno != OsConstants.ENOENT) { +// throw errnoException.rethrowAsIOException(); +// } +// } + if (file.exists() && !file.delete()) { + throw new IOException(); + } + } + + /** + * Returns a snapshot of the entry named {@code key}, or null if it doesn't + * exist is not currently readable. If a value is returned, it is moved to + * the head of the LRU queue. + */ + public synchronized Snapshot get(String key) throws IOException { + checkNotClosed(); + validateKey(key); + Entry entry = lruEntries.get(key); + if (entry == null) { + return null; + } + + if (!entry.readable) { + return null; + } + + /* + * Open all streams eagerly to guarantee that we see a single published + * snapshot. If we opened streams lazily then the streams could come + * from different edits. + */ + InputStream[] ins = new InputStream[valueCount]; + try { + for (int i = 0; i < valueCount; i++) { + ins[i] = new FileInputStream(entry.getCleanFile(i)); + } + } catch (FileNotFoundException e) { + // a file must have been deleted manually! + return null; + } + + redundantOpCount++; + journalWriter.append(READ + ' ' + key + '\n'); + if (journalRebuildRequired()) { + executorService.submit(cleanupCallable); + } + + return new Snapshot(key, entry.sequenceNumber, ins); + } + + /** + * Returns an editor for the entry named {@code key}, or null if another + * edit is in progress. + */ + public Editor edit(String key) throws IOException { + return edit(key, ANY_SEQUENCE_NUMBER); + } + + private synchronized Editor edit(String key, long expectedSequenceNumber) throws IOException { + checkNotClosed(); + validateKey(key); + Entry entry = lruEntries.get(key); + if (expectedSequenceNumber != ANY_SEQUENCE_NUMBER + && (entry == null || entry.sequenceNumber != expectedSequenceNumber)) { + return null; // snapshot is stale + } + if (entry == null) { + entry = new Entry(key); + lruEntries.put(key, entry); + } else if (entry.currentEditor != null) { + return null; // another edit is in progress + } + + Editor editor = new Editor(entry); + entry.currentEditor = editor; + + // flush the journal before creating files to prevent file leaks + journalWriter.write(DIRTY + ' ' + key + '\n'); + journalWriter.flush(); + return editor; + } + + /** + * Returns the directory where this cache stores its data. + */ + public File getDirectory() { + return directory; + } + + /** + * Returns the maximum number of bytes that this cache should use to store + * its data. + */ + public long maxSize() { + return maxSize; + } + + /** + * Returns the number of bytes currently being used to store the values in + * this cache. This may be greater than the max size if a background + * deletion is pending. + */ + public synchronized long size() { + return size; + } + + private synchronized void completeEdit(Editor editor, boolean success) throws IOException { + Entry entry = editor.entry; + if (entry.currentEditor != editor) { + throw new IllegalStateException(); + } + + // if this edit is creating the entry for the first time, every index must have a value + if (success && !entry.readable) { + for (int i = 0; i < valueCount; i++) { + if (!entry.getDirtyFile(i).exists()) { + editor.abort(); + throw new IllegalStateException("edit didn't create file " + i); + } + } + } + + for (int i = 0; i < valueCount; i++) { + File dirty = entry.getDirtyFile(i); + if (success) { + if (dirty.exists()) { + File clean = entry.getCleanFile(i); + dirty.renameTo(clean); + long oldLength = entry.lengths[i]; + long newLength = clean.length(); + entry.lengths[i] = newLength; + size = size - oldLength + newLength; + } + } else { + deleteIfExists(dirty); + } + } + + redundantOpCount++; + entry.currentEditor = null; + if (entry.readable | success) { + entry.readable = true; + journalWriter.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n'); + if (success) { + entry.sequenceNumber = nextSequenceNumber++; + } + } else { + lruEntries.remove(entry.key); + journalWriter.write(REMOVE + ' ' + entry.key + '\n'); + } + + if (size > maxSize || journalRebuildRequired()) { + executorService.submit(cleanupCallable); + } + } + + /** + * We only rebuild the journal when it will halve the size of the journal + * and eliminate at least 2000 ops. + */ + private boolean journalRebuildRequired() { + final int REDUNDANT_OP_COMPACT_THRESHOLD = 2000; + return redundantOpCount >= REDUNDANT_OP_COMPACT_THRESHOLD + && redundantOpCount >= lruEntries.size(); + } + + /** + * Drops the entry for {@code key} if it exists and can be removed. Entries + * actively being edited cannot be removed. + * + * @return true if an entry was removed. + */ + public synchronized boolean remove(String key) throws IOException { + checkNotClosed(); + validateKey(key); + Entry entry = lruEntries.get(key); + if (entry == null || entry.currentEditor != null) { + return false; + } + + for (int i = 0; i < valueCount; i++) { + File file = entry.getCleanFile(i); + if (!file.delete()) { + throw new IOException("failed to delete " + file); + } + size -= entry.lengths[i]; + entry.lengths[i] = 0; + } + + redundantOpCount++; + journalWriter.append(REMOVE + ' ' + key + '\n'); + lruEntries.remove(key); + + if (journalRebuildRequired()) { + executorService.submit(cleanupCallable); + } + + return true; + } + + /** + * Returns true if this cache has been closed. + */ + public boolean isClosed() { + return journalWriter == null; + } + + private void checkNotClosed() { + if (journalWriter == null) { + throw new IllegalStateException("cache is closed"); + } + } + + /** + * Force buffered operations to the filesystem. + */ + public synchronized void flush() throws IOException { + checkNotClosed(); + trimToSize(); + journalWriter.flush(); + } + + /** + * Closes this cache. Stored values will remain on the filesystem. + */ + public synchronized void close() throws IOException { + if (journalWriter == null) { + return; // already closed + } + for (Entry entry : new ArrayList(lruEntries.values())) { + if (entry.currentEditor != null) { + entry.currentEditor.abort(); + } + } + trimToSize(); + journalWriter.close(); + journalWriter = null; + } + + private void trimToSize() throws IOException { + while (size > maxSize) { +// Map.Entry toEvict = lruEntries.eldest(); + final Map.Entry toEvict = lruEntries.entrySet().iterator().next(); + remove(toEvict.getKey()); + } + } + + /** + * Closes the cache and deletes all of its stored values. This will delete + * all files in the cache directory including files that weren't created by + * the cache. + */ + public void delete() throws IOException { + close(); + deleteContents(directory); + } + + private void validateKey(String key) { + if (key.contains(" ") || key.contains("\n") || key.contains("\r")) { + throw new IllegalArgumentException( + "keys must not contain spaces or newlines: \"" + key + "\""); + } + } + + private static String inputStreamToString(InputStream in) throws IOException { + return readFully(new InputStreamReader(in, UTF_8)); + } + + /** + * A snapshot of the values for an entry. + */ + public final class Snapshot implements Closeable { + private final String key; + private final long sequenceNumber; + private final InputStream[] ins; + + private Snapshot(String key, long sequenceNumber, InputStream[] ins) { + this.key = key; + this.sequenceNumber = sequenceNumber; + this.ins = ins; + } + + /** + * Returns an editor for this snapshot's entry, or null if either the + * entry has changed since this snapshot was created or if another edit + * is in progress. + */ + public Editor edit() throws IOException { + return DiskLruCache.this.edit(key, sequenceNumber); + } + + /** + * Returns the unbuffered stream with the value for {@code index}. + */ + public InputStream getInputStream(int index) { + return ins[index]; + } + + /** + * Returns the string value for {@code index}. + */ + public String getString(int index) throws IOException { + return inputStreamToString(getInputStream(index)); + } + + @Override public void close() { + for (InputStream in : ins) { + closeQuietly(in); + } + } + } + + /** + * Edits the values for an entry. + */ + public final class Editor { + private final Entry entry; + private boolean hasErrors; + + private Editor(Entry entry) { + this.entry = entry; + } + + /** + * Returns an unbuffered input stream to read the last committed value, + * or null if no value has been committed. + */ + public InputStream newInputStream(int index) throws IOException { + synchronized (DiskLruCache.this) { + if (entry.currentEditor != this) { + throw new IllegalStateException(); + } + if (!entry.readable) { + return null; + } + return new FileInputStream(entry.getCleanFile(index)); + } + } + + /** + * Returns the last committed value as a string, or null if no value + * has been committed. + */ + public String getString(int index) throws IOException { + InputStream in = newInputStream(index); + return in != null ? inputStreamToString(in) : null; + } + + /** + * Returns a new unbuffered output stream to write the value at + * {@code index}. If the underlying output stream encounters errors + * when writing to the filesystem, this edit will be aborted when + * {@link #commit} is called. The returned output stream does not throw + * IOExceptions. + */ + public OutputStream newOutputStream(int index) throws IOException { + synchronized (DiskLruCache.this) { + if (entry.currentEditor != this) { + throw new IllegalStateException(); + } + return new FaultHidingOutputStream(new FileOutputStream(entry.getDirtyFile(index))); + } + } + + /** + * Sets the value at {@code index} to {@code value}. + */ + public void set(int index, String value) throws IOException { + Writer writer = null; + try { + writer = new OutputStreamWriter(newOutputStream(index), UTF_8); + writer.write(value); + } finally { + closeQuietly(writer); + } + } + + /** + * Commits this edit so it is visible to readers. This releases the + * edit lock so another edit may be started on the same key. + */ + public void commit() throws IOException { + if (hasErrors) { + completeEdit(this, false); + remove(entry.key); // the previous entry is stale + } else { + completeEdit(this, true); + } + } + + /** + * Aborts this edit. This releases the edit lock so another edit may be + * started on the same key. + */ + public void abort() throws IOException { + completeEdit(this, false); + } + + private class FaultHidingOutputStream extends FilterOutputStream { + private FaultHidingOutputStream(OutputStream out) { + super(out); + } + + @Override public void write(int oneByte) { + try { + out.write(oneByte); + } catch (IOException e) { + hasErrors = true; + } + } + + @Override public void write(byte[] buffer, int offset, int length) { + try { + out.write(buffer, offset, length); + } catch (IOException e) { + hasErrors = true; + } + } + + @Override public void close() { + try { + out.close(); + } catch (IOException e) { + hasErrors = true; + } + } + + @Override public void flush() { + try { + out.flush(); + } catch (IOException e) { + hasErrors = true; + } + } + } + } + + private final class Entry { + private final String key; + + /** Lengths of this entry's files. */ + private final long[] lengths; + + /** True if this entry has ever been published */ + private boolean readable; + + /** The ongoing edit or null if this entry is not being edited. */ + private Editor currentEditor; + + /** The sequence number of the most recently committed edit to this entry. */ + private long sequenceNumber; + + private Entry(String key) { + this.key = key; + this.lengths = new long[valueCount]; + } + + public String getLengths() throws IOException { + StringBuilder result = new StringBuilder(); + for (long size : lengths) { + result.append(' ').append(size); + } + return result.toString(); + } + + /** + * Set lengths using decimal numbers like "10123". + */ + private void setLengths(String[] strings) throws IOException { + if (strings.length != valueCount) { + throw invalidLengths(strings); + } + + try { + for (int i = 0; i < strings.length; i++) { + lengths[i] = Long.parseLong(strings[i]); + } + } catch (NumberFormatException e) { + throw invalidLengths(strings); + } + } + + private IOException invalidLengths(String[] strings) throws IOException { + throw new IOException("unexpected journal line: " + Arrays.toString(strings)); + } + + public File getCleanFile(int i) { + return new File(directory, key + "." + i); + } + + public File getDirtyFile(int i) { + return new File(directory, key + "." + i + ".tmp"); + } + } +} diff --git a/opensrp-sdidtk/src/main/java/util/ImageCache.java b/opensrp-sdidtk/src/main/java/util/ImageCache.java new file mode 100644 index 000000000..98c17b90b --- /dev/null +++ b/opensrp-sdidtk/src/main/java/util/ImageCache.java @@ -0,0 +1,738 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package util; + +import android.annotation.TargetApi; +import android.app.Fragment; +import android.app.FragmentManager; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Bitmap.CompressFormat; +import android.graphics.Bitmap.Config; +import android.graphics.BitmapFactory; +import android.graphics.drawable.BitmapDrawable; +import android.os.Build.VERSION_CODES; +import android.os.Bundle; +import android.os.Environment; +import android.os.StatFs; +import android.util.Log; +import android.util.LruCache; + +import org.ei.opensrp.BuildConfig; + +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.ref.SoftReference; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +/** + * This class handles disk and memory caching of bitmaps in conjunction with the + * {@link ImageWorker} class and its subclasses. Use + * to get an instance of this + * class, although usually a cache should be added directly to an {@link ImageWorker} by calling + * . + */ +public class ImageCache { + private static final String TAG = "ImageCache"; + + // Default memory cache size in kilobytes + private static final int DEFAULT_MEM_CACHE_SIZE = 1024 * 5; // 5MB + + // Default disk cache size in bytes + private static final int DEFAULT_DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB + + // Compression settings when writing images to disk cache + private static final CompressFormat DEFAULT_COMPRESS_FORMAT = CompressFormat.JPEG; + private static final int DEFAULT_COMPRESS_QUALITY = 70; + private static final int DISK_CACHE_INDEX = 0; + + // Constants to easily toggle various caches + private static final boolean DEFAULT_MEM_CACHE_ENABLED = true; + private static final boolean DEFAULT_DISK_CACHE_ENABLED = true; + private static final boolean DEFAULT_INIT_DISK_CACHE_ON_CREATE = false; + + private DiskLruCache mDiskLruCache; + private LruCache mMemoryCache; + private ImageCacheParams mCacheParams; + private final Object mDiskCacheLock = new Object(); + private boolean mDiskCacheStarting = true; + + private Set> mReusableBitmaps; + + /** + * Create a new ImageCache object using the specified parameters. This should not be + * called directly by other classes, instead use + * to fetch an ImageCache + * instance. + * + * @param cacheParams The cache parameters to use to initialize the cache + */ + private ImageCache(ImageCacheParams cacheParams) { + init(cacheParams); + } + + /** + * Return an {@link ImageCache} instance. A {@link RetainFragment} is used to retain the + * ImageCache object across configuration changes such as a change in device orientation. + * + * @param fragmentManager The fragment manager to use when dealing with the retained fragment. + * @param cacheParams The cache parameters to use if the ImageCache needs instantiation. + * @return An existing retained ImageCache object or a new one if one did not exist + */ + public static ImageCache getInstance( + FragmentManager fragmentManager, ImageCacheParams cacheParams) { + + // Search for, or create an instance of the non-UI RetainFragment + final RetainFragment mRetainFragment = findOrCreateRetainFragment(fragmentManager); + + // See if we already have an ImageCache stored in RetainFragment + ImageCache imageCache = (ImageCache) mRetainFragment.getObject(); + + // No existing ImageCache, create one and store it in RetainFragment + if (imageCache == null) { + imageCache = new ImageCache(cacheParams); + mRetainFragment.setObject(imageCache); + } + + return imageCache; + } + + /** + * Initialize the cache, providing all parameters. + * + * @param cacheParams The cache parameters to initialize the cache + */ + private void init(ImageCacheParams cacheParams) { + mCacheParams = cacheParams; + + //BEGIN_INCLUDE(init_memory_cache) + // Set up memory cache + if (mCacheParams.memoryCacheEnabled) { + if (BuildConfig.DEBUG) { + Log.d(TAG, "Memory cache created (size = " + mCacheParams.memCacheSize + ")"); + } + + // If we're running on Honeycomb or newer, create a set of reusable bitmaps that can be + // populated into the inBitmap field of BitmapFactory.Options. Note that the set is + // of SoftReferences which will actually not be very effective due to the garbage + // collector being aggressive clearing Soft/WeakReferences. A better approach + // would be to use a strongly references bitmaps, however this would require some + // balancing of memory usage between this set and the bitmap LruCache. It would also + // require knowledge of the expected size of the bitmaps. From Honeycomb to JellyBean + // the size would need to be precise, from KitKat onward the size would just need to + // be the upper bound (due to changes in how inBitmap can re-use bitmaps). + if (Utils.hasHoneycomb()) { + mReusableBitmaps = + Collections.synchronizedSet(new HashSet>()); + } + + mMemoryCache = new LruCache(mCacheParams.memCacheSize) { + + /** + * Notify the removed entry that is no longer being cached + */ + @Override + protected void entryRemoved(boolean evicted, String key, + BitmapDrawable oldValue, BitmapDrawable newValue) { + if (RecyclingBitmapDrawable.class.isInstance(oldValue)) { + // The removed entry is a recycling drawable, so notify it + // that it has been removed from the memory cache + ((RecyclingBitmapDrawable) oldValue).setIsCached(false); + } else { + // The removed entry is a standard BitmapDrawable + + if (Utils.hasHoneycomb()) { + // We're running on Honeycomb or later, so add the bitmap + // to a SoftReference set for possible use with inBitmap later + mReusableBitmaps.add(new SoftReference(oldValue.getBitmap())); + } + } + } + + /** + * Measure item size in kilobytes rather than units which is more practical + * for a bitmap cache + */ + @Override + protected int sizeOf(String key, BitmapDrawable value) { + final int bitmapSize = getBitmapSize(value) / 1024; + return bitmapSize == 0 ? 1 : bitmapSize; + } + }; + } + //END_INCLUDE(init_memory_cache) + + // By default the disk cache is not initialized here as it should be initialized + // on a separate thread due to disk access. + if (cacheParams.initDiskCacheOnCreate) { + // Set up disk cache + initDiskCache(); + } + } + + /** + * Initializes the disk cache. Note that this includes disk access so this should not be + * executed on the main/UI thread. By default an ImageCache does not initialize the disk + * cache when it is created, instead you should call initDiskCache() to initialize it on a + * background thread. + */ + public void initDiskCache() { + // Set up disk cache + synchronized (mDiskCacheLock) { + if (mDiskLruCache == null || mDiskLruCache.isClosed()) { + File diskCacheDir = mCacheParams.diskCacheDir; + if (mCacheParams.diskCacheEnabled && diskCacheDir != null) { + if (!diskCacheDir.exists()) { + diskCacheDir.mkdirs(); + } + if (getUsableSpace(diskCacheDir) > mCacheParams.diskCacheSize) { + try { + mDiskLruCache = DiskLruCache.open( + diskCacheDir, 1, 1, mCacheParams.diskCacheSize); + if (BuildConfig.DEBUG) { + Log.d(TAG, "Disk cache initialized"); + } + } catch (final IOException e) { + mCacheParams.diskCacheDir = null; + Log.e(TAG, "initDiskCache - " + e); + } + } + } + } + mDiskCacheStarting = false; + mDiskCacheLock.notifyAll(); + } + } + + /** + * Adds a bitmap to both memory and disk cache. + * @param data Unique identifier for the bitmap to store + * @param value The bitmap drawable to store + */ + public void addBitmapToCache(String data, BitmapDrawable value) { + //BEGIN_INCLUDE(add_bitmap_to_cache) + if (data == null || value == null) { + return; + } + + // Add to memory cache + if (mMemoryCache != null) { + if (RecyclingBitmapDrawable.class.isInstance(value)) { + // The removed entry is a recycling drawable, so notify it + // that it has been added into the memory cache + ((RecyclingBitmapDrawable) value).setIsCached(true); + } + mMemoryCache.put(data, value); + } + + synchronized (mDiskCacheLock) { + // Add to disk cache + if (mDiskLruCache != null) { + final String key = hashKeyForDisk(data); + OutputStream out = null; + try { + DiskLruCache.Snapshot snapshot = mDiskLruCache.get(key); + if (snapshot == null) { + final DiskLruCache.Editor editor = mDiskLruCache.edit(key); + if (editor != null) { + out = editor.newOutputStream(DISK_CACHE_INDEX); + value.getBitmap().compress( + mCacheParams.compressFormat, mCacheParams.compressQuality, out); + editor.commit(); + out.close(); + } + } else { + snapshot.getInputStream(DISK_CACHE_INDEX).close(); + } + } catch (final IOException e) { + Log.e(TAG, "addBitmapToCache - " + e); + } catch (Exception e) { + Log.e(TAG, "addBitmapToCache - " + e); + } finally { + try { + if (out != null) { + out.close(); + } + } catch (IOException e) {} + } + } + } + //END_INCLUDE(add_bitmap_to_cache) + } + + /** + * Get from memory cache. + * + * @param data Unique identifier for which item to get + * @return The bitmap drawable if found in cache, null otherwise + */ + public BitmapDrawable getBitmapFromMemCache(String data) { + //BEGIN_INCLUDE(get_bitmap_from_mem_cache) + BitmapDrawable memValue = null; + + if (mMemoryCache != null) { + memValue = mMemoryCache.get(data); + } + + if (BuildConfig.DEBUG && memValue != null) { + Log.d(TAG, "Memory cache hit"); + } + + return memValue; + //END_INCLUDE(get_bitmap_from_mem_cache) + } + + /** + * Get from disk cache. + * + * @param data Unique identifier for which item to get + * @return The bitmap if found in cache, null otherwise + */ + public Bitmap getBitmapFromDiskCache(String data) { + //BEGIN_INCLUDE(get_bitmap_from_disk_cache) + final String key = hashKeyForDisk(data); + Bitmap bitmap = null; + + synchronized (mDiskCacheLock) { + while (mDiskCacheStarting) { + try { + mDiskCacheLock.wait(); + } catch (InterruptedException e) {} + } + if (mDiskLruCache != null) { + InputStream inputStream = null; + try { + final DiskLruCache.Snapshot snapshot = mDiskLruCache.get(key); + if (snapshot != null) { + if (BuildConfig.DEBUG) { + Log.d(TAG, "Disk cache hit"); + } + inputStream = snapshot.getInputStream(DISK_CACHE_INDEX); + if (inputStream != null) { + FileDescriptor fd = ((FileInputStream) inputStream).getFD(); + + // Decode bitmap, but we don't want to sample so give + // MAX_VALUE as the target dimensions + bitmap = ImageResizer.decodeSampledBitmapFromDescriptor( + fd, Integer.MAX_VALUE, Integer.MAX_VALUE, this); + } + } + } catch (final IOException e) { + Log.e(TAG, "getBitmapFromDiskCache - " + e); + } finally { + try { + if (inputStream != null) { + inputStream.close(); + } + } catch (IOException e) {} + } + } + return bitmap; + } + //END_INCLUDE(get_bitmap_from_disk_cache) + } + + /** + * @param options - BitmapFactory.Options with out* options populated + * @return Bitmap that case be used for inBitmap + */ + protected Bitmap getBitmapFromReusableSet(BitmapFactory.Options options) { + //BEGIN_INCLUDE(get_bitmap_from_reusable_set) + Bitmap bitmap = null; + + if (mReusableBitmaps != null && !mReusableBitmaps.isEmpty()) { + synchronized (mReusableBitmaps) { + final Iterator> iterator = mReusableBitmaps.iterator(); + Bitmap item; + + while (iterator.hasNext()) { + item = iterator.next().get(); + + if (null != item && item.isMutable()) { + // Check to see it the item can be used for inBitmap + if (canUseForInBitmap(item, options)) { + bitmap = item; + + // Remove from reusable set so it can't be used again + iterator.remove(); + break; + } + } else { + // Remove from the set if the reference has been cleared. + iterator.remove(); + } + } + } + } + + return bitmap; + //END_INCLUDE(get_bitmap_from_reusable_set) + } + + /** + * Clears both the memory and disk cache associated with this ImageCache object. Note that + * this includes disk access so this should not be executed on the main/UI thread. + */ + public void clearCache() { + if (mMemoryCache != null) { + mMemoryCache.evictAll(); + if (BuildConfig.DEBUG) { + Log.d(TAG, "Memory cache cleared"); + } + } + + synchronized (mDiskCacheLock) { + mDiskCacheStarting = true; + if (mDiskLruCache != null && !mDiskLruCache.isClosed()) { + try { + mDiskLruCache.delete(); + if (BuildConfig.DEBUG) { + Log.d(TAG, "Disk cache cleared"); + } + } catch (IOException e) { + Log.e(TAG, "clearCache - " + e); + } + mDiskLruCache = null; + initDiskCache(); + } + } + } + + /** + * Flushes the disk cache associated with this ImageCache object. Note that this includes + * disk access so this should not be executed on the main/UI thread. + */ + public void flush() { + synchronized (mDiskCacheLock) { + if (mDiskLruCache != null) { + try { + mDiskLruCache.flush(); + if (BuildConfig.DEBUG) { + Log.d(TAG, "Disk cache flushed"); + } + } catch (IOException e) { + Log.e(TAG, "flush - " + e); + } + } + } + } + + /** + * Closes the disk cache associated with this ImageCache object. Note that this includes + * disk access so this should not be executed on the main/UI thread. + */ + public void close() { + synchronized (mDiskCacheLock) { + if (mDiskLruCache != null) { + try { + if (!mDiskLruCache.isClosed()) { + mDiskLruCache.close(); + mDiskLruCache = null; + if (BuildConfig.DEBUG) { + Log.d(TAG, "Disk cache closed"); + } + } + } catch (IOException e) { + Log.e(TAG, "close - " + e); + } + } + } + } + + /** + * A holder class that contains cache parameters. + */ + public static class ImageCacheParams { + public int memCacheSize = DEFAULT_MEM_CACHE_SIZE; + public int diskCacheSize = DEFAULT_DISK_CACHE_SIZE; + public File diskCacheDir; + public CompressFormat compressFormat = DEFAULT_COMPRESS_FORMAT; + public int compressQuality = DEFAULT_COMPRESS_QUALITY; + public boolean memoryCacheEnabled = DEFAULT_MEM_CACHE_ENABLED; + public boolean diskCacheEnabled = DEFAULT_DISK_CACHE_ENABLED; + public boolean initDiskCacheOnCreate = DEFAULT_INIT_DISK_CACHE_ON_CREATE; + + /** + * Create a set of image cache parameters that can be provided to + * or + * . + * @param context A context to use. + * @param diskCacheDirectoryName A unique subdirectory name that will be appended to the + * application cache directory. Usually "cache" or "images" + * is sufficient. + */ + public ImageCacheParams(Context context, String diskCacheDirectoryName) { + diskCacheDir = getDiskCacheDir(context, diskCacheDirectoryName); + } + + /** + * Sets the memory cache size based on a percentage of the max available VM memory. + * Eg. setting percent to 0.2 would set the memory cache to one fifth of the available + * memory. Throws {@link IllegalArgumentException} if percent is < 0.01 or > .8. + * memCacheSize is stored in kilobytes instead of bytes as this will eventually be passed + * to construct a LruCache which takes an int in its constructor. + * + * This value should be chosen carefully based on a number of factors + * Refer to the corresponding Android Training class for more discussion: + * http://developer.android.com/training/displaying-bitmaps/ + * + * @param percent Percent of available app memory to use to size memory cache + */ + public void setMemCacheSizePercent(float percent) { + if (percent < 0.01f || percent > 0.8f) { + throw new IllegalArgumentException("setMemCacheSizePercent - percent must be " + + "between 0.01 and 0.8 (inclusive)"); + } + memCacheSize = Math.round(percent * Runtime.getRuntime().maxMemory() / 1024); + } + } + + /** + * @param candidate - Bitmap to check + * @param targetOptions - Options that have the out* value populated + * @return true if candidate can be used for inBitmap re-use with + * targetOptions + */ + @TargetApi(VERSION_CODES.JELLY_BEAN) + private static boolean canUseForInBitmap( + Bitmap candidate, BitmapFactory.Options targetOptions) { + //BEGIN_INCLUDE(can_use_for_inbitmap) + if (!Utils.hasJellyBean()) { + // On earlier versions, the dimensions must match exactly and the inSampleSize must be 1 + return candidate.getWidth() == targetOptions.outWidth + && candidate.getHeight() == targetOptions.outHeight + && targetOptions.inSampleSize == 1; + } + + // From Android 4.4 (KitKat) onward we can re-use if the byte size of the new bitmap + // is smaller than the reusable bitmap candidate allocation byte count. + int width = targetOptions.outWidth / targetOptions.inSampleSize; + int height = targetOptions.outHeight / targetOptions.inSampleSize; + int byteCount = width * height * getBytesPerPixel(candidate.getConfig()); + return byteCount <= candidate.getByteCount(); + //END_INCLUDE(can_use_for_inbitmap) + } + + /** + * Return the byte usage per pixel of a bitmap based on its configuration. + * @param config The bitmap configuration. + * @return The byte usage per pixel. + */ + private static int getBytesPerPixel(Config config) { + if (config == Config.ARGB_8888) { + return 4; + } else if (config == Config.RGB_565) { + return 2; + } else if (config == Config.ARGB_4444) { + return 2; + } else if (config == Config.ALPHA_8) { + return 1; + } + return 1; + } + + /** + * Get a usable cache directory (external if available, internal otherwise). + * + * @param context The context to use + * @param uniqueName A unique directory name to append to the cache dir + * @return The cache dir + */ + public static File getDiskCacheDir(Context context, String uniqueName) { + // Check if media is mounted or storage is built-in, if so, try and use external cache dir + // otherwise use internal cache dir + final String cachePath = + Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || + !isExternalStorageRemovable() ? getExternalCacheDir(context).getPath() : + context.getCacheDir().getPath(); + + return new File(cachePath + File.separator + uniqueName); + } + + /** + * A hashing method that changes a string (like a URL) into a hash suitable for using as a + * disk filename. + */ + public static String hashKeyForDisk(String key) { + String cacheKey; + try { + final MessageDigest mDigest = MessageDigest.getInstance("MD5"); + mDigest.update(key.getBytes()); + cacheKey = bytesToHexString(mDigest.digest()); + } catch (NoSuchAlgorithmException e) { + cacheKey = String.valueOf(key.hashCode()); + } + return cacheKey; + } + + private static String bytesToHexString(byte[] bytes) { + // http://stackoverflow.com/questions/332079 + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < bytes.length; i++) { + String hex = Integer.toHexString(0xFF & bytes[i]); + if (hex.length() == 1) { + sb.append('0'); + } + sb.append(hex); + } + return sb.toString(); + } + + /** + * Get the size in bytes of a bitmap in a BitmapDrawable. Note that from Android 4.4 (KitKat) + * onward this returns the allocated memory size of the bitmap which can be larger than the + * actual bitmap data byte count (in the case it was re-used). + * + * @param value + * @return size in bytes + */ + @TargetApi(VERSION_CODES.JELLY_BEAN) + public static int getBitmapSize(BitmapDrawable value) { + Bitmap bitmap = value.getBitmap(); + + // From KitKat onward use getAllocationByteCount() as allocated bytes can potentially be + // larger than bitmap byte count. + if (Utils.hasJellyBean()) { + return bitmap.getByteCount(); + } + + if (Utils.hasHoneycombMR1()) { + return bitmap.getByteCount(); + } + + // Pre HC-MR1 + return bitmap.getRowBytes() * bitmap.getHeight(); + } + + /** + * Check if external storage is built-in or removable. + * + * @return True if external storage is removable (like an SD card), false + * otherwise. + */ + @TargetApi(VERSION_CODES.GINGERBREAD) + public static boolean isExternalStorageRemovable() { + if (Utils.hasGingerbread()) { + return Environment.isExternalStorageRemovable(); + } + return true; + } + + /** + * Get the external app cache directory. + * + * @param context The context to use + * @return The external cache dir + */ + @TargetApi(VERSION_CODES.FROYO) + public static File getExternalCacheDir(Context context) { + if (Utils.hasFroyo()) { + return context.getExternalCacheDir(); + } + + // Before Froyo we need to construct the external cache dir ourselves + final String cacheDir = "/Android/data/" + context.getPackageName() + "/cache/"; + return new File(Environment.getExternalStorageDirectory().getPath() + cacheDir); + } + + /** + * Check how much usable space is available at a given path. + * + * @param path The path to check + * @return The space available in bytes + */ + @TargetApi(VERSION_CODES.GINGERBREAD) + public static long getUsableSpace(File path) { + if (Utils.hasGingerbread()) { + return path.getUsableSpace(); + } + final StatFs stats = new StatFs(path.getPath()); + return (long) stats.getBlockSize() * (long) stats.getAvailableBlocks(); + } + + /** + * Locate an existing instance of this Fragment or if not found, create and + * add it using FragmentManager. + * + * @param fm The FragmentManager manager to use. + * @return The existing instance of the Fragment or the new instance if just + * created. + */ + private static RetainFragment findOrCreateRetainFragment(FragmentManager fm) { + //BEGIN_INCLUDE(find_create_retain_fragment) + // Check to see if we have retained the worker fragment. + RetainFragment mRetainFragment = (RetainFragment) fm.findFragmentByTag(TAG); + + // If not retained (or first time running), we need to create and add it. + if (mRetainFragment == null) { + mRetainFragment = new RetainFragment(); + fm.beginTransaction().add(mRetainFragment, TAG).commitAllowingStateLoss(); + } + + return mRetainFragment; + //END_INCLUDE(find_create_retain_fragment) + } + + /** + * A simple non-UI Fragment that stores a single Object and is retained over configuration + * changes. It will be used to retain the ImageCache object. + */ + public static class RetainFragment extends Fragment { + private Object mObject; + + /** + * Empty constructor as per the Fragment documentation + */ + public RetainFragment() {} + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Make sure this Fragment is retained over a configuration change + setRetainInstance(true); + } + + /** + * Store a single object in this Fragment. + * + * @param object The object to store + */ + public void setObject(Object object) { + mObject = object; + } + + /** + * Get the stored object. + * + * @return The stored object + */ + public Object getObject() { + return mObject; + } + } + +} diff --git a/opensrp-sdidtk/src/main/java/util/ImageFetcher.java b/opensrp-sdidtk/src/main/java/util/ImageFetcher.java new file mode 100644 index 000000000..f84a878cb --- /dev/null +++ b/opensrp-sdidtk/src/main/java/util/ImageFetcher.java @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package util; + +import android.content.Context; +import android.graphics.Bitmap; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.os.Build; +import android.util.Log; +import android.widget.Toast; + +import org.ei.opensrp.BuildConfig; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URL; +import java.net.URLConnection; + +/** + * A simple subclass of {@link ImageResizer} that fetches and resizes images fetched from a URL. + */ +public class ImageFetcher extends ImageResizer { + private static final String TAG = "ImageFetcher"; + private static final int HTTP_CACHE_SIZE = 10 * 1024 * 1024; // 10MB + private static final String HTTP_CACHE_DIR = "http"; + private static final int IO_BUFFER_SIZE = 8 * 1024; + + private DiskLruCache mHttpDiskCache; + private File mHttpCacheDir; + private boolean mHttpDiskCacheStarting = true; + private final Object mHttpDiskCacheLock = new Object(); + private static final int DISK_CACHE_INDEX = 0; + + /** + * Initialize providing a target image width and height for the processing images. + * + * @param context + * @param imageWidth + * @param imageHeight + */ + public ImageFetcher(Context context, int imageWidth, int imageHeight) { + super(context, imageWidth, imageHeight); + init(context); + } + + /** + * Initialize providing a single target image size (used for both width and height); + * + * @param context + * @param imageSize + */ + public ImageFetcher(Context context, int imageSize) { + super(context, imageSize); + init(context); + } + + private void init(Context context) { + checkConnection(context); + mHttpCacheDir = ImageCache.getDiskCacheDir(context, HTTP_CACHE_DIR); + } + + @Override + protected void initDiskCacheInternal() { + super.initDiskCacheInternal(); + initHttpDiskCache(); + } + + private void initHttpDiskCache() { + if (!mHttpCacheDir.exists()) { + mHttpCacheDir.mkdirs(); + } + synchronized (mHttpDiskCacheLock) { + if (ImageCache.getUsableSpace(mHttpCacheDir) > HTTP_CACHE_SIZE) { + try { + mHttpDiskCache = DiskLruCache.open(mHttpCacheDir, 1, 1, HTTP_CACHE_SIZE); + if (BuildConfig.DEBUG) { + Log.d(TAG, "HTTP cache initialized"); + } + } catch (IOException e) { + mHttpDiskCache = null; + } + } + mHttpDiskCacheStarting = false; + mHttpDiskCacheLock.notifyAll(); + } + } + + @Override + protected void clearCacheInternal() { + super.clearCacheInternal(); + synchronized (mHttpDiskCacheLock) { + if (mHttpDiskCache != null && !mHttpDiskCache.isClosed()) { + try { + mHttpDiskCache.delete(); + if (BuildConfig.DEBUG) { + Log.d(TAG, "HTTP cache cleared"); + } + } catch (IOException e) { + Log.e(TAG, "clearCacheInternal - " + e); + } + mHttpDiskCache = null; + mHttpDiskCacheStarting = true; + initHttpDiskCache(); + } + } + } + + @Override + protected void flushCacheInternal() { + super.flushCacheInternal(); + synchronized (mHttpDiskCacheLock) { + if (mHttpDiskCache != null) { + try { + mHttpDiskCache.flush(); + if (BuildConfig.DEBUG) { + Log.d(TAG, "HTTP cache flushed"); + } + } catch (IOException e) { + Log.e(TAG, "flush - " + e); + } + } + } + } + + @Override + protected void closeCacheInternal() { + super.closeCacheInternal(); + synchronized (mHttpDiskCacheLock) { + if (mHttpDiskCache != null) { + try { + if (!mHttpDiskCache.isClosed()) { + mHttpDiskCache.close(); + mHttpDiskCache = null; + if (BuildConfig.DEBUG) { + Log.d(TAG, "HTTP cache closed"); + } + } + } catch (IOException e) { + Log.e(TAG, "closeCacheInternal - " + e); + } + } + } + } + + /** + * Simple network connection check. + * + * @param context + */ + private void checkConnection(Context context) { + final ConnectivityManager cm = + (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + final NetworkInfo networkInfo = cm.getActiveNetworkInfo(); + if (networkInfo == null || !networkInfo.isConnectedOrConnecting()) { + Toast.makeText(context, "no network connection", Toast.LENGTH_LONG).show(); + Log.e(TAG, "checkConnection - no connection found"); + } + } + + /** + * The main process method, which will be called by the ImageWorker in the AsyncTask background + * thread. + * + * @param data The data to load the bitmap, in this case, a regular http URL + * @return The downloaded and resized bitmap + */ + private Bitmap processBitmap(String data) { + if (BuildConfig.DEBUG) { + Log.d(TAG, "processBitmap - " + data); + } + + final String key = ImageCache.hashKeyForDisk(data); + FileDescriptor fileDescriptor = null; + FileInputStream fileInputStream = null; + DiskLruCache.Snapshot snapshot; + synchronized (mHttpDiskCacheLock) { + // Wait for disk cache to initialize + while (mHttpDiskCacheStarting) { + try { + mHttpDiskCacheLock.wait(); + } catch (InterruptedException e) {} + } + + if (mHttpDiskCache != null) { + try { + snapshot = mHttpDiskCache.get(key); + if (snapshot == null) { + if (BuildConfig.DEBUG) { + Log.d(TAG, "processBitmap, not found in http cache, downloading..."); + } + DiskLruCache.Editor editor = mHttpDiskCache.edit(key); + if (editor != null) { + if (downloadUrlToStream(data, + editor.newOutputStream(DISK_CACHE_INDEX))) { + editor.commit(); + } else { + editor.abort(); + } + } + snapshot = mHttpDiskCache.get(key); + } + if (snapshot != null) { + fileInputStream = + (FileInputStream) snapshot.getInputStream(DISK_CACHE_INDEX); + fileDescriptor = fileInputStream.getFD(); + } + } catch (IOException e) { + Log.e(TAG, "processBitmap - " + e); + } catch (IllegalStateException e) { + Log.e(TAG, "processBitmap - " + e); + } finally { + if (fileDescriptor == null && fileInputStream != null) { + try { + fileInputStream.close(); + } catch (IOException e) {} + } + } + } + } + + Bitmap bitmap = null; + if (fileDescriptor != null) { + bitmap = decodeSampledBitmapFromDescriptor(fileDescriptor, mImageWidth, + mImageHeight, getImageCache()); + } + if (fileInputStream != null) { + try { + fileInputStream.close(); + } catch (IOException e) {} + } + return bitmap; + } + + @Override + protected Bitmap processBitmap(Object data) { + return processBitmap(String.valueOf(data)); + } + + /** + * Download a bitmap from a URL and write the content to an output stream. + * + * @param urlString The URL to fetch + * @return true if successful, false otherwise + */ + public boolean downloadUrlToStream(String urlString, OutputStream outputStream) { + disableConnectionReuseIfNecessary(); + URLConnection urlConnection = null; + BufferedOutputStream out = null; + BufferedInputStream in = null; + + try { + final URL url = new URL(urlString); + urlConnection = (URLConnection) url.openConnection(); + in = new BufferedInputStream(urlConnection.getInputStream(), IO_BUFFER_SIZE); + out = new BufferedOutputStream(outputStream, IO_BUFFER_SIZE); + + int b; + while ((b = in.read()) != -1) { + out.write(b); + } + return true; + } catch (final IOException e) { + Log.e(TAG, "Error in downloadBitmap - " + e); + } finally { + if (urlConnection != null) { +// urlConnection.disconnect(); + } + try { + if (out != null) { + out.close(); + } + if (in != null) { + in.close(); + } + } catch (final IOException e) {} + } + return false; + } + + /** + * Workaround for bug pre-Froyo, see here for more info: + * http://android-developers.blogspot.com/2011/09/androids-http-clients.html + */ + public static void disableConnectionReuseIfNecessary() { + // HTTP connection reuse which was buggy pre-froyo + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) { + System.setProperty("http.keepAlive", "false"); + } + } +} diff --git a/opensrp-sdidtk/src/main/java/util/ImageResizer.java b/opensrp-sdidtk/src/main/java/util/ImageResizer.java new file mode 100644 index 000000000..7844b2e5f --- /dev/null +++ b/opensrp-sdidtk/src/main/java/util/ImageResizer.java @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package util; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Build; +import android.util.Log; + +import org.ei.opensrp.BuildConfig; + +import java.io.FileDescriptor; + +/** + * A simple subclass of {@link ImageWorker} that resizes images from resources given a target width + * and height. Useful for when the input images might be too large to simply load directly into + * memory. + */ +public class ImageResizer extends ImageWorker { + private static final String TAG = "ImageResizer"; + protected int mImageWidth; + protected int mImageHeight; + + /** + * Initialize providing a single target image size (used for both width and height); + * + * @param context + * @param imageWidth + * @param imageHeight + */ + public ImageResizer(Context context, int imageWidth, int imageHeight) { + super(context); + setImageSize(imageWidth, imageHeight); + } + + /** + * Initialize providing a single target image size (used for both width and height); + * + * @param context + * @param imageSize + */ + public ImageResizer(Context context, int imageSize) { + super(context); + setImageSize(imageSize); + } + + /** + * Set the target image width and height. + * + * @param width + * @param height + */ + public void setImageSize(int width, int height) { + mImageWidth = width; + mImageHeight = height; + } + + /** + * Set the target image size (width and height will be the same). + * + * @param size + */ + public void setImageSize(int size) { + setImageSize(size, size); + } + + /** + * The main processing method. This happens in a background task. In this case we are just + * sampling down the bitmap and returning it from a resource. + * + * @param resId + * @return + */ + private Bitmap processBitmap(int resId) { + if (BuildConfig.DEBUG) { + Log.d(TAG, "processBitmap - " + resId); + } + return decodeSampledBitmapFromResource(mResources, resId, mImageWidth, + mImageHeight, getImageCache()); + } + + @Override + protected Bitmap processBitmap(Object data) { + return processBitmap(Integer.parseInt(String.valueOf(data))); + } + + /** + * Decode and sample down a bitmap from resources to the requested width and height. + * + * @param res The resources object containing the image data + * @param resId The resource id of the image data + * @param reqWidth The requested width of the resulting bitmap + * @param reqHeight The requested height of the resulting bitmap + * @param cache The ImageCache used to find candidate bitmaps for use with inBitmap + * @return A bitmap sampled down from the original with the same aspect ratio and dimensions + * that are equal to or greater than the requested width and height + */ + public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, + int reqWidth, int reqHeight, ImageCache cache) { + + // BEGIN_INCLUDE (read_bitmap_dimensions) + // First decode with inJustDecodeBounds=true to check dimensions + final BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeResource(res, resId, options); + + // Calculate inSampleSize + options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); + // END_INCLUDE (read_bitmap_dimensions) + + // If we're running on Honeycomb or newer, try to use inBitmap + if (Utils.hasHoneycomb()) { + addInBitmapOptions(options, cache); + } + + // Decode bitmap with inSampleSize set + options.inJustDecodeBounds = false; + return BitmapFactory.decodeResource(res, resId, options); + } + + /** + * Decode and sample down a bitmap from a file to the requested width and height. + * + * @param filename The full path of the file to decode + * @param reqWidth The requested width of the resulting bitmap + * @param reqHeight The requested height of the resulting bitmap + * @param cache The ImageCache used to find candidate bitmaps for use with inBitmap + * @return A bitmap sampled down from the original with the same aspect ratio and dimensions + * that are equal to or greater than the requested width and height + */ + public static Bitmap decodeSampledBitmapFromFile(String filename, + int reqWidth, int reqHeight, ImageCache cache) { + + // First decode with inJustDecodeBounds=true to check dimensions + final BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(filename, options); + + // Calculate inSampleSize + options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); + + // If we're running on Honeycomb or newer, try to use inBitmap + if (Utils.hasHoneycomb()) { + addInBitmapOptions(options, cache); + } + + // Decode bitmap with inSampleSize set + options.inJustDecodeBounds = false; + return BitmapFactory.decodeFile(filename, options); + } + + /** + * Decode and sample down a bitmap from a file input stream to the requested width and height. + * + * @param fileDescriptor The file descriptor to read from + * @param reqWidth The requested width of the resulting bitmap + * @param reqHeight The requested height of the resulting bitmap + * @param cache The ImageCache used to find candidate bitmaps for use with inBitmap + * @return A bitmap sampled down from the original with the same aspect ratio and dimensions + * that are equal to or greater than the requested width and height + */ + public static Bitmap decodeSampledBitmapFromDescriptor( + FileDescriptor fileDescriptor, int reqWidth, int reqHeight, ImageCache cache) { + + // First decode with inJustDecodeBounds=true to check dimensions + final BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options); + + // Calculate inSampleSize + options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); + + // Decode bitmap with inSampleSize set + options.inJustDecodeBounds = false; + + // If we're running on Honeycomb or newer, try to use inBitmap + if (Utils.hasHoneycomb()) { + addInBitmapOptions(options, cache); + } + + return BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options); + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + private static void addInBitmapOptions(BitmapFactory.Options options, ImageCache cache) { + //BEGIN_INCLUDE(add_bitmap_options) + // inBitmap only works with mutable bitmaps so force the decoder to + // return mutable bitmaps. + options.inMutable = true; + + if (cache != null) { + // Try and find a bitmap to use for inBitmap + Bitmap inBitmap = cache.getBitmapFromReusableSet(options); + + if (inBitmap != null) { + options.inBitmap = inBitmap; + } + } + //END_INCLUDE(add_bitmap_options) + } + + /** + * Calculate an inSampleSize for use in a {@link BitmapFactory.Options} object when decoding + * bitmaps using the decode* methods from {@link BitmapFactory}. This implementation calculates + * the closest inSampleSize that is a power of 2 and will result in the final decoded bitmap + * having a width and height equal to or larger than the requested width and height. + * + * @param options An options object with out* params already populated (run through a decode* + * method with inJustDecodeBounds==true + * @param reqWidth The requested width of the resulting bitmap + * @param reqHeight The requested height of the resulting bitmap + * @return The value to be used for inSampleSize + */ + public static int calculateInSampleSize(BitmapFactory.Options options, + int reqWidth, int reqHeight) { + // BEGIN_INCLUDE (calculate_sample_size) + // Raw height and width of image + final int height = options.outHeight; + final int width = options.outWidth; + int inSampleSize = 1; + + if (height > reqHeight || width > reqWidth) { + + final int halfHeight = height / 2; + final int halfWidth = width / 2; + + // Calculate the largest inSampleSize value that is a power of 2 and keeps both + // height and width larger than the requested height and width. + while ((halfHeight / inSampleSize) > reqHeight + && (halfWidth / inSampleSize) > reqWidth) { + inSampleSize *= 2; + } + + // This offers some additional logic in case the image has a strange + // aspect ratio. For example, a panorama may have a much larger + // width than height. In these cases the total pixels might still + // end up being too large to fit comfortably in memory, so we should + // be more aggressive with sample down the image (=larger inSampleSize). + + long totalPixels = width * height / inSampleSize; + + // Anything more than 2x the requested pixels we'll sample down further + final long totalReqPixelsCap = reqWidth * reqHeight * 2; + + while (totalPixels > totalReqPixelsCap) { + inSampleSize *= 2; + totalPixels /= 2; + } + } + return inSampleSize; + // END_INCLUDE (calculate_sample_size) + } +} diff --git a/opensrp-sdidtk/src/main/java/util/ImageWorker.java b/opensrp-sdidtk/src/main/java/util/ImageWorker.java new file mode 100644 index 000000000..c98ac626a --- /dev/null +++ b/opensrp-sdidtk/src/main/java/util/ImageWorker.java @@ -0,0 +1,485 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package util; + +import android.app.Activity; +import android.app.FragmentManager; +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.TransitionDrawable; +import android.util.Log; +import android.widget.ImageView; + +import org.ei.opensrp.BuildConfig; + +import java.lang.ref.WeakReference; + +/** + * This class wraps up completing some arbitrary long running work when loading a bitmap to an + * ImageView. It handles things like using a memory and disk cache, running the work in a background + * thread and setting a placeholder image. + */ +public abstract class ImageWorker { + private static final String TAG = "ImageWorker"; + private static final int FADE_IN_TIME = 200; + + private ImageCache mImageCache; + private ImageCache.ImageCacheParams mImageCacheParams; + private Bitmap mLoadingBitmap; + private boolean mFadeInBitmap = true; + private boolean mExitTasksEarly = false; + protected boolean mPauseWork = false; + private final Object mPauseWorkLock = new Object(); + + protected Resources mResources; + + private static final int MESSAGE_CLEAR = 0; + private static final int MESSAGE_INIT_DISK_CACHE = 1; + private static final int MESSAGE_FLUSH = 2; + private static final int MESSAGE_CLOSE = 3; + + protected ImageWorker(Context context) { + mResources = context.getResources(); + } + + /** + * Load an image specified by the data parameter into an ImageView (override + * {@link ImageWorker#processBitmap(Object)} to define the processing logic). A memory and + * disk cache will be used if an {@link ImageCache} has been added using + * . If the + * image is found in the memory cache, it is set immediately, otherwise an {@link AsyncTask} + * will be created to asynchronously load the bitmap. + * + * @param data The URL of the image to download. + * @param imageView The ImageView to bind the downloaded image to. + */ + public void loadImage(Object data, ImageView imageView) { + if (data == null) { + return; + } + + BitmapDrawable value = null; + + if (mImageCache != null) { + value = mImageCache.getBitmapFromMemCache(String.valueOf(data)); + } + + if (value != null) { + // Bitmap found in memory cache + imageView.setImageDrawable(value); + } else if (cancelPotentialWork(data, imageView)) { + //BEGIN_INCLUDE(execute_background_task) + final BitmapWorkerTask task = new BitmapWorkerTask(data, imageView); + final AsyncDrawable asyncDrawable = + new AsyncDrawable(mResources, mLoadingBitmap, task); + imageView.setImageDrawable(asyncDrawable); + + // NOTE: This uses a custom version of AsyncTask that has been pulled from the + // framework and slightly modified. Refer to the docs at the top of the class + // for more info on what was changed. + task.executeOnExecutor(AsyncTask.DUAL_THREAD_EXECUTOR); + //END_INCLUDE(execute_background_task) + } + } + + /** + * Set placeholder bitmap that shows when the the background thread is running. + * + * @param bitmap + */ + public void setLoadingImage(Bitmap bitmap) { + mLoadingBitmap = bitmap; + } + + /** + * Set placeholder bitmap that shows when the the background thread is running. + * + * @param resId + */ + public void setLoadingImage(int resId) { + mLoadingBitmap = BitmapFactory.decodeResource(mResources, resId); + } + + /** + * Adds an {@link ImageCache} to this {@link ImageWorker} to handle disk and memory bitmap + * caching. + * @param fragmentManager + * @param cacheParams The cache parameters to use for the image cache. + */ + public void addImageCache(FragmentManager fragmentManager, + ImageCache.ImageCacheParams cacheParams) { + mImageCacheParams = cacheParams; + mImageCache = ImageCache.getInstance(fragmentManager, mImageCacheParams); + new CacheAsyncTask().execute(MESSAGE_INIT_DISK_CACHE); + } + + /** + * Adds an {@link ImageCache} to this {@link ImageWorker} to handle disk and memory bitmap + * caching. + * @param activity + * @param diskCacheDirectoryName See + * {@link ImageCache.ImageCacheParams#ImageCacheParams(Context, String)}. + */ + public void addImageCache(Activity activity, String diskCacheDirectoryName) { + mImageCacheParams = new ImageCache.ImageCacheParams(activity, diskCacheDirectoryName); + mImageCache = ImageCache.getInstance(activity.getFragmentManager(), mImageCacheParams); + new CacheAsyncTask().execute(MESSAGE_INIT_DISK_CACHE); + } + + /** + * If set to true, the image will fade-in once it has been loaded by the background thread. + */ + public void setImageFadeIn(boolean fadeIn) { + mFadeInBitmap = fadeIn; + } + + public void setExitTasksEarly(boolean exitTasksEarly) { + mExitTasksEarly = exitTasksEarly; + setPauseWork(false); + } + + /** + * Subclasses should override this to define any processing or work that must happen to produce + * the final bitmap. This will be executed in a background thread and be long running. For + * example, you could resize a large bitmap here, or pull down an image from the network. + * + * @param data The data to identify which image to process, as provided by + * {@link ImageWorker#loadImage(Object, ImageView)} + * @return The processed bitmap + */ + protected abstract Bitmap processBitmap(Object data); + + /** + * @return The {@link ImageCache} object currently being used by this ImageWorker. + */ + protected ImageCache getImageCache() { + return mImageCache; + } + + /** + * Cancels any pending work attached to the provided ImageView. + * @param imageView + */ + public static void cancelWork(ImageView imageView) { + final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); + if (bitmapWorkerTask != null) { + bitmapWorkerTask.cancel(true); + if (BuildConfig.DEBUG) { + final Object bitmapData = bitmapWorkerTask.mData; + Log.d(TAG, "cancelWork - cancelled work for " + bitmapData); + } + } + } + + /** + * Returns true if the current work has been canceled or if there was no work in + * progress on this image view. + * Returns false if the work in progress deals with the same data. The work is not + * stopped in that case. + */ + public static boolean cancelPotentialWork(Object data, ImageView imageView) { + //BEGIN_INCLUDE(cancel_potential_work) + final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); + + if (bitmapWorkerTask != null) { + final Object bitmapData = bitmapWorkerTask.mData; + if (bitmapData == null || !bitmapData.equals(data)) { + bitmapWorkerTask.cancel(true); + if (BuildConfig.DEBUG) { + Log.d(TAG, "cancelPotentialWork - cancelled work for " + data); + } + } else { + // The same work is already in progress. + return false; + } + } + return true; + //END_INCLUDE(cancel_potential_work) + } + + /** + * @param imageView Any imageView + * @return Retrieve the currently active work task (if any) associated with this imageView. + * null if there is no such task. + */ + private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { + if (imageView != null) { + final Drawable drawable = imageView.getDrawable(); + if (drawable instanceof AsyncDrawable) { + final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; + return asyncDrawable.getBitmapWorkerTask(); + } + } + return null; + } + + /** + * The actual AsyncTask that will asynchronously process the image. + */ + private class BitmapWorkerTask extends AsyncTask { + private Object mData; + private final WeakReference imageViewReference; + + public BitmapWorkerTask(Object data, ImageView imageView) { + mData = data; + imageViewReference = new WeakReference(imageView); + } + + /** + * Background processing. + */ + @Override + protected BitmapDrawable doInBackground(Void... params) { + //BEGIN_INCLUDE(load_bitmap_in_background) + if (BuildConfig.DEBUG) { + Log.d(TAG, "doInBackground - starting work"); + } + + final String dataString = String.valueOf(mData); + Bitmap bitmap = null; + BitmapDrawable drawable = null; + + // Wait here if work is paused and the task is not cancelled + synchronized (mPauseWorkLock) { + while (mPauseWork && !isCancelled()) { + try { + mPauseWorkLock.wait(); + } catch (InterruptedException e) {} + } + } + + // If the image cache is available and this task has not been cancelled by another + // thread and the ImageView that was originally bound to this task is still bound back + // to this task and our "exit early" flag is not set then try and fetch the bitmap from + // the cache + if (mImageCache != null && !isCancelled() && getAttachedImageView() != null + && !mExitTasksEarly) { + bitmap = mImageCache.getBitmapFromDiskCache(dataString); + } + + // If the bitmap was not found in the cache and this task has not been cancelled by + // another thread and the ImageView that was originally bound to this task is still + // bound back to this task and our "exit early" flag is not set, then call the main + // process method (as implemented by a subclass) + if (bitmap == null && !isCancelled() && getAttachedImageView() != null + && !mExitTasksEarly) { + bitmap = processBitmap(mData); + } + + // If the bitmap was processed and the image cache is available, then add the processed + // bitmap to the cache for future use. Note we don't check if the task was cancelled + // here, if it was, and the thread is still running, we may as well add the processed + // bitmap to our cache as it might be used again in the future + if (bitmap != null) { + if (Utils.hasHoneycomb()) { + // Running on Honeycomb or newer, so wrap in a standard BitmapDrawable + drawable = new BitmapDrawable(mResources, bitmap); + } else { + // Running on Gingerbread or older, so wrap in a RecyclingBitmapDrawable + // which will recycle automagically + drawable = new RecyclingBitmapDrawable(mResources, bitmap); + } + + if (mImageCache != null) { + mImageCache.addBitmapToCache(dataString, drawable); + } + } + + if (BuildConfig.DEBUG) { + Log.d(TAG, "doInBackground - finished work"); + } + + return drawable; + //END_INCLUDE(load_bitmap_in_background) + } + + /** + * Once the image is processed, associates it to the imageView + */ + @Override + protected void onPostExecute(BitmapDrawable value) { + //BEGIN_INCLUDE(complete_background_work) + // if cancel was called on this task or the "exit early" flag is set then we're done + if (isCancelled() || mExitTasksEarly) { + value = null; + } + + final ImageView imageView = getAttachedImageView(); + if (value != null && imageView != null) { + if (BuildConfig.DEBUG) { + Log.d(TAG, "onPostExecute - setting bitmap"); + } + setImageDrawable(imageView, value); + } + //END_INCLUDE(complete_background_work) + } + + @Override + protected void onCancelled(BitmapDrawable value) { + super.onCancelled(value); + synchronized (mPauseWorkLock) { + mPauseWorkLock.notifyAll(); + } + } + + /** + * Returns the ImageView associated with this task as long as the ImageView's task still + * points to this task as well. Returns null otherwise. + */ + private ImageView getAttachedImageView() { + final ImageView imageView = imageViewReference.get(); + final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); + + if (this == bitmapWorkerTask) { + return imageView; + } + + return null; + } + } + + /** + * A custom Drawable that will be attached to the imageView while the work is in progress. + * Contains a reference to the actual worker task, so that it can be stopped if a new binding is + * required, and makes sure that only the last started worker process can bind its result, + * independently of the finish order. + */ + private static class AsyncDrawable extends BitmapDrawable { + private final WeakReference bitmapWorkerTaskReference; + + public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) { + super(res, bitmap); + bitmapWorkerTaskReference = + new WeakReference(bitmapWorkerTask); + } + + public BitmapWorkerTask getBitmapWorkerTask() { + return bitmapWorkerTaskReference.get(); + } + } + + /** + * Called when the processing is complete and the final drawable should be + * set on the ImageView. + * + * @param imageView + * @param drawable + */ + private void setImageDrawable(ImageView imageView, Drawable drawable) { + if (mFadeInBitmap) { + // Transition drawable with a transparent drawable and the final drawable + final TransitionDrawable td = + new TransitionDrawable(new Drawable[] { + new ColorDrawable(android.R.color.transparent), + drawable + }); + // Set background to loading bitmap + imageView.setBackgroundDrawable( + new BitmapDrawable(mResources, mLoadingBitmap)); + + imageView.setImageDrawable(td); + td.startTransition(FADE_IN_TIME); + } else { + imageView.setImageDrawable(drawable); + } + } + + /** + * Pause any ongoing background work. This can be used as a temporary + * measure to improve performance. For example background work could + * be paused when a ListView or GridView is being scrolled using a + * {@link android.widget.AbsListView.OnScrollListener} to keep + * scrolling smooth. + *

+ * If work is paused, be sure setPauseWork(false) is called again + * before your fragment or activity is destroyed (for example during + * {@link Activity#onPause()}), or there is a risk the + * background thread will never finish. + */ + public void setPauseWork(boolean pauseWork) { + synchronized (mPauseWorkLock) { + mPauseWork = pauseWork; + if (!mPauseWork) { + mPauseWorkLock.notifyAll(); + } + } + } + + protected class CacheAsyncTask extends AsyncTask { + + @Override + protected Void doInBackground(Object... params) { + switch ((Integer)params[0]) { + case MESSAGE_CLEAR: + clearCacheInternal(); + break; + case MESSAGE_INIT_DISK_CACHE: + initDiskCacheInternal(); + break; + case MESSAGE_FLUSH: + flushCacheInternal(); + break; + case MESSAGE_CLOSE: + closeCacheInternal(); + break; + } + return null; + } + } + + protected void initDiskCacheInternal() { + if (mImageCache != null) { + mImageCache.initDiskCache(); + } + } + + protected void clearCacheInternal() { + if (mImageCache != null) { + mImageCache.clearCache(); + } + } + + protected void flushCacheInternal() { + if (mImageCache != null) { + mImageCache.flush(); + } + } + + protected void closeCacheInternal() { + if (mImageCache != null) { + mImageCache.close(); + mImageCache = null; + } + } + + public void clearCache() { + new CacheAsyncTask().execute(MESSAGE_CLEAR); + } + + public void flushCache() { + new CacheAsyncTask().execute(MESSAGE_FLUSH); + } + + public void closeCache() { + new CacheAsyncTask().execute(MESSAGE_CLOSE); + } +} diff --git a/opensrp-sdidtk/src/main/java/util/RecyclingBitmapDrawable.java b/opensrp-sdidtk/src/main/java/util/RecyclingBitmapDrawable.java new file mode 100644 index 000000000..acf06c2c9 --- /dev/null +++ b/opensrp-sdidtk/src/main/java/util/RecyclingBitmapDrawable.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package util; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.util.Log; + +import org.ei.opensrp.BuildConfig; + +/** + * A BitmapDrawable that keeps track of whether it is being displayed or cached. + * When the drawable is no longer being displayed or cached, + * {@link Bitmap#recycle() recycle()} will be called on this drawable's bitmap. + */ +public class RecyclingBitmapDrawable extends BitmapDrawable { + + static final String TAG = "CountingBitmapDrawable"; + + private int mCacheRefCount = 0; + private int mDisplayRefCount = 0; + + private boolean mHasBeenDisplayed; + + public RecyclingBitmapDrawable(Resources res, Bitmap bitmap) { + super(res, bitmap); + } + + /** + * Notify the drawable that the displayed state has changed. Internally a + * count is kept so that the drawable knows when it is no longer being + * displayed. + * + * @param isDisplayed - Whether the drawable is being displayed or not + */ + public void setIsDisplayed(boolean isDisplayed) { + //BEGIN_INCLUDE(set_is_displayed) + synchronized (this) { + if (isDisplayed) { + mDisplayRefCount++; + mHasBeenDisplayed = true; + } else { + mDisplayRefCount--; + } + } + + // Check to see if recycle() can be called + checkState(); + //END_INCLUDE(set_is_displayed) + } + + /** + * Notify the drawable that the cache state has changed. Internally a count + * is kept so that the drawable knows when it is no longer being cached. + * + * @param isCached - Whether the drawable is being cached or not + */ + public void setIsCached(boolean isCached) { + //BEGIN_INCLUDE(set_is_cached) + synchronized (this) { + if (isCached) { + mCacheRefCount++; + } else { + mCacheRefCount--; + } + } + + // Check to see if recycle() can be called + checkState(); + //END_INCLUDE(set_is_cached) + } + + private synchronized void checkState() { + //BEGIN_INCLUDE(check_state) + // If the drawable cache and display ref counts = 0, and this drawable + // has been displayed, then recycle + if (mCacheRefCount <= 0 && mDisplayRefCount <= 0 && mHasBeenDisplayed + && hasValidBitmap()) { + if (BuildConfig.DEBUG) { + Log.d(TAG, "No longer being used or cached so recycling. " + + toString()); + } + + getBitmap().recycle(); + } + //END_INCLUDE(check_state) + } + + private synchronized boolean hasValidBitmap() { + Bitmap bitmap = getBitmap(); + return bitmap != null && !bitmap.isRecycled(); + } + +} diff --git a/opensrp-sdidtk/src/main/java/util/Utils.java b/opensrp-sdidtk/src/main/java/util/Utils.java new file mode 100644 index 000000000..c1949d585 --- /dev/null +++ b/opensrp-sdidtk/src/main/java/util/Utils.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package util; + +import android.os.Build; +import android.os.Build.VERSION_CODES; + + +/** + * Class containing some static utility methods. + */ +public class Utils { + private Utils() {}; + + + + + public static boolean hasFroyo() { + // Can use static final constants like FROYO, declared in later versions + // of the OS since they are inlined at compile time. This is guaranteed behavior. + return Build.VERSION.SDK_INT >= VERSION_CODES.FROYO; + } + + public static boolean hasGingerbread() { + return Build.VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD; + } + + public static boolean hasHoneycomb() { + return Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + } + + public static boolean hasHoneycombMR1() { + return Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1; + } + + public static boolean hasJellyBean() { + return Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; + } + +} diff --git a/opensrp-sdidtk/src/main/java/widget/CircleFlowIndicator.java b/opensrp-sdidtk/src/main/java/widget/CircleFlowIndicator.java new file mode 100644 index 000000000..d4bfc57ec --- /dev/null +++ b/opensrp-sdidtk/src/main/java/widget/CircleFlowIndicator.java @@ -0,0 +1,441 @@ +/* + * Copyright (C) 2011 Patrik Åkerfeldt + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Paint.Style; +import android.os.AsyncTask; +import android.util.AttributeSet; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.Animation.AnimationListener; +import android.view.animation.AnimationUtils; + +import org.ei.opensrp.ddtk.R; + + +/** + * A FlowIndicator which draws circles (one for each view). + *
+ * Available attributes are:
+ *

    + *
  • + * activeColor: Define the color used to draw the active circle (default to white) + *
  • + *
  • + * inactiveColor: Define the color used to draw the inactive circles (default to 0x44FFFFFF) + *
  • + *
  • + * inactiveType: Define how to draw the inactive circles, either stroke or fill (default to stroke) + *
  • + *
  • + * activeType: Define how to draw the active circle, either stroke or fill (default to fill) + *
  • + *
  • + * fadeOut: Define the time (in ms) until the indicator will fade out (default to 0 = never fade out) + *
  • + *
  • + * radius: Define the circle outer radius (default to 4.0) + *
  • + *
  • + * spacing: Define the circle spacing (default to 4.0) + *
  • + *
  • + * snap: If true, the 'active' indicator snaps from one page to the next; otherwise, it moves smoothly. + *
  • + *
+ */ +public class CircleFlowIndicator extends View implements FlowIndicator, + AnimationListener { + private static final int STYLE_STROKE = 0; + private static final int STYLE_FILL = 1; + + private float mRadius = 4; + private float mRadiusInactive = 4; + private float mRadiusActive = 4; + private float spacing = 4; + private int fadeOutTime = 0; + private final Paint mPaintInactive = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint mPaintActive = new Paint(Paint.ANTI_ALIAS_FLAG); + private ViewFlow viewFlow; + private int currentScroll = 0; + private int currentPosition = 0; + private int flowWidth = 0; + private FadeTimer timer; + public AnimationListener animationListener = this; + private Animation animation; + private boolean mCentered = false; + private boolean mSnap = false; + + /** + * Default constructor + * + * @param context + */ + public CircleFlowIndicator(Context context) { + super(context); + initColors(0xFFFFFFFF, 0xFFFFFFFF, STYLE_FILL, STYLE_STROKE); + } + + /** + * The contructor used with an inflater + * + * @param context + * @param attrs + */ + public CircleFlowIndicator(Context context, AttributeSet attrs) { + super(context, attrs); + // Retrieve styles attributs + TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.CircleFlowIndicator); + + // Gets the active circle type, defaulting to "fill" + int activeType = a.getInt(R.styleable.CircleFlowIndicator_activeType, + STYLE_FILL); + + int activeDefaultColor = 0xFFFFFFFF; + + // Get a custom active color if there is one + int activeColor = a + .getColor(R.styleable.CircleFlowIndicator_activeColor, + activeDefaultColor); + + // Gets the inactive circle type, defaulting to "stroke" + int inactiveType = a.getInt( + R.styleable.CircleFlowIndicator_inactiveType, STYLE_STROKE); + + int inactiveDefaultColor = 0x44FFFFFF; + // Get a custom inactive color if there is one + int inactiveColor = a.getColor( + R.styleable.CircleFlowIndicator_inactiveColor, + inactiveDefaultColor); + + // Retrieve the radius + mRadius = a.getDimension(R.styleable.CircleFlowIndicator_radius, 4.0f); + mRadiusActive = mRadius; + mRadiusInactive = mRadius; + + // Retrieve the spacing + spacing = a.getDimension(R.styleable.CircleFlowIndicator_spacing, 4.0f); + // We want the spacing to be center-to-center + spacing += 2 * mRadiusActive; + + // Retrieve the fade out time + fadeOutTime = a.getInt(R.styleable.CircleFlowIndicator_fadeOut, 0); + + mCentered = a.getBoolean(R.styleable.CircleFlowIndicator_centered, false); + + mSnap = a.getBoolean(R.styleable.CircleFlowIndicator_snap, false); + + initColors(activeColor, inactiveColor, activeType, inactiveType); + } + + private void initColors(int activeColor, int inactiveColor, int activeType, + int inactiveType) { + // Select the paint type given the type attr + switch (inactiveType) { + case STYLE_FILL: + mPaintInactive.setStyle(Style.FILL); + break; + default: + mPaintInactive.setStyle(Style.STROKE); + float strokeWidth = mPaintInactive.getStrokeWidth(); + if (strokeWidth == 0.0f) { + // It draws in "hairline mode", which is 1 px wide. + strokeWidth = 1.0f / getResources().getDisplayMetrics().density; + } + mRadiusInactive -= strokeWidth / 2.0f; + } + mPaintInactive.setColor(inactiveColor); + + // Select the paint type given the type attr + switch (activeType) { + case STYLE_STROKE: + mPaintActive.setStyle(Style.STROKE); + float strokeWidth = mPaintInactive.getStrokeWidth(); + if (strokeWidth == 0.0f) { + // It draws in "hairline mode", which is 1 px wide. + strokeWidth = 1.0f / getResources().getDisplayMetrics().density; + } + mRadiusActive -= strokeWidth / 2.0f; + break; + default: + mPaintActive.setStyle(Style.FILL); + } + mPaintActive.setColor(activeColor); + } + + /* + * (non-Javadoc) + * + * @see android.view.View#onDraw(android.graphics.Canvas) + */ + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + int count = 3; + if (viewFlow != null) { + count = viewFlow.getViewsCount(); + } + + //this is the amount the first circle should be offset to make the entire thing centered + float centeringOffset = 0; + + int leftPadding = getPaddingLeft(); + + // Draw stroked circles + for (int iLoop = 0; iLoop < count; iLoop++) { + canvas.drawCircle(leftPadding + mRadius + + (iLoop * spacing) + centeringOffset, + getPaddingTop() + mRadius, mRadiusInactive, mPaintInactive); + } + float cx = 0; + if (mSnap) { + cx = currentPosition * spacing; + } else { + if (flowWidth != 0) { + // Draw the filled circle according to the current scroll + cx = (currentScroll * spacing) / flowWidth; + } + // else, the flow width hasn't been updated yet. Draw the default position. + } + canvas.drawCircle(leftPadding + mRadius + cx+centeringOffset, getPaddingTop() + + mRadius, mRadiusActive, mPaintActive); + } + + /* + * (non-Javadoc) + * + * @see + * org.taptwo.android.widget.ViewFlow.ViewSwitchListener#onSwitched(android + * .view.View, int) + */ + @Override + public void onSwitched(View view, int position) { + currentPosition = position; + if (mSnap) { + setVisibility(View.VISIBLE); + resetTimer(); + invalidate(); + } + } + + /* + * (non-Javadoc) + * + * @see + * org.taptwo.android.widget.FlowIndicator#setViewFlow(org.taptwo.android + * .widget.ViewFlow) + */ + @Override + public void setViewFlow(ViewFlow view) { + resetTimer(); + viewFlow = view; + flowWidth = viewFlow.getChildWidth(); + invalidate(); + } + + /* + * (non-Javadoc) + * + * @see org.taptwo.android.widget.FlowIndicator#onScrolled(int, int, int, + * int) + */ + @Override + public void onScrolled(int h, int v, int oldh, int oldv) { + currentScroll = h; + flowWidth = viewFlow.getChildWidth(); + if (!mSnap) { + setVisibility(View.VISIBLE); + resetTimer(); + invalidate(); + } + } + + /* + * (non-Javadoc) + * + * @see android.view.View#onMeasure(int, int) + */ + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(measureWidth(widthMeasureSpec), + measureHeight(heightMeasureSpec)); + } + + /** + * Determines the width of this view + * + * @param measureSpec + * A measureSpec packed into an int + * @return The width of the view, honoring constraints from measureSpec + */ + private int measureWidth(int measureSpec) { + int result = 0; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + // We were told how big to be + if (specMode == MeasureSpec.EXACTLY) { + result = specSize; + } + // Calculate the width according the views count + else { + int count = 3; + if (viewFlow != null) { + count = viewFlow.getViewsCount(); + } + // Remember that spacing is centre-to-centre + result = (int) (getPaddingLeft() + getPaddingRight() + + (2 * mRadius) + (count - 1) * spacing); + // Respect AT_MOST value if that was what is called for by + // measureSpec + if (specMode == MeasureSpec.AT_MOST) { + result = Math.min(result, specSize); + } + } + return result; + } + + /** + * Determines the height of this view + * + * @param measureSpec + * A measureSpec packed into an int + * @return The height of the view, honoring constraints from measureSpec + */ + private int measureHeight(int measureSpec) { + int result = 0; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + // We were told how big to be + if (specMode == MeasureSpec.EXACTLY) { + result = specSize; + } + // Measure the height + else { + result = (int) (2 * mRadius + getPaddingTop() + getPaddingBottom() + 1); + // Respect AT_MOST value if that was what is called for by + // measureSpec + if (specMode == MeasureSpec.AT_MOST) { + result = Math.min(result, specSize); + } + } + return result; + } + + /** + * Sets the fill color + * + * @param color + * ARGB value for the text + */ + public void setFillColor(int color) { + mPaintActive.setColor(color); + invalidate(); + } + + /** + * Sets the stroke color + * + * @param color + * ARGB value for the text + */ + public void setStrokeColor(int color) { + mPaintInactive.setColor(color); + invalidate(); + } + + /** + * Resets the fade out timer to 0. Creating a new one if needed + */ + private void resetTimer() { + // Only set the timer if we have a timeout of at least 1 millisecond + if (fadeOutTime > 0) { + // Check if we need to create a new timer + if (timer == null || timer._run == false) { + // Create and start a new timer + timer = new FadeTimer(); + timer.execute(); + } else { + // Reset the current tiemr to 0 + timer.resetTimer(); + } + } + } + + /** + * Counts from 0 to the fade out time and animates the view away when + * reached + */ + private class FadeTimer extends AsyncTask { + // The current count + private int timer = 0; + // If we are inside the timing loop + private boolean _run = true; + + public void resetTimer() { + timer = 0; + } + + @Override + protected Void doInBackground(Void... arg0) { + while (_run) { + try { + // Wait for a millisecond + Thread.sleep(1); + // Increment the timer + timer++; + + // Check if we've reached the fade out time + if (timer == fadeOutTime) { + // Stop running + _run = false; + } + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + return null; + } + + @Override + protected void onPostExecute(Void result) { + animation = AnimationUtils.loadAnimation(getContext(), + android.R.anim.fade_out); + animation.setAnimationListener(animationListener); + startAnimation(animation); + } + } + + @Override + public void onAnimationEnd(Animation animation) { + setVisibility(View.GONE); + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + + @Override + public void onAnimationStart(Animation animation) { + } +} diff --git a/opensrp-sdidtk/src/main/java/widget/FlowIndicator.java b/opensrp-sdidtk/src/main/java/widget/FlowIndicator.java new file mode 100644 index 000000000..74b2aa480 --- /dev/null +++ b/opensrp-sdidtk/src/main/java/widget/FlowIndicator.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011 Patrik Åkerfeldt + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package widget; + +import widget.ViewFlow.ViewSwitchListener; + +/** + * An interface which defines the contract between a ViewFlow and a + * FlowIndicator.
+ * A FlowIndicator is responsible to show an visual indicator on the total views + * number and the current visible view.
+ * + */ +public interface FlowIndicator extends ViewSwitchListener { + + /** + * Set the current ViewFlow. This method is called by the ViewFlow when the + * FlowIndicator is attached to it. + * + * @param view + */ + public void setViewFlow(ViewFlow view); + + /** + * The scroll position has been changed. A FlowIndicator may implement this + * method to reflect the current position + * + * @param h + * @param v + * @param oldh + * @param oldv + */ + public void onScrolled(int h, int v, int oldh, int oldv); +} diff --git a/opensrp-sdidtk/src/main/java/widget/TitleFlowIndicator.java b/opensrp-sdidtk/src/main/java/widget/TitleFlowIndicator.java new file mode 100644 index 000000000..f58881f77 --- /dev/null +++ b/opensrp-sdidtk/src/main/java/widget/TitleFlowIndicator.java @@ -0,0 +1,448 @@ +/* + * Copyright (C) 2011 Patrik Åkerfeldt + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.util.AttributeSet; +import android.view.View; +import android.widget.TextView; + + +import org.ei.opensrp.ddtk.R; + +import java.util.ArrayList; + +/** + * A TitleFlowIndicator is a FlowIndicator which displays the title of left view + * (if exist), the title of the current select view (centered) and the title of + * the right view (if exist). When the user scrolls the ViewFlow then titles are + * also scrolled. + * + */ +public class TitleFlowIndicator extends TextView implements FlowIndicator { + + private static final float TITLE_PADDING = 10.0f; + private static final float CLIP_PADDING = 0.0f; + private static final int SELECTED_COLOR = 0xFFFFC445; + private static final boolean SELECTED_BOLD = false; + private static final int TEXT_COLOR = 0xFFAAAAAA; + private static final int TEXT_SIZE = 15; + private static final float FOOTER_LINE_HEIGHT = 4.0f; + private static final int FOOTER_COLOR = 0xFFFFC445; + private static final float FOOTER_TRIANGLE_HEIGHT = 10; + private ViewFlow viewFlow; + private int currentScroll = 0; + private TitleProvider titleProvider = null; + private int currentPosition = 0; + private Paint paintText; + private Paint paintSelected; + private Path path; + private Paint paintFooterLine; + private Paint paintFooterTriangle; + private float footerTriangleHeight; + private float titlePadding; + /** + * Left and right side padding for not active view titles. + */ + private float clipPadding; + private float footerLineHeight; + + /* These are hardcoded just like in TextView */ + private static final int SANS = 1; + private static final int SERIF = 2; + private static final int MONOSPACE = 3; + + private Typeface typeface; + + /** + * Default constructor + */ + public TitleFlowIndicator(Context context) { + super(context); + initDraw(TEXT_COLOR, TEXT_SIZE, SELECTED_COLOR, SELECTED_BOLD, TEXT_SIZE, FOOTER_LINE_HEIGHT, FOOTER_COLOR); + } + + /** + * The contructor used with an inflater + * + * @param context + * @param attrs + */ + public TitleFlowIndicator(Context context, AttributeSet attrs) { + super(context, attrs); + // Retrieve styles attributs + + int typefaceIndex = attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android", "typeface", 0); + int textStyleIndex = attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android", "textStyle", 0); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TitleFlowIndicator); + + String customTypeface = a.getString(R.styleable.TitleFlowIndicator_customTypeface); + // Retrieve the colors to be used for this view and apply them. + int footerColor = a.getColor(R.styleable.TitleFlowIndicator_footerColor, FOOTER_COLOR); + footerLineHeight = a.getDimension(R.styleable.TitleFlowIndicator_footerLineHeight, FOOTER_LINE_HEIGHT); + footerTriangleHeight = a.getDimension(R.styleable.TitleFlowIndicator_footerTriangleHeight, FOOTER_TRIANGLE_HEIGHT); + int selectedColor = a.getColor(R.styleable.TitleFlowIndicator_selectedColor, SELECTED_COLOR); + boolean selectedBold = a.getBoolean(R.styleable.TitleFlowIndicator_selectedBold, SELECTED_BOLD); + int textColor = a.getColor(R.styleable.TitleFlowIndicator_textColor, TEXT_COLOR); + float textSize = a.getDimension(R.styleable.TitleFlowIndicator_textSize, TEXT_SIZE); + float selectedSize = a.getDimension(R.styleable.TitleFlowIndicator_selectedSize, textSize); + titlePadding = a.getDimension(R.styleable.TitleFlowIndicator_titlePadding, TITLE_PADDING); + clipPadding = a.getDimension(R.styleable.TitleFlowIndicator_clipPadding, CLIP_PADDING); + initDraw(textColor, textSize, selectedColor, selectedBold, selectedSize, footerLineHeight, footerColor); + + if (customTypeface != null) + typeface = Typeface.createFromAsset(context.getAssets(), customTypeface); + else + typeface = getTypefaceByIndex(typefaceIndex); + typeface = Typeface.create(typeface, textStyleIndex); + + } + + /** + * Initialize draw objects + */ + private void initDraw(int textColor, float textSize, int selectedColor, boolean selectedBold, float selectedSize, float footerLineHeight, int footerColor) { + paintText = new Paint(); + paintText.setColor(textColor); + paintText.setTextSize(textSize); + paintText.setAntiAlias(true); + paintSelected = new Paint(); + paintSelected.setColor(selectedColor); + paintSelected.setTextSize(selectedSize); + paintSelected.setFakeBoldText(selectedBold); + paintSelected.setAntiAlias(true); + paintFooterLine = new Paint(); + paintFooterLine.setStyle(Paint.Style.FILL_AND_STROKE); + paintFooterLine.setStrokeWidth(footerLineHeight); + paintFooterLine.setColor(footerColor); + paintFooterTriangle = new Paint(); + paintFooterTriangle.setStyle(Paint.Style.FILL_AND_STROKE); + paintFooterTriangle.setColor(footerColor); + } + + /* + * (non-Javadoc) + * + * @see android.view.View#onDraw(android.graphics.Canvas) + */ + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + // Calculate views bounds + ArrayList bounds = calculateAllBounds(paintText); + + // If no value then add a fake one + int count = (viewFlow != null && viewFlow.getAdapter() != null) ? viewFlow.getAdapter().getCount() : 1; + + // Verify if the current view must be clipped to the screen + Rect curViewBound = bounds.get(currentPosition); + int curViewWidth = curViewBound.right - curViewBound.left; + if (curViewBound.left < 0) { + // Try to clip to the screen (left side) + clipViewOnTheLeft(curViewBound, curViewWidth); + } + if (curViewBound.right > getLeft() + getWidth()) { + // Try to clip to the screen (right side) + clipViewOnTheRight(curViewBound, curViewWidth); + } + + // Left views starting from the current position + if (currentPosition > 0) { + for (int iLoop = currentPosition - 1; iLoop >= 0; iLoop--) { + Rect bound = bounds.get(iLoop); + int w = bound.right - bound.left; + // Si left side is outside the screen + if (bound.left < 0) { + // Try to clip to the screen (left side) + clipViewOnTheLeft(bound, w); + // Except if there's an intersection with the right view + if (iLoop < count - 1 && currentPosition != iLoop) { + Rect rightBound = bounds.get(iLoop + 1); + // Intersection + if (bound.right + TITLE_PADDING > rightBound.left) { + bound.left = rightBound.left - (w + (int) titlePadding); + } + } + } + } + } + // Right views starting from the current position + if (currentPosition < count - 1) { + for (int iLoop = currentPosition + 1; iLoop < count; iLoop++) { + Rect bound = bounds.get(iLoop); + int w = bound.right - bound.left; + // If right side is outside the screen + if (bound.right > getLeft() + getWidth()) { + // Try to clip to the screen (right side) + clipViewOnTheRight(bound, w); + // Except if there's an intersection with the left view + if (iLoop > 0 && currentPosition != iLoop) { + Rect leftBound = bounds.get(iLoop - 1); + // Intersection + if (bound.left - TITLE_PADDING < leftBound.right) { + bound.left = leftBound.right + (int) titlePadding; + } + } + } + } + } + + // Now draw views + for (int iLoop = 0; iLoop < count; iLoop++) { + // Get the title + String title = getTitle(iLoop); + Rect bound = bounds.get(iLoop); + // Only if one side is visible + if ((bound.left > getLeft() && bound.left < getLeft() + getWidth()) || (bound.right > getLeft() && bound.right < getLeft() + getWidth())) { + Paint paint = paintText; + // Change the color is the title is closed to the center + int middle = (bound.left + bound.right) / 2; + if (Math.abs(middle - (getWidth() / 2)) < 20) { + paint = paintSelected; + } + paint.setTypeface(typeface); + canvas.drawText(title, bound.left, bound.bottom, paint); + } + } + + // Draw the footer line + path = new Path(); + int coordY = getHeight() - 1; + coordY -= (footerLineHeight % 2 == 1) ? footerLineHeight / 2 : footerLineHeight / 2 - 1; + path.moveTo(0, coordY); + path.lineTo(getWidth(), coordY); + path.close(); + canvas.drawPath(path, paintFooterLine); + // Draw the footer triangle + path = new Path(); + path.moveTo(getWidth() / 2, getHeight() - footerLineHeight - footerTriangleHeight); + path.lineTo(getWidth() / 2 + footerTriangleHeight, getHeight() - footerLineHeight); + path.lineTo(getWidth() / 2 - footerTriangleHeight, getHeight() - footerLineHeight); + path.close(); + canvas.drawPath(path, paintFooterTriangle); + + } + + /** + * Set bounds for the right textView including clip padding. + * + * @param curViewBound + * current bounds. + * @param curViewWidth + * width of the view. + */ + private void clipViewOnTheRight(Rect curViewBound, int curViewWidth) { + curViewBound.right = getLeft() + getWidth() - (int) clipPadding; + curViewBound.left = curViewBound.right - curViewWidth; + } + + /** + * Set bounds for the left textView including clip padding. + * + * @param curViewBound + * current bounds. + * @param curViewWidth + * width of the view. + */ + private void clipViewOnTheLeft(Rect curViewBound, int curViewWidth) { + curViewBound.left = 0 + (int) clipPadding; + curViewBound.right = curViewWidth; + } + + /** + * Calculate views bounds and scroll them according to the current index + * + * @param paint + * @param currentIndex + * @return + */ + private ArrayList calculateAllBounds(Paint paint) { + ArrayList list = new ArrayList(); + // For each views (If no values then add a fake one) + int count = (viewFlow != null && viewFlow.getAdapter() != null) ? viewFlow.getAdapter().getCount() : 1; + for (int iLoop = 0; iLoop < count; iLoop++) { + Rect bounds = calcBounds(iLoop, paint); + int w = (bounds.right - bounds.left); + int h = (bounds.bottom - bounds.top); + bounds.left = (getWidth() / 2) - (w / 2) - currentScroll + (iLoop * getWidth()); + bounds.right = bounds.left + w; + bounds.top = 0; + bounds.bottom = h; + list.add(bounds); + } + + return list; + } + + /** + * Calculate the bounds for a view's title + * + * @param index + * @param paint + * @return + */ + private Rect calcBounds(int index, Paint paint) { + // Get the title + String title = getTitle(index); + // Calculate the text bounds + Rect bounds = new Rect(); + bounds.right = (int) paint.measureText(title); + bounds.bottom = (int) (paint.descent() - paint.ascent()); + return bounds; + } + + /** + * Returns the title + * + * @param pos + * @return + */ + private String getTitle(int pos) { + // Set the default title + String title = "title " + pos; + // If the TitleProvider exist + if (titleProvider != null) { + title = titleProvider.getTitle(pos); + } + return title; + } + + /* + * (non-Javadoc) + * + * @see org.taptwo.android.widget.FlowIndicator#onScrolled(int, int, int, + * int) + */ + @Override + public void onScrolled(int h, int v, int oldh, int oldv) { + currentScroll = h; + invalidate(); + } + + /* + * (non-Javadoc) + * + * @see + * org.taptwo.android.widget.ViewFlow.ViewSwitchListener#onSwitched(android + * .view.View, int) + */ + @Override + public void onSwitched(View view, int position) { + currentPosition = position; + invalidate(); + } + + /* + * (non-Javadoc) + * + * @see + * org.taptwo.android.widget.FlowIndicator#setViewFlow(org.taptwo.android + * .widget.ViewFlow) + */ + @Override + public void setViewFlow(ViewFlow view) { + viewFlow = view; + currentPosition = view.getSelectedItemPosition(); + invalidate(); + } + + /** + * Set the title provider + * + * @param provider + */ + public void setTitleProvider(TitleProvider provider) { + titleProvider = provider; + } + + /* + * (non-Javadoc) + * + * @see android.view.View#onMeasure(int, int) + */ + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); + } + + /** + * Determines the width of this view + * + * @param measureSpec + * A measureSpec packed into an int + * @return The width of the view, honoring constraints from measureSpec + */ + private int measureWidth(int measureSpec) { + int result = 0; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + if (specMode != MeasureSpec.EXACTLY) { + throw new IllegalStateException("ViewFlow can only be used in EXACTLY mode."); + } + result = specSize; + return result; + } + + /** + * Determines the height of this view + * + * @param measureSpec + * A measureSpec packed into an int + * @return The height of the view, honoring constraints from measureSpec + */ + private int measureHeight(int measureSpec) { + int result = 0; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + // We were told how big to be + if (specMode == MeasureSpec.EXACTLY) { + result = specSize; + } + // Measure the height + else { + // Calculate the text bounds + Rect bounds = new Rect(); + bounds.bottom = (int) (paintText.descent() - paintText.ascent()); + result = bounds.bottom - bounds.top + (int) footerTriangleHeight + (int) footerLineHeight + 10; + return result; + } + return result; + } + + private Typeface getTypefaceByIndex(int typefaceIndex) { + switch (typefaceIndex) { + case SANS: + return Typeface.SANS_SERIF; + + case SERIF: + return Typeface.SERIF; + + case MONOSPACE: + return Typeface.MONOSPACE; + default: + return Typeface.DEFAULT; + } + } +} diff --git a/opensrp-sdidtk/src/main/java/widget/TitleProvider.java b/opensrp-sdidtk/src/main/java/widget/TitleProvider.java new file mode 100644 index 000000000..681c04ebb --- /dev/null +++ b/opensrp-sdidtk/src/main/java/widget/TitleProvider.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2011 Patrik Åkerfeldt + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package widget; + +/** + * A TitleProvider provides the title to display according to a view. + */ +public interface TitleProvider { + + /** + * Returns the title of the view at position + * @param position + * @return + */ + public String getTitle(int position); + +} diff --git a/opensrp-sdidtk/src/main/java/widget/ViewFlow.java b/opensrp-sdidtk/src/main/java/widget/ViewFlow.java new file mode 100644 index 000000000..3709adf8c --- /dev/null +++ b/opensrp-sdidtk/src/main/java/widget/ViewFlow.java @@ -0,0 +1,841 @@ +/* + * Copyright (C) 2011 Patrik Åkerfeldt + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package widget; + +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.TypedArray; +import android.database.DataSetObserver; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewTreeObserver.OnGlobalLayoutListener; +import android.widget.Adapter; +import android.widget.AdapterView; +import android.widget.Scroller; + + +import org.ei.opensrp.ddtk.R; + +import java.util.EnumSet; +import java.util.LinkedList; + +/** + * A horizontally scrollable {@link ViewGroup} with items populated from an + * {@link Adapter}. The ViewFlow uses a buffer to store loaded {@link View}s in. + * The default size of the buffer is 3 elements on both sides of the currently + * visible {@link View}, making up a total buffer size of 3 * 2 + 1 = 7. The + * buffer size can be changed using the {@code sidebuffer} xml attribute. + * + */ +public class ViewFlow extends AdapterView { + + private static final int SNAP_VELOCITY = 1000; + private static final int INVALID_SCREEN = -1; + private final static int TOUCH_STATE_REST = 0; + private final static int TOUCH_STATE_SCROLLING = 1; + + private LinkedList mLoadedViews; + private LinkedList mRecycledViews; + private int mCurrentBufferIndex; + private int mCurrentAdapterIndex; + private int mSideBuffer = 2; + private Scroller mScroller; + private VelocityTracker mVelocityTracker; + private int mTouchState = TOUCH_STATE_REST; + private float mLastMotionX; + private int mTouchSlop; + private int mMaximumVelocity; + private int mCurrentScreen; + private int mNextScreen = INVALID_SCREEN; + private boolean mFirstLayout = true; + private ViewSwitchListener mViewSwitchListener; + private ViewLazyInitializeListener mViewInitializeListener; + private EnumSet mLazyInit = EnumSet.allOf(LazyInit.class); + private Adapter mAdapter; + private int mLastScrollDirection; + private AdapterDataSetObserver mDataSetObserver; + private FlowIndicator mIndicator; + private int mLastOrientation = -1; + /** Extra return value from obtainView: tells you whether the item it returned on the last call was recycled rather than created by the adapter. + * This is a member because getting a second return value requires an allocation. */ + private boolean mLastObtainedViewWasRecycled = false; + + private OnGlobalLayoutListener orientationChangeListener = new OnGlobalLayoutListener() { + + @Override + public void onGlobalLayout() { + getViewTreeObserver().removeGlobalOnLayoutListener( + orientationChangeListener); + setSelection(mCurrentAdapterIndex); + } + }; + + /** + * Receives call backs when a new {@link View} has been scrolled to. + */ + public static interface ViewSwitchListener { + + /** + * This method is called when a new View has been scrolled to. + * + * @param view + * the {@link View} currently in focus. + * @param position + * The position in the adapter of the {@link View} currently in focus. + */ + void onSwitched(View view, int position); + + } + + public static interface ViewLazyInitializeListener { + void onViewLazyInitialize(View view, int position); + } + + enum LazyInit { + LEFT, RIGHT + } + + public ViewFlow(Context context) { + super(context); + mSideBuffer = 3; + init(); + } + + public ViewFlow(Context context, int sideBuffer) { + super(context); + mSideBuffer = sideBuffer; + init(); + } + + public ViewFlow(Context context, AttributeSet attrs) { + super(context, attrs); + TypedArray styledAttrs = context.obtainStyledAttributes(attrs, + R.styleable.ViewFlow); + mSideBuffer = styledAttrs.getInt(R.styleable.ViewFlow_sidebuffer, 3); + init(); + } + + private void init() { + mLoadedViews = new LinkedList(); + mRecycledViews = new LinkedList(); + mScroller = new Scroller(getContext()); + final ViewConfiguration configuration = ViewConfiguration + .get(getContext()); + mTouchSlop = configuration.getScaledTouchSlop(); + mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); + } + + public void onConfigurationChanged(Configuration newConfig) { + if (newConfig.orientation != mLastOrientation) { + mLastOrientation = newConfig.orientation; + getViewTreeObserver().addOnGlobalLayoutListener(orientationChangeListener); + } + } + + public int getViewsCount() { + return mAdapter.getCount(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + final int widthMode = MeasureSpec.getMode(widthMeasureSpec); + final int heightMode = MeasureSpec.getMode(heightMeasureSpec); + + int childWidth = 0; + int childHeight = 0; + int childState = 0; + + final int widthPadding = getWidthPadding(); + final int heightPadding = getHeightPadding(); + + int count = mAdapter == null ? 0 : mAdapter.getCount(); + if (count > 0) { + final View child = obtainView(0); + measureChild(child, widthMeasureSpec, heightMeasureSpec); + childWidth = child.getMeasuredWidth(); + childHeight = child.getMeasuredHeight(); + childState = child.getMeasuredState(); + mRecycledViews.add(child); + } + + switch (widthMode) { + case MeasureSpec.UNSPECIFIED: + widthSize = childWidth + widthPadding; + break; + case MeasureSpec.AT_MOST: + widthSize = (childWidth + widthPadding) | childState; + break; + case MeasureSpec.EXACTLY: + if (widthSize < childWidth + widthPadding) + widthSize |= MEASURED_STATE_TOO_SMALL; + break; + } + switch (heightMode) { + case MeasureSpec.UNSPECIFIED: + heightSize = childHeight + heightPadding; + break; + case MeasureSpec.AT_MOST: + heightSize = (childHeight + heightPadding) | (childState >> MEASURED_HEIGHT_STATE_SHIFT); + break; + case MeasureSpec.EXACTLY: + if (heightSize < childHeight + heightPadding) + heightSize |= MEASURED_STATE_TOO_SMALL; + break; + } + + if (heightMode == MeasureSpec.UNSPECIFIED) { + heightSize = heightPadding + childHeight; + } else { + heightSize |= (childState&MEASURED_STATE_MASK); + } + + setMeasuredDimension(widthSize, heightSize); + } + + private int getWidthPadding() { + return getPaddingLeft() + getPaddingRight() + getHorizontalFadingEdgeLength() * 2; + } + + public int getChildWidth() { + return getWidth() - getWidthPadding(); + } + + private int getHeightPadding() { + return getPaddingTop() + getPaddingBottom(); + } + + public int getChildHeight() { + return getHeight() - getHeightPadding(); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + final int count = getChildCount(); + for (int i = 0; i < count ; ++i) { + final View child = getChildAt(i); + child.measure(MeasureSpec.makeMeasureSpec(getChildWidth(), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(getChildHeight(), MeasureSpec.EXACTLY)); + } + + if (mFirstLayout) { + mScroller.startScroll(0, 0, mCurrentScreen * getChildWidth(), 0, 0); + mFirstLayout = false; + } + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int childLeft = getPaddingLeft() + getHorizontalFadingEdgeLength(); + + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() != View.GONE) { + final int childWidth = child.getMeasuredWidth(); + child.layout(childLeft, getPaddingTop(), childLeft + childWidth, + getPaddingTop() + child.getMeasuredHeight()); + childLeft += childWidth; + } + } + } + + @Override + protected float getTopFadingEdgeStrength() { + return 0.0f; + } + + @Override + protected float getBottomFadingEdgeStrength() { + return 0.0f; + } + + @Override + protected float getLeftFadingEdgeStrength() { + // always do the fading edge + return 1.0f; + } + + @Override + protected float getRightFadingEdgeStrength() { + // always do the fading edge + return 1.0f; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (getChildCount() == 0) + return false; + + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(ev); + + final int action = ev.getAction(); + final float x = ev.getX(); + + switch (action) { + case MotionEvent.ACTION_DOWN: + /* + * If being flinged and user touches, stop the fling. isFinished + * will be false if being flinged. + */ + if (!mScroller.isFinished()) { + mScroller.abortAnimation(); + } + + // Remember where the motion event started + mLastMotionX = x; + + mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST + : TOUCH_STATE_SCROLLING; + + break; + + case MotionEvent.ACTION_MOVE: + final int deltaX = (int) (mLastMotionX - x); + + boolean xMoved = Math.abs(deltaX) > mTouchSlop; + + if (xMoved) { + // Scroll if the user moved far enough along the X axis + mTouchState = TOUCH_STATE_SCROLLING; + + if (mViewInitializeListener != null) + initializeView(deltaX); + } + + if (mTouchState == TOUCH_STATE_SCROLLING) { + // Scroll to follow the motion event + + mLastMotionX = x; + + final int scrollX = getScrollX(); + if (deltaX < 0) { + if (scrollX > 0) { + scrollBy(Math.max(-scrollX, deltaX), 0); + } + } else if (deltaX > 0) { + final int availableToScroll = getChildAt( + getChildCount() - 1).getRight() + - getPaddingRight() - getHorizontalFadingEdgeLength() + - scrollX - getWidth(); + if (availableToScroll > 0) { + scrollBy(Math.min(availableToScroll, deltaX), 0); + } + } + return true; + } + break; + + case MotionEvent.ACTION_UP: + if (mTouchState == TOUCH_STATE_SCROLLING) { + final VelocityTracker velocityTracker = mVelocityTracker; + velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); + int velocityX = (int) velocityTracker.getXVelocity(); + + if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) { + // Fling hard enough to move left + snapToScreen(mCurrentScreen - 1); + } else if (velocityX < -SNAP_VELOCITY + && mCurrentScreen < getChildCount() - 1) { + // Fling hard enough to move right + snapToScreen(mCurrentScreen + 1); + } else { + snapToDestination(); + } + + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + } + + mTouchState = TOUCH_STATE_REST; + + break; + case MotionEvent.ACTION_CANCEL: + mTouchState = TOUCH_STATE_REST; + } + return false; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (getChildCount() == 0) + return false; + + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(ev); + + final int action = ev.getAction(); + final float x = ev.getX(); + + switch (action) { + case MotionEvent.ACTION_DOWN: + /* + * If being flinged and user touches, stop the fling. isFinished + * will be false if being flinged. + */ + if (!mScroller.isFinished()) { + mScroller.abortAnimation(); + } + + // Remember where the motion event started + mLastMotionX = x; + + mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST + : TOUCH_STATE_SCROLLING; + + break; + + case MotionEvent.ACTION_MOVE: + final int deltaX = (int) (mLastMotionX - x); + + boolean xMoved = Math.abs(deltaX) > mTouchSlop; + + if (xMoved) { + // Scroll if the user moved far enough along the X axis + mTouchState = TOUCH_STATE_SCROLLING; + + if (mViewInitializeListener != null) + initializeView(deltaX); + } + + if (mTouchState == TOUCH_STATE_SCROLLING) { + // Scroll to follow the motion event + + mLastMotionX = x; + + final int scrollX = getScrollX(); + if (deltaX < 0) { + if (scrollX > 0) { + scrollBy(Math.max(-scrollX, deltaX), 0); + } + } else if (deltaX > 0) { + final int availableToScroll = getChildAt( + getChildCount() - 1).getRight() + - getPaddingRight() - getHorizontalFadingEdgeLength() + - scrollX - getChildWidth(); + if (availableToScroll > 0) { + scrollBy(Math.min(availableToScroll, deltaX), 0); + } + } + return true; + } + break; + + case MotionEvent.ACTION_UP: + if (mTouchState == TOUCH_STATE_SCROLLING) { + final VelocityTracker velocityTracker = mVelocityTracker; + velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); + int velocityX = (int) velocityTracker.getXVelocity(); + + if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) { + // Fling hard enough to move left + snapToScreen(mCurrentScreen - 1); + } else if (velocityX < -SNAP_VELOCITY + && mCurrentScreen < getChildCount() - 1) { + // Fling hard enough to move right + snapToScreen(mCurrentScreen + 1); + } else { + snapToDestination(); + } + + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + } + + mTouchState = TOUCH_STATE_REST; + + break; + case MotionEvent.ACTION_CANCEL: + snapToDestination(); + mTouchState = TOUCH_STATE_REST; + } + return true; + } + + private void initializeView(final float direction) { + if (direction > 0) { + if (mLazyInit.contains(LazyInit.RIGHT)) { + mLazyInit.remove(LazyInit.RIGHT); + if (mCurrentBufferIndex+1 < mLoadedViews.size()) + mViewInitializeListener.onViewLazyInitialize(mLoadedViews.get(mCurrentBufferIndex + 1), mCurrentAdapterIndex + 1); + } + } else { + if (mLazyInit.contains(LazyInit.LEFT)) { + mLazyInit.remove(LazyInit.LEFT); + if (mCurrentBufferIndex > 0) + mViewInitializeListener.onViewLazyInitialize(mLoadedViews.get(mCurrentBufferIndex - 1), mCurrentAdapterIndex - 1); + } + } + } + + @Override + protected void onScrollChanged(int h, int v, int oldh, int oldv) { + super.onScrollChanged(h, v, oldh, oldv); + if (mIndicator != null) { + /* + * The actual horizontal scroll origin does typically not match the + * perceived one. Therefore, we need to calculate the perceived + * horizontal scroll origin here, since we use a view buffer. + */ + int hPerceived = h + (mCurrentAdapterIndex - mCurrentBufferIndex) + * getChildWidth(); + mIndicator.onScrolled(hPerceived, v, oldh, oldv); + } + } + + private void snapToDestination() { + final int screenWidth = getChildWidth(); + final int whichScreen = (getScrollX() + (screenWidth / 2)) + / screenWidth; + + snapToScreen(whichScreen); + } + + private void snapToScreen(int whichScreen) { + mLastScrollDirection = whichScreen - mCurrentScreen; + if (!mScroller.isFinished()) + return; + + whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1)); + + mNextScreen = whichScreen; + + final int newX = whichScreen * getChildWidth(); + final int delta = newX - getScrollX(); + mScroller.startScroll(getScrollX(), 0, delta, 0, Math.abs(delta) * 2); + invalidate(); + } + + @Override + public void computeScroll() { + if (mScroller.computeScrollOffset()) { + scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); + postInvalidate(); + } else if (mNextScreen != INVALID_SCREEN) { + mCurrentScreen = Math.max(0, + Math.min(mNextScreen, getChildCount() - 1)); + mNextScreen = INVALID_SCREEN; + post(new Runnable() { + @Override + public void run() { + postViewSwitched(mLastScrollDirection); + } + }); + } + } + + /** + * Scroll to the {@link View} in the view buffer specified by the index. + * + * @param indexInBuffer + * Index of the view in the view buffer. + */ + private void setVisibleView(int indexInBuffer, boolean uiThread) { + mCurrentScreen = Math.max(0, + Math.min(indexInBuffer, getChildCount() - 1)); + int dx = (mCurrentScreen * getChildWidth()) - mScroller.getCurrX(); + mScroller.startScroll(mScroller.getCurrX(), mScroller.getCurrY(), dx, + 0, 0); + if(dx == 0) + onScrollChanged(mScroller.getCurrX() + dx, mScroller.getCurrY(), mScroller.getCurrX() + dx, mScroller.getCurrY()); + if (uiThread) + invalidate(); + else + postInvalidate(); + } + + /** + * Set the listener that will receive notifications every time the {code + * ViewFlow} scrolls. + * + * @param l + * the scroll listener + */ + public void setOnViewSwitchListener(ViewSwitchListener l) { + mViewSwitchListener = l; + } + + public void setOnViewLazyInitializeListener(ViewLazyInitializeListener l) { + mViewInitializeListener = l; + } + + @Override + public Adapter getAdapter() { + return mAdapter; + } + + @Override + public void setAdapter(Adapter adapter) { + setAdapter(adapter, 0); + } + + public void setAdapter(Adapter adapter, int initialPosition) { + if (mAdapter != null) { + mAdapter.unregisterDataSetObserver(mDataSetObserver); + } + + mAdapter = adapter; + + if (mAdapter != null) { + mDataSetObserver = new AdapterDataSetObserver(); + mAdapter.registerDataSetObserver(mDataSetObserver); + + } + if (mAdapter == null || mAdapter.getCount() == 0) + return; + + setSelection(initialPosition); + } + + @Override + public View getSelectedView() { + return (mCurrentBufferIndex < mLoadedViews.size() ? mLoadedViews + .get(mCurrentBufferIndex) : null); + } + + @Override + public int getSelectedItemPosition() { + return mCurrentAdapterIndex; + } + + /** + * Set the FlowIndicator + * + * @param flowIndicator + */ + public void setFlowIndicator(FlowIndicator flowIndicator) { + mIndicator = flowIndicator; + mIndicator.setViewFlow(this); + } + + protected void recycleViews() { + while (!mLoadedViews.isEmpty()) + recycleView(mLoadedViews.remove()); + } + + protected void recycleView(View v) { + if (v == null) + return; + mRecycledViews.addFirst(v); + detachViewFromParent(v); + } + + protected View getRecycledView() { + return (mRecycledViews.isEmpty() ? null : mRecycledViews.remove()); + } + + @Override + public void setSelection(int position) { + mNextScreen = INVALID_SCREEN; + mScroller.forceFinished(true); + if (mAdapter == null) + return; + + position = Math.max(position, 0); + position = Math.min(position, mAdapter.getCount() - 1); + + recycleViews(); + + View currentView = makeAndAddView(position, true); + mLoadedViews.addLast(currentView); + + if (mViewInitializeListener != null) + mViewInitializeListener.onViewLazyInitialize(currentView, position); + + for(int offset = 1; mSideBuffer - offset >= 0; offset++) { + int leftIndex = position - offset; + int rightIndex = position + offset; + if(leftIndex >= 0) + mLoadedViews.addFirst(makeAndAddView(leftIndex, false)); + if(rightIndex < mAdapter.getCount()) + mLoadedViews.addLast(makeAndAddView(rightIndex, true)); + } + + mCurrentBufferIndex = mLoadedViews.indexOf(currentView); + mCurrentAdapterIndex = position; + + requestLayout(); + setVisibleView(mCurrentBufferIndex, false); + if (mIndicator != null) { + mIndicator.onSwitched(currentView, mCurrentAdapterIndex); + } + if (mViewSwitchListener != null) { + mViewSwitchListener.onSwitched(currentView, mCurrentAdapterIndex); + } + } + + private void resetFocus() { + logBuffer(); + recycleViews(); + removeAllViewsInLayout(); + mLazyInit.addAll(EnumSet.allOf(LazyInit.class)); + + for (int i = Math.max(0, mCurrentAdapterIndex - mSideBuffer); i < Math + .min(mAdapter.getCount(), mCurrentAdapterIndex + mSideBuffer + + 1); i++) { + mLoadedViews.addLast(makeAndAddView(i, true)); + if (i == mCurrentAdapterIndex) { + mCurrentBufferIndex = mLoadedViews.size() - 1; + if (mViewInitializeListener != null) + mViewInitializeListener.onViewLazyInitialize(mLoadedViews.getLast(), mCurrentAdapterIndex); + } + } + logBuffer(); + requestLayout(); + } + + private void postViewSwitched(int direction) { + if (direction == 0) + return; + + if (direction > 0) { // to the right + mCurrentAdapterIndex++; + mCurrentBufferIndex++; + mLazyInit.remove(LazyInit.LEFT); + mLazyInit.add(LazyInit.RIGHT); + + // Recycle view outside buffer range + if (mCurrentAdapterIndex > mSideBuffer) { + recycleView(mLoadedViews.removeFirst()); + mCurrentBufferIndex--; + } + + // Add new view to buffer + int newBufferIndex = mCurrentAdapterIndex + mSideBuffer; + if (newBufferIndex < mAdapter.getCount()) + mLoadedViews.addLast(makeAndAddView(newBufferIndex, true)); + + } else { // to the left + mCurrentAdapterIndex--; + mCurrentBufferIndex--; + mLazyInit.add(LazyInit.LEFT); + mLazyInit.remove(LazyInit.RIGHT); + + // Recycle view outside buffer range + if (mAdapter.getCount() - 1 - mCurrentAdapterIndex > mSideBuffer) { + recycleView(mLoadedViews.removeLast()); + } + + // Add new view to buffer + int newBufferIndex = mCurrentAdapterIndex - mSideBuffer; + if (newBufferIndex > -1) { + mLoadedViews.addFirst(makeAndAddView(newBufferIndex, false)); + mCurrentBufferIndex++; + } + + } + + requestLayout(); + setVisibleView(mCurrentBufferIndex, true); + if (mIndicator != null) { + mIndicator.onSwitched(mLoadedViews.get(mCurrentBufferIndex), + mCurrentAdapterIndex); + } + if (mViewSwitchListener != null) { + mViewSwitchListener + .onSwitched(mLoadedViews.get(mCurrentBufferIndex), + mCurrentAdapterIndex); + } + logBuffer(); + } + + @Override + protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) { + LayoutParams lp = child.getLayoutParams(); + final int childWidthSpec = getChildMeasureSpec(parentWidthMeasureSpec, getWidthPadding(), lp.width); + final int childHeightSpec = getChildMeasureSpec(parentHeightMeasureSpec, getHeightPadding(), lp.height); + child.measure(childWidthSpec, childHeightSpec); + } + + private View setupChild(View child, boolean addToEnd, boolean recycle) { + final LayoutParams lp = child.getLayoutParams(); + child.measure(MeasureSpec.makeMeasureSpec(getChildWidth(), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(getChildHeight(), MeasureSpec.EXACTLY)); + if (recycle) + attachViewToParent(child, (addToEnd ? -1 : 0), lp); + else + addViewInLayout(child, (addToEnd ? -1 : 0), lp, true); + return child; + } + + private View makeAndAddView(int position, boolean addToEnd) { + View view = obtainView(position); + return setupChild(view, addToEnd, mLastObtainedViewWasRecycled); + } + + private View obtainView(int position) { + View convertView = getRecycledView(); + View view = mAdapter.getView(position, convertView, this); + if(view != convertView && convertView != null) + mRecycledViews.add(convertView); + mLastObtainedViewWasRecycled = (view == convertView); + LayoutParams p = view.getLayoutParams(); + if (p == null) { + p = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + view.setLayoutParams(p); + } + return view; + } + + class AdapterDataSetObserver extends DataSetObserver { + + @Override + public void onChanged() { + View v = getChildAt(mCurrentBufferIndex); + if (v != null) { + for (int index = 0; index < mAdapter.getCount(); index++) { + if (v.equals(mAdapter.getItem(index))) { + mCurrentAdapterIndex = index; + break; + } + } + } + resetFocus(); + } + + @Override + public void onInvalidated() { + // Not yet implemented! + } + + } + + private void logBuffer() { + + Log.d("viewflow", "Size of mLoadedViews: " + mLoadedViews.size() + + ", Size of mRecycledViews: " + mRecycledViews.size() + + ", X: " + mScroller.getCurrX() + ", Y: " + mScroller.getCurrY()); + Log.d("viewflow", "IndexInAdapter: " + mCurrentAdapterIndex + + ", IndexInBuffer: " + mCurrentBufferIndex); + } +} diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/badge.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/badge.png new file mode 100644 index 000000000..cdb646cc5 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/badge.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/bg_texture.jpg b/opensrp-sdidtk/src/main/res/drawable-mdpi/bg_texture.jpg new file mode 100644 index 000000000..1299cee55 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/bg_texture.jpg differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/child_boy_infant.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/child_boy_infant.png new file mode 100644 index 000000000..5fd9411f3 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/child_boy_infant.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/child_girl_infant.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/child_girl_infant.png new file mode 100644 index 000000000..75ed5a7fc Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/child_girl_infant.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/flag_bpl.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/flag_bpl.png new file mode 100644 index 000000000..a28872f14 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/flag_bpl.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/flag_hp.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/flag_hp.png new file mode 100644 index 000000000..5d8148834 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/flag_hp.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/flag_hr.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/flag_hr.png new file mode 100644 index 000000000..affa5a7cf Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/flag_hr.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/flag_hrp.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/flag_hrp.png new file mode 100644 index 000000000..e237df7bb Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/flag_hrp.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/flag_sc.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/flag_sc.png new file mode 100644 index 000000000..e1fc853d5 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/flag_sc.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/flag_st.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/flag_st.png new file mode 100644 index 000000000..b1b22714a Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/flag_st.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/homestacks.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/homestacks.png new file mode 100644 index 000000000..e5839d834 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/homestacks.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_chevron_right.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_chevron_right.png new file mode 100644 index 000000000..baafa7c1f Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_chevron_right.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_cross.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_cross.png new file mode 100644 index 000000000..af58beea0 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_cross.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_down.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_down.png new file mode 100644 index 000000000..de8f51946 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_down.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_dristhi_logo.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_dristhi_logo.png new file mode 100644 index 000000000..011c0033d Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_dristhi_logo.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_dropper.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_dropper.png new file mode 100644 index 000000000..b4f6b6e11 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_dropper.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_menu_edit.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_menu_edit.png new file mode 100644 index 000000000..699b89a30 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_menu_edit.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_needle.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_needle.png new file mode 100644 index 000000000..30653b99b Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_needle.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_no.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_no.png new file mode 100644 index 000000000..635ada3b2 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_no.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_pencil.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_pencil.png new file mode 100644 index 000000000..a4e337689 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_pencil.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_plus.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_plus.png new file mode 100644 index 000000000..6b920754d Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_plus.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_remove.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_remove.png new file mode 100644 index 000000000..44908af30 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_remove.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_reporting.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_reporting.png new file mode 100644 index 000000000..9f959069c Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_reporting.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_sort.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_sort.png new file mode 100644 index 000000000..2d99d452e Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_sort.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_tv.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_tv.png new file mode 100644 index 000000000..d04858cb6 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_tv.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_village_filter.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_village_filter.png new file mode 100644 index 000000000..e80349020 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_village_filter.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_yes_large.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_yes_large.png new file mode 100644 index 000000000..f8f96c3d4 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_yes_large.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_yes_small.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_yes_small.png new file mode 100644 index 000000000..31e31e493 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/ic_yes_small.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/icon_fp_video.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/icon_fp_video.png new file mode 100644 index 000000000..a9bcefbf0 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/icon_fp_video.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/icon_plus_add_fp.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/icon_plus_add_fp.png new file mode 100644 index 000000000..28d66cd90 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/icon_plus_add_fp.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/icon_referral_warning.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/icon_referral_warning.png new file mode 100644 index 000000000..7345db1e5 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/icon_referral_warning.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/login_logo.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/login_logo.png new file mode 100644 index 000000000..31c53aa8d Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/login_logo.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/logo.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/logo.png new file mode 100644 index 000000000..2b9a0bc8b Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/logo.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/message_box.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/message_box.png new file mode 100644 index 000000000..434121ab1 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/message_box.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/register_anc.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/register_anc.png new file mode 100644 index 000000000..7a890355f Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/register_anc.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/register_child.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/register_child.png new file mode 100644 index 000000000..e90e1dbef Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/register_child.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/register_ec.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/register_ec.png new file mode 100644 index 000000000..53a7bc849 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/register_ec.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/register_fp.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/register_fp.png new file mode 100644 index 000000000..c18e83098 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/register_fp.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/register_pnc.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/register_pnc.png new file mode 100644 index 000000000..c1379fdb5 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/register_pnc.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/sdidtk_homestacks.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/sdidtk_homestacks.png new file mode 100644 index 000000000..e5839d834 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/sdidtk_homestacks.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/sdidtk_login_logo.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/sdidtk_login_logo.png new file mode 100644 index 000000000..111886032 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/sdidtk_login_logo.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/sdidtk_logo.png b/opensrp-sdidtk/src/main/res/drawable-mdpi/sdidtk_logo.png new file mode 100644 index 000000000..8fd9466d7 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/sdidtk_logo.png differ diff --git a/opensrp-sdidtk/src/main/res/drawable-mdpi/separator.gif b/opensrp-sdidtk/src/main/res/drawable-mdpi/separator.gif new file mode 100644 index 000000000..f176b3c06 Binary files /dev/null and b/opensrp-sdidtk/src/main/res/drawable-mdpi/separator.gif differ diff --git a/opensrp-sdidtk/src/main/res/layout-land/login.xml b/opensrp-sdidtk/src/main/res/layout-land/login.xml new file mode 100644 index 000000000..1e90ea4f5 --- /dev/null +++ b/opensrp-sdidtk/src/main/res/layout-land/login.xml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + +