// ----------------------------------------------------------------------- // // Copyright 2015 MIT Licence. See licence.md for more information. // // ----------------------------------------------------------------------- namespace Perspex.Controls.Generators { using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reactive.Subjects; using Perspex.Controls.Templates; /// /// Creates containers for tree items and maintains a list of created containers. /// /// The type of the container. public class TreeItemContainerGenerator : ITreeItemContainerGenerator where T : TreeViewItem, new() { private Dictionary containers = new Dictionary(); private Subject containersInitialized = new Subject(); /// /// Initializes a new instance of the class. /// /// The owner control. public TreeItemContainerGenerator(IControl owner) { this.Owner = owner; } /// /// Signalled whenever new containers are initialized. /// public IObservable ContainersInitialized => this.containersInitialized; /// /// Gets the owner control. /// public IControl Owner { get; } /// /// Creates container controls for a collection of items. /// /// /// The index of the first item of the data in the containing collection. /// /// The items. /// An optional item template. /// The created container controls. public IList CreateContainers(int startingIndex, IEnumerable items, IDataTemplate itemTemplate) { Contract.Requires(items != null); int index = startingIndex; var result = new List(); foreach (var item in items) { var container = this.CreateContainer(item, itemTemplate); this.containers.Add(item, container); result.Add(container); } this.containersInitialized.OnNext(new ItemContainers(startingIndex, result)); return result.Where(x => x != null).ToList(); } /// /// Removes a set of created containers from the index and returns the removed controls. /// /// /// The index of the first item of the data in the containing collection. /// /// The items. /// The removed controls. public IList RemoveContainers(int startingIndex, IEnumerable items) { var result = new List(); foreach (var item in items) { T container; if (this.containers.TryGetValue(item, out container)) { this.Remove(container, result); } } return result; } /// /// Clears the created containers from the index and returns the removed controls. /// /// The removed controls. public IList ClearContainers() { throw new NotImplementedException(); } /// /// Gets the container control representing the item with the specified index. /// /// The index. /// The container or null if no container created. public IControl ContainerFromIndex(int index) { throw new NotImplementedException(); } /// /// Gets the index of the specified container control. /// /// The container. /// The index of the container or -1 if not found. public int IndexFromContainer(IControl container) { throw new NotImplementedException(); } /// /// Gets all of the generated container controls. /// /// The containers. public IEnumerable GetAllContainers() { return this.containers.Values; } /// /// Gets the item that is contained by the specified container. /// /// The container. /// The item. public object ItemFromContainer(IControl container) { return container.DataContext; } /// /// Gets the container for the specified item /// /// The item. /// The container. public IControl ContainerFromItem(object item) { T result; this.containers.TryGetValue(item, out result); return result; } /// /// Creates the container for an item. /// /// The item. /// An optional item template. /// The created container control. protected virtual T CreateContainer(object item, IDataTemplate itemTemplate) { T result = item as T; if (result == null) { var template = this.GetTreeDataTemplate(item); result = new T { Header = template.Build(item), Items = template.ItemsSelector(item), IsExpanded = template.IsExpanded(item), DataContext = item, }; } return result; } /// /// Gets the data template for the specified item. /// /// The item. /// The template. private ITreeDataTemplate GetTreeDataTemplate(object item) { IDataTemplate template = this.Owner.FindDataTemplate(item); if (template == null) { template = DataTemplate.Default; } var treeTemplate = template as ITreeDataTemplate; if (treeTemplate == null) { treeTemplate = new TreeDataTemplate(typeof(object), template.Build, x => null); } return treeTemplate; } private void Remove(T container, IList removed) { if (container.Items != null) { foreach (var childItem in container.Items) { T childContainer; if (this.containers.TryGetValue(childItem, out childContainer)) { this.Remove(childContainer, removed); } } } // TODO: Dual index. var i = this.containers.FirstOrDefault(x => x.Value == container); if (i.Key != null) { this.containers.Remove(i.Key); } } } }