mirror of
https://github.com/atom/atom.git
synced 2026-04-28 03:01:47 -04:00
Merge pull request #10737 from natalieogle/mostRecentlyViewed
Add MRU tab switching functionality
This commit is contained in:
@@ -73,8 +73,10 @@
|
||||
'cmd-alt-right': 'pane:show-next-item'
|
||||
'ctrl-pageup': 'pane:show-previous-item'
|
||||
'ctrl-pagedown': 'pane:show-next-item'
|
||||
'ctrl-tab': 'pane:show-next-item'
|
||||
'ctrl-shift-tab': 'pane:show-previous-item'
|
||||
'ctrl-tab': 'pane:show-next-recently-used-item'
|
||||
'ctrl-tab ^ctrl': 'pane:move-active-item-to-top-of-stack'
|
||||
'ctrl-shift-tab': 'pane:show-previous-recently-used-item'
|
||||
'ctrl-shift-tab ^ctrl': 'pane:move-active-item-to-top-of-stack'
|
||||
'cmd-=': 'window:increase-font-size'
|
||||
'cmd-+': 'window:increase-font-size'
|
||||
'cmd--': 'window:decrease-font-size'
|
||||
|
||||
@@ -46,8 +46,10 @@
|
||||
'pagedown': 'core:page-down'
|
||||
'backspace': 'core:backspace'
|
||||
'shift-backspace': 'core:backspace'
|
||||
'ctrl-tab': 'pane:show-next-item'
|
||||
'ctrl-shift-tab': 'pane:show-previous-item'
|
||||
'ctrl-tab': 'pane:show-next-recently-used-item'
|
||||
'ctrl-tab ^ctrl': 'pane:move-active-item-to-top-of-stack'
|
||||
'ctrl-shift-tab': 'pane:show-previous-recently-used-item'
|
||||
'ctrl-shift-tab ^ctrl': 'pane:move-active-item-to-top-of-stack'
|
||||
'ctrl-pageup': 'pane:show-previous-item'
|
||||
'ctrl-pagedown': 'pane:show-next-item'
|
||||
'ctrl-up': 'core:move-up'
|
||||
|
||||
@@ -52,8 +52,10 @@
|
||||
'pagedown': 'core:page-down'
|
||||
'backspace': 'core:backspace'
|
||||
'shift-backspace': 'core:backspace'
|
||||
'ctrl-tab': 'pane:show-next-item'
|
||||
'ctrl-shift-tab': 'pane:show-previous-item'
|
||||
'ctrl-tab': 'pane:show-next-recently-used-item'
|
||||
'ctrl-tab ^ctrl': 'pane:move-active-item-to-top-of-stack'
|
||||
'ctrl-shift-tab': 'pane:show-previous-recently-used-item'
|
||||
'ctrl-shift-tab ^ctrl': 'pane:move-active-item-to-top-of-stack'
|
||||
'ctrl-pageup': 'pane:show-previous-item'
|
||||
'ctrl-pagedown': 'pane:show-next-item'
|
||||
'ctrl-shift-up': 'core:move-up'
|
||||
|
||||
@@ -183,6 +183,35 @@ describe "Pane", ->
|
||||
pane.activateItem(itemD, true)
|
||||
expect(pane.getItems().map (item) -> item.name).toEqual ['A', 'B', 'D']
|
||||
|
||||
describe "::activateNextRecentlyUsedItem() and ::activatePreviousRecentlyUsedItem()", ->
|
||||
it "sets the active item to the next/previous item in the itemStack, looping around at either end", ->
|
||||
pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C"), new Item("D"), new Item("E")]))
|
||||
[item1, item2, item3, item4, item5] = pane.getItems()
|
||||
pane.itemStack = [item3, item1, item2, item5, item4]
|
||||
|
||||
pane.activateItem(item4)
|
||||
expect(pane.getActiveItem()).toBe item4
|
||||
pane.activateNextRecentlyUsedItem()
|
||||
expect(pane.getActiveItem()).toBe item5
|
||||
pane.activateNextRecentlyUsedItem()
|
||||
expect(pane.getActiveItem()).toBe item2
|
||||
pane.activatePreviousRecentlyUsedItem()
|
||||
expect(pane.getActiveItem()).toBe item5
|
||||
pane.activatePreviousRecentlyUsedItem()
|
||||
expect(pane.getActiveItem()).toBe item4
|
||||
pane.activatePreviousRecentlyUsedItem()
|
||||
expect(pane.getActiveItem()).toBe item3
|
||||
pane.activatePreviousRecentlyUsedItem()
|
||||
expect(pane.getActiveItem()).toBe item1
|
||||
pane.activateNextRecentlyUsedItem()
|
||||
expect(pane.getActiveItem()).toBe item3
|
||||
pane.activateNextRecentlyUsedItem()
|
||||
expect(pane.getActiveItem()).toBe item4
|
||||
pane.activateNextRecentlyUsedItem()
|
||||
pane.moveActiveItemToTopOfStack()
|
||||
expect(pane.getActiveItem()).toBe item5
|
||||
expect(pane.itemStack[4]).toBe item5
|
||||
|
||||
describe "::activateNextItem() and ::activatePreviousItem()", ->
|
||||
it "sets the active item to the next/previous item, looping around at either end", ->
|
||||
pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")]))
|
||||
@@ -249,7 +278,7 @@ describe "Pane", ->
|
||||
pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")]))
|
||||
[item1, item2, item3] = pane.getItems()
|
||||
|
||||
it "removes the item from the items list and destroyes it", ->
|
||||
it "removes the item from the items list and destroys it", ->
|
||||
expect(pane.getActiveItem()).toBe item1
|
||||
pane.destroyItem(item2)
|
||||
expect(item2 in pane.getItems()).toBe false
|
||||
@@ -260,6 +289,19 @@ describe "Pane", ->
|
||||
expect(item1 in pane.getItems()).toBe false
|
||||
expect(item1.isDestroyed()).toBe true
|
||||
|
||||
it "removes the item from the itemStack", ->
|
||||
pane.itemStack = [item2, item3, item1]
|
||||
|
||||
pane.activateItem(item1)
|
||||
expect(pane.getActiveItem()).toBe item1
|
||||
pane.destroyItem(item3)
|
||||
expect(pane.itemStack).toEqual [item2, item1]
|
||||
expect(pane.getActiveItem()).toBe item1
|
||||
|
||||
pane.destroyItem(item1)
|
||||
expect(pane.itemStack).toEqual [item2]
|
||||
expect(pane.getActiveItem()).toBe item2
|
||||
|
||||
it "invokes ::onWillDestroyItem() observers before destroying the item", ->
|
||||
events = []
|
||||
pane.onWillDestroyItem (event) ->
|
||||
@@ -894,3 +936,30 @@ describe "Pane", ->
|
||||
pane.focus()
|
||||
newPane = Pane.deserialize(pane.serialize(), atom)
|
||||
expect(newPane.focused).toBe true
|
||||
|
||||
it "can serialize and deserialize the order of the items in the itemStack", ->
|
||||
[item1, item2, item3] = pane.getItems()
|
||||
pane.itemStack = [item3, item1, item2]
|
||||
newPane = Pane.deserialize(pane.serialize(), atom)
|
||||
expect(newPane.itemStack).toEqual pane.itemStack
|
||||
expect(newPane.itemStack[2]).toEqual item2
|
||||
|
||||
it "builds the itemStack if the itemStack is not serialized", ->
|
||||
[item1, item2, item3] = pane.getItems()
|
||||
newPane = Pane.deserialize(pane.serialize(), atom)
|
||||
expect(newPane.getItems()).toEqual newPane.itemStack
|
||||
|
||||
it "rebuilds the itemStack if items.length does not match itemStack.length", ->
|
||||
[item1, item2, item3] = pane.getItems()
|
||||
pane.itemStack = [item2, item3]
|
||||
newPane = Pane.deserialize(pane.serialize(), atom)
|
||||
expect(newPane.getItems()).toEqual newPane.itemStack
|
||||
|
||||
it "does not serialize the reference to the items in the itemStack for pane items that will not be serialized", ->
|
||||
[item1, item2, item3] = pane.getItems()
|
||||
pane.itemStack = [item2, item1, item3]
|
||||
unserializable = {}
|
||||
pane.activateItem(unserializable)
|
||||
|
||||
newPane = Pane.deserialize(pane.serialize(), atom)
|
||||
expect(newPane.itemStack).toEqual [item2, item1, item3]
|
||||
|
||||
@@ -20,7 +20,7 @@ class Pane extends Model
|
||||
focused: false
|
||||
|
||||
@deserialize: (state, {deserializers, applicationDelegate, config, notifications}) ->
|
||||
{items, activeItemURI, activeItemUri} = state
|
||||
{items, itemStackIndices, activeItemURI, activeItemUri} = state
|
||||
activeItemURI ?= activeItemUri
|
||||
state.items = compact(items.map (itemState) -> deserializers.deserialize(itemState))
|
||||
state.activeItem = find state.items, (item) ->
|
||||
@@ -44,18 +44,23 @@ class Pane extends Model
|
||||
@emitter = new Emitter
|
||||
@subscriptionsPerItem = new WeakMap
|
||||
@items = []
|
||||
@itemStack = []
|
||||
|
||||
@addItems(compact(params?.items ? []))
|
||||
@setActiveItem(@items[0]) unless @getActiveItem()?
|
||||
@addItemsToStack(params?.itemStackIndices ? [])
|
||||
@setFlexScale(params?.flexScale ? 1)
|
||||
|
||||
serialize: ->
|
||||
if typeof @activeItem?.getURI is 'function'
|
||||
activeItemURI = @activeItem.getURI()
|
||||
itemsToBeSerialized = compact(@items.map((item) -> item if typeof item.serialize is 'function'))
|
||||
itemStackIndices = (itemsToBeSerialized.indexOf(item) for item in @itemStack when typeof item.serialize is 'function')
|
||||
|
||||
deserializer: 'Pane'
|
||||
id: @id
|
||||
items: compact(@items.map((item) -> item.serialize?()))
|
||||
items: itemsToBeSerialized.map((item) -> item.serialize())
|
||||
itemStackIndices: itemStackIndices
|
||||
activeItemURI: activeItemURI
|
||||
focused: @focused
|
||||
flexScale: @flexScale
|
||||
@@ -283,12 +288,29 @@ class Pane extends Model
|
||||
# Returns a pane item.
|
||||
getActiveItem: -> @activeItem
|
||||
|
||||
setActiveItem: (activeItem) ->
|
||||
setActiveItem: (activeItem, options) ->
|
||||
{modifyStack} = options if options?
|
||||
unless activeItem is @activeItem
|
||||
@addItemToStack(activeItem) unless modifyStack is false
|
||||
@activeItem = activeItem
|
||||
@emitter.emit 'did-change-active-item', @activeItem
|
||||
@activeItem
|
||||
|
||||
# Build the itemStack after deserializing
|
||||
addItemsToStack: (itemStackIndices) ->
|
||||
if @items.length > 0
|
||||
if itemStackIndices.length is 0 or itemStackIndices.length isnt @items.length or itemStackIndices.indexOf(-1) >= 0
|
||||
itemStackIndices = (i for i in [0..@items.length-1])
|
||||
for itemIndex in itemStackIndices
|
||||
@addItemToStack(@items[itemIndex])
|
||||
return
|
||||
|
||||
# Add item (or move item) to the end of the itemStack
|
||||
addItemToStack: (newItem) ->
|
||||
index = @itemStack.indexOf(newItem)
|
||||
@itemStack.splice(index, 1) unless index is -1
|
||||
@itemStack.push(newItem)
|
||||
|
||||
# Return an {TextEditor} if the pane item is an {TextEditor}, or null otherwise.
|
||||
getActiveEditor: ->
|
||||
@activeItem if @activeItem instanceof TextEditor
|
||||
@@ -301,6 +323,29 @@ class Pane extends Model
|
||||
itemAtIndex: (index) ->
|
||||
@items[index]
|
||||
|
||||
# Makes the next item in the itemStack active.
|
||||
activateNextRecentlyUsedItem: ->
|
||||
if @items.length > 1
|
||||
@itemStackIndex = @itemStack.length - 1 unless @itemStackIndex?
|
||||
@itemStackIndex = @itemStack.length if @itemStackIndex is 0
|
||||
@itemStackIndex = @itemStackIndex - 1
|
||||
nextRecentlyUsedItem = @itemStack[@itemStackIndex]
|
||||
@setActiveItem(nextRecentlyUsedItem, modifyStack: false)
|
||||
|
||||
# Makes the previous item in the itemStack active.
|
||||
activatePreviousRecentlyUsedItem: ->
|
||||
if @items.length > 1
|
||||
if @itemStackIndex + 1 is @itemStack.length or not @itemStackIndex?
|
||||
@itemStackIndex = -1
|
||||
@itemStackIndex = @itemStackIndex + 1
|
||||
previousRecentlyUsedItem = @itemStack[@itemStackIndex]
|
||||
@setActiveItem(previousRecentlyUsedItem, modifyStack: false)
|
||||
|
||||
# Moves the active item to the end of the itemStack once the ctrl key is lifted
|
||||
moveActiveItemToTopOfStack: ->
|
||||
delete @itemStackIndex
|
||||
@addItemToStack(@activeItem)
|
||||
|
||||
# Public: Makes the next item active.
|
||||
activateNextItem: ->
|
||||
index = @getActiveItemIndex()
|
||||
@@ -425,9 +470,8 @@ class Pane extends Model
|
||||
removeItem: (item, moved) ->
|
||||
index = @items.indexOf(item)
|
||||
return if index is -1
|
||||
|
||||
@pendingItem = null if @getPendingItem() is item
|
||||
|
||||
@removeItemFromStack(item)
|
||||
@emitter.emit 'will-remove-item', {item, index, destroyed: not moved, moved}
|
||||
@unsubscribeFromItem(item)
|
||||
|
||||
@@ -443,6 +487,14 @@ class Pane extends Model
|
||||
@container?.didDestroyPaneItem({item, index, pane: this}) unless moved
|
||||
@destroy() if @items.length is 0 and @config.get('core.destroyEmptyPanes')
|
||||
|
||||
# Remove the given item from the itemStack.
|
||||
#
|
||||
# * `item` The item to remove.
|
||||
# * `index` {Number} indicating the index to which to remove the item from the itemStack.
|
||||
removeItemFromStack: (item) ->
|
||||
index = @itemStack.indexOf(item)
|
||||
@itemStack.splice(index, 1) unless index is -1
|
||||
|
||||
# Public: Move the given item to the given index.
|
||||
#
|
||||
# * `item` The item to move.
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
module.exports = ({commandRegistry, commandInstaller, config}) ->
|
||||
commandRegistry.add 'atom-workspace',
|
||||
'pane:show-next-recently-used-item': -> @getModel().getActivePane().activateNextRecentlyUsedItem()
|
||||
'pane:show-previous-recently-used-item': -> @getModel().getActivePane().activatePreviousRecentlyUsedItem()
|
||||
'pane:move-active-item-to-top-of-stack': -> @getModel().getActivePane().moveActiveItemToTopOfStack()
|
||||
'pane:show-next-item': -> @getModel().getActivePane().activateNextItem()
|
||||
'pane:show-previous-item': -> @getModel().getActivePane().activatePreviousItem()
|
||||
'pane:show-item-1': -> @getModel().getActivePane().activateItemAtIndex(0)
|
||||
|
||||
Reference in New Issue
Block a user