Modules (188)

FileTreeViewModel

Description

The view model (or a Store in the Flux terminology) used by the file tree.

Many of the view model's methods are implemented by pure functions, which can be helpful for composability. Many of the methods commit the new treeData and send a change event when they're done whereas the functions do not do this.

Dependencies

Functions

Private

_addNewEntries

treeData Immutable.Map
added Array.<string>
list of new project-relative file paths
Returns: Immutable.Map
revised treeData
    function _addNewEntries(treeData, added) {
        added.forEach(function (filePath) {
            var isFolder = _.last(filePath) === "/";

            filePath = isFolder ? filePath.substr(0, filePath.length - 1) : filePath;

            var parentPath = FileUtils.getDirectoryPath(filePath),
                parentObjectPath = _filePathToObjectPath(treeData, parentPath),
                basename = FileUtils.getBaseName(filePath);

            if (parentObjectPath) {
                // Verify that the children are loaded
                var childrenPath = _.clone(parentObjectPath);
                childrenPath.push("children");
                if (treeData.getIn(childrenPath) === null) {
                    return;
                }

                treeData = _createPlaceholder(treeData, parentPath, basename, isFolder, {
                    notInCreateMode: true,
                    doNotOpen: true
                });
            }
        });

        return treeData;
    }
Private

_addTimestamp

    function _addTimestamp(item) {
        return item.set("_timestamp", new Date().getTime());
    }
Private

_closeSubtree

Closes a subtree path, given by an object path.

directory Immutable.Map
Current directory
Returns: Immutable.Map
new directory
    function _closeSubtree(directory) {
        directory = directory.delete("open");

        var children = directory.get("children");
        if (children) {
            children.keySeq().forEach(function (name) {
                var subdir = children.get(name);
                if (!isFile(subdir)) {
                    subdir = _closeSubtree(subdir);
                    children = children.set(name, subdir);
                }
            });
        }

        directory = directory.set("children", children);
        return directory;
    }
Private

_createIntermediateDirectories

treeData Immutable.Map
path string
Path to the final directory to be added in the tree
Returns: {treeData: Immutable.Map,objectPath: Array.<string>}
updated treeData and object path to the created object
    function _createIntermediateDirectories(treeData, path) {
        var objectPath = [],
            result = {
                objectPath: objectPath,
                treeData: treeData
            },
            treePointer = treeData;

        if (path === "") {
            return result;
        }

        var parts = path.split("/"),
            part = parts.shift(),
            node;

        while (part) {
            if (treePointer === null) {
                return null;
            }
            node = treePointer.get(part);
            objectPath.push(part);

            // This directory is missing, so create it.
            if (node === undefined) {
                treeData = treeData.updateIn(objectPath, _createNotFullyLoadedDirectory);
                node = treeData.getIn(objectPath);
            }

            part = parts.shift();
            if (part) {
                treePointer = node.get("children");

                if (treePointer) {
                    objectPath.push("children");
                } else {

                    // The directory is there, but the directory hasn't been loaded.
                    // Update the directory to be a `notFullyLoaded` directory.
                    treeData = treeData.updateIn(objectPath, _createNotFullyLoadedDirectory);
                    objectPath.push("children");
                    treePointer = treeData.getIn(objectPath);
                }
            }
        }

        result.treeData = treeData;
        return result;
    }
Private

_createNotFullyLoadedDirectory

directory optional Immutable.Map
Directory entry to update
Returns: Immutable.Map
New or updated directory object
    function _createNotFullyLoadedDirectory(directory) {
        if (!directory) {
            return Immutable.Map({
                notFullyLoaded: true,
                children: Immutable.Map()
            });
        }
        return directory.merge({
            notFullyLoaded: true,
            children: Immutable.Map()
        });
    }
Private Public API

