377 lines
10 KiB
C#
377 lines
10 KiB
C#
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using XP.ImageProcessing.Core;
|
|
|
|
namespace XP.ImageProcessing.CfgControl;
|
|
|
|
/// <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();
|
|
}
|
|
} |