From 9e6bdd556495634509d12b6fbe27c5c4f237524a Mon Sep 17 00:00:00 2001 From: "S. Grimault" Date: Mon, 14 Oct 2019 21:21:38 +0200 Subject: [PATCH 01/16] feat: launcher icon (debug version) --- .../res/drawable/ic_launcher_background.xml | 45 +++++++++--------- .../src/debug/res/mipmap-hdpi/ic_launcher.png | Bin 3313 -> 3367 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 5374 -> 5390 bytes .../src/debug/res/mipmap-mdpi/ic_launcher.png | Bin 2183 -> 2195 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 3287 -> 3307 bytes .../debug/res/mipmap-xhdpi/ic_launcher.png | Bin 4680 -> 4715 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 7672 -> 7760 bytes .../debug/res/mipmap-xxhdpi/ic_launcher.png | Bin 7246 -> 7309 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 11989 -> 12079 bytes .../debug/res/mipmap-xxxhdpi/ic_launcher.png | Bin 9955 -> 10107 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 17141 -> 17243 bytes 11 files changed, 23 insertions(+), 22 deletions(-) diff --git a/occtax/src/debug/res/drawable/ic_launcher_background.xml b/occtax/src/debug/res/drawable/ic_launcher_background.xml index 2bb73ad3..368a6a2a 100644 --- a/occtax/src/debug/res/drawable/ic_launcher_background.xml +++ b/occtax/src/debug/res/drawable/ic_launcher_background.xml @@ -3,26 +3,27 @@ android:height="108dp" android:viewportWidth="161.19403" android:viewportHeight="161.19403"> - - - - - - - - + + + + + + + + diff --git a/occtax/src/debug/res/mipmap-hdpi/ic_launcher.png b/occtax/src/debug/res/mipmap-hdpi/ic_launcher.png index 13235b100225dd129f9cbd8a5b0ad306958e03c0..7bfbb7c8c237185fd96c8613d40ae96b04c87af2 100644 GIT binary patch delta 3364 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 IM6N<$g5C{0JOBUy delta 2170 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 delta 3283 zcmV;^3@r2O8P^$*B!8YsL_t(|+U;6-R8;2`{{}DyL^O#WjZJz;tfn@pSx=g+t?lWS zSW|-_AR;2G0}R733;RASYOuKAo?w)TD1r+ZF-lO3LB(j)sDNfS#>5B;E(nj?d%rg` zJeV0~qNe?)@0@#h^WMz&e!qKv_kQ>L9*q6}uyO#Cv5X8Swtvyb`PuOBL6b5vT=-|} zhwQ%#j(`v#>5-c_p5@lz2jQEz14MS%h7^; zeO2S7Lrj{K;gVsS3{(#>4SyRRE_udXl?2Mce4djKiC%8%2fBx4YlZ&i?XBXLm$zEjwr!uVW=(|< z5RlkYUj9B*R@TCT1#4l^B102KDG~r=rfA$fX_KYu@bhVk(6kv#j3!RKg|Ot0-W z1JBWP+X8KiKyh&ykmr{zD}xg!S~!vL@JuKv+1h>f?3Y4r?rOkjb)zZooP-p-URP}P zy6Ev9N5D%7WM{90&6{^~&?q4&Ev-gUJ3*r<1i4&~a@x}~eY&R0^nEWc)$-dXA*}{_ zU8xbgsDEn*f%hli?cFzt>70zNn?45xrC@T4IYZapctdG0<$~iRK$1K;+GQNP2>d65 zC!6Z6LW^_AmMk$qXm|p=HYGxs>Jul>wJBbT6_SLOIpTe>#%F6{&7Qwa@MP{fCAi1O z*tOqgroySOzk=sAap3Cf1w$g|2=3|_!Ce&%Lw^(zsy^84*7+Rm^X7!jzCG|Vw0m+B zxXJ8%cifVE*xB?ctUs_1Tq9=z3-t#U83-&PO5je+Qg<_*;w6i@$foYIH4T!4bsV%_ z2V)oIf^tU%EIwEdrJpo%qjS18wn%S5=25&>gW$Ub0p`88O#~k{16X(fu(?PkNg-lL zRev5rWKI@XEv2K5kVwa&YU5sz41VS7;Lw+!!8bo%f~up9P+YqUQYy+|VNErB+jkL|~59`3Xzsf#Fyqe1G!QmylR)fQhMU@Q??AY>qE@%ngDK4f~<} z#tji6Z zOmH_#i3OIXY-Rxg9=3BJEk01d6Be*Fb(IdTxjC&qHnEOL;+4mRW;*~Z~Y+MH}(ZM44=-EU7SX`KZk-)$55ZeT@)HRN3pFB_C z^QyMM@Tg!ja59$=KbW;@3CwwGIlP>k3M)U@4IRcP*s|7Z9q{g<1MqBK8aPKGXfhLc z#T;OcO394U%%2!Fi2w^bNe^M+%G(esBaz?0`+%1MDg6=Z=6B_v)O zic-p}-U6MsZdm~D!sxVIya4}PS_ng8!$hx3JmnCL!d@s z*eeJ(tW%0!9VE2A#B(b)-OGqn9> zBLR=5K>}Jik_0| zy*T@RXO95QqKg~qVd=g z%*pFk!qn2$P>Wv6*?(SPl|X+ZGWRP&Ex_|WN0P8pRun@CMGBe_No3){b^d@YpuY z-?`l^8xEd;o4`vF_I`}SuG1%B)6v7=s*AGbdEnAXiV^sXtbdiaGI#fpy#z*%bZ43B zi?$@>oE8Vqbmry1YjZeS%+M=p#ZafGN#>)rvyeVOw(Bp5TG*^FA z56%Q!3SMUh54$9JDR z4h1{5Lg?Eo;9+cki}vi~-KI%S9a!&=U<)0G6W=hk+@j9Qusuk`h@HfWRPXJgDzP784R}-k`G6PH1YxF4KUTrQV+^(Oir|!sd732b7gG+3T85!xC(d z)3FzN5q~}GM8G9=etdo^oI!`EwwK!j--FLi)8E4@NO!BsC*Weshtap&y9}9C~So~ZVM18%L_F#C561JQ;3J0)_ zcu1dQOE$n|lco}|(BOT=RrZ&cU$C~wcgN*ht$(BK^vsG<-VWqdZ-ogdYEYv@UYVB# ze_u2YCSt`hFGei8N;CMpJ?}vWHgkT4HKsam&GUe54qAK{C!h@7+dqMO^B^K12EjWd zBe(n{Sh)WKKKs^U4bR7#?;0~_z-mLlN%Q0LQn}~pxAW`X2UjFx)AJlWN+(OxgOw8H z<9`+3w-1sYW5zs;KW=t(NqPT*G}zUAiUXlJAsHJu^1erWB* z&tdhVxnjrZ6L4RqW?=9c@xU_UySZbv@)kCFwC6zkLHFX!nS^~2FunaKkd0qb0QmynokfZl!Bm&cN7t=>yA#gI9|Y~1PtKvai{Wt!UZI#i5nXu!`NnUjZS~i+0Qzgphfh_I7p3mgq0i`2iP=$Vs*d8)& zmO2j3TkhUf1L3?wosmGQ@1#gbVa*7T_=AwWuv+;7+Z8ec6!b z1^#SG+yJivj>+!UqG@y2hdJ{ODKfAW=LRC-@XoXoM(w%91+X18e+^3{**5HRo+-)$ zCj#!6Yy|#HIuDt#fny;|;OJW$F@GN@RF5$E>}|$KAV9T4a-vx_x5vA^X=m5jVRaC;yvl|4LR z=@}%O5I^$#uQ-N`NiMhdmPY&`k??dP9j3(I<H#v8f}R2+91i+_+8QXe*ku$CaNHF RI+g$c002ovPDHLkV1g2}QiuQm diff --git a/occtax/src/debug/res/mipmap-xhdpi/ic_launcher.png b/occtax/src/debug/res/mipmap-xhdpi/ic_launcher.png index 5a78108cb9183625ed88af5c71c77fa31537cfe9..0b984a7bbd5b1e2693b8ba2e6b33b24462f8040c 100644 GIT binary patch literal 4715 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 literal 4680 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

aiugBDXWDDXiJ_P6-Z0*yXNAyjm3TI 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 T^YZqa5umB6r}A0JCj5T@+lZ#P literal 7246 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 literal 11989 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

>St#l-}#G!#HIWmvp;G$xs*-e}8+L~WCs{koU$ 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 diff --git a/occtax/src/debug/res/mipmap-xxxhdpi/ic_launcher.png b/occtax/src/debug/res/mipmap-xxxhdpi/ic_launcher.png index 3a804dd283df7f2c2b0e3c19b398c7e65071fb71..988ae3858a6ba1a2e6cea6695ebae88c2553ef51 100644 GIT binary patch literal 10107 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 buI?G5HwOmdMY(a@QD8bte**N literal 9955 zcmbt)^;cA1)c(vcbPhvFcS^T(*GNi;Qi61cfYi_}rIM0@AV{}JcXtbnAl)D^Fu*&X z@B01$?^^G=>z@0=J@@RrpM7FKd*4`HZ8btXYCHe{K&YXvtdD+n{&(YGpw-1kTFaulOgWoL^toOQn%+5a*L$1d`@L3g*N!nu%-S4Rg1$`9NB_BMr!EaWtZ+i{*6<2c+q zlRthqd(28SLp_qAm{x;;A(t`!E(5;aq!?hmTWC(F~lXgxJ=K*?!xiqmF8TUN?;ph+|E z>BWTWWYNHB?q?=Y%3xH+Gbu7#Virj#oL=6m)YnaCcgbs1w)@93PcQXSrKflo_s7V? z3FqJ-%*m=eFc#6Jfn_Iv>+*!Z>`D>?>xN544T%h1wf-8nvUSynclL2@W>gl4x=a)H zJ`k%G=K$0Q4DpjL#T6EFja~}o0J?h&HYN+w@DA5Q2;Lo!M*lnTvh0pnw;W6cH0;>C z{mUg2opgC=_TmMPkbNqf}wbw zQG9w+)Ay@~6JSdKkd=)$a(H-{ThGLg9Ce@eG1u$tjmM`XIp1SaGlkSNn0ftSZJ^zC=9i+bHPx3mkr-P!jcx3#gH%O|zYUh%k{lOPHA z4gL&qH^K_jPndS&uV1VNAIzJ%`y?7dJAVZbTm2n|-O@^uLeq6GY!4T4nmsm&f>!rt zA~kt%vt+K1W%94d$;i3}Qos4SvvsN@r%s@;C z;r`OhnZtpv94gr>$|aH=5HJ@UKTi}Ng2xO%cqF$`cmy#BswX5ga} z=p3_mwQrXE{#yV|El9e^pAQC5rGyt*gJ1tLRXpM02`KqQT>Z|aahlr`(M|q7Ku=Hb z{&9B-ak|mP@_q%;!(ny00qDZnkb8V$uvYt9%8YYCnOUj;H$QiGg?~j5n4t|AAJ=og z*rtnoQp62t;}yRKB%%gGw+SCbjjGm4GLAMkcX~!MN61goQ)~4Z1Ar5llZ9pjm1y0d zaJqlvKSS0+aXUpo@`|v`TJZ1)&u-8_Qr?dSVmJtUA-{e@ZR1&_xoGkNMyKh(|5pW z@Fg^gi0}`S?%qFa!t-eBf$_-!xgb+4o!pPpA)CW`Gf~-+;K}dLqeJv6hrpISU`rKH zXZ7Dm{B(!Kx%kX9ueolLR7NxFOvj94Vl#R2y>Sru z`9x5-gLtvCyEqy>HO|DYSÐv^(0p2 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 diff --git a/occtax/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png b/occtax/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png index ecbd4a793a9005aad9afb508dc9476982fac77e1..0394959719cd35b9a304db8a2462e307e85e619c 100644 GIT binary patch literal 17243 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

