mirror of
https://github.com/atom/atom.git
synced 2026-04-28 03:01:47 -04:00
It doesn’t make sense to talk about pixels at the model layer long-term, even though we currently store view dimension information in the model so we don’t have to read from the DOM for optimization purposes. This information is only available if the view is attached, however, making these methods a liability on the model layer.
329 lines
11 KiB
CoffeeScript
329 lines
11 KiB
CoffeeScript
{View, $} = require 'space-pen'
|
|
React = require 'react-atom-fork'
|
|
{defaults} = require 'underscore-plus'
|
|
TextBuffer = require 'text-buffer'
|
|
TextEditor = require './text-editor'
|
|
TextEditorElement = require './text-editor-element'
|
|
TextEditorComponent = require './text-editor-component'
|
|
{deprecate} = require 'grim'
|
|
|
|
# Deprecated: Represents the entire visual pane in Atom.
|
|
#
|
|
# The TextEditorView manages the {TextEditor}, which manages the file buffers.
|
|
# `TextEditorView` is intentionally sparse. Most of the things you'll want
|
|
# to do are on {TextEditor}.
|
|
#
|
|
# ## Examples
|
|
#
|
|
# Requiring in packages
|
|
#
|
|
# ```coffee
|
|
# {TextEditorView} = require 'atom'
|
|
#
|
|
# miniEditorView = new TextEditorView(mini: true)
|
|
# ```
|
|
#
|
|
# Iterating over the open editor views
|
|
#
|
|
# ```coffee
|
|
# for editorView in atom.workspaceView.getEditorViews()
|
|
# console.log(editorView.getModel().getPath())
|
|
# ```
|
|
#
|
|
# Subscribing to every current and future editor
|
|
#
|
|
# ```coffee
|
|
# atom.workspace.eachEditorView (editorView) ->
|
|
# console.log(editorView.getModel().getPath())
|
|
# ```
|
|
module.exports =
|
|
class TextEditorView extends View
|
|
# The constructor for setting up an `TextEditorView` instance.
|
|
#
|
|
# * `modelOrParams` Either an {TextEditor}, or an object with one property, `mini`.
|
|
# If `mini` is `true`, a "miniature" `TextEditor` is constructed.
|
|
# Typically, this is ideal for scenarios where you need an Atom editor,
|
|
# but without all the chrome, like scrollbars, gutter, _e.t.c._.
|
|
#
|
|
constructor: (modelOrParams, props) ->
|
|
# Handle direct construction with an editor or params
|
|
unless modelOrParams instanceof HTMLElement
|
|
if modelOrParams instanceof TextEditor
|
|
model = modelOrParams
|
|
else
|
|
{editor, mini, placeholderText, attributes} = modelOrParams
|
|
model = editor ? new TextEditor
|
|
buffer: new TextBuffer
|
|
softWrapped: false
|
|
tabLength: 2
|
|
softTabs: true
|
|
mini: mini
|
|
placeholderText: placeholderText
|
|
|
|
element = new TextEditorElement
|
|
element.lineOverdrawMargin = props?.lineOverdrawMargin
|
|
element.setAttribute(name, value) for name, value of attributes if attributes?
|
|
element.setModel(model)
|
|
return element.__spacePenView
|
|
|
|
# Handle construction with an element
|
|
@element = modelOrParams
|
|
super
|
|
|
|
setModel: (@model) ->
|
|
@editor = @model
|
|
|
|
@root = $(@element.rootElement)
|
|
|
|
@scrollView = @root.find('.scroll-view')
|
|
|
|
if atom.config.get('editor.useShadowDOM')
|
|
@underlayer = $("<div class='underlayer'></div>").appendTo(this)
|
|
@overlayer = $("<div class='overlayer'></div>").appendTo(this)
|
|
else
|
|
@underlayer = @find('.highlights').addClass('underlayer')
|
|
@overlayer = @find('.lines').addClass('overlayer')
|
|
|
|
@hiddenInput = @root.find('.hidden-input')
|
|
|
|
@hiddenInput.on = (args...) =>
|
|
args[0] = 'blur' if args[0] is 'focusout'
|
|
$::on.apply(this, args)
|
|
|
|
@subscribe atom.config.observe 'editor.showLineNumbers', =>
|
|
@gutter = @root.find('.gutter')
|
|
|
|
@gutter.removeClassFromAllLines = (klass) =>
|
|
deprecate('Use decorations instead: http://blog.atom.io/2014/07/24/decorations.html')
|
|
@gutter.find('.line-number').removeClass(klass)
|
|
|
|
@gutter.getLineNumberElement = (bufferRow) =>
|
|
deprecate('Use decorations instead: http://blog.atom.io/2014/07/24/decorations.html')
|
|
@gutter.find("[data-buffer-row='#{bufferRow}']")
|
|
|
|
@gutter.addClassToLine = (bufferRow, klass) =>
|
|
deprecate('Use decorations instead: http://blog.atom.io/2014/07/24/decorations.html')
|
|
lines = @gutter.find("[data-buffer-row='#{bufferRow}']")
|
|
lines.addClass(klass)
|
|
lines.length > 0
|
|
|
|
find: ->
|
|
shadowResult = @root.find.apply(@root, arguments)
|
|
if shadowResult.length > 0
|
|
shadowResult
|
|
else
|
|
super
|
|
|
|
# Public: Get the underlying editor model for this view.
|
|
#
|
|
# Returns an {TextEditor}
|
|
getModel: -> @model
|
|
|
|
getEditor: -> @model
|
|
|
|
Object.defineProperty @::, 'lineHeight', get: -> @model.getLineHeightInPixels()
|
|
Object.defineProperty @::, 'charWidth', get: -> @model.getDefaultCharWidth()
|
|
Object.defineProperty @::, 'firstRenderedScreenRow', get: -> @component.getRenderedRowRange()[0]
|
|
Object.defineProperty @::, 'lastRenderedScreenRow', get: -> @component.getRenderedRowRange()[1]
|
|
Object.defineProperty @::, 'active', get: -> @is(@getPaneView()?.activeView)
|
|
Object.defineProperty @::, 'isFocused', get: -> document.activeElement is @element or document.activeElement is @element.component?.refs.input.getDOMNode()
|
|
Object.defineProperty @::, 'mini', get: -> @component?.props.mini
|
|
Object.defineProperty @::, 'component', get: -> @element?.component
|
|
|
|
afterAttach: (onDom) ->
|
|
return unless onDom
|
|
return if @attached
|
|
@attached = true
|
|
@trigger 'editor:attached', [this]
|
|
|
|
beforeRemove: ->
|
|
@trigger 'editor:detached', [this]
|
|
@trigger 'editor:will-be-removed', [this]
|
|
@attached = false
|
|
|
|
remove: (selector, keepData) ->
|
|
@model.destroy() unless keepData
|
|
super
|
|
|
|
scrollTop: (scrollTop) ->
|
|
if scrollTop?
|
|
@model.setScrollTop(scrollTop)
|
|
else
|
|
@model.getScrollTop()
|
|
|
|
scrollLeft: (scrollLeft) ->
|
|
if scrollLeft?
|
|
@model.setScrollLeft(scrollLeft)
|
|
else
|
|
@model.getScrollLeft()
|
|
|
|
scrollToBottom: ->
|
|
deprecate 'Use TextEditor::scrollToBottom instead. You can get the editor via editorView.getModel()'
|
|
@model.setScrollBottom(Infinity)
|
|
|
|
scrollToScreenPosition: (screenPosition, options) ->
|
|
deprecate 'Use TextEditor::scrollToScreenPosition instead. You can get the editor via editorView.getModel()'
|
|
@model.scrollToScreenPosition(screenPosition, options)
|
|
|
|
scrollToBufferPosition: (bufferPosition, options) ->
|
|
deprecate 'Use TextEditor::scrollToBufferPosition instead. You can get the editor via editorView.getModel()'
|
|
@model.scrollToBufferPosition(bufferPosition, options)
|
|
|
|
scrollToCursorPosition: ->
|
|
deprecate 'Use TextEditor::scrollToCursorPosition instead. You can get the editor via editorView.getModel()'
|
|
@model.scrollToCursorPosition()
|
|
|
|
pixelPositionForBufferPosition: (bufferPosition) ->
|
|
deprecate 'Use TextEditorElement::pixelPositionForBufferPosition instead. You can get the editor via editorView.getModel()'
|
|
@model.pixelPositionForBufferPosition(bufferPosition, true)
|
|
|
|
pixelPositionForScreenPosition: (screenPosition) ->
|
|
deprecate 'Use TextEditorElement::pixelPositionForScreenPosition instead. You can get the editor via editorView.getModel()'
|
|
@model.pixelPositionForScreenPosition(screenPosition, true)
|
|
|
|
appendToLinesView: (view) ->
|
|
view.css('position', 'absolute')
|
|
view.css('z-index', 1)
|
|
@overlayer.append(view)
|
|
|
|
unmountComponent: ->
|
|
React.unmountComponentAtNode(@element) if @component.isMounted()
|
|
|
|
splitLeft: ->
|
|
deprecate """
|
|
Use Pane::splitLeft instead.
|
|
To duplicate this editor into the split use:
|
|
editorView.getPaneView().getModel().splitLeft(copyActiveItem: true)
|
|
"""
|
|
pane = @getPaneView()
|
|
pane?.splitLeft(pane?.copyActiveItem()).activeView
|
|
|
|
splitRight: ->
|
|
deprecate """
|
|
Use Pane::splitRight instead.
|
|
To duplicate this editor into the split use:
|
|
editorView.getPaneView().getModel().splitRight(copyActiveItem: true)
|
|
"""
|
|
pane = @getPaneView()
|
|
pane?.splitRight(pane?.copyActiveItem()).activeView
|
|
|
|
splitUp: ->
|
|
deprecate """
|
|
Use Pane::splitUp instead.
|
|
To duplicate this editor into the split use:
|
|
editorView.getPaneView().getModel().splitUp(copyActiveItem: true)
|
|
"""
|
|
pane = @getPaneView()
|
|
pane?.splitUp(pane?.copyActiveItem()).activeView
|
|
|
|
splitDown: ->
|
|
deprecate """
|
|
Use Pane::splitDown instead.
|
|
To duplicate this editor into the split use:
|
|
editorView.getPaneView().getModel().splitDown(copyActiveItem: true)
|
|
"""
|
|
pane = @getPaneView()
|
|
pane?.splitDown(pane?.copyActiveItem()).activeView
|
|
|
|
# Public: Get this {TextEditorView}'s {PaneView}.
|
|
#
|
|
# Returns a {PaneView}
|
|
getPaneView: ->
|
|
@parent('.item-views').parents('atom-pane').view()
|
|
getPane: ->
|
|
deprecate 'Use TextEditorView::getPaneView() instead'
|
|
@getPaneView()
|
|
|
|
show: ->
|
|
super
|
|
@component?.checkForVisibilityChange()
|
|
|
|
hide: ->
|
|
super
|
|
@component?.checkForVisibilityChange()
|
|
|
|
pageDown: ->
|
|
deprecate('Use editorView.getModel().pageDown()')
|
|
@model.pageDown()
|
|
|
|
pageUp: ->
|
|
deprecate('Use editorView.getModel().pageUp()')
|
|
@model.pageUp()
|
|
|
|
getFirstVisibleScreenRow: ->
|
|
deprecate 'Use TextEditor::getFirstVisibleScreenRow instead. You can get the editor via editorView.getModel()'
|
|
@model.getFirstVisibleScreenRow()
|
|
|
|
getLastVisibleScreenRow: ->
|
|
deprecate 'Use TextEditor::getLastVisibleScreenRow instead. You can get the editor via editorView.getModel()'
|
|
@model.getLastVisibleScreenRow()
|
|
|
|
getFontFamily: ->
|
|
deprecate 'This is going away. Use atom.config.get("editor.fontFamily") instead'
|
|
@component?.getFontFamily()
|
|
|
|
setFontFamily: (fontFamily) ->
|
|
deprecate 'This is going away. Use atom.config.set("editor.fontFamily", "my-font") instead'
|
|
@component?.setFontFamily(fontFamily)
|
|
|
|
getFontSize: ->
|
|
deprecate 'This is going away. Use atom.config.get("editor.fontSize") instead'
|
|
@component?.getFontSize()
|
|
|
|
setFontSize: (fontSize) ->
|
|
deprecate 'This is going away. Use atom.config.set("editor.fontSize", 12) instead'
|
|
@component?.setFontSize(fontSize)
|
|
|
|
setLineHeight: (lineHeight) ->
|
|
deprecate 'This is going away. Use atom.config.set("editor.lineHeight", 1.5) instead'
|
|
@component.setLineHeight(lineHeight)
|
|
|
|
setWidthInChars: (widthInChars) ->
|
|
@component.getDOMNode().style.width = (@model.getDefaultCharWidth() * widthInChars) + 'px'
|
|
|
|
setShowIndentGuide: (showIndentGuide) ->
|
|
deprecate 'This is going away. Use atom.config.set("editor.showIndentGuide", true|false) instead'
|
|
@component.setShowIndentGuide(showIndentGuide)
|
|
|
|
setSoftWrap: (softWrapped) ->
|
|
deprecate 'Use TextEditor::setSoftWrapped instead. You can get the editor via editorView.getModel()'
|
|
@model.setSoftWrapped(softWrapped)
|
|
|
|
setShowInvisibles: (showInvisibles) ->
|
|
deprecate 'This is going away. Use atom.config.set("editor.showInvisibles", true|false) instead'
|
|
@component.setShowInvisibles(showInvisibles)
|
|
|
|
getText: ->
|
|
@model.getText()
|
|
|
|
setText: (text) ->
|
|
@model.setText(text)
|
|
|
|
insertText: (text) ->
|
|
@model.insertText(text)
|
|
|
|
isInputEnabled: ->
|
|
@component.isInputEnabled()
|
|
|
|
setInputEnabled: (inputEnabled) ->
|
|
@component.setInputEnabled(inputEnabled)
|
|
|
|
requestDisplayUpdate: ->
|
|
deprecate('Please remove from your code. ::requestDisplayUpdate no longer does anything')
|
|
|
|
updateDisplay: ->
|
|
deprecate('Please remove from your code. ::updateDisplay no longer does anything')
|
|
|
|
resetDisplay: ->
|
|
deprecate('Please remove from your code. ::resetDisplay no longer does anything')
|
|
|
|
redraw: ->
|
|
deprecate('Please remove from your code. ::redraw no longer does anything')
|
|
|
|
setPlaceholderText: (placeholderText) ->
|
|
deprecate('Use TextEditor::setPlaceholderText instead. eg. editorView.getModel().setPlaceholderText(text)')
|
|
@model.setPlaceholderText(placeholderText)
|
|
|
|
lineElementForScreenRow: (screenRow) ->
|
|
$(@component.lineNodeForScreenRow(screenRow))
|