mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-14 13:45:07 -05:00
Finding a part on the nest server meant scrolling 40k drawings: the library could only match an exact thickness or customer and knew nothing about a drawing's size or holes. The library browser gets a Filter dialog with inclusive ranges, and the query API takes them. The server never parses packages and stays off IO, so the server worker now measures each package beside its nest jobs (bounding sides, net area, closed cutouts inside the outline) and stores the summary keyed by package hash (schema v19). Identical geometry is measured once, an unreadable package is recorded once instead of retried forever, and size or hole limits match only measured drawings. Thickness ranges compare in inches across units and keep the library's rule that a drawing saved without a thickness suits any. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
90 lines
4.1 KiB
C#
90 lines
4.1 KiB
C#
namespace OpenNest.Data;
|
|
|
|
/// <summary>
|
|
/// Browse state for Add from Drawing Library: the requested search, sort, page and
|
|
/// nest filter, and the last page applied. By default only drawings with the nest's
|
|
/// material, grade and thickness are listed; <see cref="SetShowAllAsync"/> lifts that
|
|
/// filter. Paging, superseding and disposal follow <see cref="BrowseSession{TPage, TSort}"/>.
|
|
/// Call from one thread (the UI thread).
|
|
/// </summary>
|
|
public sealed class DrawingLibraryBrowseSession : BrowseSession<DrawingLibraryPage, DrawingSortField>
|
|
{
|
|
private readonly IDrawingLibrary _library;
|
|
|
|
/// <param name="nest">The nest to filter to, or null to list every active drawing (File > Drawing Library).</param>
|
|
public DrawingLibraryBrowseSession(IDrawingLibrary library, Nest? nest, int pageSize = DrawingLibraryQuery.DefaultLimit)
|
|
: base(pageSize, DrawingLibraryQuery.MaxLimit, DrawingSortField.SavedAt)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(library);
|
|
|
|
_library = library;
|
|
MaterialName = (nest?.Material?.Name ?? "").Trim();
|
|
MaterialGrade = (nest?.Material?.Grade ?? "").Trim();
|
|
// A nest without a thickness has nothing to match; it filters by material only.
|
|
Thickness = nest != null && double.IsFinite(nest.Thickness) && nest.Thickness > 0
|
|
? DrawingLibraryRules.NormalizeThickness(nest.Thickness)
|
|
: null;
|
|
}
|
|
|
|
/// <summary>The nest's material name, applied unless <see cref="ShowAll"/>; blank means any.</summary>
|
|
public string MaterialName { get; }
|
|
|
|
/// <summary>The nest's grade, applied unless <see cref="ShowAll"/>; blank means any.</summary>
|
|
public string MaterialGrade { get; }
|
|
|
|
/// <summary>The nest's thickness, applied unless <see cref="ShowAll"/>; null means any.</summary>
|
|
public double? Thickness { get; }
|
|
|
|
/// <summary>True when the nest filter is lifted and every active drawing is listed.</summary>
|
|
public bool ShowAll { get; private set; }
|
|
|
|
/// <summary>The Filter dialog's customer and ranges, applied with the nest filter; <see cref="DrawingLibraryFilter.None"/> by default.</summary>
|
|
public DrawingLibraryFilter Filter { get; private set; } = DrawingLibraryFilter.None;
|
|
|
|
/// <summary>True when the latest request narrows by the nest's material, grade or thickness.</summary>
|
|
public bool IsFilteredToNest =>
|
|
!ShowAll && (MaterialName.Length > 0 || MaterialGrade.Length > 0 || Thickness is not null);
|
|
|
|
/// <inheritdoc />
|
|
public override string Summary =>
|
|
PageSummary("drawings",
|
|
!Filter.IsEmpty ? (Search.Length > 0 ? "No drawings match the search and filter." : "No drawings match the filter.")
|
|
: Search.Length > 0 ? "No drawings match the search."
|
|
: IsFilteredToNest ? "No library drawings match this nest's material and thickness. Tick Show all materials to see every drawing."
|
|
: "No drawings in the library.");
|
|
|
|
/// <summary>Lifts or restores the nest filter and returns to the first page.</summary>
|
|
public Task<bool> SetShowAllAsync(bool showAll)
|
|
{
|
|
ShowAll = showAll;
|
|
return FirstPageAsync();
|
|
}
|
|
|
|
/// <summary>Applies the Filter dialog's choices and returns to the first page.</summary>
|
|
public Task<bool> SetFilterAsync(DrawingLibraryFilter filter)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(filter);
|
|
var error = filter.GetValidationError();
|
|
if (error is not null)
|
|
throw new ArgumentException(error, nameof(filter));
|
|
Filter = filter;
|
|
return FirstPageAsync();
|
|
}
|
|
|
|
protected override Task<DrawingLibraryPage> QueryAsync(CancellationToken cancellationToken) =>
|
|
_library.QueryAsync(
|
|
new DrawingLibraryQuery
|
|
{
|
|
Search = Search,
|
|
MaterialName = ShowAll ? "" : MaterialName,
|
|
MaterialGrade = ShowAll ? "" : MaterialGrade,
|
|
Thickness = ShowAll ? null : Thickness,
|
|
Filter = Filter,
|
|
Sort = Sort,
|
|
Descending = Descending,
|
|
Offset = Offset,
|
|
Limit = PageSize,
|
|
},
|
|
cancellationToken);
|
|
}
|