XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEToolBox

【WPF】XFE工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using ToolControls = XFEToolBox.WpfCore.Controls;

namespace XFEToolBox.Client.Views.Windows;

public partial class ControlGalleryWindow
{
    private ScenarioPreviewResult CreateScenarioPreview(string id) => id switch
    {
        "button" => BuildButtonScenarios(),
        "text-editor" => BuildTextEditorScenarios(),
        "password-editor" => BuildPasswordEditorScenarios(),
        "auto-suggest" => BuildAutoSuggestScenarios(),
        "check-box" => BuildCheckBoxScenarios(),
        "radio-button" => BuildRadioButtonScenarios(),
        "toggle-button" => BuildToggleButtonScenarios(),
        "combo-box" => BuildComboBoxScenarios(),
        "slider" => BuildSliderScenarios(),
        "color-picker" => BuildColorPickerScenarios(),
        "date-picker" => BuildDatePickerScenarios(),
        "calendar-picker" => BuildCalendarPickerScenarios(),
        "time-picker" => BuildTimePickerScenarios(),
        "progress-bar" => BuildProgressBarScenarios(),
        "progress-ring" => BuildProgressRingScenarios(),
        "info-bar" => BuildInfoBarScenarios(),
        "command-bar" => BuildCommandBarScenarios(),
        "expander" => BuildExpanderScenarios(),
        "image" => BuildImageScenarios(),
        "person-picture" => BuildPersonPictureScenarios(),
        "carousel" => BuildCarouselScenarios(),
        "data-grid" => BuildDataGridScenarios(),
        "tab-view" => BuildTabViewScenarios(),
        "navigation-view" => BuildNavigationViewScenarios(),
        "command-preview" => BuildCommandPreviewScenarios(),
        "xaml-code-viewer" => BuildXamlCodeViewerScenarios(),
        "scroll-text" => BuildScrollTextScenarios(),
        "mini-tool-button" => BuildMiniToolButtonScenarios(),
        _ => new ScenarioPreviewResult(
            new TextBlock { Text = "尚未提供此控件的场景演示。" },
            new HashSet<string>(StringComparer.Ordinal))
    };

    private static ScenarioPreviewResult Scenarios(params GalleryScenario[] scenarios)
    {
        var panel = new StackPanel();
        var coveredProperties = new HashSet<string>(StringComparer.Ordinal);
        for (var index = 0; index < scenarios.Length; index++)
        {
            var scenario = scenarios[index];
            foreach (var parameter in scenario.Parameters)
                coveredProperties.Add(parameter.PropertyName);
            panel.Children.Add(CreateScenarioCard(scenario, index + 1));
        }
        return new ScenarioPreviewResult(panel, coveredProperties);
    }

    private static GalleryScenario Scenario(
        string title,
        string description,
        FrameworkElement preview,
        params GalleryParameter[] parameters) => new(title, description, preview, parameters);

