From 5f253d78e9285d3f112df22f597ddea0ed6bd4ae Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 25 Sep 2012 13:27:46 -0600 Subject: [PATCH] Optimization: Use absolute positioning instead of flexbox in editor Flexbox was causing layouts and repaints to cover the entire scroll view instead of just the edited line. This cuts down on DOM manipulation cost significantly. --- spec/app/editor-spec.coffee | 16 ++++++++++++++-- spec/spec-helper.coffee | 2 +- src/app/editor.coffee | 16 +++++++++------- src/app/gutter.coffee | 12 ++++++++---- static/editor.css | 15 ++++++--------- 5 files changed, 38 insertions(+), 23 deletions(-) diff --git a/spec/app/editor-spec.coffee b/spec/app/editor-spec.coffee index 7b6a3d6ea..ba026ac43 100644 --- a/spec/app/editor-spec.coffee +++ b/spec/app/editor-spec.coffee @@ -517,7 +517,7 @@ describe "Editor", -> describe "mouse events", -> beforeEach -> editor.attachToDom() - editor.css(position: 'absolute', top: 10, left: 10) + editor.css(position: 'absolute', top: 10, left: 10, width: 400) describe "single-click", -> it "re-positions the cursor to the clicked row / column", -> @@ -1483,12 +1483,17 @@ describe "Editor", -> it "sets the width based on largest line number", -> expect(editor.gutter.lineNumbers.outerWidth()).toBe editor.charWidth * 2 - it "updates the width when total number of lines gains a digit", -> + it "updates the width and the left position of the scroll view when total number of lines gains a digit", -> editor.setText("") + expect(editor.gutter.lineNumbers.outerWidth()).toBe editor.charWidth * 1 + expect(parseInt(editor.scrollView.css('left'))).toBe editor.gutter.outerWidth() + for i in [1..9] # Ends on an empty line 10 editor.insertText "#{i}\n" + expect(editor.gutter.lineNumbers.outerWidth()).toBe editor.charWidth * 2 + expect(parseInt(editor.scrollView.css('left'))).toBe editor.gutter.outerWidth() describe "when lines are inserted", -> it "re-renders the correct line number range in the gutter", -> @@ -1564,6 +1569,13 @@ describe "Editor", -> expect(editor.gutter.find('.line-number:first').text()).toBe "2" expect(editor.gutter.find('.line-number:last').text()).toBe "11" + describe "when the editor is mini", -> + it "hides the gutter and does not change the scroll view's left position", -> + miniEditor = new Editor(mini: true) + miniEditor.attachToDom() + expect(miniEditor.gutter).toBeHidden() + expect(miniEditor.scrollView.css('left')).toBe '0px' + describe "folding", -> beforeEach -> editSession = rootView.project.buildEditSessionForPath('two-hundred.txt') diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index a78cef439..dafe5de7e 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -147,7 +147,7 @@ window.tokensText = (tokens) -> _.pluck(tokens, 'value').join('') window.setEditorWidthInChars = (editor, widthInChars, charWidth=editor.charWidth) -> - editor.width(charWidth * widthInChars + editor.renderedLines.position().left) + editor.width(charWidth * widthInChars + editor.gutter.outerWidth()) $(window).trigger 'resize' # update width of editor's on-screen lines window.setEditorHeightInLines = (editor, heightInChars, charHeight=editor.lineHeight) -> diff --git a/src/app/editor.coffee b/src/app/editor.coffee index 426998e3e..61feaf020 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -19,10 +19,9 @@ class Editor extends View @content: (params) -> @div class: @classes(params), tabindex: -1, => @input class: 'hidden-input', outlet: 'hiddenInput' - @div class: 'flexbox', => - @subview 'gutter', new Gutter - @div class: 'scroll-view', outlet: 'scrollView', => - @div class: 'lines', outlet: 'renderedLines', => + @subview 'gutter', new Gutter + @div class: 'scroll-view', outlet: 'scrollView', => + @div class: 'lines', outlet: 'renderedLines', => @div class: 'vertical-scrollbar', outlet: 'verticalScrollbar', => @div outlet: 'verticalScrollbarContent' @@ -135,7 +134,7 @@ class Editor extends View 'page-down': @pageDown 'page-up': @pageUp - if not @mini + unless @mini _.extend editorBindings, 'save': @save 'newline-below': @insertNewlineBelow @@ -154,7 +153,6 @@ class Editor extends View 'show-previous-buffer': @loadPreviousEditSession 'toggle-line-comments': @toggleLineCommentsInSelection - for name, method of editorBindings do (name, method) => @on name, => method.call(this); false @@ -331,6 +329,10 @@ class Editor extends View @verticalScrollbar.on 'scroll', => @scrollTop(@verticalScrollbar.scrollTop(), adjustVerticalScrollbar: false) + unless @mini + @gutter.widthChanged = (newWidth) => + @scrollView.css('left', newWidth + 'px') + @scrollView.on 'scroll', => if @scrollView.scrollLeft() == 0 @gutter.removeClass('drop-shadow') @@ -680,7 +682,7 @@ class Editor extends View @height(@lineHeight) if @mini fragment.remove() - @gutter.calculateDimensions() + @gutter.calculateWidth() prepareForScrolling: -> @adjustHeightOfRenderedLines() diff --git a/src/app/gutter.coffee b/src/app/gutter.coffee index d86d62f60..daca70157 100644 --- a/src/app/gutter.coffee +++ b/src/app/gutter.coffee @@ -10,7 +10,7 @@ class Gutter extends View @div outlet: 'lineNumbers', class: 'line-numbers' editor: -> - editor = @parentView + @parentView renderLineNumbers: (startScreenRow, endScreenRow) -> lastScreenRow = -1 @@ -21,7 +21,11 @@ class Gutter extends View @div {class: 'line-number'}, if row == lastScreenRow then '•' else row + 1 lastScreenRow = row - @calculateDimensions() + @calculateWidth() - calculateDimensions: -> - @lineNumbers.width(@editor().getLineCount().toString().length * @editor().charWidth) + calculateWidth: -> + width = @editor().getLineCount().toString().length * @editor().charWidth + if width != @cachedWidth + @cachedWidth = width + @lineNumbers.width(width) + @widthChanged?(@outerWidth()) diff --git a/static/editor.css b/static/editor.css index 96602ef00..9d43e8c40 100644 --- a/static/editor.css +++ b/static/editor.css @@ -12,16 +12,8 @@ height: auto; } -.editor .flexbox { - display: -webkit-box; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; -} - .editor .gutter { + position: absolute; height: 100%; overflow: hidden; padding-left: 0.4em; @@ -52,6 +44,11 @@ } .editor .scroll-view { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; overflow-x: auto; overflow-y: hidden; -webkit-box-flex: 1;