@@ -234,7 +234,6 @@ class MinimapLayout {
234234 scrollHeight : number ,
235235 previousLayout : MinimapLayout | null
236236 ) : MinimapLayout {
237- // console.log(`create - ${viewportStartLineNumber}, ${viewportEndLineNumber}, ${viewportHeight}, ${viewportContainsWhitespaceGaps}, ${lineCount}, ${scrollTop}, ${scrollHeight}`);
238237 const pixelRatio = options . pixelRatio ;
239238 const minimapLineHeight = options . minimapLineHeight ;
240239 const minimapLinesFitting = Math . floor ( options . canvasInnerHeight / minimapLineHeight ) ;
@@ -502,9 +501,10 @@ export class Minimap extends ViewPart implements IMinimapModel {
502501 private _selections : Selection [ ] ;
503502 private _minimapSelections : Selection [ ] ;
504503
505- private _samplingRatio ! : number ;
506- private _minimapLines ! : number [ ] ;
507- private _isSampling = false ; //true;
504+ private _samplingRatio : number ;
505+ private _minimapLines : number [ ] ;
506+ private _isSampling = false ;
507+ private _shouldCheckSampling : boolean ;
508508
509509 public readonly tokensColorTracker : MinimapTokensColorTracker ;
510510 public options : MinimapOptions ;
@@ -517,7 +517,10 @@ export class Minimap extends ViewPart implements IMinimapModel {
517517 this . _selections = [ ] ;
518518 this . _minimapSelections = [ ] ;
519519
520- this . _recreateLineMapping ( ) ;
520+ this . _samplingRatio = 1 ;
521+ this . _minimapLines = [ ] ;
522+ this . _shouldCheckSampling = false ;
523+ this . _recreateLineSampling ( null ) ;
521524
522525 this . tokensColorTracker = MinimapTokensColorTracker . getInstance ( ) ;
523526 this . options = new MinimapOptions ( this . _context . configuration , this . _context . theme , this . tokensColorTracker , this . _isSampling ) ;
@@ -594,7 +597,8 @@ export class Minimap extends ViewPart implements IMinimapModel {
594597 if ( changeStartIndex <= changeEndIndex ) {
595598 this . _actual . onLinesChanged ( changeStartIndex + 1 , changeEndIndex + 1 ) ;
596599 }
597- return this . _checkMapping ( ) ;
600+ this . _shouldCheckSampling = true ;
601+ return true ;
598602 } else {
599603 return this . _actual . onLinesDeleted ( e . fromLineNumber , e . toLineNumber ) ;
600604 }
@@ -609,7 +613,8 @@ export class Minimap extends ViewPart implements IMinimapModel {
609613 }
610614 this . _minimapLines [ i ] += insertedLineCount ;
611615 }
612- return this . _checkMapping ( ) ;
616+ this . _shouldCheckSampling = true ;
617+ return true ;
613618 } else {
614619 return this . _actual . onLinesInserted ( e . fromLineNumber , e . toLineNumber ) ;
615620 }
@@ -651,7 +656,10 @@ export class Minimap extends ViewPart implements IMinimapModel {
651656 // --- end event handlers
652657
653658 public prepareRender ( ctx : RenderingContext ) : void {
654- // nothing to read
659+ if ( this . _shouldCheckSampling ) {
660+ this . _shouldCheckSampling = false ;
661+ this . _recreateLineSampling ( this . _minimapLines ) ;
662+ }
655663 }
656664
657665 public render ( ctx : RestrictedRenderingContext ) : void {
@@ -684,12 +692,23 @@ export class Minimap extends ViewPart implements IMinimapModel {
684692
685693 //#region IMinimapModel
686694
687- private _checkMapping ( ) : boolean {
688- // console.log(`TODO: I SHOULD ADJUST THE MAPPING!!!`, this._minimapLines);
689- return false ;
695+ private _createLineSampling ( minimapLineCount : number , modelLineCount : number , ratio : number ) : number [ ] {
696+ let result : number [ ] = [ ] ;
697+ result [ 0 ] = 1 ;
698+ if ( minimapLineCount > 1 ) {
699+ const halfRatio = ratio / 2 ;
700+ for ( let i = 0 , lastIndex = minimapLineCount - 1 ; i < lastIndex ; i ++ ) {
701+ result [ i ] = Math . round ( i * ratio + halfRatio ) ;
702+ }
703+ result [ minimapLineCount - 1 ] = modelLineCount ;
704+ }
705+ return result ;
690706 }
691707
692- private _recreateLineMapping ( ) : void {
708+ private _recreateLineSampling ( oldMinimapLines : number [ ] | null ) : void {
709+ // generate at most 10 events, if there are more than 10 changes, just flush all previous data
710+ const MAX_EVENT_COUNT = 10 ;
711+
693712 const options = this . _context . configuration . options ;
694713 const layoutInfo = options . get ( EditorOption . layoutInfo ) ;
695714 const pixelRatio = options . get ( EditorOption . pixelRatio ) ;
@@ -702,10 +721,113 @@ export class Minimap extends ViewPart implements IMinimapModel {
702721 const minimapLineCount = Math . floor ( modelLineCount / desiredRatio ) ;
703722 const ratio = modelLineCount / minimapLineCount ;
704723
724+ if ( ! oldMinimapLines ) {
725+ this . _minimapLines = this . _createLineSampling ( minimapLineCount , modelLineCount , ratio ) ;
726+ this . _samplingRatio = ratio ;
727+ return ;
728+ }
729+
730+ const halfRatio = ratio / 2 ;
731+ const oldLength = oldMinimapLines . length ;
705732 let result : number [ ] = [ ] ;
733+ let oldIndex = 0 ;
734+ let oldDeltaLineCount = 0 ;
735+ let minModelLineNumber = 1 ;
736+ let eventCount = 0 ;
737+ let currentDeleteStart = 0 , currentDeleteEnd = 0 ;
738+ let currentInsertStart = 0 , currentInsertEnd = 0 ;
706739 for ( let i = 0 ; i < minimapLineCount ; i ++ ) {
707- const desiredLine = Math . min ( modelLineCount , Math . round ( ( i + 1 ) * ratio ) ) ;
708- result [ i ] = desiredLine ;
740+ const fromModelLineNumber = Math . max ( minModelLineNumber , Math . round ( i * ratio ) ) ;
741+ const toModelLineNumber = Math . max ( fromModelLineNumber , Math . round ( ( i + 1 ) * ratio ) ) ;
742+
743+ while ( oldIndex < oldLength && oldMinimapLines [ oldIndex ] < fromModelLineNumber ) {
744+ if ( eventCount < MAX_EVENT_COUNT ) {
745+ if ( currentInsertEnd !== 0 ) {
746+ // must deliver previous insert event
747+ this . _actual . onLinesInserted ( currentInsertStart , currentInsertEnd ) ;
748+ oldDeltaLineCount += ( currentInsertEnd - currentInsertStart + 1 ) ;
749+ currentInsertStart = 0 ;
750+ currentInsertEnd = 0 ;
751+ eventCount ++ ;
752+ }
753+
754+ if ( currentDeleteStart === 0 ) {
755+ currentDeleteStart = oldIndex + 1 + oldDeltaLineCount ;
756+ currentDeleteEnd = currentDeleteStart ;
757+ } else {
758+ currentDeleteEnd ++ ;
759+ }
760+ }
761+ oldIndex ++ ;
762+ }
763+
764+ let selectedModelLineNumber : number ;
765+ if ( oldIndex < oldLength && oldMinimapLines [ oldIndex ] <= toModelLineNumber ) {
766+ // reuse the old sampled line
767+ selectedModelLineNumber = oldMinimapLines [ oldIndex ] ;
768+ oldIndex ++ ;
769+ } else {
770+ if ( i === 0 ) {
771+ selectedModelLineNumber = 1 ;
772+ } else if ( i + 1 === minimapLineCount ) {
773+ selectedModelLineNumber = modelLineCount ;
774+ } else {
775+ selectedModelLineNumber = Math . round ( i * ratio + halfRatio ) ;
776+ }
777+ if ( eventCount < MAX_EVENT_COUNT ) {
778+ if ( currentDeleteEnd !== 0 ) {
779+ // must deliver previous delete event
780+ this . _actual . onLinesDeleted ( currentDeleteStart , currentDeleteEnd ) ;
781+ oldDeltaLineCount -= ( currentDeleteEnd - currentDeleteStart + 1 ) ;
782+ currentDeleteStart = 0 ;
783+ currentDeleteEnd = 0 ;
784+ eventCount ++ ;
785+ }
786+
787+ if ( currentInsertStart === 0 ) {
788+ currentInsertStart = oldIndex + 1 + oldDeltaLineCount ;
789+ currentInsertEnd = currentInsertStart ;
790+ } else {
791+ currentInsertEnd ++ ;
792+ }
793+ }
794+ }
795+
796+ result [ i ] = selectedModelLineNumber ;
797+ if ( selectedModelLineNumber === modelLineCount ) {
798+ minModelLineNumber = selectedModelLineNumber ;
799+ } else {
800+ minModelLineNumber = selectedModelLineNumber + 1 ;
801+ }
802+ }
803+
804+ if ( eventCount < MAX_EVENT_COUNT ) {
805+ if ( currentInsertEnd !== 0 ) {
806+ // must deliver previous insert event
807+ this . _actual . onLinesInserted ( currentInsertStart , currentInsertEnd ) ;
808+ oldDeltaLineCount += ( currentInsertEnd - currentInsertStart + 1 ) ;
809+ currentInsertStart = 0 ;
810+ currentInsertEnd = 0 ;
811+ }
812+ while ( oldIndex < oldLength ) {
813+ if ( currentDeleteStart === 0 ) {
814+ currentDeleteStart = oldIndex + 1 + oldDeltaLineCount ;
815+ currentDeleteEnd = currentDeleteStart ;
816+ } else {
817+ currentDeleteEnd ++ ;
818+ }
819+ oldIndex ++ ;
820+ }
821+ if ( currentDeleteEnd !== 0 ) {
822+ // must deliver previous delete event
823+ this . _actual . onLinesDeleted ( currentDeleteStart , currentDeleteEnd ) ;
824+ oldDeltaLineCount -= ( currentDeleteEnd - currentDeleteStart + 1 ) ;
825+ currentDeleteStart = 0 ;
826+ currentDeleteEnd = 0 ;
827+ }
828+ } else {
829+ // too many events, just give up
830+ this . _actual . onFlushed ( ) ;
709831 }
710832
711833 this . _samplingRatio = ratio ;
@@ -1288,8 +1410,6 @@ class InnerMinimap extends Disposable {
12881410 }
12891411
12901412 private renderLines ( layout : MinimapLayout ) : RenderData | null {
1291- const renderMinimap = this . _model . options . renderMinimap ;
1292- const charRenderer = this . _model . options . charRenderer ( ) ;
12931413 const startLineNumber = layout . startLineNumber ;
12941414 const endLineNumber = layout . endLineNumber ;
12951415 const minimapLineHeight = this . _model . options . minimapLineHeight ;
@@ -1322,7 +1442,13 @@ class InnerMinimap extends Disposable {
13221442 const lineInfo = this . _model . getMinimapLinesRenderingData ( startLineNumber , endLineNumber , needed ) ;
13231443 const tabSize = this . _model . getOptions ( ) . tabSize ;
13241444 const background = this . _model . options . backgroundColor ;
1325- const useLighterFont = this . _model . tokensColorTracker . backgroundIsLight ( ) ;
1445+ const tokensColorTracker = this . _model . tokensColorTracker ;
1446+ const useLighterFont = tokensColorTracker . backgroundIsLight ( ) ;
1447+ const renderMinimap = this . _model . options . renderMinimap ;
1448+ const charRenderer = this . _model . options . charRenderer ( ) ;
1449+ const isSampling = this . _model . options . isSampling ;
1450+ const fontScale = this . _model . options . fontScale ;
1451+ const minimapCharWidth = this . _model . options . minimapCharWidth ;
13261452
13271453 // Render the rest of lines
13281454 let dy = 0 ;
@@ -1334,13 +1460,14 @@ class InnerMinimap extends Disposable {
13341460 background ,
13351461 useLighterFont ,
13361462 renderMinimap ,
1337- this . _model . options . minimapCharWidth ,
1338- this . _model . tokensColorTracker ,
1463+ minimapCharWidth ,
1464+ tokensColorTracker ,
13391465 charRenderer ,
13401466 dy ,
13411467 tabSize ,
13421468 lineInfo [ lineIndex ] ! ,
1343- this . _model . options . fontScale
1469+ fontScale ,
1470+ isSampling
13441471 ) ;
13451472 }
13461473 renderedLines [ lineIndex ] = new MinimapLine ( dy ) ;
@@ -1466,7 +1593,8 @@ class InnerMinimap extends Disposable {
14661593 dy : number ,
14671594 tabSize : number ,
14681595 lineData : ViewLineData ,
1469- fontScale : number
1596+ fontScale : number ,
1597+ isSampling : boolean
14701598 ) : void {
14711599 const content = lineData . content ;
14721600 const tokens = lineData . tokens ;
@@ -1504,7 +1632,7 @@ class InnerMinimap extends Disposable {
15041632 if ( renderMinimap === RenderMinimap . Blocks ) {
15051633 minimapCharRenderer . blockRenderChar ( target , dx , dy , tokenColor , backgroundColor , useLighterFont ) ;
15061634 } else { // RenderMinimap.Text
1507- minimapCharRenderer . renderChar ( target , dx , dy , charCode , tokenColor , backgroundColor , fontScale , useLighterFont ) ;
1635+ minimapCharRenderer . renderChar ( target , dx , dy , charCode , tokenColor , backgroundColor , fontScale , useLighterFont , isSampling ) ;
15081636 }
15091637
15101638 dx += charWidth ;
0 commit comments