Merge pull request #13664 from atom/fb-as-show-cursor-on-selection

Add showCursorOnSelection config
This commit is contained in:
Nathan Sobo
2017-01-20 14:07:21 -07:00
committed by GitHub
8 changed files with 123 additions and 10 deletions

View File

@@ -1347,7 +1347,19 @@ describe('TextEditorComponent', function () {
expect(cursorsNode.classList.contains('blink-off')).toBe(true)
})
it('does not render cursors that are associated with non-empty selections', function () {
it('renders cursors that are associated with empty selections', function () {
editor.update({showCursorOnSelection: true})
editor.setSelectedScreenRange([[0, 4], [4, 6]])
editor.addCursorAtScreenPosition([6, 8])
runAnimationFrames()
let cursorNodes = componentNode.querySelectorAll('.cursor')
expect(cursorNodes.length).toBe(2)
expect(cursorNodes[0].style['-webkit-transform']).toBe('translate(' + (Math.round(6 * charWidth)) + 'px, ' + (4 * lineHeightInPixels) + 'px)')
expect(cursorNodes[1].style['-webkit-transform']).toBe('translate(' + (Math.round(8 * charWidth)) + 'px, ' + (6 * lineHeightInPixels) + 'px)')
})
it('does not render cursors that are associated with non-empty selections when showCursorOnSelection is false', function () {
editor.update({showCursorOnSelection: false})
editor.setSelectedScreenRange([[0, 4], [4, 6]])
editor.addCursorAtScreenPosition([6, 8])
runAnimationFrames()

View File

@@ -1583,6 +1583,7 @@ describe "TextEditorPresenter", ->
getState(presenter).content.cursors[presenter.model.getCursors()[cursorIndex].id]
it "contains pixelRects for empty selections that are visible on screen", ->
editor.update({showCursorOnSelection: false})
editor.setSelectedBufferRanges([
[[1, 2], [1, 2]],
[[2, 4], [2, 4]],
@@ -1627,6 +1628,7 @@ describe "TextEditorPresenter", ->
expect(getState(presenter).content.cursors).not.toEqual({})
it "updates when block decorations change", ->
editor.update({showCursorOnSelection: false})
editor.setSelectedBufferRanges([
[[1, 2], [1, 2]],
[[2, 4], [2, 4]],
@@ -1704,6 +1706,7 @@ describe "TextEditorPresenter", ->
expect(stateForCursor(presenter, 0)).toEqual {top: 20, left: 10 * 22, width: 10, height: 10}
it "updates when ::explicitHeight changes", ->
editor.update({showCursorOnSelection: false})
editor.setSelectedBufferRanges([
[[1, 2], [1, 2]],
[[2, 4], [2, 4]],
@@ -1757,6 +1760,7 @@ describe "TextEditorPresenter", ->
expect(stateForCursor(presenter, 0)).toEqual {top: 1 * 10, left: (3 * 10) + 20, width: 20, height: 10}
it "updates when cursors are added, moved, hidden, shown, or destroyed", ->
editor.update({showCursorOnSelection: false})
editor.setSelectedBufferRanges([
[[1, 2], [1, 2]],
[[3, 4], [3, 5]]

View File

@@ -436,6 +436,19 @@ describe('TextEditorRegistry', function () {
expect(editor.hasAtomicSoftTabs()).toBe(true)
})
it('enables or disables cursor on selection visibility based on the config', async function () {
editor.update({showCursorOnSelection: true})
expect(editor.getShowCursorOnSelection()).toBe(true)
atom.config.set('editor.showCursorOnSelection', false)
registry.maintainConfig(editor)
await initialPackageActivation
expect(editor.getShowCursorOnSelection()).toBe(false)
atom.config.set('editor.showCursorOnSelection', true)
expect(editor.getShowCursorOnSelection()).toBe(true)
})
it('enables or disables line numbers based on the config', async function () {
editor.update({showLineNumbers: true})
expect(editor.showLineNumbers).toBe(true)

View File

@@ -89,7 +89,11 @@ describe "TextEditor", ->
describe ".copy()", ->
it "returns a different editor with the same initial state", ->
editor.update({autoHeight: false, autoWidth: true})
expect(editor.getAutoHeight()).toBeFalsy()
expect(editor.getAutoWidth()).toBeFalsy()
expect(editor.getShowCursorOnSelection()).toBeTruthy()
editor.update({autoHeight: true, autoWidth: true, showCursorOnSelection: false})
editor.setSelectedBufferRange([[1, 2], [3, 4]])
editor.addSelectionForBufferRange([[5, 6], [7, 8]], reversed: true)
editor.firstVisibleScreenRow = 5
@@ -105,7 +109,8 @@ describe "TextEditor", ->
expect(editor2.getFirstVisibleScreenColumn()).toBe 5
expect(editor2.isFoldedAtBufferRow(4)).toBeTruthy()
expect(editor2.getAutoWidth()).toBeTruthy()
expect(editor2.getAutoHeight()).toBeFalsy()
expect(editor2.getAutoHeight()).toBeTruthy()
expect(editor2.getShowCursorOnSelection()).toBeFalsy()
# editor2 can now diverge from its origin edit session
editor2.getLastSelection().setBufferRange([[2, 1], [4, 3]])
@@ -1858,7 +1863,7 @@ describe "TextEditor", ->
[[4, 25], [4, 29]]
]
for cursor in editor.getCursors()
expect(cursor.isVisible()).toBeFalsy()
expect(cursor.isVisible()).toBeTruthy()
it "skips lines that are too short to create a non-empty selection", ->
editor.setSelectedBufferRange([[3, 31], [3, 38]])
@@ -1991,7 +1996,7 @@ describe "TextEditor", ->
[[2, 37], [2, 40]]
]
for cursor in editor.getCursors()
expect(cursor.isVisible()).toBeFalsy()
expect(cursor.isVisible()).toBeTruthy()
it "skips lines that are too short to create a non-empty selection", ->
editor.setSelectedBufferRange([[6, 31], [6, 38]])
@@ -2161,6 +2166,54 @@ describe "TextEditor", ->
editor.setCursorScreenPosition([3, 3])
expect(selection.isEmpty()).toBeTruthy()
describe "cursor visibility while there is a selection", ->
describe "when showCursorOnSelection is true", ->
it "is visible while there is no selection", ->
expect(selection.isEmpty()).toBeTruthy()
expect(editor.getShowCursorOnSelection()).toBeTruthy()
expect(editor.getCursors().length).toBe 1
expect(editor.getCursors()[0].isVisible()).toBeTruthy()
it "is visible while there is a selection", ->
expect(selection.isEmpty()).toBeTruthy()
editor.setSelectedBufferRange([[1, 2], [1, 5]])
expect(selection.isEmpty()).toBeFalsy()
expect(editor.getCursors().length).toBe 1
expect(editor.getCursors()[0].isVisible()).toBeTruthy()
it "is visible while there are multiple selections", ->
expect(editor.getSelections().length).toBe 1
editor.setSelectedBufferRanges([[[1, 2], [1, 5]], [[2, 2], [2, 5]]])
expect(editor.getSelections().length).toBe 2
expect(editor.getCursors().length).toBe 2
expect(editor.getCursors()[0].isVisible()).toBeTruthy()
expect(editor.getCursors()[1].isVisible()).toBeTruthy()
describe "when showCursorOnSelection is false", ->
it "is visible while there is no selection", ->
editor.update({showCursorOnSelection: false})
expect(selection.isEmpty()).toBeTruthy()
expect(editor.getShowCursorOnSelection()).toBeFalsy()
expect(editor.getCursors().length).toBe 1
expect(editor.getCursors()[0].isVisible()).toBeTruthy()
it "is not visible while there is a selection", ->
editor.update({showCursorOnSelection: false})
expect(selection.isEmpty()).toBeTruthy()
editor.setSelectedBufferRange([[1, 2], [1, 5]])
expect(selection.isEmpty()).toBeFalsy()
expect(editor.getCursors().length).toBe 1
expect(editor.getCursors()[0].isVisible()).toBeFalsy()
it "is not visible while there are multiple selections", ->
editor.update({showCursorOnSelection: false})
expect(editor.getSelections().length).toBe 1
editor.setSelectedBufferRanges([[[1, 2], [1, 5]], [[2, 2], [2, 5]]])
expect(editor.getSelections().length).toBe 2
expect(editor.getCursors().length).toBe 2
expect(editor.getCursors()[0].isVisible()).toBeFalsy()
expect(editor.getCursors()[1].isVisible()).toBeFalsy()
it "does not share selections between different edit sessions for the same buffer", ->
editor2 = null
waitsForPromise ->

View File

@@ -217,6 +217,11 @@ const configSchema = {
default: 1.5,
description: 'Height of editor lines, as a multiplier of font size.'
},
showCursorOnSelection: {
type: 'boolean',
'default': true,
description: 'Show cursor while there is a selection.'
},
showInvisibles: {
type: 'boolean',
default: false,

View File

@@ -12,15 +12,18 @@ EmptyLineRegExp = /(\r\n[\t ]*\r\n)|(\n[\t ]*\n)/g
# of a {DisplayMarker}.
module.exports =
class Cursor extends Model
showCursorOnSelection: null
screenPosition: null
bufferPosition: null
goalColumn: null
visible: true
# Instantiated by a {TextEditor}
constructor: ({@editor, @marker, id}) ->
constructor: ({@editor, @marker, @showCursorOnSelection, id}) ->
@emitter = new Emitter
@showCursorOnSelection ?= true
@assignId(id)
@updateVisibility()
@@ -575,7 +578,10 @@ class Cursor extends Model
isVisible: -> @visible
updateVisibility: ->
@setVisible(@marker.getBufferRange().isEmpty())
if @showCursorOnSelection
@setVisible(true)
else
@setVisible(@marker.getBufferRange().isEmpty())
###
Section: Comparing to another cursor
@@ -645,6 +651,11 @@ class Cursor extends Model
Section: Private
###
setShowCursorOnSelection: (value) ->
if value isnt @showCursorOnSelection
@showCursorOnSelection = value
@updateVisibility()
getNonWordCharacters: ->
@editor.getNonWordCharacters(@getScopeDescriptor().getScopesArray())

View File

@@ -11,6 +11,7 @@ const EDITOR_PARAMS_BY_SETTING_KEY = [
['editor.showInvisibles', 'showInvisibles'],
['editor.tabLength', 'tabLength'],
['editor.invisibles', 'invisibles'],
['editor.showCursorOnSelection', 'showCursorOnSelection'],
['editor.showIndentGuide', 'showIndentGuide'],
['editor.showLineNumbers', 'showLineNumbers'],
['editor.softWrap', 'softWrapped'],

View File

@@ -67,6 +67,7 @@ class TextEditor extends Model
buffer: null
languageMode: null
cursors: null
showCursorOnSelection: null
selections: null
suppressSelectionMerging: false
selectionFlashDuration: 500
@@ -133,7 +134,8 @@ class TextEditor extends Model
@mini, @placeholderText, lineNumberGutterVisible, @largeFileMode,
@assert, grammar, @showInvisibles, @autoHeight, @autoWidth, @scrollPastEnd, @editorWidthInChars,
@tokenizedBuffer, @displayLayer, @invisibles, @showIndentGuide,
@softWrapped, @softWrapAtPreferredLineLength, @preferredLineLength
@softWrapped, @softWrapAtPreferredLineLength, @preferredLineLength,
@showCursorOnSelection
} = params
@assert ?= (condition) -> condition
@@ -153,6 +155,7 @@ class TextEditor extends Model
tabLength ?= 2
@autoIndent ?= true
@autoIndentOnPaste ?= true
@showCursorOnSelection ?= true
@undoGroupingInterval ?= 300
@nonWordCharacters ?= "/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-…"
@softWrapped ?= false
@@ -342,6 +345,12 @@ class TextEditor extends Model
if value isnt @autoWidth
@autoWidth = value
@presenter?.didChangeAutoWidth()
when 'showCursorOnSelection'
if value isnt @showCursorOnSelection
@showCursorOnSelection = value
cursor.setShowCursorOnSelection(value) for cursor in @getCursors()
else
throw new TypeError("Invalid TextEditor parameter: '#{param}'")
@@ -722,7 +731,7 @@ class TextEditor extends Model
tabLength: @tokenizedBuffer.getTabLength(),
@firstVisibleScreenRow, @firstVisibleScreenColumn,
@assert, displayLayer, grammar: @getGrammar(),
@autoWidth, @autoHeight
@autoWidth, @autoHeight, @showCursorOnSelection
})
# Controls visibility based on the given {Boolean}.
@@ -2269,7 +2278,7 @@ class TextEditor extends Model
# Add a cursor based on the given {DisplayMarker}.
addCursor: (marker) ->
cursor = new Cursor(editor: this, marker: marker)
cursor = new Cursor(editor: this, marker: marker, showCursorOnSelection: @showCursorOnSelection)
@cursors.push(cursor)
@cursorsByMarkerId.set(marker.id, cursor)
@decorateMarker(marker, type: 'line-number', class: 'cursor-line')
@@ -3466,6 +3475,11 @@ class TextEditor extends Model
# Returns a positive {Number}.
getScrollSensitivity: -> @scrollSensitivity
# Experimental: Does this editor show cursors while there is a selection?
#
# Returns a positive {Boolean}.
getShowCursorOnSelection: -> @showCursorOnSelection
# Experimental: Are line numbers enabled for this editor?
#
# Returns a {Boolean}