/* Ċ Ġ* ĠCopyright Ġ 2 0 1 5 ĠN ich olas ĠB ily k Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ Ċ package Ġcom . ac orn ui . component Ċ Ċ import Ġcom . ac orn ui . assertions Enabled Ċ import Ġcom . ac orn ui . math . Math Utils Ċ import Ġcom . ac orn ui . reflect . observable Ċ import Ġcom . ac orn ui . signal . Signal Ċ import Ġcom . ac orn ui . string . to Rad ix Ċ import Ġkotlin . properties . ReadWrite Property Ċ Ċ /** Ċ Ġ* ĠA Ġcomponent Ġthat Ġhas Ġan Ġinvalidate / validate Ġcycle . Ċ Ġ* Ċ Ġ* Ġ@ author Ġnb ily k Ċ Ġ*/ Ċ interface ĠValid atable Ġ{ ĊĊ ĉ /** Ċĉ Ġ* ĠDis patched Ġwhen Ġthis Ġcomponent Ġhas Ġbeen Ġinvalid ated . Ċĉ Ġ*/ Ċ ĉ val Ġinvalid ated : ĠSignal <( Valid atable , ĠInt ) Ġ-> ĠUnit > ĊĊ ĉ /** Ċĉ Ġ* ĠThe Ġcurrently Ġinvalid Ġflags . Ċĉ Ġ*/ Ċ ĉ val Ġinvalid Flags : ĠInt ĊĊ ĉ /** Ċĉ Ġ* ĠInvalid ates Ġthe Ġgiven Ġflag . Ċĉ Ġ* ĠReturns Ġa Ġbit Ġmask Ġrepresenting Ġthe Ġflags Ġnewly Ġinvalid ated . Ċĉ Ġ* ĠDis patches Ġ[ invalid ated ] Ġwith Ġthe Ġnewly Ġinvalid ated Ġflags . Ċĉ Ġ* Ċĉ Ġ* Ġ@ param Ġflags ĠThe Ġbit Ġflags Ġto Ġinvalidate . ĠUse Ġan Ġ` or ` Ġoperation Ġto Ġinvalidate Ġmultiple Ġflags Ġat Ġonce . Ċĉ Ġ* Ġ@ see Ġ[ Validation Flags ] Ċĉ Ġ*/ Ċ ĉ fun Ġinvalidate ( flags : ĠInt ): ĠInt ĊĊ ĉ /** Ċĉ Ġ* ĠValid ates Ġthe Ġspecified Ġflags Ġfor Ġthis Ġcomponent . Ċĉ Ġ* Ċĉ Ġ* Ġ@ param Ġflags ĠA Ġbit Ġmask Ġfor Ġwhich Ġflags Ġto Ġvalidate . Ġ( Use Ġ- 1 Ġto Ġvalidate Ġall ) Ċĉ Ġ* ĠExample : Ġvalidate ( Validation Flags . LAYOUT Ġor ĠValidation Flags . PROPERTIES ) Ġto Ġvalidate Ġboth Ġlayout Ġan Ġproperties . Ċĉ Ġ*/ Ċ ĉ fun Ġvalidate ( flags : ĠInt Ġ= Ġ- 1 ) Ċ Ċ } Ċ Ċ private Ġclass ĠValidation Node ( ĊĊĉ ĉ /** Ċĉĉ Ġ* ĠThis Ġnode 's Ġflag . Ċĉĉ Ġ*/ Ċĉ ĉ val Ġflag : ĠInt , ĊĊĉ ĉ /** Ċĉĉ Ġ* ĠWhen Ġthis Ġnode 's Ġflag Ġis Ġinvalid ated , Ġthe Ġflags Ġdefined Ġin Ġinvalid ation Mask Ġwill Ġalso Ġbe Ġinvalid ated . Ċĉĉ Ġ*/ Ċĉ ĉ var Ġinvalid ation Mask : ĠInt , ĊĊĉ ĉ /** Ċĉĉ Ġ* ĠWhen Ġflags Ġis Ġbeing Ġvalidated , Ġif Ġany Ġof Ġthem Ġare Ġin Ġthis Ġmask , Ġthis Ġnode Ġwill Ġalso Ġbe Ġvalidated . Ċĉĉ Ġ*/ Ċĉ ĉ var Ġvalidation Mask : ĠInt , ĊĊĉ ĉ val Ġon Validate : Ġ() Ġ-> ĠUnit Ċ ) Ġ{ ĊĊ ĉ var ĠisValid : ĠBoolean Ġ= Ġfalse Ċ Ċ } Ċ Ċ /** Ċ Ġ* ĠA Ġdependency Ġgraph Ġof Ġvalidation Ġflags . Ċ Ġ* ĠWhen Ġa Ġflag Ġis Ġinvalid ated , Ġall Ġdepend ents Ġare Ġalso Ġinvalid ated . ĠWhen Ġa Ġflag Ġis Ġvalidated , Ġall Ġdependencies Ġare Ċ Ġ* Ġguaranteed Ġto Ġbe Ġvalid Ġfirst . Ċ Ġ* Ċ Ġ* ĠThe ĠUI ĠComponent Ġimplementation Ġwill Ġwork Ġin Ġthis Ġway : Ċ Ġ* ĠUI ĠComponents Ġwill Ġvalidate Ġthe Ġvalidation Ġgraph Ġtop Ġdown , Ġlevel Ġorder . ĠWhen Ġa Ġcomponent Ġvalidates Ġa Ġflag Ġsuch Ġas Ċ Ġ* Ġlayout , Ġthat Ġcomponent Ġmay Ġrequire Ġthat Ġa Ġchild Ġcomponent Ġhave Ġa Ġvalid Ġlayout Ġin Ġorder Ġto Ġdetermine Ġits Ġmeasured Ċ Ġ* Ġsize . ĠOn Ġretrieving Ġthe Ġchild Ġcomponent Ġsize , Ġthat Ġchild Ġcomponent Ġmay Ġthen Ġvalidate Ġits Ġlayout , Ġthus Ġeffectively Ċ Ġ* Ġvalidating Ġcertain Ġflags Ġin Ġa Ġbottom - up Ġmanner . Ċ Ġ*/ Ċ class ĠValidation Graph Ġ{ ĊĊ ĉ private Ġval Ġnodes Ġ= ĠArrayList < Validation Node >() ĊĊ ĉ /** Ċĉ Ġ* ĠThe Ġcurrent Ġnode Ġbeing Ġvalidated . Ċĉ Ġ*/ Ċ ĉ private Ġvar ĠcurrentIndex Ġ= Ġ- 1 ĊĊ ĉ /** Ċĉ Ġ* ĠReturns Ġthe Ġcurrent Ġflag Ġbeing Ġvalidated , Ġor Ġ- 1 Ġif Ġthere Ġis Ġnot Ġa Ġcurrent Ġvalidation . Ċĉ Ġ*/ Ċ ĉ val Ġcurrent Flag : ĠInt Ċĉ ĉ get () Ġ{ Ċĉĉ ĉ if Ġ( currentIndex Ġ== Ġ- 1 ) Ġreturn Ġ- 1 Ċĉĉ ĉ return Ġnodes [ currentIndex ]. flag Ċĉ ĉ } ĊĊ ĉ private Ġvar Ġ_ invalid Flags Ġ= Ġ 0 Ċ ĉ val Ġinvalid Flags : ĠInt Ċĉ ĉ get () Ġ= Ġ_ invalid Flags ĊĊ ĉ private Ġvar Ġ_ all Flags Ġ= Ġ 0 ĊĊ ĉ /** Ċĉ Ġ* ĠAll Ġflags Ġthe Ġadded Ġnodes Ġrepresent . Ċĉ Ġ*/ Ċ ĉ val Ġall Flags : ĠInt Ċĉ ĉ get () Ġ= Ġ_ all Flags ĊĊ ĉ fun Ġadd Node ( flag : ĠInt , Ġon Validate : Ġ() Ġ-> ĠUnit ) Ġ= Ġadd Node ( flag , Ġ 0 , Ġ 0 , Ġon Validate ) ĊĊ ĉ fun Ġadd Node ( flag : ĠInt , Ġdependencies : ĠInt , Ġon Validate : Ġ() Ġ-> ĠUnit ) Ġ= Ġadd Node ( flag , Ġdependencies , Ġ 0 , Ġon Validate ) ĊĊ ĉ /** Ċĉ Ġ* ĠApp ends Ġa Ġvalidation Ġnode . Ċĉ Ġ* Ġ@ param Ġdependencies ĠIf Ġany Ġof Ġthese Ġdependencies Ġbecome Ġinvalid , Ġthis Ġnode Ġwill Ġalso Ġbecome Ġinvalid . Ċĉ Ġ*/ Ċ ĉ fun Ġadd Node ( flag : ĠInt , Ġdependencies : ĠInt , Ġdepend ents : ĠInt , Ġon Validate : Ġ() Ġ-> ĠUnit ) Ġ{ Ċĉ ĉ if Ġ( assertions Enabled Ġ&& Ġ! Math Utils . is Power Of Two ( flag )) Ġthrow ĠIllegalArgumentException (" flag Ġ${ flag . to Rad ix ( 2 )} Ġis Ġnot Ġa Ġpower Ġof Ġ 2 .") Ċĉ ĉ val ĠnewNode Ġ= ĠValidation Node ( flag , Ġdepend ents Ġor Ġflag , Ġdependencies Ġor Ġflag , Ġon Validate ) Ċĉ ĉ var Ġdependencies NotFound Ġ= Ġdependencies Ċĉ ĉ var Ġdepend ents NotFound Ġ= Ġdepend ents Ċĉ ĉ var Ġinsert Index Ġ= Ġnodes . size Ċĉ ĉ for Ġ( i Ġin Ġ 0 .. nodes . last Index ) Ġ{ Ċĉĉ ĉ val Ġprevious Node Ġ= Ġnodes [ i ] Ċĉĉ ĉ if Ġ( previous Node . flag Ġ== Ġflag ) Ġthrow ĠException (" flag Ġ$ flag Ġalready Ġexists .") Ċĉĉ ĉ val Ġflag Inv Ġ= Ġprevious Node . flag . inv () Ċĉĉ ĉ dependencies NotFound Ġ= Ġdependencies NotFound Ġand Ġflag Inv Ċĉĉ ĉ dependent s NotFound Ġ= Ġdepend ents NotFound Ġand Ġflag Inv Ċĉĉ ĉ if Ġ( previous Node . validation Mask Ġand ĠnewNode . invalid ation Mask Ġ> Ġ 0 ) Ġ{ Ċĉĉĉ ĉ previous Node . validation Mask Ġ= ĠnewNode . validation Mask Ġor Ġprevious Node . validation Mask Ċĉĉĉ ĉ new Node . invalid ation Mask Ġ= ĠnewNode . invalid ation Mask Ġor Ġprevious Node . invalid ation Mask Ċĉĉĉ ĉ if Ġ( insert Index Ġ> Ġi ) Ċĉĉĉĉ ĉ insert Index Ġ= Ġi Ċĉĉ ĉ } Ċĉĉ ĉ if Ġ( previous Node . invalid ation Mask Ġand ĠnewNode . validation Mask Ġ> Ġ 0 ) Ġ{ Ċĉĉĉ ĉ new Node . validation Mask Ġ= ĠnewNode . validation Mask Ġor Ġprevious Node . validation Mask Ċĉĉĉ ĉ previous Node . invalid ation Mask Ġ= ĠnewNode . invalid ation Mask Ġor Ġprevious Node . invalid ation Mask Ċĉĉĉ ĉ if Ġ( insert Index Ġ<= Ġi ) Ġ{ Ċĉĉĉĉ ĉ throw ĠException (" Validation Ġnode Ġcannot Ġbe Ġadded Ġafter Ġdependency Ġ${ previous Node . flag . to Flag String ()} Ġand Ġbefore Ġall Ġdepend ents Ġ${ dependent s . to Flags String () }") Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } Ċĉ ĉ nodes . add ( insert Index , ĠnewNode ) Ċĉ ĉ _ invalid Flags Ġ= Ġ_ invalid Flags Ġor ĠnewNode . flag Ċĉ ĉ _ all Flags Ġ= Ġ_ all Flags Ġor ĠnewNode . flag Ċĉ ĉ if Ġ( dependent s NotFound Ġ!= Ġ 0 ) Ċĉĉ ĉ throw ĠException (" validation Ġnode Ġadded , Ġbut Ġthe Ġdependent Ġflags : Ġ${ dependent s NotFound . to Flags String ()} Ġwere Ġnot Ġfound .") Ċĉ ĉ if Ġ( dependencies NotFound Ġ!= Ġ 0 ) Ċĉĉ ĉ throw ĠException (" validation Ġnode Ġadded , Ġbut Ġthe Ġdependency Ġflags : Ġ${ dependencies NotFound . to Flags String ()} Ġwere Ġnot Ġfound .") Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠInvalid ates Ġthe Ġgiven Ġflags . Ċĉ Ġ* Ġ@ return ĠReturns Ġa Ġbit mask Ġof Ġall Ġthe Ġflags Ġinvalid ated . Ġ( This Ġwill Ġconsider Ġthe Ġdependencies Ġfor Ġall Ġnodes Ċĉ Ġ* Ġwithin Ġthe Ġ[ flags ] Ġargument . Ċĉ Ġ*/ Ċ ĉ fun Ġinvalidate ( flags : ĠInt Ġ= Ġ- 1 ): ĠInt Ġ{ Ċĉ ĉ var Ġflags Invalid ated Ġ= Ġ 0 Ċĉ ĉ var Ġflags To Invalidate Ġ= Ġflags Ġand Ġ_ invalid Flags . inv () Ċĉ ĉ if Ġ( flags To Invalidate Ġ== Ġ 0 ) Ġreturn Ġ 0 Ċĉ ĉ if Ġ( assertions Enabled Ġ&& ĠcurrentIndex Ġ>= Ġ 0 ) Ġ{ Ċĉĉ ĉ // ĠCannot Ġinvalidate Ġanything Ġthat Ġis Ġnot Ġdependent Ġon Ġthe Ġcurrent Ġnode . Ċĉĉ ĉ val ĠcurrentNode Ġ= Ġnodes [ currentIndex ] Ċĉĉ ĉ val Ġbad Flags Ġ= Ġflags To Invalidate Ġand Ġ( currentNode . validation Mask Ġand ĠcurrentNode . flag . inv ()) Ċĉĉ ĉ if Ġ( bad Flags Ġ> Ġ 0 ) Ġ{ Ċĉĉĉ ĉ throw ĠException (" Cannot Ġinvalidate Ġ${ flags . to Flags String ()} Ġwhile Ġvalidating Ġ${ currentNode . flag . to Flag String ()}; ĠThe Ġfollowing Ġinvalid ated Ġflags Ġare Ġdependencies Ġof Ġthe Ġcurrent Ġnode : Ġ${ bad Flags . to Flags String () }") Ċĉĉ ĉ } Ċĉ ĉ } Ċĉ ĉ for Ġ( i Ġin Ġ 0 .. nodes . last Index ) Ġ{ Ċĉĉ ĉ val Ġn Ġ= Ġnodes [ i ] Ċĉĉ ĉ if Ġ(! n . isValid ) Ġcontinue Ċĉĉ ĉ if Ġ( flags To Invalidate Ġand Ġn . flag Ġ> Ġ 0 ) Ġ{ Ċĉĉĉ ĉ n . isValid Ġ= Ġfalse Ċĉĉĉ ĉ flags To Invalidate Ġ= Ġflags To Invalidate Ġor Ġn . invalid ation Mask Ċĉĉĉ ĉ flags Invalid ated Ġ= Ġflags Invalid ated Ġor Ġn . flag Ċĉĉ ĉ } Ċĉ ĉ } Ċĉ ĉ _ invalid Flags Ġ= Ġ_ invalid Flags Ġor Ġflags Invalid ated Ċĉ ĉ return Ġflags Invalid ated Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠValid ates Ġthe Ġgiven Ġflags . Ċĉ Ġ* Ċĉ Ġ* Ġ@ return ĠReturns Ġthe Ġflags Ġactually Ġvalidated . Ċĉ Ġ*/ Ċ ĉ fun Ġvalidate ( flags : ĠInt Ġ= Ġ- 1 ): ĠInt Ġ{ Ċĉ ĉ if Ġ( currentIndex Ġ!= Ġ- 1 ) Ġ{ Ċĉĉ ĉ if Ġ( assertions Enabled ) Ġ{ Ċĉĉĉ ĉ val Ġnode Ġ= Ġnodes [ currentIndex ] Ċĉĉĉ ĉ val Ġbad Flags Ġ= Ġ( node . invalid ation Mask Ġand Ġnode . flag . inv ()) Ġand Ġflags Ċĉĉĉ ĉ if Ġ( bad Flags Ġ> Ġ 0 ) Ċĉĉĉĉ ĉ throw ĠIllegalStateException (" Cannot Ġvalidate Ġ${ bad Flags . to Flags String ()} Ġwhile Ġvalidating Ġ${ node . flag . to Flag String () }") Ċĉĉ ĉ } Ċĉĉ ĉ return Ġ 0 Ċĉ ĉ } Ċĉ ĉ var Ġflags To Validate Ġ= Ġflags Ġand Ġ_ invalid Flags Ċĉ ĉ if Ġ( flags To Validate Ġ== Ġ 0 ) Ġreturn Ġ 0 Ċĉ ĉ var Ġflags Validated Ġ= Ġ 0 Ċĉ ĉ for Ġ( i Ġin Ġ 0 .. nodes . last Index ) Ġ{ Ċĉĉ ĉ currentIndex Ġ= Ġi Ċĉĉ ĉ val Ġn Ġ= Ġnodes [ i ] Ċĉĉ ĉ if Ġ(! n . isValid Ġ&& Ġflags To Validate Ġand Ġn . invalid ation Mask Ġ> Ġ 0 ) Ġ{ Ċĉĉĉ ĉ n . on Validate () Ċĉĉĉ ĉ n . isValid Ġ= Ġtrue Ċĉĉĉ ĉ flags To Validate Ġ= Ġflags To Validate Ġor Ġn . validation Mask Ċĉĉĉ ĉ flags Validated Ġ= Ġflags Validated Ġor Ġn . flag Ċĉĉĉ ĉ _ invalid Flags Ġ= Ġ_ invalid Flags Ġand Ġn . flag . inv () Ċĉĉ ĉ } Ċĉ ĉ } Ċĉ ĉ currentIndex Ġ= Ġ- 1 Ċĉ ĉ return Ġflags Validated Ċ ĉ } ĊĊ ĉ fun ĠisValid ( flag : ĠInt ): ĠBoolean Ġ{ Ċĉ ĉ return Ġ_ invalid Flags Ġand Ġflag Ġ== Ġ 0 Ċ ĉ } Ċ } Ċ Ċ /** Ċ Ġ* ĠUsing Ġthe ĠValidation Flags Ġlist , Ġprints Ġout Ġa Ġcomma Ġseparated Ġlist Ġof Ġthe Ġflags Ġthis Ġbit Ġmask Ġcontains . Ċ Ġ* ĠFor Ġnon - reserved Ġflags Ġ( flags Ġat Ġleast Ġ 1 Ġshl Ġ 1 6 ), Ġthe Ġpower Ġof Ġtwo Ġwill Ġbe Ġprinted . Ċ Ġ* Ġ@ see ĠValidation Flags Ċ Ġ* Ġ@ see ĠValidation Flags . flag ToString Ċ Ġ*/ Ċ fun ĠInt . to Flags String (): ĠString Ġ{ Ċ ĉ var Ġstr Ġ= Ġ"" Ċ ĉ for Ġ( i Ġin Ġ 0 .. 3 1 ) Ġ{ Ċĉ ĉ val Ġflag Ġ= Ġ 1 Ġshl Ġi Ċĉ ĉ if Ġ( flag Ġand Ġthis Ġ> Ġ 0 ) Ġ{ Ċĉĉ ĉ if Ġ( str . isNotEmpty ()) Ġstr Ġ+= Ġ"," Ċĉĉ ĉ str Ġ+= ĠValidation Flags . flag ToString ( flag ) Ċĉ ĉ } Ċ ĉ } Ċ ĉ return Ġstr Ċ } Ċ Ċ @ Suppress (" NOTH ING _ TO _ INLINE ") Ċ inline Ġfun ĠInt . contains Flag ( flag : ĠInt ): ĠBoolean Ġ{ Ċ ĉ return Ġthis Ġand Ġflag Ġ> Ġ 0 Ċ } Ċ Ċ fun ĠInt . to Flag String (): ĠString Ġ= ĠValidation Flags . flag ToString ( this ) Ċ Ċ fun Ġvalidation Graph ( init : ĠValidation Graph . () Ġ-> ĠUnit ): ĠValidation Graph Ġ{ Ċ ĉ val Ġv Ġ= ĠValidation Graph () Ċ ĉ v . init () Ċ ĉ return Ġv Ċ } Ċ Ċ fun Ġ< T > ĠValid atable . validation Prop ( initial Value : ĠT , Ġflags : ĠInt ): ĠRead Write Property < Any , ĠT > Ġ{ Ċ ĉ return Ġobservable ( initial Value ) Ġ{ Ċĉ ĉ invalidate ( flags ) Ċ ĉ } Ċ }