mirror of
https://github.com/atom/atom.git
synced 2026-01-23 05:48:10 -05:00
At the model layer: Focus next pane when a focused pane is destroyed
This incorporates the Focusable mixin into PaneModel and ensures that all panes in the same pane container share a single focus context.
This commit is contained in:
@@ -80,7 +80,7 @@ describe "PaneModel", ->
|
||||
|
||||
it "focuses the new pane, even if the current pane isn't focused", ->
|
||||
expect(pane1.focused).toBe false
|
||||
pane2 = pane1.split()
|
||||
pane2 = pane1.splitRight()
|
||||
expect(pane2.focused).toBe true
|
||||
|
||||
describe "::destroy()", ->
|
||||
@@ -110,3 +110,13 @@ describe "PaneModel", ->
|
||||
expect(container.root.children).toEqual [pane1, pane2]
|
||||
pane2.destroy()
|
||||
expect(container.root).toBe pane1
|
||||
|
||||
describe "if the pane is focused", ->
|
||||
it "shifts focus to the next pane", ->
|
||||
pane2 = pane1.splitRight()
|
||||
pane3 = pane2.splitRight()
|
||||
pane2.focus()
|
||||
expect(pane2.focused).toBe true
|
||||
expect(pane3.focused).toBe false
|
||||
pane2.destroy()
|
||||
expect(pane3.focused).toBe true
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
{Model, Sequence} = require 'theorist'
|
||||
{flatten} = require 'underscore-plus'
|
||||
Delegator = require 'delegato'
|
||||
Serializable = require 'serializable'
|
||||
|
||||
PaneRow = null
|
||||
@@ -8,15 +10,24 @@ module.exports =
|
||||
class PaneAxisModel extends Model
|
||||
atom.deserializers.add(this)
|
||||
Serializable.includeInto(this)
|
||||
Delegator.includeInto(this)
|
||||
|
||||
@delegatesMethod 'focusNextPane', toProperty: 'parent'
|
||||
|
||||
@property 'focusContext'
|
||||
|
||||
constructor: ({@orientation, children}) ->
|
||||
@children = Sequence.fromArray(children ? [])
|
||||
|
||||
@children.onEach (child) =>
|
||||
@subscribe @$focusContext, (focusContext) =>
|
||||
child.focusContext = focusContext for child in @children
|
||||
|
||||
@subscribe @children.onEach (child) =>
|
||||
child.parent = this
|
||||
child.focusContext = @focusContext
|
||||
@subscribe child, 'destroyed', => @removeChild(child)
|
||||
|
||||
@children.onRemoval (child) => @unsubscribe(child)
|
||||
@subscribe @children.onRemoval (child) => @unsubscribe(child)
|
||||
|
||||
@when @children.$length.becomesLessThan(2), 'reparentLastChild'
|
||||
@when @children.$length.becomesLessThan(1), 'destroy'
|
||||
@@ -34,6 +45,9 @@ class PaneAxisModel extends Model
|
||||
else
|
||||
PaneRow ?= require './pane-row'
|
||||
|
||||
getPanes: ->
|
||||
flatten(@children.map (child) -> child.getPanes())
|
||||
|
||||
addChild: (child, index=@children.length) ->
|
||||
@children.splice(index, 0, child)
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
{Model} = require 'theorist'
|
||||
Serializable = require 'serializable'
|
||||
{find} = require 'underscore-plus'
|
||||
FocusContext = require './focus-context'
|
||||
|
||||
module.exports =
|
||||
class PaneContainerModel extends Model
|
||||
@@ -8,10 +10,13 @@ class PaneContainerModel extends Model
|
||||
|
||||
@properties
|
||||
root: null
|
||||
focusContext: -> new FocusContext
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
@subscribe @$root, (root) => root?.parent = this
|
||||
@subscribe @$root.filterDefined(), (root) =>
|
||||
root.parent = this
|
||||
root.focusContext = @focusContext
|
||||
|
||||
deserializeParams: (params) ->
|
||||
params.root = atom.deserializers.deserialize(params.root)
|
||||
@@ -23,3 +28,30 @@ class PaneContainerModel extends Model
|
||||
replaceChild: (oldChild, newChild) ->
|
||||
throw new Error("Replacing non-existent child") if oldChild isnt @root
|
||||
@root = newChild
|
||||
|
||||
getPanes: ->
|
||||
@root?.getPanes() ? []
|
||||
|
||||
getFocusedPane: ->
|
||||
find @getPanes(), (pane) -> pane.focused
|
||||
|
||||
focusNextPane: ->
|
||||
panes = @getPanes()
|
||||
if panes.length > 1
|
||||
currentIndex = panes.indexOf(@getFocusedPane())
|
||||
nextIndex = (currentIndex + 1) % panes.length
|
||||
panes[nextIndex].focus()
|
||||
true
|
||||
else
|
||||
false
|
||||
|
||||
focusPreviousPane: ->
|
||||
panes = @getPanes()
|
||||
if panes.length > 1
|
||||
currentIndex = panes.indexOf(@getFocusedPane())
|
||||
previousIndex = currentIndex - 1
|
||||
previousIndex = panes.length - 1 if previousIndex < 0
|
||||
panes[previousIndex].focus()
|
||||
true
|
||||
else
|
||||
false
|
||||
|
||||
@@ -3,17 +3,18 @@
|
||||
{Model} = require 'theorist'
|
||||
Serializable = require 'serializable'
|
||||
PaneAxisModel = require './pane-axis-model'
|
||||
Focusable = require './focusable'
|
||||
Pane = null
|
||||
|
||||
module.exports =
|
||||
class PaneModel extends Model
|
||||
atom.deserializers.add(this)
|
||||
Serializable.includeInto(this)
|
||||
Focusable.includeInto(this)
|
||||
|
||||
@properties
|
||||
items: -> []
|
||||
activeItem: null
|
||||
focused: false
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
@@ -32,11 +33,7 @@ class PaneModel extends Model
|
||||
|
||||
getViewClass: -> Pane ?= require './pane'
|
||||
|
||||
focus: ->
|
||||
@focused = true
|
||||
|
||||
blur: ->
|
||||
@focused = false
|
||||
getPanes: -> [this]
|
||||
|
||||
# Public: Returns all contained views.
|
||||
getItems: ->
|
||||
@@ -132,6 +129,10 @@ class PaneModel extends Model
|
||||
destroyInactiveItems: ->
|
||||
@destroyItem(item) for item in @getItems() when item isnt @activeItem
|
||||
|
||||
# Private: Called by model superclass
|
||||
destroyed: ->
|
||||
@parent.focusNextPane() if @focused
|
||||
|
||||
# Public: Prompt the user to save the given item.
|
||||
promptToSaveItem: (item) ->
|
||||
return true unless item.shouldPromptToSave?()
|
||||
@@ -211,8 +212,10 @@ class PaneModel extends Model
|
||||
if @parent.orientation isnt orientation
|
||||
@parent.replaceChild(this, new PaneAxisModel({orientation, children: [this]}))
|
||||
|
||||
newPane = new @constructor(extend({focused: true}, params))
|
||||
newPane = new @constructor(params)
|
||||
switch side
|
||||
when 'before' then @parent.insertChildBefore(this, newPane)
|
||||
when 'after' then @parent.insertChildAfter(this, newPane)
|
||||
|
||||
newPane.focus()
|
||||
newPane
|
||||
|
||||
Reference in New Issue
Block a user