mirror of
https://github.com/atom/atom.git
synced 2026-01-24 06:18:03 -05:00
project pane works. I call it Tree now though. Probably too generic, whatevs"
This commit is contained in:
@@ -1 +0,0 @@
|
||||
module.exports = Project = require 'project/project'
|
||||
@@ -1,45 +0,0 @@
|
||||
_ = require 'underscore'
|
||||
|
||||
File = require 'fs'
|
||||
Extension = require 'extension'
|
||||
ProjectPane = require 'project/projectpane'
|
||||
|
||||
module.exports =
|
||||
class Project extends Extension
|
||||
keymap: ->
|
||||
'Command-Ctrl-N': -> @pane.toggle()
|
||||
|
||||
storageNamespace: ->
|
||||
@.constructor.name + @window.path
|
||||
|
||||
constructor: (args...) ->
|
||||
super args...
|
||||
|
||||
@pane = new ProjectPane @window, @
|
||||
@pane.toggle()
|
||||
|
||||
@window.on 'open', ({filename}) =>
|
||||
if File.isDirectory filename
|
||||
@pane.reload filename # I don't think this can ever happen.
|
||||
else
|
||||
openedPaths = @get 'openedPaths', []
|
||||
if not _.include openedPaths, filename
|
||||
openedPaths.push filename
|
||||
@set 'openedPaths', openedPaths
|
||||
|
||||
@window.on 'close', ({filename}) =>
|
||||
if File.isFile filename
|
||||
openedPaths = @get 'openedPaths', []
|
||||
openedPaths = _.without openedPaths, filename
|
||||
@set 'openedPaths', openedPaths
|
||||
|
||||
load: ->
|
||||
# Reopen files (remove ones that no longer exist)
|
||||
openedPaths = @get 'openedPaths', []
|
||||
for path in openedPaths
|
||||
if File.isFile path
|
||||
@window.open path
|
||||
else if not File.exists path
|
||||
openedPaths = _.without openedPaths, path
|
||||
@set 'openedPaths', openedPaths
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
|
||||
File = require 'fs'
|
||||
Pane = require 'pane'
|
||||
|
||||
module.exports =
|
||||
class ProjectPane extends Pane
|
||||
position: 'left'
|
||||
|
||||
project: null
|
||||
|
||||
html: $ require "project/project.html"
|
||||
|
||||
constructor: (@window, @project) ->
|
||||
super @window
|
||||
|
||||
@reload()
|
||||
|
||||
$('#project li').live 'click', (event) =>
|
||||
return true if event.__projectClicked__
|
||||
|
||||
$('#project .active').removeClass 'active'
|
||||
el = $(event.currentTarget)
|
||||
path = decodeURIComponent el.attr 'path'
|
||||
if File.isDirectory path
|
||||
openedPaths = @project.get 'openedPaths', []
|
||||
if el.hasClass 'open'
|
||||
openedPaths = _.without openedPaths, path
|
||||
el.removeClass 'open'
|
||||
el.children("ul").remove()
|
||||
else
|
||||
openedPaths.push path unless _.include openedPaths, path
|
||||
el.addClass 'open'
|
||||
list = @createList path
|
||||
el.append list
|
||||
|
||||
@project.set 'openedPaths', openedPaths
|
||||
else
|
||||
el.addClass 'active'
|
||||
@window.open path
|
||||
|
||||
# HACK I need the event to propogate beyond the project pane,
|
||||
# but I need the project pane to ignore it. Need somehting
|
||||
# cleaner here.
|
||||
event.__projectClicked__ = true
|
||||
|
||||
true
|
||||
|
||||
reload: ->
|
||||
@html.children('#project .cwd').text _.last @window.path.split '/'
|
||||
fileList = @createList @window.path
|
||||
fileList.addClass('files')
|
||||
@html.children('#project .files').replaceWith(fileList)
|
||||
|
||||
createList: (root) ->
|
||||
paths = File.list root
|
||||
|
||||
list = $('<ul>')
|
||||
for path in paths
|
||||
filename = path.replace(root, "").substring 1
|
||||
type = if File.isDirectory path then 'dir' else 'file'
|
||||
encodedPath = encodeURIComponent path
|
||||
listItem = $("<li class='#{type}' path='#{encodedPath}'>#{filename}</li>")
|
||||
openedPaths = @project.get 'openedPaths', []
|
||||
if _.include(openedPaths, path) and type == 'dir'
|
||||
listItem.append @createList path
|
||||
listItem.addClass "open"
|
||||
list.append listItem
|
||||
|
||||
list
|
||||
@@ -3,7 +3,7 @@ $ = require 'jquery'
|
||||
Extension = require 'extension'
|
||||
KeyBinder = require 'key-binder'
|
||||
Event = require 'event'
|
||||
TabsPane = require 'tabs/tabspane'
|
||||
TabsPane = require 'tabs/tabs-pane'
|
||||
|
||||
fs = require 'fs'
|
||||
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
|
||||
Pane = require 'pane'
|
||||
|
||||
module.exports =
|
||||
class TabsPane extends Pane
|
||||
position: 'top'
|
||||
|
||||
html: $ require 'tabs/tabs.html'
|
||||
|
||||
constructor: ->
|
||||
# Style html
|
||||
@html.parents('.pane').css height: 'inherit'
|
||||
css = $('<style id="tabs-style"></style>').html require 'tabs/tabs.css'
|
||||
$('head').append css
|
||||
|
||||
# click tab
|
||||
tabPane = this
|
||||
$('#tabs ul li').live 'mousedown', ->
|
||||
tabPane.switchToTab this
|
||||
false
|
||||
|
||||
nextTab: ->
|
||||
@switchToTab $('#tabs ul .active').next()
|
||||
|
||||
prevTab: ->
|
||||
@switchToTab $('#tabs ul .active').prev()
|
||||
|
||||
switchToTab: (tab) ->
|
||||
tab = $("#tabs ul li").get(tab - 1) if _.isNumber tab
|
||||
return if tab.length is 0
|
||||
|
||||
$("#tabs ul .active").removeClass("active")
|
||||
$(tab).addClass 'active'
|
||||
window.editor.focusBuffer $(tab).data 'path'
|
||||
|
||||
addTab: (path) ->
|
||||
existing = $("#tabs [data-path='#{path}']")
|
||||
if existing.length
|
||||
return @switchToTab existing
|
||||
|
||||
name = if path then _.last path.split '/' else "untitled"
|
||||
$("#tabs ul .active").removeClass()
|
||||
$("#tabs ul").append """
|
||||
<li data-path='#{path}'><a href='#'>#{name}</a></li>
|
||||
"""
|
||||
$("#tabs ul li:last").addClass 'active'
|
||||
|
||||
removeTab: (path) ->
|
||||
tab = $("#tabs li[data-path='#{path}']")
|
||||
if tab.hasClass("active")
|
||||
nextTab = tab.next()
|
||||
nextTab = tab.prev() if nextTab.length == 0
|
||||
@switchToTab nextTab if nextTab.length != 0
|
||||
|
||||
tab.remove()
|
||||
|
Before Width: | Height: | Size: 518 B After Width: | Height: | Size: 518 B |
1
extensions/tree/index.coffee
Normal file
1
extensions/tree/index.coffee
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = Tree = require 'tree/tree'
|
||||
2
extensions/tree/key-bindings.coffee
Normal file
2
extensions/tree/key-bindings.coffee
Normal file
@@ -0,0 +1,2 @@
|
||||
tree:
|
||||
'cmd-ctrl-n': (tree) -> tree.pane.toggle()
|
||||
73
extensions/tree/tree-pane.coffee
Normal file
73
extensions/tree/tree-pane.coffee
Normal file
@@ -0,0 +1,73 @@
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
|
||||
fs = require 'fs'
|
||||
|
||||
Pane = require 'pane'
|
||||
|
||||
module.exports =
|
||||
class TreePane extends Pane
|
||||
position: 'left'
|
||||
|
||||
tree: null
|
||||
|
||||
html: $ require "tree/tree.html"
|
||||
|
||||
constructor: (@tree) ->
|
||||
@reload()
|
||||
|
||||
$('#tree li').live 'click', (event) =>
|
||||
return true if event.__treeClicked__
|
||||
|
||||
$('#tree .active').removeClass 'active'
|
||||
|
||||
el = $(event.currentTarget)
|
||||
path = decodeURIComponent el.data 'path'
|
||||
|
||||
if fs.isDirectory path
|
||||
window.x = @tree
|
||||
openedDirs = @tree.getOpenedDirs()
|
||||
if el.hasClass 'open'
|
||||
openedDirs = _.without openedDirs, path
|
||||
el.removeClass 'open'
|
||||
el.children("ul").remove()
|
||||
else
|
||||
openedDirs.push path unless path in openedDirs
|
||||
el.addClass 'open'
|
||||
list = @createList path
|
||||
el.append list
|
||||
@tree.setOpenedDirs openedDirs
|
||||
else
|
||||
el.addClass 'active'
|
||||
window.open path
|
||||
|
||||
# HACK I need the event to propogate beyond the tree pane,
|
||||
# but I need the tree pane to ignore it. Need somehting
|
||||
# cleaner here.
|
||||
event.__treeClicked__ = true
|
||||
|
||||
true
|
||||
|
||||
reload: ->
|
||||
@html.children('#tree .cwd').text _.last atomController.path.split '/'
|
||||
fileList = @createList atomController.path
|
||||
fileList.addClass 'files'
|
||||
@html.children('#tree .files').replaceWith fileList
|
||||
|
||||
createList: (root) ->
|
||||
paths = fs.list root
|
||||
|
||||
list = $('<ul>')
|
||||
for path in paths
|
||||
filename = path.replace(root, "").substring 1
|
||||
type = if fs.isDirectory path then 'dir' else 'file'
|
||||
encodedPath = encodeURIComponent path
|
||||
listItem = $("<li class='#{type}' data-path='#{encodedPath}'>#{filename}</li>")
|
||||
openedDirs = @tree.getOpenedDirs()
|
||||
|
||||
if path in openedDirs and fs.isDirectory path
|
||||
listItem.append @createList path
|
||||
listItem.addClass "open"
|
||||
list.append listItem
|
||||
|
||||
list
|
||||
35
extensions/tree/tree.coffee
Normal file
35
extensions/tree/tree.coffee
Normal file
@@ -0,0 +1,35 @@
|
||||
_ = require 'underscore'
|
||||
|
||||
Event = require 'event'
|
||||
Extension = require 'extension'
|
||||
KeyBinder = require 'key-binder'
|
||||
Storage = require 'storage'
|
||||
TreePane = require 'tree/tree-pane'
|
||||
|
||||
fs = require 'fs'
|
||||
|
||||
module.exports =
|
||||
class Tree extends Extension
|
||||
constructor: ->
|
||||
KeyBinder.register "tree", @
|
||||
KeyBinder.load require.resolve "tree/key-bindings.coffee"
|
||||
|
||||
# Remove dirs that no longer exist
|
||||
openedPaths = @getOpenedDirs()
|
||||
for dir in openedPaths when not fs.exists dir
|
||||
openedDirs = _.without openedDirs, path
|
||||
@setOpenedDirs openedDirs
|
||||
|
||||
@pane = new TreePane @
|
||||
|
||||
storageNamespace: ->
|
||||
@.constructor.name + ":" + atomController.path
|
||||
|
||||
getOpenedDirs: ->
|
||||
Storage.get @storageNamespace() + ':openedDirs', []
|
||||
|
||||
setOpenedDirs: (value) ->
|
||||
Storage.set @storageNamespace() + ':openedDirs', value
|
||||
|
||||
startup: ->
|
||||
@pane.show()
|
||||
@@ -1,5 +1,5 @@
|
||||
<style>
|
||||
#project {
|
||||
#tree {
|
||||
min-width: 200px;
|
||||
height: 100%;
|
||||
background-color: #DDE3EA;
|
||||
@@ -10,7 +10,7 @@
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#project .cwd {
|
||||
#tree .cwd {
|
||||
padding-top: 5px;
|
||||
padding-left: 5px;
|
||||
font-weight: bold;
|
||||
@@ -19,48 +19,48 @@
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
#project ul {
|
||||
#tree ul {
|
||||
margin: 0;
|
||||
padding-top: 2px;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
#project li {
|
||||
#tree li {
|
||||
padding: 0;
|
||||
padding-left: 20px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
#project li ul li {
|
||||
#tree li ul li {
|
||||
padding-left: 110px;
|
||||
margin-left: -100px;
|
||||
}
|
||||
|
||||
#project li.file {
|
||||
#tree li.file {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#project li.dir {
|
||||
#tree li.dir {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#project li.dir {
|
||||
background: url('extensions/project/images/dir-toggle.png') 9px 6px no-repeat;
|
||||
#tree li.dir {
|
||||
background: url('extensions/tree/images/dir-toggle.png') 9px 6px no-repeat;
|
||||
}
|
||||
|
||||
#project li.dir.open {
|
||||
#tree li.dir.open {
|
||||
background-position: 9px -16px;
|
||||
}
|
||||
|
||||
#project li ul li.dir {
|
||||
#tree li ul li.dir {
|
||||
background-position: 100px 6px;
|
||||
}
|
||||
|
||||
#project li ul li.dir.open {
|
||||
#tree li ul li.dir.open {
|
||||
background-position: 100px -16px;
|
||||
}
|
||||
|
||||
#project li.active {
|
||||
#tree li.active {
|
||||
background-image: -webkit-gradient(linear,0% 0,0% 100%,from(#BCCBEB),to(#8094BB));
|
||||
border-top: 1px solid #A0AFCD;
|
||||
color: #fff;
|
||||
@@ -68,7 +68,7 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id='project'>
|
||||
<div id='tree'>
|
||||
<div class='cwd'></div>
|
||||
<ul class='files'></ul>
|
||||
</div>
|
||||
@@ -3,6 +3,8 @@ fs = require 'fs'
|
||||
|
||||
module.exports =
|
||||
class Extension
|
||||
pane: null
|
||||
|
||||
constructor: ->
|
||||
console.log "#{@constructor.name}: Loaded"
|
||||
|
||||
@@ -11,33 +13,3 @@ class Extension
|
||||
startup: ->
|
||||
|
||||
shutdown: ->
|
||||
|
||||
pane: ->
|
||||
|
||||
# This should be stored keyed on the window path I think? But what if the path
|
||||
# changes?
|
||||
get: (key, defaultValue) ->
|
||||
try
|
||||
object = JSON.parse(localStorage[@storageNamespace()] ? "{}")
|
||||
catch error
|
||||
error.message += "\nGetting #{key}"
|
||||
console.error(error)
|
||||
|
||||
object[key] ? defaultValue
|
||||
|
||||
set: (key, value) ->
|
||||
try
|
||||
object = JSON.parse(localStorage[@storageNamespace()] ? "{}")
|
||||
catch error
|
||||
error.message += "\nSetting #{key}: #{value}"
|
||||
console.error(error)
|
||||
|
||||
if value == undefined
|
||||
delete object[key]
|
||||
else
|
||||
object[key] = value
|
||||
|
||||
localStorage[@storageNamespace()] = JSON.stringify(object)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@ module.exports =
|
||||
class Storage
|
||||
@get: (key, defaultValue) ->
|
||||
try
|
||||
object = JSON.parse(localStorage[key] ? "{}")
|
||||
value = JSON.parse(localStorage[key] ? null) ? defaultValue
|
||||
catch error
|
||||
error.message += "\nGetting #{key}"
|
||||
console.error(error)
|
||||
|
||||
object ? defaultValue
|
||||
value
|
||||
|
||||
@set: (key, value) ->
|
||||
if value == undefined
|
||||
|
||||
Reference in New Issue
Block a user