Exemplo n.º 1
0
        public void UpdateEntries(IList <GitStatusEntry> newEntries)
        {
            // Handle the empty list scenario
            if (!newEntries.Any())
            {
                entries.Clear();
                entryCommitTargets.Clear();
                tree = null;
                foldedTreeEntries.Clear();

                OnCommitTreeChange();

                return;
            }

            tree = TreeBuilder.BuildTreeRoot(newEntries, entries, entryCommitTargets, foldedTreeEntries, AssetDatabase.GetCachedIcon);

            OnCommitTreeChange();
        }
Exemplo n.º 2
0
        private void TreeNode(FileTreeNode node)
        {
            GUILayout.Space(Styles.TreeVerticalSpacing);
            var target   = node.Target;
            var isFolder = node.Children.Any();

            var isFolderForMeta = false;

            if (node.Children.Count() == 1)
            {
                isFolderForMeta = node.Children.First().Label.Substring(node.Label.Length).Equals(".meta");
            }

            GUILayout.BeginHorizontal();
            {
                if (!Readonly)
                {
                    // Commit inclusion toggle
                    var state   = node.State;
                    var toggled = state == CommitState.All;

                    EditorGUI.BeginChangeCheck();
                    {
                        toggled = GUILayout.Toggle(toggled, "", state == CommitState.Some ? Styles.ToggleMixedStyle : GUI.skin.toggle,
                                                   GUILayout.ExpandWidth(false));
                    }
                    if (EditorGUI.EndChangeCheck())
                    {
                        node.State = toggled ? CommitState.All : CommitState.None;
                    }
                }

                // Foldout
                if (isFolder)
                {
                    Rect foldoutRect;

                    if (Readonly)
                    {
                        foldoutRect = GUILayoutUtility.GetRect(1, 1);
                        foldoutRect.Set(foldoutRect.x - 7f, foldoutRect.y + 3f, 0f, EditorGUIUtility.singleLineHeight);
                    }
                    else
                    {
                        foldoutRect = GUILayoutUtility.GetLastRect();
                    }

                    foldoutRect.Set(foldoutRect.x - Styles.FoldoutWidth + Styles.FoldoutIndentation, foldoutRect.y, Styles.FoldoutWidth,
                                    foldoutRect.height);

                    EditorGUI.BeginChangeCheck();
                    {
                        node.Open = GUI.Toggle(foldoutRect, node.Open, "", EditorStyles.foldout);
                    }
                    if (EditorGUI.EndChangeCheck())
                    {
                        if (!node.Open && !foldedTreeEntries.Contains(node.RepositoryPath))
                        {
                            foldedTreeEntries.Add(node.RepositoryPath);
                        }
                        else if (node.Open)
                        {
                            foldedTreeEntries.Remove(node.RepositoryPath);
                        }

                        OnCommitTreeChange();
                    }
                }

                GitFileStatus?status = null;

                // Node icon and label
                GUILayout.BeginHorizontal();
                {
                    GUILayout.Space(Styles.CommitIconHorizontalPadding);
                    var iconRect = GUILayoutUtility.GetRect(Styles.CommitIconSize, Styles.CommitIconSize, GUILayout.ExpandWidth(false));
                    iconRect.y += 2;
                    iconRect.x -= 2;

                    if (Event.current.type == EventType.Repaint)
                    {
                        var icon = (Texture)node.Icon;
                        if (icon == null)
                        {
                            if (isFolderForMeta || !isFolder)
                            {
                                icon = Styles.DefaultAssetIcon;
                            }
                            else
                            {
                                icon = Styles.FolderIcon;
                            }
                        }

                        if (icon != null)
                        {
                            GUI.DrawTexture(iconRect,
                                            icon,
                                            ScaleMode.ScaleToFit);
                        }
                    }

                    var statusRect = new Rect(
                        iconRect.xMax - 9,
                        iconRect.yMax - 7,
                        9,
                        9);

                    // Current status (if any)
                    if (target != null)
                    {
                        var idx = entryCommitTargets.IndexOf(target);
                        if (idx > -1)
                        {
                            status = entries[idx].Status;
                            var statusIcon = Styles.GetFileStatusIcon(entries[idx].Status, false);
                            if (statusIcon != null)
                            {
                                GUI.DrawTexture(statusRect, statusIcon);
                            }
                        }
                    }

                    GUILayout.Space(Styles.CommitIconHorizontalPadding);
                }
                GUILayout.EndHorizontal();

                // Make the text gray and strikethrough if the file is deleted
                if (status == GitFileStatus.Deleted)
                {
                    GUILayout.Label(new GUIContent(node.Label, node.RepositoryPath), Styles.DeletedFileLabel, GUILayout.ExpandWidth(true));
                    var labelRect  = GUILayoutUtility.GetLastRect();
                    var strikeRect = new Rect(labelRect.xMin, labelRect.center.y, labelRect.width, 1);
                    EditorGUI.DrawRect(strikeRect, Color.gray);
                }
                else
                {
                    GUILayout.Label(new GUIContent(node.Label, node.RepositoryPath), GUILayout.ExpandWidth(true));
                }
                GUILayout.FlexibleSpace();
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            {
                // Render children (if any and folded out)
                if (isFolder && node.Open)
                {
                    GUILayout.Space(Styles.TreeIndentation);
                    GUILayout.BeginVertical();
                    {
                        foreach (var child in node.Children)
                        {
                            TreeNode(child);
                        }
                    }

                    GUILayout.EndVertical();
                }
            }

            GUILayout.EndHorizontal();
        }
Exemplo n.º 3
0
        public void UpdateEntries(IList <GitStatusEntry> newEntries)
        {
            // Handle the empty list scenario
            if (!newEntries.Any())
            {
                entries.Clear();
                entryCommitTargets.Clear();
                tree = null;
                foldedTreeEntries.Clear();

                OnCommitTreeChange();

                return;
            }

            // Remove what got nuked
            for (var index = 0; index < entries.Count;)
            {
                if (!newEntries.Contains(entries[index]))
                {
                    entries.RemoveAt(index);
                    entryCommitTargets.RemoveAt(index);
                }
                else
                {
                    index++;
                }
            }

            // Remove folding state of nuked items
            for (var index = 0; index < foldedTreeEntries.Count;)
            {
                if (!newEntries.Any(e => e.Path.IndexOf(foldedTreeEntries[index]) == 0))
                {
                    foldedTreeEntries.RemoveAt(index);
                }
                else
                {
                    index++;
                }
            }

            // Add new stuff
            for (var index = 0; index < newEntries.Count; ++index)
            {
                var entry = newEntries[index];
                if (!entries.Contains(entry))
                {
                    entries.Add(entry);
                    entryCommitTargets.Add(new GitCommitTarget());
                }
            }

            // TODO: Filter .meta files - consider adding them as children of the asset or folder they're supporting

            // TODO: In stead of completely rebuilding the tree structure, figure out a way to migrate open/closed states from the old tree to the new

            // Build tree structure

            tree = new FileTreeNode(FileSystemHelpers.FindCommonPath(entries.Select(e => e.Path)), stateChangeCallback);
            tree.RepositoryPath = tree.Path;
            for (var index = 0; index < entries.Count; index++)
            {
                var entryPath = entries[index].Path.ToNPath();
                if (entryPath.IsChildOf(tree.Path))
                {
                    entryPath = entryPath.RelativeTo(tree.Path.ToNPath());
                }

                var node = new FileTreeNode(entryPath, stateChangeCallback)
                {
                    Target = entryCommitTargets[index]
                };
                if (!string.IsNullOrEmpty(entries[index].ProjectPath))
                {
                    node.Icon = AssetDatabase.GetCachedIcon(entries[index].ProjectPath);
                }

                BuildTree(tree, node);
            }

            OnCommitTreeChange();
        }
Exemplo n.º 4
0
 public FileTreeNode Add(FileTreeNode child)
 {
     children.Add(child);
     return(child);
 }
Exemplo n.º 5
0
        private void BuildTree(FileTreeNode parent, FileTreeNode node)
        {
            if (string.IsNullOrEmpty(node.Label))
            {
                // TODO: We should probably reassign this target onto the parent? Depends on how we want to handle .meta files for folders
                return;
            }

            node.RepositoryPath = parent.RepositoryPath.ToNPath().Combine(node.Label);
            parent.Open         = !foldedTreeEntries.Contains(parent.RepositoryPath);

            // Is this node inside a folder?
            var nodePath = node.Label.ToNPath();

            if (nodePath.Elements.Count() > 1)
            {
                // Figure out what the root folder is and chop it from the path
                var root = nodePath.Elements.First();
                node.Label = new NPath("").Combine(nodePath.Elements.Skip(1).ToArray());

                // Look for a branch matching our root in the existing children
                var found = false;
                foreach (var child in parent.Children)
                {
                    // If we found the branch, continue building from that branch
                    if (child.Label.Equals(root))
                    {
                        found = true;
                        BuildTree(child, node);
                        break;
                    }
                }

                // No existing branch - we will have to add a new one to build from
                if (!found)
                {
                    var p = parent.RepositoryPath.ToNPath().Combine(root);
                    BuildTree(parent.Add(new FileTreeNode(root, stateChangeCallback)
                    {
                        RepositoryPath = p
                    }), node);
                }
            }
            else if (nodePath.ExtensionWithDot == ".meta")
            {
                // Look for a branch matching our root in the existing children
                var found = false;
                foreach (var child in parent.Children)
                {
                    // If we found the branch, continue building from that branch
                    if (child.Label.Equals(nodePath.Parent.Combine(nodePath.FileNameWithoutExtension)))
                    {
                        found = true;
                        BuildTree(child, node);
                        break;
                    }
                }
                if (!found)
                {
                    parent.Add(node);
                }
            }
            // Not inside a folder - just add this node right here
            else
            {
                parent.Add(node);
            }
        }
Exemplo n.º 6
0
        internal static FileTreeNode BuildTreeRoot(IList <GitStatusEntry> newEntries, List <GitStatusEntry> gitStatusEntries, List <GitCommitTarget> gitCommitTargets, List <string> foldedTreeEntries, Func <string, object> iconLoaderFunc = null)
        {
            Guard.ArgumentNotNullOrEmpty(newEntries, "newEntries");

            var newEntriesSetByPath       = new HashSet <string>(newEntries.Select(entry => entry.Path));
            var gitStatusEntriesSetByPath = new HashSet <string>(gitStatusEntries.Select(entry => entry.Path));

            // Remove what got nuked
            for (var index = 0; index < gitStatusEntries.Count;)
            {
                if (!newEntriesSetByPath.Contains(gitStatusEntries[index].Path))
                {
                    gitStatusEntries.RemoveAt(index);
                    gitCommitTargets.RemoveAt(index);
                }
                else
                {
                    index++;
                }
            }

            // Remove folding state of nuked items
            for (var index = 0; index < foldedTreeEntries.Count;)
            {
                if (newEntries.All(e => e.Path.IndexOf(foldedTreeEntries[index], StringComparison.CurrentCulture) != 0))
                {
                    foldedTreeEntries.RemoveAt(index);
                }
                else
                {
                    index++;
                }
            }

            var foldedTreeSet = new HashSet <string>(foldedTreeEntries);

            // Add new stuff
            for (var index = 0; index < newEntries.Count; ++index)
            {
                var entry = newEntries[index];
                if (!gitStatusEntriesSetByPath.Contains(entry.Path))
                {
                    gitStatusEntries.Add(entry);
                    gitCommitTargets.Add(new GitCommitTarget());
                }
            }

            // TODO: In stead of completely rebuilding the tree structure, figure out a way to migrate open/closed states from the old tree to the new
            // Build tree structure

            var tree = new FileTreeNode(FileSystemHelpers.FindCommonPath(gitStatusEntries.Select(e => e.Path)));

            tree.RepositoryPath = tree.Path;

            for (var index1 = 0; index1 < gitStatusEntries.Count; index1++)
            {
                var gitStatusEntry = gitStatusEntries[index1];
                var entryPath      = gitStatusEntry.Path.ToNPath();
                if (entryPath.IsChildOf(tree.Path))
                {
                    entryPath = entryPath.RelativeTo(tree.Path.ToNPath());
                }

                var node = new FileTreeNode(entryPath)
                {
                    Target = gitCommitTargets[index1]
                };
                if (!String.IsNullOrEmpty(gitStatusEntry.ProjectPath))
                {
                    node.Icon = iconLoaderFunc?.Invoke(gitStatusEntry.ProjectPath);
                }

                BuildChildNode(tree, node, foldedTreeSet);
            }

            return(tree);
        }