feature/cuid #1
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using CarManagerV3.Util;
|
||||||
|
|
||||||
namespace CarManagerV3
|
namespace CarManagerV3
|
||||||
{
|
{
|
||||||
@@ -115,12 +116,15 @@ namespace CarManagerV3
|
|||||||
int numericId = 0;
|
int numericId = 0;
|
||||||
if ((string.IsNullOrWhiteSpace(id) || int.TryParse(id, out numericId)) && id != "0")
|
if ((string.IsNullOrWhiteSpace(id) || int.TryParse(id, out numericId)) && id != "0")
|
||||||
{
|
{
|
||||||
id = Guid.NewGuid().ToString();
|
id = CUID.NewCUID().ToString();
|
||||||
if (numericId > 0)
|
if (numericId > 0)
|
||||||
{
|
{
|
||||||
order = numericId + order;
|
order = numericId + order;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if(id.Length > 8)
|
||||||
|
{
|
||||||
|
id = CUID.NewCUID().ToString();
|
||||||
}
|
}
|
||||||
// Sets the properties using the setters to ensure validation is applied.
|
// Sets the properties using the setters to ensure validation is applied.
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|||||||
245
CarManagerV3/Forms/MainForm.Designer.cs
generated
245
CarManagerV3/Forms/MainForm.Designer.cs
generated
@@ -29,171 +29,170 @@
|
|||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
|
||||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||||
this.flpCars = new System.Windows.Forms.FlowLayoutPanel();
|
flpCars = new System.Windows.Forms.FlowLayoutPanel();
|
||||||
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
|
tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
|
||||||
this.tbxSearch = new System.Windows.Forms.TextBox();
|
tbxSearch = new System.Windows.Forms.TextBox();
|
||||||
this.btnNewCar = new System.Windows.Forms.Button();
|
btnNewCar = new System.Windows.Forms.Button();
|
||||||
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
|
menuStrip1 = new System.Windows.Forms.MenuStrip();
|
||||||
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.saveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
saveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.saveAsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
saveAsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.importToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
importToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.recentFilesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
recentFilesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.revealInFileExplorerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
revealInFileExplorerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.tableLayoutPanel1.SuspendLayout();
|
tableLayoutPanel1.SuspendLayout();
|
||||||
this.tableLayoutPanel2.SuspendLayout();
|
tableLayoutPanel2.SuspendLayout();
|
||||||
this.menuStrip1.SuspendLayout();
|
menuStrip1.SuspendLayout();
|
||||||
this.SuspendLayout();
|
SuspendLayout();
|
||||||
//
|
//
|
||||||
// tableLayoutPanel1
|
// tableLayoutPanel1
|
||||||
//
|
//
|
||||||
this.tableLayoutPanel1.ColumnCount = 1;
|
tableLayoutPanel1.ColumnCount = 1;
|
||||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||||
this.tableLayoutPanel1.Controls.Add(this.flpCars, 0, 2);
|
tableLayoutPanel1.Controls.Add(flpCars, 0, 2);
|
||||||
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 0, 1);
|
tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 1);
|
||||||
this.tableLayoutPanel1.Controls.Add(this.menuStrip1, 0, 0);
|
tableLayoutPanel1.Controls.Add(menuStrip1, 0, 0);
|
||||||
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
|
tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
|
||||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||||
this.tableLayoutPanel1.RowCount = 3;
|
tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
tableLayoutPanel1.RowCount = 3;
|
||||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F));
|
tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F));
|
||||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(802, 458);
|
tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||||
this.tableLayoutPanel1.TabIndex = 0;
|
tableLayoutPanel1.Size = new System.Drawing.Size(802, 572);
|
||||||
this.tableLayoutPanel1.Paint += new System.Windows.Forms.PaintEventHandler(this.tableLayoutPanel1_Paint);
|
tableLayoutPanel1.TabIndex = 0;
|
||||||
|
tableLayoutPanel1.Paint += tableLayoutPanel1_Paint;
|
||||||
//
|
//
|
||||||
// flpCars
|
// flpCars
|
||||||
//
|
//
|
||||||
this.flpCars.AutoScroll = true;
|
flpCars.AutoScroll = true;
|
||||||
this.flpCars.AutoScrollMargin = new System.Drawing.Size(0, 200);
|
flpCars.AutoScrollMargin = new System.Drawing.Size(0, 200);
|
||||||
this.flpCars.Dock = System.Windows.Forms.DockStyle.Fill;
|
flpCars.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
this.flpCars.Location = new System.Drawing.Point(3, 67);
|
flpCars.Location = new System.Drawing.Point(3, 82);
|
||||||
this.flpCars.Name = "flpCars";
|
flpCars.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||||
this.flpCars.Size = new System.Drawing.Size(796, 412);
|
flpCars.Name = "flpCars";
|
||||||
this.flpCars.TabIndex = 1;
|
flpCars.Size = new System.Drawing.Size(796, 515);
|
||||||
|
flpCars.TabIndex = 1;
|
||||||
//
|
//
|
||||||
// tableLayoutPanel2
|
// tableLayoutPanel2
|
||||||
//
|
//
|
||||||
this.tableLayoutPanel2.ColumnCount = 2;
|
tableLayoutPanel2.ColumnCount = 2;
|
||||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||||
this.tableLayoutPanel2.Controls.Add(this.tbxSearch, 0, 0);
|
tableLayoutPanel2.Controls.Add(tbxSearch, 0, 0);
|
||||||
this.tableLayoutPanel2.Controls.Add(this.btnNewCar, 1, 0);
|
tableLayoutPanel2.Controls.Add(btnNewCar, 1, 0);
|
||||||
this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
|
tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 27);
|
tableLayoutPanel2.Location = new System.Drawing.Point(3, 32);
|
||||||
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
|
tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||||
this.tableLayoutPanel2.RowCount = 1;
|
tableLayoutPanel2.Name = "tableLayoutPanel2";
|
||||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
tableLayoutPanel2.RowCount = 1;
|
||||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 34F));
|
tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||||
this.tableLayoutPanel2.Size = new System.Drawing.Size(796, 34);
|
tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 42F));
|
||||||
this.tableLayoutPanel2.TabIndex = 2;
|
tableLayoutPanel2.Size = new System.Drawing.Size(796, 42);
|
||||||
|
tableLayoutPanel2.TabIndex = 2;
|
||||||
//
|
//
|
||||||
// tbxSearch
|
// tbxSearch
|
||||||
//
|
//
|
||||||
this.tbxSearch.Dock = System.Windows.Forms.DockStyle.Fill;
|
tbxSearch.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
this.tbxSearch.Location = new System.Drawing.Point(3, 3);
|
tbxSearch.Location = new System.Drawing.Point(3, 4);
|
||||||
this.tbxSearch.Name = "tbxSearch";
|
tbxSearch.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||||
this.tbxSearch.Size = new System.Drawing.Size(392, 22);
|
tbxSearch.Name = "tbxSearch";
|
||||||
this.tbxSearch.TabIndex = 3;
|
tbxSearch.Size = new System.Drawing.Size(392, 27);
|
||||||
this.tbxSearch.TextChanged += new System.EventHandler(this.tbxSearch_TextChanged);
|
tbxSearch.TabIndex = 3;
|
||||||
|
tbxSearch.TextChanged += tbxSearch_TextChanged;
|
||||||
//
|
//
|
||||||
// btnNewCar
|
// btnNewCar
|
||||||
//
|
//
|
||||||
this.btnNewCar.Location = new System.Drawing.Point(401, 3);
|
btnNewCar.Location = new System.Drawing.Point(401, 4);
|
||||||
this.btnNewCar.Name = "btnNewCar";
|
btnNewCar.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||||
this.btnNewCar.Size = new System.Drawing.Size(75, 23);
|
btnNewCar.Name = "btnNewCar";
|
||||||
this.btnNewCar.TabIndex = 4;
|
btnNewCar.Size = new System.Drawing.Size(75, 29);
|
||||||
this.btnNewCar.Text = "Add Car";
|
btnNewCar.TabIndex = 4;
|
||||||
this.btnNewCar.UseVisualStyleBackColor = true;
|
btnNewCar.Text = "Add Car";
|
||||||
this.btnNewCar.Click += new System.EventHandler(this.btnNewCar_Click);
|
btnNewCar.UseVisualStyleBackColor = true;
|
||||||
|
btnNewCar.Click += btnNewCar_Click;
|
||||||
//
|
//
|
||||||
// menuStrip1
|
// menuStrip1
|
||||||
//
|
//
|
||||||
this.menuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20);
|
menuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20);
|
||||||
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { fileToolStripMenuItem });
|
||||||
this.fileToolStripMenuItem});
|
menuStrip1.Location = new System.Drawing.Point(0, 0);
|
||||||
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
|
menuStrip1.Name = "menuStrip1";
|
||||||
this.menuStrip1.Name = "menuStrip1";
|
menuStrip1.Size = new System.Drawing.Size(802, 28);
|
||||||
this.menuStrip1.Size = new System.Drawing.Size(802, 24);
|
menuStrip1.TabIndex = 3;
|
||||||
this.menuStrip1.TabIndex = 3;
|
menuStrip1.Text = "menuStrip1";
|
||||||
this.menuStrip1.Text = "menuStrip1";
|
|
||||||
//
|
//
|
||||||
// fileToolStripMenuItem
|
// fileToolStripMenuItem
|
||||||
//
|
//
|
||||||
this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { openToolStripMenuItem, saveToolStripMenuItem, saveAsToolStripMenuItem, importToolStripMenuItem, recentFilesToolStripMenuItem, revealInFileExplorerToolStripMenuItem });
|
||||||
this.openToolStripMenuItem,
|
fileToolStripMenuItem.Name = "fileToolStripMenuItem";
|
||||||
this.saveToolStripMenuItem,
|
fileToolStripMenuItem.Size = new System.Drawing.Size(46, 24);
|
||||||
this.saveAsToolStripMenuItem,
|
fileToolStripMenuItem.Text = "File";
|
||||||
this.importToolStripMenuItem,
|
|
||||||
this.recentFilesToolStripMenuItem,
|
|
||||||
this.revealInFileExplorerToolStripMenuItem});
|
|
||||||
this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
|
|
||||||
this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
|
|
||||||
this.fileToolStripMenuItem.Text = "File";
|
|
||||||
//
|
//
|
||||||
// openToolStripMenuItem
|
// openToolStripMenuItem
|
||||||
//
|
//
|
||||||
this.openToolStripMenuItem.Name = "openToolStripMenuItem";
|
openToolStripMenuItem.Name = "openToolStripMenuItem";
|
||||||
this.openToolStripMenuItem.Size = new System.Drawing.Size(187, 22);
|
openToolStripMenuItem.Size = new System.Drawing.Size(238, 26);
|
||||||
this.openToolStripMenuItem.Text = "Open";
|
openToolStripMenuItem.Text = "Open";
|
||||||
this.openToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click);
|
openToolStripMenuItem.Click += openToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
// saveToolStripMenuItem
|
// saveToolStripMenuItem
|
||||||
//
|
//
|
||||||
this.saveToolStripMenuItem.Name = "saveToolStripMenuItem";
|
saveToolStripMenuItem.Name = "saveToolStripMenuItem";
|
||||||
this.saveToolStripMenuItem.Size = new System.Drawing.Size(187, 22);
|
saveToolStripMenuItem.Size = new System.Drawing.Size(238, 26);
|
||||||
this.saveToolStripMenuItem.Text = "Save";
|
saveToolStripMenuItem.Text = "Save";
|
||||||
this.saveToolStripMenuItem.Click += new System.EventHandler(this.saveToolStripMenuItem_Click);
|
saveToolStripMenuItem.Click += saveToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
// saveAsToolStripMenuItem
|
// saveAsToolStripMenuItem
|
||||||
//
|
//
|
||||||
this.saveAsToolStripMenuItem.Name = "saveAsToolStripMenuItem";
|
saveAsToolStripMenuItem.Name = "saveAsToolStripMenuItem";
|
||||||
this.saveAsToolStripMenuItem.Size = new System.Drawing.Size(187, 22);
|
saveAsToolStripMenuItem.Size = new System.Drawing.Size(238, 26);
|
||||||
this.saveAsToolStripMenuItem.Text = "Save as";
|
saveAsToolStripMenuItem.Text = "Save as";
|
||||||
this.saveAsToolStripMenuItem.Click += new System.EventHandler(this.saveAsToolStripMenuItem_Click);
|
saveAsToolStripMenuItem.Click += saveAsToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
// importToolStripMenuItem
|
// importToolStripMenuItem
|
||||||
//
|
//
|
||||||
this.importToolStripMenuItem.Name = "importToolStripMenuItem";
|
importToolStripMenuItem.Name = "importToolStripMenuItem";
|
||||||
this.importToolStripMenuItem.Size = new System.Drawing.Size(187, 22);
|
importToolStripMenuItem.Size = new System.Drawing.Size(238, 26);
|
||||||
this.importToolStripMenuItem.Text = "Import";
|
importToolStripMenuItem.Text = "Import";
|
||||||
this.importToolStripMenuItem.Click += new System.EventHandler(this.importToolStripMenuItem_Click);
|
importToolStripMenuItem.Click += importToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
// recentFilesToolStripMenuItem
|
// recentFilesToolStripMenuItem
|
||||||
//
|
//
|
||||||
this.recentFilesToolStripMenuItem.Name = "recentFilesToolStripMenuItem";
|
recentFilesToolStripMenuItem.Name = "recentFilesToolStripMenuItem";
|
||||||
this.recentFilesToolStripMenuItem.Size = new System.Drawing.Size(187, 22);
|
recentFilesToolStripMenuItem.Size = new System.Drawing.Size(238, 26);
|
||||||
this.recentFilesToolStripMenuItem.Text = "Recent Files";
|
recentFilesToolStripMenuItem.Text = "Recent Files";
|
||||||
this.recentFilesToolStripMenuItem.Click += new System.EventHandler(this.recentFilesToolStripMenuItem_Click);
|
recentFilesToolStripMenuItem.Click += recentFilesToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
// revealInFileExplorerToolStripMenuItem
|
// revealInFileExplorerToolStripMenuItem
|
||||||
//
|
//
|
||||||
this.revealInFileExplorerToolStripMenuItem.Name = "revealInFileExplorerToolStripMenuItem";
|
revealInFileExplorerToolStripMenuItem.Name = "revealInFileExplorerToolStripMenuItem";
|
||||||
this.revealInFileExplorerToolStripMenuItem.Size = new System.Drawing.Size(187, 22);
|
revealInFileExplorerToolStripMenuItem.Size = new System.Drawing.Size(238, 26);
|
||||||
this.revealInFileExplorerToolStripMenuItem.Text = "Reveal in File Explorer";
|
revealInFileExplorerToolStripMenuItem.Text = "Reveal in File Explorer";
|
||||||
this.revealInFileExplorerToolStripMenuItem.Click += new System.EventHandler(this.revealInFileExplorerToolStripMenuItem_Click);
|
revealInFileExplorerToolStripMenuItem.Click += revealInFileExplorerToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
// MainForm
|
// MainForm
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
|
AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(802, 458);
|
ClientSize = new System.Drawing.Size(802, 572);
|
||||||
this.Controls.Add(this.tableLayoutPanel1);
|
Controls.Add(tableLayoutPanel1);
|
||||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
Icon = (System.Drawing.Icon)resources.GetObject("$this.Icon");
|
||||||
this.MainMenuStrip = this.menuStrip1;
|
MainMenuStrip = menuStrip1;
|
||||||
this.MinimumSize = new System.Drawing.Size(818, 497);
|
Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||||
this.Name = "MainForm";
|
MinimumSize = new System.Drawing.Size(818, 609);
|
||||||
this.Text = "Carmanager 3";
|
Name = "MainForm";
|
||||||
this.tableLayoutPanel1.ResumeLayout(false);
|
Text = "Carmanager 3";
|
||||||
this.tableLayoutPanel1.PerformLayout();
|
tableLayoutPanel1.ResumeLayout(false);
|
||||||
this.tableLayoutPanel2.ResumeLayout(false);
|
tableLayoutPanel1.PerformLayout();
|
||||||
this.tableLayoutPanel2.PerformLayout();
|
tableLayoutPanel2.ResumeLayout(false);
|
||||||
this.menuStrip1.ResumeLayout(false);
|
tableLayoutPanel2.PerformLayout();
|
||||||
this.menuStrip1.PerformLayout();
|
menuStrip1.ResumeLayout(false);
|
||||||
this.ResumeLayout(false);
|
menuStrip1.PerformLayout();
|
||||||
|
ResumeLayout(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ namespace CarManagerV3
|
|||||||
int temp = car.Order;
|
int temp = car.Order;
|
||||||
car.Order = other.Order;
|
car.Order = other.Order;
|
||||||
other.Order = temp;
|
other.Order = temp;
|
||||||
|
cars = StateManager.normalizeOrders(cars);
|
||||||
SafeManager.SaveCars(filepath, cars);
|
SafeManager.SaveCars(filepath, cars);
|
||||||
refreshCars(cars);
|
refreshCars(cars);
|
||||||
}
|
}
|
||||||
@@ -155,6 +156,7 @@ namespace CarManagerV3
|
|||||||
int temp = car.Order;
|
int temp = car.Order;
|
||||||
car.Order = other.Order;
|
car.Order = other.Order;
|
||||||
other.Order = temp;
|
other.Order = temp;
|
||||||
|
cars = StateManager.normalizeOrders(cars);
|
||||||
SafeManager.SaveCars(filepath, cars);
|
SafeManager.SaveCars(filepath, cars);
|
||||||
refreshCars(cars);
|
refreshCars(cars);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
|
|
||||||
Version 2.0
|
Version 2.0
|
||||||
|
|
||||||
The primary goals of this format is to allow a simple XML format
|
The primary goals of this format is to allow a simple XML format
|
||||||
that is mostly human readable. The generation and parsing of the
|
that is mostly human readable. The generation and parsing of the
|
||||||
various data types are done through the TypeConverter classes
|
various data types are done through the TypeConverter classes
|
||||||
associated with the data types.
|
associated with the data types.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
... ado.net/XML headers & schema ...
|
... ado.net/XML headers & schema ...
|
||||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
<resheader name="version">2.0</resheader>
|
<resheader name="version">2.0</resheader>
|
||||||
@@ -26,36 +26,36 @@
|
|||||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
<comment>This is a comment</comment>
|
<comment>This is a comment</comment>
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
There are any number of "resheader" rows that contain simple
|
There are any number of "resheader" rows that contain simple
|
||||||
name/value pairs.
|
name/value pairs.
|
||||||
|
|
||||||
Each data row contains a name, and value. The row also contains a
|
Each data row contains a name, and value. The row also contains a
|
||||||
type or mimetype. Type corresponds to a .NET class that support
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
text/value conversion through the TypeConverter architecture.
|
text/value conversion through the TypeConverter architecture.
|
||||||
Classes that don't support this are serialized and stored with the
|
Classes that don't support this are serialized and stored with the
|
||||||
mimetype set.
|
mimetype set.
|
||||||
|
|
||||||
The mimetype is used for serialized objects, and tells the
|
The mimetype is used for serialized objects, and tells the
|
||||||
ResXResourceReader how to depersist the object. This is currently not
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
extensible. For a given mimetype the value must be set accordingly:
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
that the ResXResourceWriter will generate, however the reader can
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
read any of the formats listed below.
|
read any of the formats listed below.
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.binary.base64
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
value : The object must be serialized with
|
value : The object must be serialized with
|
||||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
: and then encoded with base64 encoding.
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.soap.base64
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
value : The object must be serialized with
|
value : The object must be serialized with
|
||||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
: and then encoded with base64 encoding.
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
value : The object must be serialized into a byte array
|
value : The object must be serialized into a byte array
|
||||||
: using a System.ComponentModel.TypeConverter
|
: using a System.ComponentModel.TypeConverter
|
||||||
: and then encoded with base64 encoding.
|
: and then encoded with base64 encoding.
|
||||||
-->
|
-->
|
||||||
|
|||||||
118
CarManagerV3/Util/CUID.cs
Normal file
118
CarManagerV3/Util/CUID.cs
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
using System;
|
||||||
|
using System.Buffers.Binary;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CarManagerV3.Util
|
||||||
|
{
|
||||||
|
internal class CUID
|
||||||
|
{
|
||||||
|
public const int DefaultLength = 6;
|
||||||
|
|
||||||
|
private static int _counter = RandomNumberGenerator.GetInt32(int.MaxValue);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate a random CUID (Collision-resistant Unique Identifier) of a specified length.
|
||||||
|
/// The CUID is designed to be unique across different machines and time, making it suitable for use as an identifier for cars in the application.
|
||||||
|
/// The length must be between 4 and 32 characters to ensure a good balance between uniqueness and readability.
|
||||||
|
/// The generated CUID consists of a combination of alphanumeric characters to ensure uniqueness and readability.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="length">The desired length of the generated CUID</param>
|
||||||
|
/// <param name="prefixWithC">Whether to prefix the CUID with 'c' for better readability and to avoid starting with a digit.</param>"
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string NewCUID(int length = DefaultLength, bool prefixWithC = true)
|
||||||
|
{
|
||||||
|
// CUIDv2 specs allow between 4 and 32 chars.
|
||||||
|
if(length < 4 || length > 32) throw new ArgumentOutOfRangeException("length");
|
||||||
|
|
||||||
|
// We will produce enough encoded chars to satisfy 'length' after prefixing and truncation.
|
||||||
|
// Base64 encodes 3 bytes -> 4 chars. So bytesNeeded ≈ ceil(charsNeeded * 3/4).
|
||||||
|
int charsNeeded = prefixWithC ? (length - 1) : length;
|
||||||
|
int bytesNeeded = (int)Math.Ceiling(charsNeeded * 3.0 / 4.0);
|
||||||
|
|
||||||
|
Span<byte> material = stackalloc byte[32];
|
||||||
|
FillMaterial(material);
|
||||||
|
|
||||||
|
byte[] outputBytes = ExpandWithSha256(material, bytesNeeded);
|
||||||
|
|
||||||
|
string encoded = Base64UrlEncode(outputBytes);
|
||||||
|
|
||||||
|
if (encoded.Length < charsNeeded)
|
||||||
|
{
|
||||||
|
// Extremely unlikely unless length is huge; ensure we have enough by expanding more.
|
||||||
|
// (Kept as a guard; for typical lengths like 24-64, you're fine.)
|
||||||
|
outputBytes = ExpandWithSha256(material, bytesNeeded + 32);
|
||||||
|
encoded = Base64UrlEncode(outputBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
string body = encoded.Substring(0, charsNeeded);
|
||||||
|
return prefixWithC ? ("c" + body) : body;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void FillMaterial(Span<byte> dst32)
|
||||||
|
{
|
||||||
|
// Compose a payload with:
|
||||||
|
// - 16 bytes random
|
||||||
|
// - 8 bytes timestamp (UTC ticks)
|
||||||
|
// - 4 bytes counter
|
||||||
|
// - 4 bytes process/thread noise
|
||||||
|
Span<byte> payload = stackalloc byte[16 + 8 + 4 + 4];
|
||||||
|
|
||||||
|
RandomNumberGenerator.Fill(payload.Slice(0, 16));
|
||||||
|
|
||||||
|
long ticks = DateTime.UtcNow.Ticks;
|
||||||
|
BinaryPrimitives.WriteInt64LittleEndian(payload.Slice(16, 8), ticks);
|
||||||
|
|
||||||
|
int c = Interlocked.Increment(ref _counter);
|
||||||
|
BinaryPrimitives.WriteInt32LittleEndian(payload.Slice(24, 4), c);
|
||||||
|
|
||||||
|
// Some extra variability (not relied on for security)
|
||||||
|
int noise = Environment.ProcessId ^ Thread.CurrentThread.ManagedThreadId ^ (int)Stopwatch.GetTimestamp();
|
||||||
|
BinaryPrimitives.WriteInt32LittleEndian(payload.Slice(28, 4), noise);
|
||||||
|
|
||||||
|
// Hash to produce 32 bytes of uniformly distributed output
|
||||||
|
SHA256.HashData(payload, dst32);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] ExpandWithSha256(ReadOnlySpan<byte> seed32, int bytesNeeded)
|
||||||
|
{
|
||||||
|
if (bytesNeeded <= 0) return Array.Empty<byte>();
|
||||||
|
|
||||||
|
// If <= 32 bytes, we can just take from seed32 by hashing once more for separation.
|
||||||
|
// We'll use SHA256(seed || blockIndex) to generate blocks.
|
||||||
|
int blocks = (int)Math.Ceiling(bytesNeeded / 32.0);
|
||||||
|
byte[] result = new byte[blocks * 32];
|
||||||
|
|
||||||
|
Span<byte> input = stackalloc byte[32 + 4];
|
||||||
|
seed32.CopyTo(input.Slice(0, 32));
|
||||||
|
|
||||||
|
for (int i = 0; i < blocks; i++)
|
||||||
|
{
|
||||||
|
BinaryPrimitives.WriteInt32LittleEndian(input.Slice(32, 4), i);
|
||||||
|
Span<byte> block = result.AsSpan(i * 32, 32);
|
||||||
|
SHA256.HashData(input, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.Length == bytesNeeded) return result;
|
||||||
|
|
||||||
|
byte[] trimmed = new byte[bytesNeeded];
|
||||||
|
Buffer.BlockCopy(result, 0, trimmed, 0, bytesNeeded);
|
||||||
|
return trimmed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string Base64UrlEncode(byte[] bytes)
|
||||||
|
{
|
||||||
|
// Standard base64url without padding per RFC 4648 §5
|
||||||
|
string b64 = Convert.ToBase64String(bytes);
|
||||||
|
return b64.Replace('+', '-').Replace('/', '_').TrimEnd('=');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user