mirror of
https://github.com/atom/atom.git
synced 2026-01-23 22:08:08 -05:00
Start converting tabs package to work with new panes / pane-items
This commit is contained in:
committed by
probablycorey
parent
5240d9989f
commit
0c24843e52
@@ -1,4 +1,5 @@
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
SortableList = require 'sortable-list'
|
||||
TabView = require './tab-view'
|
||||
|
||||
@@ -9,14 +10,16 @@ class TabBarView extends SortableList
|
||||
|
||||
initialize: (@pane) ->
|
||||
super
|
||||
|
||||
@addTabForItem(item) for item in @pane.getItems()
|
||||
|
||||
@pane.on 'pane:item-added', (e, item, index) => @addTabForItem(item, index)
|
||||
@pane.on 'pane:item-removed', (e, item) => @removeTabForItem(item)
|
||||
@pane.on 'pane:active-item-changed', => @updateActiveTab()
|
||||
|
||||
@updateActiveTab()
|
||||
|
||||
# @addTabForEditSession(editSession) for editSession in @editor.editSessions
|
||||
#
|
||||
# @setActiveTab(@editor.getActiveEditSessionIndex())
|
||||
# @editor.on 'editor:active-edit-session-changed', (e, editSession, index) => @setActiveTab(index)
|
||||
|
||||
# @editor.on 'editor:edit-session-added', (e, editSession) => @addTabForEditSession(editSession)
|
||||
# @editor.on 'editor:edit-session-removed', (e, editSession, index) => @removeTabAtIndex(index)
|
||||
# @editor.on 'editor:edit-session-order-changed', (e, editSession, fromIndex, toIndex) =>
|
||||
@@ -29,26 +32,45 @@ class TabBarView extends SortableList
|
||||
# fromTab.insertBefore(toTab)
|
||||
|
||||
@on 'click', '.tab', (e) =>
|
||||
@editor.setActiveEditSessionIndex($(e.target).closest('.tab').index())
|
||||
@editor.focus()
|
||||
tab = $(e.target).closest('.tab').view()
|
||||
@pane.showItem(tab.item)
|
||||
@pane.focus()
|
||||
|
||||
@on 'click', '.tab .close-icon', (e) =>
|
||||
index = $(e.target).closest('.tab').index()
|
||||
@editor.destroyEditSessionIndex(index)
|
||||
tab = $(e.target).closest('.tab').view()
|
||||
@pane.removeItem(tab.item)
|
||||
false
|
||||
|
||||
@pane.prepend(this)
|
||||
|
||||
addTabForItem: (item) ->
|
||||
addTabForItem: (item, index) ->
|
||||
tabView = new TabView(item, @pane)
|
||||
@append(tabView)
|
||||
@setActiveTabView(tabView) if item is @pane.currentItem
|
||||
followingTab = @tabAtIndex(index) if index?
|
||||
if followingTab
|
||||
tabView.insertBefore(followingTab)
|
||||
else
|
||||
@append(tabView)
|
||||
|
||||
setActiveTabView: (tabView) ->
|
||||
removeTabForItem: (item) ->
|
||||
@tabForItem(item).remove()
|
||||
|
||||
getTabs: ->
|
||||
@children('.tab').toArray().map (elt) -> $(elt).view()
|
||||
|
||||
tabAtIndex: (index) ->
|
||||
@children(".tab:eq(#{index})").view()
|
||||
|
||||
tabForItem: (item) ->
|
||||
_.detect @getTabs(), (tab) -> tab.item is item
|
||||
|
||||
setActiveTab: (tabView) ->
|
||||
unless tabView.hasClass('active')
|
||||
@find(".tab.active").removeClass('active')
|
||||
tabView.addClass('active')
|
||||
|
||||
updateActiveTab: ->
|
||||
@setActiveTab(@tabForItem(@pane.activeItem))
|
||||
|
||||
removeTabAtIndex: (index) ->
|
||||
@find(".tab:eq(#{index})").remove()
|
||||
|
||||
|
||||
@@ -1,100 +1,44 @@
|
||||
$ = require 'jquery'
|
||||
SortableList = require 'sortable-list'
|
||||
Tab = require './tab'
|
||||
{View} = require 'space-pen'
|
||||
fs = require 'fs'
|
||||
|
||||
module.exports =
|
||||
class TabView extends SortableList
|
||||
@activate: ->
|
||||
rootView.eachEditor (editor) =>
|
||||
@prependToEditorPane(editor) if editor.attached
|
||||
|
||||
@prependToEditorPane: (editor) ->
|
||||
if pane = editor.pane()
|
||||
pane.prepend(new TabView(editor))
|
||||
|
||||
class TabView extends View
|
||||
@content: ->
|
||||
@ul class: "tabs #{@viewClass()}"
|
||||
@li class: 'tab sortable', =>
|
||||
@span class: 'title', outlet: 'title'
|
||||
@span class: 'close-icon'
|
||||
|
||||
initialize: (@editor) ->
|
||||
super
|
||||
initialize: (@item, @pane) ->
|
||||
@title.text(@item.getTitle())
|
||||
|
||||
@addTabForEditSession(editSession) for editSession in @editor.editSessions
|
||||
|
||||
@setActiveTab(@editor.getActiveEditSessionIndex())
|
||||
@editor.on 'editor:active-edit-session-changed', (e, editSession, index) => @setActiveTab(index)
|
||||
@editor.on 'editor:edit-session-added', (e, editSession) => @addTabForEditSession(editSession)
|
||||
@editor.on 'editor:edit-session-removed', (e, editSession, index) => @removeTabAtIndex(index)
|
||||
@editor.on 'editor:edit-session-order-changed', (e, editSession, fromIndex, toIndex) =>
|
||||
fromTab = @find(".tab:eq(#{fromIndex})")
|
||||
toTab = @find(".tab:eq(#{toIndex})")
|
||||
fromTab.detach()
|
||||
if fromIndex < toIndex
|
||||
fromTab.insertAfter(toTab)
|
||||
else
|
||||
fromTab.insertBefore(toTab)
|
||||
# @buffer = @editSession.buffer
|
||||
# @subscribe @buffer, 'path-changed', => @updateFileName()
|
||||
# @subscribe @buffer, 'contents-modified', => @updateModifiedStatus()
|
||||
# @subscribe @buffer, 'saved', => @updateModifiedStatus()
|
||||
# @subscribe @buffer, 'git-status-changed', => @updateModifiedStatus()
|
||||
# @subscribe @editor, 'editor:edit-session-added', => @updateFileName()
|
||||
# @subscribe @editor, 'editor:edit-session-removed', => @updateFileName()
|
||||
# @updateFileName()
|
||||
# @updateModifiedStatus()
|
||||
|
||||
@on 'click', '.tab', (e) =>
|
||||
@editor.setActiveEditSessionIndex($(e.target).closest('.tab').index())
|
||||
@editor.focus()
|
||||
|
||||
@on 'click', '.tab .close-icon', (e) =>
|
||||
index = $(e.target).closest('.tab').index()
|
||||
@editor.destroyEditSessionIndex(index)
|
||||
false
|
||||
|
||||
addTabForEditSession: (editSession) ->
|
||||
@append(new Tab(editSession, @editor))
|
||||
|
||||
setActiveTab: (index) ->
|
||||
@find(".tab.active").removeClass('active')
|
||||
@find(".tab:eq(#{index})").addClass('active')
|
||||
|
||||
removeTabAtIndex: (index) ->
|
||||
@find(".tab:eq(#{index})").remove()
|
||||
|
||||
containsEditSession: (editor, editSession) ->
|
||||
for session in editor.editSessions
|
||||
return true if editSession.getPath() is session.getPath()
|
||||
|
||||
shouldAllowDrag: (event) ->
|
||||
panes = rootView.find('.pane')
|
||||
!(panes.length == 1 && panes.find('.sortable').length == 1)
|
||||
|
||||
onDragStart: (event) =>
|
||||
super
|
||||
|
||||
pane = $(event.target).closest('.pane')
|
||||
paneIndex = rootView.indexOfPane(pane)
|
||||
event.originalEvent.dataTransfer.setData 'from-pane-index', paneIndex
|
||||
|
||||
onDrop: (event) =>
|
||||
super
|
||||
|
||||
droppedNearTab = @getSortableElement(event)
|
||||
transfer = event.originalEvent.dataTransfer
|
||||
previousDraggedTabIndex = transfer.getData 'sortable-index'
|
||||
|
||||
fromPaneIndex = ~~transfer.getData 'from-pane-index'
|
||||
toPaneIndex = rootView.indexOfPane($(event.target).closest('.pane'))
|
||||
fromPane = $(rootView.find('.pane')[fromPaneIndex])
|
||||
fromEditor = fromPane.find('.editor').view()
|
||||
draggedTab = fromPane.find(".#{TabView.viewClass()} .sortable:eq(#{previousDraggedTabIndex})")
|
||||
|
||||
if draggedTab.is(droppedNearTab)
|
||||
fromEditor.focus()
|
||||
return
|
||||
|
||||
if fromPaneIndex == toPaneIndex
|
||||
droppedNearTab = @getSortableElement(event)
|
||||
fromIndex = draggedTab.index()
|
||||
toIndex = droppedNearTab.index()
|
||||
toIndex++ if fromIndex > toIndex
|
||||
fromEditor.moveEditSessionToIndex(fromIndex, toIndex)
|
||||
fromEditor.focus()
|
||||
updateModifiedStatus: ->
|
||||
if @buffer.isModified()
|
||||
@toggleClass('file-modified') unless @isModified
|
||||
@isModified = true
|
||||
else
|
||||
toEditor = rootView.find(".pane:eq(#{toPaneIndex}) > .editor").view()
|
||||
if @containsEditSession(toEditor, fromEditor.editSessions[draggedTab.index()])
|
||||
fromEditor.focus()
|
||||
else
|
||||
fromEditor.moveEditSessionToEditor(draggedTab.index(), toEditor, droppedNearTab.index() + 1)
|
||||
toEditor.focus()
|
||||
@removeClass('file-modified') if @isModified
|
||||
@isModified = false
|
||||
|
||||
updateFileName: ->
|
||||
fileNameText = @editSession.buffer.getBaseName()
|
||||
if fileNameText?
|
||||
duplicates = @editor.getEditSessions().filter (session) -> fileNameText is session.buffer.getBaseName()
|
||||
if duplicates.length > 1
|
||||
directory = fs.base(fs.directory(@editSession.getPath()))
|
||||
fileNameText = "#{fileNameText} - #{directory}" if directory
|
||||
else
|
||||
fileNameText = 'untitled'
|
||||
|
||||
@fileName.text(fileNameText)
|
||||
@fileName.attr('title', @editSession.getPath())
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
{View} = require 'space-pen'
|
||||
fs = require 'fs'
|
||||
|
||||
module.exports =
|
||||
class Tab extends View
|
||||
@content: (editSession) ->
|
||||
@li class: 'tab sortable', =>
|
||||
@span class: 'file-name', outlet: 'fileName'
|
||||
@span class: 'close-icon'
|
||||
|
||||
initialize: (@editSession, @editor) ->
|
||||
@buffer = @editSession.buffer
|
||||
@subscribe @buffer, 'path-changed', => @updateFileName()
|
||||
@subscribe @buffer, 'contents-modified', => @updateModifiedStatus()
|
||||
@subscribe @buffer, 'saved', => @updateModifiedStatus()
|
||||
@subscribe @editor, 'editor:edit-session-added', => @updateFileName()
|
||||
@subscribe @editor, 'editor:edit-session-removed', => @updateFileName()
|
||||
@updateFileName()
|
||||
@updateModifiedStatus()
|
||||
|
||||
updateModifiedStatus: ->
|
||||
if @buffer.isModified()
|
||||
@toggleClass('file-modified') unless @isModified
|
||||
@isModified = true
|
||||
else
|
||||
@removeClass('file-modified') if @isModified
|
||||
@isModified = false
|
||||
|
||||
updateFileName: ->
|
||||
fileNameText = @editSession.buffer.getBaseName()
|
||||
if fileNameText?
|
||||
duplicates = @editor.getEditSessions().filter (session) -> fileNameText is session.buffer.getBaseName()
|
||||
if duplicates.length > 1
|
||||
directory = fs.base(fs.directory(@editSession.getPath()))
|
||||
fileNameText = "#{fileNameText} - #{directory}" if directory
|
||||
else
|
||||
fileNameText = 'untitled'
|
||||
|
||||
@fileName.text(fileNameText)
|
||||
@fileName.attr('title', @editSession.getPath())
|
||||
5
src/packages/tabs/lib/tabs.coffee
Normal file
5
src/packages/tabs/lib/tabs.coffee
Normal file
@@ -0,0 +1,5 @@
|
||||
TabBarView = require './tab-bar-view'
|
||||
|
||||
module.exports =
|
||||
activate: ->
|
||||
rootView.eachPane (pane) => new TabBarView(pane)
|
||||
@@ -1 +1 @@
|
||||
'main': 'lib/tab-view'
|
||||
'main': 'lib/tabs'
|
||||
|
||||
@@ -1,93 +1,99 @@
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
RootView = require 'root-view'
|
||||
Pane = require 'pane'
|
||||
PaneContainer = require 'pane-container'
|
||||
TabBarView = require 'tabs/lib/tab-bar-view'
|
||||
fs = require 'fs'
|
||||
{View} = require 'space-pen'
|
||||
|
||||
describe "TabView", ->
|
||||
[editor, buffer, tabs] = []
|
||||
|
||||
describe "Tabs package main", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
rootView.open('sample.txt')
|
||||
rootView.simulateDomAttachment()
|
||||
window.loadPackage("tabs")
|
||||
editor = rootView.getActiveEditor()
|
||||
tabs = rootView.find('.tabs').view()
|
||||
|
||||
describe "@activate", ->
|
||||
it "appends a status bear to all existing and new editors", ->
|
||||
describe ".activate()", ->
|
||||
it "appends a tab bar all existing and new panes", ->
|
||||
expect(rootView.panes.find('.pane').length).toBe 1
|
||||
expect(rootView.panes.find('.pane > .tabs').length).toBe 1
|
||||
editor.splitRight()
|
||||
rootView.getActivePane().splitRight()
|
||||
expect(rootView.find('.pane').length).toBe 2
|
||||
expect(rootView.panes.find('.pane > .tabs').length).toBe 2
|
||||
|
||||
describe ".initialize()", ->
|
||||
it "creates a tab for each edit session on the editor to which the tab-strip belongs", ->
|
||||
expect(editor.editSessions.length).toBe 2
|
||||
expect(tabs.find('.tab').length).toBe 2
|
||||
fdescribe "TabBarView", ->
|
||||
[item1, item2, editSession1, editSession2, pane, tabBar] = []
|
||||
|
||||
expect(tabs.find('.tab:eq(0) .file-name').text()).toBe editor.editSessions[0].buffer.getBaseName()
|
||||
expect(tabs.find('.tab:eq(1) .file-name').text()).toBe editor.editSessions[1].buffer.getBaseName()
|
||||
class TestView extends View
|
||||
@content: (title) -> @div title
|
||||
initialize: (@title) ->
|
||||
getTitle: -> @title
|
||||
|
||||
it "highlights the tab for the current active edit session", ->
|
||||
expect(editor.getActiveEditSessionIndex()).toBe 1
|
||||
expect(tabs.find('.tab:eq(1)')).toHaveClass 'active'
|
||||
beforeEach ->
|
||||
item1 = new TestView('Item 1')
|
||||
item2 = new TestView('Item 2')
|
||||
editSession1 = project.buildEditSession('sample.js')
|
||||
paneContainer = new PaneContainer
|
||||
pane = new Pane(item1, editSession1, item2)
|
||||
pane.showItem(item2)
|
||||
paneContainer.append(pane)
|
||||
tabBar = new TabBarView(pane)
|
||||
|
||||
it "sets the title on each tab to be the full path of the edit session", ->
|
||||
expect(tabs.find('.tab:eq(0) .file-name').attr('title')).toBe editor.editSessions[0].getPath()
|
||||
expect(tabs.find('.tab:eq(1) .file-name').attr('title')).toBe editor.editSessions[1].getPath()
|
||||
describe ".initialize(pane)", ->
|
||||
it "creates a tab for each item on the tab bar's parent pane", ->
|
||||
expect(pane.getItems().length).toBe 3
|
||||
expect(tabBar.find('.tab').length).toBe 3
|
||||
|
||||
describe "when the active edit session changes", ->
|
||||
it "highlights the tab for the newly-active edit session", ->
|
||||
editor.setActiveEditSessionIndex(0)
|
||||
expect(tabs.find('.active').length).toBe 1
|
||||
expect(tabs.find('.tab:eq(0)')).toHaveClass 'active'
|
||||
expect(tabBar.find('.tab:eq(0) .title').text()).toBe item1.getTitle()
|
||||
expect(tabBar.find('.tab:eq(1) .title').text()).toBe editSession1.getTitle()
|
||||
expect(tabBar.find('.tab:eq(2) .title').text()).toBe item2.getTitle()
|
||||
|
||||
editor.setActiveEditSessionIndex(1)
|
||||
expect(tabs.find('.active').length).toBe 1
|
||||
expect(tabs.find('.tab:eq(1)')).toHaveClass 'active'
|
||||
it "highlights the tab for the active pane item", ->
|
||||
expect(tabBar.find('.tab:eq(2)')).toHaveClass 'active'
|
||||
|
||||
describe "when a new edit session is created", ->
|
||||
it "adds a tab for the new edit session", ->
|
||||
rootView.open('two-hundred.txt')
|
||||
expect(tabs.find('.tab').length).toBe 3
|
||||
expect(tabs.find('.tab:eq(2) .file-name').text()).toBe 'two-hundred.txt'
|
||||
describe "when the active pane item changes", ->
|
||||
it "highlights the tab for the new active pane item", ->
|
||||
pane.showItem(item1)
|
||||
expect(tabBar.find('.active').length).toBe 1
|
||||
expect(tabBar.find('.tab:eq(0)')).toHaveClass 'active'
|
||||
|
||||
describe "when the edit session's buffer has an undefined path", ->
|
||||
it "makes the tab text 'untitled'", ->
|
||||
rootView.open()
|
||||
expect(tabs.find('.tab').length).toBe 3
|
||||
expect(tabs.find('.tab:eq(2) .file-name').text()).toBe 'untitled'
|
||||
pane.showItem(item2)
|
||||
expect(tabBar.find('.active').length).toBe 1
|
||||
expect(tabBar.find('.tab:eq(2)')).toHaveClass 'active'
|
||||
|
||||
it "removes the tab's title", ->
|
||||
rootView.open()
|
||||
expect(tabs.find('.tab').length).toBe 3
|
||||
expect(tabs.find('.tab:eq(2) .file-name').attr('title')).toBeUndefined()
|
||||
describe "when a new item is added to the pane", ->
|
||||
ffit "adds a tab for the new item at the same index as the item in the pane", ->
|
||||
pane.showItem(item1)
|
||||
item3 = new TestView('Item 3')
|
||||
pane.showItem(item3)
|
||||
expect(tabBar.find('.tab').length).toBe 4
|
||||
expect(tabBar.tabAtIndex(1).find('.title')).toHaveText 'Item 3'
|
||||
|
||||
describe "when an edit session is removed", ->
|
||||
it "removes the tab for the removed edit session", ->
|
||||
editor.setActiveEditSessionIndex(0)
|
||||
editor.destroyActiveEditSession()
|
||||
expect(tabs.find('.tab').length).toBe 1
|
||||
expect(tabs.find('.tab:eq(0) .file-name').text()).toBe 'sample.txt'
|
||||
describe "when an item is removed from the pane", ->
|
||||
it "removes the item's tab from the tab bar", ->
|
||||
pane.removeItem(item2)
|
||||
expect(tabBar.getTabs().length).toBe 2
|
||||
expect(tabBar.find('.tab:contains(Item 2)')).not.toExist()
|
||||
|
||||
describe "when a tab is clicked", ->
|
||||
it "activates the associated edit session", ->
|
||||
expect(editor.getActiveEditSessionIndex()).toBe 1
|
||||
tabs.find('.tab:eq(0)').click()
|
||||
expect(editor.getActiveEditSessionIndex()).toBe 0
|
||||
tabs.find('.tab:eq(1)').click()
|
||||
expect(editor.getActiveEditSessionIndex()).toBe 1
|
||||
it "shows the associated item on the pane and focuses the pane", ->
|
||||
spyOn(pane, 'focus')
|
||||
|
||||
it "focuses the associated editor", ->
|
||||
rootView.attachToDom()
|
||||
expect(editor).toMatchSelector ":has(:focus)"
|
||||
editor.splitRight()
|
||||
expect(editor).not.toMatchSelector ":has(:focus)"
|
||||
tabs.find('.tab:eq(0)').click()
|
||||
expect(editor).toMatchSelector ":has(:focus)"
|
||||
tabBar.tabAtIndex(0).click()
|
||||
expect(pane.activeItem).toBe pane.getItems()[0]
|
||||
|
||||
tabBar.tabAtIndex(2).click()
|
||||
expect(pane.activeItem).toBe pane.getItems()[2]
|
||||
|
||||
expect(pane.focus.callCount).toBe 2
|
||||
|
||||
describe "when a tab's close icon is clicked", ->
|
||||
it "removes the tab's item from the pane", ->
|
||||
tabBar.tabForItem(item1).find('.close-icon').click()
|
||||
expect(pane.getItems().length).toBe 2
|
||||
expect(pane.getItems().indexOf(item1)).toBe -1
|
||||
expect(tabBar.getTabs().length).toBe 2
|
||||
expect(tabBar.find('.tab:contains(Item 1)')).not.toExist()
|
||||
|
||||
describe "when a file name associated with a tab changes", ->
|
||||
[buffer, oldPath, newPath] = []
|
||||
@@ -110,21 +116,6 @@ describe "TabView", ->
|
||||
waitsFor "file to be renamed", ->
|
||||
tabFileName.text() == "renamed-file.txt"
|
||||
|
||||
describe "when the close icon is clicked", ->
|
||||
it "closes the selected non-active edit session", ->
|
||||
activeSession = editor.activeEditSession
|
||||
expect(editor.getActiveEditSessionIndex()).toBe 1
|
||||
tabs.find('.tab .close-icon:eq(0)').click()
|
||||
expect(editor.getActiveEditSessionIndex()).toBe 0
|
||||
expect(editor.activeEditSession).toBe activeSession
|
||||
|
||||
it "closes the selected active edit session", ->
|
||||
firstSession = editor.getEditSessions()[0]
|
||||
expect(editor.getActiveEditSessionIndex()).toBe 1
|
||||
tabs.find('.tab .close-icon:eq(1)').click()
|
||||
expect(editor.getActiveEditSessionIndex()).toBe 0
|
||||
expect(editor.activeEditSession).toBe firstSession
|
||||
|
||||
describe "when two tabs have the same file name", ->
|
||||
[tempPath] = []
|
||||
|
||||
|
||||
Reference in New Issue
Block a user