_createPlaceholder

    function _createPlaceholder(treeData, basedir, name, isFolder, options) {
        options = options || {};
        var parentPath = _filePathToObjectPath(treeData, basedir);

        if (!parentPath) {
            return;
        }

        var newObject = {
        };

        if (!options.notInCreateMode) {
            newObject.creating = true;
        }

        if (isFolder) {
            // If we're creating a folder, then we know it's empty.
            // But if we're not in create mode, (we're adding a folder based on an
            // FS event), we don't know anything about the new directory's children.
            if (options.notInCreateMode) {
                newObject.children = null;
            } else {
                newObject.children = Immutable.Map();
            }
        }

        var newFile = Immutable.Map(newObject);

        if (!options.doNotOpen) {
            treeData = _openPath(treeData, basedir);
        }
        if (parentPath.length > 0) {
            var childrenPath = _.clone(parentPath);
            childrenPath.push("children");

            treeData = treeData.updateIn(childrenPath, function (children) {
                return children.set(name, newFile);
            });
        } else {
            treeData = treeData.set(name, newFile);
        }
        return treeData;
    }
Private

_deleteAtPath

    function _deleteAtPath(treeData, path) {
        var objectPath = _filePathToObjectPath(treeData, path);

        if (!objectPath) {
            return;
        }

        var originalName = _.last(objectPath);

        // Back up to the parent directory
        objectPath.pop();

        treeData = treeData.updateIn(objectPath, function (directory) {
            directory = directory.delete(originalName);
            return directory;
        });

        return treeData;
    }
Private Public API

_filePathToObjectPath

treeData Immutable.Map
path string
project relative path to the file or directory. Can include trailing slash.
Returns: Array.<string>,null
Returns null if the path can't be found in the tree, otherwise an array of strings representing the path through the object.
    function _filePathToObjectPath(treeData, path) {
        if (path === null) {
            return null;
        } else if (path === "") {
            return [];
        }

        var parts = path.split("/"),
            part = parts.shift(),
            result = [],
            node;

        // Step through the parts of the path and the treeData object simultaneously
        while (part) {
            // We hit the end of the tree without finding our object, so return null
            if (!treeData) {
                return null;
            }

            node = treeData.get(part);

            // The name represented by `part` isn't in the tree, so return null.
            if (node === undefined) {
                return null;
            }

            // We've verified this part, so store it.
            result.push(part);

            // Pull the next part of the path
            part = parts.shift();

            // If we haven't passed the end of the path string, then the object we've got in hand
            // *should* be a directory. Confirm that and add `children` to the path to move down
            // to the next directory level.
            if (part) {
                treeData = node.get("children");
                if (treeData) {
                    result.push("children");
                }
            }
        }

        return result;
    }
Private

_getChildDirectories

    function _getChildDirectories(treeData, projectRootPath) {
        var childDirectories = [];

        function addNodesAtDepth(treeData, parent, depth) {
            if (!treeData) {
                return;
            }

            treeData.forEach(function (value, key) {
                if (!isFile(value)) {
                    var directoryPath = key + "/";

                    childDirectories.push(directoryPath);
                }
            });
        }

        // start at the top of the tree and the first array element
        addNodesAtDepth(treeData, projectRootPath, 0);
        return childDirectories;
    }
Private

_getOpenNodes

    function _getOpenNodes(treeData, projectRootPath) {
        var openNodes = [];

        function addNodesAtDepth(treeData, parent, depth) {
            if (!treeData) {
                return;
            }

            treeData.forEach(function (value, key) {
                if (isFile(value)) {
                    return;
                }

                var directoryPath = parent + key + "/";

                if (value.get("open")) {
                    var nodeList = openNodes[depth];
                    if (!nodeList) {
                        nodeList = openNodes[depth] = [];
                    }
                    nodeList.push(directoryPath);
                    addNodesAtDepth(value.get("children"), directoryPath, depth + 1);
                }
            });
        }

        // start at the top of the tree and the first array element
        addNodesAtDepth(treeData, projectRootPath, 0);
        return openNodes;
    }
Private Public API

