From 6d1f8ea88cb969bcf942ee87b5795fa01de17699 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 1 Jun 2017 16:29:04 +0200 Subject: [PATCH] Render line number gutter without numbers when showLineNumbers is false Signed-off-by: Nathan Sobo --- spec/text-editor-component-spec.js | 25 +++++++++++++++++++++++-- src/text-editor-component.js | 28 ++++++++++++++++++++-------- src/text-editor.coffee | 5 +++-- 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/spec/text-editor-component-spec.js b/spec/text-editor-component-spec.js index fe237dfc2..9163b46a7 100644 --- a/spec/text-editor-component-spec.js +++ b/spec/text-editor-component-spec.js @@ -596,11 +596,32 @@ describe('TextEditorComponent', () => { ) }) - it('supports the isLineNumberGutterVisible parameter', () => { + it('does not render the line number gutter at all if the isLineNumberGutterVisible parameter is false', () => { const {component, element, editor} = buildComponent({lineNumberGutterVisible: false}) expect(element.querySelector('.line-number')).toBe(null) }) + it('does not render the line numbers but still renders the line number gutter if showLineNumbers is false', async () => { + function checkScrollContainerLeft (component) { + const {scrollContainer, gutterContainer} = component.refs + expect(scrollContainer.getBoundingClientRect().left).toBe(Math.round(gutterContainer.element.getBoundingClientRect().right)) + } + + const {component, element, editor} = buildComponent({showLineNumbers: false}) + expect(Array.from(element.querySelectorAll('.line-number')).every((e) => e.textContent === '')).toBe(true) + checkScrollContainerLeft(component) + + await editor.update({showLineNumbers: true}) + expect(Array.from(element.querySelectorAll('.line-number')).map((e) => e.textContent)).toEqual([ + '00', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13' + ]) + checkScrollContainerLeft(component) + + await editor.update({showLineNumbers: false}) + expect(Array.from(element.querySelectorAll('.line-number')).every((e) => e.textContent === '')).toBe(true) + checkScrollContainerLeft(component) + }) + it('supports the placeholderText parameter', () => { const placeholderText = 'Placeholder Test' const {element} = buildComponent({placeholderText, text: ''}) @@ -3401,7 +3422,7 @@ function buildEditor (params = {}) { const buffer = new TextBuffer({text}) const editorParams = {buffer} if (params.height != null) params.autoHeight = false - for (const paramName of ['mini', 'autoHeight', 'autoWidth', 'lineNumberGutterVisible', 'placeholderText', 'softWrapped']) { + for (const paramName of ['mini', 'autoHeight', 'autoWidth', 'lineNumberGutterVisible', 'showLineNumbers', 'placeholderText', 'softWrapped']) { if (params[paramName] != null) editorParams[paramName] = params[paramName] } return new TextEditor(editorParams) diff --git a/src/text-editor-component.js b/src/text-editor-component.js index d6ffc0531..e808fc518 100644 --- a/src/text-editor-component.js +++ b/src/text-editor-component.js @@ -135,6 +135,7 @@ class TextEditorComponent { this.idsByTileStartRow = new Map() this.nextTileId = 0 this.renderedTileStartRows = [] + this.showLineNumbers = this.props.model.doesShowLineNumbers() this.lineNumbersToRender = { maxDigits: 2, bufferRows: [], @@ -482,6 +483,7 @@ class TextEditorComponent { guttersToRender: this.guttersToRender, decorationsToRender: this.decorationsToRender, isLineNumberGutterVisible: this.props.model.isLineNumberGutterVisible(), + showLineNumbers: this.showLineNumbers, lineNumbersToRender: this.lineNumbersToRender, didMeasureVisibleBlockDecoration: this.didMeasureVisibleBlockDecoration }) @@ -818,6 +820,10 @@ class TextEditorComponent { queryLineNumbersToRender () { const {model} = this.props if (!model.isLineNumberGutterVisible()) return + if (this.showLineNumbers !== model.doesShowLineNumbers()) { + this.remeasureGutterDimensions = true + this.showLineNumbers = model.doesShowLineNumbers() + } this.queryMaxLineNumberDigits() @@ -2892,7 +2898,7 @@ class GutterContainerComponent { renderLineNumberGutter (gutter) { const { - rootComponent, isLineNumberGutterVisible, hasInitialMeasurements, lineNumbersToRender, + rootComponent, isLineNumberGutterVisible, showLineNumbers, hasInitialMeasurements, lineNumbersToRender, renderedStartRow, renderedEndRow, rowsPerTile, decorationsToRender, didMeasureVisibleBlockDecoration, scrollHeight, lineNumberGutterWidth, lineHeight } = this.props @@ -2918,13 +2924,15 @@ class GutterContainerComponent { didMeasureVisibleBlockDecoration: didMeasureVisibleBlockDecoration, height: scrollHeight, width: lineNumberGutterWidth, - lineHeight: lineHeight + lineHeight: lineHeight, + showLineNumbers }) } else { return $(LineNumberGutterComponent, { ref: 'lineNumberGutter', element: gutter.getElement(), - maxDigits: lineNumbersToRender.maxDigits + maxDigits: lineNumbersToRender.maxDigits, + showLineNumbers }) } } @@ -2948,7 +2956,7 @@ class LineNumberGutterComponent { render () { const { - rootComponent, height, width, lineHeight, startRow, endRow, rowsPerTile, + rootComponent, showLineNumbers, height, width, lineHeight, startRow, endRow, rowsPerTile, maxDigits, keys, bufferRows, softWrappedFlags, foldableFlags, decorations } = this.props @@ -2973,8 +2981,11 @@ class LineNumberGutterComponent { const decorationsForRow = decorations[row - startRow] if (decorationsForRow) className = className + ' ' + decorationsForRow - let number = softWrapped ? '•' : bufferRow + 1 - number = NBSP_CHARACTER.repeat(maxDigits - number.length) + number + let number = null + if (showLineNumbers) { + number = softWrapped ? '•' : bufferRow + 1 + number = NBSP_CHARACTER.repeat(maxDigits - number.length) + number + } const lineNumberProps = { key, @@ -3017,7 +3028,7 @@ class LineNumberGutterComponent { return $.div( { - className: 'gutter line-bufferRows', + className: 'gutter line-numbers', attributes: {'gutter-name': 'line-number'}, style: {position: 'relative', height: height + 'px'}, on: { @@ -3025,7 +3036,7 @@ class LineNumberGutterComponent { } }, $.div({key: 'placeholder', className: 'line-number dummy', style: {visibility: 'hidden'}}, - '0'.repeat(maxDigits), + showLineNumbers ? '0'.repeat(maxDigits) : null, $.div({className: 'icon-right'}) ), children @@ -3035,6 +3046,7 @@ class LineNumberGutterComponent { shouldUpdate (newProps) { const oldProps = this.props + if (oldProps.showLineNumbers !== newProps.showLineNumbers) return true if (oldProps.height !== newProps.height) return true if (oldProps.width !== newProps.width) return true if (oldProps.lineHeight !== newProps.lineHeight) return true diff --git a/src/text-editor.coffee b/src/text-editor.coffee index dae7e0698..b79d3694e 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -98,7 +98,6 @@ class TextEditor extends Model registered: false atomicSoftTabs: true invisibles: null - showLineNumbers: true scrollSensitivity: 40 Object.defineProperty @prototype, "element", @@ -156,7 +155,7 @@ class TextEditor extends Model { @softTabs, @initialScrollTopRow, @initialScrollLeftColumn, initialLine, initialColumn, tabLength, @softWrapped, @decorationManager, @selectionsMarkerLayer, @buffer, suppressCursorCreation, - @mini, @placeholderText, lineNumberGutterVisible, @largeFileMode, + @mini, @placeholderText, lineNumberGutterVisible, @showLineNumbers, @largeFileMode, @assert, grammar, @showInvisibles, @autoHeight, @autoWidth, @scrollPastEnd, @editorWidthInChars, @tokenizedBuffer, @displayLayer, @invisibles, @showIndentGuide, @softWrapped, @softWrapAtPreferredLineLength, @preferredLineLength, @@ -184,6 +183,7 @@ class TextEditor extends Model @softWrapped ?= false @softWrapAtPreferredLineLength ?= false @preferredLineLength ?= 80 + @showLineNumbers ?= true @buffer ?= new TextBuffer({shouldDestroyOnFileDelete: -> atom.config.get('core.closeDeletedFileTabs')}) @@ -357,6 +357,7 @@ class TextEditor extends Model when 'showLineNumbers' if value isnt @showLineNumbers @showLineNumbers = value + @component?.scheduleUpdate() when 'showInvisibles' if value isnt @showInvisibles