Merge pull request #13955 from atom/fb-mdt-workspace-element-to-js

Convert workspace element and spec to JavaScript
This commit is contained in:
Nathan Sobo
2017-03-07 19:49:32 -07:00
committed by GitHub
4 changed files with 416 additions and 357 deletions

View File

@@ -1,208 +0,0 @@
{ipcRenderer} = require 'electron'
path = require 'path'
temp = require('temp').track()
{Disposable} = require 'event-kit'
describe "WorkspaceElement", ->
afterEach ->
temp.cleanupSync()
describe "when the workspace element is focused", ->
it "transfers focus to the active pane", ->
workspaceElement = atom.views.getView(atom.workspace)
jasmine.attachToDOM(workspaceElement)
activePaneElement = atom.views.getView(atom.workspace.getActivePane())
document.body.focus()
expect(document.activeElement).not.toBe(activePaneElement)
workspaceElement.focus()
expect(document.activeElement).toBe(activePaneElement)
describe "the scrollbar visibility class", ->
it "has a class based on the style of the scrollbar", ->
observeCallback = null
scrollbarStyle = require 'scrollbar-style'
spyOn(scrollbarStyle, 'observePreferredScrollbarStyle').andCallFake (cb) ->
observeCallback = cb
new Disposable(->)
workspaceElement = atom.views.getView(atom.workspace)
observeCallback('legacy')
expect(workspaceElement.className).toMatch 'scrollbars-visible-always'
observeCallback('overlay')
expect(workspaceElement).toHaveClass 'scrollbars-visible-when-scrolling'
describe "editor font styling", ->
[editor, editorElement, workspaceElement] = []
beforeEach ->
waitsForPromise -> atom.workspace.open('sample.js')
runs ->
workspaceElement = atom.views.getView(atom.workspace)
jasmine.attachToDOM(workspaceElement)
editor = atom.workspace.getActiveTextEditor()
editorElement = atom.views.getView(editor)
it "updates the font-size based on the 'editor.fontSize' config value", ->
initialCharWidth = editor.getDefaultCharWidth()
expect(getComputedStyle(editorElement).fontSize).toBe atom.config.get('editor.fontSize') + 'px'
atom.config.set('editor.fontSize', atom.config.get('editor.fontSize') + 5)
expect(getComputedStyle(editorElement).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()
fontFamily = atom.config.get('editor.fontFamily')
expect(getComputedStyle(editorElement).fontFamily).toBe fontFamily
atom.config.set('editor.fontFamily', 'sans-serif')
fontFamily = atom.config.get('editor.fontFamily')
expect(getComputedStyle(editorElement).fontFamily).toBe 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(editorElement).lineHeight).toBe atom.config.get('editor.lineHeight')
expect(editor.getLineHeightInPixels()).not.toBe initialLineHeight
it "increases or decreases the font size when a ctrl-mousewheel event occurs", ->
atom.config.set('editor.zoomFontWhenCtrlScrolling', true)
atom.config.set('editor.fontSize', 12)
# Zoom out
editorElement.querySelector('span').dispatchEvent(new WheelEvent('mousewheel', {
wheelDeltaY: -10,
ctrlKey: true
}))
expect(atom.config.get('editor.fontSize')).toBe(11)
# Zoom in
editorElement.querySelector('span').dispatchEvent(new WheelEvent('mousewheel', {
wheelDeltaY: 10,
ctrlKey: true
}))
expect(atom.config.get('editor.fontSize')).toBe(12)
# Not on an atom-text-editor
workspaceElement.dispatchEvent(new WheelEvent('mousewheel', {
wheelDeltaY: 10,
ctrlKey: true
}))
expect(atom.config.get('editor.fontSize')).toBe(12)
# No ctrl key
editorElement.querySelector('span').dispatchEvent(new WheelEvent('mousewheel', {
wheelDeltaY: 10,
}))
expect(atom.config.get('editor.fontSize')).toBe(12)
atom.config.set('editor.zoomFontWhenCtrlScrolling', false)
editorElement.querySelector('span').dispatchEvent(new WheelEvent('mousewheel', {
wheelDeltaY: 10,
ctrlKey: true
}))
expect(atom.config.get('editor.fontSize')).toBe(12)
describe 'panel containers', ->
it 'inserts panel container elements in the correct places in the DOM', ->
workspaceElement = atom.views.getView(atom.workspace)
leftContainer = workspaceElement.querySelector('atom-panel-container.left')
rightContainer = workspaceElement.querySelector('atom-panel-container.right')
expect(leftContainer.nextSibling).toBe workspaceElement.verticalAxis
expect(rightContainer.previousSibling).toBe workspaceElement.verticalAxis
topContainer = workspaceElement.querySelector('atom-panel-container.top')
bottomContainer = workspaceElement.querySelector('atom-panel-container.bottom')
expect(topContainer.nextSibling).toBe workspaceElement.paneContainer
expect(bottomContainer.previousSibling).toBe workspaceElement.paneContainer
headerContainer = workspaceElement.querySelector('atom-panel-container.header')
footerContainer = workspaceElement.querySelector('atom-panel-container.footer')
expect(headerContainer.nextSibling).toBe workspaceElement.horizontalAxis
expect(footerContainer.previousSibling).toBe workspaceElement.horizontalAxis
modalContainer = workspaceElement.querySelector('atom-panel-container.modal')
expect(modalContainer.parentNode).toBe workspaceElement
it 'stretches header/footer panels to the workspace width', ->
workspaceElement = atom.views.getView(atom.workspace)
jasmine.attachToDOM(workspaceElement)
expect(workspaceElement.offsetWidth).toBeGreaterThan(0)
headerItem = document.createElement('div')
atom.workspace.addHeaderPanel({item: headerItem})
expect(headerItem.offsetWidth).toEqual(workspaceElement.offsetWidth)
footerItem = document.createElement('div')
atom.workspace.addFooterPanel({item: footerItem})
expect(footerItem.offsetWidth).toEqual(workspaceElement.offsetWidth)
it 'shrinks horizontal axis according to header/footer panels height', ->
workspaceElement = atom.views.getView(atom.workspace)
workspaceElement.style.height = '100px'
horizontalAxisElement = workspaceElement.querySelector('atom-workspace-axis.horizontal')
jasmine.attachToDOM(workspaceElement)
originalHorizontalAxisHeight = horizontalAxisElement.offsetHeight
expect(workspaceElement.offsetHeight).toBeGreaterThan(0)
expect(originalHorizontalAxisHeight).toBeGreaterThan(0)
headerItem = document.createElement('div')
headerItem.style.height = '10px'
atom.workspace.addHeaderPanel({item: headerItem})
expect(headerItem.offsetHeight).toBeGreaterThan(0)
footerItem = document.createElement('div')
footerItem.style.height = '15px'
atom.workspace.addFooterPanel({item: footerItem})
expect(footerItem.offsetHeight).toBeGreaterThan(0)
expect(horizontalAxisElement.offsetHeight).toEqual(originalHorizontalAxisHeight - headerItem.offsetHeight - footerItem.offsetHeight)
describe "the 'window:toggle-invisibles' command", ->
it "shows/hides invisibles in all open and future editors", ->
workspaceElement = atom.views.getView(atom.workspace)
expect(atom.config.get('editor.showInvisibles')).toBe false
atom.commands.dispatch(workspaceElement, 'window:toggle-invisibles')
expect(atom.config.get('editor.showInvisibles')).toBe true
atom.commands.dispatch(workspaceElement, 'window:toggle-invisibles')
expect(atom.config.get('editor.showInvisibles')).toBe false
describe "the 'window:run-package-specs' command", ->
it "runs the package specs for the active item's project path, or the first project path", ->
workspaceElement = atom.views.getView(atom.workspace)
spyOn(ipcRenderer, 'send')
# No project paths. Don't try to run specs.
atom.commands.dispatch(workspaceElement, "window:run-package-specs")
expect(ipcRenderer.send).not.toHaveBeenCalledWith("run-package-specs")
projectPaths = [temp.mkdirSync("dir1-"), temp.mkdirSync("dir2-")]
atom.project.setPaths(projectPaths)
# No active item. Use first project directory.
atom.commands.dispatch(workspaceElement, "window:run-package-specs")
expect(ipcRenderer.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[0], "spec"))
ipcRenderer.send.reset()
# Active item doesn't implement ::getPath(). Use first project directory.
item = document.createElement("div")
atom.workspace.getActivePane().activateItem(item)
atom.commands.dispatch(workspaceElement, "window:run-package-specs")
expect(ipcRenderer.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[0], "spec"))
ipcRenderer.send.reset()
# Active item has no path. Use first project directory.
item.getPath = -> null
atom.commands.dispatch(workspaceElement, "window:run-package-specs")
expect(ipcRenderer.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[0], "spec"))
ipcRenderer.send.reset()
# Active item has path. Use project path for item path.
item.getPath = -> path.join(projectPaths[1], "a-file.txt")
atom.commands.dispatch(workspaceElement, "window:run-package-specs")
expect(ipcRenderer.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[1], "spec"))
ipcRenderer.send.reset()

