/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/VisualStudio/Core/Impl/Options/AbstractOptionPageControl.cs
344 строки
13 KB
Cyrus Najmabadi
Use file scoped namespaces. (#77854)
27 мар 2025, 09:55
Не верифицирован
27 мар 2025, 09:55
98d41b8
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using Microsoft.CodeAnalysis.Options; using Microsoft.VisualStudio.LanguageServices.Implementation.Options.Converters; namespace Microsoft.VisualStudio.LanguageServices.Implementation.Options; [DesignerCategory("code")] // this must be fully qualified public abstract class AbstractOptionPageControl : UserControl { internal readonly OptionStore OptionStore; private readonly List<BindingExpressionBase> _bindingExpressions = []; private readonly List<OptionPageSearchHandler> _searchHandlers = []; private protected AbstractOptionPageControl(OptionStore optionStore) { InitializeStyles(); if (DesignerProperties.GetIsInDesignMode(this)) { return; } this.OptionStore = optionStore; } private void InitializeStyles() { var groupBoxStyle = new System.Windows.Style(typeof(GroupBox)); groupBoxStyle.Setters.Add(new Setter(GroupBox.PaddingProperty, new Thickness() { Left = 7, Right = 7, Top = 7 })); groupBoxStyle.Setters.Add(new Setter(GroupBox.MarginProperty, new Thickness() { Bottom = 3 })); groupBoxStyle.Setters.Add(new Setter(GroupBox.ForegroundProperty, new DynamicResourceExtension(SystemColors.WindowTextBrushKey))); Resources.Add(typeof(GroupBox), groupBoxStyle); var checkBoxStyle = new System.Windows.Style(typeof(CheckBox)); checkBoxStyle.Setters.Add(new Setter(CheckBox.MarginProperty, new Thickness() { Bottom = 7 })); checkBoxStyle.Setters.Add(new Setter(CheckBox.ForegroundProperty, new DynamicResourceExtension(SystemColors.WindowTextBrushKey))); Resources.Add(typeof(CheckBox), checkBoxStyle); var textBoxStyle = new System.Windows.Style(typeof(TextBox)); textBoxStyle.Setters.Add(new Setter(TextBox.MarginProperty, new Thickness() { Left = 7, Right = 7 })); textBoxStyle.Setters.Add(new Setter(TextBox.ForegroundProperty, new DynamicResourceExtension(SystemColors.WindowTextBrushKey))); Resources.Add(typeof(TextBox), textBoxStyle); var radioButtonStyle = new System.Windows.Style(typeof(RadioButton)); radioButtonStyle.Setters.Add(new Setter(RadioButton.MarginProperty, new Thickness() { Bottom = 7 })); radioButtonStyle.Setters.Add(new Setter(RadioButton.ForegroundProperty, new DynamicResourceExtension(SystemColors.WindowTextBrushKey))); Resources.Add(typeof(RadioButton), radioButtonStyle); var comboBoxStyle = new System.Windows.Style(typeof(ComboBox)); comboBoxStyle.Setters.Add(new Setter(ComboBox.MarginProperty, new Thickness() { Bottom = 7 })); comboBoxStyle.Setters.Add(new Setter(ComboBox.ForegroundProperty, new DynamicResourceExtension(SystemColors.WindowTextBrushKey))); Resources.Add(typeof(ComboBox), comboBoxStyle); } private protected void BindToOption(CheckBox checkbox, Option2<bool> optionKey) { var binding = new Binding() { Source = new OptionBinding<bool>(OptionStore, optionKey), Path = new PropertyPath("Value"), UpdateSourceTrigger = UpdateSourceTrigger.Default }; AddSearchHandler(checkbox); var bindingExpression = checkbox.SetBinding(CheckBox.IsCheckedProperty, binding); _bindingExpressions.Add(bindingExpression); } private protected void BindToOption(CheckBox checkbox, Option2<bool?> nullableOptionKey, Func<bool> onNullValue) { var binding = new Binding() { Source = new OptionBinding<bool?>(OptionStore, nullableOptionKey), Path = new PropertyPath("Value"), UpdateSourceTrigger = UpdateSourceTrigger.Default, Converter = new NullableBoolOptionConverter(onNullValue) }; AddSearchHandler(checkbox); var bindingExpression = checkbox.SetBinding(CheckBox.IsCheckedProperty, binding); _bindingExpressions.Add(bindingExpression); } private protected void BindToOption(CheckBox checkbox, PerLanguageOption2<bool> optionKey, string languageName) { var binding = new Binding() { Source = new PerLanguageOptionBinding<bool>(OptionStore, optionKey, languageName), Path = new PropertyPath("Value"), UpdateSourceTrigger = UpdateSourceTrigger.Default }; AddSearchHandler(checkbox); var bindingExpression = checkbox.SetBinding(CheckBox.IsCheckedProperty, binding); _bindingExpressions.Add(bindingExpression); } private protected void BindToOption(CheckBox checkbox, PerLanguageOption2<bool?> nullableOptionKey, string languageName, Func<bool> onNullValue) { var binding = new Binding() { Source = new PerLanguageOptionBinding<bool?>(OptionStore, nullableOptionKey, languageName), Path = new PropertyPath("Value"), UpdateSourceTrigger = UpdateSourceTrigger.Default, Converter = new NullableBoolOptionConverter(onNullValue) }; AddSearchHandler(checkbox); var bindingExpression = checkbox.SetBinding(CheckBox.IsCheckedProperty, binding); _bindingExpressions.Add(bindingExpression); } private protected void BindToOption(TextBox textBox, Option2<int> optionKey) { var binding = new Binding() { Source = new OptionBinding<int>(OptionStore, optionKey), Path = new PropertyPath("Value"), UpdateSourceTrigger = UpdateSourceTrigger.Default }; var bindingExpression = textBox.SetBinding(TextBox.TextProperty, binding); _bindingExpressions.Add(bindingExpression); } private protected void BindToOption(TextBox textBox, PerLanguageOption2<int> optionKey, string languageName) { var binding = new Binding() { Source = new PerLanguageOptionBinding<int>(OptionStore, optionKey, languageName), Path = new PropertyPath("Value"), UpdateSourceTrigger = UpdateSourceTrigger.Default }; var bindingExpression = textBox.SetBinding(TextBox.TextProperty, binding); _bindingExpressions.Add(bindingExpression); } private protected void BindToOption<T>(ComboBox comboBox, Option2<T> optionKey, ContentControl label = null) { var binding = new Binding() { Source = new OptionBinding<T>(OptionStore, optionKey), Path = new PropertyPath("Value"), Converter = new ComboBoxItemTagToIndexConverter(), ConverterParameter = comboBox }; AddSearchHandler(comboBox); if (label is not null) AddSearchHandler(label); var bindingExpression = comboBox.SetBinding(ComboBox.SelectedIndexProperty, binding); _bindingExpressions.Add(bindingExpression); } private protected void BindToOption<T>(ComboBox comboBox, PerLanguageOption2<T> optionKey, string languageName, ContentControl label = null) { var binding = new Binding() { Source = new PerLanguageOptionBinding<T>(OptionStore, optionKey, languageName), Path = new PropertyPath("Value"), Converter = new ComboBoxItemTagToIndexConverter(), ConverterParameter = comboBox }; AddSearchHandler(comboBox); if (label is not null) AddSearchHandler(label); var bindingExpression = comboBox.SetBinding(ComboBox.SelectedIndexProperty, binding); _bindingExpressions.Add(bindingExpression); } private protected void BindToOption<T>(RadioButton radiobutton, Option2<T> optionKey, T optionValue) { var binding = new Binding() { Source = new OptionBinding<T>(OptionStore, optionKey), Path = new PropertyPath("Value"), UpdateSourceTrigger = UpdateSourceTrigger.Default, Converter = new RadioButtonCheckedConverter(), ConverterParameter = optionValue }; AddSearchHandler(radiobutton); var bindingExpression = radiobutton.SetBinding(RadioButton.IsCheckedProperty, binding); _bindingExpressions.Add(bindingExpression); } private protected void BindToOption<T>(RadioButton radioButton, Option2<T?> nullableOptionKey, T optionValue, Func<bool> onNullValue) where T : struct { var binding = new Binding() { Source = new OptionBinding<T?>(OptionStore, nullableOptionKey), Path = new PropertyPath("Value"), UpdateSourceTrigger = UpdateSourceTrigger.Default, Converter = new RadioButtonCheckedConverter<T>(onNullValue), ConverterParameter = optionValue, }; AddSearchHandler(radioButton); var bindingExpression = radioButton.SetBinding(RadioButton.IsCheckedProperty, binding); _bindingExpressions.Add(bindingExpression); } private protected void BindToOption<T>(RadioButton radiobutton, PerLanguageOption2<T> optionKey, T optionValue, string languageName) { var binding = new Binding() { Source = new PerLanguageOptionBinding<T>(OptionStore, optionKey, languageName), Path = new PropertyPath("Value"), UpdateSourceTrigger = UpdateSourceTrigger.Default, Converter = new RadioButtonCheckedConverter(), ConverterParameter = optionValue }; AddSearchHandler(radiobutton); var bindingExpression = radiobutton.SetBinding(RadioButton.IsCheckedProperty, binding); _bindingExpressions.Add(bindingExpression); } internal virtual void OnLoad() { foreach (var bindingExpression in _bindingExpressions) { bindingExpression.UpdateTarget(); } } internal virtual void OnSave() { } internal virtual void Close() { } internal virtual void OnSearch(string searchString) { var shouldScrollIntoView = true; foreach (var handler in _searchHandlers) { if (handler.TryHighlightSearchString(searchString) && shouldScrollIntoView) { handler.EnsureVisible(); shouldScrollIntoView = false; } } } private protected void AddSearchHandler(ComboBox comboBox) { foreach (ComboBoxItem item in comboBox.Items) { AddSearchHandler(item); } } private protected void AddSearchHandler(ContentControl control) { Debug.Assert(control.Content is string, $"I don't know how to add keyword search support for the '{control.GetType().Name}' control with content type '{control.Content?.GetType().Name ?? "null"}'"); if (control.Content is string content) { _searchHandlers.Add(new OptionPageSearchHandler(control, content)); } } } public sealed class RadioButtonCheckedConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => value.Equals(parameter); public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => value.Equals(true) ? parameter : Binding.DoNothing; } public sealed class RadioButtonCheckedConverter<T>(Func<bool> onNullValue) : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => value switch { null => onNullValue(), _ => value.Equals(parameter), }; public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => value.Equals(true) ? parameter : Binding.DoNothing; } public class ComboBoxItemTagToIndexConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var comboBox = (ComboBox)parameter; for (var index = 0; index < comboBox.Items.Count; index++) { var item = (ComboBoxItem)comboBox.Items[index]; if (item.Tag.Equals(value)) { return index; } } return -1; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { var index = (int)value; if (index == -1) { return null; } var comboBox = (ComboBox)parameter; var item = (ComboBoxItem)comboBox.Items[index]; return item.Tag; } }