diff --git a/spec/workspace-element-spec.coffee b/spec/workspace-element-spec.coffee deleted file mode 100644 index ec24242ac..000000000 --- a/spec/workspace-element-spec.coffee +++ /dev/null @@ -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() diff --git a/spec/workspace-element-spec.js b/spec/workspace-element-spec.js new file mode 100644 index 000000000..f81276796 --- /dev/null +++ b/spec/workspace-element-spec.js @@ -0,0 +1,228 @@ +const {ipcRenderer} = require('electron'); +const path = require('path'); +const temp = require('temp').track(); +const {Disposable} = require('event-kit'); + +describe("WorkspaceElement", function() { + afterEach(() => temp.cleanupSync()); + + describe("when the workspace element is focused", () => + it("transfers focus to the active pane", function() { + 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(); + return expect(document.activeElement).toBe(activePaneElement); + }) + ); + + describe("the scrollbar visibility class", () => + it("has a class based on the style of the scrollbar", function() { + let observeCallback = null; + const scrollbarStyle = require('scrollbar-style'); + spyOn(scrollbarStyle, 'observePreferredScrollbarStyle').andCallFake(function(cb) { + observeCallback = cb; + return new Disposable(function() {}); + }); + + const workspaceElement = atom.views.getView(atom.workspace); + observeCallback('legacy'); + expect(workspaceElement.className).toMatch('scrollbars-visible-always'); + + observeCallback('overlay'); + return expect(workspaceElement).toHaveClass('scrollbars-visible-when-scrolling'); + }) + ); + + describe("editor font styling", function() { + let [editor, editorElement, workspaceElement] = Array.from([]); + + beforeEach(function() { + waitsForPromise(() => atom.workspace.open('sample.js')); + + return runs(function() { + workspaceElement = atom.views.getView(atom.workspace); + jasmine.attachToDOM(workspaceElement); + editor = atom.workspace.getActiveTextEditor(); + return editorElement = atom.views.getView(editor); + }); + }); + + it("updates the font-size based on the 'editor.fontSize' config value", function() { + 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'); + return expect(editor.getDefaultCharWidth()).toBeGreaterThan(initialCharWidth); + }); + + it("updates the font-family based on the 'editor.fontFamily' config value", function() { + 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); + return expect(editor.getDefaultCharWidth()).not.toBe(initialCharWidth); + }); + + it("updates the line-height based on the 'editor.lineHeight' config value", function() { + const initialLineHeight = editor.getLineHeightInPixels(); + atom.config.set('editor.lineHeight', '30px'); + expect(getComputedStyle(editorElement).lineHeight).toBe(atom.config.get('editor.lineHeight')); + return expect(editor.getLineHeightInPixels()).not.toBe(initialLineHeight); + }); + + return it("increases or decreases the font size when a ctrl-mousewheel event occurs", function() { + 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 + })); + return expect(atom.config.get('editor.fontSize')).toBe(12); + }); + }); + + describe('panel containers', function() { + it('inserts panel container elements in the correct places in the DOM', function() { + 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'); + return expect(modalContainer.parentNode).toBe(workspaceElement); + }); + + it('stretches header/footer panels to the workspace width', function() { + 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}); + return expect(footerItem.offsetWidth).toEqual(workspaceElement.offsetWidth); + }); + + return it('shrinks horizontal axis according to header/footer panels height', function() { + 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); + + return 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", function() { + 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'); + return expect(atom.config.get('editor.showInvisibles')).toBe(false); + }) + ); + + return describe("the 'window:run-package-specs' command", () => + it("runs the package specs for the active item's project path, or the first project path", function() { + 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")); + return ipcRenderer.send.reset(); + }) + ); +}); diff --git a/src/workspace-element.coffee b/src/workspace-element.coffee deleted file mode 100644 index 6defe33da..000000000 --- a/src/workspace-element.coffee +++ /dev/null @@ -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 diff --git a/src/workspace-element.js b/src/workspace-element.js new file mode 100644 index 000000000..b24bb80f6 --- /dev/null +++ b/src/workspace-element.js @@ -0,0 +1,196 @@ +let WorkspaceElement; +const {ipcRenderer} = require('electron'); +const path = require('path'); +const fs = require('fs-plus'); +const {CompositeDisposable} = require('event-kit'); +const scrollbarStyle = require('scrollbar-style'); + +module.exports = +__initClass__(WorkspaceElement = class WorkspaceElement extends HTMLElement { + static initClass() { + this.prototype.globalTextEditorStyleSheet = null; + } + + attachedCallback() { + return this.focus(); + } + + detachedCallback() { + return 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); + + return this.appendChild(this.horizontalAxis); + } + + observeScrollbarStyle() { + return this.subscriptions.add(scrollbarStyle.observePreferredScrollbarStyle(style => { + switch (style) { + case 'legacy': + this.classList.remove('scrollbars-visible-when-scrolling'); + return this.classList.add("scrollbars-visible-always"); + case 'overlay': + this.classList.remove('scrollbars-visible-always'); + return this.classList.add("scrollbars-visible-when-scrolling"); + } + } + ) + ); + } + + 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))); + return 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'}); + return 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(); + return event.stopPropagation(); + } + } + + handleFocus(event) { + return this.model.getActivePane().activate(); + } + + focusPaneViewAbove() { return this.paneContainer.focusPaneViewAbove(); } + + focusPaneViewBelow() { return this.paneContainer.focusPaneViewBelow(); } + + focusPaneViewOnLeft() { return this.paneContainer.focusPaneViewOnLeft(); } + + focusPaneViewOnRight() { return this.paneContainer.focusPaneViewOnRight(); } + + moveActiveItemToPaneAbove(params) { return this.paneContainer.moveActiveItemToPaneAbove(params); } + + moveActiveItemToPaneBelow(params) { return this.paneContainer.moveActiveItemToPaneBelow(params); } + + moveActiveItemToPaneOnLeft(params) { return this.paneContainer.moveActiveItemToPaneOnLeft(params); } + + moveActiveItemToPaneOnRight(params) { return this.paneContainer.moveActiveItemToPaneOnRight(params); } + + runPackageSpecs() { + let activePath, projectPath; + if (activePath = __guardMethod__(this.workspace.getActivePaneItem(), 'getPath', o => o.getPath())) { + [projectPath] = Array.from(this.project.relativizePath(activePath)); + } else { + [projectPath] = Array.from(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; + } + + return ipcRenderer.send('run-package-specs', specPath); + } + } + + runBenchmarks() { + let activePath, projectPath; + if (activePath = __guardMethod__(this.workspace.getActivePaneItem(), 'getPath', o => o.getPath())) { + [projectPath] = Array.from(this.project.relativizePath(activePath)); + } else { + [projectPath] = Array.from(this.project.getPaths()); + } + + if (projectPath) { + return ipcRenderer.send('run-benchmarks', path.join(projectPath, 'benchmarks')); + } + } +}); + +module.exports = WorkspaceElement = document.registerElement('atom-workspace', {prototype: WorkspaceElement.prototype}); + +function __initClass__(c) { + c.initClass(); + return c; +} +function __guardMethod__(obj, methodName, transform) { + if (typeof obj !== 'undefined' && obj !== null && typeof obj[methodName] === 'function') { + return transform(obj, methodName); + } else { + return undefined; + } +} \ No newline at end of file