From e23ae0a47a98a1faef75cf8d3599cda58588d556 Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Fri, 17 Mar 2023 15:02:14 +0100 Subject: [PATCH] Add logo and improve error handling --- ClipCMD/ClipCMD.csproj | 45 +++++++++++++-------- ClipCMD/MainWindow.xaml | 18 ++++++--- ClipCMD/MainWindow.xaml.cs | 79 ++++++++++++++++++++++++++++++++----- ClipCMD/logo.ico | Bin 0 -> 103463 bytes 4 files changed, 110 insertions(+), 32 deletions(-) create mode 100644 ClipCMD/logo.ico diff --git a/ClipCMD/ClipCMD.csproj b/ClipCMD/ClipCMD.csproj index 9bf5502..aae9f95 100644 --- a/ClipCMD/ClipCMD.csproj +++ b/ClipCMD/ClipCMD.csproj @@ -1,20 +1,33 @@  - - WinExe - net7.0-windows - enable - true - 0.0.0.2 - 0.0.0.2 - 0.0.0.2 - + + WinExe + net7.0-windows + enable + true + true + 0.0.0.2 + 0.0.0.2 + 0.0.0.2 + logo.ico + - - - - - - + + + Always + + - + + + + + + + + + + Always + + + \ No newline at end of file diff --git a/ClipCMD/MainWindow.xaml b/ClipCMD/MainWindow.xaml index 0bd061a..064304d 100644 --- a/ClipCMD/MainWindow.xaml +++ b/ClipCMD/MainWindow.xaml @@ -5,15 +5,16 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:ClipCMD" mc:Ignorable="d" - Title="ClipCMD" Height="450" Width="800"> + Title="ClipCMD" Height="450" Width="800" + Closing="OnClose" StateChanged="OnStateChanged" Icon="logo.ico"> @@ -23,14 +24,19 @@ - - + + + + \ No newline at end of file diff --git a/ClipCMD/MainWindow.xaml.cs b/ClipCMD/MainWindow.xaml.cs index 0937b69..7c2ad4d 100644 --- a/ClipCMD/MainWindow.xaml.cs +++ b/ClipCMD/MainWindow.xaml.cs @@ -1,12 +1,13 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Management.Automation; +using System.Management.Automation.Language; using System.Text; using System.Windows; -using System.Windows.Media; using WindowsInput; using WindowsInput.Native; @@ -20,11 +21,25 @@ public partial class MainWindow : Window { private readonly Dictionary commands = new Dictionary(); + private readonly System.Windows.Forms.NotifyIcon notifyIcon; + private WindowState storedWindowState = WindowState.Normal; + private readonly string cmdPath; private readonly string fixPath; public MainWindow() { + notifyIcon = new System.Windows.Forms.NotifyIcon + { + BalloonTipText = "ClipCMD has been minimized. Click the tray icon to show.", + BalloonTipTitle = "ClipCMD", + Text = "ClipCMD", + Icon = new System.Drawing.Icon("logo.ico"), + Visible = true + }; + + notifyIcon.Click += NotifyIcon_Click; + InitializeComponent(); string filePath = System.Reflection.Assembly.GetExecutingAssembly().Location; @@ -62,6 +77,30 @@ public partial class MainWindow : Window } } + private void OnClose(object? sender, CancelEventArgs args) + { + notifyIcon.Dispose(); + } + + private void OnStateChanged(object? sender, EventArgs args) + { + if (WindowState == WindowState.Minimized) + { + Hide(); + notifyIcon?.ShowBalloonTip(2000); + } + else + { + storedWindowState = WindowState; + } + } + + private void NotifyIcon_Click(object? sender, EventArgs e) + { + Show(); + WindowState = storedWindowState; + } + private IDataObject? oldData; private void ClipboardManager_ClipboardChanged(object? sender, EventArgs e) @@ -120,13 +159,14 @@ public partial class MainWindow : Window private void StaticCommandsTextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e) { - //TODO parse commands - string[] lines = commandsTextBox.Text.Split('\n').Append("[#END#]").ToArray(); string commandNames = string.Empty; StringBuilder script = new StringBuilder(); - commandsTextBox.Foreground = Brushes.Black; + commandsTextBox.Foreground = System.Windows.Media.Brushes.Black; + errorPanel.Visibility = Visibility.Collapsed; + logPanel.Visibility = Visibility.Visible; + errorListBox.Items.Clear(); commands.Clear(); foreach (string l in lines) @@ -137,16 +177,25 @@ public partial class MainWindow : Window { if (!string.IsNullOrEmpty(commandNames)) { + _ = Parser.ParseInput(script.ToString(), out _, out ParseError[] errors); + + if (errors.Length > 0) + { + foreach (ParseError error in errors) + { + AddError($"[{commandNames}]\n{error}"); + } + } + foreach (string commandName in commandNames.Split(',')) { - if (!string.IsNullOrWhiteSpace(commandName) && commands.TryAdd(commandName.Trim(), script.ToString())) + if (string.IsNullOrWhiteSpace(commandName)) { - commandsTextBox.Foreground = Brushes.Black; + AddError($"[{commandNames}]\nCommand \"{commandName}\" is empty!"); } - else + else if (!commands.TryAdd(commandName.Trim(), script.ToString())) { - commandsTextBox.Foreground = Brushes.Red; - return; + AddError($"[{commandNames}]\nCommand \"{commandName}\" already exists!"); } } } @@ -163,14 +212,24 @@ public partial class MainWindow : Window } else { - commandsTextBox.Foreground = Brushes.Red; + AddError($"[{commandNames}]\nInput has to start with []!"); return; } } + _ = commands.TryAdd("list", $"\"{string.Join(", ", commands.Keys)}\""); + File.WriteAllText(cmdPath, commandsTextBox.Text); } + private void AddError(string error) + { + errorPanel.Visibility = Visibility.Visible; + logPanel.Visibility = Visibility.Collapsed; + commandsTextBox.Foreground = System.Windows.Media.Brushes.Red; + _ = errorListBox.Items.Add(error); + } + private void FixTextBox_TextChanged(object sender, System.Windows.Input.KeyEventArgs e) { if (prefixTextBox is null || suffixTextBox is null) diff --git a/ClipCMD/logo.ico b/ClipCMD/logo.ico new file mode 100644 index 0000000000000000000000000000000000000000..aff544c613a8ded0b1d6c95963a0409bc76e6143 GIT binary patch literal 103463 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 R<^{$F