using Avalonia; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.LogicalTree; using Avalonia.Markup.Xaml; using Avalonia.Media; using Avalonia.Threading; using AvaloniaApplication1.DataBase; using DaireApplication.DataBase; using DaireApplication.ViewModels; using DaireApplication.Views; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.IO.Ports; using System.Linq; using System.Numerics; using System.Reflection.Emit; using System.Reflection.PortableExecutable; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; namespace DaireApplication; public partial class Software : UserControl { private MainWindow? _mainWindow; public UserTable _user = new(); public ScreeenTable _screeen = new(); private Process? _keyboardProcess; private bool _isWindowLoaded = false; TextBox targetText = new TextBox(); int oldValue = 0; bool _isAdvSetting; bool _isFromManualControl; public event PropertyChangedEventHandler? PropertyChanged; private void RaisePropertyChanged([CallerMemberName] string? name = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); public ObservableCollection SerialPorts { get; } = new() { "Choose COM" }; private string? _selectedPort; public string? SelectedPort { get => _selectedPort; set { if (_selectedPort != value) { _selectedPort = value; RaisePropertyChanged(); } } } public Software(MainWindow mainWindow,bool isAdvSetting=false, bool isFromManualControl=false) { _mainWindow = mainWindow; _isAdvSetting = isAdvSetting; _isFromManualControl = isFromManualControl; foreach (var port in SerialPort.GetPortNames()) { SerialPorts.Add(port); } var screen = _screeen.ReadScreens()[0]; InitializeComponent(); this.Loaded += OnWindowLoaded; if (SerialPorts.Count - 1 > 0) { if (!string.IsNullOrEmpty(screen.port)) { SerialPorts[0] = "Close Comunication"; SelectedPort = screen.port; } else { SerialPorts[0] = "Choose COM"; SelectedPort = SerialPorts[0]; } } else SelectedPort = SerialPorts[0]; DataContext = this; setDefaultSettings(); showDefaultValues(); sendingTimetxt.AddHandler(TextInputEvent, OnTextInput, RoutingStrategies.Tunnel); warningLimit.AddHandler(TextInputEvent, OnTextInput, RoutingStrategies.Tunnel); errorLimit.AddHandler(TextInputEvent, OnTextInput, RoutingStrategies.Tunnel); passwordBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); warningBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); errorBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); AttachHandlers(_mainWindow.logoBtn, AdvanceSettingsView); AttachHandlers(_mainWindow.UserName, CloseApplication); } public void AttachHandlers(Button button, System.EventHandler func) { if (button != null) { button.Holding += func; button.PointerPressed += (sender, e) => { // Simulate a long press on any pointer (mouse or touch) var point = e.GetPosition(button); func(sender, new HoldingRoutedEventArgs(HoldingState.Started, point, e.Pointer.Type)); }; button.PointerReleased += (sender, e) => { // End simulated long press var point = e.GetPosition(button); func(sender, new HoldingRoutedEventArgs(HoldingState.Completed, point, e.Pointer.Type)); }; } } public Software() { InitializeComponent(); } public void AdvanceSettingsView(object? sender, RoutedEventArgs e) { if (_mainWindow.ContentArea.Content == this) { _mainWindow.ContentArea.Content = new AdvanceSettings(_mainWindow,false,true); } } public static void CloseApplication(object? sender, RoutedEventArgs e) { var lifetime = Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime; lifetime?.Shutdown(); // This should correctly shut down the application } private void OnWindowLoaded(object? sender, RoutedEventArgs e) { _isWindowLoaded = true; } private void OnTextInput(object? sender, TextInputEventArgs e) { if (sender is TextBox textBox) { string newText = textBox.Text + e.Text; if (!Regex.IsMatch(newText, @"^\d*\.?\d*$")) { e.Handled = true; } } } private void hidePasswordPopUp(object sender, RoutedEventArgs e) { passwordInput.Text = ""; CloseKeyboard(); passwordPopupOverlay.IsVisible = false; } private async void passwordSaveClick(object? sender, RoutedEventArgs e) { var user = _user.ReadUsers().FirstOrDefault(x=>x.UserName.ToLower()==titelMsg.Tag.ToString().ToLower()); user.Password = passwordInput.Text; user.IsActive = isActivePass.IsChecked.Value; if (_user.UpdateUser(user)) { //await MainWindow.MessageBox.Show(_mainWindow, "Password Changed Sucseccfully", "Sucsecc"); passwordInput.Text = ""; CloseKeyboard(); passwordPopupOverlay.IsVisible = false; } else { if (_keyboardProcess != null) { _keyboardProcess.Kill(); } await MainWindow.MessageBox.Show(_mainWindow, "Password Does Not Changed Try Again", "Error"); _mainWindow.Topmost = false; } } private void showChangePasswordPopUp(object? sender, RoutedEventArgs e) { if (sender is Button button) { var text = button.Content as TextBlock; titelMsg.Text = $"New {text.Text} Password:"; titelMsg.Tag = text.Text; var user = _user.ReadUsers().FirstOrDefault(x => x.UserName.ToLower() == titelMsg.Tag.ToString().ToLower()); isActivePass.IsVisible = true; isActivePass.IsChecked = user.IsActive; passwordPopupOverlay.IsVisible = true; } } private void hideScreenPopUp(object sender, RoutedEventArgs e) { slider.Value = 0; secreenPopupOverlay.IsVisible = false; } private async void screenSaveClick(object? sender, RoutedEventArgs e) { var screenData = _screeen.ReadScreens()?[0]; string brightnessPath = "/sys/class/backlight/backlight/brightness"; // Try backlight1 if this fails if (titelSecreenMsg.Tag.ToString()== "BRIGHTNESS") { try { if (!string.IsNullOrEmpty(sliderValue.Text)) { int brightnessValue = (int)(Int32.Parse(sliderValue.Text) / 100.0 * 255); screenData.brightness = Int32.Parse(sliderValue.Text); _screeen.UpdateScreen(screenData); File.WriteAllText(brightnessPath, brightnessValue.ToString()); } } catch (Exception ex) { Console.WriteLine("Error: " + ex.Message); } } else if (titelSecreenMsg.Tag.ToString() == "AUTO DIM") { if (!string.IsNullOrEmpty(sliderValue.Text)) { if ((screenData?.offSec / 60.0) < float.Parse(sliderValue.Text)) { if (_keyboardProcess != null) { _keyboardProcess.Kill(); } await MainWindow.MessageBox.Show(_mainWindow, "AutoOff Value must be greater than AutoDim Value", "Error"); _mainWindow.Topmost = false; return; } screenData.dimSec = float.Parse(sliderValue.Text) * 60; _screeen.UpdateScreen(screenData); } } else if (titelSecreenMsg.Tag.ToString() == "AUTO OFF") { if (!string.IsNullOrEmpty(sliderValue.Text)) { if ((screenData?.dimSec / 60.0)> float.Parse(sliderValue.Text)) { if (_keyboardProcess != null) { _keyboardProcess.Kill(); } await MainWindow.MessageBox.Show(_mainWindow, "AutoOff Value must be greater than AutoDim Value", "Error"); _mainWindow.Topmost = false; return; } screenData.offSec = float.Parse(sliderValue.Text) * 60; _screeen.UpdateScreen(screenData); } } showDefaultValues(); secreenPopupOverlay.IsVisible = false; } private void InnerPopupPointerPressed(object? sender, PointerPressedEventArgs e) { e.Handled = true; } private void showScreenPopUp(object? sender, RoutedEventArgs e) { if (sender is Button button) { var screenData = _screeen.ReadScreens()?[0]; if (button.Tag.ToString() == "BRIGHTNESS") { slider.Maximum = 100; titelSecreenMsg.Text = $"Enter {button.Tag} percentage:"; titelSecreenMsg.Tag = button.Tag; slider.Value = screenData.brightness; secreenPopupOverlay.IsVisible = true; } if (button.Tag.ToString() == "AUTO DIM") { slider.Maximum = 120; titelSecreenMsg.Text = $"Enter {button.Tag} value in min:"; titelSecreenMsg.Tag = button.Tag; slider.Value = screenData.dimSec / 60; secreenPopupOverlay.IsVisible = true; } if (button.Tag.ToString() == "AUTO OFF") { slider.Maximum = 120; titelSecreenMsg.Text = $"Enter {button.Tag} value in min:"; titelSecreenMsg.Tag = button.Tag; slider.Value = screenData.offSec / 60; secreenPopupOverlay.IsVisible = true; } } } private void OnSliderValueChanged(object? sender, RoutedEventArgs e) { if (sender is Slider slider) { var parent = slider.Parent as StackPanel; var targetText = parent.Children[1] as TextBlock; targetText.Text= slider.Value.ToString(); //sliderValue.Text= slider.Value.ToString(); } } private void changeValueClick(object? sender, RoutedEventArgs e) { if (sender is Button button) { var parent = button.Parent as StackPanel; var slider = parent.Children[1] as Slider; var grandParent = parent.Parent as StackPanel; var stack = grandParent.Children[0] as StackPanel; var targetText = stack.Children[1] as TextBlock; targetText.Text = slider.Value.ToString(); if (button.Content=="+") // + { slider.Value = Int32.Parse(targetText.Text) + 1; } else // - { if (Int32.Parse(targetText.Text)>0) { slider.Value = Int32.Parse(targetText.Text) - 1; } } } } private void OnComSliderValueChanged(object? sender, RoutedEventArgs e) { if (sender is Slider slider) { var parent = slider.Parent.Parent as StackPanel; var stack = parent.Children[0] as StackPanel; var targetText = stack.Children[1] as TextBlock; targetText.Text= slider.Value.ToString(); } } private void hideComPopUp(object sender, RoutedEventArgs e) { //comSlider.Value = 0; comPopupOverlay.IsVisible = false; } private void hideTempPopUp(object sender, RoutedEventArgs e) { tempPopupOverlay.IsVisible = false; } private async void comSaveClick(object? sender, RoutedEventArgs e) { var screen = _screeen.ReadScreens()[0]; var boundRateItem = boundRateComboBox.SelectedItem as ComboBoxItem; screen.boundRate = Int32.Parse(boundRateItem.Content.ToString()); var stopbitsItem = stopBitsComboBox.SelectedItem as ComboBoxItem; screen.stopBits = Int32.Parse(stopbitsItem.Tag.ToString()); var parityItem = parityComboBox.SelectedItem as ComboBoxItem; screen.parity = Int32.Parse(parityItem.Tag.ToString()); screen.sendingTime = Int32.Parse(sendingTimetxt.Text); if (_screeen.UpdateScreen(screen)) { _mainWindow.resetPort = true; _mainWindow.footerMsg.Text = "Connecting....."; _mainWindow.footerMsg.IsVisible = true; comPopupOverlay.IsVisible = false; } } private void showComPopUp(object? sender, RoutedEventArgs e) { var screen = _screeen.ReadScreens()[0]; boundRateComboBox.SelectedIndex=int.Parse(boundRateComboBox.Items.OfType().FirstOrDefault(item => item.Content?.ToString() == screen.boundRate.ToString()).Tag.ToString()); stopBitsComboBox.SelectedIndex = screen.stopBits; parityComboBox.SelectedIndex = screen.parity; sendingTimetxt.Text=screen.sendingTime.ToString(); comPopupOverlay.IsVisible = true; } private void ShowTempPopUp(object? sender, RoutedEventArgs e) { var screen = _screeen.ReadScreens()[0]; warningLimit.Text=screen.warningLimit.ToString(); errorLimit.Text=screen.errorLimit.ToString(); tempPopupOverlay.IsVisible = true; } private void tempSaveBtn(object? sender, RoutedEventArgs e) { var screen = _screeen.ReadScreens()[0]; screen.warningLimit = double.Parse(warningLimit.Text); screen.errorLimit = double.Parse(errorLimit.Text); _screeen.UpdateScreen(screen); CloseKeyboard(); //if (_keyboardProcess != null) //{ // _keyboardProcess.Kill(); //} tempPopupOverlay.IsVisible=false; } private void portChanged(object? sender, RoutedEventArgs e) { if (!_isWindowLoaded) return; if (sender is ComboBox comboBox) { if (comboBox.SelectedItem is string selectedItem) { var screen = _screeen.ReadScreens()[0]; if (selectedItem.ToString()!= "Choose COM" && selectedItem.ToString()!= "Close Comunication") { screen.port = selectedItem.ToString(); _screeen.UpdateScreen(screen); } else { screen.port = ""; _screeen.UpdateScreen(screen); } boundRateComboBox.SelectedIndex = int.Parse(boundRateComboBox.Items.OfType().FirstOrDefault(item => item.Content?.ToString() == screen.boundRate.ToString()).Tag.ToString()); stopBitsComboBox.SelectedIndex = screen.stopBits; parityComboBox.SelectedIndex = screen.parity; sendingTimetxt.Text = screen.sendingTime.ToString(); this.comSaveButton.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); } } } private (string? fileName, string args) GetKeyboardCommand() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return ("osk.exe", ""); if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return ("onboard", ""); // or "florence", "matchbox-keyboard" return (null, ""); } private async void OnTextBoxFocused(object? sender, PointerPressedEventArgs e) { if (_keyboardProcess is { HasExited: false }) return; var (fileName, args) = GetKeyboardCommand(); if (fileName is null) return; _keyboardProcess = new Process { StartInfo = new ProcessStartInfo { FileName = fileName, Arguments = args, UseShellExecute = true, WorkingDirectory = "/usr/bin" }, EnableRaisingEvents = true }; try { _keyboardProcess.Start(); Dispatcher.UIThread.Post(() => { if (sender is Border border) { var textbox = border.Child as TextBox; textbox.SelectionStart = 0; textbox.SelectionEnd = textbox.Text?.Length ?? 0; } }); } catch { // fail silently if keyboard not found } } private void OnPopupOverlayPointerPressed(object sender, PointerPressedEventArgs e) { targetText.Text = oldValue.ToString(); CancelComButton.Focus(); keyBoardPopup.IsVisible = false; } private void OnKeyClick(object? sender, RoutedEventArgs e) { if (sender is Button button) { targetText.Text += button.Content; } } private void ShowNumberKeyBoard(object? sender, RoutedEventArgs e) { targetText = sendingTimetxt; oldValue = Int32.Parse(targetText.Text); targetText.Text = ""; keyBoardPopup.IsVisible = true; } private void OnBackClick(object? sender, RoutedEventArgs e) { if (!string.IsNullOrEmpty(targetText.Text)) { // Remove the last character from the text box targetText.Text = targetText.Text.Remove(targetText.Text.Length - 1, 1); } } private void EnterClick(object? sender, RoutedEventArgs e) { CancelComButton.Focus(); keyBoardPopup.IsVisible = false; } private void CloseKeyboard() { try { if (_keyboardProcess != null) { // Kill the keyboard process _keyboardProcess.Kill(); _keyboardProcess.Dispose(); _keyboardProcess = null; // Force kill any remaining keyboard processes var processKill = new Process { StartInfo = new ProcessStartInfo { FileName = "killall", Arguments = "-9 onboard matchbox-keyboard florence", // Common Linux on-screen keyboards UseShellExecute = false, CreateNoWindow = true } }; processKill.Start(); processKill.WaitForExit(1000); processKill.Dispose(); } } catch (Exception ex) { Console.WriteLine($"Error closing keyboard: {ex.Message}"); } } private void setDefaultSettings() { _mainWindow.minimizeBtn.IsVisible = false; var stackPanel = _mainWindow.HomeTrack.Parent as StackPanel; if (_isFromManualControl) { // Special UI setup when called from ManualControl _mainWindow.HomeTrack.IsVisible = true; _mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black; _mainWindow.RecipeSelTrack.IsVisible = false; _mainWindow.RunInterfaceTrack.IsVisible = false; _mainWindow.RecipePanelTrack.IsVisible = true; _mainWindow.RecipePanelPolygon.Stroke = Avalonia.Media.Brushes.Black; _mainWindow.RecipeEditTrack.IsVisible = false; _mainWindow.SettingTrack.IsVisible = false; _mainWindow.AdvanceSettingsTrack.IsVisible = false; _mainWindow.ManualControlTrack.IsVisible = true; _mainWindow.ManualControlPolygon.Stroke = Avalonia.Media.Brushes.Black; } else { // Original logic for other callers //Set Track Up _mainWindow.HomeTrack.IsVisible = true; _mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black; _mainWindow.RecipeSelTrack.IsVisible = false; _mainWindow.RunInterfaceTrack.IsVisible = false; _mainWindow.RecipePanelTrack.IsVisible = false; _mainWindow.RecipeEditTrack.IsVisible = false; if (_isAdvSetting) { _mainWindow.SettingTrack.IsVisible = false; _mainWindow.AdvanceSettingsTrack.IsVisible = true; _mainWindow.AdvanceSettingsPolygon.Stroke = Avalonia.Media.Brushes.Black; } else { _mainWindow.SettingTrack.IsVisible = true; _mainWindow.SettingPolygon.Stroke = Avalonia.Media.Brushes.Black; _mainWindow.AdvanceSettingsTrack.IsVisible = false; } } _mainWindow.DiagnosticsTrack.IsVisible = false; // Remove the button from its current position stackPanel.Children.Remove(_mainWindow.SoftwareTrack); // Add it back at the end of the StackPanel stackPanel.Children.Add(_mainWindow.SoftwareTrack); _mainWindow.SoftwareTrack.IsVisible = true; _mainWindow.SoftwarePolygon.Stroke = Brush.Parse("#A4275D"); _mainWindow.TitleBtn.IsVisible = false; //Set Footer _mainWindow.footerMsg.IsVisible = false; _mainWindow.footer.Background = Brush.Parse("#f2f2f2"); _mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy"); _mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt"); _mainWindow.footerDateContainer.IsVisible = true; _mainWindow.footerStartBtn.IsVisible = false; _mainWindow.adminBtns.IsVisible = false; } private void showDefaultValues() { var users = _user.ReadUsers(); var allUIUsers = this.GetLogicalDescendants() .OfType() .Where(cb => cb.Classes.Contains("user")) .ToList(); for (int i = 0; i < allUIUsers.Count; i++) { allUIUsers[i].Text = users[i].UserName; } var screenData = _screeen.ReadScreens()?[0]; brightnessValue.Text = screenData?.brightness.ToString(); dimValue.Text = (screenData?.dimSec/60.0).ToString(); offValue.Text = (screenData?.offSec/60.0).ToString(); } }