/// <summary> /// Constructor for an actual valid item. /// </summary> /// <param name="i"></param> public ItemTreeElement(ItemTreeElement itemParent, ItemTreeElement depencencyParent, IItem i, bool searchable = true) { CategoryParent = itemParent; SetParent = depencencyParent; Item = i; Searchable = searchable; Children = new ObservableCollection <ItemTreeElement>(); }
/// <summary> /// Constructor for an empty header cateogory /// </summary> /// <param name="name"></param> /// <param name="children"></param> public ItemTreeElement(ItemTreeElement itemParent, ItemTreeElement depencencyParent, string name, bool searchable = false) { CategoryParent = itemParent; SetParent = depencencyParent; _backupName = name; Searchable = searchable; Children = new ObservableCollection <ItemTreeElement>(); }
private async Task <List <IItem> > BuildCategoryTree() { foreach (var kv in _categoryStructure) { // Make the top level node. var e = new ItemTreeElement(null, null, kv.Key); foreach (var secondary in kv.Value) { var e2 = new ItemTreeElement(e, null, secondary); e.Children.Add(e2); } CategoryElements.Add(e); } var gameDir = XivCache.GameInfo.GameDirectory; var language = XivCache.GameInfo.GameLanguage; var items = await XivCache.GetFullItemList(); foreach (var item in items) { // Find what node we should be attached to. ItemTreeElement catParent = null; var topLevel = CategoryElements.FirstOrDefault(x => x.DisplayName == item.PrimaryCategory); if (topLevel == null) { topLevel = new ItemTreeElement(null, null, item.PrimaryCategory); CategoryElements.Add(topLevel); } var secondLevel = topLevel.Children.FirstOrDefault(x => x.DisplayName == item.SecondaryCategory); if (secondLevel == null) { if (item.SecondaryCategory == item.Name) { // These are a special snowflake case. secondLevel = topLevel; } else { secondLevel = new ItemTreeElement(topLevel, null, item.SecondaryCategory); topLevel.Children.Add(secondLevel); } } catParent = secondLevel; ItemTreeElement setParent = null; // Try and see if we have a valid root parent to attach to in the sets tree. try { var type = item.GetType(); // Perf. Much faster to just not test those types at all, as we know they won't resolve. if (type != typeof(XivUi)) { var itemRoot = item.GetRootInfo(); if (itemRoot.PrimaryType != XivItemType.unknown) { var st = itemRoot.ToString(); if (DependencyRootNodes.ContainsKey(st)) { setParent = DependencyRootNodes[st]; } } } } catch (Exception ex) { throw; } var e2 = new ItemTreeElement(catParent, setParent, item); if (catParent != null) { catParent.Children.Add(e2); } if (setParent != null) { setParent.Children.Add(e2); } } return(items); }
/// <summary> /// This should only really be called directly if the control was created with DeferLoading set to true. /// </summary> /// <returns></returns> public async Task LoadItems() { if (_READY) { SearchTimer.Stop(); SearchTimer.Dispose(); ClearSelection(); } if (LockUiFunction != null) { await LockUiFunction(UIStrings.Loading_Items, null, this); } // Pump us into another thread so the UI stays nice and fresh. await Task.Run(async() => { CategoryElements = new ObservableCollection <ItemTreeElement>(); SetElements = new ObservableCollection <ItemTreeElement>(); DependencyRootNodes = new Dictionary <string, ItemTreeElement>(); try { // Gotta build set tree first, so the items from the item list can latch onto the nodes there. BuildSetTree(); await BuildCategoryTree(); } catch (Exception ex) { FlexibleMessageBox.Show("An error occurred while loading the item list.\n" + ex.Message, "Item List Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Warning); return; } var toAdd = new List <(ItemTreeElement parent, ItemTreeElement child)>(); foreach (var kv in DependencyRootNodes) { // This dependency root had no EXD-Items associated with it. // Gotta make a generic item for it. if (kv.Value.Children.Count == 0) { // See if we can actually turn this root into a fully fledged item. try { var root = await XivCache.GetFirstRoot(kv.Key); if (root != null) { // If we can, add it into the list. var item = root.ToRawItem(); var e = new ItemTreeElement(null, kv.Value, item); toAdd.Add((kv.Value, e)); } else { var e = new ItemTreeElement(null, kv.Value, "[Unsupported]"); toAdd.Add((kv.Value, e)); } } catch (Exception ex) { throw; } } } // Loop back through to add the new items, so we're not affecting the previous iteration. foreach (var tup in toAdd) { tup.parent.Children.Add(tup.child); } }); var view = (CollectionView)CollectionViewSource.GetDefaultView(CategoryElements); view.Filter = SearchFilter; view = (CollectionView)CollectionViewSource.GetDefaultView(SetElements); view.Filter = SearchFilter; SearchTimer = new Timer(300); SearchTimer.Elapsed += Search; CategoryTree.ItemsSource = CategoryElements; SetTree.ItemsSource = SetElements; _READY = true; Search(this, null); if (UnlockUiFunction != null) { await UnlockUiFunction(this); } if (ItemsLoaded != null) { ItemsLoaded.Invoke(this, null); } }
/// <summary> /// Builds the set tree from XivCache.GetAllRoots(). /// </summary> private void BuildSetTree() { // First we must generate all the dependency root nodes. var roots = XivCache.GetAllRootsDictionary(); var primaryTypeGroups = new Dictionary <XivItemType, ItemTreeElement>(); var primaryIdGroups = new Dictionary <XivItemType, Dictionary <int, ItemTreeElement> >(); var secondaryTypeGroups = new Dictionary <XivItemType, Dictionary <int, Dictionary <XivItemType, ItemTreeElement> > >(); var secondaryIdGroups = new Dictionary <XivItemType, Dictionary <int, Dictionary <XivItemType, Dictionary <int, ItemTreeElement> > > >(); // This giant for loop monstrosity builds the actual root nodes based on the dictionaries returned by XivCache.GetAllRoots() foreach (var kvPrimaryType in roots) { var primaryType = kvPrimaryType.Key; // Create the new node. primaryTypeGroups.Add(primaryType, new ItemTreeElement(null, null, XivItemTypes.NiceNames[primaryType], true)); // Add us to parent. SetElements.Add(primaryTypeGroups[primaryType]); // Ensure the other lists have our primary type reference. primaryIdGroups.Add(primaryType, new Dictionary <int, ItemTreeElement>()); secondaryTypeGroups.Add(primaryType, new Dictionary <int, Dictionary <XivItemType, ItemTreeElement> >()); secondaryIdGroups.Add(primaryType, new Dictionary <int, Dictionary <XivItemType, Dictionary <int, ItemTreeElement> > >()); foreach (var kvPrimaryId in kvPrimaryType.Value) { var primaryId = kvPrimaryId.Key; // Create the new node. primaryIdGroups[primaryType].Add(primaryId, new ItemTreeElement(null, primaryTypeGroups[primaryType], XivItemTypes.GetSystemPrefix(primaryType) + primaryId.ToString().PadLeft(4, '0'), true)); // Add us to parent. primaryTypeGroups[primaryType].Children.Add(primaryIdGroups[primaryType][primaryId]); // Ensure the other lists have our primary id reference. secondaryTypeGroups[primaryType].Add(primaryId, new Dictionary <XivItemType, ItemTreeElement>()); secondaryIdGroups[primaryType].Add(primaryId, new Dictionary <XivItemType, Dictionary <int, ItemTreeElement> >()); foreach (var kvSecondaryType in kvPrimaryId.Value) { var secondaryType = kvSecondaryType.Key; if (secondaryType != XivItemType.none) { // Create the new node. secondaryTypeGroups[primaryType][primaryId].Add(secondaryType, new ItemTreeElement(null, primaryIdGroups[primaryType][primaryId], XivItemTypes.NiceNames[secondaryType], true)); // Add us to parent. primaryIdGroups[primaryType][primaryId].Children.Add(secondaryTypeGroups[primaryType][primaryId][secondaryType]); // Ensure the other lists have our secondary type reference. secondaryIdGroups[primaryType][primaryId].Add(secondaryType, new Dictionary <int, ItemTreeElement>()); } foreach (var kvSecondaryId in kvSecondaryType.Value) { var secondaryId = kvSecondaryId.Key; if (secondaryType != XivItemType.none) { // Create the new node. secondaryIdGroups[primaryType][primaryId][secondaryType].Add(secondaryId, new ItemTreeElement(null, secondaryTypeGroups[primaryType][primaryId][secondaryType], XivItemTypes.GetSystemPrefix(secondaryType) + secondaryId.ToString().PadLeft(4, '0'), true)); // Add us to parent. secondaryTypeGroups[primaryType][primaryId][secondaryType].Children.Add(secondaryIdGroups[primaryType][primaryId][secondaryType][secondaryId]); } foreach (var kvSlot in kvSecondaryId.Value) { var root = kvSlot.Value; var slotName = Mdl.SlotAbbreviationDictionary.FirstOrDefault(x => x.Value == root.Slot).Key; if (secondaryType != XivItemType.none) { // This root has no slots, just list the parent as the root element. if (String.IsNullOrWhiteSpace(slotName)) { DependencyRootNodes.Add(root.ToString(), secondaryIdGroups[primaryType][primaryId][secondaryType][secondaryId]); break; } // Create the new node. var elem = new ItemTreeElement(null, secondaryIdGroups[primaryType][primaryId][secondaryType][secondaryId], slotName); // Add us to parent. secondaryIdGroups[primaryType][primaryId][secondaryType][secondaryId].Children.Add(elem); // Save us to the primary listing so the items can list themselves under us. DependencyRootNodes.Add(root.ToString(), elem); } else { // This root has no slots, just list the parent as the root element. if (String.IsNullOrWhiteSpace(slotName)) { DependencyRootNodes.Add(root.ToString(), primaryIdGroups[primaryType][primaryId]); break; } // Create the new node. var elem = new ItemTreeElement(null, primaryIdGroups[primaryType][primaryId], slotName); // Add us to parent. primaryIdGroups[primaryType][primaryId].Children.Add(elem); // Save us to the primary listing so the items can list themselves under us. DependencyRootNodes.Add(root.ToString(), elem); } } } } } } }