feat(ui): add equipment and drawing selectors powered by API\n\n- Inject ICutFabApiClient into MainForm\n- Populate equipment and drawings on load\n- Hook selection changes and pass into export context\n- Resize layout and replace prefix textbox with selectors

This commit is contained in:
AJ
2025-10-28 17:24:00 -04:00
parent b677ac8ec9
commit b122b88435
2 changed files with 126 additions and 88 deletions

View File

@@ -31,11 +31,13 @@
this.activeDocTitleBox = new System.Windows.Forms.TextBox(); this.activeDocTitleBox = new System.Windows.Forms.TextBox();
this.richTextBox1 = new System.Windows.Forms.RichTextBox(); this.richTextBox1 = new System.Windows.Forms.RichTextBox();
this.label1 = new System.Windows.Forms.Label(); this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.prefixTextBox = new System.Windows.Forms.TextBox();
this.button1 = new System.Windows.Forms.Button(); this.button1 = new System.Windows.Forms.Button();
this.label3 = new System.Windows.Forms.Label(); this.label3 = new System.Windows.Forms.Label();
this.comboBox1 = new System.Windows.Forms.ComboBox(); this.comboBox1 = new System.Windows.Forms.ComboBox();
this.label4 = new System.Windows.Forms.Label();
this.equipmentNoBox = new System.Windows.Forms.ComboBox();
this.label5 = new System.Windows.Forms.Label();
this.comboBox2 = new System.Windows.Forms.ComboBox();
this.SuspendLayout(); this.SuspendLayout();
// //
// activeDocTitleBox // activeDocTitleBox
@@ -46,8 +48,8 @@
this.activeDocTitleBox.Location = new System.Drawing.Point(130, 13); this.activeDocTitleBox.Location = new System.Drawing.Point(130, 13);
this.activeDocTitleBox.Name = "activeDocTitleBox"; this.activeDocTitleBox.Name = "activeDocTitleBox";
this.activeDocTitleBox.ReadOnly = true; this.activeDocTitleBox.ReadOnly = true;
this.activeDocTitleBox.Size = new System.Drawing.Size(584, 25); this.activeDocTitleBox.Size = new System.Drawing.Size(748, 25);
this.activeDocTitleBox.TabIndex = 2; this.activeDocTitleBox.TabIndex = 1;
this.activeDocTitleBox.TextChanged += new System.EventHandler(this.activeDocTitleBox_TextChanged); this.activeDocTitleBox.TextChanged += new System.EventHandler(this.activeDocTitleBox_TextChanged);
// //
// richTextBox1 // richTextBox1
@@ -59,8 +61,8 @@
this.richTextBox1.Location = new System.Drawing.Point(12, 106); this.richTextBox1.Location = new System.Drawing.Point(12, 106);
this.richTextBox1.Name = "richTextBox1"; this.richTextBox1.Name = "richTextBox1";
this.richTextBox1.ReadOnly = true; this.richTextBox1.ReadOnly = true;
this.richTextBox1.Size = new System.Drawing.Size(754, 342); this.richTextBox1.Size = new System.Drawing.Size(866, 556);
this.richTextBox1.TabIndex = 3; this.richTextBox1.TabIndex = 10;
this.richTextBox1.Text = ""; this.richTextBox1.Text = "";
// //
// label1 // label1
@@ -69,72 +71,92 @@
this.label1.Location = new System.Drawing.Point(13, 16); this.label1.Location = new System.Drawing.Point(13, 16);
this.label1.Name = "label1"; this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(111, 17); this.label1.Size = new System.Drawing.Size(111, 17);
this.label1.TabIndex = 4; this.label1.TabIndex = 0;
this.label1.Text = "Active document :"; this.label1.Text = "Active document :";
// //
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(23, 47);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(101, 17);
this.label2.TabIndex = 4;
this.label2.Text = "Prefix files with :";
//
// prefixTextBox
//
this.prefixTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.prefixTextBox.Location = new System.Drawing.Point(130, 44);
this.prefixTextBox.Name = "prefixTextBox";
this.prefixTextBox.Size = new System.Drawing.Size(584, 25);
this.prefixTextBox.TabIndex = 2;
//
// button1 // button1
// //
this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.button1.Image = global::ExportDXF.Properties.Resources.play; this.button1.Image = global::ExportDXF.Properties.Resources.play;
this.button1.Location = new System.Drawing.Point(720, 13); this.button1.Location = new System.Drawing.Point(884, 13);
this.button1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); this.button1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.button1.Name = "button1"; this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(46, 56); this.button1.Size = new System.Drawing.Size(46, 56);
this.button1.TabIndex = 0; this.button1.TabIndex = 11;
this.button1.UseVisualStyleBackColor = true; this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click); this.button1.Click += new System.EventHandler(this.button1_Click);
// //
// label3 // label3
// //
this.label3.AutoSize = true; this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(12, 78); this.label3.Location = new System.Drawing.Point(12, 47);
this.label3.Name = "label3"; this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(112, 17); this.label3.Size = new System.Drawing.Size(112, 17);
this.label3.TabIndex = 4; this.label3.TabIndex = 2;
this.label3.Text = "View flip decider :"; this.label3.Text = "View flip decider :";
// //
// comboBox1 // comboBox1
// //
this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBox1.FormattingEnabled = true; this.comboBox1.FormattingEnabled = true;
this.comboBox1.Location = new System.Drawing.Point(130, 75); this.comboBox1.Location = new System.Drawing.Point(130, 44);
this.comboBox1.Name = "comboBox1"; this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(353, 25); this.comboBox1.Size = new System.Drawing.Size(432, 25);
this.comboBox1.TabIndex = 5; this.comboBox1.TabIndex = 3;
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(42, 78);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(82, 17);
this.label4.TabIndex = 4;
this.label4.Text = "Equipment #";
//
// equipmentNoBox
//
this.equipmentNoBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.equipmentNoBox.FormattingEnabled = true;
this.equipmentNoBox.Location = new System.Drawing.Point(130, 75);
this.equipmentNoBox.Name = "equipmentNoBox";
this.equipmentNoBox.Size = new System.Drawing.Size(138, 25);
this.equipmentNoBox.TabIndex = 5;
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(314, 78);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(68, 17);
this.label5.TabIndex = 6;
this.label5.Text = "Drawing #";
//
// comboBox2
//
this.comboBox2.FormattingEnabled = true;
this.comboBox2.Location = new System.Drawing.Point(388, 75);
this.comboBox2.Name = "comboBox2";
this.comboBox2.Size = new System.Drawing.Size(174, 25);
this.comboBox2.TabIndex = 7;
// //
// MainForm // MainForm
// //
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.ClientSize = new System.Drawing.Size(778, 460); this.ClientSize = new System.Drawing.Size(942, 674);
this.Controls.Add(this.comboBox2);
this.Controls.Add(this.equipmentNoBox);
this.Controls.Add(this.label5);
this.Controls.Add(this.comboBox1); this.Controls.Add(this.comboBox1);
this.Controls.Add(this.label4);
this.Controls.Add(this.label3); this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1); this.Controls.Add(this.label1);
this.Controls.Add(this.richTextBox1); this.Controls.Add(this.richTextBox1);
this.Controls.Add(this.prefixTextBox);
this.Controls.Add(this.activeDocTitleBox); this.Controls.Add(this.activeDocTitleBox);
this.Controls.Add(this.button1); this.Controls.Add(this.button1);
this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.MaximizeBox = false; this.MaximizeBox = false;
this.MinimumSize = new System.Drawing.Size(643, 355);
this.Name = "MainForm"; this.Name = "MainForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "ExportDXF"; this.Text = "ExportDXF";
@@ -149,10 +171,12 @@
private System.Windows.Forms.TextBox activeDocTitleBox; private System.Windows.Forms.TextBox activeDocTitleBox;
private System.Windows.Forms.RichTextBox richTextBox1; private System.Windows.Forms.RichTextBox richTextBox1;
private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox prefixTextBox;
private System.Windows.Forms.Label label3; private System.Windows.Forms.Label label3;
private System.Windows.Forms.ComboBox comboBox1; private System.Windows.Forms.ComboBox comboBox1;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.ComboBox equipmentNoBox;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.ComboBox comboBox2;
} }
} }

