mirror of
https://github.com/atom/atom.git
synced 2026-02-06 20:55:33 -05:00
97
src/packages/tabs/lib/tab-view.coffee
Normal file
97
src/packages/tabs/lib/tab-view.coffee
Normal file
@@ -0,0 +1,97 @@
|
||||
$ = require 'jquery'
|
||||
SortableList = require 'sortable-list'
|
||||
Tab = require './tab'
|
||||
|
||||
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))
|
||||
|
||||
@content: ->
|
||||
@ul class: "tabs #{@viewClass()}"
|
||||
|
||||
initialize: (@editor) ->
|
||||
super
|
||||
|
||||
@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)
|
||||
|
||||
@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})")
|
||||
return if draggedTab.is(droppedNearTab)
|
||||
|
||||
if fromPaneIndex == toPaneIndex
|
||||
droppedNearTab = @getSortableElement(event)
|
||||
fromIndex = draggedTab.index()
|
||||
toIndex = droppedNearTab.index()
|
||||
toIndex++ if fromIndex > toIndex
|
||||
fromEditor.moveEditSessionToIndex(fromIndex, toIndex)
|
||||
fromEditor.focus()
|
||||
else
|
||||
toPane = $(rootView.find('.pane')[toPaneIndex])
|
||||
toEditor = toPane.find('.editor').view()
|
||||
|
||||
unless @containsEditSession(toEditor, fromEditor.editSessions[draggedTab.index()])
|
||||
fromEditor.moveEditSessionToEditor(draggedTab.index(), toEditor, droppedNearTab.index() + 1)
|
||||
toEditor.focus()
|
||||
@@ -4,7 +4,7 @@ fs = require 'fs'
|
||||
module.exports =
|
||||
class Tab extends View
|
||||
@content: (editSession) ->
|
||||
@li class: 'tab', =>
|
||||
@li class: 'tab sortable', =>
|
||||
@span class: 'file-name', outlet: 'fileName'
|
||||
@span class: 'close-icon'
|
||||
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
$ = require 'jquery'
|
||||
{View} = require 'space-pen'
|
||||
Tab = require './tab'
|
||||
|
||||
module.exports =
|
||||
class Tabs extends View
|
||||
@activate: ->
|
||||
rootView.eachEditor (editor) =>
|
||||
@prependToEditorPane(rootView, editor) if editor.attached
|
||||
|
||||
@prependToEditorPane: (rootView, editor) ->
|
||||
if pane = editor.pane()
|
||||
pane.prepend(new Tabs(editor))
|
||||
|
||||
@content: ->
|
||||
@ul class: 'tabs'
|
||||
|
||||
initialize: (@editor) ->
|
||||
for editSession, index in @editor.editSessions
|
||||
@addTabForEditSession(editSession)
|
||||
|
||||
@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)
|
||||
|
||||
@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()
|
||||
@@ -1 +1 @@
|
||||
'main': 'lib/tabs-view'
|
||||
'main': 'lib/tab-view'
|
||||
|
||||
@@ -3,11 +3,11 @@ _ = require 'underscore'
|
||||
RootView = require 'root-view'
|
||||
fs = require 'fs'
|
||||
|
||||
describe "Tabs", ->
|
||||
describe "TabView", ->
|
||||
[editor, buffer, tabs] = []
|
||||
|
||||
beforeEach ->
|
||||
rootView = new RootView(require.resolve('fixtures/sample.js'))
|
||||
new RootView(require.resolve('fixtures/sample.js'))
|
||||
rootView.open('sample.txt')
|
||||
rootView.simulateDomAttachment()
|
||||
atom.loadPackage("tabs")
|
||||
@@ -144,3 +144,68 @@ describe "Tabs", ->
|
||||
expect(tabs.find('.tab:last .file-name').text()).toBe 'sample.js - tmp'
|
||||
editor.destroyActiveEditSession()
|
||||
expect(tabs.find('.tab:eq(0) .file-name').text()).toBe 'sample.js'
|
||||
|
||||
describe "when an editor:edit-session-order-changed event is triggered", ->
|
||||
it "updates the order of the tabs to match the new edit session order", ->
|
||||
expect(tabs.find('.tab:eq(0) .file-name').text()).toBe "sample.js"
|
||||
expect(tabs.find('.tab:eq(1) .file-name').text()).toBe "sample.txt"
|
||||
|
||||
editor.moveEditSessionToIndex(0, 1)
|
||||
expect(tabs.find('.tab:eq(0) .file-name').text()).toBe "sample.txt"
|
||||
expect(tabs.find('.tab:eq(1) .file-name').text()).toBe "sample.js"
|
||||
|
||||
editor.moveEditSessionToIndex(1, 0)
|
||||
expect(tabs.find('.tab:eq(0) .file-name').text()).toBe "sample.js"
|
||||
expect(tabs.find('.tab:eq(1) .file-name').text()).toBe "sample.txt"
|
||||
|
||||
describe "dragging and dropping tabs", ->
|
||||
describe "when a tab is dragged from and dropped onto the same editor", ->
|
||||
it "moves the edit session, updates the order of the tabs, and focuses the editor", ->
|
||||
expect(tabs.find('.tab:eq(0) .file-name').text()).toBe "sample.js"
|
||||
expect(tabs.find('.tab:eq(1) .file-name').text()).toBe "sample.txt"
|
||||
|
||||
sortableElement = [tabs.find('.tab:eq(0)')]
|
||||
spyOn(tabs, 'getSortableElement').andCallFake -> sortableElement[0]
|
||||
event = $.Event()
|
||||
event.target = tabs[0]
|
||||
event.originalEvent =
|
||||
dataTransfer:
|
||||
data: {}
|
||||
setData: (key, value) -> @data[key] = value
|
||||
getData: (key) -> @data[key]
|
||||
|
||||
editor.hiddenInput.focusout()
|
||||
tabs.onDragStart(event)
|
||||
sortableElement = [tabs.find('.tab:eq(1)')]
|
||||
tabs.onDrop(event)
|
||||
|
||||
expect(tabs.find('.tab:eq(0) .file-name').text()).toBe "sample.txt"
|
||||
expect(tabs.find('.tab:eq(1) .file-name').text()).toBe "sample.js"
|
||||
expect(editor.isFocused).toBeTruthy()
|
||||
|
||||
describe "when a tab is dragged from one editor and dropped onto another editor", ->
|
||||
it "moves the edit session, updates the order of the tabs, and focuses the destination editor", ->
|
||||
leftTabs = tabs
|
||||
rightEditor = editor.splitRight()
|
||||
rightTabs = rootView.find('.tabs:last').view()
|
||||
|
||||
sortableElement = [leftTabs.find('.tab:eq(0)')]
|
||||
spyOn(tabs, 'getSortableElement').andCallFake -> sortableElement[0]
|
||||
event = $.Event()
|
||||
event.target = leftTabs
|
||||
event.originalEvent =
|
||||
dataTransfer:
|
||||
data: {}
|
||||
setData: (key, value) -> @data[key] = value
|
||||
getData: (key) -> @data[key]
|
||||
|
||||
rightEditor.hiddenInput.focusout()
|
||||
tabs.onDragStart(event)
|
||||
|
||||
event.target = rightTabs
|
||||
sortableElement = [rightTabs.find('.tab:eq(0)')]
|
||||
tabs.onDrop(event)
|
||||
|
||||
expect(rightTabs.find('.tab:eq(0) .file-name').text()).toBe "sample.txt"
|
||||
expect(rightTabs.find('.tab:eq(1) .file-name').text()).toBe "sample.js"
|
||||
expect(rightEditor.isFocused).toBeTruthy()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
'#root-view':
|
||||
'body':
|
||||
'meta-\\': 'tree-view:toggle'
|
||||
'meta-|': 'tree-view:reveal-active-file'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user