diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 2e60f3aec..0cffc74da 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -40,6 +40,7 @@ describe "EditorComponent", -> {component} = wrapperView component.performSyncUpdates = false + component.setFontFamily('monospace') component.setLineHeight(1.3) component.setFontSize(20) @@ -1975,7 +1976,7 @@ describe "EditorComponent", -> afterEach -> atom.themes.removeStylesheet('test') - it "does not re-measure character widths until the editor is shown again", -> + fit "does not re-measure character widths until the editor is shown again", -> atom.config.set('editor.fontFamily', 'sans-serif') wrapperView.hide() @@ -1984,7 +1985,6 @@ describe "EditorComponent", -> font-weight: bold; } """ - nextAnimationFrame() wrapperView.show() editor.setCursorBufferPosition([0, Infinity]) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 407cbb8a9..80207c952 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -130,6 +130,8 @@ afterEach -> atom.project?.destroy() atom.project = null + atom.themes.removeStylesheet('global-editor-styles') + delete atom.state.packageStates $('#jasmine-content').empty() unless window.debugContent diff --git a/spec/workspace-view-spec.coffee b/spec/workspace-view-spec.coffee index 082244f83..44dbc2428 100644 --- a/spec/workspace-view-spec.coffee +++ b/spec/workspace-view-spec.coffee @@ -20,7 +20,6 @@ describe "WorkspaceView", -> waitsForPromise -> atom.workspace.open(pathToOpen) - describe "@deserialize()", -> viewState = null @@ -294,3 +293,31 @@ describe "WorkspaceView", -> expect(atom.workspaceView).toHaveClass 'scrollbars-visible-always' scrollbarStyle.emitValue 'overlay' expect(atom.workspaceView).toHaveClass 'scrollbars-visible-when-scrolling' + + describe "editor font styling", -> + [editorNode, editor] = [] + + beforeEach -> + atom.workspaceView.attachToDom() + editorNode = atom.workspaceView.find('.editor')[0] + editor = atom.workspaceView.find('.editor').view().getEditor() + + it "updates the font-size based on the 'editor.fontSize' config value", -> + initialCharWidth = editor.getDefaultCharWidth() + expect(getComputedStyle(editorNode).fontSize).toBe atom.config.get('editor.fontSize') + 'px' + atom.config.set('editor.fontSize', atom.config.get('editor.fontSize') + 5) + expect(getComputedStyle(editorNode).fontSize).toBe atom.config.get('editor.fontSize') + 'px' + expect(editor.getDefaultCharWidth()).toBeGreaterThan initialCharWidth + + it "updates the font-family based on the 'editor.fontFamily' config value", -> + initialCharWidth = editor.getDefaultCharWidth() + expect(getComputedStyle(editorNode).fontFamily).toBe atom.config.get('editor.fontFamily') + atom.config.set('editor.fontFamily', 'sans-serif') + expect(getComputedStyle(editorNode).fontFamily).toBe atom.config.get('editor.fontFamily') + expect(editor.getDefaultCharWidth()).not.toBe initialCharWidth + + it "updates the line-height based on the 'editor.lineHeight' config value", -> + initialLineHeight = editor.getLineHeightInPixels() + atom.config.set('editor.lineHeight', '30px') + expect(getComputedStyle(editorNode).lineHeight).toBe atom.config.get('editor.lineHeight') + expect(editor.getLineHeightInPixels()).not.toBe initialLineHeight diff --git a/src/editor-component.coffee b/src/editor-component.coffee index ffa585d26..fd01764de 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -40,7 +40,7 @@ EditorComponent = React.createClass scrollSensitivity: 0.4 heightAndWidthMeasurementRequested: false measureLineHeightAndDefaultCharWidthWhenShown: false - remeasureCharacterWidthsIfVisibleAfterNextUpdate: false + remeasureCharacterWidthsWhenShown: false inputEnabled: true scopedCharacterWidthsChangeCount: null domPollingInterval: 100 @@ -48,13 +48,12 @@ EditorComponent = React.createClass domPollingPaused: false render: -> - {focused, fontSize, lineHeight, fontFamily, showIndentGuide, showInvisibles, showLineNumbers, visible} = @state + {focused, showIndentGuide, showInvisibles, showLineNumbers, visible} = @state {editor, mini, cursorBlinkPeriod, cursorBlinkResumeDelay} = @props maxLineNumberDigits = editor.getLineCount().toString().length invisibles = if showInvisibles and not mini then @state.invisibles else {} hasSelection = editor.getSelection()? and !editor.getSelection().isEmpty() - style = {fontSize, fontFamily} - style.lineHeight = lineHeight unless mini + style = {} if @performedInitialMeasurement renderedRowRange = @getRenderedRowRange() @@ -177,7 +176,7 @@ EditorComponent = React.createClass @listenForDOMEvents() @listenForCommands() - @subscribe atom.themes, 'stylesheet-added stylsheet-removed', @onStylesheetsChanged + @subscribe atom.themes, 'stylesheet-added stylesheet-removed stylesheet-updated', @onStylesheetsChanged @subscribe scrollbarStyle.changes, @refreshScrollbars if @visible = @isVisible() @@ -212,15 +211,15 @@ EditorComponent = React.createClass if @performedInitialMeasurement @measureScrollbars() if @measuringScrollbars - @measureLineHeightAndDefaultCharWidthIfNeeded(prevState) - @remeasureCharacterWidthsIfNeeded(prevState) performInitialMeasurement: -> @updatesPaused = true - @measureLineHeightAndDefaultCharWidth() @measureHeightAndWidth() + @sampleFontStyling() @sampleBackgroundColors() @measureScrollbars() + @measureLineHeightAndDefaultCharWidth() if @measureLineHeightAndDefaultCharWidthWhenShown + @remeasureCharacterWidths() if @remeasureCharacterWidthsWhenShown @props.editor.setVisible(true) @updatesPaused = false @performedInitialMeasurement = true @@ -250,6 +249,9 @@ EditorComponent = React.createClass @updateRequestedWhilePaused = false @forceUpdate() + getTopmostDOMNode: -> + @props.parentView.element + getRenderedRowRange: -> {editor, lineOverdrawMargin} = @props [visibleStartRow, visibleEndRow] = editor.getVisibleRowRange() @@ -511,9 +513,6 @@ EditorComponent = React.createClass parentView.command command, listener observeConfig: -> - @subscribe atom.config.observe 'editor.fontFamily', @setFontFamily - @subscribe atom.config.observe 'editor.fontSize', @setFontSize - @subscribe atom.config.observe 'editor.lineHeight', @setLineHeight @subscribe atom.config.observe 'editor.showIndentGuide', @setShowIndentGuide @subscribe atom.config.observe 'editor.invisibles', @setInvisibles @subscribe atom.config.observe 'editor.showInvisibles', @setShowInvisibles @@ -668,10 +667,12 @@ EditorComponent = React.createClass editor.setSelectedScreenRange([tailPosition, [dragRow + 1, 0]]) onStylesheetsChanged: (stylesheet) -> + return unless @performedInitialMeasurement + @refreshScrollbars() if @containsScrollbarSelector(stylesheet) + @sampleFontStyling() @sampleBackgroundColors() - @remeasureCharacterWidthsIfVisibleAfterNextUpdate = true - @requestUpdate() if @visible + @remeasureCharacterWidths() onScreenLinesChanged: (change) -> {editor} = @props @@ -769,6 +770,7 @@ EditorComponent = React.createClass if @visible = @isVisible() if wasVisible @measureHeightAndWidth() + @sampleFontStyling() @sampleBackgroundColors() else @performInitialMeasurement() @@ -811,6 +813,19 @@ EditorComponent = React.createClass clientWidth -= paddingLeft editor.setWidth(clientWidth) if clientWidth > 0 + sampleFontStyling: -> + oldFontSize = @fontSize + oldFontFamily = @fontFamily + oldLineHeight = @lineHeight + + {@fontSize, @fontFamily, @lineHeight} = getComputedStyle(@getTopmostDOMNode()) + + if @fontSize isnt oldFontSize or @fontFamily isnt oldFontFamily or @lineHeight isnt oldLineHeight + @measureLineHeightAndDefaultCharWidth() + + if (@fontSize isnt oldFontSize or @fontFamily isnt oldFontFamily) and @performedInitialMeasurement + @remeasureCharacterWidths() + sampleBackgroundColors: (suppressUpdate) -> {parentView} = @props {showLineNumbers} = @state @@ -826,31 +841,19 @@ EditorComponent = React.createClass @gutterBackgroundColor = gutterBackgroundColor @requestUpdate() unless suppressUpdate - measureLineHeightAndDefaultCharWidthIfNeeded: (prevState) -> - if not isEqualForProperties(prevState, @state, 'lineHeight', 'fontSize', 'fontFamily') - if @visible - @measureLineHeightAndDefaultCharWidth() - else - @measureLineHeightAndDefaultCharWidthWhenShown = true - else if @measureLineHeightAndDefaultCharWidthWhenShown and @visible - @measureLineHeightAndDefaultCharWidthWhenShown = false - @measureLineHeightAndDefaultCharWidth() - measureLineHeightAndDefaultCharWidth: -> - @refs.lines.measureLineHeightAndDefaultCharWidth() - - remeasureCharacterWidthsIfNeeded: (prevState) -> - if not isEqualForProperties(prevState, @state, 'fontSize', 'fontFamily') - if @visible - @remeasureCharacterWidths() - else - @remeasureCharacterWidthsIfVisibleAfterNextUpdate = true - else if @remeasureCharacterWidthsIfVisibleAfterNextUpdate and @visible - @remeasureCharacterWidthsIfVisibleAfterNextUpdate = false - @remeasureCharacterWidths() + if @visible + @measureLineHeightAndDefaultCharWidthWhenShown = false + @refs.lines.measureLineHeightAndDefaultCharWidth() + else + @measureLineHeightAndDefaultCharWidthWhenShown = true remeasureCharacterWidths: -> - @refs.lines.remeasureCharacterWidths() + if @visible + @remeasureCharacterWidthsWhenShown = false + @refs.lines.remeasureCharacterWidths() + else + @remeasureCharacterWidthsWhenShown = true measureScrollbars: -> return unless @visible @@ -911,19 +914,22 @@ EditorComponent = React.createClass null getFontSize: -> - @state.fontSize + parseInt(getComputedStyle(@getTopmostDOMNode()).fontSize) setFontSize: (fontSize) -> - @setState({fontSize}) + @getTopmostDOMNode().style.fontSize = fontSize + 'px' + @sampleFontStyling() getFontFamily: -> - @state.fontFamily + getComputedStyle(@getTopmostDOMNode()).fontFamily setFontFamily: (fontFamily) -> - @setState({fontFamily}) + @getTopmostDOMNode().style.fontFamily = fontFamily + @sampleFontStyling() setLineHeight: (lineHeight) -> - @setState({lineHeight}) + @getTopmostDOMNode().style.lineHeight = lineHeight + @sampleFontStyling() setShowIndentGuide: (showIndentGuide) -> @setState({showIndentGuide}) diff --git a/src/workspace-view.coffee b/src/workspace-view.coffee index f055a0d45..4206e9f83 100644 --- a/src/workspace-view.coffee +++ b/src/workspace-view.coffee @@ -96,6 +96,11 @@ class WorkspaceView extends View when 'overlay' @addClass("scrollbars-visible-when-scrolling") + + @subscribe atom.config.observe 'editor.fontSize', @setEditorFontSize + @subscribe atom.config.observe 'editor.fontFamily', @setEditorFontFamily + @subscribe atom.config.observe 'editor.lineHeight', @setEditorLineHeight + @updateTitle() @on 'focus', (e) => @handleFocus(e) @@ -340,6 +345,26 @@ class WorkspaceView extends View beforeRemove: -> @model.destroy() + setEditorFontSize: (fontSize) => + @setEditorStyle('font-size', fontSize + 'px') + + setEditorFontFamily: (fontFamily) => + @setEditorStyle('font-family', fontFamily) + + setEditorLineHeight: (lineHeight) => + @setEditorStyle('line-height', lineHeight) + + setEditorStyle: (property, value) -> + unless styleNode = atom.themes.stylesheetElementForId('global-editor-styles')[0] + atom.themes.applyStylesheet('global-editor-styles', '.editor {}') + styleNode = atom.themes.stylesheetElementForId('global-editor-styles')[0] + + {sheet} = styleNode + editorRule = sheet.cssRules[0] + editorRule.style[property] = value + atom.themes.emit 'stylesheet-updated', sheet + atom.themes.emit 'stylesheets-changed' + # Deprecated eachPane: (callback) -> deprecate("Use WorkspaceView::eachPaneView instead")