Skip to content

Commit

Permalink
Implement sorted decorations rendering
Browse files Browse the repository at this point in the history
Closes #453
  • Loading branch information
abe33 committed Mar 6, 2016
1 parent b912132 commit 8ad6a66
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 24 deletions.
11 changes: 11 additions & 0 deletions lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,17 @@ class Main {
return this.emitter.on('did-deactivate-plugin', callback)
}

/**
* Registers a callback to listen to the `did-change-plugin-order` event of
* the package.
*
* @param {function(event:Object):void} callback the callback function
* @return {Disposable} a disposable to stop listening to the event
*/
onDidChangePluginOrder (callback) {
return this.emitter.on('did-change-plugin-order', callback)
}

/**
* Returns the `Minimap` class
*
Expand Down
5 changes: 5 additions & 0 deletions lib/minimap-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import {CompositeDisposable, Disposable} from 'atom'
import {EventsDelegation, AncestorsMethods} from 'atom-utils'
import Main from './main'
import include from './decorators/include'
import element from './decorators/element'
import DOMStylesReader from './mixins/dom-styles-reader'
Expand Down Expand Up @@ -666,6 +667,10 @@ export default class MinimapElement {
this.requestUpdate()
}))

this.subscriptions.add(Main.onDidChangePluginOrder(() => {
this.requestForcedUpdate()
}))

this.setStandAlone(this.minimap.isStandAlone())

if (this.width != null && this.height != null) {
Expand Down
47 changes: 30 additions & 17 deletions lib/mixins/canvas-drawer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import _ from 'underscore-plus'
import Mixin from 'mixto'
import Main from '../main'
import CanvasLayer from '../canvas-layer'

/**
Expand Down Expand Up @@ -331,17 +332,19 @@ export default class CanvasDrawer extends Mixin {
canvasHeight: canvasHeight,
lineHeight: lineHeight,
charWidth: charWidth,
charHeight: charHeight
charHeight: charHeight,
orders: Main.getPluginsOrder()
}

for (let screenRow = firstRow; screenRow <= lastRow; screenRow++) {
renderData.row = offsetRow + (screenRow - firstRow)
renderData.yRow = renderData.row * lineHeight
renderData.screenRow = screenRow

this.drawDecorations(screenRow, decorations, 'line', renderData, this.drawLineDecoration)

this.drawDecorations(screenRow, decorations, 'highlight-under', renderData, this.drawHighlightDecoration)
this.drawDecorations(screenRow, decorations, renderData, {
'line': this.drawLineDecoration,
'highlight-under': this.drawHighlightDecoration
})
}

this.backLayer.context.fill()
Expand Down Expand Up @@ -374,17 +377,19 @@ export default class CanvasDrawer extends Mixin {
canvasHeight: canvasHeight,
lineHeight: lineHeight,
charWidth: charWidth,
charHeight: charHeight
charHeight: charHeight,
orders: Main.getPluginsOrder()
}

for (let screenRow = firstRow; screenRow <= lastRow; screenRow++) {
renderData.row = offsetRow + (screenRow - firstRow)
renderData.yRow = renderData.row * lineHeight
renderData.screenRow = screenRow

this.drawDecorations(screenRow, decorations, 'highlight-over', renderData, this.drawHighlightDecoration)

this.drawDecorations(screenRow, decorations, 'highlight-outline', renderData, this.drawHighlightOutlineDecoration)
this.drawDecorations(screenRow, decorations, renderData, {
'highlight-outline': this.drawHighlightOutlineDecoration,
'highlight-over': this.drawHighlightDecoration
})
}

renderData.context.fill()
Expand Down Expand Up @@ -513,19 +518,27 @@ export default class CanvasDrawer extends Mixin {
* @param {number} screenRow the screen row index for which
* render decorations
* @param {Object} decorations the object containing all the decorations
* @param {string} type the type of decorations to render
* @param {Object} renderData the object containing the render data
* @param {Fundtion} renderMethod the method to call to render
* the decorations
* @param {Object} types an object with the type to render as key and the
* render method as value
* @access private
*/
drawDecorations (screenRow, decorations, type, renderData, renderMethod) {
let ref
decorations = (ref = decorations[type]) != null ? ref[screenRow] : void 0
drawDecorations (screenRow, decorations, renderData, types) {
let decorationsToRender = []

for (let i in types) {
decorationsToRender = decorationsToRender.concat(
decorations[i] != null ? decorations[i][screenRow] || [] : []
)
}

decorationsToRender.sort((a, b) =>
(renderData.orders[a.properties.plugin] || 0) - (renderData.orders[b.properties.plugin] || 0)
)

if (decorations != null ? decorations.length : void 0) {
for (let i = 0, len = decorations.length; i < len; i++) {
renderMethod.call(this, decorations[i], renderData)
if (decorationsToRender != null ? decorationsToRender.length : void 0) {
for (let i = 0, len = decorationsToRender.length; i < len; i++) {
types[decorationsToRender[i].properties.type].call(this, decorationsToRender[i], renderData)
}
}
}
Expand Down
18 changes: 17 additions & 1 deletion lib/mixins/decoration-management.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use babel'

import _ from 'underscore-plus'
import path from 'path'
import Mixin from 'mixto'
import {Emitter} from 'atom'
import Decoration from '../decoration'
Expand Down Expand Up @@ -307,7 +309,11 @@ export default class DecorationManagement extends Mixin {
decorationParams.type = 'highlight-over'
}

const {type} = decorationParams
const {type, plugin} = decorationParams

if (plugin == null) {
decorationParams.plugin = this.getOriginatorPackageName()
}

if (decorationParams.scope == null && decorationParams['class'] != null) {
let cls = decorationParams['class'].split(' ').join('.')
Expand Down Expand Up @@ -395,6 +401,16 @@ export default class DecorationManagement extends Mixin {
return decoration
}

getOriginatorPackageName () {
const line = new Error().stack.split('\n')[3]
const filePath = line.split('(')[1].replace(')', '')
const re = new RegExp(
atom.packages.getPackageDirPaths().join('|') + _.escapeRegExp(path.sep)
)
const plugin = filePath.replace(re, '').split(path.sep)[0].replace(/minimap-|-minimap/, '')
return plugin.indexOf(path.sep) < 0 ? plugin : undefined
}

/**
* Given two ranges, it returns an array of ranges representing the
* differences between them.
Expand Down
43 changes: 37 additions & 6 deletions lib/mixins/plugin-management.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ export default class PluginManagement extends Mixin {
* @access private
*/
this.pluginsSubscriptions = {}

/**
* A map that stores the display order for each plugin
*
* @type {Object}
* @access private
*/
this.pluginsOrderMap = {}
}

/**
Expand Down Expand Up @@ -149,10 +157,10 @@ export default class PluginManagement extends Mixin {
* @access private
*/
updatesPluginActivationState (name) {
let plugin = this.plugins[name]
let pluginActive = plugin.isActive()
let settingActive = atom.config.get(`minimap.plugins.${name}`)
let event = { name: name, plugin: plugin }
const plugin = this.plugins[name]
const pluginActive = plugin.isActive()
const settingActive = atom.config.get(`minimap.plugins.${name}`)
const event = { name: name, plugin: plugin }

if (settingActive && !pluginActive) {
plugin.activatePlugin()
Expand Down Expand Up @@ -207,17 +215,40 @@ export default class PluginManagement extends Mixin {
this.updatesPluginActivationState(name)
}))

this.pluginsSubscriptions[name].add(atom.config.observe(orderSettingsKey, () => {

this.pluginsSubscriptions[name].add(atom.config.observe(orderSettingsKey, (order) => {
this.updatePluginsOrderMap(name)
const event = { name: name, plugin: plugin, order: order }
this.emitter.emit('did-change-plugin-order', event)
}))

this.pluginsSubscriptions[name].add(atom.commands.add('atom-workspace', {
[`minimap:toggle-${name}`]: () => {
this.togglePluginActivation(name)
}
}))

this.updatePluginsOrderMap(name)
}

/**
* Updates the display order in the map for the passed-in plugin name.
*
* @param {string} name the name of the plugin to update
* @access private
*/
updatePluginsOrderMap (name) {
const orderSettingsKey = `minimap.plugins.${name}DecorationsOrder`

this.pluginsOrderMap[name] = atom.config.get(orderSettingsKey)
}

/**
* Returns the plugins display order mapped by name.
*
* @return {Object} The plugins order by name
*/
getPluginsOrder () { return this.pluginsOrderMap }

/**
* When the `minimap.displayPluginsControls` setting is toggled,
* this function will unregister the commands and setting that
Expand Down
59 changes: 59 additions & 0 deletions spec/minimap-element-spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use babel'

import fs from 'fs-plus'
import Main from '../lib/main'
import Minimap from '../lib/minimap'
import MinimapElement from '../lib/minimap-element'
import {stylesheet} from './helpers/workspace'
Expand All @@ -23,6 +24,16 @@ function sleep (duration) {
waitsFor(() => { return new Date() - t > duration })
}

function createPlugin () {
const plugin = {
active: false,
activatePlugin () { this.active = true },
deactivatePlugin () { this.active = false },
isActive () { return this.active }
}
return plugin
}

describe('MinimapElement', () => {
let [editor, minimap, largeSample, mediumSample, smallSample, jasmineContent, editorElement, minimapElement, dir] = []

Expand All @@ -36,6 +47,7 @@ describe('MinimapElement', () => {
atom.config.set('minimap.interline', 1)
atom.config.set('minimap.textOpacity', 1)
atom.config.set('minimap.smoothScrolling', true)
atom.config.set('minimap.plugins', {})

MinimapElement.registerViewProvider(Minimap)

Expand Down Expand Up @@ -241,6 +253,53 @@ describe('MinimapElement', () => {
expect(() => { nextAnimationFrame() }).not.toThrow()
})

it('renders the decorations based on the order settings', () => {
atom.config.set('minimap.displayPluginsControls', true)

const pluginFoo = createPlugin()
const pluginBar = createPlugin()

Main.registerPlugin('foo', pluginFoo)
Main.registerPlugin('bar', pluginBar)

atom.config.set('minimap.plugins.fooDecorationsOrder', 1)

const calls = []
spyOn(minimapElement, 'drawLineDecoration').andCallFake((d) => {
calls.push(d.getProperties().plugin)
})
spyOn(minimapElement, 'drawHighlightDecoration').andCallFake((d) => {
calls.push(d.getProperties().plugin)
})

minimap.decorateMarker(editor.markBufferRange([[1, 0], [1, 10]]), {type: 'line', color: '#0000FF', plugin: 'bar'})
minimap.decorateMarker(editor.markBufferRange([[1, 0], [1, 10]]), {type: 'highlight-under', color: '#0000FF', plugin: 'foo'})

editorElement.setScrollTop(0)

waitsFor(() => { return nextAnimationFrame !== noAnimationFrame })
runs(() => {
nextAnimationFrame()

expect(calls).toEqual(['bar', 'foo'])

atom.config.set('minimap.plugins.fooDecorationsOrder', -1)

calls.length = 0
})

waitsFor(() => { return nextAnimationFrame !== noAnimationFrame })

runs(() => {
nextAnimationFrame()

expect(calls).toEqual(['foo', 'bar'])

Main.unregisterPlugin('foo')
Main.unregisterPlugin('bar')
})
})

it('renders the visible line decorations', () => {
spyOn(minimapElement, 'drawLineDecoration').andCallThrough()

Expand Down

0 comments on commit 8ad6a66

Please sign in to comment.