    private static Border CreateScenarioCard(GalleryScenario scenario, int sequence)
    {
        var root = new Grid();
        root.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
        root.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1) });
        root.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });

        var titleGrid = new Grid { Margin = new Thickness(16, 13, 16, 12) };
        titleGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(34) });
        titleGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
        var badge = new Border
        {
            Width = 25,
            Height = 25,
            CornerRadius = new CornerRadius(8),
            Background = new SolidColorBrush(Color.FromRgb(238, 237, 251)),
            VerticalAlignment = VerticalAlignment.Top,
            Child = new TextBlock
            {
                Text = sequence.ToString("00"),
                Foreground = new SolidColorBrush(Color.FromRgb(105, 105, 188)),
                FontFamily = new FontFamily("Cascadia Mono, Consolas"),
                FontSize = 9,
                FontWeight = FontWeights.SemiBold,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            }
        };
        titleGrid.Children.Add(badge);
        var heading = new StackPanel { Margin = new Thickness(0, 0, 0, 0) };
        heading.Children.Add(new TextBlock
        {
            Text = scenario.Title,
            Foreground = new SolidColorBrush(Color.FromRgb(70, 70, 91)),
            FontSize = 12,
            FontWeight = FontWeights.SemiBold
        });
        heading.Children.Add(new TextBlock
        {
            Text = scenario.Description,
            Foreground = new SolidColorBrush(Color.FromRgb(143, 143, 162)),
            FontSize = 9,
            Margin = new Thickness(0, 3, 0, 0),
            TextWrapping = TextWrapping.Wrap
        });
        Grid.SetColumn(heading, 1);
        titleGrid.Children.Add(heading);
        root.Children.Add(titleGrid);

        var divider = new Border { Background = new SolidColorBrush(Color.FromRgb(236, 235, 244)) };
        Grid.SetRow(divider, 1);
        root.Children.Add(divider);

        var body = new Grid { Margin = new Thickness(14) };
        body.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star), MinWidth = 250 });
        body.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(25) });
        body.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(282) });

        var previewSurface = new Border
        {
            MinHeight = 142,
            Padding = new Thickness(18),
            Background = new SolidColorBrush(Color.FromRgb(248, 248, 252)),
            BorderBrush = new SolidColorBrush(Color.FromRgb(235, 234, 244)),
            BorderThickness = new Thickness(1),
            CornerRadius = new CornerRadius(12),
            VerticalAlignment = VerticalAlignment.Stretch,
            Child = scenario.Preview
        };
        body.Children.Add(previewSurface);

        var bodyDivider = new Border
        {
            Background = new SolidColorBrush(Color.FromRgb(235, 234, 244)),
            Margin = new Thickness(12, 0, 12, 0)
        };
        Grid.SetColumn(bodyDivider, 1);
        body.Children.Add(bodyDivider);

        var parameters = new StackPanel { Margin = new Thickness(14, 0, 0, 0) };
        parameters.Children.Add(new TextBlock
        {
            Text = "场景参数",
            Foreground = new SolidColorBrush(Color.FromRgb(91, 91, 160)),
            FontSize = 9,
            FontWeight = FontWeights.SemiBold,
            Margin = new Thickness(0, 0, 0, 8)
        });
        foreach (var parameter in scenario.Parameters)
            parameters.Children.Add(parameter.Editor);
        Grid.SetColumn(parameters, 2);
        body.Children.Add(parameters);
        Grid.SetRow(body, 2);
        root.Children.Add(body);

        return new Border
        {
            Margin = new Thickness(0, 0, 0, 14),
            Background = Brushes.White,
            BorderBrush = new SolidColorBrush(Color.FromRgb(229, 228, 240)),
            BorderThickness = new Thickness(1),
            CornerRadius = new CornerRadius(14),
            Child = root
        };
    }

    private static GalleryParameter ToggleParameter(string propertyName, bool initialValue, Action<bool> changed)
    {
        var toggle = new CheckBox { Content = initialValue ? "已启用" : "已关闭", IsChecked = initialValue };
        toggle.Click += (_, _) =>
        {
            var value = toggle.IsChecked == true;
            toggle.Content = value ? "已启用" : "已关闭";
            changed(value);
        };
        return Parameter(propertyName, toggle);
    }

    private static GalleryParameter TriStateParameter(string propertyName, bool? initialValue, Action<bool?> changed)
    {
        var combo = new ComboBox
        {
            Height = 34,
            ItemsSource = new[] { "未选中", "已选中", "不确定" },
            SelectedIndex = initialValue is null ? 2 : initialValue.Value ? 1 : 0
        };
        combo.SelectionChanged += (_, _) => changed(combo.SelectedIndex switch { 1 => true, 2 => null, _ => false });
        return Parameter(propertyName, combo);
    }

    private static GalleryParameter TextParameter(string propertyName, string initialValue, Action<string> changed)
    {
        var editor = new ToolControls.TextEditor { Height = 34, Text = initialValue };
        editor.TextChanged += (_, _) => changed(editor.Text);
        return Parameter(propertyName, editor);
    }

    private static GalleryParameter ChoiceParameter(
        string propertyName,
        IReadOnlyList<string> choices,
        int selectedIndex,
        Action<int, string> changed)
    {
        var combo = new ComboBox { Height = 34, ItemsSource = choices, SelectedIndex = selectedIndex };
        combo.SelectionChanged += (_, _) =>
        {
            if (combo.SelectedIndex >= 0 && combo.SelectedItem is string value)
                changed(combo.SelectedIndex, value);
        };
        return Parameter(propertyName, combo);
    }

    private static GalleryParameter SliderParameter(
        string propertyName,
        double minimum,
        double maximum,
        double initialValue,
        Action<double> changed,
        string format = "0")
    {
        var panel = new StackPanel();
        var valueText = new TextBlock
        {
            Text = initialValue.ToString(format),
            Foreground = new SolidColorBrush(Color.FromRgb(105, 105, 188)),
            FontFamily = new FontFamily("Cascadia Mono, Consolas"),
            FontSize = 9,
            HorizontalAlignment = HorizontalAlignment.Right
        };
        var slider = new Slider
        {
            Minimum = minimum,
            Maximum = maximum,
            Value = initialValue,
            TickFrequency = format.Contains('.') ? 0.1 : 1,
            IsSnapToTickEnabled = !format.Contains('.')
        };
        slider.ValueChanged += (_, _) =>
        {
            valueText.Text = slider.Value.ToString(format);
            changed(slider.Value);
        };
        panel.Children.Add(valueText);
        panel.Children.Add(slider);
        return Parameter(propertyName, panel);
    }

    private static GalleryParameter ActionParameter(string propertyName, string buttonText, Action clicked)
    {
        var button = new Button { Content = buttonText, Height = 32, HorizontalAlignment = HorizontalAlignment.Stretch };
        button.Click += (_, _) => clicked();
        return Parameter(propertyName, button);
    }

    private static GalleryParameter LiveValueParameter(string propertyName, string initialValue, out TextBlock valueText)
    {
        valueText = new TextBlock
        {
            Text = initialValue,
            Foreground = new SolidColorBrush(Color.FromRgb(91, 91, 160)),
            FontFamily = new FontFamily("Cascadia Mono, Consolas"),
            FontSize = 9.5,
            TextWrapping = TextWrapping.Wrap
        };
        return Parameter(propertyName, new Border
        {
            Padding = new Thickness(9, 7, 9, 7),
            Background = new SolidColorBrush(Color.FromRgb(245, 244, 252)),
            CornerRadius = new CornerRadius(8),
            Child = valueText
        });
    }

    private static GalleryParameter Parameter(string propertyName, FrameworkElement editor)
    {
        var panel = new StackPanel();
        panel.Children.Add(new TextBlock
        {
            Text = propertyName,
            Foreground = new SolidColorBrush(Color.FromRgb(91, 91, 111)),
            FontFamily = new FontFamily("Cascadia Mono, Consolas"),
            FontSize = 8.5,
            FontWeight = FontWeights.SemiBold,
            Margin = new Thickness(0, 0, 0, 5)
        });
        panel.Children.Add(editor);
        return new GalleryParameter(propertyName, new Border
        {
            Margin = new Thickness(0, 0, 0, 10),
            Child = panel
        });
    }

    private static StackPanel ScenarioPreviewStack(params UIElement[] children)
    {
        var panel = new StackPanel
        {
            HorizontalAlignment = HorizontalAlignment.Stretch,
            VerticalAlignment = VerticalAlignment.Center
        };
        foreach (var child in children)
            panel.Children.Add(child);
        return panel;
    }

    private static TextBlock ScenarioStatus(string text) => new()
    {
        Text = text,
        Foreground = new SolidColorBrush(Color.FromRgb(126, 126, 146)),
        FontSize = 9.5,
        Margin = new Thickness(0, 12, 0, 0),
        TextWrapping = TextWrapping.Wrap
    };

    private static StackPanel ScenarioRow(params UIElement[] children)
    {
        var panel = new StackPanel { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Left };
        foreach (var child in children)
            panel.Children.Add(child);
        return panel;
    }

    private sealed record ScenarioPreviewResult(FrameworkElement View, IReadOnlySet<string> CoveredProperties);

    private sealed record GalleryScenario(
        string Title,
        string Description,
        FrameworkElement Preview,
        IReadOnlyList<GalleryParameter> Parameters);

    private sealed record GalleryParameter(string PropertyName, FrameworkElement Editor);

    private sealed class GalleryCommand(Action execute) : ICommand
    {
        public bool CanExecute(object? parameter) => true;
        public void Execute(object? parameter) => execute();
        public event EventHandler? CanExecuteChanged { add { } remove { } }
    }
}