using System.Windows.Controls; using System.Windows; using CMM.Library.ViewModel; using CMM.Library.Method; using CMM.Language; using System; using System.Collections.Generic; using System.Threading.Tasks; namespace CMM.Management.Control { /// /// Single monitor control /// internal class MonCtrl : System.Windows.Controls.Control { public static readonly DependencyProperty MonProperty; private StackPanel _sp; static MonCtrl() { DefaultStyleKeyProperty.OverrideMetadata(typeof(MonCtrl), new FrameworkPropertyMetadata(typeof(MonCtrl))); MonProperty = DependencyProperty.Register( "Monitor", typeof(XMonitor), typeof(MonCtrl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnMonChangedCallback)); } public override void OnApplyTemplate() { _sp = Template.FindName("sp", this) as StackPanel; if (_sp != null && Mon != null) { _ = LoadControlsAsync(); } } public XMonitor Mon { get => (XMonitor)GetValue(MonProperty); set => SetValue(MonProperty, value); } static void OnMonChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args) { var me = sender as MonCtrl; if (me != null) { me.OnMonChanged((XMonitor)args.NewValue); } } public virtual void OnMonChanged(XMonitor value) { if (_sp != null && value != null) { _ = LoadControlsAsync(); } } private async Task LoadControlsAsync() { if (_sp == null || Mon == null) return; _sp.Children.Clear(); var brightness = await CMMCommand.GetBrightness(Mon.SerialNumber); var contrast = await CMMCommand.GetContrast(Mon.SerialNumber); var inputSource = await CMMCommand.GetInputSource(Mon.SerialNumber); var inputOptions = await CMMCommand.GetInputSourceOptions(Mon.SerialNumber); var powerStatus = await CMMCommand.GetMonPowerStatus(Mon.SerialNumber); // Brightness slider var brightnessPanel = CreateSliderControl( Lang.Find("Brightness"), brightness ?? 50, Mon.SerialNumber, async (sn, value) => await CMMCommand.SetBrightness(sn, value)); _sp.Children.Add(brightnessPanel); // Contrast slider var contrastPanel = CreateSliderControl( Lang.Find("Contrast"), contrast ?? 50, Mon.SerialNumber, async (sn, value) => await CMMCommand.SetContrast(sn, value)); _sp.Children.Add(contrastPanel); // Input source dropdown if (inputOptions.Count > 0) { var inputPanel = CreateInputSourceControl( Mon.SerialNumber, inputSource, inputOptions); _sp.Children.Add(inputPanel); } // Power button var powerPanel = CreatePowerControl(Mon.SerialNumber, powerStatus); _sp.Children.Add(powerPanel); } private StackPanel CreateSliderControl( string label, int currentValue, string monitorSN, Func onValueChanged) { var panel = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 5, 0, 5) }; var labelBlock = new TextBlock { Text = label, Width = 100, VerticalAlignment = VerticalAlignment.Center, Foreground = System.Windows.Media.Brushes.White }; var slider = new Slider { Style = (Style)FindResource("Horizontal_Slider"), Minimum = 0, Maximum = 100, Value = currentValue, Tag = monitorSN, Width = 200 }; var valueBlock = new TextBlock { Text = currentValue.ToString(), Width = 40, VerticalAlignment = VerticalAlignment.Center, Foreground = System.Windows.Media.Brushes.White, TextAlignment = TextAlignment.Right }; // Update value display while dragging slider.ValueChanged += (s, e) => { valueBlock.Text = ((int)e.NewValue).ToString(); }; // Only send command on release (PreviewMouseUp) slider.PreviewMouseUp += async (s, e) => { var sld = s as Slider; var sn = sld?.Tag?.ToString(); if (!string.IsNullOrEmpty(sn)) { await onValueChanged(sn, (int)sld.Value); } }; panel.Children.Add(labelBlock); panel.Children.Add(slider); panel.Children.Add(valueBlock); return panel; } private StackPanel CreateInputSourceControl( string monitorSN, int? currentInputSource, List options) { var panel = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 5, 0, 5) }; var labelBlock = new TextBlock { Text = Lang.Find("InputSource"), Width = 100, VerticalAlignment = VerticalAlignment.Center, Foreground = System.Windows.Media.Brushes.White }; var comboBox = new ComboBox { Width = 200, Tag = monitorSN, ItemsSource = options, DisplayMemberPath = "Name" }; // Set current selection if (currentInputSource.HasValue) { var currentOption = options.Find(o => o.Value == currentInputSource.Value); if (currentOption != null) { comboBox.SelectedItem = currentOption; } } comboBox.SelectionChanged += async (s, e) => { var cb = s as ComboBox; var sn = cb?.Tag?.ToString(); var selectedOption = cb?.SelectedItem as InputSourceOption; if (!string.IsNullOrEmpty(sn) && selectedOption != null) { await CMMCommand.SetInputSource(sn, selectedOption.Value); } }; panel.Children.Add(labelBlock); panel.Children.Add(comboBox); return panel; } private StackPanel CreatePowerControl(string monitorSN, string powerStatus) { var panel = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 10, 0, 0) }; var labelBlock = new TextBlock { Text = Lang.Find("Power"), Width = 100, VerticalAlignment = VerticalAlignment.Center, Foreground = System.Windows.Media.Brushes.White }; var btn = new Button { Tag = monitorSN, Content = GetLocalizedPowerStatus(powerStatus), Width = 200, Height = 30 }; btn.Click += async (s, e) => await TogglePower(s, e); panel.Children.Add(labelBlock); panel.Children.Add(btn); return panel; } private string GetLocalizedPowerStatus(string status) { return status switch { "PowerOn" => Lang.Find("PowerOn"), "Sleep" => Lang.Find("Sleep"), "PowerOff" => Lang.Find("PowerOff"), _ => status }; } private async Task TogglePower(object sender, RoutedEventArgs e) { var btn = sender as Button; var tag = btn?.Tag?.ToString(); if (string.IsNullOrEmpty(tag)) return; var currentStatus = await CMMCommand.GetMonPowerStatus(tag); if (currentStatus == "Sleep" || currentStatus == "PowerOff") { await CMMCommand.PowerOn(tag); } else { await CMMCommand.Sleep(tag); } await Task.Delay(1000); var newStatus = await CMMCommand.GetMonPowerStatus(tag); btn!.Content = GetLocalizedPowerStatus(newStatus); } } }