/* Ċ Ġ* ĠCopyright Ġ 2 0 0 0 - 2 0 1 9 ĠJetBrains Ġs . r . o . ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠApache Ġ 2 . 0 Ġlicense Ġthat Ġcan Ġbe Ġfound Ġin Ġthe ĠLICENSE Ġfile . Ċ Ġ*/ Ċ Ċ package Ġorg . intellij . data vis . r . in lay s Ċ Ċ import Ġcom . intellij . ide . ui . UI Settings Ċ import Ġcom . intellij . openapi . application . Application Manager Ċ import Ġcom . intellij . openapi . application . Modal ity State Ċ import Ġcom . intellij . openapi . application . Read Action Ċ import Ġcom . intellij . openapi . application . invoke Later Ċ import Ġcom . intellij . openapi . editor . Editor Ċ import Ġcom . intellij . openapi . editor . Fold Region Ċ import Ġcom . intellij . openapi . editor . In lay Ċ import Ġcom . intellij . openapi . editor . event . Caret Event Ċ import Ġcom . intellij . openapi . editor . event . Caret Listener Ċ import Ġcom . intellij . openapi . editor . event . Document Event Ċ import Ġcom . intellij . openapi . editor . event . Document Listener Ċ import Ġcom . intellij . openapi . editor . ex . Editor G utter Component Ex Ċ import Ġcom . intellij . openapi . editor . ex . Fold ing Listener Ċ import Ġcom . intellij . openapi . editor . ex . util . Editor Scrolling Position Keeper Ċ import Ġcom . intellij . openapi . editor . impl . Editor Impl Ċ import Ġcom . intellij . openapi . project . Project Ċ import Ġcom . intellij . openapi . util . Dis poser Ċ import Ġcom . intellij . openapi . util . Key Ċ import Ġcom . intellij . openapi . util . Text Range Ċ import Ġcom . intellij . psi . Psi Document Manager Ċ import Ġcom . intellij . psi . Psi Element Ċ import Ġcom . intellij . psi . util . Psi Tree Util Ċ import Ġcom . intellij . util . concurrency . Future Result Ċ import Ġcom . intellij . util . concurrency . Non U rg ent Executor Ċ import Ġcom . intellij . util . ui . update . Mer ging Update Queue Ċ import Ġcom . intellij . util . ui . update . Update Ċ import Ġorg . intellij . data vis . r . in lay s . components . In lay Progress Status Ċ import Ġorg . intellij . data vis . r . ui . Ui Customizer Ċ import Ġorg . jetbrains . annotations . Test Only Ċ import Ġorg . jetbrains . concurrency . C ancellable Promise Ċ import Ġjava . awt . Point Ċ import Ġjava . awt . event . Component Adapter Ċ import Ġjava . awt . event . Component Event Ċ import Ġjava . util . concurrent . Future Ċ import Ġkotlin . math . max Ċ import Ġkotlin . math . min Ċ Ċ /** Ċ Ġ* ĠMan ages Ġin lay s . Ċ Ġ* Ċ Ġ* ĠOn Ġproject Ġload Ġsub scri bes Ċ Ġ* ĠĠĠ Ġon Ġeditor Ġopening / closing . Ċ Ġ* ĠĠĠ Ġon Ġadding / re moving Ġnotebook Ġcells Ċ Ġ* ĠĠĠ Ġon Ġany Ġdocument Ġchanges Ċ Ġ* ĠĠĠ Ġon Ġfold ing Ġactions Ċ Ġ* Ċ Ġ* ĠOn Ġeditor Ġopen Ġchecks Ġthe ĠP SI Ġstructure Ġand Ġrest ores Ġsaved Ġin lay s . Ċ Ġ* Ċ Ġ* ĠTo Do Ġshould Ġbe Ġsplit Ġinto ĠIn lay s Manager Ġwith Ġall Ġbasics Ġand ĠNotebook In lay s Manager Ġwith Ġall Ġspecific . Ċ Ġ*/ Ċ class ĠEditor In lay s Manager ( val Ġproject : ĠProject , Ġprivate Ġval Ġeditor : ĠEditor Impl , Ġval Ġdescriptor : ĠIn lay Element Descriptor ) Ġ{ ĊĊĠ Ġprivate Ġval Ġin lay s : ĠMutable Map < Psi Element , ĠNotebook In lay Component > Ġ= ĠLinkedHashMap () ĊĠ Ġprivate Ġval Ġin lay Elements Ġ= ĠLinked HashSet < Psi Element >() ĊĠ Ġprivate Ġval Ġscroll Keeper : ĠEditor Scrolling Position Keeper Ġ= ĠEditor Scrolling Position Keeper ( editor ) ĊĠ Ġprivate Ġval Ġviewport Queue Ġ= ĠMer ging Update Queue ( VIEW PORT _ TASK _ NAME , ĠVIEW PORT _ TIME _ SPAN , Ġtrue , Ġnull , Ġproject ) ĊĠ Ġ@ Volatile Ġprivate Ġvar Ġtoolbar Update Scheduled : ĠBoolean Ġ= Ġfalse ĊĊĠ Ġinit Ġ{ ĊĠĠĠ Ġadd Resize Listener () ĊĠĠĠ Ġadd Caret Listener () ĊĠĠĠ Ġadd Fold ing Listener () ĊĠĠĠ Ġadd Document Listener () ĊĠĠĠ Ġadd Viewport Listener () ĊĠĠĠ Ġeditor . settings . is Right Margin Shown Ġ= Ġfalse ĊĠĠĠ ĠUI Settings . instance . show Editor ToolTip Ġ= Ġfalse ĊĠĠĠ ĠMouse Wheel Utils . wrap Editor Mouse Wheel Listeners ( editor ) ĊĠĠĠ Ġrestore Toolbar s (). on Success Ġ{ Ġrestore Outputs () Ġ} ĊĠĠĠ Ġon Caret Position Changed () ĊĠĠĠ ĠApplication Manager . getApplication (). invoke Later Ġ{ ĊĠĠĠĠĠ Ġif Ġ( Dis poser . is Disposed ( editor . dis posable )) Ġreturn @ invoke Later ĊĠĠĠĠĠ Ġupdate In lay Components Width () ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġfun Ġdispose () Ġ{ ĊĠĠĠ Ġin lay s . values . forEach Ġ{ ĊĠĠĠĠĠ Ġit . dispose In lay () ĊĠĠĠĠĠ Ġit . dispose () ĊĠĠĠ Ġ} ĊĠĠĠ Ġin lay s . clear () ĊĠĠĠ Ġin lay Elements . clear () ĊĠ Ġ} ĊĊĠ Ġfun Ġupdate Cell ( psi : ĠPsi Element , Ġin lay Outputs : ĠList < In lay Output >? Ġ= Ġnull , Ġcreate Text Output : ĠBoolean Ġ= Ġfalse ): ĠFuture < Unit > Ġ{ ĊĠĠĠ Ġval Ġresult Ġ= ĠFuture Result < Unit >() ĊĠĠĠ Ġif Ġ( Application Manager . getApplication (). is UnitTest Mode Ġ&& Ġ! isEnabled In Tests ) Ġreturn Ġresult . apply Ġ{ Ġset ( Unit ) Ġ} ĊĠĠĠ ĠApplication Manager . getApplication (). invoke Later Ġ{ ĊĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( Dis poser . is Disposed ( editor . dis posable )) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġresult . set ( Unit ) ĊĠĠĠĠĠĠĠĠĠ Ġreturn @ invoke Later ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġif Ġ(! psi . isValid ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġget In lay Component ( psi )?. let Ġ{ Ġold In lay Ġ-> Ġremove In lay ( old In lay , Ġcleanup Ġ= Ġfalse ) Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġresult . set ( Unit ) ĊĠĠĠĠĠĠĠĠĠ Ġreturn @ invoke Later ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġif Ġ( is Output Position Collapsed ( psi )) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġresult . set ( Unit ) ĊĠĠĠĠĠĠĠĠĠ Ġreturn @ invoke Later ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġoutputs Ġ= Ġin lay Outputs Ġ?: Ġdescriptor . getIn lay Outputs ( psi ) ĊĠĠĠĠĠĠĠ Ġif Ġ( outputs Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġresult . set ( Unit ) ĊĠĠĠĠĠĠĠĠĠ Ġreturn @ invoke Later ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġscroll Keeper . save Position () ĊĠĠĠĠĠĠĠ Ġget In lay Component ( psi )?. let Ġ{ Ġold In lay Ġ-> Ġremove In lay ( old In lay , Ġcleanup Ġ= Ġfalse ) Ġ} ĊĠĠĠĠĠĠĠ Ġif Ġ( outputs . isEmpty () Ġ&& Ġ! createText Output ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġresult . set ( Unit ) ĊĠĠĠĠĠĠĠĠĠ Ġreturn @ invoke Later ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġcomponent Ġ= Ġadd In lay Component ( psi ) ĊĠĠĠĠĠĠĠ Ġif Ġ( outputs . isNotEmpty ()) Ġadd In lay Outputs ( component , Ġoutputs ) ĊĠĠĠĠĠĠĠ Ġif Ġ( createText Output ) Ġcomponent . create Output Component () ĊĠĠĠĠĠĠĠ Ġscroll Keeper . restore Position ( true ) ĊĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠ Ġresult . set ( Unit ) ĊĠĠĠĠĠĠĠ Ġthrow Ġe ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ ĠApplication Manager . getApplication (). invoke Later Ġ{ ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġscroll Keeper . save Position () ĊĠĠĠĠĠĠĠĠĠ Ġupdate In lay s () ĊĠĠĠĠĠĠĠĠĠ Ġscroll Keeper . restore Position ( true ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġfinally Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġresult . set ( Unit ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġresult ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġis Output Position Collapsed ( psi Cell : ĠPsi Element ): ĠBoolean Ġ= ĊĠĠĠ Ġeditor . fold ing Model . is Offset Collapsed ( descriptor . getIn lay Offset ( psi Cell )) ĊĊĠ Ġfun Ġadd Text To In lay ( psi : ĠPsi Element , Ġmessage : ĠString , Ġoutput Type : ĠKey <* >) Ġ{ ĊĠĠĠ Ġinvoke Later Ġ{ ĊĠĠĠĠĠ Ġscroll Keeper . save Position () ĊĠĠĠĠĠ Ġget In lay Component ( psi )?. add Text ( message , Ġoutput Type ) ĊĠĠĠĠĠ Ġscroll Keeper . restore Position ( true ) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġfun Ġupdate In lay Progress Status ( psi : ĠPsi Element , Ġprogress Status : ĠIn lay Progress Status ): ĠFuture < Unit > Ġ{ ĊĠĠĠ Ġval Ġresult Ġ= ĠFuture Result < Unit >() ĊĠĠĠ ĠApplication Manager . getApplication (). invoke Later Ġ{ ĊĠĠĠĠĠ Ġget In lay Component ( psi )?. update Progress Status ( progress Status ) ĊĠĠĠĠĠ Ġresult . set ( Unit ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġresult ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġupdate In lay s For Viewport () Ġ{ ĊĠĠĠ Ġinvoke Later Ġ{ ĊĠĠĠĠĠ Ġif Ġ( Dis poser . is Disposed ( editor . dis posable )) Ġreturn @ invoke Later ĊĠĠĠĠĠ Ġval Ġviewport Range Ġ= Ġcalculate Viewport Range ( editor ) ĊĠĠĠĠĠ Ġval Ġexpansion Range Ġ= Ġcalculate In lay Expansion Range ( editor , Ġviewport Range ) ĊĠĠĠĠĠ Ġfor Ġ( element Ġin Ġin lay Elements ) Ġ{ ĊĠĠĠĠĠĠĠ Ġupdate In lay For Viewport ( element , Ġviewport Range , Ġexpansion Range ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġupdate In lay For Viewport ( element : ĠPsi Element , Ġviewport Range : ĠInt Range , Ġexpansion Range : ĠInt Range ) Ġ{ ĊĠĠĠ Ġval Ġin lay Ġ= Ġin lay s [ element ] ĊĠĠĠ Ġif Ġ( in lay Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠ Ġval Ġbounds Ġ= Ġin lay . bounds ĊĠĠĠĠĠ Ġval ĠisIn Viewport Ġ= Ġbounds . y Ġ<= Ġviewport Range . last Ġ&& Ġbounds . y Ġ+ Ġbounds . height Ġ>= Ġviewport Range . first ĊĠĠĠĠĠ Ġin lay . on Viewport Change ( isIn Viewport ) ĊĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠ Ġif Ġ( element . text Range . start Offset Ġin Ġexpansion Range ) Ġ{ ĊĠĠĠĠĠĠĠ Ġupdate Cell ( element ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġadd In lay Outputs ( in lay Component : ĠNotebook In lay Component , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġin lay Outputs : ĠList < In lay Output >) Ġ{ ĊĠĠĠ Ġin lay Component . add In lay Outputs ( in lay Outputs ) Ġ{ Ġremove In lay ( in lay Component ) Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġremove In lay ( in lay Component : ĠNotebook In lay Component , Ġcleanup : ĠBoolean Ġ= Ġtrue ) Ġ{ ĊĠĠĠ Ġval Ġcell Ġ= Ġin lay Component . cell ĊĠĠĠ Ġif Ġ( cleanup Ġ&& Ġcell . isValid ) Ġdescriptor . cleanup ( cell ) ĊĠĠĠ Ġin lay Component . parent ?. remove ( in lay Component ) ĊĠĠĠ Ġin lay Component . dispose In lay () ĊĠĠĠ Ġin lay Component . dispose () ĊĠĠĠ Ġin lay s . remove ( cell ) ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġadd Fold ing Listener () Ġ{ ĊĠĠĠ Ġdata Ġclass ĠRegion ( val Ġtext Range : ĠText Range , Ġval Ġis Expanded : ĠBoolean ) ĊĠĠĠ Ġval Ġlistener Ġ= Ġobject Ġ: ĠFold ing Listener Ġ{ ĊĠĠĠĠĠ Ġprivate Ġval Ġregions Ġ= ĠArrayList < Region >() ĊĊĠĠĠĠĠ Ġoverride Ġfun Ġon Fold Region StateChange ( region : ĠFold Region ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif ( region . isValid ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġregions . add ( Region ( Text Range . create ( region . start Offset , Ġregion . end Offset ), Ġregion . is Expanded )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ Ġoverride Ġfun Ġon Fold Processing End () Ġ{ ĊĠĠĠĠĠĠĠ Ġin lay s . filter Ġ{ Ġpair Ġ-> Ġis Output Position Collapsed ( pair . key ) Ġ}. forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġremove In lay ( it . value , Ġcleanup Ġ= Ġfalse ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġin lay Elements . filter Ġ{ Ġkey Ġ-> Ġregions . filter Ġ{ Ġit . is Expanded Ġ}. any Ġ{ Ġkey . text Range . intersect s ( it . text Range ) Ġ} Ġ}. forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġupdate Cell ( it ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġregions . clear () ĊĠĠĠĠĠĠĠ Ġupdate In lay s () ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġeditor . fold ing Model . addListener ( listener , Ġeditor . dis posable ) ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġadd Document Listener () Ġ{ ĊĠĠĠ Ġeditor . document . add Document Listener ( object Ġ: ĠDocument Listener Ġ{ ĊĠĠĠĠĠ Ġoverride Ġfun Ġdocument Changed ( event : ĠDocument Event ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( Dis poser . is Disposed ( project )) Ġreturn ĊĠĠĠĠĠĠĠ Ġif Ġ(! toolbar Update Scheduled ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġtoolbar Update Scheduled Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠ ĠPsi Document Manager . getInstance ( project ). perform For Commit ted Document ( editor . document ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġschedule Interval Update ( event . offset , Ġevent . new Fragment . length ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtoolbar Update Scheduled Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġif Ġ(! descriptor . should Update In lay s ( event )) Ġreturn ĊĠĠĠĠĠĠĠ ĠPsi Document Manager . getInstance ( project ). perform For Commit ted Document ( editor . document ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġupdate In lay s () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}, Ġeditor . dis posable ) ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġschedule Interval Update ( offset : ĠInt , Ġlength : ĠInt ) Ġ{ ĊĠĠĠ Ġval Ġpsi File Ġ= Ġdescriptor . psi File ĊĠĠĠ Ġvar Ġnode Ġ= Ġpsi File . node . find Leaf ElementAt ( offset )?. psi ĊĠĠĠ Ġwhile Ġ( node Ġ!= Ġnull Ġ&& Ġnode . parent Ġ!= Ġpsi File ) Ġ{ ĊĠĠĠĠĠ Ġnode Ġ= Ġnode . parent ĊĠĠĠ Ġ} ĊĠĠĠ Ġin lay Elements . filter Ġ{ Ġ! it . isValid Ġ}. forEach Ġ{ Ġget In lay Component ( it )?. let Ġ{ Ġin lay Ġ-> Ġremove In lay ( in lay ) Ġ} Ġ} ĊĠĠĠ Ġin lay Elements . remove If Ġ{ Ġ! it . isValid Ġ} ĊĠĠĠ Ġwhile Ġ( node Ġ!= Ġnull Ġ&& Ġnode . text Range . start Offset Ġ< Ġoffset Ġ+ Ġlength ) Ġ{ ĊĠĠĠĠĠ ĠPsi Tree Util . collect Elements ( node ) Ġ{ Ġpsi Ġ-> Ġdescriptor . isIn lay Element ( psi ) Ġ}. forEach Ġ{ Ġpsi Ġ-> ĊĠĠĠĠĠĠĠ Ġin lay Elements . add ( psi ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġnode Ġ= Ġnode . next Sibling ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĠOn Ġeditor Ġresize Ġall Ġin lay s Ġgot Ġwidth Ġof Ġeditor . Ġ*/ ĊĠ Ġprivate Ġfun Ġadd Resize Listener () Ġ{ ĊĠĠĠ Ġeditor . component . addComponent Listener ( object Ġ: ĠComponent Adapter () Ġ{ ĊĠĠĠĠĠ Ġoverride Ġfun Ġcomponent Res ized ( e : ĠComponent Event ) Ġ{ ĊĠĠĠĠĠĠĠ Ġupdate In lay Components Width () ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}) ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġadd Viewport Listener () Ġ{ ĊĠĠĠ Ġeditor . scroll Pane . viewport . add ChangeListener Ġ{ ĊĠĠĠĠĠ Ġviewport Queue . queue ( object Ġ: ĠUpdate ( VIEW PORT _ TASK _ IDENTITY ) Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġrun () Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġupdate In lay s For Viewport () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ}) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġrestore Outputs () Ġ{ ĊĠĠĠ Ġupdate In lay s For Viewport () ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġrestore Toolbar s (): ĠC ancellable Promise < *> Ġ{ ĊĠĠĠ Ġval Ġin lay s Psi Elements Ġ= ĠArrayList < Psi Element >() ĊĠĠĠ Ġreturn ĠRead Action . non Blocking Ġ{ ĊĠĠĠĠĠ ĠPsi Tree Util . process Elements ( descriptor . psi File ) Ġ{ Ġelement Ġ-> ĊĠĠĠĠĠĠĠ Ġif Ġ( descriptor . isIn lay Element ( element )) Ġin lay s Psi Elements . add ( element ) ĊĠĠĠĠĠĠĠ Ġtrue ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}. finish On Ui Thread ( Modal ity State . NON _ MOD AL ) Ġ{ ĊĠĠĠĠĠ Ġin lay Elements . clear () ĊĠĠĠĠĠ Ġin lay Elements . addAll ( in lay s Psi Elements ) ĊĠĠĠ Ġ}. in Smart Mode ( project ). submit ( Non U rg ent Executor . getInstance ()) ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġget In lay Component By Offset ( offset : ĠInt ): ĠNotebook In lay Component ? Ġ{ ĊĠĠĠ Ġreturn Ġif Ġ( offset Ġ== Ġeditor . document . text Length ) ĊĠĠĠĠĠ Ġin lay s . entries . first OrNull Ġ{ Ġit . key . text Range . contains Offset ( offset ) Ġ} ?. value ĊĠĠĠ Ġelse ĊĠĠĠĠĠ Ġin lay s . entries . first OrNull Ġ{ Ġit . key . text Range . contains ( offset ) Ġ} ?. value ĊĠ Ġ} ĊĊĠ Ġ/** ĠAdd Ġcaret Ġlistener Ġfor Ġeditor Ġto Ġdraw Ġhighlighted Ġbackground Ġfor Ġpsi Cell Ġunder Ġcaret . Ġ*/ ĊĠ Ġprivate Ġfun Ġadd Caret Listener () Ġ{ ĊĠĠĠ Ġeditor . caret Model . add Caret Listener ( object Ġ: ĠCare t Listener Ġ{ ĊĊĠĠĠĠĠ Ġoverride Ġfun Ġcaret Position Changed ( e : ĠCare t Event ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( editor . caret Model . primary Caret Ġ!= Ġe . caret ) Ġreturn ĊĠĠĠĠĠĠĠ Ġon Caret Position Changed () ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}, Ġeditor . dis posable ) ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġon Caret Position Changed () Ġ{ ĊĊĠĠĠ Ġif Ġ( editor . is Disposed ) Ġ{ ĊĠĠĠĠĠ Ġreturn ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġcell Under Caret Ġ= Ġget In lay Component By Offset ( editor . logical Position To Offset ( editor . caret Model . logical Position )) ĊĠĠĠ Ġif Ġ( cell Under Caret Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠ Ġin lay s . values . forEach Ġ{ Ġit . selected Ġ= Ġfalse Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠ Ġif Ġ(! cell Under Caret . selected ) Ġ{ ĊĠĠĠĠĠĠĠ Ġin lay s . values . forEach Ġ{ Ġit . selected Ġ= Ġfalse Ġ} ĊĠĠĠĠĠĠĠ Ġcell Under Caret . selected Ġ= Ġtrue ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĠWhen Ġwe Ġare Ġadding Ġor Ġremoving Ġparagraphs , Ġold Ġcells Ġcan Ġchange Ġtheir Ġtext Ġranges */ ĊĠ Ġprivate Ġfun Ġupdate In lay s () Ġ{ ĊĠĠĠ Ġin lay s . values . forEach Ġ{ Ġupdate In lay Position ( it ) Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġsetup In lay Component ( in lay Component : ĠNotebook In lay Component ) Ġ{ ĊĊĠĠĠ Ġfun Ġupdate In lay s In Editor ( editor : ĠEditor ) Ġ{ ĊĊĠĠĠĠĠ Ġval Ġend Ġ= Ġeditor . xy To Logical Position ( Point ( 0 , ĠInt . MAX _ VALUE )) ĊĠĠĠĠĠ Ġval Ġoffset End Ġ= Ġeditor . logical Position To Offset ( end ) ĊĊĠĠĠĠĠ Ġval Ġin lay s Ġ= Ġeditor . in lay Model . getBlock Elements InRange ( 0 , Ġoffset End ) ĊĊĠĠĠĠĠ Ġin lay s . forEach Ġ{ Ġin lay Ġ-> ĊĠĠĠĠĠĠĠ Ġif Ġ( in lay . renderer Ġis ĠIn lay Component ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġ( in lay . renderer Ġas ĠIn lay Component ). update Component Bounds ( in lay ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġin lay Component . before Height Changed Ġ= Ġ{ ĊĠĠĠĠĠ Ġscroll Keeper . save Position () ĊĠĠĠ Ġ} ĊĠĠĠ Ġin lay Component . after Height Changed Ġ= Ġ{ ĊĠĠĠĠĠ Ġupdate In lay s In Editor ( editor ) ĊĠĠĠĠĠ Ġscroll Keeper . restore Position ( true ) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĠAlign s Ġall Ġeditor Ġin lay s Ġto Ġfill Ġfull Ġwidth Ġof Ġeditor . Ġ*/ ĊĠ Ġprivate Ġfun Ġupdate In lay Components Width () Ġ{ ĊĠĠĠ Ġval Ġin lay Width Ġ= ĠIn lay Dimensions . calculate In lay Width ( editor ) ĊĠĠĠ Ġif Ġ( in lay Width Ġ> Ġ 0 ) Ġ{ ĊĠĠĠĠĠ Ġin lay s . values . forEach Ġ{ ĊĠĠĠĠĠĠĠ Ġit . setSize ( in lay Width , Ġit . height ) ĊĠĠĠĠĠĠĠ Ġit . in lay ?. update Size () ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĠIt Ġcould Ġbe Ġthat Ġuser Ġstarted Ġto Ġtype Ġbelow Ġin lay . ĠIn Ġthis Ġcase Ġwe Ġwill Ġdetect Ġnew Ġposition Ġand Ġperform Ġin lay Ġre position ing . Ġ*/ ĊĠ Ġprivate Ġfun Ġupdate In lay Position ( in lay Component : ĠNotebook In lay Component ) Ġ{ ĊĠĠĠ Ġ// Ġedited Cell Ġhere Ġcontains Ġold Ġtext . ĠThis Ġevent Ġwill Ġbe Ġprocessed Ġby ĠP SI Ġlater . ĊĠĠĠ Ġval Ġoffset Ġ= Ġdescriptor . getIn lay Offset ( in lay Component . cell ) ĊĠĠĠ Ġif Ġ( in lay Component . in lay !!. offset Ġ!= Ġoffset ) Ġ{ ĊĠĠĠĠĠ Ġin lay Component . dispose In lay () ĊĠĠĠĠĠ Ġval Ġin lay Ġ= Ġadd Block Element ( offset , Ġin lay Component ) ĊĠĠĠĠĠ Ġin lay Component . assign In lay ( in lay ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġin lay Component . update Component Bounds ( in lay Component . in lay !! ) ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġadd Block Element ( offset : ĠInt , Ġin lay Component : ĠNotebook In lay Component ): ĠIn lay < Notebook In lay Component > Ġ{ ĊĠĠĠ Ġreturn Ġeditor . in lay Model . add Block Element ( offset , Ġtrue , Ġfalse , ĠIN LAY _ PRIORITY , Ġin lay Component ) ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġadd In lay Component ( cell : ĠPsi Element ): ĠNotebook In lay Component Ġ{ ĊĊĠĠĠ Ġval Ġexisting In lay Ġ= Ġin lay s [ cell ] ĊĠĠĠ Ġif Ġ( existing In lay Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠ Ġthrow ĠException (" Cell Ġalready Ġadded .") ĊĠĠĠ Ġ} ĊĊĠĠĠ ĠIn lay Dimensions . init ( editor ) ĊĊĠĠĠ Ġval Ġoffset Ġ= Ġdescriptor . getIn lay Offset ( cell ) ĊĠĠĠ Ġval Ġin lay Component Ġ= ĠUi Customizer . instance . create Notebook In lay Component ( cell , Ġeditor ) ĊĊĠĠĠ Ġ// ĠOn Ġeditor Ġcreation Ġit Ġhas Ġ 0 Ġwidth ĊĠĠĠ Ġval Ġg utter Width Ġ= Ġ( editor . gutter Ġas ĠEditor G utter Component Ex ). width ĊĠĠĠ Ġvar Ġeditor Wide Width Ġ= Ġeditor . component . width Ġ- Ġin lay Component . width Ġ- Ġg utter Width Ġ- ĠIn lay Dimensions . right Border ĊĠĠĠ Ġif Ġ( editor Wide Width Ġ<= Ġ 0 ) Ġ{ ĊĠĠĠĠĠ Ġeditor Wide Width Ġ= ĠIn lay Dimensions . width ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġin lay Component . setBounds ( 0 , Ġeditor . offset To XY ( offset ). y Ġ+ Ġeditor . line Height , Ġeditor Wide Width , ĠIn lay Dimensions . small Height ) ĊĠĠĠ Ġeditor . content Component . add ( in lay Component ) ĊĠĠĠ Ġval Ġin lay Ġ= Ġadd Block Element ( offset , Ġin lay Component ) ĊĊĠĠĠ Ġin lay Component . assign In lay ( in lay ) ĊĠĠĠ Ġin lay s [ cell ] Ġ= Ġin lay Component ĊĊĠĠĠ Ġsetup In lay Component ( in lay Component ) ĊĊĠĠĠ Ġreturn Ġin lay Component ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġget In lay Component ( cell : ĠPsi Element ): ĠNotebook In lay Component ? Ġ{ ĊĠĠĠ Ġreturn Ġin lay s [ cell ] ĊĠ Ġ} ĊĊĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠ Ġprivate Ġconst Ġval ĠVIEW PORT _ TASK _ NAME Ġ= Ġ" On Ġviewport Ġchange " ĊĠĠĠ Ġprivate Ġconst Ġval ĠVIEW PORT _ TASK _ IDENTITY Ġ= Ġ" On Ġviewport Ġchange Ġtask " ĊĠĠĠ Ġprivate Ġconst Ġval ĠVIEW PORT _ TIME _ SPAN Ġ= Ġ 5 0 ĊĊĠĠĠ Ġconst Ġval ĠIN LAY _ PRIORITY Ġ= Ġ 0 ĊĊĠĠĠ Ġ@ Test Only ĊĠĠĠ Ġvar Ġis Enabled In Tests : ĠBoolean Ġ= Ġfalse ĊĠ Ġ} Ċ } Ċ Ċ const Ġval ĠVIEW PORT _ IN LAY _ RANGE Ġ= Ġ 2 0 Ċ Ċ fun Ġcalculate Viewport Range ( editor : ĠEditor Impl ): ĠInt Range Ġ{ ĊĠ Ġval Ġviewport Ġ= Ġeditor . scroll Pane . viewport ĊĠ Ġval Ġy Min Ġ= Ġviewport . view Position . y ĊĠ Ġval Ġy Max Ġ= Ġy Min Ġ+ Ġviewport . height ĊĠ Ġreturn Ġy Min Ġuntil Ġy Max Ċ } Ċ Ċ fun Ġcalculate In lay Expansion Range ( editor : ĠEditor Impl , Ġviewport Range : ĠInt Range ): ĠInt Range Ġ{ ĊĠ Ġval Ġstart Line Ġ= Ġeditor . xy To Logical Position ( Point ( 0 , Ġviewport Range . first )). line ĊĠ Ġval Ġend Line Ġ= Ġeditor . xy To Logical Position ( Point ( 0 , Ġviewport Range . last Ġ+ Ġ 1 )). line ĊĠ Ġval Ġstart Offset Ġ= Ġeditor . document . getLine Start Offset ( max ( start Line Ġ- ĠVIEW PORT _ IN LAY _ RANGE , Ġ 0 )) ĊĠ Ġval Ġend Offset Ġ= Ġeditor . document . getLine Start Offset ( max ( min ( end Line Ġ+ ĠVIEW PORT _ IN LAY _ RANGE , Ġeditor . document . line Count Ġ- Ġ 1 ), Ġ 0 )) ĊĠ Ġreturn Ġstart Offset .. end Offset Ċ }