diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index 8e2d426f4..8f9eaf573 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -1,3 +1,5 @@ +path = require 'path' +temp = require 'temp' Workspace = require '../src/workspace' {View} = require '../src/space-pen-extensions' @@ -369,3 +371,58 @@ describe "Workspace", -> workspace2 = Workspace.deserialize(state) expect(jsPackage.loadGrammarsSync.callCount).toBe 1 expect(coffeePackage.loadGrammarsSync.callCount).toBe 1 + + describe "document.title", -> + describe "when the project has no path", -> + it "sets the title to 'untitled'", -> + atom.project.setPath(undefined) + expect(document.title).toBe 'untitled' + + describe "when the project has a path", -> + beforeEach -> + waitsForPromise -> + atom.workspace.open('b') + + describe "when there is an active pane item", -> + it "sets the title to the pane item's title plus the project path", -> + item = atom.workspace.getActivePaneItem() + console.log item.getTitle() + expect(document.title).toBe "#{item.getTitle()} - #{atom.project.getPath()}" + + describe "when the title of the active pane item changes", -> + it "updates the window title based on the item's new title", -> + editor = atom.workspace.getActivePaneItem() + editor.buffer.setPath(path.join(temp.dir, 'hi')) + expect(document.title).toBe "#{editor.getTitle()} - #{atom.project.getPath()}" + + describe "when the active pane's item changes", -> + it "updates the title to the new item's title plus the project path", -> + atom.workspace.getActivePane().activateNextItem() + item = atom.workspace.getActivePaneItem() + expect(document.title).toBe "#{item.getTitle()} - #{atom.project.getPath()}" + + describe "when the last pane item is removed", -> + it "updates the title to contain the project's path", -> + atom.workspace.getActivePane().destroy() + expect(atom.workspace.getActivePaneItem()).toBeUndefined() + expect(document.title).toBe atom.project.getPath() + + describe "when an inactive pane's item changes", -> + it "does not update the title", -> + pane = atom.workspace.getActivePane() + pane.splitRight() + initialTitle = document.title + pane.activateNextItem() + expect(document.title).toBe initialTitle + + describe "when the workspace is deserialized", -> + beforeEach -> + waitsForPromise -> atom.workspace.open('a') + + it "updates the title to contain the project's path", -> + document.title = null + console.log atom.workspace.getActivePaneItem() + workspace2 = atom.workspace.testSerialization() + item = atom.workspace.getActivePaneItem() + expect(document.title).toBe "#{item.getTitle()} - #{atom.project.getPath()}" + workspace2.destroy() diff --git a/spec/workspace-view-spec.coffee b/spec/workspace-view-spec.coffee index d75a92deb..b738349c5 100644 --- a/spec/workspace-view-spec.coffee +++ b/spec/workspace-view-spec.coffee @@ -141,56 +141,6 @@ describe "WorkspaceView", -> atom.workspaceView.trigger(event) expect(commandHandler).toHaveBeenCalled() - describe "window title", -> - describe "when the project has no path", -> - it "sets the title to 'untitled'", -> - atom.project.setPath(undefined) - expect(document.title).toBe 'untitled' - - describe "when the project has a path", -> - beforeEach -> - waitsForPromise -> - atom.workspace.open('b') - - describe "when there is an active pane item", -> - it "sets the title to the pane item's title plus the project path", -> - item = atom.workspace.getActivePaneItem() - expect(document.title).toBe "#{item.getTitle()} - #{atom.project.getPath()}" - - describe "when the title of the active pane item changes", -> - it "updates the window title based on the item's new title", -> - editor = atom.workspace.getActivePaneItem() - editor.buffer.setPath(path.join(temp.dir, 'hi')) - expect(document.title).toBe "#{editor.getTitle()} - #{atom.project.getPath()}" - - describe "when the active pane's item changes", -> - it "updates the title to the new item's title plus the project path", -> - atom.workspaceView.getActivePaneView().activateNextItem() - item = atom.workspace.getActivePaneItem() - expect(document.title).toBe "#{item.getTitle()} - #{atom.project.getPath()}" - - describe "when the last pane item is removed", -> - it "updates the title to contain the project's path", -> - atom.workspaceView.getActivePaneView().remove() - expect(atom.workspace.getActivePaneItem()).toBeUndefined() - expect(document.title).toBe atom.project.getPath() - - describe "when an inactive pane's item changes", -> - it "does not update the title", -> - pane = atom.workspaceView.getActivePaneView() - pane.splitRight() - initialTitle = document.title - pane.activateNextItem() - expect(document.title).toBe initialTitle - - describe "when the root view is deserialized", -> - it "updates the title to contain the project's path", -> - workspace2 = atom.workspace.testSerialization() - workspaceView2 = workspace2.getView(workspace2).__spacePenView - item = atom.workspace.getActivePaneItem() - expect(document.title).toBe "#{item.getTitle()} - #{atom.project.getPath()}" - workspaceView2.remove() - describe "window:toggle-invisibles event", -> it "shows/hides invisibles in all open and future editors", -> atom.workspaceView.height(200) diff --git a/src/workspace-view.coffee b/src/workspace-view.coffee index b838acc51..d0ca046e5 100644 --- a/src/workspace-view.coffee +++ b/src/workspace-view.coffee @@ -103,15 +103,10 @@ class WorkspaceView extends View @subscribe atom.config.observe 'editor.fontFamily', @setEditorFontFamily @subscribe atom.config.observe 'editor.lineHeight', @setEditorLineHeight - @updateTitle() - @on 'focus', (e) => @handleFocus(e) @subscribe $(window), 'focus', (e) => @handleFocus(e) if document.activeElement is document.body - atom.project.on 'path-changed', => @updateTitle() - @on 'pane-container:active-pane-item-changed', => @updateTitle() - @on 'pane:active-item-title-changed', '.active.pane', => @updateTitle() @on 'pane:active-item-modified-status-changed', '.active.pane', => @updateDocumentEdited() @command 'application:about', -> ipc.send('command', 'application:about') @@ -337,7 +332,6 @@ class WorkspaceView extends View @getActivePaneView().focus() false else - @updateTitle() focusableChild = @find("[tabindex=-1]:visible:first") if focusableChild.length focusableChild.focus() @@ -350,23 +344,6 @@ class WorkspaceView extends View confirmClose: -> @model.confirmClose() - # Updates the application's title and proxy icon based on whichever file is - # open. - updateTitle: -> - if projectPath = atom.project.getPath() - if item = @getModel().getActivePaneItem() - title = "#{item.getTitle?() ? 'untitled'} - #{projectPath}" - @setTitle(title, item.getPath?()) - else - @setTitle(projectPath, projectPath) - else - @setTitle('untitled') - - # Sets the application's title (and the proxy icon on OS X) - setTitle: (title, proxyIconPath='') -> - document.title = title - atom.setRepresentedFilename(proxyIconPath) - # On OS X, fades the application window's proxy icon when the current file # has been modified. updateDocumentEdited: -> diff --git a/src/workspace.coffee b/src/workspace.coffee index 999ee0b01..434ef20b3 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -5,7 +5,7 @@ _ = require 'underscore-plus' Q = require 'q' Serializable = require 'serializable' Delegator = require 'delegato' -{Emitter} = require 'event-kit' +{Emitter, Disposable, CompositeDisposable} = require 'event-kit' CommandInstaller = require './command-installer' Editor = require './editor' PaneContainer = require './pane-container' @@ -39,12 +39,15 @@ class Workspace extends Model super @emitter = new Emitter + @subscriptions = new CompositeDisposable @openers = [] @viewRegistry ?= new ViewRegistry @paneContainer ?= new PaneContainer({@viewRegistry}) @paneContainer.onDidDestroyPaneItem(@onPaneItemDestroyed) + @maintainWindowTitle() + @registerOpener (filePath) => switch filePath when 'atom://.atom/stylesheet' @@ -118,6 +121,42 @@ class Workspace extends Model message: "Commands installed." detailedMessage: "The shell commands `atom` and `apm` are installed." + maintainWindowTitle: -> + @updateWindowTitle() + atom.project.on 'path-changed', @updateWindowTitle + + titleSubscription = null + @subscribe @onDidChangeActivePaneItem (item) => + @updateWindowTitle() + + if titleSubscription? + @subscriptions.remove(titleSubscription) + titleSubscription.dispose() + titleSubscription = null + + if typeof item?.onDidChangeTitle is 'function' + titleSubscription = item.onDidChangeTitle(@updateWindowTitle) + else if typeof item?.on is 'function' + titleSubscription = item.on('title-changed', @updateWindowTitle) + unless typeof titleSubscription?.dispose is 'function' + titleSubscription = new Disposable => item.off('title-changed', @updateWindowTitle) + + @subscriptions.add(titleSubscription) if titleSubscription? + + # Updates the application's title and proxy icon based on whichever file is + # open. + updateWindowTitle: => + if projectPath = atom.project.getPath() + if item = @getActivePaneItem() + document.title = "#{item.getTitle?() ? 'untitled'} - #{projectPath}" + atom.setRepresentedFilename(item.getPath?()) + else + document.title = projectPath + atom.setRepresentedFilename(projectPath) + else + document.title = 'untitled' + atom.setRepresentedFilename('') + ### Section: Event Subscription ### @@ -522,6 +561,7 @@ class Workspace extends Model # Called by Model superclass when destroyed destroyed: -> @paneContainer.destroy() + @subscriptions.dispose() ### Section: View Management