Dispenser/DispenserUI/Views/Controls/CameraParamsEditor.axaml.cs

466 lines
13 KiB
C#

using System;
using System.Reflection;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using DispenserCommon.Atrributes;
using DispenserCommon.Utils;
using DispenserHal.Camera.DTO;
using DispenserUI.ViewModels.Components;
using DispenserUI.ViewModels.DTO;
using Masuit.Tools.Reflection;
using Control = Avalonia.Controls.Control;
using Cursor = Avalonia.Input.Cursor;
using HorizontalAlignment = Avalonia.Layout.HorizontalAlignment;
using Orientation = Avalonia.Layout.Orientation;
using UserControl = Avalonia.Controls.UserControl;
namespace DispenserUI.Views.Controls;
public partial class CameraParamsEditor : UserControl
{
public CameraParamsEditor()
{
DataContext = ViewModel;
InitializeComponent();
ViewModel.ReloadCameraParams();
}
public CameraParamsVM ViewModel { get; } = ServiceLocator.GetService<CameraParamsVM>();
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
CameraParamsPanel = this.Get<StackPanel>("CameraParamsPanel");
RenderControls();
}
/// <summary>
/// 根据获取到的参数,渲染参数界面
/// </summary>
private void RenderControls()
{
var properties = typeof(CameraParams).GetProperties();
foreach (var property in properties)
{
var propertyType = property.PropertyType;
switch (propertyType.Name)
{
case nameof(StringValue):
CameraParamsPanel.Children.Add(RenderStringParams(property));
break;
case nameof(IntValue):
CameraParamsPanel.Children.Add(RenderIntParams(property));
break;
case nameof(Boolean):
CameraParamsPanel.Children.Add(RenderBooleanParams(property));
break;
case nameof(FloatValue):
CameraParamsPanel.Children.Add(RenderFloatParams(property));
break;
case nameof(EnumValue):
CameraParamsPanel.Children.Add(RenderEnumParams(property));
break;
}
}
// 刷新页面
InvalidateVisual();
}
/// <summary>
/// 渲染字符串参数
/// </summary>
/// <param name="property"></param>
private Control RenderStringParams(PropertyInfo property)
{
var panel = new StackPanel
{
Orientation = Orientation.Horizontal,
Height = 50,
VerticalAlignment = VerticalAlignment.Center
};
var name = new TextBlock
{
Text = property.GetDescription(),
Margin = new Thickness(0, 0, 10, 0),
TextWrapping = TextWrapping.Wrap,
Width = 80,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center
};
var value = new TextBlock
{
Name = property.Name,
Width = 250,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center
};
value.Bind(TextBlock.TextProperty, new Binding(property.Name + ".CurValue"));
panel.Children.Add(name);
panel.Children.Add(value);
return panel;
}
/// <summary>
/// 渲染数字参数
/// </summary>
/// <param name="property"></param>
private Control RenderIntParams(PropertyInfo property)
{
var panel = new StackPanel
{
Orientation = Orientation.Horizontal,
Height = 50,
VerticalAlignment = VerticalAlignment.Center
};
var name = new TextBlock
{
Text = property.GetDescription(),
Margin = new Thickness(0, 0, 10, 0),
Width = 80,
TextWrapping = TextWrapping.Wrap,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center
};
var grid = new Grid
{
Width = 250,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
ColumnDefinitions = new ColumnDefinitions("*,60")
};
var slider = new Slider
{
Name = property.Name,
Background = Brushes.Gray,
Cursor = new Cursor(StandardCursorType.Hand),
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
};
slider.Bind(RangeBase.ValueProperty, new Binding(property.Name + ".CurValue")
{
Mode = BindingMode.TwoWay
});
slider.Bind(RangeBase.MinimumProperty, new Binding(property.Name + ".Min")
{
Mode = BindingMode.TwoWay
});
var pro = property.GetCustomAttribute<Property>();
if (pro != null && pro.Max != 0)
{
slider.Maximum = pro.Max;
}
else
{
slider.Bind(RangeBase.MaximumProperty, new Binding(property.Name + ".Max")
{
Mode = BindingMode.TwoWay
});
}
slider.ValueChanged += OnSliderValueChanged;
var value = new NumericUpDown
{
Name = property.Name,
Margin = new Thickness(10, 0, 0, 0),
Width = 60,
Height = 30,
ShowButtonSpinner = false,
FormatString = "F0",
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
};
value.Bind(NumericUpDown.ValueProperty, new Binding(property.Name + ".CurValue")
{
Mode = BindingMode.TwoWay
});
value.ValueChanged += OnNumericValueChanged;
grid.Children.Add(slider);
grid.Children.Add(value);
Grid.SetColumn(slider, 0);
Grid.SetColumn(value, 1);
panel.Children.Add(name);
panel.Children.Add(grid);
return panel;
}
/// <summary>
/// 渲染bool参数
/// </summary>
/// <param name="property"></param>
private Control RenderBooleanParams(PropertyInfo property)
{
var panel = new StackPanel
{
Orientation = Orientation.Horizontal,
Height = 50,
VerticalAlignment = VerticalAlignment.Center
};
var name = new TextBlock
{
Text = property.GetDescription(),
Margin = new Thickness(0, 0, 10, 0),
Width = 80,
TextWrapping = TextWrapping.Wrap,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center
};
var value = new ToggleSwitch
{
Name = property.Name,
OnContent = "开启",
OffContent = "关闭",
Cursor = new Cursor(StandardCursorType.Hand),
HorizontalAlignment = HorizontalAlignment.Right,
HorizontalContentAlignment = HorizontalAlignment.Center,
VerticalContentAlignment = VerticalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
};
value.Bind(ToggleButton.IsCheckedProperty, new Binding(property.Name)
{
Mode = BindingMode.TwoWay
});
value.IsCheckedChanged += OnToggleSwitchChanged;
panel.Children.Add(name);
panel.Children.Add(value);
return panel;
}
/// <summary>
/// 渲染浮点型参数
/// </summary>
/// <param name="property"></param>
private Control RenderFloatParams(PropertyInfo property)
{
var panel = new StackPanel
{
Orientation = Orientation.Horizontal,
Height = 50,
VerticalAlignment = VerticalAlignment.Center
};
var name = new TextBlock
{
Text = property.GetDescription(),
Margin = new Thickness(0, 0, 10, 0),
Width = 80,
TextWrapping = TextWrapping.Wrap,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center
};
var grid = new Grid
{
Width = 250,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
ColumnDefinitions = new ColumnDefinitions("*,60")
};
var slider = new Slider
{
Name = property.Name,
Background = Brushes.Gray,
Cursor = new Cursor(StandardCursorType.Hand),
VerticalAlignment = VerticalAlignment.Center
};
slider.Bind(RangeBase.ValueProperty, new Binding(property.Name + ".CurValue")
{
Mode = BindingMode.TwoWay
});
slider.Bind(RangeBase.MinimumProperty, new Binding(property.Name + ".Min")
{
Mode = BindingMode.TwoWay
});
var pro = property.GetCustomAttribute<Property>();
if (pro != null && pro.Max != 0)
{
slider.Maximum = pro.Max;
}
else
{
slider.Bind(RangeBase.MaximumProperty, new Binding(property.Name + ".Max")
{
Mode = BindingMode.TwoWay
});
}
slider.ValueChanged += OnSliderValueChanged;
var value = new NumericUpDown
{
Name = property.Name,
Margin = new Thickness(10, 0, 0, 0),
Width = 60,
Height = 30,
ShowButtonSpinner = false,
FormatString = "0.###",
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
};
value.Bind(NumericUpDown.ValueProperty, new Binding(property.Name + ".CurValue")
{
Mode = BindingMode.TwoWay
});
value.ValueChanged += OnNumericValueChanged;
grid.Children.Add(slider);
grid.Children.Add(value);
Grid.SetColumn(slider, 0);
Grid.SetColumn(value, 1);
panel.Children.Add(name);
panel.Children.Add(grid);
return panel;
}
/// <summary>
/// 渲染枚举类型参数
/// </summary>
/// <param name="property"></param>
private Control RenderEnumParams(PropertyInfo property)
{
var panel = new StackPanel
{
Orientation = Orientation.Horizontal,
Height = 50,
VerticalAlignment = VerticalAlignment.Center
};
var name = new TextBlock
{
Text = property.GetDescription(),
Margin = new Thickness(0, 0, 10, 0),
Width = 80,
TextWrapping = TextWrapping.Wrap,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center
};
var value = new ComboBox
{
Name = property.Name,
Width = 250,
AutoScrollToSelectedItem = true
};
value.Bind(ItemsControl.ItemsSourceProperty, new Binding(property.Name + ".Labels")
{
Mode = BindingMode.TwoWay
});
value.Bind(SelectingItemsControl.SelectedIndexProperty, new Binding(property.Name + ".CurIndex")
{
Mode = BindingMode.TwoWay
});
value.SelectionChanged += OnSelectionChanged;
panel.Children.Add(name);
panel.Children.Add(value);
return panel;
}
/// <summary>
/// 当选择框发生变化时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnSelectionChanged(object? sender, SelectionChangedEventArgs e)
{
if (sender is ComboBox { IsDropDownOpen: true } comboBox)
{
var property = comboBox.Name;
var value = comboBox.SelectedIndex;
ViewModel.UpdateCameraParams(property, value);
}
}
/// <summary>
/// 当输入框发生变化时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnNumericValueChanged(object? sender, RoutedEventArgs e)
{
if (sender is NumericUpDown { IsKeyboardFocusWithin: true } numeric)
{
var property = numeric.Name;
var value = numeric.Value;
ViewModel.UpdateCameraParams(property, value);
}
}
/// <summary>
/// 当滑动条发生变化时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnSliderValueChanged(object? sender, RoutedEventArgs e)
{
if (sender is Slider { IsFocused: true } slider)
{
var property = slider.Name;
var value = slider.Value;
ViewModel.UpdateCameraParams(property, value);
}
}
/// <summary>
/// 当开关发生变化时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnToggleSwitchChanged(object? sender, RoutedEventArgs e)
{
if (sender is ToggleButton { IsFocused: true } toggleButton)
{
var property = toggleButton.Name;
var value = toggleButton.IsChecked;
ViewModel.UpdateCameraParams(property, value);
}
}
}