/* Ċ Ġ* ĠCopyright Ġ 2 0 2 1 ĠThe ĠAndroid ĠOpen ĠSource ĠProject Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠ Ġhttps :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ package Ġcom . example . android dev challenge . ui . found ations Ċ Ċ import Ġandroid . graphics . Paint Ċ import Ġandroid . graphics . PointF Ċ import Ġandroid . graphics . Type face Ċ import Ġandroidx . compose . animation . core . Anim atable Ċ import Ġandroidx . compose . animation . core . t ween Ċ import Ġandroidx . compose . foundation . Canvas Ċ import Ġandroidx . compose . runtime . Composable Ċ import Ġandroidx . compose . runtime . La unched Effect Ċ import Ġandroidx . compose . runtime . remember Ċ import Ġandroidx . compose . ui . Modifier Ċ import Ġandroidx . compose . ui . geometry . Offset Ċ import Ġandroidx . compose . ui . graphics . Color Ċ import Ġandroidx . compose . ui . graphics . Path Ċ import Ġandroidx . compose . ui . graphics . Path Effect Ċ import Ġandroidx . compose . ui . graphics . draw scope . Stroke Ċ import Ġandroidx . compose . ui . graphics . draw scope . draw Into Canvas Ċ import Ġandroidx . compose . ui . graphics . native Canvas Ċ import Ġandroidx . compose . ui . graphics . to Argb Ċ import Ġandroidx . compose . ui . platform . Local Context Ċ import Ġandroidx . compose . ui . unit . dp Ċ import Ġandroidx . compose . ui . unit . sp Ċ import Ġandroidx . core . content . res . Resources Compat Ċ import Ġcom . example . android dev challenge . R Ċ Ċ @ Composable Ċ fun ĠChart ( ĊĠĠĠ Ġmodifier : ĠModifier Ġ= ĠModifier , ĊĠĠĠ Ġchart Data : ĠChart Data , ĊĠĠĠ Ġchart Configuration : ĠChart Configuration Ċ ) Ġ{ ĊĠĠĠ Ġ// ĠSet Ġmaximum Ġand Ġminimum Ġvalues Ġfrom Ġthe Ġprovided Ġdata ĊĠĠĠ Ġval Ġ( max Value , Ġmin Value ) Ġ= Ġwhen Ġ( chart Configuration . value Range ) Ġ{ ĊĠĠĠĠĠĠĠ ĠChart Value Range . By Data Ġ-> ĠPair ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchart Data . values . max OrNull () Ġ?: Ġ 1 f , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchart Data . values . min OrNull () Ġ?: Ġ 0 f ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġis ĠChart Value Range . Co erce At Ġ-> ĠPair ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchart Configuration . value Range . max , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchart Configuration . value Range . min ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠGenerates Ġan Ġanimation Ġfor Ġeach Ġdata Ġpoint , Ġstarting Ġat Ġ 0 Ġand Ġincreasing Ġsimultaneously ĊĠĠĠ Ġ// Ġuntil Ġre aching Ġthe Ġactual Ġvalue . ĊĠĠĠ Ġval Ġanimated Values Ġ= Ġchart Data . values . map Ġ{ Ġremember Ġ{ ĠAnim atable ( min Value ) Ġ} Ġ} ĊĠĠĠ Ġanimated Values . forEach Indexed Ġ{ Ġindex , Ġanim atable Ġ-> ĊĠĠĠĠĠĠĠ ĠLa unched Effect ( chart Data ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġanim atable . animate To ( chart Data . values [ index ], Ġt ween ( duration Millis Ġ= Ġ 1 5 0 0 )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠGet Ġtype face Ġfor Ġchart Ġtags Ġ( context Ġcannot Ġbe Ġretrieved Ġinside Ġa ĠCanvas Ġscope ). ĊĠĠĠ Ġval Ġtype face : ĠType face ? Ġ= ĠResources Compat . getFont ( Local Context . current , ĠR . font . lat o ) ĊĊĠĠĠ ĠCanvas ( modifier ) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġval Ġside Margin Ġ= Ġsize . width Ġ* Ġ 0 . 1 f ĊĠĠĠĠĠĠĠ Ġval Ġx Diff : ĠFloat Ġ= Ġsize . width . minus ( side Margin Ġ* Ġ 2 ) Ġ/ Ġ( chart Data . values . size Ġ- Ġ 1 ) ĊĊĠĠĠĠĠĠĠ Ġ// ĠCalculate Ġmargins Ġinside Ġthe Ġchart ĊĠĠĠĠĠĠĠ Ġval Ġtop Margin Ġ= Ġ( size . height Ġ* Ġ 0 . 0 5 f ) ĊĠĠĠĠĠĠĠ Ġval Ġbottom Margin Ġ= Ġ( size . height Ġ* Ġ 0 . 9 5 f ) ĊĊĠĠĠĠĠĠĠ Ġ// ĠCalculate Ġratio Ġdata / axis Ġcoordinates . ĊĠĠĠĠĠĠĠ Ġval Ġratio Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( bottom Margin Ġ- Ġtop Margin ) Ġ/ Ġif Ġ( max Value Ġ== Ġmin Value ) Ġ 1 f Ġelse Ġ( max Value Ġ- Ġmin Value ) ĊĊĠĠĠĠĠĠĠ Ġ// ĠCalculates ĠX , Y Ġpoints Ġbased Ġon ĊĠĠĠĠĠĠĠ Ġval Ġpoints Ġ= Ġanimated Values . map Indexed Ġ{ Ġindex , Ġvalue Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ ĠOffset (( x Diff Ġ* Ġindex ) Ġ+ Ġside Margin , Ġtop Margin Ġ+ Ġ( max Value Ġ- Ġvalue . value ) Ġ* Ġratio ) ĊĠĠĠĠĠĠĠ Ġ}. to Mutable List (). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġadd ( 0 , ĠOffset ( 0 f , Ġbottom Margin )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġadd ( Offset ( this @ Canvas . size . width , Ġbottom Margin )) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// ĠCalculate Ġcontrol Ġpoints Ġfor Ġthe ĠBe zier Ġcurves ĊĠĠĠĠĠĠĠ Ġval Ġcontrol Points 1 Ġ= Ġmutable ListOf < PointF >() ĊĠĠĠĠĠĠĠ Ġval Ġcontrol Points 2 Ġ= Ġmutable ListOf < PointF >() ĊĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 1 Ġuntil Ġpoints . size ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontrol Points 1 . add ( PointF (( points [ i ]. x Ġ+ Ġpoints [ i Ġ- Ġ 1 ]. x ) Ġ/ Ġ 2 , Ġpoints [ i Ġ- Ġ 1 ]. y )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontrol Points 2 . add ( PointF (( points [ i ]. x Ġ+ Ġpoints [ i Ġ- Ġ 1 ]. x ) Ġ/ Ġ 2 , Ġpoints [ i ]. y )) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġdraw Line ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcolor Ġ= Ġchart Configuration . axis Color . copy ( alpha Ġ= Ġ 0 . 2 f ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstart Ġ= ĠOffset ( 0 f , Ġsize . height Ġ* Ġ 0 . 0 5 f ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġend Ġ= ĠOffset ( size . width , Ġsize . height Ġ* Ġ 0 . 0 5 f ), ĊĠĠĠĠĠĠĠĠĠĠĠ ĠstrokeWidth Ġ= Ġ 2 f , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpath Effect Ġ= ĠPath Effect . dash Path Effect ( float ArrayOf ( 1 6 f , Ġ 8 f )) ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġdraw Line ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcolor Ġ= Ġchart Configuration . axis Color . copy ( alpha Ġ= Ġ 0 . 2 f ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstart Ġ= ĠOffset ( 0 f , Ġsize . height Ġ* Ġ 0 . 5 f ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġend Ġ= ĠOffset ( size . width , Ġsize . height Ġ* Ġ 0 . 5 f ), ĊĠĠĠĠĠĠĠĠĠĠĠ ĠstrokeWidth Ġ= Ġ 2 f , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpath Effect Ġ= ĠPath Effect . dash Path Effect ( float ArrayOf ( 1 6 f , Ġ 8 f )) ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġ// ĠDraw Ġchart Ġarea ĊĠĠĠĠĠĠĠ Ġdraw Path ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcolor Ġ= Ġchart Configuration . area Color , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpath Ġ= ĠPath (). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmove To ( 0 f , Ġsize . height ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġline To ( points [ 0 ]. x , Ġpoints [ 0 ]. y ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 1 Ġuntil Ġpoints . size ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcp 1 Ġ= Ġcontrol Points 1 [ i Ġ- Ġ 1 ] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcp 2 Ġ= Ġcontrol Points 2 [ i Ġ- Ġ 1 ] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcubic To ( cp 1 . x , Ġcp 1 . y , Ġcp 2 . x , Ġcp 2 . y , Ġpoints [ i ]. x , Ġpoints [ i ]. y ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġline To ( size . width , Ġsize . height ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġline To ( 0 f , Ġsize . height ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġ// ĠDraw Ġmarkers Ġand Ġtags ĊĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 1 Ġuntil Ġpoints . size Ġ- Ġ 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdraw Circle ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcolor Ġ= Ġchart Configuration . marker Color , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcenter Ġ= Ġpoints [ i ], ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġradius Ġ= Ġ 4 . dp . to Px () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdraw Circle ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcolor Ġ= Ġchart Configuration . axis Color , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcenter Ġ= Ġpoints [ i ], ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġradius Ġ= Ġ 4 . dp . to Px (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstyle Ġ= ĠSt roke ( 2 f ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO : ĠUse Ġnative Ġcanvas Ġuntil Ġno Ġdraw Text Ġmethod Ġis Ġprovided Ġin ĠDraw Scope . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpaint Ġ= ĠPaint () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpaint . textAlign Ġ= ĠPaint . Align . CENTER ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpaint . text Size Ġ= Ġ 1 4 . sp . to Px () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpaint . color Ġ= Ġchart Configuration . axis Color . to Argb () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtype face ?. let Ġ{ Ġpaint . type face Ġ= Ġit Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdraw Into Canvas Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . native Canvas . draw Text ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġchart Configuration . format Value ( animated Values . get OrNull ( i Ġ- Ġ 1 )?. value ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpoints [ i ]. x , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpoints [ i ]. y Ġ- Ġ 3 0 f , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpaint ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// ĠDraw Ġaxes ĊĠĠĠĠĠĠĠ Ġdraw Line ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcolor Ġ= Ġchart Configuration . axis Color . copy ( alpha Ġ= Ġ 0 . 2 f ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstart Ġ= ĠOffset ( 0 f , Ġsize . height ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġend Ġ= ĠOffset ( 0 f , Ġ 0 f ) ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġdraw Line ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcolor Ġ= Ġchart Configuration . axis Color , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstart Ġ= ĠOffset ( 0 f , Ġsize . height ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġend Ġ= ĠOffset ( size . width , Ġsize . height ) ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġdraw Line ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcolor Ġ= Ġchart Configuration . axis Color . copy ( alpha Ġ= Ġ 0 . 2 f ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstart Ġ= ĠOffset ( size . width , Ġsize . height ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġend Ġ= ĠOffset ( size . width , Ġ 0 f ) ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ sealed Ġclass ĠChart Value Range Ġ{ ĊĠĠĠ Ġobject ĠBy Data Ġ: ĠChart Value Range () ĊĠĠĠ Ġclass ĠCo erce At ( val Ġmin : ĠFloat , Ġval Ġmax : ĠFloat ) Ġ: ĠChart Value Range () Ċ } Ċ Ċ data Ġclass ĠChart Data ( ĊĠĠĠ Ġval Ġvalues : ĠList < Float >, ĊĠĠĠ Ġval Ġtags : ĠList < String > Ċ ) Ċ Ċ data Ġclass ĠChart Configuration ( ĊĠĠĠ Ġval Ġmarker Color : ĠColor , ĊĠĠĠ Ġval Ġaxis Color : ĠColor , ĊĠĠĠ Ġval Ġarea Color : ĠColor , ĊĠĠĠ Ġval Ġformat Value : Ġ( Float ?) Ġ-> ĠString , ĊĠĠĠ Ġval Ġvalue Range : ĠChart Value Range Ċ ) Ċ