mirror of
https://github.com/atom/atom.git
synced 2026-04-06 03:02:13 -04:00
Merge pull request #13664 from atom/fb-as-show-cursor-on-selection
Add showCursorOnSelection config
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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]]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 ->
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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())
|
||||
|
||||
|
||||
@@ -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'],
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user