diff --git a/lib/minimap.coffee b/lib/minimap.coffee index 733ae805..c88985e6 100644 --- a/lib/minimap.coffee +++ b/lib/minimap.coffee @@ -20,7 +20,7 @@ class Minimap # options - An {Object} with the following properties: # :textEditor - A `TextEditor` instance. constructor: (options={}) -> - {@textEditor} = options + {@textEditor, @standAlone, @width, @height} = options unless @textEditor? throw new Error('Cannot create a minimap without an editor') @@ -135,6 +135,14 @@ class Minimap onDidDestroy: (callback) -> @emitter.on 'did-destroy', callback + # Returns `true` when the minimap is in stand-alone mode. + # + # The stand-alone mode means that the minimap size won't be tied + # to the `TextEditor` but based on the specified options instead. + # + # Returns a {Boolean}. + isStandAlone: -> @standAlone + # Returns the `TextEditor` that this minimap represents. # # Returns a `TextEditor`. @@ -143,7 +151,8 @@ class Minimap # Returns the height of the `TextEditor` at the {Minimap} scale. # # Returns a {Number}. - getTextEditorScaledHeight: -> @textEditor.getHeight() * @getVerticalScaleFactor() + getTextEditorScaledHeight: -> + @textEditor.getHeight() * @getVerticalScaleFactor() # Returns the `TextEditor::getScrollTop` value at the {Minimap} scale. # @@ -196,14 +205,43 @@ class Minimap # Returns a {Number}. getHeight: -> @textEditor.getScreenLineCount() * @getLineHeight() - # Returns the height the {Minimap} will take on screen. + # Returns the width of the whole minimap in pixels based on the `minimap` + # settings. + # + # Returns a {Number}. + getWidth: -> @textEditor.getMaxScreenLineLength() * @getCharWidth() + + # Returns the height the {Minimap} content will take on screen. # # When the {Minimap} height is greater than the `TextEditor` height, the # `TextEditor` height is returned instead. # # Returns a {Number}. - getVisibleHeight: -> - Math.min(@textEditor.getHeight(), @getHeight()) + getVisibleHeight: -> Math.min(@getScreenHeight(), @getHeight()) + + # Returns the height the minimap should take once displayed, it's either the + # height of the `TextEditor` or the provided `height` when in standAlone mode. + # + # Returns a {Number}. + getScreenHeight: -> + if @isStandAlone() + if @height? then @height else @getHeight() + else + @textEditor.getHeight() + + # Returns the width the whole {Minimap} will take on screen. + # + # Returns a {Number}. + getVisibleWidth: -> + Math.min(@getScreenWidth(), @getWidth()) + + # Returns the width the minimap should take once displayed, it's either the + # width of the minimap content or the provided `width` when in standAlone + # mode. + # + # Returns a {Number}. + getScreenWidth: -> + if @isStandAlone() and @width? then @width else @getWidth() # Returns the vertical scaling factor when converting coordinates from the # `TextEditor` to the {Minimap}. @@ -249,7 +287,7 @@ class Minimap # # Returns a {Number}. getLastVisibleScreenRow: -> - Math.ceil((@getScrollTop() + @textEditor.getHeight()) / @getLineHeight()) + Math.ceil((@getScrollTop() + @getScreenHeight()) / @getLineHeight()) # Returns the current scroll of the {Minimap}. # @@ -263,7 +301,8 @@ class Minimap # Returns the maximum scroll value of the {Minimap}. # # Returns a {Number}. - getMaxScrollTop: -> Math.max(0, @getHeight() - @textEditor.getHeight()) + getMaxScrollTop: -> + Math.max(0, @getHeight() - @getScreenHeight()) # Returns `true` when the {Minimap} can scroll. # diff --git a/spec/minimap-spec.coffee b/spec/minimap-spec.coffee index 8b67c285..701b4854 100644 --- a/spec/minimap-spec.coffee +++ b/spec/minimap-spec.coffee @@ -334,3 +334,107 @@ describe 'Minimap', -> expect(decorations['line']['3'].length).toEqual(1) expect(decorations['highlight-under']['5'].length).toEqual(1) + +## ###### ######## ### ## ## ######## +## ## ## ## ## ## ### ## ## ## +## ## ## ## ## #### ## ## ## +## ###### ## ## ## ## ## ## ## ## +## ## ## ######### ## #### ## ## +## ## ## ## ## ## ## ### ## ## +## ###### ## ## ## ## ## ######## +## +## ### ## ####### ## ## ######## +## ## ## ## ## ## ### ## ## +## ## ## ## ## ## #### ## ## +## ## ## ## ## ## ## ## ## ###### +## ######### ## ## ## ## #### ## +## ## ## ## ## ## ## ### ## +## ## ## ######## ####### ## ## ######## + +describe 'Stand alone minimap', -> + [editor, minimap, largeSample, smallSample] = [] + + beforeEach -> + atom.config.set 'minimap.charHeight', 4 + atom.config.set 'minimap.charWidth', 2 + atom.config.set 'minimap.interline', 1 + + editor = new TextEditor({}) + editor.setLineHeightInPixels(10) + editor.setHeight(50) + editor.setWidth(200) + + dir = atom.project.getDirectories()[0] + + minimap = new Minimap({ + textEditor: editor + standAlone: true + }) + + largeSample = fs.readFileSync(dir.resolve('large-file.coffee')).toString() + smallSample = fs.readFileSync(dir.resolve('sample.coffee')).toString() + + it 'has an associated editor', -> + expect(minimap.getTextEditor()).toEqual(editor) + + it 'measures the minimap size based on the current editor content', -> + editor.setText(smallSample) + expect(minimap.getHeight()).toEqual(editor.getScreenLineCount() * 5) + + editor.setText(largeSample) + expect(minimap.getHeight()).toEqual(editor.getScreenLineCount() * 5) + + it 'measures the scaling factor between the editor and the minimap', -> + expect(minimap.getVerticalScaleFactor()).toEqual(0.5) + expect(minimap.getHorizontalScaleFactor()).toEqual(2 / editor.getDefaultCharWidth()) + + it 'measures the editor visible area size at minimap scale', -> + editor.setText(largeSample) + expect(minimap.getTextEditorScaledHeight()).toEqual(25) + + it 'has a visible height based on the passed-in options', -> + expect(minimap.getVisibleHeight()).toEqual(5) + + editor.setText(smallSample) + expect(minimap.getVisibleHeight()).toEqual(20) + + editor.setText(largeSample) + expect(minimap.getVisibleHeight()).toEqual(editor.getScreenLineCount() * 5) + + minimap.height = 100 + expect(minimap.getVisibleHeight()).toEqual(100) + + it 'has a visible width based on the passed-in options', -> + expect(minimap.getVisibleWidth()).toEqual(0) + + editor.setText(smallSample) + expect(minimap.getVisibleWidth()).toEqual(36) + + editor.setText(largeSample) + expect(minimap.getVisibleWidth()).toEqual(editor.getMaxScreenLineLength() * 2) + + minimap.width = 50 + expect(minimap.getVisibleWidth()).toEqual(50) + + it 'measures the available minimap scroll', -> + editor.setText(largeSample) + largeLineCount = editor.getScreenLineCount() + + expect(minimap.getMaxScrollTop()).toEqual(0) + expect(minimap.canScroll()).toBeFalsy() + + minimap.height = 100 + + expect(minimap.getMaxScrollTop()).toEqual(largeLineCount * 5 - 100) + expect(minimap.canScroll()).toBeTruthy() + + it 'computes the first visible row in the minimap', -> + expect(minimap.getFirstVisibleScreenRow()).toEqual(0) + + it 'computes the last visible row in the minimap', -> + editor.setText(largeSample) + + expect(minimap.getLastVisibleScreenRow()).toEqual(editor.getScreenLineCount()) + + minimap.height = 100 + expect(minimap.getLastVisibleScreenRow()).toEqual(20)