From 272ed999d8863c78be1bf53fd7496b4cd81a43ad Mon Sep 17 00:00:00 2001 From: Frozd Date: Mon, 2 Mar 2026 15:33:56 +0100 Subject: [PATCH] feat: reordering --- CarManagerV3/Car.cs | 2 +- CarManagerV3/CarCard.Designer.cs | 4 +-- CarManagerV3/CarCard.cs | 21 +++++++++---- CarManagerV3/CarCard.resx | 4 +-- CarManagerV3/CarManagerV3.csproj | 5 ++- CarManagerV3/Class1.cs | 12 ------- CarManagerV3/LegacyException.cs | 16 ++++++++++ CarManagerV3/MainForm.cs | 54 +++++++++++++++++++++++++++----- CarManagerV3/SafeManager.cs | 24 ++++++++++++-- CarManagerV3/StateManager.cs | 11 +++++++ 10 files changed, 119 insertions(+), 34 deletions(-) delete mode 100644 CarManagerV3/Class1.cs create mode 100644 CarManagerV3/LegacyException.cs diff --git a/CarManagerV3/Car.cs b/CarManagerV3/Car.cs index 8b7d0a4..431da59 100644 --- a/CarManagerV3/Car.cs +++ b/CarManagerV3/Car.cs @@ -209,7 +209,7 @@ namespace CarManagerV3 /// public bool IsChanged(Car other) { - return this.Make != other.Make || this.Model != other.Model || this.Year != other.Year || this.Color != other.Color || this.Mileage != other.Mileage || this.Price != other.Price || this.Color != other.Color; + return this.Make != other.Make || this.Model != other.Model || this.Year != other.Year || this.Color != other.Color || this.Mileage != other.Mileage || this.Price != other.Price || this.Color != other.Color || this.Order != other.Order; } /// diff --git a/CarManagerV3/CarCard.Designer.cs b/CarManagerV3/CarCard.Designer.cs index 9a0184a..b7a2443 100644 --- a/CarManagerV3/CarCard.Designer.cs +++ b/CarManagerV3/CarCard.Designer.cs @@ -59,7 +59,7 @@ // lblCarDetails // this.lblCarDetails.AutoSize = true; - this.lblCarDetails.Location = new System.Drawing.Point(3, 184); + this.lblCarDetails.Location = new System.Drawing.Point(3, 174); this.lblCarDetails.Name = "lblCarDetails"; this.lblCarDetails.Size = new System.Drawing.Size(101, 16); this.lblCarDetails.TabIndex = 5; @@ -72,7 +72,7 @@ this.lblCarName.Font = new System.Drawing.Font("Arial", 13.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.lblCarName.Location = new System.Drawing.Point(3, 130); this.lblCarName.Name = "lblCarName"; - this.lblCarName.Size = new System.Drawing.Size(204, 54); + this.lblCarName.Size = new System.Drawing.Size(204, 44); this.lblCarName.TabIndex = 4; this.lblCarName.Text = "Skoda Fabia fdsdfsdfsdfsdf"; this.lblCarName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; diff --git a/CarManagerV3/CarCard.cs b/CarManagerV3/CarCard.cs index 1c34a6f..ece30c1 100644 --- a/CarManagerV3/CarCard.cs +++ b/CarManagerV3/CarCard.cs @@ -38,12 +38,14 @@ namespace CarManagerV3 foreach (Control ctrl in this.Controls) { - ctrl.Click += ForwardClick; - foreach (Control inner in ctrl.Controls) // In case you have nested controls - inner.Click += ForwardClick; + ctrl.MouseClick += ForwardClick; + foreach (Control inner in ctrl.Controls) + { + inner.MouseClick += ForwardClick; + } } - this.Click += (s, e) => this.OnCardClicked(); + this.MouseClick += (s, e) => this.OnCardClicked(s, e); } public async void LoadImage() @@ -59,15 +61,22 @@ namespace CarManagerV3 }); } - private void ForwardClick(object sender, EventArgs e) + private void ForwardClick(object sender, MouseEventArgs e) { // Raise your CardClicked event no matter what got clicked + if (e.Button == MouseButtons.Right) return; + + Console.WriteLine($"Forwarding click from {sender.GetType().Name}"); CardClicked?.Invoke(this, EventArgs.Empty); } public event EventHandler CardClicked; - private void OnCardClicked() + private void OnCardClicked(object sender, MouseEventArgs e) { + Console.WriteLine($"Card clicked at {e.Location} with button {e.Button}"); + if (e.Button == MouseButtons.Right) return; + Console.WriteLine($"Card clicked: {this.CarName}"); + if (this.CardClicked != null) { this.CardClicked(this, EventArgs.Empty); diff --git a/CarManagerV3/CarCard.resx b/CarManagerV3/CarCard.resx index ca00d24..0850e49 100644 --- a/CarManagerV3/CarCard.resx +++ b/CarManagerV3/CarCard.resx @@ -121,7 +121,7 @@ iVBORw0KGgoAAAANSUhEUgAABLAAAALuCAYAAAC+de9yAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL - EgAACxIB0t1+/AAA/7JJREFUeF7s/fuXZ8dZ349K5gs2dggQCJeYXAADx+IWooRLwsUc8Jc44QBfgpwE + EQAACxEBf2RfkQAA/7JJREFUeF7s/fuXZ8dZ349K5gs2dggQCJeYXAADx+IWooRLwsUc8Jc44QBfgpwE MNiAbQIYI3yRrZHUv50VlhewCHG8tIyQLVmyaY/m0jM9PT09Mz33W3dPT09Pz4zGwsn5S3RWXZ6n3s+7 an96ZBvb2O/3Ws/au+61a9duTb30VH3uuUeSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmS JEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmS @@ -5505,7 +5505,7 @@ iVBORw0KGgoAAAANSUhEUgAABLAAAALuCAYAAAC+de9yAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL - EgAACxIB0t1+/AAA/7JJREFUeF7s/fuXZ8dZ349K5gs2dggQCJeYXAADx+IWooRLwsUc8Jc44QBfgpwE + EQAACxEBf2RfkQAA/7JJREFUeF7s/fuXZ8dZ349K5gs2dggQCJeYXAADx+IWooRLwsUc8Jc44QBfgpwE MNiAbQIYI3yRrZHUv50VlhewCHG8tIyQLVmyaY/m0jM9PT09Mz33W3dPT09Pz4zGwsn5S3RWXZ6n3s+7 an96ZBvb2O/3Ws/au+61a9duTb30VH3uuUeSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmS JEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmS diff --git a/CarManagerV3/CarManagerV3.csproj b/CarManagerV3/CarManagerV3.csproj index 2b42b76..0dcc141 100644 --- a/CarManagerV3/CarManagerV3.csproj +++ b/CarManagerV3/CarManagerV3.csproj @@ -68,7 +68,7 @@ CarCard.cs - + Form @@ -139,5 +139,8 @@ false + + + \ No newline at end of file diff --git a/CarManagerV3/Class1.cs b/CarManagerV3/Class1.cs deleted file mode 100644 index ba23fd9..0000000 --- a/CarManagerV3/Class1.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace CarManagerV3 -{ - internal class LegacyException : Exception - { - } -} diff --git a/CarManagerV3/LegacyException.cs b/CarManagerV3/LegacyException.cs new file mode 100644 index 0000000..e9fd65c --- /dev/null +++ b/CarManagerV3/LegacyException.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CarManagerV3 +{ + /// + /// LegacyException is a custom exception class used to indicate that a file is in a legacy format that cannot be read by the current version of the application. It is thrown when the SafeManager encounters a file format that it does not recognize, allowing the application to handle this specific case separately from other types of exceptions. + /// + /// + internal class LegacyException : Exception + { + } +} diff --git a/CarManagerV3/MainForm.cs b/CarManagerV3/MainForm.cs index aed2273..e5dd190 100644 --- a/CarManagerV3/MainForm.cs +++ b/CarManagerV3/MainForm.cs @@ -37,6 +37,8 @@ namespace CarManagerV3 showOpenFileDialog(); } + refreshRecents(); + } public void showOpenFileDialog() @@ -56,7 +58,7 @@ namespace CarManagerV3 this.Text = "Car Manager - " + System.IO.Path.GetFileName(filepath); // Sort by Car.Order. If equal, sort by ID - _cars = _cars.Count > 0 ? _cars.OrderBy(c => c.Order).ThenBy(c => c.Id).ToList() : _cars; + _cars = _cars.Count > 0 ? _cars.OrderBy(c => c.Order).ToList() : _cars; if (updateGlobal) { @@ -79,7 +81,7 @@ namespace CarManagerV3 continue; } // compare details - Console.WriteLine($"[L] Checking car: {car.Id} | Car Color: {car.Color} | Ex Color: {existingCar.Color}"); + // Console.WriteLine($"[L] Checking car: {car.Id} | Car Color: {car.Color} | Ex Color: {existingCar.Color}"); if (existingCar.IsChanged(car)) { Console.WriteLine($"[L] Updating car: {car.Id}"); @@ -90,14 +92,14 @@ namespace CarManagerV3 else { // no changes - Console.WriteLine($"[L] No changes for car: {car.Id}"); + // Console.WriteLine($"[L] No changes for car: {car.Id}"); flpCars.Controls.SetChildIndex(existing, _cars.IndexOf(car)); continue; } } card.CarName = $"{car.Make} {car.Model}"; - card.CarDetails = $"{car.Year}, {car.Mileage} km, ${car.Price}"; + card.CarDetails = $"({car.Order}) {car.Year}, {car.Mileage} km, ${car.Price}"; card.Car = car.Clone(); card.LoadImage(); // clear existing event handlers to prevent multiple subscriptions @@ -125,6 +127,42 @@ namespace CarManagerV3 detailsForm.ShowDialog(); }; + ContextMenu cm = new ContextMenu(); + cm.MenuItems.Add(new MenuItem("Move Up", (s, e) => + { + int order = car.Order; + // find car with order just less than this one + Car other = cars.Where(c => c.Order < order).OrderByDescending(c => c.Order).FirstOrDefault(); + if (other != null) + { + Console.WriteLine($"Swapping order of {car.ToString()} ({car.Order}) and {other.ToString()} ({other.Order})"); + int temp = car.Order; + car.Order = other.Order; + other.Order = temp; + SafeManager.SaveCars(filepath, cars); + refreshCars(cars); + } + })); + + cm.MenuItems.Add(new MenuItem("Move Down", (s, e) => + { + + int order = car.Order; + // find car with order just greater than this one + Car other = cars.Where(c => c.Order > order).OrderBy(c => c.Order).FirstOrDefault(); + if (other != null) + { + Console.WriteLine($"Swapping order of {car.ToString()} ({car.Order}) and {other.ToString()} ({other.Order})"); + int temp = car.Order; + car.Order = other.Order; + other.Order = temp; + SafeManager.SaveCars(filepath, cars); + refreshCars(cars); + } + })); + + card.ContextMenu = cm; + if (isNew) { flpCars.Controls.Add(card); @@ -217,7 +255,7 @@ namespace CarManagerV3 dlgOpen.Filter = "CSV Files (*.csv)|*.csv|All Files (*.*)|*.*"; dlgOpen.Title = "Open Car Data File"; // Default to users documents - dlgOpen.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + dlgOpen.InitialDirectory = SafeManager.getRecentFolder(); DialogResult result = dlgOpen.ShowDialog(); if (result == DialogResult.OK) @@ -263,7 +301,7 @@ namespace CarManagerV3 dlgSave.Filter = "CSV Files (*.csv)|*.csv|All Files (*.*)|*.*"; dlgSave.Title = "Save Car Data File As"; // Default to users documents - dlgSave.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + dlgSave.InitialDirectory = SafeManager.getRecentFolder(); DialogResult result = dlgSave.ShowDialog(); if (result == DialogResult.OK) @@ -296,7 +334,7 @@ namespace CarManagerV3 dlgOpen.Filter = "CSV Files (*.csv)|*.csv|All Files (*.*)|*.*"; dlgOpen.Title = "Import Car Data File"; // Default to users documents - dlgOpen.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + dlgOpen.InitialDirectory = SafeManager.getRecentFolder(); DialogResult dlgResult = dlgOpen.ShowDialog(); if (dlgResult == DialogResult.OK) { @@ -320,7 +358,7 @@ namespace CarManagerV3 dlgSave.Filter = "CSV Files (*.csv)|*.csv|All Files (*.*)|*.*"; dlgSave.Title = "Save Merged Car Data File As"; // Default to users documents - dlgSave.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + dlgSave.InitialDirectory = SafeManager.getRecentFolder(); DialogResult saveResult = dlgSave.ShowDialog(); if (saveResult == DialogResult.OK) { diff --git a/CarManagerV3/SafeManager.cs b/CarManagerV3/SafeManager.cs index 47aefad..9f94e73 100644 --- a/CarManagerV3/SafeManager.cs +++ b/CarManagerV3/SafeManager.cs @@ -104,8 +104,9 @@ namespace CarManagerV3 } MessageBox.Show($"Warning: {failedLines.Count} lines in the file could not be parsed and were skipped. Check the console for details.", "Parsing Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); } + cars = StateManager.normalizeOrders(cars); cars = cars.OrderBy(c => c.Order).ToList(); - if(isLegacy) + if (isLegacy) { SafeManager.SaveCars(path, cars); } @@ -213,6 +214,25 @@ namespace CarManagerV3 return paths; } - + /// + /// Gets the folder of the most recently opened file, or the users documents folder if no recent files. + /// + /// + public static string getRecentFolder() + { + List recentPaths = GetRecentPaths(); + if (recentPaths.Count > 0) + { + string recentFile = recentPaths[0]; + if (File.Exists(recentFile)) + { + return Path.GetDirectoryName(recentFile); + } + } + return Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + } + + + } } diff --git a/CarManagerV3/StateManager.cs b/CarManagerV3/StateManager.cs index e635dd6..23ecba5 100644 --- a/CarManagerV3/StateManager.cs +++ b/CarManagerV3/StateManager.cs @@ -119,6 +119,17 @@ namespace CarManagerV3 filePath = path; } + public static List normalizeOrders(List cars) + { + // Normalize the Order field of all cars to be sequential starting from 1, while keeping the relative order the same. + var orderedCars = cars.OrderBy(c => c.Order).ToList(); + for (int i = 0; i < orderedCars.Count; i++) + { + orderedCars[i].Order = i + 1; + } + return orderedCars; + } + public static bool askForMigration() { if (hasConfirmedMigration)