diff --git a/spec/text-editor-element-spec.coffee b/spec/text-editor-element-spec.coffee index 256f31968..5ce987c00 100644 --- a/spec/text-editor-element-spec.coffee +++ b/spec/text-editor-element-spec.coffee @@ -229,6 +229,24 @@ describe "TextEditorElement", -> element.getModel().setMini(false) expect(element.hasAttribute('mini')).toBe false + describe "when the editor's autoHeight parameter changes", -> + it "changes the element's height", -> + editor = atom.workspace.buildTextEditor() + jasmine.attachToDOM(editor.element) + expect(editor.element.style.height).toBe('') + + waitsForPromise -> + editor.update({autoHeight: false}) + + runs -> + expect(editor.element.style.height).toBe('100%') + + waitsForPromise -> + editor.update({autoHeight: true}) + + runs -> + expect(editor.element.style.height).toBe('') + describe "events", -> element = null diff --git a/spec/text-editor-spec.coffee b/spec/text-editor-spec.coffee index a4c5ff4f5..dc13ff0bc 100644 --- a/spec/text-editor-spec.coffee +++ b/spec/text-editor-spec.coffee @@ -79,6 +79,33 @@ describe "TextEditor", -> editor2.unfoldBufferRow(4) expect(editor2.isFoldedAtBufferRow(4)).not.toBe editor.isFoldedAtBufferRow(4) + describe ".update()", -> + it "updates the editor with the supplied config parameters", -> + element = editor.element # force element initialization + editor.setShowInvisibles(true) + editor.onDidChange(changeSpy = jasmine.createSpy('onDidChange')) + + updatePromise = editor.update({ + tabLength: 6, softTabs: false, softWrapped: true, editorWidthInChars: 40, + showInvisibles: false, mini: false, lineNumberGutterVisible: false, scrollPastEnd: true, + autoHeight: false + }) + + waitsForPromise -> + updatePromise + + runs -> + expect(changeSpy.callCount).toBe(1) + expect(editor.getTabLength()).toBe(6) + expect(editor.getSoftTabs()).toBe(false) + expect(editor.isSoftWrapped()).toBe(true) + expect(editor.getEditorWidthInChars()).toBe(40) + expect(editor.getInvisibles()).toEqual({}) + expect(editor.isMini()).toBe(false) + expect(editor.isLineNumberGutterVisible()).toBe(false) + expect(editor.getScrollPastEnd()).toBe(true) + expect(editor.getAutoHeight()).toBe(false) + describe "title", -> describe ".getTitle()", -> it "uses the basename of the buffer's path as its title, or 'untitled' if the path is undefined", -> @@ -5451,6 +5478,22 @@ describe "TextEditor", -> expect(scrollSpy).toHaveBeenCalledWith(screenRange: [[8, 20], [8, 20]], options: {center: true}) expect(scrollSpy).toHaveBeenCalledWith(screenRange: [[8, 20], [8, 20]], options: {center: false, reversed: true}) + describe "scroll past end", -> + it "returns false by default but can be customized", -> + expect(editor.getScrollPastEnd()).toBe(false) + editor.setScrollPastEnd(true) + expect(editor.getScrollPastEnd()).toBe(true) + editor.setScrollPastEnd(false) + expect(editor.getScrollPastEnd()).toBe(false) + + describe "auto height", -> + it "returns true by default but can be customized", -> + expect(editor.getAutoHeight()).toBe(true) + editor.setAutoHeight(false) + expect(editor.getAutoHeight()).toBe(false) + editor.setAutoHeight(true) + expect(editor.getAutoHeight()).toBe(true) + describe '.get/setPlaceholderText()', -> it 'can be created with placeholderText', -> newEditor = atom.workspace.buildTextEditor( diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index 744f82770..1d5bf1b67 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -42,7 +42,7 @@ class TextEditorComponent @assert domNode?, "TextEditorComponent::domNode was set to null." @domNodeValue = domNode - constructor: ({@editor, @hostElement, @rootElement, @stylesElement, tileSize, @views, @themes, @assert, scrollPastEnd}) -> + constructor: ({@editor, @hostElement, @rootElement, @stylesElement, tileSize, @views, @themes, @assert}) -> @tileSize = tileSize if tileSize? @disposables = new CompositeDisposable @@ -56,7 +56,6 @@ class TextEditorComponent cursorBlinkResumeDelay: @cursorBlinkResumeDelay stoppedScrollingDelay: 200 lineTopIndex: lineTopIndex - scrollPastEnd: scrollPastEnd @presenter.onDidUpdateState(@requestUpdate) diff --git a/src/text-editor-element.coffee b/src/text-editor-element.coffee index 42bce4978..21ff45ef0 100644 --- a/src/text-editor-element.coffee +++ b/src/text-editor-element.coffee @@ -17,8 +17,6 @@ class TextEditorElement extends HTMLElement focusOnAttach: false hasTiledRendering: true logicalDisplayBuffer: true - scrollPastEnd: true - autoHeight: true createdCallback: -> # Use globals when the following instance variables aren't set. @@ -38,7 +36,7 @@ class TextEditorElement extends HTMLElement @setAttribute('tabindex', -1) initializeContent: (attributes) -> - unless @autoHeight + unless @getModel().getAutoHeight() @style.height = "100%" unless ShadowStyleSheet? @@ -80,7 +78,7 @@ class TextEditorElement extends HTMLElement @subscriptions.add @component.onDidChangeScrollLeft => @emitter.emit("did-change-scroll-left", arguments...) - initialize: (model, {@views, @themes, @workspace, @assert, @styles}, @autoHeight = true, @scrollPastEnd = true) -> + initialize: (model, {@views, @themes, @workspace, @assert, @styles}) -> throw new Error("Must pass a views parameter when initializing TextEditorElements") unless @views? throw new Error("Must pass a themes parameter when initializing TextEditorElements") unless @themes? throw new Error("Must pass a workspace parameter when initializing TextEditorElements") unless @workspace? @@ -132,7 +130,6 @@ class TextEditorElement extends HTMLElement themes: @themes workspace: @workspace assert: @assert - scrollPastEnd: @scrollPastEnd ) @rootElement.appendChild(@component.getDomNode()) @@ -169,6 +166,13 @@ class TextEditorElement extends HTMLElement removeMiniAttribute: -> @removeAttribute("mini") + didChangeAutoHeight: -> + @views.updateDocument => + if @getModel().getAutoHeight() + @style.height = "" + else + @style.height = "100%" + addEncodingAttribute: -> @dataset.encoding = @model.getEncoding() diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 3e3972505..59eb4a9f8 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -187,6 +187,60 @@ class TextEditor extends Model priority: 0 visible: lineNumberGutterVisible + update: (params) -> + { + softTabs, tabLength, softWrapped, mini, placeholderText, lineNumberGutterVisible, + showInvisibles, ignoreInvisibles, editorWidthInChars, scrollPastEnd, autoHeight + } = params + + resetDisplayLayer = false + + if softTabs? and softTabs isnt @softTabs + @setSoftTabs(softTabs) + + if tabLength? and tabLength isnt @tabLength + @setTabLength(tabLength, false) + resetDisplayLayer = true + + if softWrapped? and softWrapped isnt @softWrapped + @setSoftWrapped(softWrapped, false) + resetDisplayLayer = true + + if mini? and mini isnt @mini + @setMini(mini) + + if placeholderText? and placeholderText isnt @placeholderText + @setPlaceholderText(placeholderText) + + if lineNumberGutterVisible? and lineNumberGutterVisible isnt @lineNumberGutterVisible + @setLineNumberGutterVisible(lineNumberGutterVisible) + + if showInvisibles? and showInvisibles isnt @showInvisibles + @showInvisibles = showInvisibles + resetDisplayLayer = true + + if ignoreInvisibles? and ignoreInvisibles isnt @ignoreInvisibles + @setIgnoreInvisibles(ignoreInvisibles, false) + resetDisplayLayer = true + + if editorWidthInChars? and editorWidthInChars isnt @editorWidthInChars + @setEditorWidthInChars(editorWidthInChars, false) + resetDisplayLayer = true + + if scrollPastEnd? and scrollPastEnd isnt @scrollPastEnd + @setScrollPastEnd(scrollPastEnd) + + if autoHeight? and autoHeight isnt @autoHeight + @setAutoHeight(autoHeight) + + if resetDisplayLayer + @resetDisplayLayer() + + if @editorElement? + @editorElement.views.getNextUpdatePromise() + else + Promise.resolve() + serialize: -> tokenizedBufferState = @tokenizedBuffer.serialize() @@ -627,12 +681,12 @@ class TextEditor extends Model # # * `editorWidthInChars` A {Number} representing the width of the # {TextEditorElement} in characters. - setEditorWidthInChars: (editorWidthInChars) -> + setEditorWidthInChars: (editorWidthInChars, resetDisplayLayer=true) -> if editorWidthInChars > 0 previousWidthInChars = @editorWidthInChars @editorWidthInChars = editorWidthInChars if editorWidthInChars isnt previousWidthInChars and @isSoftWrapped() - @resetDisplayLayer() + @resetDisplayLayer() if resetDisplayLayer # Returns the editor width in characters. getEditorWidthInChars: -> @@ -2721,12 +2775,12 @@ class TextEditor extends Model # # * `tabLength` {Number} length of a single tab. Setting to `null` will # fallback to using the `editor.tabLength` config setting - setTabLength: (tabLength) -> + setTabLength: (tabLength, resetDisplayLayer=true) -> return if tabLength is @tabLength @tabLength = tabLength @tokenizedBuffer.setTabLength(@tabLength) - @resetDisplayLayer() + @resetDisplayLayer() if resetDisplayLayer # Returns a {Boolean} indicating whether atomic soft tabs are enabled for this editor. doesShowInvisibles: -> @showInvisibles @@ -2739,6 +2793,12 @@ class TextEditor extends Model @showInvisibles = showInvisibles @resetDisplayLayer() + setIgnoreInvisibles: (ignoreInvisibles, resetDisplayLayer=true) -> + return if ignoreInvisibles is @ignoreInvisibles + + @ignoreInvisibles = ignoreInvisibles + @resetDisplayLayer() if resetDisplayLayer + # Returns an {Object} representing the current invisible character # substitutions for this editor. See {::setInvisibles}. getInvisibles: -> @@ -2820,10 +2880,10 @@ class TextEditor extends Model # * `softWrapped` A {Boolean} # # Returns a {Boolean}. - setSoftWrapped: (softWrapped) -> + setSoftWrapped: (softWrapped, resetDisplayLayer=true) -> if softWrapped isnt @softWrapped @softWrapped = softWrapped - @resetDisplayLayer() + @resetDisplayLayer() if resetDisplayLayer softWrapped = @isSoftWrapped() @emitter.emit 'did-change-soft-wrapped', softWrapped softWrapped @@ -3306,6 +3366,20 @@ class TextEditor extends Model scrollEvent = {screenRange, options} @emitter.emit "did-request-autoscroll", scrollEvent + getScrollPastEnd: -> + if @scrollPastEnd? + @scrollPastEnd + else + @config.get('editor.scrollPastEnd', scope: @getRootScopeDescriptor()) + + setScrollPastEnd: (scrollPastEnd) -> + if scrollPastEnd isnt @scrollPastEnd + @scrollPastEnd = scrollPastEnd + @emitter.emit('did-change-scroll-past-end') + + onDidChangeScrollPastEnd: (callback) -> + @emitter.on('did-change-scroll-past-end', callback) + getHorizontalScrollbarHeight: -> Grim.deprecate("This is now a view method. Call TextEditorElement::getHorizontalScrollbarHeight instead.") @@ -3463,7 +3537,7 @@ class TextEditor extends Model # Get the Element for the editor. getElement: -> - @editorElement ?= new TextEditorElement().initialize(this, atom, @autoHeight, @scrollPastEnd) + @editorElement ?= new TextEditorElement().initialize(this, atom) # Essential: Retrieves the greyed out placeholder of a mini editor. # @@ -3538,6 +3612,13 @@ class TextEditor extends Model Grim.deprecate("This is now a view method. Call TextEditorElement::getHeight instead.") @height + getAutoHeight: -> @autoHeight + + setAutoHeight: (autoHeight) -> + if autoHeight isnt @autoHeight + @autoHeight = autoHeight + @editorElement?.didChangeAutoHeight() + setWidth: (width, reentrant=false) -> if reentrant oldWidth = @width