KasG)@4TWRycXm}VMy0_x3S@Vlk^ihy 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 From 6c1e8eb0ab2ee6617e3b88760ee8e0c50ebe6f0a Mon Sep 17 00:00:00 2001 From: "S. Grimault" Date: Tue, 15 Oct 2019 21:39:50 +0200 Subject: [PATCH 02/16] chore: update core and maps modules dependencies --- gn_mobile_maps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gn_mobile_maps b/gn_mobile_maps index fbb5bddb..bef55c57 160000 --- a/gn_mobile_maps +++ b/gn_mobile_maps @@ -1 +1 @@ -Subproject commit fbb5bddb4db2d7ace9f2bd1314ef13ebbc1c3f35 +Subproject commit bef55c579a8cc1769aa27821c22e1580100e9e4c From 99408919ec4a5f8130dfdf8b6e732f7ff58c36d8 Mon Sep 17 00:00:00 2001 From: "S. Grimault" Date: Tue, 15 Oct 2019 21:41:17 +0200 Subject: [PATCH 03/16] fix: clear active selection while refreshing the current Fragment --- occtax/build.gradle | 2 +- .../fr/geonature/occtax/ui/input/map/InputMapFragment.kt | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/occtax/build.gradle b/occtax/build.gradle index ce95f3d6..828e180a 100644 --- a/occtax/build.gradle +++ b/occtax/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' -version = "0.1.6" +version = "0.1.7" android { compileSdkVersion 28 diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/map/InputMapFragment.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/map/InputMapFragment.kt index c8130c97..bc961bd1 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/map/InputMapFragment.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/map/InputMapFragment.kt @@ -41,7 +41,7 @@ class InputMapFragment : MapFragment(), onSelectedPOIsListener = object : OnSelectedPOIsListener { override fun onSelectedPOIs(pois: List) { if (pois.isEmpty()) { - clearSelection() + clearInputSelection() } else { selectPOI(pois[0]) @@ -59,6 +59,7 @@ class InputMapFragment : MapFragment(), } override fun validate(): Boolean { + clearActiveSelection() return this.input?.geometry != null } @@ -74,7 +75,7 @@ class InputMapFragment : MapFragment(), this.input = input as Input } - private fun clearSelection() { + private fun clearInputSelection() { input?.geometry = null (activity as AbstractPagerFragmentActivity?)?.validateCurrentPage() From d48c42e09e15605a53c0e20d246335fedbadda10 Mon Sep 17 00:00:00 2001 From: "S. Grimault" Date: Sat, 19 Oct 2019 10:38:35 +0200 Subject: [PATCH 04/16] fix: clear active selection while refreshing the current Fragment --- gn_mobile_core | 2 +- gn_mobile_maps | 2 +- .../fr/geonature/occtax/ui/input/map/InputMapFragment.kt | 7 ++++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/gn_mobile_core b/gn_mobile_core index e8e2716b..63c7aa4f 160000 --- a/gn_mobile_core +++ b/gn_mobile_core @@ -1 +1 @@ -Subproject commit e8e2716b3b1a91ee6847b402f8579e7d8ff19804 +Subproject commit 63c7aa4fba78dfeabbbc2aaf9f2cd668e418f92b diff --git a/gn_mobile_maps b/gn_mobile_maps index bef55c57..3355ff30 160000 --- a/gn_mobile_maps +++ b/gn_mobile_maps @@ -1 +1 @@ -Subproject commit bef55c579a8cc1769aa27821c22e1580100e9e4c +Subproject commit 3355ff30a3c13fc72ee71481bcf99430554f24c6 diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/map/InputMapFragment.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/map/InputMapFragment.kt index bc961bd1..02ad4ff2 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/map/InputMapFragment.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/map/InputMapFragment.kt @@ -50,6 +50,12 @@ class InputMapFragment : MapFragment(), } } + override fun onPause() { + super.onPause() + + clearActiveSelection() + } + override fun getResourceTitle(): Int { return R.string.pager_fragment_map_title } @@ -59,7 +65,6 @@ class InputMapFragment : MapFragment(), } override fun validate(): Boolean { - clearActiveSelection() return this.input?.geometry != null } From a9ed91345309b43c7b35c4ad107e87e494bf9260 Mon Sep 17 00:00:00 2001 From: "S. Grimault" Date: Tue, 22 Oct 2019 21:46:39 +0200 Subject: [PATCH 05/16] style: OccTax launcher icon --- artwork/occtax_launcher.svg | 105 ++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 artwork/occtax_launcher.svg diff --git a/artwork/occtax_launcher.svg b/artwork/occtax_launcher.svg new file mode 100644 index 00000000..0e85b561 --- /dev/null +++ b/artwork/occtax_launcher.svg @@ -0,0 +1,105 @@ + + + + + + image/svg+xml + + OccTax launcher icon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From c9328c45523a7231f596603e818321bdecda9807 Mon Sep 17 00:00:00 2001 From: Camille Monchicourt Date: Tue, 22 Oct 2019 22:54:20 +0200 Subject: [PATCH 06/16] Add occtax-mobile-launcher PNG --- artwork/occtax-mobile-icon.png | Bin 0 -> 20444 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 artwork/occtax-mobile-icon.png diff --git a/artwork/occtax-mobile-icon.png b/artwork/occtax-mobile-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..457ba1872f65ff5bd028a8421e380be5ff84301c GIT binary patch literal 20444 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 D0rY!u literal 0 HcmV?d00001 From cfb4e9a2cdfe0e5db5b059c148d49ae817ce260e Mon Sep 17 00:00:00 2001 From: Camille Monchicourt Date: Tue, 22 Oct 2019 22:57:52 +0200 Subject: [PATCH 07/16] README - Launcher + description --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 08bc00a8..1666342a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,8 @@ -# gn_mobile_occtax +# Occtax-mobile + +![Occtax-mobile launcher](https://raw.githubusercontent.com/PnX-SI/gn_mobile_occtax/develop/occtax/src/main/res/mipmap-xxxhdpi/ic_launcher.png) + +GeoNature Android mobile application for Occtax module. ## Upgrade git sub modules From 7e378789b18944695c6186a8edfa16383a79196d Mon Sep 17 00:00:00 2001 From: Camille Monchicourt Date: Tue, 22 Oct 2019 22:58:12 +0200 Subject: [PATCH 08/16] Delete occtax-mobile-icon.png --- artwork/occtax-mobile-icon.png | Bin 20444 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 artwork/occtax-mobile-icon.png diff --git a/artwork/occtax-mobile-icon.png b/artwork/occtax-mobile-icon.png deleted file mode 100644 index 457ba1872f65ff5bd028a8421e380be5ff84301c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20444 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 D0rY!u From 9ff948182e589c61d1c61cd527b7cf71f0e8930c Mon Sep 17 00:00:00 2001 From: "S. Grimault" Date: Sun, 27 Oct 2019 11:35:42 +0100 Subject: [PATCH 09/16] feat: add additional counting information for the given input taxon. --- occtax/src/main/AndroidManifest.xml | 4 +- .../occtax/input/CountingMetadata.kt | 100 +++++ .../fr/geonature/occtax/input/InputTaxon.kt | 70 ++- .../geonature/occtax/input/PropertyValue.kt | 84 ++++ .../occtax/input/SelectedProperty.kt | 6 + .../input/io/OnInputJsonReaderListenerImpl.kt | 221 ++++++++- .../input/io/OnInputJsonWriterListenerImpl.kt | 130 +++++- .../ui/input/InputPagerFragmentActivity.kt | 3 + .../ui/input/counting/CountingFragment.kt | 176 ++++++++ .../counting/CountingRecyclerViewAdapter.kt | 200 +++++++++ .../counting/EditCountingMetadataActivity.kt | 88 ++++ .../counting/EditCountingMetadataFragment.kt | 192 ++++++++ .../NomenclatureTypesRecyclerViewAdapter.kt | 423 ++++++++++++++++++ .../ChooseNomenclatureDialogFragment.kt | 5 +- .../NomenclatureRecyclerViewAdapter.kt | 2 +- .../input/informations/InformationFragment.kt | 1 + .../NomenclatureTypesRecyclerViewAdapter.kt | 8 +- occtax/src/main/res/layout/card_view.xml | 4 +- .../src/main/res/layout/fragment_counting.xml | 42 ++ occtax/src/main/res/layout/list_item_2.xml | 8 +- occtax/src/main/res/layout/recycler_view.xml | 4 +- .../main/res/layout/view_action_edit_text.xml | 1 + .../main/res/layout/view_action_min_max.xml | 43 ++ .../src/main/res/values-fr/nomenclatures.xml | 4 + occtax/src/main/res/values-fr/strings.xml | 11 + occtax/src/main/res/values/nomenclatures.xml | 4 + occtax/src/main/res/values/strings.xml | 11 + .../occtax/input/CountingMetadataTest.kt | 80 ++++ .../geonature/occtax/input/InputTaxonTest.kt | 117 +++++ .../occtax/input/PropertyValueTest.kt | 130 ++++++ .../occtax/input/io/InputJsonReaderTest.kt | 82 ++-- .../occtax/input/io/InputJsonWriterTest.kt | 82 ++-- .../test/resources/fixtures/input_simple.json | 33 +- 33 files changed, 2255 insertions(+), 114 deletions(-) create mode 100644 occtax/src/main/java/fr/geonature/occtax/input/CountingMetadata.kt create mode 100644 occtax/src/main/java/fr/geonature/occtax/input/PropertyValue.kt create mode 100644 occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingFragment.kt create mode 100644 occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingRecyclerViewAdapter.kt create mode 100644 occtax/src/main/java/fr/geonature/occtax/ui/input/counting/EditCountingMetadataActivity.kt create mode 100644 occtax/src/main/java/fr/geonature/occtax/ui/input/counting/EditCountingMetadataFragment.kt create mode 100644 occtax/src/main/java/fr/geonature/occtax/ui/input/counting/NomenclatureTypesRecyclerViewAdapter.kt rename occtax/src/main/java/fr/geonature/occtax/ui/input/{informations => dialog}/ChooseNomenclatureDialogFragment.kt (98%) rename occtax/src/main/java/fr/geonature/occtax/ui/input/{informations => dialog}/NomenclatureRecyclerViewAdapter.kt (98%) create mode 100644 occtax/src/main/res/layout/fragment_counting.xml create mode 100644 occtax/src/main/res/layout/view_action_min_max.xml create mode 100644 occtax/src/test/java/fr/geonature/occtax/input/CountingMetadataTest.kt create mode 100644 occtax/src/test/java/fr/geonature/occtax/input/InputTaxonTest.kt create mode 100644 occtax/src/test/java/fr/geonature/occtax/input/PropertyValueTest.kt diff --git a/occtax/src/main/AndroidManifest.xml b/occtax/src/main/AndroidManifest.xml index 5fa209ae..1af09bd6 100644 --- a/occtax/src/main/AndroidManifest.xml +++ b/occtax/src/main/AndroidManifest.xml @@ -16,8 +16,7 @@ + android:label="@string/activity_main_title"> @@ -33,6 +32,7 @@ + diff --git a/occtax/src/main/java/fr/geonature/occtax/input/CountingMetadata.kt b/occtax/src/main/java/fr/geonature/occtax/input/CountingMetadata.kt new file mode 100644 index 00000000..a4b25cea --- /dev/null +++ b/occtax/src/main/java/fr/geonature/occtax/input/CountingMetadata.kt @@ -0,0 +1,100 @@ +package fr.geonature.occtax.input + +import android.os.Parcel +import android.os.Parcelable +import java.util.SortedMap +import java.util.TreeMap + +/** + * Counting metadata. + * + * @author [S. Grimault](mailto:sebastien.grimault@gmail.com) + */ +class CountingMetadata() : Parcelable { + + var index: Int = 0 + internal set + + val properties: SortedMap = TreeMap(Comparator { o1, o2 -> + val i1 = defaultMnemonicOrder.indexOfFirst { it == o1 } + val i2 = defaultMnemonicOrder.indexOfFirst { it == o2 } + + when { + i1 == -1 -> 1 + i2 == -1 -> -1 + else -> i1 - i2 + } + }) + var min: Int = 0 + var max: Int = 0 + + constructor(source: Parcel) : this() { + index = source.readInt() + (source.createTypedArrayList(PropertyValue.CREATOR) + ?: emptyList()) + .forEach { + this.properties[it.code] = it + } + min = source.readInt() + max = source.readInt() + } + + override fun describeContents(): Int { + return 0 + } + + override fun writeToParcel(dest: Parcel?, + flags: Int) { + dest?.also { + it.writeInt(index) + it.writeTypedList(this.properties.values.toList()) + it.writeInt(min) + it.writeInt(max) + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is CountingMetadata) return false + + if (index != other.index) return false + if (properties != other.properties) return false + if (min != other.min) return false + if (max != other.max) return false + + return true + } + + override fun hashCode(): Int { + var result = index + result = 31 * result + properties.hashCode() + result = 31 * result + min + result = 31 * result + max + + return result + } + + fun isEmpty(): Boolean { + return properties.filterNot { it.value.isEmpty() }.isEmpty() && min == 0 && max == 0 + } + + companion object { + + private val defaultMnemonicOrder = arrayOf("STADE_VIE", + "SEXE", + "OBJ_DENBR", + "TYP_DENBR") + + @JvmField + val CREATOR: Parcelable.Creator = object : Parcelable.Creator { + + override fun createFromParcel(source: Parcel): CountingMetadata { + return CountingMetadata(source) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } + } +} \ No newline at end of file diff --git a/occtax/src/main/java/fr/geonature/occtax/input/InputTaxon.kt b/occtax/src/main/java/fr/geonature/occtax/input/InputTaxon.kt index 8c73b1fd..415db1f5 100644 --- a/occtax/src/main/java/fr/geonature/occtax/input/InputTaxon.kt +++ b/occtax/src/main/java/fr/geonature/occtax/input/InputTaxon.kt @@ -4,6 +4,8 @@ import android.os.Parcel import android.os.Parcelable import fr.geonature.commons.data.AbstractTaxon import fr.geonature.commons.input.AbstractInputTaxon +import java.util.SortedMap +import java.util.TreeMap /** * Describes an input taxon. @@ -12,7 +14,17 @@ import fr.geonature.commons.input.AbstractInputTaxon */ class InputTaxon : AbstractInputTaxon { - val properties: MutableMap = HashMap() + val properties: SortedMap = TreeMap(Comparator { o1, o2 -> + val i1 = defaultPropertiesMnemonicOrder.indexOfFirst { it == o1 } + val i2 = defaultPropertiesMnemonicOrder.indexOfFirst { it == o2 } + + when { + i1 == -1 -> 1 + i2 == -1 -> -1 + else -> i1 - i2 + } + }) + private val counting: SortedMap = TreeMap() constructor(taxon: AbstractTaxon) : super(taxon) constructor(source: Parcel) : super(source) { @@ -21,6 +33,11 @@ class InputTaxon : AbstractInputTaxon { .forEach { this.properties[it.code] = it } + + val countLingAsList = mutableListOf() + source.readTypedList(countLingAsList, + CountingMetadata.CREATOR) + countLingAsList.forEach { counting[it.index] = it } } override fun writeToParcel(dest: Parcel?, @@ -28,7 +45,10 @@ class InputTaxon : AbstractInputTaxon { super.writeToParcel(dest, flags) - dest?.writeTypedList(this.properties.values.toList()) + dest?.also { + it.writeTypedList(this.properties.values.toList()) + it.writeTypedList(getCounting()) + } } override fun equals(other: Any?): Boolean { @@ -37,6 +57,7 @@ class InputTaxon : AbstractInputTaxon { if (!super.equals(other)) return false if (properties != other.properties) return false + if (counting != other.counting) return false return true } @@ -44,17 +65,50 @@ class InputTaxon : AbstractInputTaxon { override fun hashCode(): Int { var result = super.hashCode() result = 31 * result + properties.hashCode() + result = 31 * result + counting.hashCode() return result } - companion object CREATOR : Parcelable.Creator { - override fun createFromParcel(parcel: Parcel): InputTaxon { - return InputTaxon(parcel) - } + fun getCounting(): List { + return counting.values.toList() + } + + fun addCountingMetadata(countingMetadata: CountingMetadata) { + if (countingMetadata.isEmpty()) return + + val index = if (countingMetadata.index > 0) countingMetadata.index + else this.counting.keys.max()?.plus(1) ?: 1 + + counting[index] = countingMetadata.apply { this.index = index } + } - override fun newArray(size: Int): Array { - return arrayOfNulls(size) + + fun deleteCountingMetadata(index: Int): CountingMetadata? { + return counting.remove(index) + } + + companion object { + + private val defaultPropertiesMnemonicOrder = arrayOf("METH_OBS", + "ETA_BIO", + "METH_DETERMIN", + "DETERMINER", + "STATUT_BIO", + "NATURALITE", + "PREUVE_EXIST", + "COMMENT") + + @JvmField + val CREATOR: Parcelable.Creator = object : Parcelable.Creator { + + override fun createFromParcel(source: Parcel): InputTaxon { + return InputTaxon(source) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } } } } \ No newline at end of file diff --git a/occtax/src/main/java/fr/geonature/occtax/input/PropertyValue.kt b/occtax/src/main/java/fr/geonature/occtax/input/PropertyValue.kt new file mode 100644 index 00000000..dc44c571 --- /dev/null +++ b/occtax/src/main/java/fr/geonature/occtax/input/PropertyValue.kt @@ -0,0 +1,84 @@ +package fr.geonature.occtax.input + +import android.os.Parcel +import android.os.Parcelable +import android.text.TextUtils +import fr.geonature.commons.data.Nomenclature +import fr.geonature.commons.input.AbstractInputTaxon +import java.io.Serializable + +/** + * Property value for [AbstractInputTaxon] + * + * @author [S. Grimault](mailto:sebastien.grimault@gmail.com) + */ +data class PropertyValue(val code: String, + val label: String?, + val value: Serializable?) : Parcelable { + + internal constructor(source: Parcel) : this(source.readString()!!, + source.readString(), + source.readSerializable()) + + override fun describeContents(): Int { + return 0 + } + + override fun writeToParcel(dest: Parcel?, + flags: Int) { + dest?.also { + it.writeString(code) + it.writeString(label) + it.writeSerializable(value) + } + } + + fun isEmpty(): Boolean { + return TextUtils.isEmpty(label) && value == null + } + + companion object { + + /** + * Creates a [PropertyValue] instance from given [Nomenclature]. + */ + fun fromNomenclature(code: String, + nomenclature: Nomenclature?): PropertyValue { + return PropertyValue(code, + nomenclature?.defaultLabel, + nomenclature?.id) + } + + /** + * Creates a [PropertyValue] instance from given String value. + */ + fun fromValue(code: String, + value: String?): PropertyValue { + return PropertyValue(code, + null, + value) + } + + /** + * Creates a [PropertyValue] instance from given Int value. + */ + fun fromValue(code: String, + value: Int?): PropertyValue { + return PropertyValue(code, + null, + value) + } + + @JvmField + val CREATOR: Parcelable.Creator = object : Parcelable.Creator { + + override fun createFromParcel(source: Parcel): PropertyValue { + return PropertyValue(source) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } + } +} \ No newline at end of file diff --git a/occtax/src/main/java/fr/geonature/occtax/input/SelectedProperty.kt b/occtax/src/main/java/fr/geonature/occtax/input/SelectedProperty.kt index a29dc26c..5f177f5b 100644 --- a/occtax/src/main/java/fr/geonature/occtax/input/SelectedProperty.kt +++ b/occtax/src/main/java/fr/geonature/occtax/input/SelectedProperty.kt @@ -12,6 +12,8 @@ import java.util.Locale * * @author [S. Grimault](mailto:sebastien.grimault@gmail.com) */ +@Deprecated("see PropertyValue", + ReplaceWith("PropertyValue")) data class SelectedProperty(val type: PropertyType, val code: String, val id: Long?, @@ -63,6 +65,8 @@ data class SelectedProperty(val type: PropertyType, /** * Creates a SelectedProperty instance from given [Nomenclature] */ + @Deprecated("use fromNomenclature from PropertyValue", + ReplaceWith("PropertyValue")) fun fromNomenclature(code: String, nomenclature: Nomenclature?): SelectedProperty { return SelectedProperty(PropertyType.NOMENCLATURE, @@ -74,6 +78,8 @@ data class SelectedProperty(val type: PropertyType, /** * Creates a SelectedProperty instance from given String value */ + @Deprecated("use fromValue from PropertyValue", + ReplaceWith("PropertyValue")) fun fromValue(code: String, value: String?): SelectedProperty { return SelectedProperty(PropertyType.TEXT, diff --git a/occtax/src/main/java/fr/geonature/occtax/input/io/OnInputJsonReaderListenerImpl.kt b/occtax/src/main/java/fr/geonature/occtax/input/io/OnInputJsonReaderListenerImpl.kt index 38f4635b..912351ff 100644 --- a/occtax/src/main/java/fr/geonature/occtax/input/io/OnInputJsonReaderListenerImpl.kt +++ b/occtax/src/main/java/fr/geonature/occtax/input/io/OnInputJsonReaderListenerImpl.kt @@ -9,9 +9,12 @@ import fr.geonature.commons.input.AbstractInput import fr.geonature.commons.input.io.InputJsonReader import fr.geonature.commons.util.IsoDateUtils import fr.geonature.maps.jts.geojson.io.GeoJsonReader +import fr.geonature.occtax.input.CountingMetadata import fr.geonature.occtax.input.Input import fr.geonature.occtax.input.InputTaxon +import fr.geonature.occtax.input.PropertyValue import fr.geonature.occtax.input.SelectedProperty +import java.io.Serializable import java.util.Date import java.util.Locale @@ -120,6 +123,39 @@ class OnInputJsonReaderListenerImpl : InputJsonReader.OnInputJsonReaderListener< reader.endArray() } + /** + * Reads input taxon as object: + * + * ``` + * { + * "cd_nom": "String", + * "nom_cite": "String", + * "regne": "String", + * "group2_inpn": "String", + * "properties": { + * "property_code_x": { + * "type": "PropertyType", + * "id": "Long", + * "label: "String" + * }, + * ... + * "counting": [ + * { + * "property_code_x": { + * "type": "PropertyType", + * "id": "Long", + * "label: "String" + * }, + * ... + * "min": "Int", + * "max": "Int" + * }, + * ... + * ] + * } + * } + * ``` + */ private fun readInputTaxon(reader: JsonReader, input: AbstractInput) { reader.beginObject() @@ -128,7 +164,8 @@ class OnInputJsonReaderListenerImpl : InputJsonReader.OnInputJsonReaderListener< var name: String? = null var kingdom: String? = null var group: String? = null - val properties = mutableMapOf() + val properties = Pair(mutableMapOf(), + mutableListOf()) while (reader.hasNext()) { when (reader.nextName()) { @@ -138,7 +175,10 @@ class OnInputJsonReaderListenerImpl : InputJsonReader.OnInputJsonReaderListener< "group2_inpn" -> group = reader.nextString() "properties" -> { if (reader.peek() != JsonToken.NULL) { - properties.putAll(readInputTaxonProperties(reader)) + readInputTaxonProperties(reader).also { + properties.first.putAll(it.first) + properties.second.addAll(it.second) + } } else { reader.nextNull() @@ -156,21 +196,54 @@ class OnInputJsonReaderListenerImpl : InputJsonReader.OnInputJsonReaderListener< name!!, Taxonomy(kingdom!!, group))).apply { - this.properties.putAll(properties) + this.properties.putAll(properties.first) + properties.second.forEach { this.addCountingMetadata(it) } }) } - private fun readInputTaxonProperties(reader: JsonReader): Map { - val properties = mutableMapOf() + /** + * Reads input taxon properties as object: + * + * ``` + * { + * "property_code_x": { + * "type": "PropertyType", + * "id": "Long", + * "label: "String" + * }, + * ... + * "counting": [ + * { + * "property_code_x": { + * "type": "PropertyType", + * "id": "Long", + * "label: "String" + * }, + * ... + * "min": "Int", + * "max": "Int" + * }, + * ... + * ] + * } + * ``` + */ + private fun readInputTaxonProperties(reader: JsonReader): Pair, List> { + val properties = Pair(mutableMapOf(), + mutableListOf()) reader.beginObject() while (reader.hasNext()) { when (reader.peek()) { JsonToken.NAME -> { - val selectedProperty = readInputTaxonProperty(reader, - reader.nextName()) - if (selectedProperty != null) properties[selectedProperty.code] = selectedProperty + when (val propertyName = reader.nextName()) { + "counting" -> properties.second.addAll(readInputTaxonCounting(reader)) + else -> readInputTaxonProperty(reader, + propertyName)?.also { + properties.first[it.code] = it + } + } } else -> reader.skipValue() } @@ -181,6 +254,97 @@ class OnInputJsonReaderListenerImpl : InputJsonReader.OnInputJsonReaderListener< return properties } + /** + * Reads input taxon counting as array: + * + * ``` + * [ + * { + * "property_code_x": { + * "type": "PropertyType", + * "id": "Long", + * "label: "String" + * }, + * ... + * "min": "Int", + * "max": "Int" + * }, + * ... + * ] + * ``` + */ + private fun readInputTaxonCounting(reader: JsonReader): List { + val counting = mutableListOf() + + reader.beginArray() + + while (reader.hasNext()) { + readInputTaxonCountingMetadata(reader)?.also { + counting.add(it) + } + } + + reader.endArray() + + return counting + } + + /** + * Reads input taxon counting metadata as object: + * + * ``` + * { + * "index": "Int", + * "property_code_x": { + * "type": "PropertyType", + * "id": "Long", + * "label: "String" + * }, + * ... + * "min": "Int", + * "max": "Int" + * } + * ``` + */ + private fun readInputTaxonCountingMetadata(reader: JsonReader): CountingMetadata? { + reader.beginObject() + + val countingMetadata = CountingMetadata() + + while (reader.hasNext()) { + when (reader.peek()) { + JsonToken.NAME -> { + when (val propertyName = reader.nextName()) { + "index" -> countingMetadata.index = reader.nextInt() + "min" -> countingMetadata.min = reader.nextInt() + "max" -> countingMetadata.max = reader.nextInt() + else -> readInputTaxonPropertyValue(reader, + propertyName)?.also { + countingMetadata.properties[it.code] = it + } + } + } + else -> reader.skipValue() + } + } + + reader.endObject() + + return if (countingMetadata.isEmpty()) null else countingMetadata + } + + /** + * Reads input taxon property as object: + * + * ``` + * { + * "type": "PropertyType", + * "id": "Long", + * "label: "String" + * } + * ``` + */ + @Deprecated("use readInputTaxonPropertyValue") private fun readInputTaxonProperty(reader: JsonReader, code: String): SelectedProperty? { reader.beginObject() @@ -209,4 +373,45 @@ class OnInputJsonReaderListenerImpl : InputJsonReader.OnInputJsonReaderListener< return if (selectedProperty.isEmpty()) null else selectedProperty } + + /** + * Reads input taxon property as object: + * + * ``` + * { + * "label: "String" + * "value": "String"|Long|Int + * } + * ``` + */ + private fun readInputTaxonPropertyValue(reader: JsonReader, + code: String): PropertyValue? { + reader.beginObject() + + var label: String? = null + var value: Serializable? = null + + while (reader.hasNext()) { + when (reader.nextName()) { + "label" -> label = reader.nextString() + "value" -> { + when (reader.peek()) { + JsonToken.STRING -> value = reader.nextString() + JsonToken.NUMBER -> value = reader.nextLong() + else -> reader.nextNull() + } + } + else -> reader.skipValue() + } + } + + reader.endObject() + + val propertyValue = PropertyValue( + code.toUpperCase(Locale.ROOT), + label, + value) + + return if (propertyValue.isEmpty()) null else propertyValue + } } \ No newline at end of file diff --git a/occtax/src/main/java/fr/geonature/occtax/input/io/OnInputJsonWriterListenerImpl.kt b/occtax/src/main/java/fr/geonature/occtax/input/io/OnInputJsonWriterListenerImpl.kt index 2e15dec2..586e08f3 100644 --- a/occtax/src/main/java/fr/geonature/occtax/input/io/OnInputJsonWriterListenerImpl.kt +++ b/occtax/src/main/java/fr/geonature/occtax/input/io/OnInputJsonWriterListenerImpl.kt @@ -6,8 +6,10 @@ import fr.geonature.commons.input.AbstractInputTaxon import fr.geonature.commons.input.io.InputJsonWriter import fr.geonature.commons.util.IsoDateUtils import fr.geonature.maps.jts.geojson.io.GeoJsonWriter +import fr.geonature.occtax.input.CountingMetadata import fr.geonature.occtax.input.Input import fr.geonature.occtax.input.InputTaxon +import fr.geonature.occtax.input.PropertyValue import fr.geonature.occtax.input.SelectedProperty import java.util.Locale @@ -112,35 +114,19 @@ class OnInputJsonWriterListenerImpl : InputJsonWriter.OnInputJsonWriterListener< writer.name("group2_inpn") .value(inputTaxon.taxon.taxonomy.group) - val defaultMnemonicOrder = arrayOf("METH_OBS", - "ETA_BIO", - "METH_DETERMIN", - "DETERMINER", - "STATUT_BIO", - "NATURALITE", - "PREUVE_EXIST", - "COMMENT") - writeInputTaxonProperties(writer, - (inputTaxon as InputTaxon).properties.toSortedMap(Comparator { o1, o2 -> - val i1 = defaultMnemonicOrder.indexOfFirst { it == o1 } - val i2 = defaultMnemonicOrder.indexOfFirst { it == o2 } - - when { - i1 == -1 -> 1 - i2 == -1 -> -1 - else -> i1 - i2 - } - })) + (inputTaxon as InputTaxon).properties, + inputTaxon.getCounting()) writer.endObject() } private fun writeInputTaxonProperties(writer: JsonWriter, - properties: Map) { + properties: Map, + counting: List) { writer.name("properties") - if (properties.isEmpty()) { + if (properties.isEmpty() && counting.isEmpty()) { writer.nullValue() return } @@ -153,6 +139,9 @@ class OnInputJsonWriterListenerImpl : InputJsonWriter.OnInputJsonWriterListener< it.value) } + writeInputTaxonCounting(writer, + counting) + writer.endObject() // GeoNature mapping @@ -170,8 +159,70 @@ class OnInputJsonWriterListenerImpl : InputJsonWriter.OnInputJsonWriterListener< "COMMENT" -> writer.name("comment").value(it.value.label) } } + + // GeoNature mapping: counting + writer.name("cor_counting_occtax") + .beginArray() + counting.forEach { c -> + if (c.isEmpty()) return@forEach + + writer.beginObject() + + c.properties.forEach { p -> + when (p.key) { + "STADE_VIE" -> writer.name("id_nomenclature_life_stage").value(p.value.value as Long) + "SEXE" -> writer.name("id_nomenclature_sex").value(p.value.value as Long) + "OBJ_DENBR" -> writer.name("id_nomenclature_obj_count").value(p.value.value as Long) + "TYP_DENBR" -> writer.name("id_nomenclature_type_count").value(p.value.value as Long) + } + } + + writer.name("count_min") + .value(c.min) + writer.name("count_max") + .value(c.max) + + writer.endObject() + } + writer.endArray() + } + + private fun writeInputTaxonCounting(writer: JsonWriter, + counting: List) { + writer.name("counting") + .beginArray() + + counting.forEach { + writeInputTaxonCountingMetadata(writer, + it) + } + + writer.endArray() } + private fun writeInputTaxonCountingMetadata(writer: JsonWriter, + countingMetadata: CountingMetadata) { + if (countingMetadata.isEmpty()) return + + writer.beginObject() + + writer.name("index") + .value(countingMetadata.index) + countingMetadata.properties.forEach { + writeInputTaxonPropertyValue(writer, + it.key, + it.value) + } + + writer.name("min") + .value(countingMetadata.min) + writer.name("max") + .value(countingMetadata.max) + + writer.endObject() + } + + @Deprecated("use writeInputTaxonPropertyValue") private fun writeInputTaxonProperty(writer: JsonWriter, name: String, selectedProperty: SelectedProperty) { @@ -195,4 +246,41 @@ class OnInputJsonWriterListenerImpl : InputJsonWriter.OnInputJsonWriterListener< writer.endObject() } + + /** + * Writes property value as object: + * + * ``` + * "property_code": { + * "label": "String", + * "value": "String"|Long|Int + * } + * ``` + */ + private fun writeInputTaxonPropertyValue(writer: JsonWriter, + name: String, + propertyValue: PropertyValue) { + if (propertyValue.isEmpty()) return + + writer.name(name.toLowerCase(Locale.ROOT)) + .beginObject() + + if (!TextUtils.isEmpty(propertyValue.label)) { + writer.name("label") + .value(propertyValue.label) + } + + if (propertyValue.value != null) { + when (propertyValue.value) { + is String -> writer.name("value") + .value(propertyValue.value) + is Long -> writer.name("value") + .value(propertyValue.value) + is Int -> writer.name("value") + .value(propertyValue.value) + } + } + + writer.endObject() + } } \ No newline at end of file diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/InputPagerFragmentActivity.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/InputPagerFragmentActivity.kt index 907967c6..a1e7dc8b 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/InputPagerFragmentActivity.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/InputPagerFragmentActivity.kt @@ -11,6 +11,7 @@ import fr.geonature.occtax.R import fr.geonature.occtax.input.Input import fr.geonature.occtax.input.InputViewModel import fr.geonature.occtax.settings.AppSettings +import fr.geonature.occtax.ui.input.counting.CountingFragment import fr.geonature.occtax.ui.input.informations.InformationFragment import fr.geonature.occtax.ui.input.map.InputMapFragment import fr.geonature.occtax.ui.input.observers.ObserversAndDateInputFragment @@ -73,6 +74,8 @@ class InputPagerFragmentActivity : AbstractNavigationHistoryPagerFragmentActivit TaxaFragment.newInstance()) put(R.string.pager_fragment_information_title, InformationFragment.newInstance()) + put(R.string.pager_fragment_counting_title, + CountingFragment.newInstance()) } override fun performFinishAction() { diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingFragment.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingFragment.kt new file mode 100644 index 00000000..e4fba101 --- /dev/null +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingFragment.kt @@ -0,0 +1,176 @@ +package fr.geonature.occtax.ui.input.counting + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.animation.AnimationUtils +import android.widget.Toast +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.snackbar.Snackbar +import fr.geonature.commons.data.Taxonomy +import fr.geonature.commons.input.AbstractInput +import fr.geonature.occtax.R +import fr.geonature.occtax.input.CountingMetadata +import fr.geonature.occtax.input.Input +import fr.geonature.occtax.input.InputTaxon +import fr.geonature.occtax.ui.input.IInputFragment +import fr.geonature.viewpager.ui.IValidateFragment +import kotlinx.android.synthetic.main.fragment_counting.countingContent +import kotlinx.android.synthetic.main.fragment_counting.countingEmptyTextView +import kotlinx.android.synthetic.main.fragment_counting.countingRecyclerView +import kotlinx.android.synthetic.main.fragment_counting.fab + +/** + * [Fragment] to let the user to add additional counting information for the given [Input]. + * + * @author [S. Grimault](mailto:sebastien.grimault@gmail.com) + */ +class CountingFragment : Fragment(), + IValidateFragment, + IInputFragment { + + private var input: Input? = null + private var adapter: CountingRecyclerViewAdapter? = null + + override fun onCreateView(inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.fragment_counting, + container, + false) + } + + override fun onViewCreated( + view: View, + savedInstanceState: Bundle?) { + super.onViewCreated(view, + savedInstanceState) + + fab.setOnClickListener { + val context = context ?: return@setOnClickListener + + startActivityForResult(EditCountingMetadataActivity.newIntent(context, + input?.getCurrentSelectedInputTaxon()?.taxon?.taxonomy + ?: Taxonomy(Taxonomy.ANY, + Taxonomy.ANY)), + 0) + } + + adapter = CountingRecyclerViewAdapter(object : CountingRecyclerViewAdapter.OnCountingRecyclerViewAdapterListener { + override fun onClick(countingMetadata: CountingMetadata) { + val context = context ?: return + startActivityForResult(EditCountingMetadataActivity.newIntent(context, + input?.getCurrentSelectedInputTaxon()?.taxon?.taxonomy + ?: Taxonomy(Taxonomy.ANY, + Taxonomy.ANY), + countingMetadata), + 0) + } + + override fun onLongClicked(position: Int, + countingMetadata: CountingMetadata) { + if ((input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.deleteCountingMetadata(countingMetadata.index) != null) { + refreshView() + + Snackbar.make(countingContent, + R.string.counting_snackbar_counting_deleted, + Snackbar.LENGTH_LONG) + .setAction(R.string.counting_snackbar_counting_undo + ) { + (input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.addCountingMetadata(countingMetadata) + refreshView() + } + .show() + } + } + + override fun showEmptyTextView(show: Boolean) { + if (countingEmptyTextView.visibility == View.VISIBLE == show) { + return + } + + if (show) { + countingEmptyTextView.startAnimation(AnimationUtils.loadAnimation(context, + android.R.anim.fade_in)) + countingEmptyTextView.visibility = View.VISIBLE + + } + else { + countingEmptyTextView.startAnimation(AnimationUtils.loadAnimation(context, + android.R.anim.fade_out)) + countingEmptyTextView.visibility = View.GONE + } + } + }) + + with(countingRecyclerView as RecyclerView) { + layoutManager = LinearLayoutManager(context) + adapter = this@CountingFragment.adapter + + val dividerItemDecoration = DividerItemDecoration(context, + (layoutManager as LinearLayoutManager).orientation) + addItemDecoration(dividerItemDecoration) + } + } + + override fun onActivityResult( + requestCode: Int, + resultCode: Int, + data: Intent?) { + if ((resultCode == Activity.RESULT_OK) && (data != null)) { + val countingMetadata = data.getParcelableExtra(EditCountingMetadataActivity.EXTRA_COUNTING_METADATA) + + if (countingMetadata.isEmpty()) { + (input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.deleteCountingMetadata(countingMetadata.index) + Toast.makeText(context, + R.string.counting_toast_empty, + Toast.LENGTH_LONG) + .show() + + return + } + + (input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.addCountingMetadata(countingMetadata) + } + } + + override fun getResourceTitle(): Int { + return R.string.pager_fragment_counting_title + } + + override fun pagingEnabled(): Boolean { + return true + } + + override fun validate(): Boolean { + return true + } + + override fun refreshView() { + (input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.getCounting() + ?.also { + adapter?.setCounting(it) + } + } + + override fun setInput(input: AbstractInput) { + this.input = input as Input + } + + companion object { + + /** + * Use this factory method to create a new instance of [CountingFragment]. + * + * @return A new instance of [CountingFragment] + */ + @JvmStatic + fun newInstance() = CountingFragment() + } +} \ No newline at end of file diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingRecyclerViewAdapter.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingRecyclerViewAdapter.kt new file mode 100644 index 00000000..a2833512 --- /dev/null +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingRecyclerViewAdapter.kt @@ -0,0 +1,200 @@ +package fr.geonature.occtax.ui.input.counting + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.RecyclerView +import fr.geonature.occtax.R +import fr.geonature.occtax.input.CountingMetadata +import java.util.Locale + +/** + * Default RecyclerView Adapter used by [CountingFragment]. + * + * @author [S. Grimault](mailto:sebastien.grimault@gmail.com) + */ +class CountingRecyclerViewAdapter(private val listener: OnCountingRecyclerViewAdapterListener) : RecyclerView.Adapter() { + + private val counting = mutableListOf() + private val onClickListener: View.OnClickListener + + init { + registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { + override fun onChanged() { + super.onChanged() + + listener.showEmptyTextView(itemCount == 0) + } + + override fun onItemRangeChanged(positionStart: Int, + itemCount: Int) { + super.onItemRangeChanged(positionStart, + itemCount) + + listener.showEmptyTextView(itemCount == 0) + } + + override fun onItemRangeInserted(positionStart: Int, + itemCount: Int) { + super.onItemRangeInserted(positionStart, + itemCount) + + listener.showEmptyTextView(false) + } + + override fun onItemRangeRemoved(positionStart: Int, + itemCount: Int) { + super.onItemRangeRemoved(positionStart, + itemCount) + + listener.showEmptyTextView(itemCount == 0) + } + }) + + onClickListener = View.OnClickListener { v -> + val counting = v.tag as CountingMetadata + listener.onClick(counting) + } + } + + override fun onCreateViewHolder(parent: ViewGroup, + viewType: Int): ViewHolder { + return ViewHolder(parent) + } + + override fun getItemCount(): Int { + return counting.size + } + + override fun onBindViewHolder(holder: ViewHolder, + position: Int) { + holder.bind(position) + } + + fun setCounting(counting: List) { + val newList = counting.distinct() + + if (this.counting.isEmpty()) { + this.counting.addAll(newList) + + if (this.counting.isNotEmpty()) { + notifyItemRangeInserted(0, + this.counting.size) + } + + return + } + + if (counting.isEmpty()) { + this.counting.clear() + notifyDataSetChanged() + + return + } + + val diffResult = DiffUtil.calculateDiff(object : DiffUtil.Callback() { + override fun getOldListSize(): Int { + return this@CountingRecyclerViewAdapter.counting.size + } + + override fun getNewListSize(): Int { + return newList.size + } + + override fun areItemsTheSame(oldItemPosition: Int, + newItemPosition: Int): Boolean { + return this@CountingRecyclerViewAdapter.counting.toList()[oldItemPosition].index == newList[newItemPosition].index + } + + override fun areContentsTheSame(oldItemPosition: Int, + newItemPosition: Int): Boolean { + return this@CountingRecyclerViewAdapter.counting.toList()[oldItemPosition] == newList[newItemPosition] + } + }) + + this.counting.clear() + this.counting.addAll(newList) + + diffResult.dispatchUpdatesTo(this) + } + + inner class ViewHolder(parent: ViewGroup) : RecyclerView.ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.list_item_2, + parent, + false)) { + private val text1: TextView = itemView.findViewById(android.R.id.text1) + private val text2: TextView = itemView.findViewById(android.R.id.text2) + + fun bind(position: Int) { + val countingMetadata = counting[position] + + text1.text = itemView.context.getString(R.string.counting_main_label, + countingMetadata.index) + text2.text = buildDescription(countingMetadata) + + with(itemView) { + tag = countingMetadata + setOnClickListener(onClickListener) + setOnLongClickListener { + listener.onLongClicked(counting.indexOf(countingMetadata), + countingMetadata) + true + } + } + } + + private fun buildDescription(countingMetadata: CountingMetadata): String { + return (countingMetadata.properties.values.asSequence() + .filterNot { it.isEmpty() } + .map { + itemView.context.getString(R.string.counting_description_separator, + getNomenclatureTypeLabel(it.code), + it.label) + } + arrayOf(Pair(R.string.counting_min_label, + countingMetadata.min), + Pair(R.string.counting_max_label, + countingMetadata.max)).asSequence() + .map { + itemView.context.getString(R.string.counting_description_separator, + itemView.context.getString(it.first), + it.second.toString()) + }) + .joinToString(", ") + } + + private fun getNomenclatureTypeLabel(mnemonic: String): String { + val resourceId = itemView.resources.getIdentifier("nomenclature_${mnemonic.toLowerCase(Locale.getDefault())}", + "string", + itemView.context.packageName) + + return if (resourceId == 0) mnemonic else itemView.context.getString(resourceId) + } + } + + /** + * Callback used by [CountingRecyclerViewAdapter]. + */ + interface OnCountingRecyclerViewAdapterListener { + + /** + * Called when a [CountingMetadata] has been clicked. + * + * @param countingMetadata the selected CountingMetadata to edit + */ + fun onClick(countingMetadata: CountingMetadata) + + /** + * Called when a [CountingMetadata] has been clicked and held. + * + * @param countingMetadata the selected [CountingMetadata] + */ + fun onLongClicked(position: Int, + countingMetadata: CountingMetadata) + + /** + * Whether to show an empty text view when data changed. + */ + fun showEmptyTextView(show: Boolean) + } +} \ No newline at end of file diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/EditCountingMetadataActivity.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/EditCountingMetadataActivity.kt new file mode 100644 index 00000000..e1f41da4 --- /dev/null +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/EditCountingMetadataActivity.kt @@ -0,0 +1,88 @@ +package fr.geonature.occtax.ui.input.counting + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.view.MenuItem +import androidx.appcompat.app.AppCompatActivity +import fr.geonature.commons.data.Taxonomy +import fr.geonature.occtax.input.CountingMetadata + +/** + * Edit additional counting information Activity. + * + * @see EditCountingMetadataFragment + * + * @author [S. Grimault](mailto:sebastien.grimault@gmail.com) + */ +class EditCountingMetadataActivity : AppCompatActivity(), + EditCountingMetadataFragment.OnEditCountingMetadataFragmentListener { + + private lateinit var countingMetadata: CountingMetadata + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + supportActionBar?.setDisplayHomeAsUpEnabled(true) + + countingMetadata = intent.getParcelableExtra(EXTRA_COUNTING_METADATA) ?: CountingMetadata() + + if (savedInstanceState == null) { + supportFragmentManager.beginTransaction() + .replace(android.R.id.content, + EditCountingMetadataFragment.newInstance(intent.getParcelableExtra(EXTRA_TAXONOMY), + countingMetadata)) + .commit() + } + } + + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + return when (item?.itemId) { + android.R.id.home -> { + sendResult() + finish() + true + } + else -> super.onOptionsItemSelected(item) + } + } + + override fun onBackPressed() { + sendResult() + + super.onBackPressed() + } + + override fun onCountingMetadata(countingMetadata: CountingMetadata) { + this.countingMetadata = countingMetadata + } + + private fun sendResult() { + setResult(Activity.RESULT_OK, + Intent().apply { + putExtra(EXTRA_COUNTING_METADATA, + countingMetadata) + }) + } + + companion object { + + const val EXTRA_TAXONOMY = "extra_taxonomy" + const val EXTRA_COUNTING_METADATA = "extra_counting_metadata" + + fun newIntent(context: Context, + taxonomy: Taxonomy, + countingMetadata: CountingMetadata? = null): Intent { + return Intent(context, + EditCountingMetadataActivity::class.java).apply { + putExtra(EXTRA_TAXONOMY, + taxonomy) + countingMetadata?.let { + putExtra(EXTRA_COUNTING_METADATA, + countingMetadata) + } + } + } + } +} \ No newline at end of file diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/EditCountingMetadataFragment.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/EditCountingMetadataFragment.kt new file mode 100644 index 00000000..78ce9902 --- /dev/null +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/EditCountingMetadataFragment.kt @@ -0,0 +1,192 @@ +package fr.geonature.occtax.ui.input.counting + +import android.content.Context +import android.database.Cursor +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.loader.app.LoaderManager +import androidx.loader.content.CursorLoader +import androidx.loader.content.Loader +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import fr.geonature.commons.data.Nomenclature +import fr.geonature.commons.data.NomenclatureType +import fr.geonature.commons.data.Provider +import fr.geonature.commons.data.Taxonomy +import fr.geonature.commons.util.KeyboardUtils.hideSoftKeyboard +import fr.geonature.occtax.R +import fr.geonature.occtax.input.CountingMetadata +import fr.geonature.occtax.input.Input +import fr.geonature.occtax.input.PropertyValue +import fr.geonature.occtax.ui.input.dialog.ChooseNomenclatureDialogFragment + +/** + * [Fragment] to let the user to edit additional counting information for the given [Input]. + * + * @author [S. Grimault](mailto:sebastien.grimault@gmail.com) + */ +class EditCountingMetadataFragment : Fragment(), + ChooseNomenclatureDialogFragment.OnChooseNomenclatureDialogFragmentListener { + + private var listener: OnEditCountingMetadataFragmentListener? = null + private var adapter: NomenclatureTypesRecyclerViewAdapter? = null + private lateinit var taxonomy: Taxonomy + private lateinit var countingMetadata: CountingMetadata + + private val loaderCallbacks = object : LoaderManager.LoaderCallbacks { + override fun onCreateLoader(id: Int, + args: Bundle?): Loader { + when (id) { + LOADER_NOMENCLATURE_TYPES -> { + return CursorLoader(requireContext(), + Provider.buildUri(NomenclatureType.TABLE_NAME), + null, + null, + null, + null) + } + else -> throw IllegalArgumentException() + } + } + + override fun onLoadFinished(loader: Loader, + data: Cursor?) { + if (data == null) { + Log.w(TAG, + "Failed to load data from '${(loader as CursorLoader).uri}'") + + return + } + + when (loader.id) { + LOADER_NOMENCLATURE_TYPES -> { + adapter?.also { + it.bind(data) + it.setCountingMetata(countingMetadata) + } + } + } + } + + override fun onLoaderReset(loader: Loader) { + when (loader.id) { + LOADER_NOMENCLATURE_TYPES -> adapter?.bind(null) + } + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + arguments?.also { + taxonomy = it.getParcelable(ARG_TAXONOMY) ?: Taxonomy(Taxonomy.ANY, + Taxonomy.ANY) + countingMetadata = it.getParcelable(ARG_COUNTING_METADATA) ?: CountingMetadata() + } + } + + override fun onCreateView(inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?): View? { + val recyclerView = inflater.inflate(R.layout.recycler_view, + container, + false) + // Set the adapter + adapter = NomenclatureTypesRecyclerViewAdapter(object : NomenclatureTypesRecyclerViewAdapter.OnNomenclatureTypesRecyclerViewAdapterListener { + + override fun onAction(nomenclatureTypeMnemonic: String) { + // workaround to force hide the soft keyboard + view?.rootView?.also { + hideSoftKeyboard(it) + } + + val chooseNomenclatureDialogFragment = ChooseNomenclatureDialogFragment.newInstance(nomenclatureTypeMnemonic, + taxonomy) + chooseNomenclatureDialogFragment.show(childFragmentManager, + CHOOSE_NOMENCLATURE_DIALOG_FRAGMENT) + } + + override fun onMinMaxValues(min: Int, + max: Int) { + countingMetadata.apply { + this.min = min + this.max = max + } + + listener?.onCountingMetadata(countingMetadata) + } + }) + + with(recyclerView as RecyclerView) { + layoutManager = LinearLayoutManager(context) + adapter = this@EditCountingMetadataFragment.adapter + } + + return recyclerView + } + + override fun onViewCreated(view: View, + savedInstanceState: Bundle?) { + LoaderManager.getInstance(this) + .initLoader(LOADER_NOMENCLATURE_TYPES, + null, + loaderCallbacks) + } + + override fun onAttach(context: Context) { + super.onAttach(context) + + if (context is OnEditCountingMetadataFragmentListener) { + listener = context + } + else { + throw RuntimeException("$context must implement OnEditCountingMetadataFragmentListener") + } + } + + override fun onSelectedNomenclature(nomenclatureType: String, + nomenclature: Nomenclature) { + countingMetadata.properties[nomenclatureType] = PropertyValue.fromNomenclature(nomenclatureType, + nomenclature) + adapter?.setCountingMetata(countingMetadata) + } + + /** + * Callback used by [EditCountingMetadataFragment]. + */ + interface OnEditCountingMetadataFragmentListener { + fun onCountingMetadata(countingMetadata: CountingMetadata) + } + + companion object { + private val TAG = EditCountingMetadataFragment::class.java.name + + const val ARG_TAXONOMY = "arg_taxonomy" + const val ARG_COUNTING_METADATA = "arg_counting_metadata" + + private const val LOADER_NOMENCLATURE_TYPES = 1 + private const val CHOOSE_NOMENCLATURE_DIALOG_FRAGMENT = "choose_nomenclature_dialog_fragment" + + /** + * Use this factory method to create a new instance of [EditCountingMetadataFragment]. + * + * @return A new instance of [EditCountingMetadataFragment] + */ + @JvmStatic + fun newInstance(taxonomy: Taxonomy, + countingMetadata: CountingMetadata? = null) = EditCountingMetadataFragment().apply { + arguments = Bundle().apply { + putParcelable(ARG_TAXONOMY, + taxonomy) + countingMetadata?.let { + putParcelable(ARG_COUNTING_METADATA, + countingMetadata) + } + } + } + } +} \ No newline at end of file diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/NomenclatureTypesRecyclerViewAdapter.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/NomenclatureTypesRecyclerViewAdapter.kt new file mode 100644 index 00000000..17cd15cc --- /dev/null +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/NomenclatureTypesRecyclerViewAdapter.kt @@ -0,0 +1,423 @@ +package fr.geonature.occtax.ui.input.counting + +import android.database.Cursor +import android.text.Editable +import android.text.TextWatcher +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Button +import android.widget.EditText +import android.widget.FrameLayout +import android.widget.TextView +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.RecyclerView +import fr.geonature.commons.data.NomenclatureType +import fr.geonature.commons.util.KeyboardUtils.hideSoftKeyboard +import fr.geonature.occtax.input.CountingMetadata +import fr.geonature.occtax.input.PropertyValue +import java.util.Locale + +/** + * Default RecyclerView Adapter used by [EditCountingMetadataFragment]. + * + * @author [S. Grimault](mailto:sebastien.grimault@gmail.com) + */ +class NomenclatureTypesRecyclerViewAdapter(private val listener: OnNomenclatureTypesRecyclerViewAdapterListener) : RecyclerView.Adapter() { + + private val mnemonicFilter = arrayOf(Pair("STADE_VIE", + ViewType.NOMENCLATURE_TYPE), + Pair("SEXE", + ViewType.NOMENCLATURE_TYPE), + Pair("OBJ_DENBR", + ViewType.NOMENCLATURE_TYPE), + Pair("TYP_DENBR", + ViewType.NOMENCLATURE_TYPE), + Pair("MIN", + ViewType.MIN_MAX), + Pair("MAX", + ViewType.MIN_MAX)) + + private val availableNomenclatureTypes = mutableListOf>() + private val properties = mutableListOf() + + private val onClickListener: View.OnClickListener + + init { + onClickListener = View.OnClickListener { v -> + val selectedProperty = v.tag as PropertyValue + listener.onAction(selectedProperty.code) + } + } + + override fun onCreateViewHolder(parent: ViewGroup, + viewType: Int): AbstractCardViewHolder { + return when (ViewType.values()[viewType]) { + ViewType.MIN_MAX -> MinMaxViewHolder(parent) + else -> NomenclatureTypeViewHolder(parent) + } + } + + override fun getItemCount(): Int { + return (properties.size - 1).coerceAtLeast(0) + } + + override fun onBindViewHolder(holder: AbstractCardViewHolder, + position: Int) { + holder.bind(properties[position]) + } + + override fun getItemViewType(position: Int): Int { + return mnemonicFilter.first { it.first == properties[position].code } + .second.ordinal + } + + fun bind(cursor: Cursor?) { + availableNomenclatureTypes.clear() + + cursor?.run { + if (this.isClosed) return@run + + this.moveToFirst() + + while (!this.isAfterLast) { + NomenclatureType.fromCursor(this) + ?.run { + val validNomenclatureType = mnemonicFilter.find { it.first == this.mnemonic } + if (validNomenclatureType != null) { + availableNomenclatureTypes.add(validNomenclatureType) + } + } + cursor.moveToNext() + } + + // add default mnemonic filters + availableNomenclatureTypes.addAll(mnemonicFilter.filter { it.second != ViewType.NOMENCLATURE_TYPE }) + } + + availableNomenclatureTypes.sortWith(Comparator { o1, o2 -> + val i1 = mnemonicFilter.indexOfFirst { it.first == o1.first } + val i2 = mnemonicFilter.indexOfFirst { it.first == o2.first } + + when { + i1 == -1 -> 1 + i2 == -1 -> -1 + else -> i1 - i2 + } + }) + + setNomenclatureTypes(availableNomenclatureTypes) + } + + fun setCountingMetata(countingMetadata: CountingMetadata) { + val diffResult = DiffUtil.calculateDiff(object : DiffUtil.Callback() { + override fun getOldListSize(): Int { + return this@NomenclatureTypesRecyclerViewAdapter.properties.size + } + + override fun getNewListSize(): Int { + return this@NomenclatureTypesRecyclerViewAdapter.properties.size + } + + override fun areItemsTheSame(oldItemPosition: Int, + newItemPosition: Int): Boolean { + return true + } + + override fun areContentsTheSame(oldItemPosition: Int, + newItemPosition: Int): Boolean { + val oldProperty = this@NomenclatureTypesRecyclerViewAdapter.properties[oldItemPosition] + val viewType = mnemonicFilter.firstOrNull { it.first == oldProperty.code } + ?.second ?: return false + + return when (viewType) { + ViewType.NOMENCLATURE_TYPE -> countingMetadata.properties[oldProperty.code] == oldProperty + ViewType.MIN_MAX -> { + val minProperty = this@NomenclatureTypesRecyclerViewAdapter.properties.firstOrNull { it.code == "MIN" } + val maxProperty = this@NomenclatureTypesRecyclerViewAdapter.properties.firstOrNull { it.code == "MAX" } + + if (minProperty == null || maxProperty == null) return false + + return minProperty.value as Int == countingMetadata.min && maxProperty.value as Int == countingMetadata.max + } + } + } + }) + + val newProperties = this.properties.map { p -> + when (mnemonicFilter.firstOrNull { it.first == p.code }?.second ?: return@map p) { + ViewType.NOMENCLATURE_TYPE -> countingMetadata.properties[p.code] ?: p + ViewType.MIN_MAX -> when (p.code) { + "MIN" -> PropertyValue.fromValue(p.code, + countingMetadata.min) + "MAX" -> PropertyValue.fromValue(p.code, + countingMetadata.max) + else -> p + } + } + } + this.properties.clear() + this.properties.addAll(newProperties) + + diffResult.dispatchUpdatesTo(this) + } + + private fun setNomenclatureTypes(nomenclatureTypes: List>) { + if (this.properties.isEmpty()) { + this.properties.addAll(nomenclatureTypes.map { + when (it.second) { + ViewType.NOMENCLATURE_TYPE -> PropertyValue.fromNomenclature(it.first, + null) + else -> PropertyValue.fromValue(it.first, + 0) + } + }) + + if (this.properties.isNotEmpty()) { + notifyItemRangeInserted(0, + this.properties.size) + } + + return + } + + if (nomenclatureTypes.isEmpty()) { + this.properties.clear() + notifyDataSetChanged() + + return + } + + val diffResult = DiffUtil.calculateDiff(object : DiffUtil.Callback() { + + override fun getOldListSize(): Int { + return this@NomenclatureTypesRecyclerViewAdapter.properties.size + } + + override fun getNewListSize(): Int { + return nomenclatureTypes.size + } + + override fun areItemsTheSame(oldItemPosition: Int, + newItemPosition: Int): Boolean { + return this@NomenclatureTypesRecyclerViewAdapter.properties[oldItemPosition].code == nomenclatureTypes[newItemPosition].first + } + + override fun areContentsTheSame(oldItemPosition: Int, + newItemPosition: Int): Boolean { + return this@NomenclatureTypesRecyclerViewAdapter.properties[oldItemPosition].code == nomenclatureTypes[newItemPosition].first + } + }) + + this.properties.clear() + this.properties.addAll(nomenclatureTypes.map { + when (it.second) { + ViewType.NOMENCLATURE_TYPE -> PropertyValue.fromNomenclature(it.first, + null) + else -> PropertyValue.fromValue(it.first, + 0) + } + }) + + diffResult.dispatchUpdatesTo(this) + } + + abstract inner class AbstractCardViewHolder(parent: ViewGroup) : RecyclerView.ViewHolder(LayoutInflater.from(parent.context).inflate(fr.geonature.occtax.R.layout.card_view, + parent, + false)) { + internal val contentView: View + private var property: PropertyValue? = null + + init { + contentView = LayoutInflater.from(itemView.context) + .inflate(this.getLayoutResourceId(), + itemView as FrameLayout, + true) + + // workaround to force hide the soft keyboard + contentView.setOnClickListener { + it.clearFocus() + } + } + + fun bind(property: PropertyValue) { + this.property = property + + onBind(property) + } + + @LayoutRes + abstract fun getLayoutResourceId(): Int + + abstract fun onBind(property: PropertyValue) + + fun getNomenclatureTypeLabel(mnemonic: String): String { + val resourceId = contentView.resources.getIdentifier("nomenclature_${mnemonic.toLowerCase(Locale.getDefault())}", + "string", + contentView.context.packageName) + + return if (resourceId == 0) mnemonic else contentView.context.getString(resourceId) + } + } + + inner class NomenclatureTypeViewHolder(parent: ViewGroup) : AbstractCardViewHolder(parent) { + private var title: TextView = contentView.findViewById(android.R.id.title) + private var text1: TextView = contentView.findViewById(android.R.id.text1) + private var button1: Button = contentView.findViewById(android.R.id.button1) + + override fun getLayoutResourceId(): Int { + return fr.geonature.occtax.R.layout.view_action_nomenclature_type + } + + override fun onBind(property: PropertyValue) { + title.text = getNomenclatureTypeLabel(property.code) + text1.text = property.label + + with(button1) { + tag = property + setOnClickListener(onClickListener) + } + } + } + + inner class MinMaxViewHolder(parent: ViewGroup) : AbstractCardViewHolder(parent) { + private var editMin: EditText = contentView.findViewById(fr.geonature.occtax.R.id.editMin) + private var editMax: EditText = contentView.findViewById(fr.geonature.occtax.R.id.editMax) + + private val minTextWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence?, + start: Int, + count: Int, + after: Int) { + } + + override fun onTextChanged(s: CharSequence?, + start: Int, + before: Int, + count: Int) { + } + + override fun afterTextChanged(s: Editable?) { + val minValue = s?.toString()?.toIntOrNull() ?: 0 + val maxValue = editMax.text?.toString()?.toIntOrNull() ?: 0 + + if (minValue > maxValue) setMaxValue(minValue) + + listener.onMinMaxValues(minValue, + if (minValue > maxValue) minValue else maxValue) + } + } + + private val maxTextWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence?, + start: Int, + count: Int, + after: Int) { + } + + override fun onTextChanged(s: CharSequence?, + start: Int, + before: Int, + count: Int) { + } + + override fun afterTextChanged(s: Editable?) { + val minValue = editMin.text?.toString()?.toIntOrNull() ?: 0 + val maxValue = s?.toString()?.toIntOrNull() ?: 0 + + listener.onMinMaxValues(minValue, + if (minValue > maxValue) minValue else maxValue) + } + } + + init { + with(editMin) { + addTextChangedListener(minTextWatcher) + setOnFocusChangeListener { v, hasFocus -> + if (!hasFocus) { + // workaround to force hide the soft keyboard + hideSoftKeyboard(v) + } + } + } + + with(editMax) { + addTextChangedListener(maxTextWatcher) + setOnFocusChangeListener { v, hasFocus -> + if (!hasFocus) { + // workaround to force hide the soft keyboard + hideSoftKeyboard(v) + + val minValue = editMin.text?.toString()?.toIntOrNull() ?: 0 + val maxValue = editMax.text?.toString()?.toIntOrNull() ?: 0 + + if (minValue > maxValue) setMaxValue(minValue) + } + } + } + } + + override fun getLayoutResourceId(): Int { + return fr.geonature.occtax.R.layout.view_action_min_max + } + + override fun onBind(property: PropertyValue) { + val minProperty = properties.firstOrNull { it.code == "MIN" } + val maxProperty = properties.firstOrNull { it.code == "MAX" } + + if (minProperty == null || maxProperty == null) return + + setMinValue(minProperty.value as Int) + setMaxValue(maxProperty.value as Int) + } + + private fun setMinValue(min: Int = 0) { + editMin.also { + it.removeTextChangedListener(minTextWatcher) + it.text = Editable.Factory.getInstance() + .newEditable(min.toString()) + it.addTextChangedListener(minTextWatcher) + } + + if (editMax.text?.toString()?.toIntOrNull() ?: 0 < min) setMaxValue(min) + } + + private fun setMaxValue(max: Int = 0) { + editMax.also { + it.removeTextChangedListener(maxTextWatcher) + it.text = Editable.Factory.getInstance() + .newEditable(max.toString()) + it.addTextChangedListener(maxTextWatcher) + } + } + + } + + enum class ViewType { + NOMENCLATURE_TYPE, + MIN_MAX + } + + /** + * Callback used by [NomenclatureTypesRecyclerViewAdapter]. + */ + interface OnNomenclatureTypesRecyclerViewAdapterListener { + + /** + * Called when the action button has been clicked for a given nomenclature type. + * + * @param nomenclatureTypeMnemonic the selected nomenclature type + */ + fun onAction(nomenclatureTypeMnemonic: String) + + /** + * Called when min/max values have been set. + * + * @param min the min value (default: 0) + * @param max the max value (default: the min value) + */ + fun onMinMaxValues(min: Int = 0, + max: Int = 0) + } +} \ No newline at end of file diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/ChooseNomenclatureDialogFragment.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/dialog/ChooseNomenclatureDialogFragment.kt similarity index 98% rename from occtax/src/main/java/fr/geonature/occtax/ui/input/informations/ChooseNomenclatureDialogFragment.kt rename to occtax/src/main/java/fr/geonature/occtax/ui/input/dialog/ChooseNomenclatureDialogFragment.kt index f55bc3ef..18979cf2 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/ChooseNomenclatureDialogFragment.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/dialog/ChooseNomenclatureDialogFragment.kt @@ -1,4 +1,4 @@ -package fr.geonature.occtax.ui.input.informations +package fr.geonature.occtax.ui.input.dialog import android.app.Dialog import android.database.Cursor @@ -98,7 +98,8 @@ class ChooseNomenclatureDialogFragment : DialogFragment() { // Set the adapter adapter = NomenclatureRecyclerViewAdapter(object : NomenclatureRecyclerViewAdapter.OnNomenclatureRecyclerViewAdapterListener { override fun onSelectedNomenclature(nomenclature: Nomenclature) { - val nomenclatureType = arguments?.getString(ARG_NOMENCLATURE_TYPE) ?: return + val nomenclatureType = arguments?.getString(ARG_NOMENCLATURE_TYPE) + ?: return listener?.onSelectedNomenclature(nomenclatureType, nomenclature) dismiss() diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/NomenclatureRecyclerViewAdapter.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/dialog/NomenclatureRecyclerViewAdapter.kt similarity index 98% rename from occtax/src/main/java/fr/geonature/occtax/ui/input/informations/NomenclatureRecyclerViewAdapter.kt rename to occtax/src/main/java/fr/geonature/occtax/ui/input/dialog/NomenclatureRecyclerViewAdapter.kt index bbbb0874..64bcd96c 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/NomenclatureRecyclerViewAdapter.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/dialog/NomenclatureRecyclerViewAdapter.kt @@ -1,4 +1,4 @@ -package fr.geonature.occtax.ui.input.informations +package fr.geonature.occtax.ui.input.dialog import android.database.Cursor import android.view.LayoutInflater diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/InformationFragment.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/InformationFragment.kt index 015550d2..76bcfd4f 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/InformationFragment.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/InformationFragment.kt @@ -22,6 +22,7 @@ import fr.geonature.occtax.input.Input import fr.geonature.occtax.input.InputTaxon import fr.geonature.occtax.input.SelectedProperty import fr.geonature.occtax.ui.input.IInputFragment +import fr.geonature.occtax.ui.input.dialog.ChooseNomenclatureDialogFragment import fr.geonature.viewpager.ui.IValidateFragment /** diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/NomenclatureTypesRecyclerViewAdapter.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/NomenclatureTypesRecyclerViewAdapter.kt index f143387f..bf7084f2 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/NomenclatureTypesRecyclerViewAdapter.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/informations/NomenclatureTypesRecyclerViewAdapter.kt @@ -192,7 +192,8 @@ class NomenclatureTypesRecyclerViewAdapter(private val listener: OnNomenclatureT } if (nomenclatureTypes.isEmpty()) { - clear() + this.properties.clear() + notifyDataSetChanged() return } @@ -231,11 +232,6 @@ class NomenclatureTypesRecyclerViewAdapter(private val listener: OnNomenclatureT diffResult.dispatchUpdatesTo(this) } - private fun clear() { - this.properties.clear() - notifyDataSetChanged() - } - abstract inner class AbstractCardViewHolder(parent: ViewGroup) : RecyclerView.ViewHolder(LayoutInflater.from(parent.context).inflate(fr.geonature.occtax.R.layout.card_view, parent, false)) { diff --git a/occtax/src/main/res/layout/card_view.xml b/occtax/src/main/res/layout/card_view.xml index cf4be595..2e8a9c94 100644 --- a/occtax/src/main/res/layout/card_view.xml +++ b/occtax/src/main/res/layout/card_view.xml @@ -4,9 +4,11 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginEnd="@dimen/padding_default" android:layout_marginStart="@dimen/padding_default" android:layout_marginTop="@dimen/padding_default" + android:layout_marginEnd="@dimen/padding_default" + android:focusable="true" + android:focusableInTouchMode="true" app:cardCornerRadius="@dimen/cardview_radius" app:cardElevation="@dimen/cardview_elevation" app:contentPadding="@dimen/padding_default"> diff --git a/occtax/src/main/res/layout/fragment_counting.xml b/occtax/src/main/res/layout/fragment_counting.xml new file mode 100644 index 00000000..4094ae13 --- /dev/null +++ b/occtax/src/main/res/layout/fragment_counting.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/occtax/src/main/res/layout/list_item_2.xml b/occtax/src/main/res/layout/list_item_2.xml index 62a02165..8ea063c3 100644 --- a/occtax/src/main/res/layout/list_item_2.xml +++ b/occtax/src/main/res/layout/list_item_2.xml @@ -7,13 +7,15 @@ android:layout_height="wrap_content" android:background="?attr/selectableItemBackground" android:minHeight="?attr/listPreferredItemHeight" - android:paddingEnd="?attr/listPreferredItemPaddingEnd" - android:paddingStart="?attr/listPreferredItemPaddingStart"> + android:paddingStart="?attr/listPreferredItemPaddingStart" + android:paddingEnd="?attr/listPreferredItemPaddingEnd"> \ No newline at end of file + android:layout_height="match_parent" + android:clipToPadding="false" + android:paddingBottom="@dimen/padding_default" /> \ No newline at end of file diff --git a/occtax/src/main/res/layout/view_action_edit_text.xml b/occtax/src/main/res/layout/view_action_edit_text.xml index ad6da4a3..f246b821 100644 --- a/occtax/src/main/res/layout/view_action_edit_text.xml +++ b/occtax/src/main/res/layout/view_action_edit_text.xml @@ -22,6 +22,7 @@ android:imeOptions="actionDone" android:importantForAutofill="no" android:inputType="textNoSuggestions" + android:labelFor="@android:id/title" app:layout_constraintTop_toBottomOf="@android:id/title" /> \ No newline at end of file diff --git a/occtax/src/main/res/layout/view_action_min_max.xml b/occtax/src/main/res/layout/view_action_min_max.xml new file mode 100644 index 00000000..ab5f64d2 --- /dev/null +++ b/occtax/src/main/res/layout/view_action_min_max.xml @@ -0,0 +1,43 @@ + + + + + + + + + + \ No newline at end of file diff --git a/occtax/src/main/res/values-fr/nomenclatures.xml b/occtax/src/main/res/values-fr/nomenclatures.xml index 4619daa7..3a54f4b2 100644 --- a/occtax/src/main/res/values-fr/nomenclatures.xml +++ b/occtax/src/main/res/values-fr/nomenclatures.xml @@ -10,5 +10,9 @@ Niveau de naturalité Preuve d\'existence Commentaire + Stade de vie + Sexe + Objet du dénombrement + Type de dénombrement \ No newline at end of file diff --git a/occtax/src/main/res/values-fr/strings.xml b/occtax/src/main/res/values-fr/strings.xml index f535c5f9..ca758ae0 100644 --- a/occtax/src/main/res/values-fr/strings.xml +++ b/occtax/src/main/res/values-fr/strings.xml @@ -43,6 +43,7 @@ Pointage Taxons Informations + Dénombrements Observateurs @@ -56,4 +57,14 @@ Déterminateur Ajouter un commentaire optionnel + Aucun dénombrement effectué.\nCréer un nouveau dénombrement via le bouton + + Dénombrement #%d + %1$s : %2$s + Dénombrement supprimé + Annuler + Aucune information à sauvegarder + Min & Max + Min + Max + \ No newline at end of file diff --git a/occtax/src/main/res/values/nomenclatures.xml b/occtax/src/main/res/values/nomenclatures.xml index c05ba2bd..4bc84de5 100644 --- a/occtax/src/main/res/values/nomenclatures.xml +++ b/occtax/src/main/res/values/nomenclatures.xml @@ -10,5 +10,9 @@ Level of naturalness Proof of existence Comment + Life stage + Sex + Purpose of the enumeration + Type of enumeration \ No newline at end of file diff --git a/occtax/src/main/res/values/strings.xml b/occtax/src/main/res/values/strings.xml index 9546d012..ce6b61e8 100644 --- a/occtax/src/main/res/values/strings.xml +++ b/occtax/src/main/res/values/strings.xml @@ -47,6 +47,7 @@ Pointing Taxa Information + Counting Selected observers @@ -60,4 +61,14 @@ Add determiner Add comment + No counting.\nCreate a new one by tapping the + button. + Counting #%d + %1$s: %2$s + Counting deleted + Undo + Empty counting: Nothing to save + Min & Max + Min + Max + diff --git a/occtax/src/test/java/fr/geonature/occtax/input/CountingMetadataTest.kt b/occtax/src/test/java/fr/geonature/occtax/input/CountingMetadataTest.kt new file mode 100644 index 00000000..de89765d --- /dev/null +++ b/occtax/src/test/java/fr/geonature/occtax/input/CountingMetadataTest.kt @@ -0,0 +1,80 @@ +package fr.geonature.occtax.input + +import android.os.Parcel +import fr.geonature.commons.data.Nomenclature +import fr.geonature.occtax.input.PropertyValue.Companion.fromNomenclature +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +/** + * Unit tests about [CountingMetadata]. + * + * @author [S. Grimault](mailto:sebastien.grimault@gmail.com) + */ +@RunWith(RobolectricTestRunner::class) +class CountingMetadataTest { + + @Test + fun testIsEmpty() { + assertFalse(CountingMetadata().apply { + properties.putAll(mutableMapOf(Pair("SEXE", + fromNomenclature("SEXE", + Nomenclature(168L, + "Femelle", + "009.002", + "Femelle", + 9L))))) + min = 1 + max = 2 + }.isEmpty()) + + assertFalse(CountingMetadata().apply { + properties.putAll(mutableMapOf(Pair("SEXE", + fromNomenclature("SEXE", + Nomenclature(168L, + "Femelle", + "009.002", + "Femelle", + 9L))))) + }.isEmpty()) + + assertTrue(CountingMetadata().isEmpty()) + assertTrue(CountingMetadata().apply { + properties["MIN"] = PropertyValue("MIN", + null, + null) + }.isEmpty()) + } + + @Test + fun testParcelable() { + // given counting metadata + val countingMetadata = CountingMetadata().apply { + properties.putAll(mutableMapOf(Pair("SEXE", + fromNomenclature("SEXE", + Nomenclature(168L, + "Femelle", + "009.002", + "Femelle", + 9L))))) + min = 1 + max = 2 + } + + // when we obtain a Parcel object to write the selected counting metadata instance to it + val parcel = Parcel.obtain() + countingMetadata.writeToParcel(parcel, + 0) + + // reset the parcel for reading + parcel.setDataPosition(0) + + // then + assertEquals(countingMetadata, + CountingMetadata.CREATOR.createFromParcel(parcel)) + } +} \ No newline at end of file diff --git a/occtax/src/test/java/fr/geonature/occtax/input/InputTaxonTest.kt b/occtax/src/test/java/fr/geonature/occtax/input/InputTaxonTest.kt new file mode 100644 index 00000000..bf4ad0ca --- /dev/null +++ b/occtax/src/test/java/fr/geonature/occtax/input/InputTaxonTest.kt @@ -0,0 +1,117 @@ +package fr.geonature.occtax.input + +import android.os.Parcel +import fr.geonature.commons.data.Nomenclature +import fr.geonature.commons.data.Taxon +import fr.geonature.commons.data.Taxonomy +import org.junit.Assert.assertArrayEquals +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertNull +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +/** + * Unit tests about [InputTaxon]. + * + * @author [S. Grimault](mailto:sebastien.grimault@gmail.com) + */ +@RunWith(RobolectricTestRunner::class) +class InputTaxonTest { + + @Test + fun testAddCountingMetadata() { + // given an input taxon + val inputTaxon = InputTaxon(Taxon(1234L, + "taxon_01", + Taxonomy("Animalia", + "Ascidies"), + null)) + + // when adding an empty counting metadata + inputTaxon.addCountingMetadata(CountingMetadata()) + + // then + assertTrue(inputTaxon.getCounting().isEmpty()) + + // when adding valid counting metadata + inputTaxon.addCountingMetadata(CountingMetadata().apply { min = 1 }) + inputTaxon.addCountingMetadata(CountingMetadata().apply { + min = 2 + max = 3 + }) + assertArrayEquals(arrayOf(CountingMetadata().apply { + index = 1 + min = 1 + }, + CountingMetadata().apply { + index = 2 + min = 2 + max = 3 + }), + inputTaxon.getCounting().toTypedArray()) + + } + + @Test + fun testDeleteCountingMetadata() { + // given an input taxon with counting metadata + val inputTaxon = InputTaxon(Taxon(1234L, + "taxon_01", + Taxonomy("Animalia", + "Ascidies"), + null)).apply { + addCountingMetadata(CountingMetadata().apply { min = 1 }) + } + + // when deleting counting metadata + assertNotNull(inputTaxon.deleteCountingMetadata(1)) + + // when deleting non existing counting metadata + assertNull(inputTaxon.deleteCountingMetadata(1)) + } + + @Test + fun testParcelable() { + // given an input taxon + val inputTaxon = InputTaxon(Taxon(1234L, + "taxon_01", + Taxonomy("Animalia", + "Ascidies"), + null)).apply { + properties["ETA_BIO"] = SelectedProperty.fromNomenclature("ETA_BIO", + Nomenclature(1234L, + "2", + "1234:001", + "label", + 123L)) + addCountingMetadata(CountingMetadata().apply { + properties.putAll(mutableMapOf(Pair("SEXE", + PropertyValue.fromNomenclature("SEXE", + Nomenclature(168L, + "Femelle", + "009.002", + "Femelle", + 9L))))) + min = 1 + max = 2 + }) + } + + // when we obtain a Parcel object to write the input taxon instance to it + val parcel = Parcel.obtain() + inputTaxon.writeToParcel(parcel, + 0) + + // reset the parcel for reading + parcel.setDataPosition(0) + + // then + val inputTaxonFromParcel = InputTaxon.CREATOR.createFromParcel(parcel) + assertEquals(inputTaxon, + inputTaxonFromParcel) + + } +} \ No newline at end of file diff --git a/occtax/src/test/java/fr/geonature/occtax/input/PropertyValueTest.kt b/occtax/src/test/java/fr/geonature/occtax/input/PropertyValueTest.kt new file mode 100644 index 00000000..45a540c8 --- /dev/null +++ b/occtax/src/test/java/fr/geonature/occtax/input/PropertyValueTest.kt @@ -0,0 +1,130 @@ +package fr.geonature.occtax.input + +import android.os.Parcel +import fr.geonature.commons.data.Nomenclature +import fr.geonature.occtax.input.PropertyValue.Companion.fromNomenclature +import fr.geonature.occtax.input.PropertyValue.Companion.fromValue +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +/** + * Unit tests about [PropertyValue]. + * + * @author [S. Grimault](mailto:sebastien.grimault@gmail.com) + */ +@RunWith(RobolectricTestRunner::class) +class PropertyValueTest { + + @Test + fun testCreateFromNomenclature() { + assertEquals(PropertyValue( + "ETA_BIO", + "label", + 1234L), + fromNomenclature("ETA_BIO", + Nomenclature(1234L, + "2", + "1234:001", + "label", + 123L))) + } + + @Test + fun testCreateFromValue() { + assertEquals(PropertyValue( + "DETERMINER", + null, + "some_value"), + fromValue("DETERMINER", + "some_value")) + assertEquals(PropertyValue( + "MIN", + null, + 2), + fromValue("MIN", + 2)) + } + + @Test + fun testIsEmpty() { + assertFalse(fromNomenclature("ETA_BIO", + Nomenclature(1234L, + "2", + "1234:001", + "label", + 123L)).isEmpty()) + assertFalse(fromValue("DETERMINER", + "some_value").isEmpty()) + assertFalse(fromValue("MIN", + 2).isEmpty()) + assertTrue(PropertyValue( + "ETA_BIO", + null, + null).isEmpty()) + } + + @Test + fun testParcelableFromNomenclature() { + // given a property value instance + val propertyValue = fromNomenclature("ETA_BIO", + Nomenclature(1234L, + "2", + "1234:001", + "label", + 123L)) + + // when we obtain a Parcel object to write the property value instance to it + val parcel = Parcel.obtain() + propertyValue.writeToParcel(parcel, + 0) + + // reset the parcel for reading + parcel.setDataPosition(0) + + // then + assertEquals(propertyValue, + PropertyValue.CREATOR.createFromParcel(parcel)) + } + + @Test + fun testParcelableFromStringValue() { + // given a property value instance + val propertyValue = fromValue("DETERMINER", + "some_value") + + // when we obtain a Parcel object to write the property value instance to it + val parcel = Parcel.obtain() + propertyValue.writeToParcel(parcel, + 0) + + // reset the parcel for reading + parcel.setDataPosition(0) + + // then + assertEquals(propertyValue, + PropertyValue.CREATOR.createFromParcel(parcel)) + } + + @Test + fun testParcelableFromIntValue() { + // given a property value instance + val propertyValue = fromValue("MIN", + 2) + + // when we obtain a Parcel object to write the property value instance to it + val parcel = Parcel.obtain() + propertyValue.writeToParcel(parcel, + 0) + + // reset the parcel for reading + parcel.setDataPosition(0) + + // then + assertEquals(propertyValue, + PropertyValue.CREATOR.createFromParcel(parcel)) + } +} \ No newline at end of file diff --git a/occtax/src/test/java/fr/geonature/occtax/input/io/InputJsonReaderTest.kt b/occtax/src/test/java/fr/geonature/occtax/input/io/InputJsonReaderTest.kt index 66dbf1ab..bd938791 100644 --- a/occtax/src/test/java/fr/geonature/occtax/input/io/InputJsonReaderTest.kt +++ b/occtax/src/test/java/fr/geonature/occtax/input/io/InputJsonReaderTest.kt @@ -6,8 +6,10 @@ import fr.geonature.commons.input.AbstractInputTaxon import fr.geonature.commons.input.io.InputJsonReader import fr.geonature.commons.util.IsoDateUtils.toDate import fr.geonature.occtax.FixtureHelper.getFixture +import fr.geonature.occtax.input.CountingMetadata import fr.geonature.occtax.input.Input import fr.geonature.occtax.input.InputTaxon +import fr.geonature.occtax.input.PropertyValue import fr.geonature.occtax.input.SelectedProperty import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals @@ -89,38 +91,58 @@ class InputJsonReaderTest { "taxon_01", Taxonomy("Animalia", "Ascidies"))).apply { - this.properties["METH_OBS"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, - "METH_OBS", - 41, + properties["METH_OBS"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, + "METH_OBS", + 41, + null) + properties["ETA_BIO"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, + "ETA_BIO", + 29, + null) + properties["METH_DETERMIN"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, + "METH_DETERMIN", + 445, null) - this.properties["ETA_BIO"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, - "ETA_BIO", - 29, + properties["DETERMINER"] = SelectedProperty(SelectedProperty.PropertyType.TEXT, + "DETERMINER", + null, + "Determiner value") + properties["STATUT_BIO"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, + "STATUT_BIO", + 29, + null) + properties["NATURALITE"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, + "NATURALITE", + 160, + null) + properties["PREUVE_EXIST"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, + "PREUVE_EXIST", + 81, null) - this.properties["METH_DETERMIN"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, - "METH_DETERMIN", - 445, - null) - this.properties["DETERMINER"] = SelectedProperty(SelectedProperty.PropertyType.TEXT, - "DETERMINER", - null, - "Determiner value") - this.properties["STATUT_BIO"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, - "STATUT_BIO", - 29, - null) - this.properties["NATURALITE"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, - "NATURALITE", - 160, - null) - this.properties["PREUVE_EXIST"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, - "PREUVE_EXIST", - 81, - null) - this.properties["COMMENT"] = SelectedProperty(SelectedProperty.PropertyType.TEXT, - "COMMENT", - null, - "Some comment") + properties["COMMENT"] = SelectedProperty(SelectedProperty.PropertyType.TEXT, + "COMMENT", + null, + "Some comment") + addCountingMetadata(CountingMetadata().apply { + properties.putAll(mutableMapOf(Pair("STADE_VIE", + PropertyValue("STADE_VIE", + null, + 2L)), + Pair("SEXE", + PropertyValue("SEXE", + null, + 168L)), + Pair("OBJ_DENBR", + PropertyValue("OBJ_DENBR", + null, + 146L)), + Pair("TYP_DENBR", + PropertyValue("TYP_DENBR", + null, + 93L)))) + min = 1 + max = 2 + }) }), input.getInputTaxa()) } diff --git a/occtax/src/test/java/fr/geonature/occtax/input/io/InputJsonWriterTest.kt b/occtax/src/test/java/fr/geonature/occtax/input/io/InputJsonWriterTest.kt index 5b6b0cfb..e21141b8 100644 --- a/occtax/src/test/java/fr/geonature/occtax/input/io/InputJsonWriterTest.kt +++ b/occtax/src/test/java/fr/geonature/occtax/input/io/InputJsonWriterTest.kt @@ -5,8 +5,10 @@ import fr.geonature.commons.data.Taxonomy import fr.geonature.commons.input.io.InputJsonWriter import fr.geonature.commons.util.IsoDateUtils.toDate import fr.geonature.occtax.FixtureHelper.getFixture +import fr.geonature.occtax.input.CountingMetadata import fr.geonature.occtax.input.Input import fr.geonature.occtax.input.InputTaxon +import fr.geonature.occtax.input.PropertyValue import fr.geonature.occtax.input.SelectedProperty import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull @@ -45,38 +47,58 @@ class InputJsonWriterTest { "taxon_01", Taxonomy("Animalia", "Ascidies"))).apply { - this.properties["METH_OBS"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, - "METH_OBS", - 41, + properties["METH_OBS"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, + "METH_OBS", + 41, + null) + properties["ETA_BIO"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, + "ETA_BIO", + 29, + null) + properties["METH_DETERMIN"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, + "METH_DETERMIN", + 445, null) - this.properties["ETA_BIO"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, - "ETA_BIO", - 29, + properties["DETERMINER"] = SelectedProperty(SelectedProperty.PropertyType.TEXT, + "DETERMINER", + null, + "Determiner value") + properties["STATUT_BIO"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, + "STATUT_BIO", + 29, + null) + properties["NATURALITE"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, + "NATURALITE", + 160, + null) + properties["PREUVE_EXIST"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, + "PREUVE_EXIST", + 81, null) - this.properties["METH_DETERMIN"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, - "METH_DETERMIN", - 445, - null) - this.properties["DETERMINER"] = SelectedProperty(SelectedProperty.PropertyType.TEXT, - "DETERMINER", - null, - "Determiner value") - this.properties["STATUT_BIO"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, - "STATUT_BIO", - 29, - null) - this.properties["NATURALITE"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, - "NATURALITE", - 160, - null) - this.properties["PREUVE_EXIST"] = SelectedProperty(SelectedProperty.PropertyType.NOMENCLATURE, - "PREUVE_EXIST", - 81, - null) - this.properties["COMMENT"] = SelectedProperty(SelectedProperty.PropertyType.TEXT, - "COMMENT", - null, - "Some comment") + properties["COMMENT"] = SelectedProperty(SelectedProperty.PropertyType.TEXT, + "COMMENT", + null, + "Some comment") + addCountingMetadata(CountingMetadata().apply { + properties.putAll(mutableMapOf(Pair("STADE_VIE", + PropertyValue("STADE_VIE", + null, + 2L)), + Pair("SEXE", + PropertyValue("SEXE", + null, + 168L)), + Pair("OBJ_DENBR", + PropertyValue("OBJ_DENBR", + null, + 146L)), + Pair("TYP_DENBR", + PropertyValue("TYP_DENBR", + null, + 93L)))) + min = 1 + max = 2 + }) }) } diff --git a/occtax/src/test/resources/fixtures/input_simple.json b/occtax/src/test/resources/fixtures/input_simple.json index ab931c8e..cea63d00 100644 --- a/occtax/src/test/resources/fixtures/input_simple.json +++ b/occtax/src/test/resources/fixtures/input_simple.json @@ -50,7 +50,26 @@ "comment": { "type": "text", "label": "Some comment" - } + }, + "counting": [ + { + "index": 1, + "stade_vie": { + "value": 2 + }, + "sexe": { + "value": 168 + }, + "obj_denbr": { + "value": 146 + }, + "typ_denbr": { + "value": 93 + }, + "min": 1, + "max": 2 + } + ] }, "id_nomenclature_obs_meth": 41, "id_nomenclature_bio_condition": 29, @@ -59,7 +78,17 @@ "id_nomenclature_bio_status": 29, "id_nomenclature_naturalness": 160, "id_nomenclature_exist_proof": 81, - "comment": "Some comment" + "comment": "Some comment", + "cor_counting_occtax": [ + { + "id_nomenclature_life_stage": 2, + "id_nomenclature_sex": 168, + "id_nomenclature_obj_count": 146, + "id_nomenclature_type_count": 93, + "count_min": 1, + "count_max": 2 + } + ] } ] } From 2518889e1295e1bf33d024182239d07494f4a193 Mon Sep 17 00:00:00 2001 From: "S. Grimault" Date: Sun, 27 Oct 2019 11:36:06 +0100 Subject: [PATCH 10/16] chore: upgrade libraries dependencies --- occtax/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/occtax/build.gradle b/occtax/build.gradle index 828e180a..3b6ecbea 100644 --- a/occtax/build.gradle +++ b/occtax/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' -version = "0.1.7" +version = "0.1.8" android { compileSdkVersion 28 @@ -55,10 +55,10 @@ dependencies { implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0' implementation 'androidx.core:core-ktx:1.2.0-beta01' - implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0-beta01" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0-rc01" implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'com.google.android.material:material:1.0.0' - implementation 'androidx.recyclerview:recyclerview:1.1.0-beta05' + implementation 'androidx.recyclerview:recyclerview:1.1.0-rc01' implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.preference:preference:1.1.0' implementation 'com.l4digital.fastscroll:fastscroll:2.0.1' From ce8a3c49579339147a5ff20a1c34dded9b03029b Mon Sep 17 00:00:00 2001 From: "S. Grimault" Date: Sun, 27 Oct 2019 11:36:38 +0100 Subject: [PATCH 11/16] chore: update core and maps modules dependencies --- gn_mobile_core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gn_mobile_core b/gn_mobile_core index 63c7aa4f..3c4260f5 160000 --- a/gn_mobile_core +++ b/gn_mobile_core @@ -1 +1 @@ -Subproject commit 63c7aa4fba78dfeabbbc2aaf9f2cd668e418f92b +Subproject commit 3c4260f5d457e9f532b726ad50af607b0cd596ef From 199005180017e4559b4a5f2ac4ab6b18081c8667 Mon Sep 17 00:00:00 2001 From: "S. Grimault" Date: Sun, 27 Oct 2019 11:45:52 +0100 Subject: [PATCH 12/16] fix: hide empty text view by default --- occtax/src/main/res/layout/fragment_home.xml | 10 +++++----- occtax/src/main/res/layout/view_action_list_item.xml | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/occtax/src/main/res/layout/fragment_home.xml b/occtax/src/main/res/layout/fragment_home.xml index 5ba0b166..ab814f60 100644 --- a/occtax/src/main/res/layout/fragment_home.xml +++ b/occtax/src/main/res/layout/fragment_home.xml @@ -37,8 +37,8 @@ android:id="@+id/textViewLastInputs" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/padding_default" android:layout_marginTop="@dimen/padding_default" + android:layout_marginBottom="@dimen/padding_default" android:text="@string/home_last_inputs" android:textAppearance="@style/TextAppearance.AppCompat.Medium" android:textStyle="bold" @@ -53,8 +53,7 @@ - + android:layout_height="match_parent" /> + android:textAlignment="center" + android:visibility="gone" /> @@ -73,8 +73,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" - android:layout_marginBottom="@dimen/padding_default" android:layout_marginEnd="@dimen/padding_default" + android:layout_marginBottom="@dimen/padding_default" android:clickable="true" android:focusable="true" android:tint="@android:color/white" diff --git a/occtax/src/main/res/layout/view_action_list_item.xml b/occtax/src/main/res/layout/view_action_list_item.xml index bedd3f55..630eca7f 100644 --- a/occtax/src/main/res/layout/view_action_list_item.xml +++ b/occtax/src/main/res/layout/view_action_list_item.xml @@ -37,7 +37,8 @@ android:layout_gravity="center" android:layout_margin="@dimen/text_margin" android:text="@string/no_data" - android:textAlignment="center" /> + android:textAlignment="center" + android:visibility="gone" /> From acf6dce342f04bbcbfcb39979ace5a63418a7093 Mon Sep 17 00:00:00 2001 From: "S. Grimault" Date: Tue, 29 Oct 2019 23:06:27 +0100 Subject: [PATCH 13/16] chore: update core and maps modules dependencies --- gn_mobile_core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gn_mobile_core b/gn_mobile_core index 3c4260f5..35e941bb 160000 --- a/gn_mobile_core +++ b/gn_mobile_core @@ -1 +1 @@ -Subproject commit 3c4260f5d457e9f532b726ad50af607b0cd596ef +Subproject commit 35e941bbc4375ad0811d55ea61d5100c97e282ae From a841055a4b1c1c3f7c7770e7bffc5ea423357a7f Mon Sep 17 00:00:00 2001 From: "S. Grimault" Date: Tue, 29 Oct 2019 23:08:19 +0100 Subject: [PATCH 14/16] feat: last step with a summary of all edited taxa. --- .../ui/input/InputPagerFragmentActivity.kt | 3 + .../ui/input/counting/CountingFragment.kt | 71 +++--- .../counting/CountingRecyclerViewAdapter.kt | 166 ++---------- .../input/summary/InputTaxaSummaryFragment.kt | 179 +++++++++++++ .../InputTaxaSummaryRecyclerViewAdapter.kt | 47 ++++ .../adapter/ListItemRecyclerViewAdapter.kt | 241 ++++++++++++++++++ ...ing.xml => fragment_recycler_view_fab.xml} | 17 +- occtax/src/main/res/values-fr/strings.xml | 7 +- occtax/src/main/res/values/strings.xml | 7 +- 9 files changed, 548 insertions(+), 190 deletions(-) create mode 100644 occtax/src/main/java/fr/geonature/occtax/ui/input/summary/InputTaxaSummaryFragment.kt create mode 100644 occtax/src/main/java/fr/geonature/occtax/ui/input/summary/InputTaxaSummaryRecyclerViewAdapter.kt create mode 100644 occtax/src/main/java/fr/geonature/occtax/ui/shared/adapter/ListItemRecyclerViewAdapter.kt rename occtax/src/main/res/layout/{fragment_counting.xml => fragment_recycler_view_fab.xml} (73%) diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/InputPagerFragmentActivity.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/InputPagerFragmentActivity.kt index a1e7dc8b..0bc7144b 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/InputPagerFragmentActivity.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/InputPagerFragmentActivity.kt @@ -15,6 +15,7 @@ import fr.geonature.occtax.ui.input.counting.CountingFragment import fr.geonature.occtax.ui.input.informations.InformationFragment import fr.geonature.occtax.ui.input.map.InputMapFragment import fr.geonature.occtax.ui.input.observers.ObserversAndDateInputFragment +import fr.geonature.occtax.ui.input.summary.InputTaxaSummaryFragment import fr.geonature.occtax.ui.input.taxa.TaxaFragment import fr.geonature.occtax.util.SettingsUtils.getMapShowCompass import fr.geonature.occtax.util.SettingsUtils.getMapShowScale @@ -76,6 +77,8 @@ class InputPagerFragmentActivity : AbstractNavigationHistoryPagerFragmentActivit InformationFragment.newInstance()) put(R.string.pager_fragment_counting_title, CountingFragment.newInstance()) + put(R.string.pager_fragment_summary_title, + InputTaxaSummaryFragment.newInstance()) } override fun performFinishAction() { diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingFragment.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingFragment.kt index e4fba101..5f9c3514 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingFragment.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingFragment.kt @@ -20,11 +20,12 @@ import fr.geonature.occtax.input.CountingMetadata import fr.geonature.occtax.input.Input import fr.geonature.occtax.input.InputTaxon import fr.geonature.occtax.ui.input.IInputFragment +import fr.geonature.occtax.ui.shared.adapter.ListItemRecyclerViewAdapter import fr.geonature.viewpager.ui.IValidateFragment -import kotlinx.android.synthetic.main.fragment_counting.countingContent -import kotlinx.android.synthetic.main.fragment_counting.countingEmptyTextView -import kotlinx.android.synthetic.main.fragment_counting.countingRecyclerView -import kotlinx.android.synthetic.main.fragment_counting.fab +import kotlinx.android.synthetic.main.fragment_recycler_view_fab.content +import kotlinx.android.synthetic.main.fragment_recycler_view_fab.empty +import kotlinx.android.synthetic.main.fragment_recycler_view_fab.fab +import kotlinx.android.synthetic.main.fragment_recycler_view_fab.list /** * [Fragment] to let the user to add additional counting information for the given [Input]. @@ -41,7 +42,7 @@ class CountingFragment : Fragment(), override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.fragment_counting, + return inflater.inflate(R.layout.fragment_recycler_view_fab, container, false) } @@ -52,6 +53,8 @@ class CountingFragment : Fragment(), super.onViewCreated(view, savedInstanceState) + empty.text = getString(R.string.counting_no_data) + fab.setOnClickListener { val context = context ?: return@setOnClickListener @@ -62,54 +65,54 @@ class CountingFragment : Fragment(), 0) } - adapter = CountingRecyclerViewAdapter(object : CountingRecyclerViewAdapter.OnCountingRecyclerViewAdapterListener { - override fun onClick(countingMetadata: CountingMetadata) { + adapter = CountingRecyclerViewAdapter(object : ListItemRecyclerViewAdapter.OnListItemRecyclerViewAdapterListener { + override fun onClick(item: CountingMetadata) { val context = context ?: return startActivityForResult(EditCountingMetadataActivity.newIntent(context, input?.getCurrentSelectedInputTaxon()?.taxon?.taxonomy ?: Taxonomy(Taxonomy.ANY, Taxonomy.ANY), - countingMetadata), + item), 0) } override fun onLongClicked(position: Int, - countingMetadata: CountingMetadata) { - if ((input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.deleteCountingMetadata(countingMetadata.index) != null) { - refreshView() - - Snackbar.make(countingContent, - R.string.counting_snackbar_counting_deleted, - Snackbar.LENGTH_LONG) - .setAction(R.string.counting_snackbar_counting_undo - ) { - (input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.addCountingMetadata(countingMetadata) - refreshView() - } - .show() - } + item: CountingMetadata) { + adapter?.remove(item) + (input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.deleteCountingMetadata(item.index) + + Snackbar.make(content, + R.string.counting_snackbar_counting_deleted, + Snackbar.LENGTH_LONG) + .setAction(R.string.counting_snackbar_counting_undo + ) { + adapter?.add(item, + position) + (input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.addCountingMetadata(item) + } + .show() } override fun showEmptyTextView(show: Boolean) { - if (countingEmptyTextView.visibility == View.VISIBLE == show) { + if (empty.visibility == View.VISIBLE == show) { return } if (show) { - countingEmptyTextView.startAnimation(AnimationUtils.loadAnimation(context, - android.R.anim.fade_in)) - countingEmptyTextView.visibility = View.VISIBLE + empty.startAnimation(AnimationUtils.loadAnimation(context, + android.R.anim.fade_in)) + empty.visibility = View.VISIBLE } else { - countingEmptyTextView.startAnimation(AnimationUtils.loadAnimation(context, - android.R.anim.fade_out)) - countingEmptyTextView.visibility = View.GONE + empty.startAnimation(AnimationUtils.loadAnimation(context, + android.R.anim.fade_out)) + empty.visibility = View.GONE } } }) - with(countingRecyclerView as RecyclerView) { + with(list as RecyclerView) { layoutManager = LinearLayoutManager(context) adapter = this@CountingFragment.adapter @@ -149,14 +152,12 @@ class CountingFragment : Fragment(), } override fun validate(): Boolean { - return true + return input?.getCurrentSelectedInputTaxon() != null } override fun refreshView() { - (input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.getCounting() - ?.also { - adapter?.setCounting(it) - } + adapter?.setItems((input?.getCurrentSelectedInputTaxon() as InputTaxon?)?.getCounting() + ?: emptyList()) } override fun setInput(input: AbstractInput) { diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingRecyclerViewAdapter.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingRecyclerViewAdapter.kt index a2833512..e2409f49 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingRecyclerViewAdapter.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/counting/CountingRecyclerViewAdapter.kt @@ -1,13 +1,10 @@ package fr.geonature.occtax.ui.input.counting -import android.view.LayoutInflater import android.view.View -import android.view.ViewGroup import android.widget.TextView -import androidx.recyclerview.widget.DiffUtil -import androidx.recyclerview.widget.RecyclerView import fr.geonature.occtax.R import fr.geonature.occtax.input.CountingMetadata +import fr.geonature.occtax.ui.shared.adapter.ListItemRecyclerViewAdapter import java.util.Locale /** @@ -15,133 +12,40 @@ import java.util.Locale * * @author [S. Grimault](mailto:sebastien.grimault@gmail.com) */ -class CountingRecyclerViewAdapter(private val listener: OnCountingRecyclerViewAdapterListener) : RecyclerView.Adapter() { +class CountingRecyclerViewAdapter(listener: OnListItemRecyclerViewAdapterListener) : ListItemRecyclerViewAdapter(listener) { - private val counting = mutableListOf() - private val onClickListener: View.OnClickListener - - init { - registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { - override fun onChanged() { - super.onChanged() - - listener.showEmptyTextView(itemCount == 0) - } - - override fun onItemRangeChanged(positionStart: Int, - itemCount: Int) { - super.onItemRangeChanged(positionStart, - itemCount) - - listener.showEmptyTextView(itemCount == 0) - } - - override fun onItemRangeInserted(positionStart: Int, - itemCount: Int) { - super.onItemRangeInserted(positionStart, - itemCount) - - listener.showEmptyTextView(false) - } - - override fun onItemRangeRemoved(positionStart: Int, - itemCount: Int) { - super.onItemRangeRemoved(positionStart, - itemCount) - - listener.showEmptyTextView(itemCount == 0) - } - }) - - onClickListener = View.OnClickListener { v -> - val counting = v.tag as CountingMetadata - listener.onClick(counting) - } - } - - override fun onCreateViewHolder(parent: ViewGroup, - viewType: Int): ViewHolder { - return ViewHolder(parent) + override fun getViewHolder(view: View, + viewType: Int): AbstractViewHolder { + return ViewHolder(view) } - override fun getItemCount(): Int { - return counting.size + override fun getLayoutResourceId(position: Int, + item: CountingMetadata): Int { + return R.layout.list_item_2 } - override fun onBindViewHolder(holder: ViewHolder, - position: Int) { - holder.bind(position) + override fun areItemsTheSame(oldItems: List, + newItems: List, + oldItemPosition: Int, + newItemPosition: Int): Boolean { + return oldItems[oldItemPosition].index == newItems[newItemPosition].index } - fun setCounting(counting: List) { - val newList = counting.distinct() - - if (this.counting.isEmpty()) { - this.counting.addAll(newList) - - if (this.counting.isNotEmpty()) { - notifyItemRangeInserted(0, - this.counting.size) - } - - return - } - - if (counting.isEmpty()) { - this.counting.clear() - notifyDataSetChanged() - - return - } - - val diffResult = DiffUtil.calculateDiff(object : DiffUtil.Callback() { - override fun getOldListSize(): Int { - return this@CountingRecyclerViewAdapter.counting.size - } - - override fun getNewListSize(): Int { - return newList.size - } - - override fun areItemsTheSame(oldItemPosition: Int, - newItemPosition: Int): Boolean { - return this@CountingRecyclerViewAdapter.counting.toList()[oldItemPosition].index == newList[newItemPosition].index - } - - override fun areContentsTheSame(oldItemPosition: Int, - newItemPosition: Int): Boolean { - return this@CountingRecyclerViewAdapter.counting.toList()[oldItemPosition] == newList[newItemPosition] - } - }) - - this.counting.clear() - this.counting.addAll(newList) - - diffResult.dispatchUpdatesTo(this) + override fun areContentsTheSame(oldItems: List, + newItems: List, + oldItemPosition: Int, + newItemPosition: Int): Boolean { + return oldItems[oldItemPosition] == newItems[newItemPosition] } - inner class ViewHolder(parent: ViewGroup) : RecyclerView.ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.list_item_2, - parent, - false)) { + inner class ViewHolder(itemView: View) : ListItemRecyclerViewAdapter.AbstractViewHolder(itemView) { private val text1: TextView = itemView.findViewById(android.R.id.text1) private val text2: TextView = itemView.findViewById(android.R.id.text2) - fun bind(position: Int) { - val countingMetadata = counting[position] - + override fun onBind(item: CountingMetadata) { text1.text = itemView.context.getString(R.string.counting_main_label, - countingMetadata.index) - text2.text = buildDescription(countingMetadata) - - with(itemView) { - tag = countingMetadata - setOnClickListener(onClickListener) - setOnLongClickListener { - listener.onLongClicked(counting.indexOf(countingMetadata), - countingMetadata) - true - } - } + item.index) + text2.text = buildDescription(item) } private fun buildDescription(countingMetadata: CountingMetadata): String { @@ -171,30 +75,4 @@ class CountingRecyclerViewAdapter(private val listener: OnCountingRecyclerViewAd return if (resourceId == 0) mnemonic else itemView.context.getString(resourceId) } } - - /** - * Callback used by [CountingRecyclerViewAdapter]. - */ - interface OnCountingRecyclerViewAdapterListener { - - /** - * Called when a [CountingMetadata] has been clicked. - * - * @param countingMetadata the selected CountingMetadata to edit - */ - fun onClick(countingMetadata: CountingMetadata) - - /** - * Called when a [CountingMetadata] has been clicked and held. - * - * @param countingMetadata the selected [CountingMetadata] - */ - fun onLongClicked(position: Int, - countingMetadata: CountingMetadata) - - /** - * Whether to show an empty text view when data changed. - */ - fun showEmptyTextView(show: Boolean) - } } \ No newline at end of file diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/summary/InputTaxaSummaryFragment.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/summary/InputTaxaSummaryFragment.kt new file mode 100644 index 00000000..f520129e --- /dev/null +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/summary/InputTaxaSummaryFragment.kt @@ -0,0 +1,179 @@ +package fr.geonature.occtax.ui.input.summary + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.animation.AnimationUtils +import android.widget.Toast +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.snackbar.BaseTransientBottomBar + +import com.google.android.material.snackbar.Snackbar +import fr.geonature.commons.input.AbstractInput +import fr.geonature.commons.input.AbstractInputTaxon +import fr.geonature.occtax.R +import fr.geonature.occtax.input.Input +import fr.geonature.occtax.ui.input.IInputFragment +import fr.geonature.occtax.ui.shared.adapter.ListItemRecyclerViewAdapter +import fr.geonature.viewpager.ui.AbstractPagerFragmentActivity +import fr.geonature.viewpager.ui.IValidateFragment +import kotlinx.android.synthetic.main.fragment_recycler_view_fab.content +import kotlinx.android.synthetic.main.fragment_recycler_view_fab.empty +import kotlinx.android.synthetic.main.fragment_recycler_view_fab.fab +import kotlinx.android.synthetic.main.fragment_recycler_view_fab.list + +/** + * Summary of all edited taxa. + * + * @author [S. Grimault](mailto:sebastien.grimault@gmail.com) + */ +class InputTaxaSummaryFragment : Fragment(), + IValidateFragment, + IInputFragment { + + private var input: Input? = null + private var adapter: InputTaxaSummaryRecyclerViewAdapter? = null + + override fun onCreateView(inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.fragment_recycler_view_fab, + container, + false) + } + + override fun onViewCreated( + view: View, + savedInstanceState: Bundle?) { + super.onViewCreated(view, + savedInstanceState) + + empty.text = getString(R.string.summary_no_data) + + fab.setOnClickListener { + input?.clearCurrentSelectedInputTaxon() + + ((activity as AbstractPagerFragmentActivity?))?.also { + if (this@InputTaxaSummaryFragment.validate()) { + it.goToPageByKey(R.string.pager_fragment_taxa_title) + + return@also + } + + it.goToPreviousPage() + it.goToNextPage() + } + } + + adapter = InputTaxaSummaryRecyclerViewAdapter(object : ListItemRecyclerViewAdapter.OnListItemRecyclerViewAdapterListener { + override fun onClick(item: AbstractInputTaxon) { + input?.setCurrentSelectedInputTaxonId(item.taxon.id) + (activity as AbstractPagerFragmentActivity?)?.goToPageByKey(R.string.pager_fragment_information_title) + } + + override fun onLongClicked(position: Int, + item: AbstractInputTaxon) { + adapter?.remove(item) + input?.removeInputTaxon(item.taxon.id) + (activity as AbstractPagerFragmentActivity?)?.validateCurrentPage() + + Snackbar.make(content, + R.string.summary_snackbar_input_taxon_deleted, + Snackbar.LENGTH_LONG) + .setAction(R.string.summary_snackbar_input_taxon_undo + ) { + adapter?.add(item, + position) + input?.addInputTaxon(item) + } + .addCallback(object : BaseTransientBottomBar.BaseCallback() { + override fun onDismissed(transientBottomBar: Snackbar?, + event: Int) { + super.onDismissed(transientBottomBar, + event) + + (activity as AbstractPagerFragmentActivity?)?.validateCurrentPage() + + // check if this step is still valid and apply automatic redirection if any + if (!this@InputTaxaSummaryFragment.validate()) { + val context = context ?: return + + Toast.makeText(context, + R.string.summary_toast_no_input_taxon, + Toast.LENGTH_LONG) + .show() + + ((activity as AbstractPagerFragmentActivity?))?.also { + it.goToPreviousPage() + it.goToNextPage() + } + } + } + }) + .show() + } + + override fun showEmptyTextView(show: Boolean) { + if (empty.visibility == View.VISIBLE == show) { + return + } + + if (show) { + empty.startAnimation(AnimationUtils.loadAnimation(context, + android.R.anim.fade_in)) + empty.visibility = View.VISIBLE + + } + else { + empty.startAnimation(AnimationUtils.loadAnimation(context, + android.R.anim.fade_out)) + empty.visibility = View.GONE + } + } + }) + + with(list as RecyclerView) { + layoutManager = LinearLayoutManager(context) + adapter = this@InputTaxaSummaryFragment.adapter + + val dividerItemDecoration = DividerItemDecoration(context, + (layoutManager as LinearLayoutManager).orientation) + addItemDecoration(dividerItemDecoration) + } + } + + override fun getResourceTitle(): Int { + return R.string.pager_fragment_summary_title + } + + override fun pagingEnabled(): Boolean { + return true + } + + override fun validate(): Boolean { + return input?.getInputTaxa()?.isNotEmpty() ?: false + } + + override fun refreshView() { + adapter?.setItems(input?.getInputTaxa() ?: emptyList()) + } + + override fun setInput(input: AbstractInput) { + this.input = input as Input + } + + companion object { + + /** + * Use this factory method to create a new instance of [InputTaxaSummaryFragment]. + * + * @return A new instance of [InputTaxaSummaryFragment] + */ + @JvmStatic + fun newInstance() = InputTaxaSummaryFragment() + } +} \ No newline at end of file diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/summary/InputTaxaSummaryRecyclerViewAdapter.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/summary/InputTaxaSummaryRecyclerViewAdapter.kt new file mode 100644 index 00000000..262a3a26 --- /dev/null +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/summary/InputTaxaSummaryRecyclerViewAdapter.kt @@ -0,0 +1,47 @@ +package fr.geonature.occtax.ui.input.summary + +import android.view.View +import android.widget.TextView +import fr.geonature.commons.input.AbstractInputTaxon +import fr.geonature.occtax.R +import fr.geonature.occtax.ui.shared.adapter.ListItemRecyclerViewAdapter + +/** + * Default RecyclerView Adapter used by [InputTaxaSummaryFragment]. + * + * @author [S. Grimault](mailto:sebastien.grimault@gmail.com) + */ +class InputTaxaSummaryRecyclerViewAdapter(listener: OnListItemRecyclerViewAdapterListener) : ListItemRecyclerViewAdapter(listener) { + + override fun getViewHolder(view: View, + viewType: Int): AbstractViewHolder { + return ViewHolder(view) + } + + override fun getLayoutResourceId(position: Int, + item: AbstractInputTaxon): Int { + return R.layout.list_item_2 + } + + override fun areItemsTheSame(oldItems: List, + newItems: List, + oldItemPosition: Int, + newItemPosition: Int): Boolean { + return oldItems[oldItemPosition].taxon.id == newItems[newItemPosition].taxon.id + } + + override fun areContentsTheSame(oldItems: List, + newItems: List, + oldItemPosition: Int, + newItemPosition: Int): Boolean { + return oldItems[oldItemPosition] == newItems[newItemPosition] + } + + inner class ViewHolder(itemView: View) : ListItemRecyclerViewAdapter.AbstractViewHolder(itemView) { + private val text1: TextView = itemView.findViewById(android.R.id.text1) + + override fun onBind(item: AbstractInputTaxon) { + text1.text = item.taxon.name + } + } +} \ No newline at end of file diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/shared/adapter/ListItemRecyclerViewAdapter.kt b/occtax/src/main/java/fr/geonature/occtax/ui/shared/adapter/ListItemRecyclerViewAdapter.kt new file mode 100644 index 00000000..00b6e690 --- /dev/null +++ b/occtax/src/main/java/fr/geonature/occtax/ui/shared/adapter/ListItemRecyclerViewAdapter.kt @@ -0,0 +1,241 @@ +package fr.geonature.occtax.ui.shared.adapter + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.RecyclerView + +/** + * Base [RecyclerView.Adapter] that is backed by a [List] of arbitrary objects. + * + * @author [S. Grimault](mailto:sebastien.grimault@gmail.com) + */ +abstract class ListItemRecyclerViewAdapter(private val listener: OnListItemRecyclerViewAdapterListener) : RecyclerView.Adapter.AbstractViewHolder>() { + + private val items = mutableListOf() + + init { + this.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { + override fun onChanged() { + super.onChanged() + + listener.showEmptyTextView(itemCount == 0) + } + + override fun onItemRangeChanged(positionStart: Int, + itemCount: Int) { + super.onItemRangeChanged(positionStart, + itemCount) + + listener.showEmptyTextView(itemCount == 0) + } + + override fun onItemRangeInserted(positionStart: Int, + itemCount: Int) { + super.onItemRangeInserted(positionStart, + itemCount) + + listener.showEmptyTextView(false) + } + + override fun onItemRangeRemoved(positionStart: Int, + itemCount: Int) { + super.onItemRangeRemoved(positionStart, + itemCount) + + listener.showEmptyTextView(itemCount == 0) + } + }) + } + + override fun onCreateViewHolder(parent: ViewGroup, + viewType: Int): AbstractViewHolder { + return getViewHolder(LayoutInflater.from(parent.context) + .inflate(viewType, + parent, + false) + , + viewType) + } + + override fun getItemCount(): Int { + return items.size + } + + override fun onBindViewHolder(holder: AbstractViewHolder, + position: Int) { + holder.bind(position, + items[position]) + } + + override fun getItemViewType(position: Int): Int { + return getLayoutResourceId(position, + items[position]) + } + + /** + * Sets new items. + */ + fun setItems(newItems: List) { + if (this.items.isEmpty()) { + this.items.addAll(newItems) + + if (this.items.isNotEmpty()) { + notifyItemRangeInserted(0, + this.items.size) + } + else { + notifyDataSetChanged() + } + + return + } + + if (items.isEmpty()) { + this.items.clear() + notifyDataSetChanged() + + return + } + + val diffResult = DiffUtil.calculateDiff(object : DiffUtil.Callback() { + override fun getOldListSize(): Int { + return this@ListItemRecyclerViewAdapter.items.size + } + + override fun getNewListSize(): Int { + return newItems.size + } + + override fun areItemsTheSame(oldItemPosition: Int, + newItemPosition: Int): Boolean { + return this@ListItemRecyclerViewAdapter.areItemsTheSame(this@ListItemRecyclerViewAdapter.items, + newItems, + oldItemPosition, + newItemPosition) + } + + override fun areContentsTheSame(oldItemPosition: Int, + newItemPosition: Int): Boolean { + return this@ListItemRecyclerViewAdapter.areContentsTheSame(this@ListItemRecyclerViewAdapter.items, + newItems, + oldItemPosition, + newItemPosition) + } + }) + + this.items.clear() + this.items.addAll(newItems) + + diffResult.dispatchUpdatesTo(this) + } + + /** + * Add or insert item at given position. + */ + fun add(item: T, + index: Int = -1) { + val position = if (index == -1) this.items.size - 1 else index + this.items.add(index, + item) + + notifyItemInserted(position) + } + + /** + * Removes item from the list. + * + * @return item position if successfully removed, -1 otherwise + */ + fun remove(item: T): Int { + val itemPosition = this.items.indexOf(item) + val removed = this.items.remove(item) + + if (removed) { + notifyItemRemoved(itemPosition) + + if (this.items.isEmpty()) { + notifyDataSetChanged() + } + } + + return if (removed) itemPosition else -1 + } + + /** + * Gets the [AbstractViewHolder] implementation for given view type. + */ + protected abstract fun getViewHolder(view: View, + viewType: Int): AbstractViewHolder + + /** + * Gets the layout resource Id at given position. + */ + @LayoutRes + protected abstract fun getLayoutResourceId(position: Int, + item: T): Int + + /** + * Called by the `DiffUtil` to decide whether two object represent the same item. + */ + protected abstract fun areItemsTheSame(oldItems: List, + newItems: List, + oldItemPosition: Int, + newItemPosition: Int): Boolean + + /** + * Called by the `DiffUtil` when it wants to check whether two items have the same data. + */ + protected abstract fun areContentsTheSame(oldItems: List, + newItems: List, + oldItemPosition: Int, + newItemPosition: Int): Boolean + + abstract inner class AbstractViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + fun bind(position: Int, + item: T) { + onBind(item) + + with(itemView) { + setOnClickListener { + listener.onClick(item) + } + setOnLongClickListener { + listener.onLongClicked(position, + item) + true + } + } + } + + abstract fun onBind(item: T) + } + + /** + * Callback used by [ListItemRecyclerViewAdapter]. + */ + interface OnListItemRecyclerViewAdapterListener { + + /** + * Called when an item has been clicked. + * + * @param item the selected item to edit + */ + fun onClick(item: T) + + /** + * Called when an item has been clicked and held. + * + * @param item the selected item + */ + fun onLongClicked(position: Int, + item: T) + + /** + * Whether to show an empty text view when data changed. + */ + fun showEmptyTextView(show: Boolean) + } +} \ No newline at end of file diff --git a/occtax/src/main/res/layout/fragment_counting.xml b/occtax/src/main/res/layout/fragment_recycler_view_fab.xml similarity index 73% rename from occtax/src/main/res/layout/fragment_counting.xml rename to occtax/src/main/res/layout/fragment_recycler_view_fab.xml index 4094ae13..c9fa8704 100644 --- a/occtax/src/main/res/layout/fragment_counting.xml +++ b/occtax/src/main/res/layout/fragment_recycler_view_fab.xml @@ -2,7 +2,7 @@ @@ -10,19 +10,18 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - + + android:text="@string/no_data" + android:textAlignment="center" + android:visibility="gone" /> diff --git a/occtax/src/main/res/values-fr/strings.xml b/occtax/src/main/res/values-fr/strings.xml index ca758ae0..b9076785 100644 --- a/occtax/src/main/res/values-fr/strings.xml +++ b/occtax/src/main/res/values-fr/strings.xml @@ -19,7 +19,6 @@ Annuler Aucune donnée - Aucune sélection.\nAjouter en un via le bouton "Ajouter". Paramètres Recherche @@ -44,6 +43,7 @@ Taxons Informations Dénombrements + Bilan de la saisie Observateurs @@ -67,4 +67,9 @@ Min Max + Aucune saisie.\nAjouter un nouveau taxon via le bouton +. + Saisie supprimée + Annuler + Aucune saisie. Redirection vers la dernière étape valide. + \ No newline at end of file diff --git a/occtax/src/main/res/values/strings.xml b/occtax/src/main/res/values/strings.xml index ce6b61e8..22214cc7 100644 --- a/occtax/src/main/res/values/strings.xml +++ b/occtax/src/main/res/values/strings.xml @@ -23,7 +23,6 @@ Undo No data - No selected item.\nAdd one by tapping the "Add" button. Settings Search @@ -48,6 +47,7 @@ Taxa Information Counting + Summary Selected observers @@ -71,4 +71,9 @@ Min Max + No input taxon.\nCreate a new one by tapping the + button. + Input taxon deleted + Undo + No input taxon.\nRedirecting to the last valid step. + From 0c4b3be095f92bb7967b4dbe4ba0aa7d2d03f573 Mon Sep 17 00:00:00 2001 From: "S. Grimault" Date: Tue, 29 Oct 2019 23:09:51 +0100 Subject: [PATCH 15/16] fix: do not restart automatically the loader about current selected taxon. --- occtax/build.gradle | 2 +- .../occtax/ui/input/taxa/TaxaFragment.kt | 39 ++++--------------- .../ui/input/taxa/TaxaRecyclerViewAdapter.kt | 6 +-- 3 files changed, 9 insertions(+), 38 deletions(-) diff --git a/occtax/build.gradle b/occtax/build.gradle index 3b6ecbea..4e1da531 100644 --- a/occtax/build.gradle +++ b/occtax/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' -version = "0.1.8" +version = "0.1.9" android { compileSdkVersion 28 diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/taxa/TaxaFragment.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/taxa/TaxaFragment.kt index 03513e0e..ac695c90 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/taxa/TaxaFragment.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/taxa/TaxaFragment.kt @@ -38,8 +38,6 @@ class TaxaFragment : Fragment(), IInputFragment { private var input: Input? = null - private var selectedTaxonId: Long? = null - private var adapter: TaxaRecyclerViewAdapter? = null private val loaderCallbacks = object : LoaderManager.LoaderCallbacks { @@ -104,6 +102,9 @@ class TaxaFragment : Fragment(), adapter?.setSelectedTaxon(selectedTaxon) } } + + LoaderManager.getInstance(this@TaxaFragment) + .destroyLoader(LOADER_TAXON) } } } @@ -115,14 +116,6 @@ class TaxaFragment : Fragment(), } } - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - if (savedInstanceState?.containsKey(KEY_SELECTED_TAXON_ID) == true) { - selectedTaxonId = savedInstanceState.getLong(KEY_SELECTED_TAXON_ID) - } - } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { @@ -134,24 +127,17 @@ class TaxaFragment : Fragment(), // Set the adapter adapter = TaxaRecyclerViewAdapter(object : TaxaRecyclerViewAdapter.OnTaxaRecyclerViewAdapterListener { override fun onSelectedTaxon(taxon: AbstractTaxon) { - val selectedTaxonId = selectedTaxonId - - if (selectedTaxonId != null) { - input?.removeInputTaxon(selectedTaxonId) - } + input?.getCurrentSelectedInputTaxon() + ?.also { input?.removeInputTaxon(it.taxon.id) } input?.addInputTaxon(InputTaxon(taxon)) - this@TaxaFragment.selectedTaxonId = taxon.id (activity as AbstractPagerFragmentActivity?)?.validateCurrentPage() } override fun onNoTaxonSelected() { - val selectedTaxonId = selectedTaxonId - - if (selectedTaxonId != null) { - input?.removeInputTaxon(selectedTaxonId) - } + input?.getCurrentSelectedInputTaxon() + ?.also { input?.removeInputTaxon(it.taxon.id) } (activity as AbstractPagerFragmentActivity?)?.validateCurrentPage() } @@ -182,17 +168,6 @@ class TaxaFragment : Fragment(), setHasOptionsMenu(true) } - override fun onSaveInstanceState(outState: Bundle) { - val selectedTaxonId = selectedTaxonId - - if (selectedTaxonId != null) { - outState.putLong(KEY_SELECTED_TAXON_ID, - selectedTaxonId) - } - - super.onSaveInstanceState(outState) - } - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { diff --git a/occtax/src/main/java/fr/geonature/occtax/ui/input/taxa/TaxaRecyclerViewAdapter.kt b/occtax/src/main/java/fr/geonature/occtax/ui/input/taxa/TaxaRecyclerViewAdapter.kt index 428f327b..13d1f8a5 100644 --- a/occtax/src/main/java/fr/geonature/occtax/ui/input/taxa/TaxaRecyclerViewAdapter.kt +++ b/occtax/src/main/java/fr/geonature/occtax/ui/input/taxa/TaxaRecyclerViewAdapter.kt @@ -73,7 +73,7 @@ class TaxaRecyclerViewAdapter(private val listener: OnTaxaRecyclerViewAdapterLis val cursor = cursor ?: return "" cursor.moveToPosition(position) val taxon = Taxon.fromCursor(cursor) ?: return "" - val name = taxon.name ?: return "" + val name = taxon.name return name.elementAt(0) .toString() @@ -85,10 +85,6 @@ class TaxaRecyclerViewAdapter(private val listener: OnTaxaRecyclerViewAdapterLis notifyDataSetChanged() } - fun getSelectedTaxon(): AbstractTaxon? { - return this.selectedTaxon - } - fun bind(cursor: Cursor?) { this.cursor = cursor scrollToFirstItemSelected() From 991e53ae8e61d12e646896026b6b2ecbd308c77d Mon Sep 17 00:00:00 2001 From: "S. Grimault" Date: Wed, 30 Oct 2019 20:26:35 +0100 Subject: [PATCH 16/16] chore: 0.1.9 release --- occtax/version.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/occtax/version.properties b/occtax/version.properties index 651e0293..c012275f 100644 --- a/occtax/version.properties +++ b/occtax/version.properties @@ -1,2 +1,2 @@ -#Sun Oct 13 17:23:18 CEST 2019 -VERSION_CODE=1000 +#Wed Oct 30 20:21:41 CET 2019 +VERSION_CODE=1170