Files
XplorePlane/ImageProcessing.Controls/ProcessorParameterControl.xaml.cs
T
2026-04-13 13:41:40 +08:00

377 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using ImageProcessing.Core;
using System.Windows;
using System.Windows.Controls;
namespace ImageProcessing.Controls;
/// <summary>
/// 通用参数配置 UserControl
/// 可以根据不同算子的参数自动生成对应的 UI 控件
/// </summary>
public partial class ProcessorParameterControl : UserControl
{
private ImageProcessorBase? _currentProcessor;
/// <summary>
/// 参数变化事件
/// </summary>
public event EventHandler? ParameterChanged;
public ProcessorParameterControl()
{
InitializeComponent();
UpdateNoProcessorText();
}
/// <summary>
/// 更新"未选择算子"的文本
/// </summary>
private void UpdateNoProcessorText()
{
txtProcessorName.Text = LocalizationHelper.GetString("NoProcessorSelected");
txtProcessorDescription.Text = LocalizationHelper.GetString("PleaseSelectProcessor");
}
/// <summary>
/// 触发参数变化事件
/// </summary>
protected virtual void OnParameterChanged()
{
ParameterChanged?.Invoke(this, EventArgs.Empty);
}
/// <summary>
/// 加载算子参数并生成 UI
/// </summary>
public void LoadProcessor(ImageProcessorBase? processor)
{
_currentProcessor = processor;
pnlParameters.Children.Clear();
if (processor == null)
{
UpdateNoProcessorText();
return;
}
// 显示算子信息
txtProcessorName.Text = processor.Name;
txtProcessorDescription.Text = processor.Description;
// 生成参数控件
var parameters = processor.GetParameters();
foreach (var param in parameters)
{
CreateParameterControl(param);
}
}
/// <summary>
/// 根据参数类型创建对应的控件
/// </summary>
private void CreateParameterControl(ProcessorParameter param)
{
// 如果参数不可见,跳过创建
if (!param.IsVisible)
{
return;
}
// 参数标签
var label = new TextBlock
{
Text = param.DisplayName + ":",
Margin = new Thickness(0, 10, 0, 5),
FontWeight = FontWeights.Bold,
FontSize = 13
};
pnlParameters.Children.Add(label);
// 根据参数类型创建不同的控件
UIElement? control = null;
if (param.ValueType == typeof(int))
{
control = CreateIntegerControl(param);
}
else if (param.ValueType == typeof(double) || param.ValueType == typeof(float))
{
control = CreateDoubleControl(param);
}
else if (param.ValueType == typeof(bool))
{
control = CreateBooleanControl(param);
}
else if (param.ValueType == typeof(string) && param.Options != null)
{
control = CreateComboBoxControl(param);
}
else if (param.ValueType == typeof(string))
{
control = CreateTextBoxControl(param);
}
if (control != null)
{
pnlParameters.Children.Add(control);
// 添加描述标签
if (!string.IsNullOrEmpty(param.Description))
{
var desc = new TextBlock
{
Text = param.Description,
Margin = new Thickness(0, 5, 0, 0),
FontSize = 11,
Foreground = System.Windows.Media.Brushes.Gray,
TextWrapping = TextWrapping.Wrap
};
pnlParameters.Children.Add(desc);
}
}
}
/// <summary>
/// 创建整数类型控件(Slider + TextBox 或仅 TextBox
/// 当 MinValue 和 MaxValue 都为 null 时,只显示文本框,不显示滑块
/// </summary>
private UIElement CreateIntegerControl(ProcessorParameter param)
{
var panel = new StackPanel();
var textBox = new TextBox
{
Text = param.Value.ToString(),
Width = 100,
HorizontalAlignment = HorizontalAlignment.Left
};
if (param.MinValue != null && param.MaxValue != null)
{
var slider = new Slider
{
Minimum = Convert.ToDouble(param.MinValue),
Maximum = Convert.ToDouble(param.MaxValue),
Value = Convert.ToDouble(param.Value),
TickFrequency = 1,
IsSnapToTickEnabled = true,
Margin = new Thickness(0, 0, 0, 5)
};
slider.ValueChanged += (s, e) =>
{
int value = (int)slider.Value;
textBox.Text = value.ToString();
_currentProcessor?.SetParameter(param.Name, value);
OnParameterChanged();
};
textBox.TextChanged += (s, e) =>
{
if (int.TryParse(textBox.Text, out int value))
{
var min = Convert.ToInt32(param.MinValue);
var max = Convert.ToInt32(param.MaxValue);
if (value >= min && value <= max)
{
slider.Value = value;
}
}
};
panel.Children.Add(slider);
}
else
{
textBox.TextChanged += (s, e) =>
{
if (int.TryParse(textBox.Text, out int value))
{
_currentProcessor?.SetParameter(param.Name, value);
OnParameterChanged();
}
};
}
panel.Children.Add(textBox);
return panel;
}
/// <summary>
/// 创建浮点数类型控件(Slider + TextBox 或仅 TextBox
/// 当 MinValue 和 MaxValue 都为 null 时,只显示文本框,不显示滑块
/// </summary>
private UIElement CreateDoubleControl(ProcessorParameter param)
{
var panel = new StackPanel();
var textBox = new TextBox
{
Text = Convert.ToDouble(param.Value).ToString("F2"),
Width = 100,
HorizontalAlignment = HorizontalAlignment.Left
};
if (param.MinValue != null && param.MaxValue != null)
{
var slider = new Slider
{
Minimum = Convert.ToDouble(param.MinValue),
Maximum = Convert.ToDouble(param.MaxValue),
Value = Convert.ToDouble(param.Value),
TickFrequency = 0.1,
Margin = new Thickness(0, 0, 0, 5)
};
slider.ValueChanged += (s, e) =>
{
double value = Math.Round(slider.Value, 2);
textBox.Text = value.ToString("F2");
_currentProcessor?.SetParameter(param.Name, value);
OnParameterChanged();
};
textBox.TextChanged += (s, e) =>
{
if (double.TryParse(textBox.Text, out double value))
{
var min = Convert.ToDouble(param.MinValue);
var max = Convert.ToDouble(param.MaxValue);
if (value >= min && value <= max)
{
slider.Value = value;
}
}
};
panel.Children.Add(slider);
}
else
{
textBox.TextChanged += (s, e) =>
{
if (double.TryParse(textBox.Text, out double value))
{
_currentProcessor?.SetParameter(param.Name, value);
OnParameterChanged();
}
};
}
panel.Children.Add(textBox);
return panel;
}
/// <summary>
/// 创建布尔类型控件(CheckBox)
/// </summary>
private UIElement CreateBooleanControl(ProcessorParameter param)
{
var checkBox = new CheckBox
{
Content = param.DisplayName,
IsChecked = Convert.ToBoolean(param.Value),
Margin = new Thickness(0, 5, 0, 0)
};
checkBox.Checked += (s, e) =>
{
_currentProcessor?.SetParameter(param.Name, true);
OnParameterChanged();
};
checkBox.Unchecked += (s, e) =>
{
_currentProcessor?.SetParameter(param.Name, false);
OnParameterChanged();
};
return checkBox;
}
/// <summary>
/// 创建下拉框控件(ComboBox
/// </summary>
private UIElement CreateComboBoxControl(ProcessorParameter param)
{
var comboBox = new ComboBox
{
Margin = new Thickness(0, 5, 0, 0),
Width = 200,
HorizontalAlignment = HorizontalAlignment.Left
};
if (param.Options != null)
{
foreach (var option in param.Options)
{
comboBox.Items.Add(option);
}
}
comboBox.SelectedItem = param.Value;
comboBox.SelectionChanged += (s, e) =>
{
if (comboBox.SelectedItem != null)
{
_currentProcessor?.SetParameter(param.Name, comboBox.SelectedItem.ToString()!);
// 如果是 FilterType 参数,重新加载界面以更新参数可见性
if (param.Name == "FilterType")
{
LoadProcessor(_currentProcessor);
}
OnParameterChanged();
}
};
return comboBox;
}
/// <summary>
/// 创建文本框控件(TextBox
/// </summary>
private UIElement CreateTextBoxControl(ProcessorParameter param)
{
var textBox = new TextBox
{
Text = param.Value?.ToString() ?? "",
Margin = new Thickness(0, 5, 0, 0),
Width = 200,
HorizontalAlignment = HorizontalAlignment.Left
};
textBox.TextChanged += (s, e) =>
{
_currentProcessor?.SetParameter(param.Name, textBox.Text);
OnParameterChanged();
};
return textBox;
}
/// <summary>
/// 获取当前配置的算子
/// </summary>
public ImageProcessorBase? GetProcessor()
{
return _currentProcessor;
}
/// <summary>
/// 清空参数控件
/// </summary>
public void Clear()
{
_currentProcessor = null;
pnlParameters.Children.Clear();
UpdateNoProcessorText();
}
}