mirror of
https://github.com/atom/atom.git
synced 2026-02-06 12:44:59 -05:00
Merge pull request #2497 from atom/cj-add-react-editor-shims
Add shims to the React View Editor
This commit is contained in:
@@ -230,8 +230,7 @@ class DisplayBuffer extends Model
|
||||
@charWidthsByScope = {}
|
||||
|
||||
getScrollHeight: ->
|
||||
unless @getLineHeightInPixels() > 0
|
||||
throw new Error("You must assign lineHeightInPixels before calling ::getScrollHeight()")
|
||||
return 0 unless @getLineHeightInPixels() > 0
|
||||
|
||||
@getLineCount() * @getLineHeightInPixels()
|
||||
|
||||
@@ -239,8 +238,7 @@ class DisplayBuffer extends Model
|
||||
(@getMaxLineLength() * @getDefaultCharWidth()) + @getCursorWidth()
|
||||
|
||||
getVisibleRowRange: ->
|
||||
unless @getLineHeightInPixels() > 0
|
||||
throw new Error("You must assign a non-zero lineHeightInPixels before calling ::getVisibleRowRange()")
|
||||
return [0, 0] unless @getLineHeightInPixels() > 0
|
||||
|
||||
heightInLines = Math.ceil(@getHeight() / @getLineHeightInPixels()) + 1
|
||||
startRow = Math.floor(@getScrollTop() / @getLineHeightInPixels())
|
||||
|
||||
@@ -37,6 +37,7 @@ EditorComponent = React.createClass
|
||||
overflowChangedEventsPaused: false
|
||||
overflowChangedWhilePaused: false
|
||||
measureLineHeightAndDefaultCharWidthWhenShown: false
|
||||
inputEnabled: true
|
||||
|
||||
render: ->
|
||||
{focused, fontSize, lineHeight, fontFamily, showIndentGuide, showInvisibles, visible} = @state
|
||||
@@ -165,7 +166,9 @@ EditorComponent = React.createClass
|
||||
window.removeEventListener('resize', @onWindowResize)
|
||||
|
||||
componentWillUpdate: ->
|
||||
@props.parentView.trigger 'cursor:moved' if @cursorsMoved
|
||||
if @props.editor.isAlive()
|
||||
@props.parentView.trigger 'cursor:moved' if @cursorsMoved
|
||||
@props.parentView.trigger 'selection:changed' if @selectionChanged
|
||||
|
||||
componentDidUpdate: (prevProps, prevState) ->
|
||||
@pendingChanges.length = 0
|
||||
@@ -457,6 +460,8 @@ EditorComponent = React.createClass
|
||||
scrollViewNode.scrollLeft = 0
|
||||
|
||||
onInput: (char, replaceLastCharacter) ->
|
||||
return unless @inputEnabled
|
||||
|
||||
{editor} = @props
|
||||
|
||||
if replaceLastCharacter
|
||||
@@ -531,6 +536,7 @@ EditorComponent = React.createClass
|
||||
|
||||
onCursorsMoved: ->
|
||||
@cursorsMoved = true
|
||||
@requestUpdate()
|
||||
|
||||
onDecorationChanged: ->
|
||||
@decorationChangedImmediate ?= setImmediate =>
|
||||
@@ -707,50 +713,21 @@ EditorComponent = React.createClass
|
||||
show: ->
|
||||
@setState(visible: true)
|
||||
|
||||
runScrollBenchmark: ->
|
||||
unless process.env.NODE_ENV is 'production'
|
||||
ReactPerf = require 'react-atom-fork/lib/ReactDefaultPerf'
|
||||
ReactPerf.start()
|
||||
|
||||
node = @getDOMNode()
|
||||
|
||||
scroll = (delta, done) ->
|
||||
dispatchMouseWheelEvent = ->
|
||||
node.dispatchEvent(new WheelEvent('mousewheel', wheelDeltaX: -0, wheelDeltaY: -delta))
|
||||
|
||||
stopScrolling = ->
|
||||
clearInterval(interval)
|
||||
done?()
|
||||
|
||||
interval = setInterval(dispatchMouseWheelEvent, 10)
|
||||
setTimeout(stopScrolling, 500)
|
||||
|
||||
console.timeline('scroll')
|
||||
scroll 50, ->
|
||||
scroll 100, ->
|
||||
scroll 200, ->
|
||||
scroll 400, ->
|
||||
scroll 800, ->
|
||||
scroll 1600, ->
|
||||
console.timelineEnd('scroll')
|
||||
unless process.env.NODE_ENV is 'production'
|
||||
ReactPerf.stop()
|
||||
console.log "Inclusive"
|
||||
ReactPerf.printInclusive()
|
||||
console.log "Exclusive"
|
||||
ReactPerf.printExclusive()
|
||||
console.log "Wasted"
|
||||
ReactPerf.printWasted()
|
||||
getFontSize: ->
|
||||
@state.fontSize
|
||||
|
||||
setFontSize: (fontSize) ->
|
||||
@setState({fontSize})
|
||||
|
||||
setLineHeight: (lineHeight) ->
|
||||
@setState({lineHeight})
|
||||
getFontFamily: ->
|
||||
@state.fontFamily
|
||||
|
||||
setFontFamily: (fontFamily) ->
|
||||
@setState({fontFamily})
|
||||
|
||||
setLineHeight: (lineHeight) ->
|
||||
@setState({lineHeight})
|
||||
|
||||
setShowIndentGuide: (showIndentGuide) ->
|
||||
@setState({showIndentGuide})
|
||||
|
||||
@@ -786,6 +763,48 @@ EditorComponent = React.createClass
|
||||
left = clientX - scrollViewClientRect.left + editor.getScrollLeft()
|
||||
{top, left}
|
||||
|
||||
getModel: ->
|
||||
@props.editor
|
||||
|
||||
isInputEnabled: -> @inputEnabled
|
||||
|
||||
setInputEnabled: (@inputEnabled) -> @inputEnabled
|
||||
|
||||
updateParentViewFocusedClassIfNeeded: (prevState) ->
|
||||
if prevState.focused isnt @state.focused
|
||||
@props.parentView.toggleClass('is-focused', @props.focused)
|
||||
|
||||
runScrollBenchmark: ->
|
||||
unless process.env.NODE_ENV is 'production'
|
||||
ReactPerf = require 'react-atom-fork/lib/ReactDefaultPerf'
|
||||
ReactPerf.start()
|
||||
|
||||
node = @getDOMNode()
|
||||
|
||||
scroll = (delta, done) ->
|
||||
dispatchMouseWheelEvent = ->
|
||||
node.dispatchEvent(new WheelEvent('mousewheel', wheelDeltaX: -0, wheelDeltaY: -delta))
|
||||
|
||||
stopScrolling = ->
|
||||
clearInterval(interval)
|
||||
done?()
|
||||
|
||||
interval = setInterval(dispatchMouseWheelEvent, 10)
|
||||
setTimeout(stopScrolling, 500)
|
||||
|
||||
console.timeline('scroll')
|
||||
scroll 50, ->
|
||||
scroll 100, ->
|
||||
scroll 200, ->
|
||||
scroll 400, ->
|
||||
scroll 800, ->
|
||||
scroll 1600, ->
|
||||
console.timelineEnd('scroll')
|
||||
unless process.env.NODE_ENV is 'production'
|
||||
ReactPerf.stop()
|
||||
console.log "Inclusive"
|
||||
ReactPerf.printInclusive()
|
||||
console.log "Exclusive"
|
||||
ReactPerf.printExclusive()
|
||||
console.log "Wasted"
|
||||
ReactPerf.printWasted()
|
||||
|
||||
@@ -282,7 +282,7 @@ class EditorView extends View
|
||||
@editor.moveCursorUp(@getPageRows())
|
||||
@scrollTop(newScrollTop, adjustVerticalScrollbar: true)
|
||||
|
||||
# Public: Gets the number of actual page rows existing in an editor.
|
||||
# Gets the number of actual page rows existing in an editor.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getPageRows: ->
|
||||
|
||||
@@ -62,7 +62,7 @@ GutterComponent = React.createClass
|
||||
# since the real line numbers are absolutely positioned for performance reasons.
|
||||
appendDummyLineNumber: ->
|
||||
{maxLineNumberDigits} = @props
|
||||
WrapperDiv.innerHTML = @buildLineNumberHTML(0, false, maxLineNumberDigits)
|
||||
WrapperDiv.innerHTML = @buildLineNumberHTML(-1, false, maxLineNumberDigits)
|
||||
@dummyLineNumberNode = WrapperDiv.children[0]
|
||||
@refs.lineNumbers.getDOMNode().appendChild(@dummyLineNumberNode)
|
||||
|
||||
@@ -140,7 +140,7 @@ GutterComponent = React.createClass
|
||||
if decorations?
|
||||
for decoration in decorations
|
||||
classes += decoration.class + ' ' if not softWrapped or softWrapped and decoration.softWrap
|
||||
classes += 'line-number'
|
||||
classes += "line-number line-number-#{bufferRow}"
|
||||
|
||||
"<div class=\"#{classes}\" style=\"#{style}\" data-buffer-row=\"#{bufferRow}\" data-screen-row=\"#{screenRow}\">#{innerHTML}</div>"
|
||||
|
||||
|
||||
@@ -212,7 +212,10 @@ class Pane extends Model
|
||||
@destroyItem(item) for item in @getItems() when item isnt @activeItem
|
||||
|
||||
destroy: ->
|
||||
super unless @container?.isAlive() and @container?.getPanes().length is 1
|
||||
if @container?.isAlive() and @container.getPanes().length is 1
|
||||
@destroyItems()
|
||||
else
|
||||
super
|
||||
|
||||
# Called by model superclass.
|
||||
destroyed: ->
|
||||
@@ -331,7 +334,7 @@ class Pane extends Model
|
||||
if @parent.orientation isnt orientation
|
||||
@parent.replaceChild(this, new PaneAxis({@container, orientation, children: [this]}))
|
||||
|
||||
newPane = new @constructor(extend({focused: true}, params))
|
||||
newPane = new @constructor(params)
|
||||
switch side
|
||||
when 'before' then @parent.insertChildBefore(this, newPane)
|
||||
when 'after' then @parent.insertChildAfter(this, newPane)
|
||||
|
||||
@@ -23,6 +23,41 @@ class ReactEditorView extends View
|
||||
Object.defineProperty @::, 'charWidth', get: -> @editor.getDefaultCharWidth()
|
||||
Object.defineProperty @::, 'firstRenderedScreenRow', get: -> @component.getRenderedRowRange()[0]
|
||||
Object.defineProperty @::, 'lastRenderedScreenRow', get: -> @component.getRenderedRowRange()[1]
|
||||
Object.defineProperty @::, 'active', get: -> @is(@getPane().activeView)
|
||||
Object.defineProperty @::, 'isFocused', get: -> @component?.state.focused
|
||||
|
||||
afterAttach: (onDom) ->
|
||||
return unless onDom
|
||||
return if @attached
|
||||
|
||||
@attached = true
|
||||
props = defaults({@editor, parentView: this}, @props)
|
||||
@component = React.renderComponent(EditorComponent(props), @element)
|
||||
|
||||
node = @component.getDOMNode()
|
||||
|
||||
@scrollView = $(node).find('.scroll-view')
|
||||
@underlayer = $(node).find('.selections').addClass('underlayer')
|
||||
@overlayer = $(node).find('.lines').addClass('overlayer')
|
||||
@hiddenInput = $(node).find('.hidden-input')
|
||||
|
||||
@gutter = $(node).find('.gutter')
|
||||
@gutter.removeClassFromAllLines = (klass) =>
|
||||
Grim.deprecate 'You no longer need to manually add and remove classes. Use `Editor::removeDecorationFromBufferRow()` and related functions'
|
||||
@gutter.find('.line-number').removeClass(klass)
|
||||
|
||||
@gutter.getLineNumberElement = (bufferRow) =>
|
||||
@gutter.find("[data-buffer-row='#{bufferRow}']")
|
||||
|
||||
@gutter.addClassToLine = (bufferRow, klass) =>
|
||||
Grim.deprecate 'You no longer need to manually add and remove classes. Use `Editor::addDecorationToBufferRow()` and related functions'
|
||||
lines = @gutter.find("[data-buffer-row='#{bufferRow}']")
|
||||
lines.addClass(klass)
|
||||
lines.length > 0
|
||||
|
||||
@focus() if @focusOnAttach
|
||||
|
||||
@trigger 'editor:attached', [this]
|
||||
|
||||
scrollTop: (scrollTop) ->
|
||||
if scrollTop?
|
||||
@@ -36,36 +71,21 @@ class ReactEditorView extends View
|
||||
else
|
||||
@editor.getScrollLeft()
|
||||
|
||||
scrollToBottom: ->
|
||||
@editor.setScrollBottom(Infinity)
|
||||
|
||||
scrollToScreenPosition: (screenPosition) ->
|
||||
@editor.scrollToScreenPosition(screenPosition)
|
||||
|
||||
scrollToBufferPosition: (bufferPosition) ->
|
||||
@editor.scrollToBufferPosition(bufferPosition)
|
||||
|
||||
afterAttach: (onDom) ->
|
||||
return unless onDom
|
||||
@attached = true
|
||||
props = defaults({@editor, parentView: this}, @props)
|
||||
@component = React.renderComponent(EditorComponent(props), @element)
|
||||
scrollToCursorPosition: ->
|
||||
@editor.scrollToCursorPosition()
|
||||
|
||||
node = @component.getDOMNode()
|
||||
|
||||
@underlayer = $(node).find('.selections')
|
||||
|
||||
@gutter = $(node).find('.gutter')
|
||||
@gutter.removeClassFromAllLines = (klass) =>
|
||||
Grim.deprecate 'You no longer need to manually add and remove classes. Use `Editor::removeDecorationFromBufferRow()` and related functions'
|
||||
@gutter.find('.line-number').removeClass(klass)
|
||||
|
||||
@gutter.addClassToLine = (bufferRow, klass) =>
|
||||
Grim.deprecate 'You no longer need to manually add and remove classes. Use `Editor::addDecorationToBufferRow()` and related functions'
|
||||
lines = @gutter.find("[data-buffer-row='#{bufferRow}']")
|
||||
lines.addClass(klass)
|
||||
lines.length > 0
|
||||
|
||||
@focus() if @focusOnAttach
|
||||
|
||||
@trigger 'editor:attached', [this]
|
||||
scrollToPixelPosition: (pixelPosition) ->
|
||||
screenPosition = screenPositionForPixelPosition(pixelPosition)
|
||||
@editor.scrollToScreenPosition(screenPosition)
|
||||
|
||||
pixelPositionForBufferPosition: (bufferPosition) ->
|
||||
@editor.pixelPositionForBufferPosition(bufferPosition)
|
||||
@@ -83,6 +103,26 @@ class ReactEditorView extends View
|
||||
@attached = false
|
||||
@trigger 'editor:detached', this
|
||||
|
||||
# Public: Split the editor view left.
|
||||
splitLeft: ->
|
||||
pane = @getPane()
|
||||
pane?.splitLeft(pane?.copyActiveItem()).activeView
|
||||
|
||||
# Public: Split the editor view right.
|
||||
splitRight: ->
|
||||
pane = @getPane()
|
||||
pane?.splitRight(pane?.copyActiveItem()).activeView
|
||||
|
||||
# Public: Split the editor view up.
|
||||
splitUp: ->
|
||||
pane = @getPane()
|
||||
pane?.splitUp(pane?.copyActiveItem()).activeView
|
||||
|
||||
# Public: Split the editor view down.
|
||||
splitDown: ->
|
||||
pane = @getPane()
|
||||
pane?.splitDown(pane?.copyActiveItem()).activeView
|
||||
|
||||
getPane: ->
|
||||
@closest('.pane').view()
|
||||
|
||||
@@ -94,10 +134,77 @@ class ReactEditorView extends View
|
||||
|
||||
hide: ->
|
||||
super
|
||||
@component.hide()
|
||||
@component?.hide()
|
||||
|
||||
show: ->
|
||||
super
|
||||
@component.show()
|
||||
@component?.show()
|
||||
|
||||
pageDown: ->
|
||||
@editor.pageDown()
|
||||
|
||||
pageUp: ->
|
||||
@editor.pageUp()
|
||||
|
||||
getModel: ->
|
||||
@component?.getModel()
|
||||
|
||||
getFirstVisibleScreenRow: ->
|
||||
@editor.getVisibleRowRange()[0]
|
||||
|
||||
getLastVisibleScreenRow: ->
|
||||
@editor.getVisibleRowRange()[1]
|
||||
|
||||
getFontFamily: ->
|
||||
@component?.getFontFamily()
|
||||
|
||||
setFontFamily: (fontFamily)->
|
||||
@component?.setFontFamily(fontFamily)
|
||||
|
||||
getFontSize: ->
|
||||
@component?.getFontSize()
|
||||
|
||||
setFontSize: (fontSize)->
|
||||
@component?.setFontSize(fontSize)
|
||||
|
||||
setWidthInChars: (widthInChars) ->
|
||||
@component.getDOMNode().style.width = (@editor.getDefaultCharWidth() * widthInChars) + 'px'
|
||||
|
||||
setLineHeight: (lineHeight) ->
|
||||
@component.setLineHeight(lineHeight)
|
||||
|
||||
setShowIndentGuide: (showIndentGuide) ->
|
||||
@component.setShowIndentGuide(showIndentGuide)
|
||||
|
||||
setSoftWrap: (softWrap) ->
|
||||
@editor.setSoftWrap(softWrap)
|
||||
|
||||
setShowInvisibles: (showInvisibles) ->
|
||||
@component.setShowInvisibles(showInvisibles)
|
||||
|
||||
toggleSoftWrap: ->
|
||||
@editor.toggleSoftWrap()
|
||||
|
||||
toggleSoftTabs: ->
|
||||
@editor.toggleSoftTabs()
|
||||
|
||||
getText: ->
|
||||
@editor.getText()
|
||||
|
||||
setText: (text) ->
|
||||
@editor.setText(text)
|
||||
|
||||
insertText: (text) ->
|
||||
@editor.insertText(text)
|
||||
|
||||
isInputEnabled: ->
|
||||
@component.isInputEnabled()
|
||||
|
||||
setInputEnabled: (inputEnabled) ->
|
||||
@component.setInputEnabled(inputEnabled)
|
||||
|
||||
requestDisplayUpdate: -> # No-op shim for find-and-replace
|
||||
|
||||
updateDisplay: -> # No-op shim for package specs
|
||||
|
||||
redraw: -> # No-op shim
|
||||
|
||||
Reference in New Issue
Block a user