View File

@@ -1,35 +1,33 @@
using ExportDXF.Extensions; using ExportDXF.Extensions;
using ExportDXF.Models; using ExportDXF.Models;
using ExportDXF.Services; using ExportDXF.Services;
using ExportDXF.ViewFlipDeciders; using ExportDXF.ViewFlipDeciders;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Information;
using System; using System;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
namespace ExportDXF.Forms namespace ExportDXF.Forms
{ {
public partial class MainForm : Form public partial class MainForm : Form
{ {
private readonly ISolidWorksService _solidWorksService; private readonly ISolidWorksService _solidWorksService;
private readonly IDxfExportService _exportService; private readonly IDxfExportService _exportService;
private readonly ICutFabApiClient _apiClient;
private CancellationTokenSource _cancellationTokenSource; private CancellationTokenSource _cancellationTokenSource;
public MainForm(ISolidWorksService solidWorksService, IDxfExportService exportService, ICutFabApiClient apiClient)
public MainForm(ISolidWorksService solidWorksService, IDxfExportService exportService)
{ {
InitializeComponent(); InitializeComponent();
_solidWorksService = solidWorksService ?? _solidWorksService = solidWorksService ??
throw new ArgumentNullException(nameof(solidWorksService)); throw new ArgumentNullException(nameof(solidWorksService));
_exportService = exportService ?? _exportService = exportService ??
throw new ArgumentNullException(nameof(exportService)); throw new ArgumentNullException(nameof(exportService));
_apiClient = apiClient ??
throw new ArgumentNullException(nameof(apiClient));
InitializeViewFlipDeciders(); InitializeViewFlipDeciders();
} }
~MainForm() ~MainForm()
{ {
_cancellationTokenSource?.Dispose(); _cancellationTokenSource?.Dispose();
@@ -37,29 +35,24 @@ namespace ExportDXF.Forms
components?.Dispose(); components?.Dispose();
Dispose(false); Dispose(false);
} }
protected override async void OnLoad(EventArgs e) protected override async void OnLoad(EventArgs e)
{ {
base.OnLoad(e); base.OnLoad(e);
button1.Enabled = false; button1.Enabled = false;
await InitializeAsync(); await InitializeAsync();
} }
private async Task InitializeAsync() private async Task InitializeAsync()
{ {
try try
{ {
LogMessage("Connecting to SolidWorks, this may take a minute..."); LogMessage("Connecting to SolidWorks, this may take a minute...");
await _solidWorksService.ConnectAsync(); await _solidWorksService.ConnectAsync();
_solidWorksService.ActiveDocumentChanged += OnActiveDocumentChanged; _solidWorksService.ActiveDocumentChanged += OnActiveDocumentChanged;
LogMessage("Ready", Color.Green); LogMessage("Ready", Color.Green);
UpdateActiveDocumentDisplay(); UpdateActiveDocumentDisplay();
button1.Enabled = true; button1.Enabled = true;
// Populate equipment and (initial) drawings
await PopulateEquipmentAsync();
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -68,7 +61,58 @@ namespace ExportDXF.Forms
Application.Exit(); Application.Exit();
} }
} }
private async Task PopulateEquipmentAsync()
{
try
{
LogMessage($"Loading equipment from {_apiClient.BaseUrl} ...");
var list = await _apiClient.GetEquipmentAsync();
equipmentNoBox.DisplayMember = nameof(CutFabApiClient.ApiEquipment.EquipmentNumber);
equipmentNoBox.ValueMember = nameof(CutFabApiClient.ApiEquipment.ID);
equipmentNoBox.DataSource = list;
equipmentNoBox.SelectedIndexChanged -= equipmentNoBox_SelectedIndexChanged;
equipmentNoBox.SelectedIndexChanged += equipmentNoBox_SelectedIndexChanged;
if (list != null && list.Count > 0)
{
equipmentNoBox.SelectedIndex = 0;
await PopulateDrawingsForSelectedEquipmentAsync();
LogMessage($"Loaded {list.Count} equipment record(s)", Color.Green);
}
else
{
LogMessage("No equipment returned by API", Color.DarkBlue);
}
}
catch (Exception ex)
{
LogMessage($"Failed to load equipment: {ex.Message}", Color.Red);
}
}
private async void equipmentNoBox_SelectedIndexChanged(object sender, EventArgs e)
{
await PopulateDrawingsForSelectedEquipmentAsync();
}
private async Task PopulateDrawingsForSelectedEquipmentAsync()
{
try
{
var selected = equipmentNoBox.SelectedItem as CutFabApiClient.ApiEquipment;
if (selected == null)
{
comboBox2.DataSource = null;
return;
}
var drawings = await _apiClient.GetDrawingsForEquipmentAsync(selected.ID);
comboBox2.DisplayMember = nameof(CutFabApiClient.ApiDrawingSummary.DrawingNumber);
comboBox2.ValueMember = nameof(CutFabApiClient.ApiDrawingSummary.ID);
comboBox2.DataSource = drawings;
LogMessage($"Loaded {drawings.Count} drawing(s) for equipment {selected.EquipmentNumber}");
}
catch (Exception ex)
{
LogMessage($"Failed to load drawings: {ex.Message}", Color.Red);
}
}
private void InitializeViewFlipDeciders() private void InitializeViewFlipDeciders()
{ {
var items = ViewFlipDeciderFactory.GetAvailableDeciders() var items = ViewFlipDeciderFactory.GetAvailableDeciders()
@@ -78,7 +122,6 @@ namespace ExportDXF.Forms
ViewFlipDecider = d ViewFlipDecider = d
}) })
.ToList(); .ToList();
// Move "Automatic" to the top if it exists // Move "Automatic" to the top if it exists
var automatic = items.FirstOrDefault(i => i.Name == "Automatic"); var automatic = items.FirstOrDefault(i => i.Name == "Automatic");
if (automatic != null) if (automatic != null)
@@ -86,11 +129,9 @@ namespace ExportDXF.Forms
items.Remove(automatic); items.Remove(automatic);
items.Insert(0, automatic); items.Insert(0, automatic);
} }
comboBox1.DataSource = items; comboBox1.DataSource = items;
comboBox1.DisplayMember = "Name"; comboBox1.DisplayMember = "Name";
} }
private async void button1_Click(object sender, EventArgs e) private async void button1_Click(object sender, EventArgs e)
{ {
if (_cancellationTokenSource != null) if (_cancellationTokenSource != null)
@@ -102,39 +143,33 @@ namespace ExportDXF.Forms
await StartExportAsync(); await StartExportAsync();
} }
} }
private async Task StartExportAsync() private async Task StartExportAsync()
{ {
try try
{ {
_cancellationTokenSource = new CancellationTokenSource(); _cancellationTokenSource = new CancellationTokenSource();
var token = _cancellationTokenSource.Token; var token = _cancellationTokenSource.Token;
UpdateUIForExportStart(); UpdateUIForExportStart();
var activeDoc = _solidWorksService.GetActiveDocument(); var activeDoc = _solidWorksService.GetActiveDocument();
if (activeDoc == null) if (activeDoc == null)
{ {
LogMessage("No active document.", Color.Red); LogMessage("No active document.", Color.Red);
return; return;
} }
var viewFlipDecider = GetSelectedViewFlipDecider(); var viewFlipDecider = GetSelectedViewFlipDecider();
var prefix = prefixTextBox.Text; var drawingNumberText = comboBox2.Text?.Trim();
var selectedEquipment = equipmentNoBox.SelectedItem as CutFabApiClient.ApiEquipment;
var exportContext = new ExportContext var exportContext = new ExportContext
{ {
ActiveDocument = activeDoc, ActiveDocument = activeDoc,
ViewFlipDecider = viewFlipDecider, ViewFlipDecider = viewFlipDecider,
FilePrefix = prefix, FilePrefix = drawingNumberText,
EquipmentId = selectedEquipment?.ID,
CancellationToken = token, CancellationToken = token,
ProgressCallback = LogMessage ProgressCallback = LogMessage
}; };
LogMessage($"Started at {DateTime.Now:t}"); LogMessage($"Started at {DateTime.Now:t}");
await Task.Run(() => _exportService.Export(exportContext), token); await Task.Run(() => _exportService.Export(exportContext), token);
LogMessage("Done.", Color.Green); LogMessage("Done.", Color.Green);
} }
catch (OperationCanceledException) catch (OperationCanceledException)
@@ -153,41 +188,33 @@ namespace ExportDXF.Forms
_cancellationTokenSource = null; _cancellationTokenSource = null;
} }
} }
private void CancelExport() private void CancelExport()
{ {
button1.Enabled = false; button1.Enabled = false;
_cancellationTokenSource?.Cancel(); _cancellationTokenSource?.Cancel();
} }
private IViewFlipDecider GetSelectedViewFlipDecider() private IViewFlipDecider GetSelectedViewFlipDecider()
{ {
var item = comboBox1.SelectedItem as ViewFlipDeciderComboboxItem; var item = comboBox1.SelectedItem as ViewFlipDeciderComboboxItem;
return item?.ViewFlipDecider; return item?.ViewFlipDecider;
} }
private void UpdateUIForExportStart() private void UpdateUIForExportStart()
{ {
activeDocTitleBox.Enabled = false; activeDocTitleBox.Enabled = false;
prefixTextBox.Enabled = false;
comboBox1.Enabled = false; comboBox1.Enabled = false;
button1.Image = Properties.Resources.stop_alt; button1.Image = Properties.Resources.stop_alt;
if (richTextBox1.TextLength != 0) if (richTextBox1.TextLength != 0)
{ {
richTextBox1.AppendText("\n\n"); richTextBox1.AppendText("\n\n");
} }
} }
private void UpdateUIForExportComplete() private void UpdateUIForExportComplete()
{ {
activeDocTitleBox.Enabled = true; activeDocTitleBox.Enabled = true;
prefixTextBox.Enabled = true;
comboBox1.Enabled = true; comboBox1.Enabled = true;
button1.Image = Properties.Resources.play; button1.Image = Properties.Resources.play;
button1.Enabled = true; button1.Enabled = true;
} }
private void OnActiveDocumentChanged(object sender, EventArgs e) private void OnActiveDocumentChanged(object sender, EventArgs e)
{ {
if (InvokeRequired) if (InvokeRequired)
@@ -195,47 +222,36 @@ namespace ExportDXF.Forms
Invoke(new Action(() => OnActiveDocumentChanged(sender, e))); Invoke(new Action(() => OnActiveDocumentChanged(sender, e)));
return; return;
} }
UpdateActiveDocumentDisplay(); UpdateActiveDocumentDisplay();
UpdatePrefixFromActiveDocument(); UpdatePrefixFromActiveDocument();
} }
private void UpdateActiveDocumentDisplay() private void UpdateActiveDocumentDisplay()
{ {
var activeDoc = _solidWorksService.GetActiveDocument(); var activeDoc = _solidWorksService.GetActiveDocument();
activeDocTitleBox.Text = activeDoc?.Title ?? "<No Document Open>"; activeDocTitleBox.Text = activeDoc?.Title ?? "<No Document Open>";
} }
private void UpdatePrefixFromActiveDocument() private void UpdatePrefixFromActiveDocument()
{ {
var activeDoc = _solidWorksService.GetActiveDocument(); var activeDoc = _solidWorksService.GetActiveDocument();
if (activeDoc == null) if (activeDoc == null)
{ {
prefixTextBox.Text = string.Empty;
return; return;
} }
if (activeDoc.DocumentType == DocumentType.Drawing) if (activeDoc.DocumentType == DocumentType.Drawing)
{ {
var drawingInfo = DrawingInfo.Parse(activeDoc.Title); var drawingInfo = DrawingInfo.Parse(activeDoc.Title);
if (drawingInfo != null) if (drawingInfo != null)
{ {
prefixTextBox.Text = $"{drawingInfo.JobNo} {drawingInfo.DrawingNo} PT";
prefixTextBox.SelectionStart = prefixTextBox.Text.Length;
} }
} }
else else
{ {
prefixTextBox.Text = string.Empty;
} }
} }
private void activeDocTitleBox_TextChanged(object sender, EventArgs e) private void activeDocTitleBox_TextChanged(object sender, EventArgs e)
{ {
UpdatePrefixFromActiveDocument(); UpdatePrefixFromActiveDocument();
} }
private void LogMessage(string message, Color? color = null) private void LogMessage(string message, Color? color = null)
{ {
if (InvokeRequired) if (InvokeRequired)
@@ -243,7 +259,6 @@ namespace ExportDXF.Forms
Invoke(new Action(() => LogMessage(message, color))); Invoke(new Action(() => LogMessage(message, color)));
return; return;
} }
if (color.HasValue) if (color.HasValue)
{ {
richTextBox1.AppendText(message + System.Environment.NewLine, color.Value); richTextBox1.AppendText(message + System.Environment.NewLine, color.Value);
@@ -252,7 +267,6 @@ namespace ExportDXF.Forms
{ {
richTextBox1.AppendText(message + System.Environment.NewLine); richTextBox1.AppendText(message + System.Environment.NewLine);
} }
richTextBox1.ScrollToCaret(); richTextBox1.ScrollToCaret();
} }
} }