_isFilePathVisible

    function _isFilePathVisible(treeData, path) {
        if (path === null) {
            return null;
        } else if (path === "") {
            return true;
        }

        var parts = path.split("/"),
            part = parts.shift(),
            result = [],
            node;

        while (part) {
            if (treeData === null) {
                return false;
            }
            node = treeData.get(part);
            if (node === undefined) {
                return null;
            }
            result.push(part);
            part = parts.shift();
            if (part) {
                if (!node.get("open")) {
                    return false;
                }
                treeData = node.get("children");
                if (treeData) {
                    result.push("children");
                }
            }
        }

        return true;
    }
Private

_markAsChanged

treeData Immutable.Map
changed Array.<string>
list of changed project-relative file paths
Returns: Immutable.Map
revised treeData
    function _markAsChanged(treeData, changed) {
        changed.forEach(function (filePath) {
            var objectPath = _filePathToObjectPath(treeData, filePath);
            if (objectPath) {
                treeData = treeData.updateIn(objectPath, _addTimestamp);
            }
        });
        return treeData;
    }
Private

_mergeContentsIntoChildren

children Immutable.Map
current children in the directory
contents Array.<FileSystemEntry>
FileSystemEntry objects currently in the directory
Returns: Immutable.Map
updated children
    function _mergeContentsIntoChildren(children, contents) {

        // We keep track of the names we've seen among the current directory entries to make
        // it easy to spot the names that we *haven't* seen (in other words, files that have
        // been deleted).
        var keysSeen = [];

        children = children.withMutations(function (children) {

            // Loop through the directory entries
            contents.forEach(function (entry) {
                keysSeen.push(entry.name);

                var match = children.get(entry.name);
                if (match) {
                    // Confirm that a name that used to represent a file and now represents a
                    // directory (or vice versa) isn't what we've encountered here. If we have
                    // hit this situation, pretend the current child of treeData doesn't exist
                    // so we can replace it.
                    var matchIsFile = isFile(match);
                    if (matchIsFile !== entry.isFile) {
                        match = undefined;
                    }
                }

                // We've got a new entry that we need to add.
                if (!match) {
                    if (entry.isFile) {
                        children.set(entry.name, Immutable.Map());
                    } else {
                        children.set(entry.name, Immutable.Map({
                            children: null
                        }));
                    }
                }
            });

            // Look at the list of names that we currently have in the treeData that no longer
            // appear in the directory and delete those.
            var currentEntries = children.keySeq().toJS(),
                deletedEntries = _.difference(currentEntries, keysSeen);

            deletedEntries.forEach(function (name) {
                children.delete(name);
            });
        });
        return children;
    }
Private

_moveMarker

    function _moveMarker(treeData, markerName, oldPath, newPath) {
        var objectPath;

        if (newPath) {
            objectPath = _filePathToObjectPath(treeData, newPath);
        }

        var newTreeData = treeData;

        if (oldPath && oldPath !== newPath) {
            var lastObjectPath = _filePathToObjectPath(treeData, oldPath);
            if (lastObjectPath) {
                newTreeData = newTreeData.updateIn(lastObjectPath, function (entry) {
                    return entry.delete(markerName);
                });
            }
        }

        if (newPath && objectPath && objectPath.length !== 0) {
            newTreeData = newTreeData.updateIn(objectPath, function (entry) {
                return entry.set(markerName, true);
            });
        }

        return newTreeData;
    }
Private

_openPath

treeData Immutable.Map
path string
Path to open
    function _openPath(treeData, path) {
        var objectPath = _filePathToObjectPath(treeData, path);

        function setOpen(node) {
            return node.set("open", true);
        }

        while (objectPath && objectPath.length) {
            var node = treeData.getIn(objectPath);
            if (isFile(node)) {
                objectPath.pop();
            } else {
                if (!node.get("open")) {
                    treeData = treeData.updateIn(objectPath, setOpen);
                }
                objectPath.pop();
                if (objectPath.length) {
                    objectPath.pop();
                }
            }
        }

        return treeData;
    }
Private

