mirror of
https://github.com/atom/atom.git
synced 2026-01-23 05:48:10 -05:00
TreeView directories can be selected by clicking them. Start on keyboard nav.
This commit is contained in:
@@ -15,8 +15,8 @@ describe "TreeView", ->
|
||||
|
||||
describe ".initialize(project)", ->
|
||||
it "renders the root of the project and its contents alphabetically with subdirectories first in a collapsed state", ->
|
||||
expect(rootDirectoryView.find('> .disclosure-arrow')).toHaveText('▾')
|
||||
expect(rootDirectoryView.find('> .name')).toHaveText('fixtures/')
|
||||
expect(rootDirectoryView.find('> .header .disclosure-arrow')).toHaveText('▾')
|
||||
expect(rootDirectoryView.find('> .header .name')).toHaveText('fixtures/')
|
||||
|
||||
rootEntries = rootDirectoryView.find('.entries')
|
||||
subdir1 = rootEntries.find('> li:eq(0)')
|
||||
@@ -34,27 +34,26 @@ describe "TreeView", ->
|
||||
|
||||
describe "when a directory's disclosure arrow is clicked", ->
|
||||
it "expands / collapses the associated directory", ->
|
||||
subdir = rootDirectoryView.find('.entries > li:contains(dir/)')
|
||||
subdir = rootDirectoryView.find('.entries > li:contains(dir/)').view()
|
||||
|
||||
disclosureArrow = subdir.find('.disclosure-arrow')
|
||||
expect(disclosureArrow).toHaveText('▸')
|
||||
expect(subdir.disclosureArrow).toHaveText('▸')
|
||||
expect(subdir.find('.entries')).not.toExist()
|
||||
|
||||
disclosureArrow.click()
|
||||
subdir.disclosureArrow.click()
|
||||
|
||||
expect(disclosureArrow).toHaveText('▾')
|
||||
expect(subdir.disclosureArrow).toHaveText('▾')
|
||||
expect(subdir.find('.entries')).toExist()
|
||||
|
||||
disclosureArrow.click()
|
||||
expect(disclosureArrow).toHaveText('▸')
|
||||
subdir.disclosureArrow.click()
|
||||
expect(subdir.disclosureArrow).toHaveText('▸')
|
||||
expect(subdir.find('.entries')).not.toExist()
|
||||
|
||||
it "restores the expansion state of descendant directories", ->
|
||||
child = rootDirectoryView.find('.entries > li:contains(dir/)')
|
||||
child.find('> .disclosure-arrow').click()
|
||||
child = rootDirectoryView.find('.entries > li:contains(dir/)').view()
|
||||
child.disclosureArrow.click()
|
||||
|
||||
grandchild = child.find('.entries > li:contains(a-dir/)')
|
||||
grandchild.find('> .disclosure-arrow').click()
|
||||
grandchild = child.find('.entries > li:contains(a-dir/)').view()
|
||||
grandchild.disclosureArrow.click()
|
||||
|
||||
rootDirectoryView.find('> .disclosure-arrow').click()
|
||||
rootDirectoryView.find('> .disclosure-arrow').click()
|
||||
@@ -84,6 +83,12 @@ describe "TreeView", ->
|
||||
expect(treeView.find('.selected').length).toBe 1
|
||||
expect(rootView.activeEditor().buffer.path).toBe require.resolve('fixtures/sample.txt')
|
||||
|
||||
describe "when a directory is clicked", ->
|
||||
it "is selected", ->
|
||||
subdir = rootDirectoryView.find('.directory:first').view()
|
||||
subdir.click()
|
||||
expect(subdir).toHaveClass 'selected'
|
||||
|
||||
describe "when a new file is opened in the active editor", ->
|
||||
it "is selected in the tree view if visible", ->
|
||||
sampleJs.click()
|
||||
@@ -102,3 +107,28 @@ describe "TreeView", ->
|
||||
expect(sampleTxt).toHaveClass('selected')
|
||||
leftEditor.focus()
|
||||
expect(sampleJs).toHaveClass('selected')
|
||||
|
||||
describe "keyboard navigation", ->
|
||||
afterEach ->
|
||||
expect(treeView.find('.selected').length).toBeLessThan 2
|
||||
|
||||
describe "move-down", ->
|
||||
describe "if nothing is selected", ->
|
||||
it "selects the first entry", ->
|
||||
treeView.trigger 'move-down'
|
||||
expect(rootDirectoryView).toHaveClass 'selected'
|
||||
|
||||
describe "if a collapsed directory is selected", ->
|
||||
it "skips to the next directory", ->
|
||||
rootDirectoryView.find('.directory:eq(0)').click()
|
||||
treeView.trigger 'move-down'
|
||||
expect(rootDirectoryView.find('.directory:eq(1)')).toHaveClass 'selected'
|
||||
|
||||
describe "if an expanded directory is selected", ->
|
||||
it "selects the first entry of the directory", ->
|
||||
|
||||
describe "if the last entry of an expanded directory is selected", ->
|
||||
it "selects the entry after its parent directory", ->
|
||||
|
||||
describe "if the last entry of the last directory is selected", ->
|
||||
it "does not change the selection", ->
|
||||
|
||||
@@ -13,26 +13,41 @@ class TreeView extends View
|
||||
@subview 'root', new DirectoryView(directory: rootView.project.getRootDirectory(), isExpanded: true)
|
||||
|
||||
initialize: (@rootView) ->
|
||||
@on 'click', '.file', (e) =>
|
||||
clickedLi = $(e.target)
|
||||
@rootView.open(clickedLi.attr('path'))
|
||||
@find('.selected').removeClass('selected')
|
||||
clickedLi.addClass('selected')
|
||||
@on 'click', '.entry', (e) =>
|
||||
entry = $(e.currentTarget)
|
||||
@rootView.open(entry.attr('path')) if entry.is('.file')
|
||||
@selectEntry(entry)
|
||||
false
|
||||
|
||||
@on 'move-down', => @moveDown()
|
||||
@on 'tree-view:expand-directory', => @selectActiveFile()
|
||||
@rootView.on 'active-editor-path-change', => @selectActiveFile()
|
||||
|
||||
selectActiveFile: ->
|
||||
console.log ""
|
||||
@find('.selected').removeClass('selected')
|
||||
activeFilePath = @rootView.activeEditor()?.buffer.path
|
||||
@find(".file[path='#{activeFilePath}']").addClass('selected')
|
||||
@selectEntry(@find(".file[path='#{activeFilePath}']"))
|
||||
|
||||
moveDown: ->
|
||||
selectedEntry = @selectedEntry()
|
||||
|
||||
if selectedEntry.length
|
||||
@selectEntry(selectedEntry.next())
|
||||
else
|
||||
@selectEntry(@root)
|
||||
|
||||
selectedEntry: ->
|
||||
@find('.selected')
|
||||
|
||||
selectEntry: (entry) ->
|
||||
@find('.selected').removeClass('selected')
|
||||
entry.addClass('selected')
|
||||
|
||||
class DirectoryView extends View
|
||||
@content: ({directory, isExpanded}) ->
|
||||
@li class: 'directory', =>
|
||||
@span '▸', class: 'disclosure-arrow', outlet: 'disclosureArrow', click: 'toggleExpansion'
|
||||
@span directory.getName(), class: 'name'
|
||||
@li class: 'directory entry', =>
|
||||
@div class: 'header', =>
|
||||
@span '▸', class: 'disclosure-arrow', outlet: 'disclosureArrow', click: 'toggleExpansion'
|
||||
@span directory.getName(), class: 'name'
|
||||
|
||||
entries: null
|
||||
|
||||
@@ -45,7 +60,7 @@ class DirectoryView extends View
|
||||
if entry instanceof Directory
|
||||
@entries.append(new DirectoryView(directory: entry, isExpanded: false))
|
||||
else
|
||||
@entries.append $$ -> @li entry.getName(), class: 'file', path: entry.path
|
||||
@entries.append $$ -> @li entry.getName(), class: 'file entry', path: entry.path
|
||||
@append(@entries)
|
||||
|
||||
toggleExpansion: ->
|
||||
@@ -59,6 +74,7 @@ class DirectoryView extends View
|
||||
@deserializeEntries(@entryStates) if @entryStates?
|
||||
@isExpanded = true
|
||||
@trigger 'tree-view:expand-directory'
|
||||
false
|
||||
|
||||
collapse: ->
|
||||
@entryStates = @serializeEntries()
|
||||
@@ -77,7 +93,7 @@ class DirectoryView extends View
|
||||
|
||||
deserializeEntries: (entryStates) ->
|
||||
for directoryName, childEntryStates of entryStates
|
||||
@entries.find("> .directory:contains(#{directoryName})").each ->
|
||||
@entries.find("> .directory:contains('#{directoryName}')").each ->
|
||||
view = $(this).view()
|
||||
view.entryStates = childEntryStates
|
||||
view.expand()
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
padding-left: 2ex;
|
||||
}
|
||||
|
||||
.tree-view .directory .selected {
|
||||
.tree-view .file.selected, .tree-view .directory.selected > .header {
|
||||
background: #333;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user