public ThreadTable(TreeViewState state, MultiColumnHeader multicolumnHeader, List <string> threadNames, List <string> threadUINames, ThreadSelection threadSelection) : base(state, multicolumnHeader) { StateChanged = false; m_AllThreadIdentifier = new ThreadIdentifier(); m_AllThreadIdentifier.SetName("All"); m_AllThreadIdentifier.SetAll(); Assert.AreEqual(m_SortOptions.Length, Enum.GetValues(typeof(MyColumns)).Length, "Ensure number of sort options are in sync with number of MyColumns enum values"); // Custom setup rowHeight = kRowHeights; showAlternatingRowBackgrounds = true; columnIndexForTreeFoldouts = (int)(MyColumns.GroupName); showBorder = true; customFoldoutYOffset = (kRowHeights - EditorGUIUtility.singleLineHeight) * 0.5f; // center foldout in the row since we also center content. See RowGUI // extraSpaceBeforeIconAndLabel = 0; multicolumnHeader.sortingChanged += OnSortingChanged; multicolumnHeader.visibleColumnsChanged += OnVisibleColumnsChanged; m_ThreadNames = threadNames; m_ThreadUINames = threadUINames; m_ThreadSelection = new ThreadSelection(threadSelection); #if UNITY_2018_3_OR_NEWER this.foldoutOverride += DoFoldout; #endif Reload(); }
public void SetGroup(string groupName) { groups.Clear(); selection.Clear(); ThreadIdentifier allThreadSelection = new ThreadIdentifier(groupName, ThreadIdentifier.kAll); groups.Add(allThreadSelection.threadNameWithIndex); }
public void SetAll() { groups.Clear(); selection.Clear(); ThreadIdentifier allThreadSelection = new ThreadIdentifier("All", ThreadIdentifier.kAll); groups.Add(allThreadSelection.threadNameWithIndex); }
protected override TreeViewItem BuildRoot() { int idForHiddenRoot = -1; int depthForHiddenRoot = -1; ProfileTreeViewItem root = new ProfileTreeViewItem(idForHiddenRoot, depthForHiddenRoot, "root", null); int depth = 0; var top = new ThreadTreeViewItem(-1, depth, m_AllThreadIdentifier.name, m_AllThreadIdentifier); root.AddChild(top); var expandList = new List <int>() { -1 }; string lastThreadName = ""; TreeViewItem node = root; for (int index = 0; index < m_ThreadNames.Count; ++index) { var threadNameWithIndex = m_ThreadNames[index]; if (threadNameWithIndex == m_AllThreadIdentifier.threadNameWithIndex) { continue; } var threadIdentifier = new ThreadIdentifier(threadNameWithIndex); var item = new ThreadTreeViewItem(index, depth, m_ThreadUINames[index], threadIdentifier); if (threadIdentifier.name != lastThreadName) { // New threads at root node = top; depth = 0; } node.AddChild(item); if (threadIdentifier.name != lastThreadName) { // Extra instances hang of the parent lastThreadName = threadIdentifier.name; node = item; depth = 1; } } SetExpanded(expandList); SetupDepthsFromParentsAndChildren(root); return(root); }
protected int GetChildCount(ThreadIdentifier selectedThreadIdentifier, out int selected) { int count = 0; int selectedCount = 0; if (selectedThreadIdentifier.index == ThreadIdentifier.kAll) { if (selectedThreadIdentifier.name == "All") { for (int index = 0; index < m_ThreadNames.Count; ++index) { var threadNameWithIndex = m_ThreadNames[index]; var threadIdentifier = new ThreadIdentifier(threadNameWithIndex); if (threadIdentifier.index != ThreadIdentifier.kAll) { count++; if (m_ThreadSelection.selection.Contains(threadNameWithIndex)) { selectedCount++; } } } } else { for (int index = 0; index < m_ThreadNames.Count; ++index) { var threadNameWithIndex = m_ThreadNames[index]; var threadIdentifier = new ThreadIdentifier(threadNameWithIndex); if (selectedThreadIdentifier.name == threadIdentifier.name && threadIdentifier.index != ThreadIdentifier.kAll) { count++; if (m_ThreadSelection.selection.Contains(threadNameWithIndex)) { selectedCount++; } } } } } selected = selectedCount; return(count); }
void CellGUI(Rect cellRect, ThreadTreeViewItem item, MyColumns column, ref RowGUIArgs args) { // Center cell rect vertically (makes it easier to place controls, icons etc in the cells) CenterRectUsingSingleLineHeight(ref cellRect); switch (column) { case MyColumns.ThreadName: { args.rowRect = cellRect; // base.RowGUI(args); // Required to show tree indenting // Draw manually to keep indenting by add a tooltip Rect rect = cellRect; if (Event.current.rawType == EventType.Repaint) { int selectedChildren; int childCount = GetChildCount(item.threadIdentifier, out selectedChildren); string text; string tooltip; string fullThreadName = item.threadIdentifier.name; string groupName = GetItemGroupName(item); // string threadName = ProfileData.GetThreadNameWithoutGroup(fullThreadName, out groupName); if (childCount <= 1) { text = item.displayName; tooltip = (groupName == "") ? text : string.Format("{0}\n{1}", text, groupName); } else if (selectedChildren != childCount) { text = string.Format("{0} ({1} of {2})", fullThreadName, selectedChildren, childCount); tooltip = (groupName == "") ? text : string.Format("{0}\n{1}", text, groupName); } else { text = string.Format("{0} (All)", fullThreadName); tooltip = (groupName == "") ? text : string.Format("{0}\n{1}", text, groupName); } var content = new GUIContent(text, tooltip); if (activeLineStyle == null) { // activeLineStyle = DefaultStyles.boldLabel; activeLineStyle = new GUIStyle(DefaultStyles.label); activeLineStyle.normal.textColor = DefaultStyles.boldLabel.onActive.textColor; } // The rect is assumed indented and sized after the content when pinging float indent = GetContentIndent(item) + extraSpaceBeforeIconAndLabel; rect.xMin += indent; int iconRectWidth = 16; int kSpaceBetweenIconAndText = 2; // Draw icon Rect iconRect = rect; iconRect.width = iconRectWidth; // iconRect.x += 7f; Texture icon = args.item.icon; if (icon != null) { GUI.DrawTexture(iconRect, icon, ScaleMode.ScaleToFit); } rect.xMin += icon == null ? 0 : iconRectWidth + kSpaceBetweenIconAndText; //bool mouseOver = rect.Contains(Event.current.mousePosition); //DefaultStyles.label.Draw(rect, content, mouseOver, false, args.selected, args.focused); // Must use this call to draw tooltip EditorGUI.LabelField(rect, content, args.selected ? activeLineStyle : DefaultStyles.label); } } break; case MyColumns.GroupName: { string groupName = GetItemGroupName(item); var content = new GUIContent(groupName, groupName); EditorGUI.LabelField(cellRect, content); } break; case MyColumns.State: bool oldState = ThreadSelected(item.threadIdentifier); bool newState = EditorGUI.Toggle(cellRect, oldState); if (newState != oldState) { if (item.threadIdentifier.threadNameWithIndex == m_AllThreadIdentifier.threadNameWithIndex) { // Record active groups m_ThreadSelection.groups.Clear(); if (newState) { if (!m_ThreadSelection.groups.Contains(item.threadIdentifier.threadNameWithIndex)) { m_ThreadSelection.groups.Add(item.threadIdentifier.threadNameWithIndex); } } // Update selection m_ThreadSelection.selection.Clear(); if (newState) { foreach (string threadNameWithIndex in m_ThreadNames) { if (threadNameWithIndex != m_AllThreadIdentifier.threadNameWithIndex) { var threadIdentifier = new ThreadIdentifier(threadNameWithIndex); if (threadIdentifier.index != ThreadIdentifier.kAll) { m_ThreadSelection.selection.Add(threadNameWithIndex); } } } } } else if (item.threadIdentifier.index == ThreadIdentifier.kAll) { // Record active groups if (newState) { if (!m_ThreadSelection.groups.Contains(item.threadIdentifier.threadNameWithIndex)) { m_ThreadSelection.groups.Add(item.threadIdentifier.threadNameWithIndex); } } else { m_ThreadSelection.groups.Remove(item.threadIdentifier.threadNameWithIndex); // When turning off a sub group, turn of the 'all' group too m_ThreadSelection.groups.Remove(m_AllThreadIdentifier.threadNameWithIndex); } // Update selection if (newState) { foreach (string threadNameWithIndex in m_ThreadNames) { var threadIdentifier = new ThreadIdentifier(threadNameWithIndex); if (threadIdentifier.name == item.threadIdentifier.name && threadIdentifier.index != ThreadIdentifier.kAll) { if (!m_ThreadSelection.selection.Contains(threadNameWithIndex)) { m_ThreadSelection.selection.Add(threadNameWithIndex); } } } } else { var removeSelection = new List <string>(); foreach (string threadNameWithIndex in m_ThreadSelection.selection) { var threadIdentifier = new ThreadIdentifier(threadNameWithIndex); if (threadIdentifier.name == item.threadIdentifier.name && threadIdentifier.index != ThreadIdentifier.kAll) { removeSelection.Add(threadNameWithIndex); } } foreach (string threadNameWithIndex in removeSelection) { m_ThreadSelection.selection.Remove(threadNameWithIndex); } } } else { if (newState) { m_ThreadSelection.selection.Add(item.threadIdentifier.threadNameWithIndex); } else { m_ThreadSelection.selection.Remove(item.threadIdentifier.threadNameWithIndex); // Turn off any group its in too var groupIdentifier = new ThreadIdentifier(item.threadIdentifier); groupIdentifier.SetAll(); m_ThreadSelection.groups.Remove(groupIdentifier.threadNameWithIndex); // Turn of the 'all' group too m_ThreadSelection.groups.Remove(m_AllThreadIdentifier.threadNameWithIndex); } } } break; } }
bool ThreadSelected(ThreadIdentifier selectedThreadIdentifier) { if (ProfileAnalyzer.MatchThreadFilter(selectedThreadIdentifier.threadNameWithIndex, m_ThreadSelection.selection)) { return(true); } // If querying the 'All' filter then check if all selected if (selectedThreadIdentifier.threadNameWithIndex == m_AllThreadIdentifier.threadNameWithIndex) { // Check all threads without All in the name are selected foreach (var threadNameWithIndex in m_ThreadNames) { var threadIdentifier = new ThreadIdentifier(threadNameWithIndex); if (threadIdentifier.index == ThreadIdentifier.kAll || threadIdentifier.index == ThreadIdentifier.kSingle) { continue; } if (!m_ThreadSelection.selection.Contains(threadNameWithIndex)) { return(false); } } return(true); } // Need to check 'all' and thread group all. if (selectedThreadIdentifier.index == ThreadIdentifier.kAll) { // Count all threads that match this thread group int count = 0; foreach (var threadNameWithIndex in m_ThreadNames) { var threadIdentifier = new ThreadIdentifier(threadNameWithIndex); if (threadIdentifier.index == ThreadIdentifier.kAll || threadIdentifier.index == ThreadIdentifier.kSingle) { continue; } if (selectedThreadIdentifier.name != threadIdentifier.name) { continue; } count++; } // Count all the threads we have selected that match this thread group int selectedCount = 0; foreach (var threadNameWithIndex in m_ThreadSelection.selection) { var threadIdentifier = new ThreadIdentifier(threadNameWithIndex); if (selectedThreadIdentifier.name != threadIdentifier.name) { continue; } if (threadIdentifier.index > count) { continue; } selectedCount++; } if (count == selectedCount) { return(true); } } return(false); }
public ThreadTreeViewItem(int id, int depth, string displayName, ThreadIdentifier threadIdentifier) : base(id, depth, displayName) { this.threadIdentifier = threadIdentifier; }
void CellGUI(Rect cellRect, ThreadTreeViewItem item, MyColumns column, ref RowGUIArgs args) { // Center cell rect vertically (makes it easier to place controls, icons etc in the cells) CenterRectUsingSingleLineHeight(ref cellRect); switch (column) { case MyColumns.ThreadName: { args.rowRect = cellRect; // base.RowGUI(args); // Required to show tree indenting // Draw manually to keep indenting while add a tooltip Rect rect = cellRect; if (Event.current.rawType == EventType.Repaint) { string text; string tooltip; GetThreadTreeViewItemInfo(item, out text, out tooltip); var content = new GUIContent(text, tooltip); if (activeLineStyle == null) { // activeLineStyle = DefaultStyles.boldLabel; activeLineStyle = new GUIStyle(DefaultStyles.label); activeLineStyle.normal.textColor = DefaultStyles.boldLabel.onActive.textColor; } // rect = DrawIndent(rect, item, ref args); //bool mouseOver = rect.Contains(Event.current.mousePosition); //DefaultStyles.label.Draw(rect, content, mouseOver, false, args.selected, args.focused); // Must use this call to draw tooltip EditorGUI.LabelField(rect, content, args.selected ? activeLineStyle : DefaultStyles.label); } } break; case MyColumns.GroupName: { Rect rect = cellRect; if (Event.current.rawType == EventType.Repaint) { rect = DrawIndent(rect, item, ref args); string groupName = GetItemGroupName(item); var content = new GUIContent(groupName, groupName); EditorGUI.LabelField(rect, content); } } break; case MyColumns.State: bool oldState = GetThreadSelectedState(item.threadIdentifier) == ThreadSelected.Selected; bool newState = EditorGUI.Toggle(cellRect, oldState); if (newState != oldState) { if (item.threadIdentifier.threadNameWithIndex == m_AllThreadIdentifier.threadNameWithIndex) { // Record active groups m_ThreadSelection.groups.Clear(); if (newState) { if (!m_ThreadSelection.groups.Contains(item.threadIdentifier.threadNameWithIndex)) { m_ThreadSelection.groups.Add(item.threadIdentifier.threadNameWithIndex); } } // Update selection m_ThreadSelection.selection.Clear(); if (newState) { foreach (string threadNameWithIndex in m_ThreadNames) { if (threadNameWithIndex != m_AllThreadIdentifier.threadNameWithIndex) { var threadIdentifier = new ThreadIdentifier(threadNameWithIndex); if (threadIdentifier.index != ThreadIdentifier.kAll) { m_ThreadSelection.selection.Add(threadNameWithIndex); } } } } } else if (item.threadIdentifier.index == ThreadIdentifier.kAll) { // Record active groups if (newState) { if (!m_ThreadSelection.groups.Contains(item.threadIdentifier.threadNameWithIndex)) { m_ThreadSelection.groups.Add(item.threadIdentifier.threadNameWithIndex); } } else { m_ThreadSelection.groups.Remove(item.threadIdentifier.threadNameWithIndex); // When turning off a sub group, turn of the 'all' group too m_ThreadSelection.groups.Remove(m_AllThreadIdentifier.threadNameWithIndex); } // Update selection if (newState) { foreach (string threadNameWithIndex in m_ThreadNames) { var threadIdentifier = new ThreadIdentifier(threadNameWithIndex); if (threadIdentifier.name == item.threadIdentifier.name && threadIdentifier.index != ThreadIdentifier.kAll) { if (!m_ThreadSelection.selection.Contains(threadNameWithIndex)) { m_ThreadSelection.selection.Add(threadNameWithIndex); } } } } else { var removeSelection = new List <string>(); foreach (string threadNameWithIndex in m_ThreadSelection.selection) { var threadIdentifier = new ThreadIdentifier(threadNameWithIndex); if (threadIdentifier.name == item.threadIdentifier.name && threadIdentifier.index != ThreadIdentifier.kAll) { removeSelection.Add(threadNameWithIndex); } } foreach (string threadNameWithIndex in removeSelection) { m_ThreadSelection.selection.Remove(threadNameWithIndex); } } } else { if (newState) { m_ThreadSelection.selection.Add(item.threadIdentifier.threadNameWithIndex); } else { m_ThreadSelection.selection.Remove(item.threadIdentifier.threadNameWithIndex); // Turn off any group its in too var groupIdentifier = new ThreadIdentifier(item.threadIdentifier); groupIdentifier.SetAll(); m_ThreadSelection.groups.Remove(groupIdentifier.threadNameWithIndex); // Turn of the 'all' group too m_ThreadSelection.groups.Remove(m_AllThreadIdentifier.threadNameWithIndex); } } StateChanged = true; // Re-sort SortIfNeeded(GetRows()); } break; } }
/// <summary>Initialise ThreadIdentifier from another ThreadIdentifier</summary> /// <param name="threadIdentifier">The other ThreadIdentifier</param> public ThreadIdentifier(ThreadIdentifier threadIdentifier) { name = threadIdentifier.name; index = threadIdentifier.index; threadNameWithIndex = threadIdentifier.threadNameWithIndex; }