using CMM.Language;
using CMM.Library.Method;
using CMM.Library.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace DellMonitorControl;
///
/// Interaction logic for ControlPanel.xaml
///
public partial class ControlPanel : UserControl
{
public ControlPanel()
{
InitializeComponent();
}
public async Task Refresh()
{
try
{
sp.Children.Clear();
await CMMCommand.ScanMonitor();
var monitors = (await CMMCommand.ReadMonitorsData()).ToList();
if (!monitors.Any())
{
sp.Children.Add(new TextBlock
{
Text = "No DDC/CI monitors detected",
Foreground = System.Windows.Media.Brushes.White,
FontSize = 14
});
return;
}
foreach (var m in monitors)
{
var brightness = await CMMCommand.GetBrightness(m.SerialNumber) ?? 50;
var contrast = await CMMCommand.GetContrast(m.SerialNumber) ?? 50;
var inputSource = await CMMCommand.GetInputSource(m.SerialNumber);
var inputOptions = await CMMCommand.GetInputSourceOptions(m.SerialNumber);
var powerStatus = await CMMCommand.GetMonPowerStatus(m.SerialNumber) ?? "Unknown";
// Monitor name header
sp.Children.Add(new TextBlock
{
Text = m.MonitorName,
Foreground = System.Windows.Media.Brushes.White,
FontSize = 14,
FontWeight = FontWeights.Bold,
Margin = new Thickness(0, 10, 0, 5)
});
// Brightness row
var brightnessRow = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 3, 0, 3) };
brightnessRow.Children.Add(new TextBlock { Text = "Brightness", Foreground = System.Windows.Media.Brushes.LightGray, Width = 70, FontSize = 12, VerticalAlignment = VerticalAlignment.Center });
var bSlider = new Slider { Minimum = 0, Maximum = 100, Value = brightness, Width = 140, VerticalAlignment = VerticalAlignment.Center, Tag = m.SerialNumber };
var bValue = new TextBlock { Text = brightness.ToString(), Foreground = System.Windows.Media.Brushes.White, Width = 30, FontSize = 12, Margin = new Thickness(5, 0, 0, 0), VerticalAlignment = VerticalAlignment.Center };
bSlider.ValueChanged += (s, e) => bValue.Text = ((int)e.NewValue).ToString();
bSlider.PreviewMouseUp += async (s, e) => { if (s is Slider sl && sl.Tag is string sn) await CMMCommand.SetBrightness(sn, (int)sl.Value); };
brightnessRow.Children.Add(bSlider);
brightnessRow.Children.Add(bValue);
sp.Children.Add(brightnessRow);
// Contrast row
var contrastRow = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 3, 0, 3) };
contrastRow.Children.Add(new TextBlock { Text = "Contrast", Foreground = System.Windows.Media.Brushes.LightGray, Width = 70, FontSize = 12, VerticalAlignment = VerticalAlignment.Center });
var cSlider = new Slider { Minimum = 0, Maximum = 100, Value = contrast, Width = 140, VerticalAlignment = VerticalAlignment.Center, Tag = m.SerialNumber };
var cValue = new TextBlock { Text = contrast.ToString(), Foreground = System.Windows.Media.Brushes.White, Width = 30, FontSize = 12, Margin = new Thickness(5, 0, 0, 0), VerticalAlignment = VerticalAlignment.Center };
cSlider.ValueChanged += (s, e) => cValue.Text = ((int)e.NewValue).ToString();
cSlider.PreviewMouseUp += async (s, e) => { if (s is Slider sl && sl.Tag is string sn) await CMMCommand.SetContrast(sn, (int)sl.Value); };
contrastRow.Children.Add(cSlider);
contrastRow.Children.Add(cValue);
sp.Children.Add(contrastRow);
// Input source row (if options available)
if (inputOptions.Count > 0)
{
var inputRow = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 3, 0, 3) };
inputRow.Children.Add(new TextBlock { Text = "Input", Foreground = System.Windows.Media.Brushes.LightGray, Width = 70, FontSize = 12, VerticalAlignment = VerticalAlignment.Center });
var combo = new ComboBox { Width = 170, ItemsSource = inputOptions, DisplayMemberPath = "Name", Tag = m.SerialNumber };
if (inputSource.HasValue) combo.SelectedItem = inputOptions.Find(o => o.Value == inputSource.Value);
combo.SelectionChanged += async (s, e) => { if (s is ComboBox cb && cb.Tag is string sn && cb.SelectedItem is InputSourceOption opt) await CMMCommand.SetInputSource(sn, opt.Value); };
inputRow.Children.Add(combo);
sp.Children.Add(inputRow);
}
// Power row
var powerRow = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 3, 0, 3) };
powerRow.Children.Add(new TextBlock { Text = "Power", Foreground = System.Windows.Media.Brushes.LightGray, Width = 70, FontSize = 12, VerticalAlignment = VerticalAlignment.Center });
var powerBtn = new Button { Content = powerStatus, Width = 170, Tag = m.SerialNumber };
powerBtn.Click += async (s, e) =>
{
if (s is Button btn && btn.Tag is string sn)
{
var status = await CMMCommand.GetMonPowerStatus(sn);
if (status == "Sleep" || status == "PowerOff") await CMMCommand.PowerOn(sn);
else await CMMCommand.Sleep(sn);
await Task.Delay(1000);
btn.Content = await CMMCommand.GetMonPowerStatus(sn);
}
};
powerRow.Children.Add(powerBtn);
sp.Children.Add(powerRow);
}
}
catch (Exception ex)
{
sp.Children.Clear();
sp.Children.Add(new TextBlock
{
Text = $"Error: {ex.Message}",
Foreground = System.Windows.Media.Brushes.Red,
FontSize = 12,
TextWrapping = TextWrapping.Wrap
});
}
}
private StackPanel CreateControlSimple(
XMonitor monitorModel,
int? brightness,
int? contrast,
int? currentInputSource,
List inputOptions,
string powerStatus)
{
var container = new StackPanel
{
Orientation = Orientation.Vertical,
Margin = new Thickness(0, 5, 0, 10)
};
// Monitor name
container.Children.Add(new TextBlock
{
Text = $"{monitorModel.MonitorName} ({monitorModel.SerialNumber})",
Foreground = System.Windows.Media.Brushes.White,
FontSize = 14,
FontWeight = FontWeights.Bold,
Margin = new Thickness(0, 0, 0, 5)
});
// Brightness
var brightnessPanel = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 2, 0, 2) };
brightnessPanel.Children.Add(new TextBlock { Text = "Brightness:", Foreground = System.Windows.Media.Brushes.LightGray, Width = 80, FontSize = 12 });
var brightnessSlider = new Slider { Minimum = 0, Maximum = 100, Value = brightness ?? 50, Width = 150, Tag = monitorModel.SerialNumber };
var brightnessValue = new TextBlock { Text = (brightness ?? 50).ToString(), Foreground = System.Windows.Media.Brushes.White, Width = 30, FontSize = 12, Margin = new Thickness(5, 0, 0, 0) };
brightnessSlider.ValueChanged += (s, e) => brightnessValue.Text = ((int)e.NewValue).ToString();
brightnessSlider.PreviewMouseUp += async (s, e) =>
{
var sld = s as Slider;
if (sld?.Tag is string sn)
await CMMCommand.SetBrightness(sn, (int)sld.Value);
};
brightnessPanel.Children.Add(brightnessSlider);
brightnessPanel.Children.Add(brightnessValue);
container.Children.Add(brightnessPanel);
// Contrast
var contrastPanel = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 2, 0, 2) };
contrastPanel.Children.Add(new TextBlock { Text = "Contrast:", Foreground = System.Windows.Media.Brushes.LightGray, Width = 80, FontSize = 12 });
var contrastSlider = new Slider { Minimum = 0, Maximum = 100, Value = contrast ?? 50, Width = 150, Tag = monitorModel.SerialNumber };
var contrastValue = new TextBlock { Text = (contrast ?? 50).ToString(), Foreground = System.Windows.Media.Brushes.White, Width = 30, FontSize = 12, Margin = new Thickness(5, 0, 0, 0) };
contrastSlider.ValueChanged += (s, e) => contrastValue.Text = ((int)e.NewValue).ToString();
contrastSlider.PreviewMouseUp += async (s, e) =>
{
var sld = s as Slider;
if (sld?.Tag is string sn)
await CMMCommand.SetContrast(sn, (int)sld.Value);
};
contrastPanel.Children.Add(contrastSlider);
contrastPanel.Children.Add(contrastValue);
container.Children.Add(contrastPanel);
// Input source (if available)
if (inputOptions.Count > 0)
{
var inputPanel = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 2, 0, 2) };
inputPanel.Children.Add(new TextBlock { Text = "Input:", Foreground = System.Windows.Media.Brushes.LightGray, Width = 80, FontSize = 12 });
var combo = new ComboBox { Width = 150, ItemsSource = inputOptions, DisplayMemberPath = "Name", Tag = monitorModel.SerialNumber };
if (currentInputSource.HasValue)
combo.SelectedItem = inputOptions.Find(o => o.Value == currentInputSource.Value);
combo.SelectionChanged += async (s, e) =>
{
var cb = s as ComboBox;
if (cb?.Tag is string sn && cb.SelectedItem is InputSourceOption opt)
await CMMCommand.SetInputSource(sn, opt.Value);
};
inputPanel.Children.Add(combo);
container.Children.Add(inputPanel);
}
// Power
var powerPanel = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 2, 0, 2) };
powerPanel.Children.Add(new TextBlock { Text = "Power:", Foreground = System.Windows.Media.Brushes.LightGray, Width = 80, FontSize = 12 });
var powerBtn = new Button { Content = powerStatus, Width = 150, Tag = monitorModel.SerialNumber };
powerBtn.Click += async (s, e) =>
{
var btn = s as Button;
if (btn?.Tag is string sn)
{
var status = await CMMCommand.GetMonPowerStatus(sn);
if (status == "Sleep" || status == "PowerOff")
await CMMCommand.PowerOn(sn);
else
await CMMCommand.Sleep(sn);
await Task.Delay(1000);
btn.Content = await CMMCommand.GetMonPowerStatus(sn);
}
};
powerPanel.Children.Add(powerBtn);
container.Children.Add(powerPanel);
return container;
}
private StackPanel CreateControl(
XMonitor monitorModel,
int? brightness,
int? contrast,
int? currentInputSource,
List inputOptions,
string powerStatus)
{
var container = new StackPanel
{
Orientation = Orientation.Vertical,
Margin = new Thickness(10, 5, 10, 10)
};
// Monitor name header
var header = new TextBlock
{
Text = $"{monitorModel.MonitorName} ({monitorModel.SerialNumber})",
HorizontalAlignment = HorizontalAlignment.Left,
Style = (Style)FindResource("LableStyle"),
Margin = new Thickness(0, 0, 0, 5)
};
container.Children.Add(header);
// Brightness slider
var brightnessPanel = CreateSliderControl(
Lang.Find("Brightness"),
brightness ?? 50,
monitorModel.SerialNumber,
async (sn, value) => await CMMCommand.SetBrightness(sn, value));
container.Children.Add(brightnessPanel);
// Contrast slider
var contrastPanel = CreateSliderControl(
Lang.Find("Contrast"),
contrast ?? 50,
monitorModel.SerialNumber,
async (sn, value) => await CMMCommand.SetContrast(sn, value));
container.Children.Add(contrastPanel);
// Input source dropdown
if (inputOptions.Count > 0)
{
var inputPanel = CreateInputSourceControl(
monitorModel.SerialNumber,
currentInputSource,
inputOptions);
container.Children.Add(inputPanel);
}
// Power button
var powerPanel = CreatePowerControl(monitorModel.SerialNumber, powerStatus);
container.Children.Add(powerPanel);
return container;
}
private StackPanel CreateSliderControl(
string label,
int currentValue,
string monitorSN,
Func onValueChanged)
{
var panel = new StackPanel
{
Orientation = Orientation.Horizontal,
Margin = new Thickness(0, 3, 0, 3)
};
var labelBlock = new TextBlock
{
Text = label,
Width = 80,
VerticalAlignment = VerticalAlignment.Center,
Style = (Style)FindResource("LableStyle")
};
var slider = new Slider
{
Style = (Style)FindResource("Horizontal_Slider"),
Minimum = 0,
Maximum = 100,
Value = currentValue,
Tag = monitorSN,
Width = 180
};
var valueBlock = new TextBlock
{
Text = currentValue.ToString(),
Width = 35,
VerticalAlignment = VerticalAlignment.Center,
Style = (Style)FindResource("LableStyle"),
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) && sld != null)
{
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, 3, 0, 3)
};
var labelBlock = new TextBlock
{
Text = Lang.Find("InputSource"),
Width = 80,
VerticalAlignment = VerticalAlignment.Center,
Style = (Style)FindResource("LableStyle")
};
var comboBox = new ComboBox
{
Width = 180,
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, 5, 0, 0)
};
var labelBlock = new TextBlock
{
Text = Lang.Find("Power"),
Width = 80,
VerticalAlignment = VerticalAlignment.Center,
Style = (Style)FindResource("LableStyle")
};
var btn = new Button
{
Tag = monitorSN,
Content = GetLocalizedPowerStatus(powerStatus),
Style = (Style)FindResource("TextButtonStyle"),
Width = 180
};
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);
}
private void Border_MouseLeave(object sender, MouseEventArgs e)
{
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
// Use Dispatcher to let the popup fully render first
Dispatcher.BeginInvoke(new Action(async () =>
{
try
{
await Refresh();
}
catch (Exception ex)
{
sp.Children.Clear();
sp.Children.Add(new TextBlock
{
Text = $"Error: {ex.Message}",
Foreground = System.Windows.Media.Brushes.Red,
FontSize = 12,
TextWrapping = TextWrapping.Wrap
});
}
}), System.Windows.Threading.DispatcherPriority.Background);
}
}