mirror of
https://github.com/atom/atom.git
synced 2026-02-08 05:35:04 -05:00
130 lines
4.0 KiB
CoffeeScript
130 lines
4.0 KiB
CoffeeScript
{View, $$} = require 'space-pen'
|
|
Directory = require 'directory'
|
|
$ = require 'jquery'
|
|
|
|
module.exports =
|
|
class TreeView extends View
|
|
@activate: (rootView) ->
|
|
requireStylesheet 'tree-view.css'
|
|
rootView.prepend(new TreeView(rootView))
|
|
|
|
@content: (rootView) ->
|
|
@div class: 'tree-view', tabindex: -1, =>
|
|
@subview 'root', new DirectoryView(directory: rootView.project.getRootDirectory(), isExpanded: true)
|
|
|
|
initialize: (@rootView) ->
|
|
@on 'click', '.entry', (e) =>
|
|
entry = $(e.currentTarget)
|
|
@selectEntry(entry)
|
|
@openSelectedEntry() if entry.is('.file')
|
|
false
|
|
|
|
@on 'move-up', => @moveUp()
|
|
@on 'move-down', => @moveDown()
|
|
@on 'tree-view:expand-directory', => @expandDirectory()
|
|
@on 'tree-view:collapse-directory', => @collapseDirectory()
|
|
@on 'tree-view:open-selected-entry', => @openSelectedEntry()
|
|
@rootView.on 'active-editor-path-change', => @selectActiveFile()
|
|
|
|
selectActiveFile: ->
|
|
activeFilePath = @rootView.activeEditor()?.buffer.path
|
|
@selectEntry(@find(".file[path='#{activeFilePath}']"))
|
|
|
|
moveDown: ->
|
|
selectedEntry = @selectedEntry()
|
|
if selectedEntry[0]
|
|
if selectedEntry.is('.expanded.directory')
|
|
return if @selectEntry(selectedEntry.find('.entry:first'))
|
|
return if @selectEntry(selectedEntry.next())
|
|
return if @selectEntry(selectedEntry.closest('.directory').next())
|
|
else
|
|
@selectEntry(@root)
|
|
|
|
moveUp: ->
|
|
selectedEntry = @selectedEntry()
|
|
if selectedEntry[0]
|
|
return if @selectEntry(selectedEntry.prev())
|
|
return if @selectEntry(selectedEntry.parents('.directory').first())
|
|
else
|
|
@selectEntry(@find('.entry').last())
|
|
|
|
expandDirectory: ->
|
|
selectedEntry = @selectedEntry()
|
|
selectedEntry.view().expand() if selectedEntry.is('.directory')
|
|
|
|
collapseDirectory: ->
|
|
selectedEntry = @selectedEntry()
|
|
directory = selectedEntry.closest('.expanded.directory').view()
|
|
directory.collapse()
|
|
@selectEntry(directory)
|
|
|
|
openSelectedEntry: ->
|
|
selectedEntry = @selectedEntry()
|
|
if selectedEntry.is('.directory')
|
|
selectedEntry.view().toggleExpansion()
|
|
else if selectedEntry.is('.file')
|
|
@rootView.open(selectedEntry.attr('path'))
|
|
|
|
selectedEntry: ->
|
|
@find('.selected')
|
|
|
|
selectEntry: (entry) ->
|
|
return false unless entry[0]
|
|
@find('.selected').removeClass('selected')
|
|
entry.addClass('selected')
|
|
|
|
class DirectoryView extends View
|
|
@content: ({directory, isExpanded}) ->
|
|
@li class: 'directory entry', =>
|
|
@div class: 'header', =>
|
|
@span '▸', class: 'disclosure-arrow', outlet: 'disclosureArrow', click: 'toggleExpansion'
|
|
@span directory.getName(), class: 'name'
|
|
|
|
entries: null
|
|
|
|
initialize: ({@directory, isExpanded}) ->
|
|
@expand() if isExpanded
|
|
|
|
buildEntries: ->
|
|
@entries = $$ -> @ol class: 'entries'
|
|
for entry in @directory.getEntries()
|
|
if entry instanceof Directory
|
|
@entries.append(new DirectoryView(directory: entry, isExpanded: false))
|
|
else
|
|
@entries.append $$ -> @li entry.getName(), class: 'file entry', path: entry.path
|
|
@append(@entries)
|
|
|
|
toggleExpansion: ->
|
|
if @isExpanded then @collapse() else @expand()
|
|
|
|
expand: ->
|
|
return if @isExpanded
|
|
@addClass('expanded')
|
|
@disclosureArrow.text('▾')
|
|
@buildEntries()
|
|
@deserializeEntries(@entryStates) if @entryStates?
|
|
@isExpanded = true
|
|
false
|
|
|
|
collapse: ->
|
|
@entryStates = @serializeEntries()
|
|
@removeClass('expanded')
|
|
@disclosureArrow.text('▸')
|
|
@entries.remove()
|
|
@entries = null
|
|
@isExpanded = false
|
|
|
|
serializeEntries: ->
|
|
entryStates = {}
|
|
@entries.find('> .directory.expanded').each ->
|
|
view = $(this).view()
|
|
entryStates[view.directory.getName()] = view.serializeEntries()
|
|
entryStates
|
|
|
|
deserializeEntries: (entryStates) ->
|
|
for directoryName, childEntryStates of entryStates
|
|
@entries.find("> .directory:contains('#{directoryName}')").each ->
|
|
view = $(this).view()
|
|
view.entryStates = childEntryStates
|
|
view.expand()
|