_setDirectoryOpen

    function _setDirectoryOpen(treeData, path, open) {
        var objectPath = _filePathToObjectPath(treeData, path),
            directory = treeData.getIn(objectPath);

        if (!objectPath) {
            return {
                needsLoading: true,
                treeData: treeData
            };
        }

        if (isFile(directory)) {
            return;
        }

        var alreadyOpen = directory.get("open") === true;

        if ((alreadyOpen && open) || (!alreadyOpen && !open)) {
            return;
        }

        treeData = treeData.updateIn(objectPath, function (directory) {
            if (open) {
                return directory.set("open", true);
            } else {
                return directory.delete("open");
            }
        });

        if (open && (directory.get("children") === null || directory.get("notFullyLoaded"))) {
            return {
                needsLoading: true,
                treeData: treeData
            };
        }
        return {
            needsLoading: false,
            treeData: treeData
        };
    }
Private

_setIn

treeData Immutable.Map
objectPath Array.<string>
path to object that should be replaced
newValue Immutable.Map
new value to provide at that path
Returns: Immutable.Map
updated treeData
    function _setIn(treeData, objectPath, newValue) {
        return treeData.updateIn(objectPath, function (oldValue) {
            return newValue;
        });
    }
Public API

isFile

Determine if an entry from the treeData map is a file.

entry Immutable.Map
entry to test
Returns: boolean
true if this is a file and not a directory
    function isFile(entry) {
        return entry.get("children") === undefined;
    }

Classes

Constructor

FileTreeViewModel

    function FileTreeViewModel() {
        // For convenience in callbacks, make a bound version of this method so that we can
        // just refer to it as this._commit when passing in a callback.
        this._commit = this._commit.bind(this);
    }
    EventDispatcher.makeEventDispatcher(FileTreeViewModel.prototype);

Properties

Private

_selectionViewInfo

Type
Immutable.Map
    FileTreeViewModel.prototype._selectionViewInfo = Immutable.Map({
        width: 0,
        scrollTop: 0,
        scrollLeft: 0,
        offsetTop: 0,
        hasContext: false,
        hasSelection: false
    });

    Object.defineProperty(FileTreeViewModel.prototype, "selectionViewInfo", {
        get: function () {
            return this._selectionViewInfo;
        }
    });
Private

_treeData

Type
Immutable.Map
    FileTreeViewModel.prototype._treeData = Immutable.Map();

    Object.defineProperty(FileTreeViewModel.prototype, "treeData", {
        get: function () {
            return this._treeData;
        }
    });

sortDirectoriesFirst

Type
boolean
    FileTreeViewModel.prototype.sortDirectoriesFirst = false;

Methods

Private

_commit

treeData nullable Immutable.Map
new treeData state
selectionViewInfo nullable Immutable.Map
updated information for the selection/context bars
    FileTreeViewModel.prototype._commit = function (treeData, selectionViewInfo) {
        var changed = false;
        if (treeData && treeData !== this._treeData) {
            this._treeData = treeData;
            changed = true;
        }

        if (selectionViewInfo && selectionViewInfo !== this._selectionViewInfo) {
            this._selectionViewInfo = selectionViewInfo;
            changed = true;
        }
        if (changed) {
            this.trigger(EVENT_CHANGE);
        }
    };
Private

_getObject

Returns the object at the given file path.

path string
Path to the object
Returns: Immutable.Map=
directory or file object from the tree. Null if it's not found.
    FileTreeViewModel.prototype._getObject = function (path) {
        var objectPath = _filePathToObjectPath(this._treeData, path);
        if (!objectPath) {
            return null;
        }
        return this._treeData.getIn(objectPath);
    };
Private

_rootChanged

    FileTreeViewModel.prototype._rootChanged = function () {
        this._treeData = Immutable.Map();
    };

closeSubtree

Closes the directory at path and recursively closes all of its children.

