protected void UpdateContextMenu(MultiSourceTreeNode[] nodes) { cmbPopupMenu.BeginInit(); // Clear the existing menu items, killing their tooltip in the process - otherwise // there would be a dangling reference and they would never go out of scope. foreach (BaseItem item in popupMenu.SubItems) { tooltip.SetSuperTooltip(item, null); } popupMenu.SubItems.Clear(); // We need some nodez biatches! if (nodes.Length == 0) { return; } Dictionary <MenuGroup, Dictionary <string, ButtonItem> > items = new Dictionary <MenuGroup, Dictionary <string, ButtonItem> >(); // Get a sorted list of groups and their child items. foreach (MultiSourceTreeNode node in nodes) { foreach (NodeInfo info in node.InfoEntries) { foreach (NodeStateSubscriber subscriber in info.Subscriptions) { if (!subscriber.Active) { continue; } // Copy the menu definitions to a temp array so they can be sorted. MenuDefinition[] defs = new MenuDefinition[subscriber.State.MenuDefinitions.Count]; subscriber.State.MenuDefinitions.Keys.CopyTo(defs, 0); Array.Sort(defs, new MenuDefinitionComparer()); foreach (MenuDefinition def in defs) { // If we have a test, run it to see if this item should be added. if (def.MenuItemTest != null) { if (!def.MenuItemTest.Invoke(node, info)) { continue; // Nope! } } // Get the group container. Dictionary <string, ButtonItem> container; if (!items.ContainsKey(def.Group)) { items.Add(def.Group, new Dictionary <string, ButtonItem>()); } container = items[def.Group]; // Create and add the menu item. ButtonItem menuItem = def.CreateMenuItem(node, tooltip); menuItem.Tag = info; // TODO: This will need to be adjusted to the plural text somehow // if more than one node is selected that contains this type. if (!container.ContainsKey(def.Text)) { container.Add(def.Text, menuItem); } } } } } // Return if we had no groups to display. if (items.Count == 0) { return; } // Now that we have all of our groups, we need to sort them by priority. List <ButtonItemGroup> sortedGroups = new List <ButtonItemGroup>(); while (items.Count > 0) { MenuGroup priorityGroup = null; foreach (MenuGroup group in items.Keys) { if (priorityGroup == null) { priorityGroup = group; } else if (group.SortingPriority > priorityGroup.SortingPriority) { priorityGroup = group; } } ButtonItem[] buttonItems = new ButtonItem[items[priorityGroup].Values.Count]; items[priorityGroup].Values.CopyTo(buttonItems, 0); ButtonItemGroup newGroup = new ButtonItemGroup(); newGroup.Group = priorityGroup; newGroup.Items = buttonItems; sortedGroups.Add(newGroup); items.Remove(priorityGroup); } // And now we can construct the actual popup menu! YAY! foreach (ButtonItemGroup group in sortedGroups) { LabelItem groupLabel = group.Group.CreateLabelItem(); popupMenu.SubItems.Add(groupLabel); popupMenu.SubItems.AddRange(group.Items); } // Final pass - remove incorrect grouping. for (int x = 0; x < popupMenu.SubItems.Count; x++) { if (x == 0) { popupMenu.SubItems[x].BeginGroup = false; } else { if (!(popupMenu.SubItems[x - 1] is ButtonItem)) { popupMenu.SubItems[x].BeginGroup = false; } } } cmbPopupMenu.EndInit(); }