diff --git a/lib/config-schema.json b/lib/config-schema.json index 67870b89..11d8c74e 100644 --- a/lib/config-schema.json +++ b/lib/config-schema.json @@ -98,6 +98,11 @@ "default":false, "description":"When enabled the text editor content will be able to flow below the minimap." }, + "adjustAbsoluteModeHeight":{ + "type":"boolean", + "default":false, + "description":"When enabled and `Absolute Mode` is also enabled, the minimap height will be adjusted to only take the space required by the text editor content, leaving the space below triggering mouse events on the text editor. **Be aware this can have some impact on performances as the minimap canvases will be resized every time a change in the editor make its height change.**" + }, "ignoreWhitespacesInTokens": { "type":"boolean", "default":false, diff --git a/lib/minimap-element.js b/lib/minimap-element.js index 09f5b77c..0b0cd4ed 100644 --- a/lib/minimap-element.js +++ b/lib/minimap-element.js @@ -276,6 +276,12 @@ export default class MinimapElement { return this.classList.toggle('absolute', this.absoluteMode) }, + 'minimap.adjustAbsoluteModeHeight': (adjustAbsoluteModeHeight) => { + this.adjustAbsoluteModeHeight = adjustAbsoluteModeHeight + + return this.classList.toggle('adjust-absolute-height', this.adjustAbsoluteModeHeight) + }, + 'minimap.ignoreWhitespacesInTokens': (ignoreWhitespacesInTokens) => { this.ignoreWhitespacesInTokens = ignoreWhitespacesInTokens @@ -828,6 +834,8 @@ export default class MinimapElement { if (!minimap.canScroll()) { this.disposeScrollIndicator() } } + if (this.absoluteMode && this.adjustAbsoluteModeHeight) { this.updateCanvasesSize() } + this.updateCanvas() minimap.clearCache() } @@ -904,9 +912,13 @@ export default class MinimapElement { this.width = this.clientWidth let canvasWidth = this.width - if ((this.minimap != null)) { this.minimap.setScreenHeightAndWidth(this.height, this.width) } + if ((this.minimap != null)) { + this.minimap.setScreenHeightAndWidth(this.height, this.width) + } - if (wasResized || visibilityChanged || forceUpdate) { this.requestForcedUpdate() } + if (wasResized || visibilityChanged || forceUpdate) { + this.requestForcedUpdate() + } if (!this.isVisible()) { return } @@ -927,12 +939,22 @@ export default class MinimapElement { delete this.flexBasis } - let canvas = this.getFrontCanvas() - if (canvasWidth !== canvas.width || this.height !== canvas.height) { - this.setCanvasesSize( - canvasWidth * devicePixelRatio, - (this.height + this.minimap.getLineHeight()) * devicePixelRatio - ) + this.updateCanvasesSize(canvasWidth) + } + } + + updateCanvasesSize (canvasWidth=this.getFrontCanvas().width) { + const maxCanvasHeight = this.height + this.minimap.getLineHeight() + const newHeight = this.absoluteMode && this.adjustAbsoluteModeHeight ? Math.min(this.minimap.getHeight(), maxCanvasHeight) : maxCanvasHeight + const canvas = this.getFrontCanvas() + if (canvasWidth !== canvas.width || newHeight !== canvas.height) { + this.setCanvasesSize( + canvasWidth * devicePixelRatio, + newHeight * devicePixelRatio + ) + if (this.absoluteMode && this.adjustAbsoluteModeHeight) { + this.offscreenFirstRow = null + this.offscreenLastRow = null } } } diff --git a/spec/minimap-element-spec.js b/spec/minimap-element-spec.js index 319b0624..fb42a3fb 100644 --- a/spec/minimap-element-spec.js +++ b/spec/minimap-element-spec.js @@ -1495,6 +1495,44 @@ describe('MinimapElement', () => { expect(minimapElement.classList.contains('left')).toBeTruthy() }) }) + + describe('when minimap.adjustAbsoluteModeHeight setting is true', () => { + beforeEach(() => { + atom.config.set('minimap.adjustAbsoluteModeHeight', true) + }) + describe('when the content of the minimap is smaller that the editor height', () => { + beforeEach(() => { + editor.setText(smallSample) + editorElement.setHeight(400) + minimapElement.measureHeightAndWidth() + + waitsFor('a new animation frame request', () => { + return nextAnimationFrame !== noAnimationFrame + }) + + runs(() => nextAnimationFrame()) + }) + it('adjusts the canvas height to the minimap height', () => { + expect(minimapElement.shadowRoot.querySelector('canvas').offsetHeight).toEqual(minimap.getHeight()) + }) + + describe('when the content is modified', () => { + beforeEach(() => { + editor.insertText('foo\n\nbar\n') + + waitsFor('a new animation frame request', () => { + return nextAnimationFrame !== noAnimationFrame + }) + + runs(() => nextAnimationFrame()) + }) + + it('adjusts the canvas height to the new minimap height', () => { + expect(minimapElement.shadowRoot.querySelector('canvas').offsetHeight).toEqual(minimap.getHeight()) + }) + }) + }) + }) }) describe('when the smoothScrolling setting is disabled', () => { diff --git a/styles/minimap.less b/styles/minimap.less index 79656dbb..6bd8aec1 100644 --- a/styles/minimap.less +++ b/styles/minimap.less @@ -32,6 +32,15 @@ atom-text-editor::shadow, atom-text-editor, html { position: absolute; right: 0; + &.adjust-absolute-height { + pointer-events: none; + &::shadow { + * { + pointer-events: auto; + } + } + } + // absolute mode do nothing when the minimap is on the left, because // it would conflict with the editor's gutter &.left {