/* Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 1 8 ĠThe ĠAndroid ĠOpen ĠSource ĠProject Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ package Ġcom . android . tools . idea . ui . resourcemanager . widget Ċ Ċ import Ġcom . google . common . collect . Hash Bi Map Ċ import Ġcom . intellij . openapi . ui . Vertical Flow Layout Ċ import Ġcom . intellij . ui . Colo red List Cell Renderer Ċ import Ġcom . intellij . ui . Scrolling Util Ċ import Ġcom . intellij . ui . components . JB List Ċ import Ġcom . intellij . ui . components . JB ScrollPane Ċ import Ġcom . intellij . util . ui . J BU I Ċ import Ġjava . awt . Color Ċ import Ġjava . awt . Container Ċ import Ġjava . awt . Dimension Ċ import Ġjava . awt . Rectangle Ċ import Ġjava . awt . event . Adjustment Event Ċ import Ġjava . awt . event . Focus Adapter Ċ import Ġjava . awt . event . Focus Event Ċ import Ġjava . awt . event . Mouse Adapter Ċ import Ġjava . awt . event . MouseEvent Ċ import Ġjavax . swing . Box Ċ import Ġjavax . swing . J Component Ċ import Ġjavax . swing . JLabel Ċ import Ġjavax . swing . J List Ċ import Ġjavax . swing . JPanel Ċ import Ġjavax . swing . J ScrollPane Ċ import Ġjavax . swing . List Cell Renderer Ċ import Ġjavax . swing . ListModel Ċ import Ġjavax . swing . List Selection Model Ċ import Ġjavax . swing . event . List Data Event Ċ import Ġjavax . swing . event . List Data Listener Ċ import Ġjavax . swing . event . List Selection Listener Ċ Ċ private Ġval ĠEMPTY _ SELECTION _ ARRAY Ġ= ĠInt Array ( 0 ) Ċ Ċ /** Ċ Ġ* ĠA ĠSw ing Ġcomponent Ġdisplaying Ġmultiple Ġlists Ġorganized Ġin Ġ[ Section ] s Ġwith Ġa Ġheader . Ċ Ġ* Ċ Ġ* ĠThe Ġcomponent Ġis Ġdivided Ġinto Ġtwo Ġparts : Ġthe Ġmain Ġcomponent Ġ( this Ġinstance ) Ġwhich Ġdisplays Ċ Ġ* Ġthe Ġlists Ġin Ġa Ġ[ J ScrollPane ] Ġand Ġthe Ġsection Ġlist Ġ([ sections Component ]) Ġwhich Ġdisplays Ġthe Ġlist Ġof Ċ Ġ* Ġthe Ġsections ' Ġnames . Ċ Ġ* Ċ Ġ* ĠThe ĠScroll Pane Ġand Ġthe ĠSection Ġlist Ġare Ġsynchronized : Ġclicking Ġon Ġa Ġsection Ġname Ġin Ġthe Ġlist Ġwill Ġscroll Ċ Ġ* Ġthe Ġcorresponding Ġsection Ġin Ġthe Ġmain Ġcomponent , Ġand Ġscrolling Ġthe Ġmain Ġcomponent Ġwill Ġselect Ġthe Ġsection Ġname Ġof Ċ Ġ* Ġthe Ġsection Ġvisible Ġat Ġthe Ġtop Ġin Ġthe Ġsection Ġlist . Ċ Ġ*/ Ċ class ĠSection List ( private Ġval Ġmodel : ĠSection ListModel ) Ġ: ĠJ B ScrollPane () Ġ{ ĊĊĠ Ġprivate Ġvar Ġsection List Ġ= ĠJ B List < Section < *> >( model ) ĊĠ Ġprivate Ġval Ġall Inner Lists Ġ= Ġmutable ListOf < J List <* >>() ĊĠ Ġprivate Ġvar Ġlist Selection Changing Ġ= Ġfalse ĊĠ Ġprivate Ġval Ġinner List Selection Listener Ġ= Ġcreate List Selection Listener () ĊĠ Ġprivate Ġvar Ġcontent : ĠJ Component Ġ= Ġcreate Multi List Panel ( all Inner Lists , Ġinner List Selection Listener ) ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠG ap Ġbetween Ġlists ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġval Ġlists Gap Ġ= ĠJ BU I . scale ( 1 6 ) ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠReturns Ġthe Ġlist Ġof Ġ[ Section ] Ġname ĊĠĠ Ġ*/ ĊĠ Ġval Ġsections Component Ġ= Ġsection List ĊĊĠ Ġprivate Ġval Ġmulti L is LayoutManager Ġ= ĠVertical Flow Layout ( true , Ġfalse ) ĊĊĠ Ġprivate Ġval Ġfocus Listener Ġ= Ġobject Ġ: ĠFocus Adapter () Ġ{ ĊĊĠĠĠ Ġoverride Ġfun Ġfocus G ained ( focus Event : ĠFocus Event ?) Ġ{ ĊĠĠĠĠĠ Ġval Ġlist Ġ= Ġfocus Event ?. source Ġas ĠJ List < *> ĊĠĠĠĠĠ Ġif Ġ( list . selectedIndex Ġ== Ġ- 1 ) Ġ{ ĊĠĠĠĠĠĠĠ Ġlist . selectedIndex Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġscroll To Selection () ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġinit Ġ{ ĊĠĠĠ Ġmodel . add List Data Listener ( object Ġ: ĠList Data Listener Ġ{ ĊĠĠĠĠĠ Ġoverride Ġfun Ġcontents Changed ( e : ĠList Data Event ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġall Inner Lists . clear () ĊĠĠĠĠĠĠĠ Ġsection List . selection Model . clear Selection () ĊĠĠĠĠĠĠĠ Ġcontent Ġ= Ġcreate Multi List Panel ( all Inner Lists , Ġinner List Selection Listener ) ĊĠĠĠĠĠĠĠ Ġset Viewport View ( content ) ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ Ġoverride Ġfun Ġinterval Removed ( e : ĠList Data Event ?) Ġ{} ĊĊĠĠĠĠĠ Ġoverride Ġfun Ġinterval Added ( e : ĠList Data Event ?) Ġ{} ĊĠĠĠ Ġ}) ĊĠĠĠ Ġsection List . selection Mode Ġ= ĠList Selection Model . SINGLE _ SELECTION ĊĠĠĠ Ġsection List . selectedIndex Ġ= Ġ 0 ĊĠĠĠ Ġsection List . cell Renderer Ġ= Ġcreate Section Cell Renderer () ĊĠĠĠ Ġsection List . add List Selection Listener Ġ{ ĊĠĠĠĠĠ Ġval Ġselected Value Ġ= Ġsection List . selected Value ĊĠĠĠĠĠ Ġif Ġ( selected Value Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġviewport . view Position Ġ= Ġselected Value . header . location ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġvertical ScrollBar Policy Ġ= ĠJ ScrollPane . VERTICAL _ SCROLL BAR _ ALWAYS ĊĠĠĠ Ġadd Mouse Listener ( object Ġ: ĠMouse Adapter () Ġ{ ĊĠĠĠĠĠ Ġoverride Ġfun Ġmouse Clicked ( p 0 : ĠMouseEvent ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġfocus Inner List () ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}) ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠF oc uses Ġthe Ġfirst Ġlist Ġwith Ġa Ġselected Ġitem , Ġor Ġjust Ġthe Ġfirst Ġlist Ġif Ġthere 's Ġno Ġselection . ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġfun Ġfocus Inner List () Ġ{ ĊĠĠĠ Ġ( all Inner Lists . first OrNull Ġ{ Ġit . selectedIndex Ġ!= Ġ- 1 Ġ} Ġ?: Ġall Inner Lists . first OrNull ()) ?. request Focus In Window () ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠCreates Ġa Ġ[ List Selection Listener ] Ġthat Ġclears Ġthe Ġselection Ġof ĊĠĠ Ġ* Ġall Ġlists Ġexcept Ġthe Ġone Ġwhich Ġis Ġthe Ġsource Ġof Ġthe Ġevent . ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġfun Ġcreate List Selection Listener (): ĠList Selection Listener Ġ{ ĊĠĠĠ Ġreturn ĠList Selection Listener Ġ{ Ġevent Ġ-> ĊĠĠĠĠĠ Ġif Ġ(! list Selection Changing ) Ġ{ ĊĠĠĠĠĠĠĠ Ġlist Selection Changing Ġ= Ġtrue ĊĠĠĠĠĠĠĠ Ġall Inner Lists ĊĠĠĠĠĠĠĠĠĠ Ġ. filter Not Ġ{ Ġit Ġ== Ġevent . source Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ. forEach Ġ{ Ġit . clear Selection () Ġ} ĊĠĠĠĠĠĠĠ Ġlist Selection Changing Ġ= Ġfalse ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠSets Ġthe Ġ[ List Cell Renderer ] Ġof Ġthe Ġsection Ġlist ĊĠĠ Ġ* ĊĠĠ Ġ* Ġ@ see Ġsections Component ĊĠĠ Ġ*/ ĊĠ Ġfun Ġset Section List Cell Renderer ( renderer : ĠList Cell Renderer < Section <* >>) Ġ{ ĊĠĠĠ Ġsection List . cell Renderer Ġ= Ġrenderer ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠCreates Ġthe Ġdefault Ġ[ List Cell Renderer ] Ġfor Ġthe Ġsection Ġlist Ġwhich Ġjust Ġdisplays Ġthe Ġname ĊĠĠ Ġ* Ġof Ġthe Ġsection Ġin Ġa ĠJLabel ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġfun Ġcreate Section Cell Renderer (): ĠCo lo red List Cell Renderer < Section <* >> Ġ{ ĊĠĠĠ Ġreturn Ġobject Ġ: ĠCo lo red List Cell Renderer < Section <* >>() Ġ{ ĊĠĠĠĠĠ Ġoverride Ġfun Ġcustomize Cell Renderer ( ĊĠĠĠĠĠĠĠ Ġlist : ĠJ List < out ĠSection <* >>, ĊĠĠĠĠĠĠĠ Ġvalue : ĠSection < *> ?, ĊĠĠĠĠĠĠĠ Ġindex : ĠInt , ĊĠĠĠĠĠĠĠ Ġselected : ĠBoolean , ĊĠĠĠĠĠĠĠ Ġhas Focus : ĠBoolean ĊĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġappend ( value ?. name Ġ?: Ġ"") ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġcreate Multi List Panel ( ĊĠĠĠ Ġall Inner Lists : ĠMutable List < J List <* >>, ĊĠĠĠ Ġselection Listener : ĠList Selection Listener ĊĠ Ġ): ĠJ Component Ġ{ ĊĠĠĠ Ġreturn ĠJPanel ( multi L is LayoutManager ). apply { ĊĠĠĠĠĠ Ġbackground Ġ= Ġthis @ Section List . background ĊĠĠĠĠĠ Ġfor Ġ( section Ġin Ġmodel . sections ) Ġ{ ĊĠĠĠĠĠĠĠ Ġall Inner Lists Ġ+= Ġsection . list ĊĠĠĠĠĠĠĠ Ġsection . list . add List Selection Listener ( selection Listener ) ĊĠĠĠĠĠĠĠ Ġsection . list . add Focus Listener ( focus Listener ) ĊĠĠĠĠĠĠĠ Ġadd ( section . header ) ĊĠĠĠĠĠĠĠ Ġadd ( section . list ) ĊĠĠĠĠĠĠĠ Ġadd ( Box . create Vertical Str ut ( lists Gap )) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġfun Ġget Lists (): ĠList < J List <* >> Ġ{ ĊĠĠĠ Ġreturn Ġall Inner Lists ĊĠ Ġ} ĊĊĠ Ġvar Ġselected Value : ĠAny ? ĊĠĠĠ Ġget () Ġ= Ġall Inner Lists . first OrNull Ġ{ Ġit . selected Value Ġ!= Ġnull Ġ} ?. selected Value ĊĠĠĠ Ġset ( value ) Ġ= Ġall Inner Lists . forEach Ġ{ ĊĠĠĠĠĠ Ġlist Selection Changing Ġ= Ġtrue ĊĠĠĠĠĠ Ġit . setSelected Value ( value , Ġfalse ) ĊĠĠĠĠĠ Ġlist Selection Changing Ġ= Ġfalse ĊĠĠĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠRepresent Ġthe Ġselected Ġindices Ġfor Ġeach Ġinner Ġ[ J List ] ĊĠĠ Ġ* Ġ@ see ĠJ List . getSelected Indices ĊĠĠ Ġ* Ġ@ see ĠJ List . setSelected Indices ĊĠĠ Ġ*/ ĊĠ Ġvar Ġselected Indices : ĠList < IntArray ?> ĊĠĠĠ Ġget () Ġ= Ġall Inner Lists . map Ġ{ Ġit . selected Indices Ġ} ĊĠĠĠ Ġset ( indices By List ) Ġ= Ġindices By List . zip ( all Inner Lists ). forEach Ġ{ Ġ( indices , Ġlist ) Ġ-> ĊĠĠĠĠĠ Ġlist Selection Changing Ġ= Ġtrue ĊĠĠĠĠĠ Ġlist . selected Indices Ġ= Ġindices Ġ?: ĠEMPTY _ SELECTION _ ARRAY ĊĠĠĠĠĠ Ġlist Selection Changing Ġ= Ġfalse ĊĠĠĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠPair Ġof Ġthe Ġindex Ġof Ġthe Ġfirst Ġselected Ġinner Ġ[ J List ] Ġto Ġits Ġfirst Ġselected Ġindex ĊĠĠ Ġ* Ġ@ see ĠJ List . setSelected Index ĊĠĠ Ġ* Ġ@ see ĠJ List . getSelected Index ĊĠĠ Ġ*/ ĊĠ Ġvar Ġselected Index : ĠPair < Int , ĠInt >? ĊĠĠĠ Ġget () Ġ{ ĊĠĠĠĠĠ Ġval ĠindexOf Selected List Ġ= Ġall Inner Lists . indexOf First Ġ{ Ġit . selectedIndex Ġ!= Ġ- 1 Ġ} ĊĠĠĠĠĠ Ġif Ġ( indexOf Selected List Ġ== Ġ- 1 ) Ġreturn Ġnull ĊĠĠĠĠĠ Ġreturn ĠindexOf Selected List Ġto Ġall Inner Lists [ indexOf Selected List ]. selectedIndex ĊĠĠĠ Ġ} ĊĠĠĠ Ġset ( list To Index ) Ġ{ ĊĠĠĠĠĠ Ġif Ġ( list To Index Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġ( list , Ġindex ) Ġ= Ġlist To Index ĊĠĠĠĠĠĠĠ Ġall Inner Lists . get OrNull ( list )?. selectedIndex Ġ= Ġindex ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠĠĠ Ġall Inner Lists . forEach Ġ{ Ġit . selectedIndex Ġ= Ġ- 1 Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġoverride Ġfun Ġset Background ( bg : ĠColor ?) Ġ{ ĊĠĠĠ Ġ@ Suppress (" UN NE C ESS ARY _ SAFE _ CALL ") ĊĠĠĠ Ġcontent ?. background Ġ= Ġbg ĊĠĠĠ Ġviewport ?. background Ġ= Ġbg ĊĠĠĠ Ġsuper . setBackground ( bg ) ĊĠ Ġ} ĊĊĠ Ġfun Ġscroll To Selection () Ġ{ ĊĠĠĠ Ġval Ġ( list Index , Ġitem Index ) Ġ= Ġselected Index Ġ?: Ġreturn ĊĠĠĠ ĠScroll ing Util . ensure Index Is Visible ( all Inner Lists [ list Index ], Ġitem Index , Ġ 1 ) ĊĠ Ġ} ĊĊĠ Ġoverride Ġfun Ġdo Layout () Ġ{ ĊĠĠĠ Ġviewport . view ?. take If Ġ{ Ġit Ġis ĠContainer Ġ} ?. let Ġ{ Ġcontent Ġ-> ĊĠĠĠĠĠ Ġval Ġcontent Height Ġ= Ġmulti L is LayoutManager . preferred Layout Size ( content Ġas ĠContainer ). height ĊĠĠĠĠĠ Ġval Ġscroll Pref Size Ġ= Ġpreferred Size ĊĠĠĠĠĠ Ġif Ġ( scroll Pref Size Ġ== Ġnull Ġ|| Ġcontent Height Ġ!= Ġscroll Pref Size . height Ġ|| Ġcontent Height Ġ!= Ġmaximum Size . height ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠHave Ġscroll Ġpane Ġfit Ġto Ġthe Ġheight Ġof Ġits Ġcontents . ĊĠĠĠĠĠĠĠ Ġpreferred Size Ġ= ĠDimension ( scroll Pref Size . width , Ġcontent Height ) ĊĠĠĠĠĠĠĠ Ġmaximum Size Ġ= ĠDimension ( Int . MAX _ VALUE , Ġcontent Height ) ĊĠĠĠĠĠĠĠ Ġ// ĠTrigger Ġa Ġlayout Ġin Ġthe Ġparent Ġfor Ġthe Ġnew Ġdimensions . ĊĠĠĠĠĠĠĠ Ġparent ?. re validate () ĊĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġsuper . do Layout () ĊĠ Ġ} Ċ } Ċ Ċ class ĠSection ListModel Ġ: ĠList Model < Section <* >> Ġ{ ĊĊĠ Ġval Ġsections : ĠMutable List < Section <* >> Ġ= Ġmutable ListOf () ĊĠ Ġprivate Ġval Ġdata Listeners Ġ= Ġmutable ListOf < List Data Listener >() ĊĊĠ Ġoverride Ġfun Ġget ElementAt ( index : ĠInt ) Ġ= Ġsections [ index ] ĊĊĠ Ġoverride Ġfun Ġget Size () Ġ= Ġsections . size ĊĊĠ Ġoverride Ġfun Ġadd List Data Listener ( listener : ĠList Data Listener ?) Ġ{ ĊĠĠĠ Ġif Ġ(! data Listeners . contains ( listener Ġ?: Ġreturn )) Ġ{ ĊĠĠĠĠĠ Ġdata Listeners . add ( listener ) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġoverride Ġfun Ġremove List Data Listener ( listener : ĠList Data Listener ?) Ġ{ ĊĠĠĠ Ġdata Listeners . remove ( listener Ġ?: Ġreturn ) ĊĠ Ġ} ĊĊĠ Ġfun Ġadd Section ( section : ĠSection <* >) Ġ{ ĊĠĠĠ Ġsections Ġ+= Ġsection ĊĠĠĠ Ġdata Listeners . forEach Ġ{ Ġit . contents Changed ( List Data Event ( this , ĠList Data Event . CONTENTS _ CHANGED , Ġ 0 , Ġsections . size )) Ġ} ĊĠ Ġ} ĊĊĠ Ġfun Ġadd Sections ( new Sections : ĠList < Section <* >>) Ġ{ ĊĠĠĠ Ġsections Ġ+= Ġnew Sections ĊĠĠĠ Ġdata Listeners . forEach Ġ{ Ġit . contents Changed ( List Data Event ( this , ĠList Data Event . CONTENTS _ CHANGED , Ġ 0 , Ġsections . size )) Ġ} ĊĠ Ġ} ĊĊĠ Ġfun Ġclear () Ġ{ ĊĠĠĠ Ġsections . clear () ĊĠĠĠ Ġdata Listeners . forEach Ġ{ Ġit . contents Changed ( List Data Event ( this , ĠList Data Event . CONTENTS _ CHANGED , Ġ 0 , Ġsections . size )) Ġ} ĊĠ Ġ} Ċ } Ċ Ċ interface ĠSection < T > Ġ{ ĊĠ Ġvar Ġname : ĠString ĊĠ Ġvar Ġlist : ĠJ List < T > ĊĠ Ġvar Ġheader : ĠJ Component Ċ } Ċ Ċ class ĠSimple Section < T >( ĊĠ Ġoverride Ġvar Ġname : ĠString Ġ= Ġ"", ĊĠ Ġoverride Ġvar Ġlist : ĠJ List < T >, ĊĠ Ġoverride Ġvar Ġheader : ĠJ Component Ġ= ĠJLabel ( name ) Ċ ) Ġ: ĠSection < T > Ċ