View File

@@ -0,0 +1,232 @@
'use strict'
/* global getComputedStyle, WheelEvent */
const {ipcRenderer} = require('electron')
const path = require('path')
const temp = require('temp').track()
const {Disposable} = require('event-kit')
describe('WorkspaceElement', () => {
afterEach(() => { temp.cleanupSync() })
describe('when the workspace element is focused', () => {
it('transfers focus to the active pane', () => {
const workspaceElement = atom.views.getView(atom.workspace)
jasmine.attachToDOM(workspaceElement)
const activePaneElement = atom.views.getView(atom.workspace.getActivePane())
document.body.focus()
expect(document.activeElement).not.toBe(activePaneElement)
workspaceElement.focus()
expect(document.activeElement).toBe(activePaneElement)
})
})
describe('the scrollbar visibility class', () => {
it('has a class based on the style of the scrollbar', () => {
let observeCallback
const scrollbarStyle = require('scrollbar-style')
spyOn(scrollbarStyle, 'observePreferredScrollbarStyle').andCallFake(cb => {
observeCallback = cb
return new Disposable(() => {})
})
const workspaceElement = atom.views.getView(atom.workspace)
observeCallback('legacy')
expect(workspaceElement.className).toMatch('scrollbars-visible-always')
observeCallback('overlay')
expect(workspaceElement).toHaveClass('scrollbars-visible-when-scrolling')
})
})
describe('editor font styling', () => {
let editor, editorElement, workspaceElement
beforeEach(() => {
waitsForPromise(() => atom.workspace.open('sample.js'))
runs(() => {
workspaceElement = atom.views.getView(atom.workspace)
jasmine.attachToDOM(workspaceElement)
editor = atom.workspace.getActiveTextEditor()
editorElement = atom.views.getView(editor)
})
})
it("updates the font-size based on the 'editor.fontSize' config value", () => {
const initialCharWidth = editor.getDefaultCharWidth()
expect(getComputedStyle(editorElement).fontSize).toBe(atom.config.get('editor.fontSize') + 'px')
atom.config.set('editor.fontSize', atom.config.get('editor.fontSize') + 5)
expect(getComputedStyle(editorElement).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", () => {
const initialCharWidth = editor.getDefaultCharWidth()
let fontFamily = atom.config.get('editor.fontFamily')
expect(getComputedStyle(editorElement).fontFamily).toBe(fontFamily)
atom.config.set('editor.fontFamily', 'sans-serif')
fontFamily = atom.config.get('editor.fontFamily')
expect(getComputedStyle(editorElement).fontFamily).toBe(fontFamily)
expect(editor.getDefaultCharWidth()).not.toBe(initialCharWidth)
})
it("updates the line-height based on the 'editor.lineHeight' config value", () => {
const initialLineHeight = editor.getLineHeightInPixels()
atom.config.set('editor.lineHeight', '30px')
expect(getComputedStyle(editorElement).lineHeight).toBe(atom.config.get('editor.lineHeight'))
expect(editor.getLineHeightInPixels()).not.toBe(initialLineHeight)
})
it('increases or decreases the font size when a ctrl-mousewheel event occurs', () => {
atom.config.set('editor.zoomFontWhenCtrlScrolling', true)
atom.config.set('editor.fontSize', 12)
// Zoom out
editorElement.querySelector('span').dispatchEvent(new WheelEvent('mousewheel', {
wheelDeltaY: -10,
ctrlKey: true
}))
expect(atom.config.get('editor.fontSize')).toBe(11)
// Zoom in
editorElement.querySelector('span').dispatchEvent(new WheelEvent('mousewheel', {
wheelDeltaY: 10,
ctrlKey: true
}))
expect(atom.config.get('editor.fontSize')).toBe(12)
// Not on an atom-text-editor
workspaceElement.dispatchEvent(new WheelEvent('mousewheel', {
wheelDeltaY: 10,
ctrlKey: true
}))
expect(atom.config.get('editor.fontSize')).toBe(12)
// No ctrl key
editorElement.querySelector('span').dispatchEvent(new WheelEvent('mousewheel', {
wheelDeltaY: 10
}))
expect(atom.config.get('editor.fontSize')).toBe(12)
atom.config.set('editor.zoomFontWhenCtrlScrolling', false)
editorElement.querySelector('span').dispatchEvent(new WheelEvent('mousewheel', {
wheelDeltaY: 10,
ctrlKey: true
}))
expect(atom.config.get('editor.fontSize')).toBe(12)
})
})
describe('panel containers', () => {
it('inserts panel container elements in the correct places in the DOM', () => {
const workspaceElement = atom.views.getView(atom.workspace)
const leftContainer = workspaceElement.querySelector('atom-panel-container.left')
const rightContainer = workspaceElement.querySelector('atom-panel-container.right')
expect(leftContainer.nextSibling).toBe(workspaceElement.verticalAxis)
expect(rightContainer.previousSibling).toBe(workspaceElement.verticalAxis)
const topContainer = workspaceElement.querySelector('atom-panel-container.top')
const bottomContainer = workspaceElement.querySelector('atom-panel-container.bottom')
expect(topContainer.nextSibling).toBe(workspaceElement.paneContainer)
expect(bottomContainer.previousSibling).toBe(workspaceElement.paneContainer)
const headerContainer = workspaceElement.querySelector('atom-panel-container.header')
const footerContainer = workspaceElement.querySelector('atom-panel-container.footer')
expect(headerContainer.nextSibling).toBe(workspaceElement.horizontalAxis)
expect(footerContainer.previousSibling).toBe(workspaceElement.horizontalAxis)
const modalContainer = workspaceElement.querySelector('atom-panel-container.modal')
expect(modalContainer.parentNode).toBe(workspaceElement)
})
it('stretches header/footer panels to the workspace width', () => {
const workspaceElement = atom.views.getView(atom.workspace)
jasmine.attachToDOM(workspaceElement)
expect(workspaceElement.offsetWidth).toBeGreaterThan(0)
const headerItem = document.createElement('div')
atom.workspace.addHeaderPanel({item: headerItem})
expect(headerItem.offsetWidth).toEqual(workspaceElement.offsetWidth)
const footerItem = document.createElement('div')
atom.workspace.addFooterPanel({item: footerItem})
expect(footerItem.offsetWidth).toEqual(workspaceElement.offsetWidth)
})
it('shrinks horizontal axis according to header/footer panels height', () => {
const workspaceElement = atom.views.getView(atom.workspace)
workspaceElement.style.height = '100px'
const horizontalAxisElement = workspaceElement.querySelector('atom-workspace-axis.horizontal')
jasmine.attachToDOM(workspaceElement)
const originalHorizontalAxisHeight = horizontalAxisElement.offsetHeight
expect(workspaceElement.offsetHeight).toBeGreaterThan(0)
expect(originalHorizontalAxisHeight).toBeGreaterThan(0)
const headerItem = document.createElement('div')
headerItem.style.height = '10px'
atom.workspace.addHeaderPanel({item: headerItem})
expect(headerItem.offsetHeight).toBeGreaterThan(0)
const footerItem = document.createElement('div')
footerItem.style.height = '15px'
atom.workspace.addFooterPanel({item: footerItem})
expect(footerItem.offsetHeight).toBeGreaterThan(0)
expect(horizontalAxisElement.offsetHeight).toEqual(originalHorizontalAxisHeight - headerItem.offsetHeight - footerItem.offsetHeight)
})
})
describe("the 'window:toggle-invisibles' command", () => {
it('shows/hides invisibles in all open and future editors', () => {
const workspaceElement = atom.views.getView(atom.workspace)
expect(atom.config.get('editor.showInvisibles')).toBe(false)
atom.commands.dispatch(workspaceElement, 'window:toggle-invisibles')
expect(atom.config.get('editor.showInvisibles')).toBe(true)
atom.commands.dispatch(workspaceElement, 'window:toggle-invisibles')
expect(atom.config.get('editor.showInvisibles')).toBe(false)
})
})
describe("the 'window:run-package-specs' command", () => {
it("runs the package specs for the active item's project path, or the first project path", () => {
const workspaceElement = atom.views.getView(atom.workspace)
spyOn(ipcRenderer, 'send')
// No project paths. Don't try to run specs.
atom.commands.dispatch(workspaceElement, 'window:run-package-specs')
expect(ipcRenderer.send).not.toHaveBeenCalledWith('run-package-specs')
const projectPaths = [temp.mkdirSync('dir1-'), temp.mkdirSync('dir2-')]
atom.project.setPaths(projectPaths)
// No active item. Use first project directory.
atom.commands.dispatch(workspaceElement, 'window:run-package-specs')
expect(ipcRenderer.send).toHaveBeenCalledWith('run-package-specs', path.join(projectPaths[0], 'spec'))
ipcRenderer.send.reset()
// Active item doesn't implement ::getPath(). Use first project directory.
const item = document.createElement('div')
atom.workspace.getActivePane().activateItem(item)
atom.commands.dispatch(workspaceElement, 'window:run-package-specs')
expect(ipcRenderer.send).toHaveBeenCalledWith('run-package-specs', path.join(projectPaths[0], 'spec'))
ipcRenderer.send.reset()
// Active item has no path. Use first project directory.
item.getPath = () => null
atom.commands.dispatch(workspaceElement, 'window:run-package-specs')
expect(ipcRenderer.send).toHaveBeenCalledWith('run-package-specs', path.join(projectPaths[0], 'spec'))
ipcRenderer.send.reset()
// Active item has path. Use project path for item path.
item.getPath = () => path.join(projectPaths[1], 'a-file.txt')
atom.commands.dispatch(workspaceElement, 'window:run-package-specs')
expect(ipcRenderer.send).toHaveBeenCalledWith('run-package-specs', path.join(projectPaths[1], 'spec'))
ipcRenderer.send.reset()
})
})
})

View File

@@ -1,149 +0,0 @@
{ipcRenderer} = require 'electron'
path = require 'path'
fs = require 'fs-plus'
{CompositeDisposable} = require 'event-kit'
scrollbarStyle = require 'scrollbar-style'
module.exports =
class WorkspaceElement extends HTMLElement
globalTextEditorStyleSheet: null
attachedCallback: ->
@focus()
detachedCallback: ->
@subscriptions.dispose()
initializeContent: ->
@classList.add 'workspace'
@setAttribute 'tabindex', -1
@verticalAxis = document.createElement('atom-workspace-axis')
@verticalAxis.classList.add('vertical')
@horizontalAxis = document.createElement('atom-workspace-axis')
@horizontalAxis.classList.add('horizontal')
@horizontalAxis.appendChild(@verticalAxis)
@appendChild(@horizontalAxis)
observeScrollbarStyle: ->
@subscriptions.add scrollbarStyle.observePreferredScrollbarStyle (style) =>
switch style
when 'legacy'
@classList.remove('scrollbars-visible-when-scrolling')
@classList.add("scrollbars-visible-always")
when 'overlay'
@classList.remove('scrollbars-visible-always')
@classList.add("scrollbars-visible-when-scrolling")
observeTextEditorFontConfig: ->
@updateGlobalTextEditorStyleSheet()
@subscriptions.add @config.onDidChange 'editor.fontSize', @updateGlobalTextEditorStyleSheet.bind(this)
@subscriptions.add @config.onDidChange 'editor.fontFamily', @updateGlobalTextEditorStyleSheet.bind(this)
@subscriptions.add @config.onDidChange 'editor.lineHeight', @updateGlobalTextEditorStyleSheet.bind(this)
updateGlobalTextEditorStyleSheet: ->
styleSheetSource = """
atom-text-editor {
font-size: #{@config.get('editor.fontSize')}px;
font-family: #{@config.get('editor.fontFamily')};
line-height: #{@config.get('editor.lineHeight')};
}
"""
@styles.addStyleSheet(styleSheetSource, sourcePath: 'global-text-editor-styles')
@views.performDocumentPoll()
initialize: (@model, {@views, @workspace, @project, @config, @styles}) ->
throw new Error("Must pass a views parameter when initializing WorskpaceElements") unless @views?
throw new Error("Must pass a workspace parameter when initializing WorskpaceElements") unless @workspace?
throw new Error("Must pass a project parameter when initializing WorskpaceElements") unless @project?
throw new Error("Must pass a config parameter when initializing WorskpaceElements") unless @config?
throw new Error("Must pass a styles parameter when initializing WorskpaceElements") unless @styles?
@subscriptions = new CompositeDisposable
@initializeContent()
@observeScrollbarStyle()
@observeTextEditorFontConfig()
@paneContainer = @views.getView(@model.paneContainer)
@verticalAxis.appendChild(@paneContainer)
@addEventListener 'focus', @handleFocus.bind(this)
@addEventListener 'mousewheel', @handleMousewheel.bind(this), true
@panelContainers =
top: @views.getView(@model.panelContainers.top)
left: @views.getView(@model.panelContainers.left)
right: @views.getView(@model.panelContainers.right)
bottom: @views.getView(@model.panelContainers.bottom)
header: @views.getView(@model.panelContainers.header)
footer: @views.getView(@model.panelContainers.footer)
modal: @views.getView(@model.panelContainers.modal)
@horizontalAxis.insertBefore(@panelContainers.left, @verticalAxis)
@horizontalAxis.appendChild(@panelContainers.right)
@verticalAxis.insertBefore(@panelContainers.top, @paneContainer)
@verticalAxis.appendChild(@panelContainers.bottom)
@insertBefore(@panelContainers.header, @horizontalAxis)
@appendChild(@panelContainers.footer)
@appendChild(@panelContainers.modal)
this
getModel: -> @model
handleMousewheel: (event) ->
if event.ctrlKey and @config.get('editor.zoomFontWhenCtrlScrolling') and event.target.closest('atom-text-editor')?
if event.wheelDeltaY > 0
@model.increaseFontSize()
else if event.wheelDeltaY < 0
@model.decreaseFontSize()
event.preventDefault()
event.stopPropagation()
handleFocus: (event) ->
@model.getActivePane().activate()
focusPaneViewAbove: -> @paneContainer.focusPaneViewAbove()
focusPaneViewBelow: -> @paneContainer.focusPaneViewBelow()
focusPaneViewOnLeft: -> @paneContainer.focusPaneViewOnLeft()
focusPaneViewOnRight: -> @paneContainer.focusPaneViewOnRight()
moveActiveItemToPaneAbove: (params) -> @paneContainer.moveActiveItemToPaneAbove(params)
moveActiveItemToPaneBelow: (params) -> @paneContainer.moveActiveItemToPaneBelow(params)
moveActiveItemToPaneOnLeft: (params) -> @paneContainer.moveActiveItemToPaneOnLeft(params)
moveActiveItemToPaneOnRight: (params) -> @paneContainer.moveActiveItemToPaneOnRight(params)
runPackageSpecs: ->
if activePath = @workspace.getActivePaneItem()?.getPath?()
[projectPath] = @project.relativizePath(activePath)
else
[projectPath] = @project.getPaths()
if projectPath
specPath = path.join(projectPath, 'spec')
testPath = path.join(projectPath, 'test')
if not fs.existsSync(specPath) and fs.existsSync(testPath)
specPath = testPath
ipcRenderer.send('run-package-specs', specPath)
runBenchmarks: ->
if activePath = @workspace.getActivePaneItem()?.getPath?()
[projectPath] = @project.relativizePath(activePath)
else
[projectPath] = @project.getPaths()
if projectPath
ipcRenderer.send('run-benchmarks', path.join(projectPath, 'benchmarks'))
module.exports = WorkspaceElement = document.registerElement 'atom-workspace', prototype: WorkspaceElement.prototype

184
src/workspace-element.js Normal file
View File

@@ -0,0 +1,184 @@
'use strict'
/* global HTMLElement */
const {ipcRenderer} = require('electron')
const path = require('path')
const fs = require('fs-plus')
const {CompositeDisposable} = require('event-kit')
const scrollbarStyle = require('scrollbar-style')
class WorkspaceElement extends HTMLElement {
attachedCallback () {
this.focus()
}
detachedCallback () {
this.subscriptions.dispose()
}
initializeContent () {
this.classList.add('workspace')
this.setAttribute('tabindex', -1)
this.verticalAxis = document.createElement('atom-workspace-axis')
this.verticalAxis.classList.add('vertical')
this.horizontalAxis = document.createElement('atom-workspace-axis')
this.horizontalAxis.classList.add('horizontal')
this.horizontalAxis.appendChild(this.verticalAxis)
this.appendChild(this.horizontalAxis)
}
observeScrollbarStyle () {
this.subscriptions.add(scrollbarStyle.observePreferredScrollbarStyle(style => {
switch (style) {
case 'legacy':
this.classList.remove('scrollbars-visible-when-scrolling')
this.classList.add('scrollbars-visible-always')
break
case 'overlay':
this.classList.remove('scrollbars-visible-always')
this.classList.add('scrollbars-visible-when-scrolling')
break
}
}))
}
observeTextEditorFontConfig () {
this.updateGlobalTextEditorStyleSheet()
this.subscriptions.add(this.config.onDidChange('editor.fontSize', this.updateGlobalTextEditorStyleSheet.bind(this)))
this.subscriptions.add(this.config.onDidChange('editor.fontFamily', this.updateGlobalTextEditorStyleSheet.bind(this)))
this.subscriptions.add(this.config.onDidChange('editor.lineHeight', this.updateGlobalTextEditorStyleSheet.bind(this)))
}
updateGlobalTextEditorStyleSheet () {
const styleSheetSource = `atom-text-editor {
font-size: ${this.config.get('editor.fontSize')}px;
font-family: ${this.config.get('editor.fontFamily')};
line-height: ${this.config.get('editor.lineHeight')};
}`
this.styles.addStyleSheet(styleSheetSource, {sourcePath: 'global-text-editor-styles'})
this.views.performDocumentPoll()
}
initialize (model, {views, workspace, project, config, styles}) {
this.model = model
this.views = views
this.workspace = workspace
this.project = project
this.config = config
this.styles = styles
if (this.views == null) { throw new Error('Must pass a views parameter when initializing WorskpaceElements') }
if (this.workspace == null) { throw new Error('Must pass a workspace parameter when initializing WorskpaceElements') }
if (this.project == null) { throw new Error('Must pass a project parameter when initializing WorskpaceElements') }
if (this.config == null) { throw new Error('Must pass a config parameter when initializing WorskpaceElements') }
if (this.styles == null) { throw new Error('Must pass a styles parameter when initializing WorskpaceElements') }
this.subscriptions = new CompositeDisposable()
this.initializeContent()
this.observeScrollbarStyle()
this.observeTextEditorFontConfig()
this.paneContainer = this.views.getView(this.model.paneContainer)
this.verticalAxis.appendChild(this.paneContainer)
this.addEventListener('focus', this.handleFocus.bind(this))
this.addEventListener('mousewheel', this.handleMousewheel.bind(this), true)
this.panelContainers = {
top: this.views.getView(this.model.panelContainers.top),
left: this.views.getView(this.model.panelContainers.left),
right: this.views.getView(this.model.panelContainers.right),
bottom: this.views.getView(this.model.panelContainers.bottom),
header: this.views.getView(this.model.panelContainers.header),
footer: this.views.getView(this.model.panelContainers.footer),
modal: this.views.getView(this.model.panelContainers.modal)
}
this.horizontalAxis.insertBefore(this.panelContainers.left, this.verticalAxis)
this.horizontalAxis.appendChild(this.panelContainers.right)
this.verticalAxis.insertBefore(this.panelContainers.top, this.paneContainer)
this.verticalAxis.appendChild(this.panelContainers.bottom)
this.insertBefore(this.panelContainers.header, this.horizontalAxis)
this.appendChild(this.panelContainers.footer)
this.appendChild(this.panelContainers.modal)
return this
}
getModel () { return this.model }
handleMousewheel (event) {
if (event.ctrlKey && this.config.get('editor.zoomFontWhenCtrlScrolling') && (event.target.closest('atom-text-editor') != null)) {
if (event.wheelDeltaY > 0) {
this.model.increaseFontSize()
} else if (event.wheelDeltaY < 0) {
this.model.decreaseFontSize()
}
event.preventDefault()
event.stopPropagation()
}
}
handleFocus (event) {
this.model.getActivePane().activate()
}
focusPaneViewAbove () { this.paneContainer.focusPaneViewAbove() }
focusPaneViewBelow () { this.paneContainer.focusPaneViewBelow() }
focusPaneViewOnLeft () { this.paneContainer.focusPaneViewOnLeft() }
focusPaneViewOnRight () { this.paneContainer.focusPaneViewOnRight() }
moveActiveItemToPaneAbove (params) { this.paneContainer.moveActiveItemToPaneAbove(params) }
moveActiveItemToPaneBelow (params) { this.paneContainer.moveActiveItemToPaneBelow(params) }
moveActiveItemToPaneOnLeft (params) { this.paneContainer.moveActiveItemToPaneOnLeft(params) }
moveActiveItemToPaneOnRight (params) { this.paneContainer.moveActiveItemToPaneOnRight(params) }
runPackageSpecs () {
const activePaneItem = this.workspace.getActivePaneItem()
const activePath = activePaneItem && typeof activePaneItem.getPath === 'function' ? activePaneItem.getPath() : null
let projectPath
if (activePath != null) {
[projectPath] = this.project.relativizePath(activePath)
} else {
[projectPath] = this.project.getPaths()
}
if (projectPath) {
let specPath = path.join(projectPath, 'spec')
const testPath = path.join(projectPath, 'test')
if (!fs.existsSync(specPath) && fs.existsSync(testPath)) {
specPath = testPath
}
ipcRenderer.send('run-package-specs', specPath)
}
}
runBenchmarks () {
const activePaneItem = this.workspace.getActivePaneItem()
const activePath = activePaneItem && typeof activePaneItem.getPath === 'function' ? activePaneItem.getPath() : null
let projectPath
if (activePath) {
[projectPath] = this.project.relativizePath(activePath)
} else {
[projectPath] = this.project.getPaths()
}
if (projectPath) {
ipcRenderer.send('run-benchmarks', path.join(projectPath, 'benchmarks'))
}
}
}
module.exports = document.registerElement('atom-workspace', {prototype: WorkspaceElement.prototype})