path string
Path of subtree to close
    FileTreeViewModel.prototype.closeSubtree = function (path) {
        var treeData = this._treeData,
            subtreePath = _filePathToObjectPath(treeData, path);

        if (!subtreePath) {
            return;
        }

        var directory = treeData.getIn(subtreePath);

        directory = _closeSubtree(directory);
        treeData = _setIn(treeData, subtreePath, directory);
        this._commit(treeData);
    };

createPlaceholder

Creates a placeholder file or directory that appears in the tree so that the user can provide a name for the new entry.

basedir string
Directory that contains the new file or folder
name string
Initial name to give the new entry
isFolder boolean
true if the entry being created is a folder
    FileTreeViewModel.prototype.createPlaceholder = function (basedir, name, isFolder) {
        var treeData = _createPlaceholder(this._treeData, basedir, name, isFolder);
        this._commit(treeData);
    };

deleteAtPath

Deletes the entry at the given path.

path string
Project-relative path to delete
    FileTreeViewModel.prototype.deleteAtPath = function (path) {
        var treeData = _deleteAtPath(this._treeData, path);
        if (treeData) {
            this._commit(treeData);
        }
    };

ensureDirectoryExists

Makes sure that the directory exists. This will create a directory object (unloaded) if the directory does not already exist. A change message is also fired in that case.

This is useful for file system events which can refer to a directory that we don't know about already.

path string
Project-relative path to the directory
    FileTreeViewModel.prototype.ensureDirectoryExists = function (path) {
        var treeData          = this._treeData,
            pathWithoutSlash  = FileUtils.stripTrailingSlash(path),
            parentPath        = FileUtils.getDirectoryPath(pathWithoutSlash),
            name              = pathWithoutSlash.substr(parentPath.length),
            targetPath        = [];

        if (parentPath) {
            targetPath = _filePathToObjectPath(treeData, parentPath);
            if (!targetPath) {
                return;
            }
            targetPath.push("children");
            if (!treeData.getIn(targetPath)) {
                return;
            }
        }

        targetPath.push(name);

        if (treeData.getIn(targetPath)) {
            return;
        }

        treeData = _setIn(treeData, targetPath, Immutable.Map({
            children: null
        }));

        this._commit(treeData);
    };

getOpenNodes

Creates an array of arrays where each entry of the top-level array has an array of paths that are at the same depth in the tree. All of the paths are full paths.

This is used for saving the current set of open nodes to the preferences system for restoring on project open.

projectRootPath string
Full path to the project root
Returns: Array.<Array.<string>>
Array of array of full paths, organized by depth in the tree.
    FileTreeViewModel.prototype.getOpenNodes = function (projectRootPath) {
        return _getOpenNodes(this._treeData, projectRootPath);
    };

    FileTreeViewModel.prototype.getChildDirectories = function (parent) {
        var treeData = this._treeData,
            objectPath = _filePathToObjectPath(treeData, parent);

        if (!objectPath) {
            return;
        }

        var children;
        if (objectPath.length === 0) {
            // this is the root of the tree
            children = this._treeData;
        } else {
            objectPath.push("children");
            children = this._treeData.getIn(objectPath);
        }

        return _getChildDirectories(children, parent);
    };

isFilePathVisible

Determines if a given file path is visible within the tree.

For detailed documentation on how the loop works, see _filePathToObjectPath which follows the same pattern. This differs from that function in that this one checks for the open state of directories and has a different return value.

path string
project relative file path
Returns: boolean,null
true if the given path is currently visible in the tree, null if the given path is not present in the tree.
    FileTreeViewModel.prototype.isFilePathVisible = function (path) {
        return _isFilePathVisible(this._treeData, path);
    };

isPathLoaded

Determines if a given path has been loaded.

path string
project relative file or directory path
Returns: boolean
true if the path has been loaded
    FileTreeViewModel.prototype.isPathLoaded = function (path) {
        var objectPath = _filePathToObjectPath(this._treeData, path);

        if (!objectPath) {
            return false;
        }

        // If it's a directory, make sure that its children are loaded
        if (_.last(path) === "/") {
            var directory = this._treeData.getIn(objectPath);
            if (!directory.get("children") || directory.get("notFullyLoaded")) {
                return false;
            }
        }

        return true;
    };

