mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2025-01-07 23:59:22 +03:00
Remove the old root view properly
This commit is contained in:
parent
32f0eb4f76
commit
465d2afd95
@ -1,5 +1,6 @@
|
||||
path = require 'path'
|
||||
temp = require 'temp'
|
||||
PaneContainer = require '../src/pane-container'
|
||||
PaneContainerView = require '../src/pane-container-view'
|
||||
PaneView = require '../src/pane-view'
|
||||
{$, View, $$} = require 'atom'
|
||||
@ -18,7 +19,7 @@ describe "PaneContainerView", ->
|
||||
save: -> @saved = true
|
||||
isEqual: (other) -> @name is other?.name
|
||||
|
||||
container = new PaneContainerView
|
||||
container = atom.workspace.getView(atom.workspace.paneContainer).__spacePenView
|
||||
pane1 = container.getRoot()
|
||||
pane1.activateItem(new TestView('1'))
|
||||
pane2 = pane1.splitRight(new TestView('2'))
|
||||
@ -95,7 +96,7 @@ describe "PaneContainerView", ->
|
||||
|
||||
describe "serialization", ->
|
||||
it "can be serialized and deserialized, and correctly adjusts dimensions of deserialized panes after attach", ->
|
||||
newContainer = new PaneContainerView(container.model.testSerialization())
|
||||
newContainer = atom.workspace.getView(container.model.testSerialization()).__spacePenView
|
||||
expect(newContainer.find('.pane-row > :contains(1)')).toExist()
|
||||
expect(newContainer.find('.pane-row > .pane-column > :contains(2)')).toExist()
|
||||
expect(newContainer.find('.pane-row > .pane-column > :contains(3)')).toExist()
|
||||
@ -111,14 +112,14 @@ describe "PaneContainerView", ->
|
||||
|
||||
describe "if the 'core.destroyEmptyPanes' config option is false (the default)", ->
|
||||
it "leaves the empty panes intact", ->
|
||||
newContainer = new PaneContainerView(container.model.testSerialization())
|
||||
newContainer = atom.workspace.getView(container.model.testSerialization()).__spacePenView
|
||||
expect(newContainer.find('.pane-row > :contains(1)')).toExist()
|
||||
expect(newContainer.find('.pane-row > .pane-column > .pane').length).toBe 2
|
||||
|
||||
describe "if the 'core.destroyEmptyPanes' config option is true", ->
|
||||
it "removes empty panes on deserialization", ->
|
||||
atom.config.set('core.destroyEmptyPanes', true)
|
||||
newContainer = new PaneContainerView(container.model.testSerialization())
|
||||
newContainer = atom.workspace.getView(container.model.testSerialization()).__spacePenView
|
||||
expect(newContainer.find('.pane-row, .pane-column')).not.toExist()
|
||||
expect(newContainer.find('> :contains(1)')).toExist()
|
||||
|
||||
@ -131,7 +132,7 @@ describe "PaneContainerView", ->
|
||||
item2b = new TestView('2b')
|
||||
item3a = new TestView('3a')
|
||||
|
||||
container = new PaneContainerView
|
||||
container = atom.workspace.getView(new PaneContainer).__spacePenView
|
||||
pane1 = container.getRoot()
|
||||
pane1.activateItem(item1a)
|
||||
container.attachToDom()
|
||||
@ -281,7 +282,7 @@ describe "PaneContainerView", ->
|
||||
# |7|8|9|
|
||||
# -------
|
||||
|
||||
container = new PaneContainerView
|
||||
container = atom.workspace.getView(new PaneContainer).__spacePenView
|
||||
pane1 = container.getRoot()
|
||||
pane1.activateItem(new TestView('1'))
|
||||
pane4 = pane1.splitDown(new TestView('4'))
|
||||
|
@ -1,4 +1,4 @@
|
||||
PaneContainerView = require '../src/pane-container-view'
|
||||
PaneContainer = require '../src/pane-container'
|
||||
PaneView = require '../src/pane-view'
|
||||
fs = require 'fs-plus'
|
||||
{Emitter} = require 'event-kit'
|
||||
@ -24,7 +24,7 @@ describe "PaneView", ->
|
||||
|
||||
beforeEach ->
|
||||
atom.deserializers.add(TestView)
|
||||
container = new PaneContainerView
|
||||
container = atom.workspace.getView(new PaneContainer).__spacePenView
|
||||
containerModel = container.model
|
||||
view1 = new TestView(id: 'view-1', text: 'View 1')
|
||||
view2 = new TestView(id: 'view-2', text: 'View 2')
|
||||
@ -311,13 +311,13 @@ describe "PaneView", ->
|
||||
container.attachToDom()
|
||||
pane.focus()
|
||||
|
||||
container2 = new PaneContainerView(container.model.testSerialization())
|
||||
container2 = atom.workspace.getView(container.model.testSerialization()).__spacePenView
|
||||
pane2 = container2.getRoot()
|
||||
container2.attachToDom()
|
||||
expect(pane2).toMatchSelector(':has(:focus)')
|
||||
|
||||
$(document.activeElement).blur()
|
||||
container3 = new PaneContainerView(container.model.testSerialization())
|
||||
container3 = atom.workspace.getView(container.model.testSerialization()).__spacePenView
|
||||
pane3 = container3.getRoot()
|
||||
container3.attachToDom()
|
||||
expect(pane3).not.toMatchSelector(':has(:focus)')
|
||||
|
79
src/pane-container-element.coffee
Normal file
79
src/pane-container-element.coffee
Normal file
@ -0,0 +1,79 @@
|
||||
{CompositeDisposable} = require 'event-kit'
|
||||
{callAttachHooks} = require './space-pen-extensions'
|
||||
PaneContainerView = require './pane-container-view'
|
||||
_ = require 'underscore-plus'
|
||||
|
||||
module.exports =
|
||||
class PaneContainerElement extends HTMLElement
|
||||
createdCallback: ->
|
||||
@subscriptions = new CompositeDisposable
|
||||
@classList.add 'panes'
|
||||
@__spacePenView = new PaneContainerView(this)
|
||||
|
||||
setModel: (@model) ->
|
||||
@subscriptions.add @model.observeRoot(@rootChanged.bind(this))
|
||||
@__spacePenView.setModel(@model)
|
||||
|
||||
rootChanged: (root) ->
|
||||
focusedElement = document.activeElement if @hasFocus()
|
||||
@firstChild?.remove()
|
||||
if root?
|
||||
view = @model.getView(root)
|
||||
@appendChild(view)
|
||||
callAttachHooks(view)
|
||||
focusedElement?.focus()
|
||||
|
||||
hasFocus: ->
|
||||
this is document.activeElement or @contains(document.activeElement)
|
||||
|
||||
focusPaneViewAbove: ->
|
||||
@nearestPaneInDirection('above')?.focus()
|
||||
|
||||
focusPaneViewBelow: ->
|
||||
@nearestPaneInDirection('below')?.focus()
|
||||
|
||||
focusPaneViewOnLeft: ->
|
||||
@nearestPaneInDirection('left')?.focus()
|
||||
|
||||
focusPaneViewOnRight: ->
|
||||
@nearestPaneInDirection('right')?.focus()
|
||||
|
||||
nearestPaneInDirection: (direction) ->
|
||||
distance = (pointA, pointB) ->
|
||||
x = pointB.x - pointA.x
|
||||
y = pointB.y - pointA.y
|
||||
Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2))
|
||||
|
||||
paneView = @model.getView(@model.getActivePane())
|
||||
box = @boundingBoxForPaneView(paneView)
|
||||
|
||||
paneViews = _.toArray(@querySelectorAll('.pane'))
|
||||
.filter (otherPaneView) =>
|
||||
otherBox = @boundingBoxForPaneView(otherPaneView)
|
||||
switch direction
|
||||
when 'left' then otherBox.right.x <= box.left.x
|
||||
when 'right' then otherBox.left.x >= box.right.x
|
||||
when 'above' then otherBox.bottom.y <= box.top.y
|
||||
when 'below' then otherBox.top.y >= box.bottom.y
|
||||
.sort (paneViewA, paneViewB) =>
|
||||
boxA = @boundingBoxForPaneView(paneViewA)
|
||||
boxB = @boundingBoxForPaneView(paneViewB)
|
||||
switch direction
|
||||
when 'left' then distance(box.left, boxA.right) - distance(box.left, boxB.right)
|
||||
when 'right' then distance(box.right, boxA.left) - distance(box.right, boxB.left)
|
||||
when 'above' then distance(box.top, boxA.bottom) - distance(box.top, boxB.bottom)
|
||||
when 'below' then distance(box.bottom, boxA.top) - distance(box.bottom, boxB.top)
|
||||
|
||||
paneViews[0]
|
||||
|
||||
boundingBoxForPaneView: (paneView) ->
|
||||
boundingBox = paneView.getBoundingClientRect()
|
||||
|
||||
left: {x: boundingBox.left, y: boundingBox.top}
|
||||
right: {x: boundingBox.right, y: boundingBox.top}
|
||||
top: {x: boundingBox.left, y: boundingBox.top}
|
||||
bottom: {x: boundingBox.left, y: boundingBox.bottom}
|
||||
|
||||
module.exports = PaneContainerElement = document.registerElement 'atom-pane-container',
|
||||
prototype: PaneContainerElement.prototype
|
||||
extends: 'div'
|
@ -15,43 +15,20 @@ class PaneContainerView extends View
|
||||
@content: ->
|
||||
@div class: 'panes'
|
||||
|
||||
initialize: (params) ->
|
||||
constructor: (@element) ->
|
||||
super
|
||||
@subscriptions = new CompositeDisposable
|
||||
|
||||
if params instanceof PaneContainer
|
||||
@model = params
|
||||
else
|
||||
@model = new PaneContainer({root: params?.root?.model})
|
||||
|
||||
@subscriptions.add @model.observeRoot(@onRootChanged)
|
||||
setModel: (@model) ->
|
||||
@subscriptions.add @model.onDidChangeActivePaneItem(@onActivePaneItemChanged)
|
||||
|
||||
getRoot: ->
|
||||
view = @model.getView(@model.getRoot())
|
||||
view.__spacePenView ? view
|
||||
|
||||
onRootChanged: (root) =>
|
||||
focusedElement = document.activeElement if @hasFocus()
|
||||
|
||||
if oldRootView = @model.getView(@model.getRoot())
|
||||
oldRootView.remove()
|
||||
|
||||
if root?
|
||||
view = @model.getView(root)
|
||||
@append(view)
|
||||
callAttachHooks(view)
|
||||
focusedElement?.focus()
|
||||
else
|
||||
atom.workspaceView?.focus() if focusedElement?
|
||||
|
||||
onActivePaneItemChanged: (activeItem) =>
|
||||
@trigger 'pane-container:active-pane-item-changed', [activeItem]
|
||||
|
||||
removeChild: (child) ->
|
||||
throw new Error("Removing non-existant child") unless @getRoot() is child
|
||||
@setRoot(null)
|
||||
@trigger 'pane:removed', [child] if child instanceof PaneView
|
||||
|
||||
confirmClose: ->
|
||||
saved = true
|
||||
for paneView in @getPaneViews()
|
||||
@ -102,56 +79,17 @@ class PaneContainerView extends View
|
||||
@model.activatePreviousPane()
|
||||
|
||||
focusPaneViewAbove: ->
|
||||
@nearestPaneInDirection('above')?.focus()
|
||||
@element.focusPaneViewAbove()
|
||||
|
||||
focusPaneViewBelow: ->
|
||||
@nearestPaneInDirection('below')?.focus()
|
||||
@element.focusPaneViewBelow()
|
||||
|
||||
focusPaneViewOnLeft: ->
|
||||
@nearestPaneInDirection('left')?.focus()
|
||||
@element.focusPaneViewOnLeft()
|
||||
|
||||
focusPaneViewOnRight: ->
|
||||
@nearestPaneInDirection('right')?.focus()
|
||||
@element.focusPaneViewOnRight()
|
||||
|
||||
nearestPaneInDirection: (direction) ->
|
||||
distance = (pointA, pointB) ->
|
||||
x = pointB.x - pointA.x
|
||||
y = pointB.y - pointA.y
|
||||
Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2))
|
||||
|
||||
paneView = @getActivePaneView()
|
||||
box = @boundingBoxForPaneView(paneView)
|
||||
paneViews = @getPaneViews()
|
||||
.filter (otherPaneView) =>
|
||||
otherBox = @boundingBoxForPaneView(otherPaneView)
|
||||
switch direction
|
||||
when 'left' then otherBox.right.x <= box.left.x
|
||||
when 'right' then otherBox.left.x >= box.right.x
|
||||
when 'above' then otherBox.bottom.y <= box.top.y
|
||||
when 'below' then otherBox.top.y >= box.bottom.y
|
||||
.sort (paneViewA, paneViewB) =>
|
||||
boxA = @boundingBoxForPaneView(paneViewA)
|
||||
boxB = @boundingBoxForPaneView(paneViewB)
|
||||
switch direction
|
||||
when 'left' then distance(box.left, boxA.right) - distance(box.left, boxB.right)
|
||||
when 'right' then distance(box.right, boxA.left) - distance(box.right, boxB.left)
|
||||
when 'above' then distance(box.top, boxA.bottom) - distance(box.top, boxB.bottom)
|
||||
when 'below' then distance(box.bottom, boxA.top) - distance(box.bottom, boxB.top)
|
||||
|
||||
paneViews[0]
|
||||
|
||||
boundingBoxForPaneView: (paneView) ->
|
||||
boundingBox = paneView[0].getBoundingClientRect()
|
||||
|
||||
left: {x: boundingBox.left, y: boundingBox.top}
|
||||
right: {x: boundingBox.right, y: boundingBox.top}
|
||||
top: {x: boundingBox.left, y: boundingBox.top}
|
||||
bottom: {x: boundingBox.left, y: boundingBox.bottom}
|
||||
|
||||
# Deprecated
|
||||
getPanes: ->
|
||||
deprecate("Use PaneContainerView::getPaneViews() instead")
|
||||
@getPaneViews()
|
||||
|
||||
beforeRemove: ->
|
||||
@subscriptions.dispose()
|
||||
|
@ -4,11 +4,11 @@
|
||||
Serializable = require 'serializable'
|
||||
Pane = require './pane'
|
||||
PaneElement = require './pane-element'
|
||||
PaneAxis = require './pane-axis'
|
||||
PaneContainerElement = require './pane-container-element'
|
||||
PaneAxisElement = require './pane-axis-element'
|
||||
PaneAxis = require './pane-axis'
|
||||
ViewRegistry = require './view-registry'
|
||||
ItemRegistry = require './item-registry'
|
||||
PaneContainerView = null
|
||||
|
||||
module.exports =
|
||||
class PaneContainer extends Model
|
||||
@ -35,12 +35,7 @@ class PaneContainer extends Model
|
||||
|
||||
@itemRegistry = new ItemRegistry
|
||||
@viewRegistry = params?.viewRegistry ? new ViewRegistry
|
||||
@viewRegistry.addViewProvider
|
||||
modelConstructor: Pane
|
||||
viewConstructor: PaneElement
|
||||
@viewRegistry.addViewProvider
|
||||
modelConstructor: PaneAxis
|
||||
viewConstructor: PaneAxisElement
|
||||
@registerViewProviders()
|
||||
|
||||
@setRoot(params?.root ? new Pane)
|
||||
@destroyEmptyPanes() if params?.destroyEmptyPanes
|
||||
@ -58,8 +53,18 @@ class PaneContainer extends Model
|
||||
root: @root?.serialize()
|
||||
activePaneId: @activePane.id
|
||||
|
||||
getViewClass: ->
|
||||
PaneContainerView ?= require './pane-container-view'
|
||||
registerViewProviders: ->
|
||||
@viewRegistry.addViewProvider
|
||||
modelConstructor: PaneContainer
|
||||
viewConstructor: PaneContainerElement
|
||||
|
||||
@viewRegistry.addViewProvider
|
||||
modelConstructor: PaneAxis
|
||||
viewConstructor: PaneAxisElement
|
||||
|
||||
@viewRegistry.addViewProvider
|
||||
modelConstructor: Pane
|
||||
viewConstructor: PaneElement
|
||||
|
||||
getView: (object) ->
|
||||
@viewRegistry.getView(object)
|
||||
|
@ -29,11 +29,12 @@ class Workspace extends Model
|
||||
@delegatesProperty 'activePane', 'activePaneItem', toProperty: 'paneContainer'
|
||||
|
||||
@properties
|
||||
viewRegistry: null
|
||||
paneContainer: null
|
||||
fullScreen: false
|
||||
destroyedItemUris: -> []
|
||||
|
||||
constructor: ->
|
||||
constructor: (params) ->
|
||||
super
|
||||
|
||||
@emitter = new Emitter
|
||||
@ -61,6 +62,7 @@ class Workspace extends Model
|
||||
|
||||
params.viewRegistry = new ViewRegistry
|
||||
params.paneContainer.viewRegistry = params.viewRegistry
|
||||
console.log "deserializing pane container"
|
||||
params.paneContainer = PaneContainer.deserialize(params.paneContainer)
|
||||
params
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user