mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-11-10 10:17:11 +03:00
Manage the active pane at the model level
This commit is contained in:
parent
4026e6ca5c
commit
5e1b2e2696
@ -50,7 +50,7 @@
|
||||
"temp": "0.5.0",
|
||||
"text-buffer": "0.12.0",
|
||||
"underscore-plus": "0.6.1",
|
||||
"theorist": "~0.9.0",
|
||||
"theorist": "~0.10.0",
|
||||
"delegato": "~0.4.0",
|
||||
"mixto": "~0.4.0"
|
||||
},
|
||||
|
@ -11,6 +11,36 @@ describe "PaneContainerModel", ->
|
||||
expect(pane3A.focused).toBe true
|
||||
|
||||
containerB = containerA.testSerialization()
|
||||
[pane1A, pane2A, pane3A] = containerB.getPanes()
|
||||
expect(pane3A.focusContext).toBe containerB.focusContext
|
||||
expect(pane3A.focused).toBe true
|
||||
[pane1B, pane2B, pane3B] = containerB.getPanes()
|
||||
expect(pane3B.focusContext).toBe containerB.focusContext
|
||||
expect(pane3B.focused).toBe true
|
||||
|
||||
describe "::activePane", ->
|
||||
[container, pane1, pane2] = []
|
||||
|
||||
beforeEach ->
|
||||
pane1 = new PaneModel
|
||||
container = new PaneContainerModel(root: pane1)
|
||||
|
||||
it "references the first pane if no pane has been focused", ->
|
||||
expect(container.activePane).toBe pane1
|
||||
expect(pane1.active).toBe true
|
||||
|
||||
it "references the most recently focused pane", ->
|
||||
pane2 = pane1.splitRight()
|
||||
expect(container.activePane).toBe pane2
|
||||
expect(pane1.active).toBe false
|
||||
expect(pane2.active).toBe true
|
||||
pane1.focus()
|
||||
expect(container.activePane).toBe pane1
|
||||
expect(pane1.active).toBe true
|
||||
expect(pane2.active).toBe false
|
||||
|
||||
it "is reassigned to the next pane if the current active pane is unfocused and destroyed", ->
|
||||
pane2 = pane1.splitRight()
|
||||
pane2.blur()
|
||||
pane2.destroy()
|
||||
expect(container.activePane).toBe pane1
|
||||
expect(pane1.active).toBe true
|
||||
pane1.destroy()
|
||||
expect(container.activePane).toBe null
|
||||
|
@ -88,7 +88,8 @@ describe "PaneModel", ->
|
||||
describe "::removeItemAtIndex(index)", ->
|
||||
describe "when the removal of the item causes blur to be called on the pane model", ->
|
||||
it "remains focused if it was before the item was removed", ->
|
||||
pane = new PaneModel(items: ["A", "B", "C"], focusContext: new FocusContext)
|
||||
pane = new PaneModel(items: ["A", "B", "C"])
|
||||
container = new PaneContainerModel(root: pane)
|
||||
pane.on 'item-removed', -> pane.blur()
|
||||
pane.focus()
|
||||
pane.removeItemAtIndex(0)
|
||||
|
@ -12,19 +12,14 @@ class PaneAxisModel extends Model
|
||||
Serializable.includeInto(this)
|
||||
Delegator.includeInto(this)
|
||||
|
||||
@delegatesMethod 'focusNextPane', toProperty: 'parent'
|
||||
@delegatesProperty 'focusContext', toProperty: 'container'
|
||||
|
||||
@property 'focusContext'
|
||||
|
||||
constructor: ({@focusContext, @orientation, children}) ->
|
||||
constructor: ({@container, @orientation, children}) ->
|
||||
@children = Sequence.fromArray(children ? [])
|
||||
|
||||
@subscribe @$focusContext, (focusContext) =>
|
||||
child.focusContext = focusContext for child in @children
|
||||
|
||||
@subscribe @children.onEach (child) =>
|
||||
child.parent = this
|
||||
child.focusContext = @focusContext
|
||||
child.container = @container
|
||||
@subscribe child, 'destroyed', => @removeChild(child)
|
||||
|
||||
@subscribe @children.onRemoval (child) => @unsubscribe(child)
|
||||
@ -33,8 +28,8 @@ class PaneAxisModel extends Model
|
||||
@when @children.$length.becomesLessThan(1), 'destroy'
|
||||
|
||||
deserializeParams: (params) ->
|
||||
{focusContext} = params
|
||||
params.children = params.children.map (childState) -> atom.deserializers.deserialize(childState, {focusContext})
|
||||
{container} = params
|
||||
params.children = params.children.map (childState) -> atom.deserializers.deserialize(childState, {container})
|
||||
params
|
||||
|
||||
serializeParams: ->
|
||||
|
@ -2,6 +2,7 @@
|
||||
Serializable = require 'serializable'
|
||||
{find} = require 'underscore-plus'
|
||||
FocusContext = require './focus-context'
|
||||
PaneModel = require './pane-model'
|
||||
|
||||
module.exports =
|
||||
class PaneContainerModel extends Model
|
||||
@ -10,18 +11,23 @@ class PaneContainerModel extends Model
|
||||
|
||||
@properties
|
||||
root: null
|
||||
focusContext: -> new FocusContext
|
||||
focusContext: null
|
||||
activePane: null
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
@focusContext ?= new FocusContext
|
||||
|
||||
@subscribe @$root, (root) =>
|
||||
if root?
|
||||
root.parent = this
|
||||
root.focusContext = @focusContext
|
||||
root.container = this
|
||||
@activePane ?= root if root instanceof PaneModel
|
||||
|
||||
deserializeParams: (params) ->
|
||||
params.focusContext ?= new FocusContext
|
||||
params.root = atom.deserializers.deserialize(params.root, focusContext: params.focusContext)
|
||||
@focusContext ?= params.focusContext ? new FocusContext
|
||||
params.root = atom.deserializers.deserialize(params.root, container: this)
|
||||
params
|
||||
|
||||
serializeParams: (params) ->
|
||||
@ -57,3 +63,12 @@ class PaneContainerModel extends Model
|
||||
true
|
||||
else
|
||||
false
|
||||
|
||||
makeNextPaneActive: ->
|
||||
panes = @getPanes()
|
||||
if panes.length > 1
|
||||
currentIndex = panes.indexOf(@activePane)
|
||||
nextIndex = (currentIndex + 1) % panes.length
|
||||
@activePane = panes[nextIndex]
|
||||
else
|
||||
@activePane = null
|
||||
|
@ -13,26 +13,38 @@ class PaneModel extends Model
|
||||
Focusable.includeInto(this)
|
||||
|
||||
@properties
|
||||
container: null
|
||||
activeItem: null
|
||||
|
||||
@behavior 'active', ->
|
||||
@$container
|
||||
.flatMapLatest((container) -> container?.$activePane)
|
||||
.map((activePane) => activePane is this)
|
||||
.distinctUntilChanged()
|
||||
|
||||
constructor: (params) ->
|
||||
super
|
||||
|
||||
@focus() if params?.focused
|
||||
|
||||
@items = Sequence.fromArray(params?.items ? [])
|
||||
@activeItem ?= @items[0]
|
||||
|
||||
@subscribe @$container, (container) =>
|
||||
@focusContext = container?.focusContext
|
||||
|
||||
@subscribe @items.onEach (item) =>
|
||||
if typeof item.on is 'function'
|
||||
@subscribe item, 'destroyed', => @removeItem(item)
|
||||
|
||||
@subscribe @items.onRemoval (item, index) =>
|
||||
@unsubscribe item
|
||||
@unsubscribe item if typeof item.on is 'function'
|
||||
@emit 'item-removed', item, index
|
||||
|
||||
@when @items.$length.becomesLessThan(1), 'destroy'
|
||||
|
||||
@when @$focused, => @makeActive()
|
||||
|
||||
@focus() if params?.focused
|
||||
|
||||
serializeParams: ->
|
||||
items: compact(@items.map((item) -> item.serialize?()))
|
||||
activeItemUri: @activeItem?.getUri?()
|
||||
@ -46,6 +58,10 @@ class PaneModel extends Model
|
||||
|
||||
getViewClass: -> Pane ?= require './pane'
|
||||
|
||||
isActive: -> @active
|
||||
|
||||
makeActive: -> @container.activePane = this
|
||||
|
||||
getPanes: -> [this]
|
||||
|
||||
# Public: Returns all contained views.
|
||||
@ -144,7 +160,10 @@ class PaneModel extends Model
|
||||
# Private: Called by model superclass
|
||||
destroyed: ->
|
||||
item.destroy?() for item in @items.slice()
|
||||
@parent.focusNextPane() if @focused
|
||||
if @focused
|
||||
@container.focusNextPane()
|
||||
else if @isActive()
|
||||
@container.makeNextPaneActive()
|
||||
|
||||
# Public: Prompt the user to save the given item.
|
||||
promptToSaveItem: (item) ->
|
||||
@ -223,7 +242,7 @@ class PaneModel extends Model
|
||||
|
||||
split: (orientation, side, params) ->
|
||||
if @parent.orientation isnt orientation
|
||||
@parent.replaceChild(this, new PaneAxisModel({orientation, children: [this]}))
|
||||
@parent.replaceChild(this, new PaneAxisModel({@container, orientation, children: [this]}))
|
||||
|
||||
newPane = new @constructor(params)
|
||||
switch side
|
||||
|
Loading…
Reference in New Issue
Block a user