moveMarker

Moves a boolean marker flag from one file path to another.

markerName string
Name of the flag to set (for example, "selected")
oldPath string,null
Project relative file path with the location of the marker to move, or null if it's not being moved from elsewhere in the tree
newPath string,null
Project relative file path with where to place the marker, or null if the marker is being removed from the tree
    FileTreeViewModel.prototype.moveMarker = function (markerName, oldPath, newPath) {
        var newTreeData = _moveMarker(this._treeData, markerName, oldPath, newPath),
            selectionViewInfo = this._selectionViewInfo;

        if (markerName === "selected") {
            selectionViewInfo = selectionViewInfo.set("hasSelection", !!newPath);
        } else if (markerName === "context") {
            selectionViewInfo = selectionViewInfo.set("hasContext", !!newPath);
        }
        this._commit(newTreeData, selectionViewInfo);
    };

openPath

Opens the directories along the given path.

path string
Project-relative path
    FileTreeViewModel.prototype.openPath = function (path) {
        this._commit(_openPath(this._treeData, path));
    };

processChanges

Applies changes to the tree. The changes object can have one or more of the following keys which all have arrays of project-relative paths as their values:

  • changed: entries that have changed in some way that should be re-rendered
  • added: new entries that need to appear in the tree
  • removed: entries that have been deleted from the tree
{changed: Array.<string>=,added: Array.<string>=,removed: Array.<string>=}
    FileTreeViewModel.prototype.processChanges = function (changes) {
        var treeData = this._treeData;

        if (changes.changed) {
            treeData = _markAsChanged(treeData, changes.changed);
        }

        if (changes.added) {
            treeData = _addNewEntries(treeData, changes.added);
        }

        if (changes.removed) {
            changes.removed.forEach(function (path) {
                treeData = _deleteAtPath(treeData, path);
            });
        }

        this._commit(treeData);
    };

renameItem

Changes the path of the item at the currentPath to newPath.

currentPath string
project relative file path to the current item
newPath string
project relative new path to give the item
    FileTreeViewModel.prototype.renameItem = function (oldPath, newPath) {
        var treeData = this._treeData,
            oldObjectPath = _filePathToObjectPath(treeData, oldPath),
            newDirectoryPath = FileUtils.getParentPath(newPath),
            newObjectPath = _filePathToObjectPath(treeData, newDirectoryPath);

        if (!oldObjectPath || !newObjectPath) {
            return;
        }

        var originalName = _.last(oldObjectPath),
            newName = FileUtils.getBaseName(newPath),
            currentObject;

        // Back up to the parent directory
        oldObjectPath.pop();

        // Remove the oldPath
        treeData = treeData.updateIn(oldObjectPath, function (directory) {
            currentObject = directory.get(originalName);
            directory = directory.delete(originalName);
            return directory;
        });

        // Add the newPath

        // If the new directory is not loaded, create a not fully loaded directory there,
        // so that we can add the new item as a child of new directory
        if (!this.isPathLoaded(newDirectoryPath)) {
            treeData = treeData.updateIn(newObjectPath, _createNotFullyLoadedDirectory);
        }

        // If item moved to root directory, objectPath should not have "children",
        // otherwise the objectPath should have "children"
        if (newObjectPath.length > 0) {
            newObjectPath.push("children");
        }

        treeData = treeData.updateIn(newObjectPath, function (children) {
            return children.set(newName, currentObject);
        });

        this._commit(treeData);
    };

setDirectoryContents

Updates the directory at the given path with the new contents. If the parent directories of this directory have not been loaded yet, they will be created. This allows directories to be loaded in any order.

