From 3fc32e56e1f5cbe213def927822ebb277a7a77a4 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Mon, 5 Oct 2026 14:50:36 -0400 Subject: [PATCH] feat(ui): drag-and-drop to open .nest files in Database mode Open browses server records in Database mode, with no way to load a local file. Dragging .nest files onto the window (or an open plate) now opens them from disk in either storage mode; PlateView forwards file drops via a new FilesDropped event instead of swallowing them, gated on having a listener so other PlateView hosts are unaffected. A dropped document is unbound, so Save in Database mode creates a new record on first save via the existing storage-mode logic. Co-Authored-By: Claude Sonnet 5 --- OpenNest/Controls/PlateView.cs | 14 ++++++++++++ OpenNest/Forms/MainForm.cs | 39 ++++++++++++++++++++++++++++++++++ docs/nest-storage.md | 7 ++++++ 3 files changed, 60 insertions(+) diff --git a/OpenNest/Controls/PlateView.cs b/OpenNest/Controls/PlateView.cs index c3c01ef..b68709a 100644 --- a/OpenNest/Controls/PlateView.cs +++ b/OpenNest/Controls/PlateView.cs @@ -78,6 +78,12 @@ namespace OpenNest.Controls public event EventHandler> PartRemoved; public event EventHandler StatusChanged; + /// + /// Raised when files are dropped on the plate and something is listening (see + /// ); callers decide which paths to act on. + /// + public event EventHandler FilesDropped; + public event EventHandler SelectionChanged { add => selection.SelectionChanged += value; @@ -305,10 +311,18 @@ namespace OpenNest.Controls { if (drgevent.Data.GetData(typeof(Drawing)) != null) drgevent.Effect = DragDropEffects.Copy; + else if (FilesDropped != null && drgevent.Data.GetDataPresent(DataFormats.FileDrop)) + drgevent.Effect = DragDropEffects.Copy; } protected override void OnDragDrop(DragEventArgs drgevent) { + if (drgevent.Data.GetDataPresent(DataFormats.FileDrop)) + { + FilesDropped?.Invoke(this, (string[])drgevent.Data.GetData(DataFormats.FileDrop)); + return; + } + var dwg = drgevent.Data.GetData(typeof(Drawing)) as Drawing; if (dwg == null) diff --git a/OpenNest/Forms/MainForm.cs b/OpenNest/Forms/MainForm.cs index 80a3169..4956f05 100644 --- a/OpenNest/Forms/MainForm.cs +++ b/OpenNest/Forms/MainForm.cs @@ -69,6 +69,7 @@ namespace OpenNest.Forms clickUpdateLocation = true; this.SetBevel(false); + AllowDrop = true; LoadPosts(); EnableCheck(); @@ -173,6 +174,7 @@ namespace OpenNest.Forms if (remoteId != Guid.Empty) editForm.Document.BindRemote(remoteId, serverUrl); editForm.MdiParent = this; + editForm.PlateView.FilesDropped += (sender, paths) => OpenDroppedNestFiles(paths); editForm.PlateChanged += (sender, e) => { NavigationEnableCheck(); @@ -552,6 +554,43 @@ namespace OpenNest.Forms Settings.Default.Save(); } + protected override void OnDragEnter(DragEventArgs e) + { + base.OnDragEnter(e); + e.Effect = HasDroppedNestFile(e.Data) ? DragDropEffects.Copy : DragDropEffects.None; + } + + protected override void OnDragDrop(DragEventArgs e) + { + base.OnDragDrop(e); + if (e.Data.GetData(DataFormats.FileDrop) is string[] paths) + OpenDroppedNestFiles(paths); + } + + private static bool HasDroppedNestFile(IDataObject data) => + data.GetData(DataFormats.FileDrop) is string[] paths + && paths.Any(path => string.Equals( + Path.GetExtension(path), NestFormat.FileExtension, StringComparison.OrdinalIgnoreCase)); + + /// + /// Opens dropped .nest files locally regardless of storage mode. Loaded documents are + /// not bound to a server record, so Save/Save As follow the normal storage-mode rules + /// (File mode writes to disk; Database mode creates a new record on first save). + /// + private void OpenDroppedNestFiles(IEnumerable paths) + { + foreach (var path in paths) + { + if (!string.Equals(Path.GetExtension(path), NestFormat.FileExtension, StringComparison.OrdinalIgnoreCase)) + continue; + + var reader = new NestReader(path); + var nest = reader.Read(); + LoadNest(nest); + ShowNestWarnings(reader); + } + } + protected override void OnClosing(System.ComponentModel.CancelEventArgs e) { base.OnClosing(e); diff --git a/docs/nest-storage.md b/docs/nest-storage.md index 8ee1917..12b49c0 100644 --- a/docs/nest-storage.md +++ b/docs/nest-storage.md @@ -18,6 +18,13 @@ The desktop app can save nests two ways: modes) for producing a local file to share or back up. Export does not change the document's file save path or database record association. +Dragging one or more `.nest` files onto the main window (or onto an open +plate) opens them from disk directly, in either mode — this is the only way +to open a local file while in Database mode, since Open there browses server +records instead of showing a file dialog. A document opened this way is not +bound to a server record, so a subsequent Save in Database mode creates a new +record on first save, same as any other unbound document. + The mode and server address are stored per-PC at `%APPDATA%\OpenNest\storage.json` (`OpenNest.Data.NestStorageSettings`), defaulting to File mode so existing installs are unaffected until an operator opts in via **File > Storage Mode...**.