/// <summary> /// Gets the initial column states. /// Note that this method itself does not actually cause any UI/column updates, /// but just computes and returns the new states. /// </summary> private static Dictionary <string, ColumnState2> GetInitialCustomColumnStates( IReadOnlyList <ColumnState> allColumnStates, ImmutableArray <AbstractCustomColumnDefinition> customColumns) { var customColumnStatesMap = new Dictionary <string, ColumnState2>(customColumns.Length); var customColumnNames = new HashSet <string>(customColumns.Select(c => c.Name)); // Compute the default visibility for each custom column. // If there is an existing column state for the custom column, flip it to be non-visible // by default at the start of FAR query. // We do so because the column will have empty values for all results for a FAR query for // certain cases such as types, literals, no references found case, etc. // It is preferable to dynamically hide an empty column for such queries, and dynamically // show the column if it has at least one non-default value. foreach (ColumnState2 columnState in allColumnStates.Where(c => customColumnNames.Contains(c.Name))) { var newColumnState = new ColumnState2(columnState.Name, isVisible: false, columnState.Width, columnState.SortPriority, columnState.DescendingSort, columnState.GroupingPriority); customColumnStatesMap.Add(columnState.Name, newColumnState); } // For the remaining custom columns with no existing column state, use the default column state. foreach (var customColumn in customColumns) { if (!customColumnStatesMap.ContainsKey(customColumn.Name)) { customColumnStatesMap.Add(customColumn.Name, customColumn.DefaultColumnState); } } return(customColumnStatesMap); }
public Reference[] GetContents(string windowCaption) { return(InvokeOnUIThread <Reference[]>(cancellationToken => { // Find the tool window var tableControl = GetFindReferencesWindow(windowCaption); // Remove all grouping var columnStates = tableControl.ColumnStates; var newColumnsStates = new List <ColumnState2>(); foreach (ColumnState2 state in columnStates) { var newState = new ColumnState2( state.Name, state.IsVisible, state.Width, state.SortPriority, state.DescendingSort, groupingPriority: 0); newColumnsStates.Add(newState); } tableControl.SetColumnStates(newColumnsStates); // Force a refresh, if necessary. This doesn't re-run the Find References or // Find Implementations operation itself, it just forces the results to be // realized in the table. var forcedUpdateResult = ThreadHelper.JoinableTaskFactory.Run(async delegate { return await tableControl.ForceUpdateAsync(); }); // Extract the basic text of the results. return forcedUpdateResult.AllEntries.Select(CreateReference).ToArray(); })); }
public async Task <ImmutableArray <ITableEntryHandle2> > GetContentsAsync(CancellationToken cancellationToken) { await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); await TestServices.Workspace.WaitForAsyncOperationsAsync(FeatureAttribute.FindReferences, cancellationToken); // Find the tool window var tableControl = await GetFindReferencesWindowAsync(cancellationToken); // Remove all grouping var columnStates = tableControl.ColumnStates; var newColumnsStates = new List <ColumnState2>(); foreach (ColumnState2 state in columnStates) { var newState = new ColumnState2( state.Name, state.IsVisible, state.Width, state.SortPriority, state.DescendingSort, groupingPriority: 0); newColumnsStates.Add(newState); } tableControl.SetColumnStates(newColumnsStates); // Force a refresh, if necessary. This doesn't re-run the Find References or // Find Implementations operation itself, it just forces the results to be // realized in the table. var forcedUpdateResult = await tableControl.ForceUpdateAsync().WithCancellation(cancellationToken); // Extract the basic text of the results. return(forcedUpdateResult.AllEntries.Cast <ITableEntryHandle2>().ToImmutableArray()); }
public static IEnumerable <ColumnState> LoadSettings(string window, IEnumerable <ColumnState> defaultColumns) { var columns = new List <Tuple <int, ColumnState> >(); using (var rootKey = VSRegistry.RegistryRoot(ProjectSystemToolsPackage.ServiceProvider, __VsLocalRegistryType.RegType_UserSettings, writable: false)) { using (var columnsSubKey = rootKey.OpenSubKey(CreateColumnsKey(window), writable: false)) { if (columnsSubKey == null) { return(defaultColumns); } foreach (var columnName in columnsSubKey.GetSubKeyNames()) { using (var columnSubKey = columnsSubKey.OpenSubKey(columnName, writable: false)) { if (columnSubKey == null) { continue; } var descendingSort = (int)columnSubKey.GetValue(ColumnSortDown, 1) != 0; var sortPriority = (int)columnSubKey.GetValue(ColumnSortPriority, 0); var groupingPriority = (int)columnSubKey.GetValue(ColumnGroupingPriority, 0); var columnOrder = (int)columnSubKey.GetValue(ColumnOrder, int.MaxValue); var visibility = (int)columnSubKey.GetValue(ColumnVisibility, 0) != 0; var width = (int)columnSubKey.GetValue(ColumnWidth, 20); var state = new ColumnState2(columnName, visibility, width, sortPriority, descendingSort, groupingPriority); columns.Add(new Tuple <int, ColumnState>(columnOrder, state)); } } } } columns.Sort((a, b) => a.Item1 - b.Item1); return(columns.Select(a => a.Item2)); }
private void UpdateCustomColumnsVisibility(ImmutableDictionary <string, ImmutableArray <string> > additionalPropertiesWithMultipleValues) { // Check if we have any custom reference data to display. // columnDefinitionManager will be null under unit test var columnDefinitionManager = TableControl.ColumnDefinitionManager; if (additionalPropertiesWithMultipleValues.Count == 0 || columnDefinitionManager == null) { return; } // Get the new column states corresponding to the custom columns to display for custom data. var newColumnStates = ArrayBuilder <ColumnState2> .GetInstance(); try { lock (Gate) { foreach (var customColumnName in additionalPropertiesWithMultipleValues.Keys) { // Get the matching custom column. var customColumnDefinition = columnDefinitionManager.GetColumnDefinition(customColumnName) as AbstractCustomColumnDefinition; if (customColumnDefinition == null) { Debug.Fail($"{nameof(SourceReferenceItem.AdditionalPropertiesWithMultipleValues)} has a key '{customColumnName}', but there is no exported '{nameof(AbstractCustomColumnDefinition)}' with this name."); continue; } // Ensure that we flip the visibility to true for the custom column. // Note that the actual UI update happens outside the lock when we // invoke "TableControl.SetColumnStates" below. ColumnState2 newColumnStateOpt = null; if (_customColumnTitleToStatesMap.TryGetValue(customColumnDefinition.Name, out var columnState)) { if (!columnState.IsVisible) { newColumnStateOpt = new ColumnState2(columnState.Name, isVisible: true, columnState.Width, columnState.SortPriority, columnState.DescendingSort, columnState.GroupingPriority); } } else { newColumnStateOpt = customColumnDefinition.DefaultColumnState; } if (newColumnStateOpt != null) { _customColumnTitleToStatesMap[customColumnDefinition.Name] = newColumnStateOpt; newColumnStates.Add(newColumnStateOpt); } } } // Update the column states if required. if (newColumnStates.Count > 0) { // SetColumnStates API forces a switch to UI thread, so it should be safe to call // from a background thread here. // Also note that we will call it only once for each new custom column to add for // each find references query - the lock above guarantees that newColumnStatesOpt is // going to be non-null only for the first result that has a non-empty column value. TableControl.SetColumnStates(newColumnStates.ToImmutable()); } } finally { newColumnStates.Free(); } }
public Reference[] GetContents(string windowCaption) { return(InvokeOnUIThread(() => { // Find the tool window var toolWindow = ((DTE2)GetDTE()).ToolWindows.GetToolWindow(windowCaption); // Dig through to get the Find References control. var toolWindowType = toolWindow.GetType(); var toolWindowControlField = toolWindowType.GetField("Control"); var toolWindowControl = toolWindowControlField.GetValue(toolWindow); // Dig further to get the results table (as opposed to the toolbar). var tableControlAndCommandTargetType = toolWindowControl.GetType(); var tableControlField = tableControlAndCommandTargetType.GetField("TableControl"); var tableControl = (IWpfTableControl2)tableControlField.GetValue(toolWindowControl); // Remove all grouping var columnStates = tableControl.ColumnStates; var newColumnsStates = new List <ColumnState2>(); foreach (ColumnState2 state in columnStates) { var newState = new ColumnState2( state.Name, state.IsVisible, state.Width, state.SortPriority, state.DescendingSort, groupingPriority: 0); newColumnsStates.Add(newState); } tableControl.SetColumnStates(newColumnsStates); // Force a refresh, if necessary. This doesn't re-run the Find References or // Find Implementations operation itself, it just forces the results to be // realized in the table. var forcedUpdateResult = ThreadHelper.JoinableTaskFactory.Run(async delegate { return await tableControl.ForceUpdateAsync(); }); // Extract the basic text of the results. return forcedUpdateResult.AllEntries.Select(handle => { handle.TryGetValue(StandardTableKeyNames.DocumentName, out string filePath); handle.TryGetValue(StandardTableKeyNames.Line, out int line); handle.TryGetValue(StandardTableKeyNames.Column, out int column); handle.TryGetValue(StandardTableKeyNames.Text, out string code); var reference = new Reference { FilePath = filePath, Line = line, Column = column, Code = code }; return reference; }).ToArray(); })); }
protected AbstractFindUsagesCustomColumnDefinition() { DefaultColumnState = new ColumnState2(Name, isVisible: false, DefaultWidth); }