Project string
relative path to the directory that is being updated.
Current Array.<FileSystemEntry>
contents of the directory
    FileTreeViewModel.prototype.setDirectoryContents = function (path, contents) {
        path = FileUtils.stripTrailingSlash(path);

        var intermediate = _createIntermediateDirectories(this._treeData, path),
            objectPath = intermediate.objectPath,
            treeData = intermediate.treeData;

        if (objectPath === null) {
            return;
        }

        var directory = treeData.getIn(objectPath),
            children = directory;

        // The root directory doesn't need this special handling.
        if (path !== "") {

            // The user of this API passed in a path to a file rather than a directory.
            // Perhaps this should be an exception?
            if (isFile(directory)) {
                return;
            }

            // If the directory had been created previously as `notFullyLoaded`, we can
            // remove that flag now because this is the step that is loading the directory.
            if (directory.get("notFullyLoaded")) {
                directory = directory.delete("notFullyLoaded");
            }

            if (!directory.get("children")) {
                directory = directory.set("children", Immutable.Map());
            }

            treeData = _setIn(treeData, objectPath, directory);

            objectPath.push("children");
            children = directory.get("children");
        }

        children = _mergeContentsIntoChildren(children, contents);
        treeData = _setIn(treeData, objectPath, children);
        this._commit(treeData);
    };

setDirectoryOpen

Sets the directory at the given path to open or closed. Returns true if the directory contents need to be loaded.

path string
Project relative file path to the directory
open boolean
True to open the directory
Returns: boolean
true if the directory contents need to be loaded.
    FileTreeViewModel.prototype.setDirectoryOpen = function (path, open) {
        var result = _setDirectoryOpen(this._treeData, path, open);
        if (result && result.treeData) {
            this._commit(result.treeData);
        }
        return result ? result.needsLoading : false;
    };

setSelectionScrollerInfo

Sets the scroll position of the file tree to help position the selection bar. SPECIAL CASE NOTE: this does not trigger a change event because this data is explicitly set in the rendering process (see ProjectManager._renderTree).

scrollWidth int
width of the tree content
scrollTop int
Scroll position
scrollLeft optional int
Horizontal scroll position
offsetTop optional int
top of the scroller
    FileTreeViewModel.prototype.setSelectionScrollerInfo = function (scrollWidth, scrollTop, scrollLeft, offsetTop) {
        this._selectionViewInfo = this._selectionViewInfo.set("scrollWidth", scrollWidth);
        this._selectionViewInfo = this._selectionViewInfo.set("scrollTop", scrollTop);

        if (scrollLeft !== undefined) {
            this._selectionViewInfo = this._selectionViewInfo.set("scrollLeft", scrollLeft);
        }

        if (offsetTop !== undefined) {
            this._selectionViewInfo = this._selectionViewInfo.set("offsetTop", offsetTop);
        }
        // Does not emit change event. See SPECIAL CASE NOTE in docstring above.
    };

    // Private API
    exports.EVENT_CHANGE          = EVENT_CHANGE;
    exports._filePathToObjectPath = _filePathToObjectPath;
    exports._isFilePathVisible    = _isFilePathVisible;
    exports._createPlaceholder    = _createPlaceholder;

    // Public API
    exports.isFile            = isFile;
    exports.FileTreeViewModel = FileTreeViewModel;
});

setSelectionWidth

Sets the width of the selection bar.

width int
New width
    FileTreeViewModel.prototype.setSelectionWidth = function (width) {
        var selectionViewInfo = this._selectionViewInfo;
        selectionViewInfo = selectionViewInfo.set("width", width);
        this._commit(null, selectionViewInfo);
    };

setSortDirectoriesFirst

Sets the value of the sortDirectoriesFirst flag which tells to view that directories should be listed before the alphabetical listing of files.

sortDirectoriesFirst boolean
True if directories should be displayed first
    FileTreeViewModel.prototype.setSortDirectoriesFirst = function (sortDirectoriesFirst) {
        if (sortDirectoriesFirst !== this.sortDirectoriesFirst) {
            this.sortDirectoriesFirst = sortDirectoriesFirst;
            this.trigger(EVENT_CHANGE);
        }
    };