Skip to content
Snippets Groups Projects
Commit c2c5f2eb authored by Stanley Goldman's avatar Stanley Goldman
Browse files

Isolating code for building ChangesTreeView for relocation and performance testing

parent a7f55167
No related branches found
No related tags found
No related merge requests found
...@@ -102,6 +102,7 @@ ...@@ -102,6 +102,7 @@
<Compile Include="UI\IView.cs" /> <Compile Include="UI\IView.cs" />
<Compile Include="UI\SettingsView.cs" /> <Compile Include="UI\SettingsView.cs" />
<Compile Include="UI\Subview.cs" /> <Compile Include="UI\Subview.cs" />
<Compile Include="UI\TreeBuilder.cs" />
<Compile Include="UI\Window.cs" /> <Compile Include="UI\Window.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
...@@ -111,7 +112,7 @@ ...@@ -111,7 +112,7 @@
</ItemGroup> </ItemGroup>
<Choose> <Choose>
<When Condition="$(Buildtype) == 'Internal'"> <When Condition="$(Buildtype) == 'Internal'">
<ItemGroup > <ItemGroup>
<Compile Include="$(SolutionDir)\script\src\MetricsInitialization.cs"> <Compile Include="$(SolutionDir)\script\src\MetricsInitialization.cs">
<Link>Metrics\MetricsInitialization.cs</Link> <Link>Metrics\MetricsInitialization.cs</Link>
</Compile> </Compile>
......
...@@ -109,135 +109,11 @@ namespace GitHub.Unity ...@@ -109,135 +109,11 @@ namespace GitHub.Unity
return; return;
} }
// Remove what got nuked tree = TreeBuilder.BuildTree4(newEntries, entries, entryCommitTargets, foldedTreeEntries, stateChangeCallback);
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(); OnCommitTreeChange();
} }
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);
}
}
private void TreeNode(FileTreeNode node) private void TreeNode(FileTreeNode node)
{ {
GUILayout.Space(Styles.TreeVerticalSpacing); GUILayout.Space(Styles.TreeVerticalSpacing);
...@@ -330,7 +206,7 @@ namespace GitHub.Unity ...@@ -330,7 +206,7 @@ namespace GitHub.Unity
if (Event.current.type == EventType.Repaint) if (Event.current.type == EventType.Repaint)
{ {
var icon = node.Icon ?? (isFolder ? Styles.FolderIcon : Styles.DefaultAssetIcon); var icon = (Texture) node.Icon ?? (isFolder ? Styles.FolderIcon : Styles.DefaultAssetIcon);
if (icon != null) if (icon != null)
{ {
GUI.DrawTexture(iconRect, GUI.DrawTexture(iconRect,
...@@ -411,147 +287,147 @@ namespace GitHub.Unity ...@@ -411,147 +287,147 @@ namespace GitHub.Unity
{ {
get { return entryCommitTargets; } get { return entryCommitTargets; }
} }
}
private enum CommitState class FileTreeNode
{
private readonly Action<FileTreeNode> stateChangeCallback;
private List<FileTreeNode> children;
private string path;
private CommitState state;
public object Icon;
public string Label;
public bool Open = true;
public string RepositoryPath;
public GitCommitTarget Target { get; set; }
public FileTreeNode(Action<FileTreeNode> stateChangeCallback)
{ {
None, this.stateChangeCallback = stateChangeCallback;
Some, children = new List<FileTreeNode>();
All
} }
private class FileTreeNode public FileTreeNode(string path, Action<FileTreeNode> stateChangeCallback)
{ {
private readonly Action<FileTreeNode> stateChangeCallback; this.stateChangeCallback = stateChangeCallback;
private List<FileTreeNode> children; this.path = path ?? "";
private string path; Label = this.path;
private CommitState state; children = new List<FileTreeNode>();
}
public Texture Icon;
public string Label;
public bool Open = true;
public string RepositoryPath;
public GitCommitTarget Target { get; set; }
public FileTreeNode(Action<FileTreeNode> stateChangeCallback)
{
this.stateChangeCallback = stateChangeCallback;
children = new List<FileTreeNode>();
}
public FileTreeNode(string path, Action<FileTreeNode> stateChangeCallback) public FileTreeNode Add(FileTreeNode child)
{ {
this.stateChangeCallback = stateChangeCallback; children.Add(child);
this.path = path ?? ""; return child;
Label = this.path; }
children = new List<FileTreeNode>();
}
public FileTreeNode Add(FileTreeNode child) public CommitState State
{
get
{ {
children.Add(child); if (children == null)
return child; return state;
}
public CommitState State var commitState = CommitState.None;
{ if (Target != null)
get
{ {
if (children == null) commitState = Target.All ? CommitState.All : Target.Any ? CommitState.Some : CommitState.None;
return state; if (!children.Any())
var commitState = CommitState.None;
if (Target != null)
{ {
commitState = Target.All ? CommitState.All : Target.Any ? CommitState.Some : CommitState.None; state = commitState;
if (!children.Any()) return state;
{
state = commitState;
return state;
}
} }
}
var allCount = children.Count(c => c.State == CommitState.All); var allCount = children.Count(c => c.State == CommitState.All);
if (allCount == children.Count && (commitState == CommitState.All || Target == null)) if (allCount == children.Count && (commitState == CommitState.All || Target == null))
{ {
state = CommitState.All; state = CommitState.All;
return state; return state;
} }
if (allCount > 0 || commitState == CommitState.Some) if (allCount > 0 || commitState == CommitState.Some)
{ {
state = CommitState.Some; state = CommitState.Some;
return state; return state;
} }
var someCount = children.Count(c => c.State == CommitState.Some); var someCount = children.Count(c => c.State == CommitState.Some);
if (someCount > 0 || commitState == CommitState.Some) if (someCount > 0 || commitState == CommitState.Some)
{ {
state = CommitState.Some; state = CommitState.Some;
return state;
}
state = CommitState.None;
return state; return state;
} }
state = CommitState.None;
return state;
}
set set
{
if (value == state)
{ {
if (value == state) return;
}
if (Target != null)
{
if (value == CommitState.None)
{ {
return; Target.Clear();
} }
else if (value == CommitState.All)
if (Target != null)
{ {
if (value == CommitState.None) Target.All = true;
{
Target.Clear();
}
else if (value == CommitState.All)
{
Target.All = true;
}
} }
}
state = value; state = value;
stateChangeCallback.SafeInvoke(this); stateChangeCallback.SafeInvoke(this);
if (children == null) if (children == null)
{ {
return; return;
} }
for (var index = 0; index < children.Count; ++index) for (var index = 0; index < children.Count; ++index)
{ {
children[index].State = value; children[index].State = value;
}
} }
} }
}
public string Path public string Path
{ {
get { return path; } get { return path; }
} }
public IEnumerable<FileTreeNode> Children public IEnumerable<FileTreeNode> Children
{ {
get { get {
if (children == null) if (children == null)
children = new List<FileTreeNode>(); children = new List<FileTreeNode>();
return children; return children;
}
} }
}
private ILogging logger; private ILogging logger;
protected ILogging Logger protected ILogging Logger
{
get
{ {
get if (logger == null)
{ logger = Logging.GetLogger(GetType());
if (logger == null) return logger;
logger = Logging.GetLogger(GetType());
return logger;
}
} }
} }
} }
enum CommitState
{
None,
Some,
All
}
} }
using System;
using System.Collections.Generic;
using System.Linq;
using GitHub.Unity;
using UnityEditor;
static internal class TreeBuilder
{
internal static void BuildTree(FileTreeNode parent, FileTreeNode node, List<string> foldedTreeEntries1, Action<FileTreeNode> stateChangeCallback1)
{
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 = !foldedTreeEntries1.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, foldedTreeEntries1, stateChangeCallback1);
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, stateChangeCallback1) { RepositoryPath = p }), node, foldedTreeEntries1, stateChangeCallback1);
}
}
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, foldedTreeEntries1, stateChangeCallback1);
break;
}
}
if (!found)
{
parent.Add(node);
}
}
// Not inside a folder - just add this node right here
else
{
parent.Add(node);
}
}
internal static FileTreeNode BuildTree3(List<GitStatusEntry> gitStatusEntries, Action<FileTreeNode> stateChangeCallback1, List<GitCommitTarget> entryCommitTargets, List<string> foldedTreeEntries1)
{
// 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
var tree = new FileTreeNode(FileSystemHelpers.FindCommonPath(gitStatusEntries.Select(e => e.Path)), stateChangeCallback1);
tree.RepositoryPath = tree.Path;
for (var index = 0; index < gitStatusEntries.Count; index++)
{
GitStatusEntry gitStatusEntry = gitStatusEntries[index];
var entryPath = gitStatusEntry.Path.ToNPath();
if (entryPath.IsChildOf(tree.Path)) entryPath = entryPath.RelativeTo(tree.Path.ToNPath());
var node = new FileTreeNode(entryPath, stateChangeCallback1) { Target = entryCommitTargets[index] };
if (!String.IsNullOrEmpty(gitStatusEntry.ProjectPath))
{
node.Icon = AssetDatabase.GetCachedIcon(gitStatusEntry.ProjectPath);
}
TreeBuilder.BuildTree(tree, node, foldedTreeEntries1, stateChangeCallback1);
}
return tree;
}
internal static FileTreeNode BuildTree4(IList<GitStatusEntry> newEntries, List<GitStatusEntry> gitStatusEntries, List<GitCommitTarget> gitCommitTargets, List<string> foldedTreeEntries1, Action<FileTreeNode> stateChangeCallback1)
{
// Remove what got nuked
for (var index = 0; index < gitStatusEntries.Count;)
{
if (!newEntries.Contains(gitStatusEntries[index]))
{
gitStatusEntries.RemoveAt(index);
gitCommitTargets.RemoveAt(index);
}
else
{
index++;
}
}
// Remove folding state of nuked items
for (var index = 0; index < foldedTreeEntries1.Count;)
{
if (!newEntries.Any(e => e.Path.IndexOf(foldedTreeEntries1[index]) == 0))
{
foldedTreeEntries1.RemoveAt(index);
}
else
{
index++;
}
}
// Add new stuff
for (var index = 0; index < newEntries.Count; ++index)
{
var entry = newEntries[index];
if (!gitStatusEntries.Contains(entry))
{
gitStatusEntries.Add(entry);
gitCommitTargets.Add(new GitCommitTarget());
}
}
return TreeBuilder.BuildTree3(gitStatusEntries, stateChangeCallback1, gitCommitTargets, foldedTreeEntries1);
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment