File: Options\Style\NamingPreferences\NamingStyleOptionPageControl.xaml.cs
Web Access
Project: src\src\VisualStudio\Core\Impl\Microsoft.VisualStudio.LanguageServices.Implementation.csproj (Microsoft.VisualStudio.LanguageServices.Implementation)
// 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.Linq;
using System.Windows;
using System.Windows.Controls;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
using Microsoft.CodeAnalysis.NamingStyles;
using Microsoft.CodeAnalysis.Notification;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.VisualStudio.Imaging;
using Microsoft.VisualStudio.LanguageServices.Implementation.Options.Style.NamingPreferences;
using Microsoft.VisualStudio.PlatformUI;
 
namespace Microsoft.VisualStudio.LanguageServices.Implementation.Options.Style;
 
internal partial class NamingStyleOptionPageControl : AbstractOptionPageControl
{
    public static string ReorderHeader => ServicesVSResources.Reorder;
    public static string SpecificationHeader => ServicesVSResources.Specification;
    public static string RequiredStyleHeader => ServicesVSResources.Required_Style;
    public static string SeverityHeader => ServicesVSResources.Severity;
    public static string ExplanatoryText => ServicesVSResources.For_a_given_symbol_only_the_topmost_rule_with_a_matching_Specification_will_be_applied_Violation_of_that_rules_Required_Style_will_be_reported_at_the_chosen_Severity_level;
    public static string AddRuleAutomationText => ServicesVSResources.Add_a_naming_rule;
    public static string RemoveAutomationText => ServicesVSResources.Remove_naming_rule;
    public static string SymbolSpecificationAutomationText => ServicesVSResources.Symbol_Specification;
    public static string NamingStyleAutomationText => ServicesVSResources.Naming_Style;
    public static string SeverityAutomationText => ServicesVSResources.Severity;
 
    private NamingStyleOptionPageViewModel _viewModel;
    private readonly string _languageName;
    private readonly INotificationService _notificationService;
 
    private readonly NotificationOptionViewModel[] _notifications =
    [
        new NotificationOptionViewModel(NotificationOption2.Silent, KnownMonikers.None),
        new NotificationOptionViewModel(NotificationOption2.Suggestion, KnownMonikers.StatusInformation),
        new NotificationOptionViewModel(NotificationOption2.Warning, KnownMonikers.StatusWarning),
        new NotificationOptionViewModel(NotificationOption2.Error, KnownMonikers.StatusError)
    ];
 
    internal NamingStyleOptionPageControl(OptionStore optionStore, INotificationService notificationService, string languageName)
        : base(optionStore)
    {
        _languageName = languageName;
        _notificationService = notificationService;
 
        InitializeComponent();
        OnLoad();
    }
 
    private NamingStyleOptionPageViewModel.NamingRuleViewModel CreateItemWithNoSelections()
    {
        return new NamingStyleOptionPageViewModel.NamingRuleViewModel()
        {
            Specifications = [.. _viewModel.Specifications],
            NamingStyles = [.. _viewModel.NamingStyles],
            NotificationPreferences = _notifications
        };
    }
 
    private void AddButton_Click(object sender, RoutedEventArgs e)
        => _viewModel.AddItem(CreateItemWithNoSelections());
 
    private void ManageSpecificationsButton_Click(object sender, RoutedEventArgs e)
    {
        var viewModel = new ManageSymbolSpecificationsDialogViewModel(_viewModel.Specifications, [.. _viewModel.CodeStyleItems], _languageName, _notificationService);
        var dialog = new ManageNamingStylesInfoDialog(viewModel);
        if (dialog.ShowModal().Value == true)
        {
            _viewModel.UpdateSpecificationList(viewModel);
        }
    }
 
    private void ManageStylesButton_Click(object sender, RoutedEventArgs e)
    {
        var viewModel = new ManageNamingStylesDialogViewModel(_viewModel.NamingStyles, [.. _viewModel.CodeStyleItems], _notificationService);
        var dialog = new ManageNamingStylesInfoDialog(viewModel);
        if (dialog.ShowModal().Value == true)
        {
            _viewModel.UpdateStyleList(viewModel);
        }
    }
 
    private void MoveUp_Click(object sender, EventArgs e)
    {
        var oldSelectedIndex = CodeStyleMembers.SelectedIndex;
        if (oldSelectedIndex > 0)
        {
            _viewModel.MoveItem(oldSelectedIndex, oldSelectedIndex - 1);
            CodeStyleMembers.SelectedIndex = oldSelectedIndex - 1;
            SetFocusToSelectedRow();
        }
    }
 
    private void MoveDown_Click(object sender, EventArgs e)
    {
        var oldSelectedIndex = CodeStyleMembers.SelectedIndex;
        if (oldSelectedIndex < CodeStyleMembers.Items.Count - 1)
        {
            _viewModel.MoveItem(oldSelectedIndex, oldSelectedIndex + 1);
            CodeStyleMembers.SelectedIndex = oldSelectedIndex + 1;
            SetFocusToSelectedRow();
        }
    }
 
    private void RemoveButton_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        var button = (Button)sender;
        var context = button.DataContext as NamingStyleOptionPageViewModel.NamingRuleViewModel;
        _viewModel.RemoveItem(context);
    }
 
    private void SetFocusToSelectedRow()
    {
        if (CodeStyleMembers.SelectedIndex >= 0)
        {
            if (CodeStyleMembers.ItemContainerGenerator.ContainerFromIndex(CodeStyleMembers.SelectedIndex) is not DataGridRow row)
            {
                CodeStyleMembers.ScrollIntoView(CodeStyleMembers.SelectedItem);
                row = CodeStyleMembers.ItemContainerGenerator.ContainerFromIndex(CodeStyleMembers.SelectedIndex) as DataGridRow;
            }
 
            if (row != null)
            {
                var cell = row.FindDescendant<DataGridCell>();
                cell?.Focus();
            }
        }
    }
 
    internal override void OnSave()
    {
        var symbolSpecifications = ArrayBuilder<SymbolSpecification>.GetInstance();
        var namingRules = ArrayBuilder<NamingRule>.GetInstance();
        var namingStyles = ArrayBuilder<NamingStyle>.GetInstance();
 
        foreach (var item in _viewModel.CodeStyleItems)
        {
            if (!item.IsComplete())
            {
                continue;
            }
 
            var rule = new NamingRule(
                item.SelectedSpecification,
                item.SelectedStyle.NamingStyle,
                item.SelectedNotificationPreference.Notification.Severity);
 
            namingRules.Add(rule);
        }
 
        foreach (var item in _viewModel.Specifications)
        {
            symbolSpecifications.Add(item);
        }
 
        foreach (var item in _viewModel.NamingStyles)
        {
            namingStyles.Add(item.NamingStyle);
        }
 
        var info = new NamingStylePreferences(
            symbolSpecifications.ToImmutableAndFree(),
            namingStyles.ToImmutableAndFree(),
            namingRules.ToImmutableAndFree());
 
        OptionStore.SetOption(NamingStyleOptions.NamingPreferences, _languageName, info);
    }
 
    internal override void OnLoad()
    {
        base.OnLoad();
 
        var preferences = OptionStore.GetOption<NamingStylePreferences>(NamingStyleOptions.NamingPreferences, _languageName);
        if (preferences == null)
        {
            return;
        }
 
        _viewModel = new NamingStyleOptionPageViewModel(preferences);
        DataContext = _viewModel;
    }
 
    internal bool ContainsErrors()
        => _viewModel.CodeStyleItems.Any(i => !i.IsComplete());
 
    private void CodeStyleMembers_SelectionChanged(object sender, SelectionChangedEventArgs e)
        => _viewModel.SelectedIndex = CodeStyleMembers.SelectedIndex;
}