From 4f0bf9020bb1ebc8149b311f200f0698c2fe3732 Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Wed, 6 Mar 2013 16:05:26 -0800 Subject: [PATCH] Fix pane focus and active item serialization Also: Un-x root view serialization specs --- spec/app/pane-spec.coffee | 27 ++++++++++++++++++ spec/app/root-view-spec.coffee | 52 +++++++++++++--------------------- src/app/pane.coffee | 18 ++++++++++-- 3 files changed, 62 insertions(+), 35 deletions(-) diff --git a/spec/app/pane-spec.coffee b/spec/app/pane-spec.coffee index 97c27dd8b..3c62fc797 100644 --- a/spec/app/pane-spec.coffee +++ b/spec/app/pane-spec.coffee @@ -664,3 +664,30 @@ describe "Pane", -> it "can serialize and deserialize the pane and all its serializable items", -> newPane = deserialize(pane.serialize()) expect(newPane.getItems()).toEqual [editSession1, editSession2] + + it "restores the active item on deserialization if it serializable", -> + pane.showItem(editSession2) + newPane = deserialize(pane.serialize()) + expect(newPane.activeItem).toEqual editSession2 + + it "defaults to the first item on deserialization if the active item was not serializable", -> + expect(view2.serialize?()).toBeFalsy() + pane.showItem(view2) + newPane = deserialize(pane.serialize()) + expect(newPane.activeItem).toEqual editSession1 + + it "focuses the pane after attach only if had focus when serialized", -> + container.attachToDom() + + pane.focus() + state = pane.serialize() + pane.remove() + newPane = deserialize(state) + container.append(newPane) + expect(newPane).toMatchSelector(':has(:focus)') + + $(document.activeElement).blur() + state = newPane.serialize() + newPane.remove() + newerPane = deserialize(state) + expect(newerPane).not.toMatchSelector(':has(:focus)') diff --git a/spec/app/root-view-spec.coffee b/spec/app/root-view-spec.coffee index d4c8a31c4..9cbd75837 100644 --- a/spec/app/root-view-spec.coffee +++ b/spec/app/root-view-spec.coffee @@ -18,39 +18,40 @@ describe "RootView", -> rootView.open(pathToOpen) rootView.focus() - xdescribe "@deserialize()", -> + describe "@deserialize()", -> viewState = null describe "when the serialized RootView has an unsaved buffer", -> it "constructs the view with the same panes", -> + rootView.attachToDom() rootView.open() - editor1 = rootView.getActiveEditor() + editor1 = rootView.getActiveView() buffer = editor1.getBuffer() editor1.splitRight() - viewState = rootView.serialize() rootView.deactivate() - window.rootView = RootView.deserialize(viewState) - rootView.focus() + window.rootView = RootView.deserialize(viewState) + rootView.attachToDom() + expect(rootView.getEditors().length).toBe 2 - expect(rootView.getActiveEditor().getText()).toBe buffer.getText() - expect(rootView.getTitle()).toBe "untitled – #{project.getPath()}" + expect(rootView.getActiveView().getText()).toBe buffer.getText() + expect(rootView.title).toBe "untitled - #{project.getPath()}" describe "when the serialized RootView has a project", -> describe "when there are open editors", -> it "constructs the view with the same panes", -> - editor1 = rootView.getActiveEditor() - editor2 = editor1.splitRight() - editor3 = editor2.splitRight() - editor4 = editor2.splitDown() - editor2.edit(project.buildEditSession('b')) - editor3.edit(project.buildEditSession('../sample.js')) - editor3.setCursorScreenPosition([2, 4]) - editor4.edit(project.buildEditSession('../sample.txt')) - editor4.setCursorScreenPosition([0, 2]) rootView.attachToDom() - editor2.focus() + pane1 = rootView.getActivePane() + pane2 = pane1.splitRight() + pane3 = pane2.splitRight() + pane4 = pane2.splitDown() + pane2.showItem(project.buildEditSession('b')) + pane3.showItem(project.buildEditSession('../sample.js')) + pane3.activeItem.setCursorScreenPosition([2, 4]) + pane4.showItem(project.buildEditSession('../sample.txt')) + pane4.activeItem.setCursorScreenPosition([0, 2]) + pane2.focus() viewState = rootView.serialize() rootView.deactivate() @@ -82,11 +83,11 @@ describe "RootView", -> expect(editor3.isFocused).toBeFalsy() expect(editor4.isFocused).toBeFalsy() - expect(rootView.getTitle()).toBe "#{fs.base(editor2.getPath())} – #{project.getPath()}" + expect(rootView.title).toBe "#{fs.base(editor2.getPath())} - #{project.getPath()}" describe "where there are no open editors", -> it "constructs the view with no open editors", -> - rootView.getActiveEditor().remove() + rootView.getActivePane().remove() expect(rootView.getEditors().length).toBe 0 viewState = rootView.serialize() @@ -96,19 +97,6 @@ describe "RootView", -> rootView.attachToDom() expect(rootView.getEditors().length).toBe 0 - describe "when a pane's wrapped view cannot be deserialized", -> - it "renders an empty pane", -> - viewState = - panesViewState: - deserializer: "Pane", - wrappedView: - deserializer: "BogusView" - - rootView.deactivate() - window.rootView = RootView.deserialize(viewState) - expect(rootView.find('.pane').length).toBe 1 - expect(rootView.find('.pane').children().length).toBe 0 - describe "focus", -> describe "when there is an active view", -> it "hands off focus to the active view", -> diff --git a/src/app/pane.coffee b/src/app/pane.coffee index 54b9e375d..ef29ce72f 100644 --- a/src/app/pane.coffee +++ b/src/app/pane.coffee @@ -10,8 +10,11 @@ class Pane extends View @div class: 'pane', => @div class: 'item-views', outlet: 'itemViews' - @deserialize: ({items}) -> - new Pane(items.map((item) -> deserialize(item))...) + @deserialize: ({items, focused, activeItemUri}) -> + pane = new Pane(items.map((item) -> deserialize(item))...) + pane.showItemForUri(activeItemUri) if activeItemUri + pane.focusOnAttach = true if focused + pane activeItem: null items: null @@ -47,7 +50,11 @@ class Pane extends View @on 'focusin', => @makeActive() @on 'focusout', => @autosaveActiveItem() - afterAttach: -> + afterAttach: (onDom) -> + if @focusOnAttach and onDom + @focusOnAttach = null + @focus() + return if @attached @attached = true @trigger 'pane:attached' @@ -206,6 +213,9 @@ class Pane extends View itemForUri: (uri) -> _.detect @items, (item) -> item.getUri?() is uri + showItemForUri: (uri) -> + @showItem(@itemForUri(uri)) + cleanupItemView: (item) -> if item instanceof $ viewToRemove = item @@ -238,6 +248,8 @@ class Pane extends View serialize: -> deserializer: "Pane" + focused: @is(':has(:focus)') + activeItemUri: @activeItem.getUri?() if typeof @activeItem.serialize is 'function' items: _.compact(@getItems().map (item) -> item.serialize?()) adjustDimensions: -> # do nothing