/
docNemo
/
clothes-graph
Обзор
Документация
Войти
/
docNemo
/
clothes-graph
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
src/ClothesGraph.App/ViewModels/PieceSeamMapViewModel.cs
144 строки
5 KB
docNemo
Запрос на слияние 'interface-to-spec' (
#1
) из interface-to-spec в main
09 авг 2026, 20:28
Верифицирован
09 авг 2026, 20:28
1bbc436
Код
Авторство
О чём код?
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using ClothesGraph.Geometry; using ClothesGraph.Model.Pieces; using ClothesGraph.Model.Seams; using CommunityToolkit.Mvvm.ComponentModel; namespace ClothesGraph.App.ViewModels; /// <summary>Состояние участка контура на карте швов.</summary> public enum SeamSegmentState { /// <summary>Ни в один шов не входит.</summary> Free, /// <summary>Сшит, длины сходятся.</summary> Sewn, /// <summary>Сшит, но длины расходятся сверх допуска.</summary> Problem } /// <summary>Участок контура детали на карте швов.</summary> public sealed class SeamSegmentViewModel( int index, IReadOnlyList<Point2> points, SeamSegmentState state, string? seamName) { /// <summary>Номер участка в контуре, считая от нуля.</summary> public int Index { get; } = index; /// <summary>Номер для показа — от единицы, как во всех прочих списках.</summary> public int Number => Index + 1; public IReadOnlyList<Point2> Points { get; } = points; public SeamSegmentState State { get; } = state; public string? SeamName { get; } = seamName; /// <summary> /// Цвет участка по его состоянию. /// </summary> /// <remarks> /// Расхождение обязано быть заметно там, где шов правят, а не только в /// перечне: именно на детали видно, какой край не сойдётся. /// </remarks> public string Colour => State switch { SeamSegmentState.Problem => "#FF9B9B", SeamSegmentState.Sewn => "#9BD5A8", _ => "#8A93A6" }; } /// <summary> /// Деталь на вкладке швов: её контур по участкам и выбор участка указанием. /// </summary> public sealed partial class PieceSeamMapViewModel : ObservableObject { private readonly Action<int> _selected; [ObservableProperty] private int? _selectedSegment; [ObservableProperty] private string _hint = string.Empty; internal PieceSeamMapViewModel(Action<int> selected) { _selected = selected; Segments = []; Outline = []; } public ObservableCollection<SeamSegmentViewModel> Segments { get; } public IReadOnlyList<Point2> Outline { get; private set; } /// <summary>Заполняет карту по вычисленной геометрии детали.</summary> internal void Load( PatternPiece? piece, PieceGeometry? geometry, SeamGraph seams, IReadOnlyCollection<SeamId> problems) { Segments.Clear(); Outline = geometry?.Outline ?? []; if (piece is null || geometry is null) { Hint = "Выберите деталь"; OnPropertyChanged(nameof(Outline)); return; } for (var index = 0; index < piece.Contour.Count; index++) { var points = geometry.PointsOf(index); if (points.Count < 2) continue; var seam = seams.SeamOf(new SeamEdge(piece.Id, index)); var state = seam is null ? SeamSegmentState.Free : problems.Contains(seam.Id) ? SeamSegmentState.Problem : SeamSegmentState.Sewn; Segments.Add(new SeamSegmentViewModel(index, points, state, seam?.Name)); } Hint = Segments.Count == 0 ? "Контур ещё не собран" : "Укажите участок на контуре"; OnPropertyChanged(nameof(Outline)); } /// <summary>Участок выбран указанием на карте.</summary> internal void Select(int index) { SelectedSegment = index; _selected(index); } /// <summary>Описание выбранного участка для панели.</summary> public string Describe() { if (SelectedSegment is not { } index) return "участок не выбран"; var segment = Segments.FirstOrDefault(item => item.Index == index); if (segment is null) return "участок не выбран"; return segment.SeamName is { } name ? $"участок {segment.Number} — уже сшит швом «{name}»" : $"участок {segment.Number}"; } }