/
docNemo
/
clothes-graph
Обзор
Документация
Войти
/
docNemo
/
clothes-graph
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
src/ClothesGraph.App/Views/DraftView.axaml
297 строк
17 KB
docNemo
Запрос на слияние 'interface-to-spec' (
#1
) из interface-to-spec в main
09 авг 2026, 20:28
Верифицирован
09 авг 2026, 20:28
1bbc436
Код
Авторство
О чём код?
<UserControl xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="clr-namespace:ClothesGraph.App.ViewModels" xmlns:controls="clr-namespace:ClothesGraph.App.Controls" xmlns:rendering="clr-namespace:ClothesGraph.Rendering;assembly=ClothesGraph.Rendering" x:Class="ClothesGraph.App.Views.DraftView" x:DataType="vm:DraftViewModel"> <Grid ColumnDefinitions="*,300"> <!-- Поверхность вывода и слой точек над ней. Наложение возможно потому, что поверхность участвует в композиции, а не встроена отдельным окном. --> <Panel Grid.Column="0" ClipToBounds="True" Background="#1B1D20"> <!-- Подложка лежит ниже поверхности вывода: та очищается прозрачным, поэтому изображение видно сквозь неё. --> <controls:UnderlayLayer x:Name="Underlays" /> <rendering:DraftViewport x:Name="Viewport" /> <controls:DraftOverlay x:Name="Overlay" /> <Border VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="12" Padding="10,6" Background="#B0151820" CornerRadius="4"> <StackPanel Orientation="Horizontal" Spacing="16"> <TextBlock Text="{Binding Status}" Foreground="#C8CEDA" FontSize="12" /> <TextBlock x:Name="ZoomText" Foreground="#8A93A6" FontSize="12" /> </StackPanel> </Border> </Panel> <Border Grid.Column="1" Background="#1B1E26" Padding="14"> <Grid RowDefinitions="Auto,Auto,Auto,Auto,*"> <StackPanel Grid.Row="0" Spacing="8"> <TextBlock Text="Построение" FontSize="15" FontWeight="SemiBold" Foreground="#D6DBE6" /> <!-- Активный размер отдельно от базового: посмотреть другой размер не должно означать изменить смысл документа. --> <TextBlock Text="Размер на чертеже" FontSize="11" Foreground="#8A93A6" /> <ComboBox ItemsSource="{Binding AvailableSizes}" SelectedItem="{Binding ActiveSize}" HorizontalAlignment="Stretch" /> <TextBlock Text="Правка в неосновном размере станет поправкой на него" FontSize="11" Foreground="#FFD08A" TextWrapping="Wrap" IsVisible="{Binding !IsBaseSizeActive}" /> <TextBox Text="{Binding NewPointName}" PlaceholderText="Имя точки" /> <TextBox Text="{Binding NewPointDistance}" PlaceholderText="Расстояние, формула" /> <TextBox Text="{Binding NewPointAngle}" PlaceholderText="Угол в градусах, формула" /> <!-- Поля расстояния и угла служат координатами x и y, когда точка создаётся свободной. --> <Button Content="Точка смещением от выбранной" Command="{Binding AddOffsetPointCommand}" HorizontalAlignment="Stretch" /> <Button Content="Точка на выбранной линии" Command="{Binding AddPointOnCurveCommand}" HorizontalAlignment="Stretch" /> <Button Content="Пересечение двух линий" Command="{Binding AddIntersectionPointCommand}" HorizontalAlignment="Stretch" /> <Button Content="Свободная точка по координатам" Command="{Binding AddFreePointCommand}" HorizontalAlignment="Stretch" /> <Button Content="Отрезок до последней точки" Command="{Binding AddSegmentCommand}" HorizontalAlignment="Stretch" /> <Button Content="Кривая по четырём точкам" Command="{Binding AddCubicCurveCommand}" HorizontalAlignment="Stretch" /> <!-- Порядок выбора определяет форму кривой, поэтому он показан: иначе о нём приходится помнить. --> <TextBlock Text="{Binding PickedPointNames}" FontSize="11" Foreground="#8A93A6" TextWrapping="Wrap" IsVisible="{Binding PickedPointNames, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" /> <TextBlock Text="Кривая берёт четыре точки по порядку выбора: начало, две направляющие, конец" FontSize="11" Foreground="#7C8496" TextWrapping="Wrap" /> </StackPanel> <StackPanel Grid.Row="1" Spacing="8" Margin="0,16,0,0" IsVisible="{Binding HasFormulas}"> <TextBlock Text="Формулы выбранного" FontSize="13" Foreground="#A8B0C0" /> <!-- Полей столько, сколько у построения числовых параметров: у точки смещением это расстояние и угол. --> <ItemsControl ItemsSource="{Binding SelectedFormulas}"> <ItemsControl.ItemTemplate> <DataTemplate x:DataType="vm:FormulaFieldViewModel"> <StackPanel Spacing="3" Margin="0,3"> <TextBlock Text="{Binding Label}" FontSize="11" Foreground="#8A93A6" /> <TextBox Text="{Binding Text}" AcceptsReturn="False" PlaceholderText="Ог/4 + 2" /> </StackPanel> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> <!-- Имена мерок и построений вставляются выбором из списка: набирать их по памяти значит ошибаться в них. --> <ComboBox ItemsSource="{Binding AvailableNames}" SelectedItem="{Binding NameToInsert}" PlaceholderText="Вставить имя мерки или построения" HorizontalAlignment="Stretch" /> <Button Content="Применить" Command="{Binding ApplyFormulaCommand}" HorizontalAlignment="Stretch" /> <!-- Обратная задача: величина снята с образца и стоит числом, но числом она не градируется. --> <Button Content="Подобрать формулу от мерок" Command="{Binding SuggestFormulaCommand}" HorizontalAlignment="Stretch" /> <ListBox ItemsSource="{Binding FormulaSuggestions}" SelectedItem="{Binding SelectedSuggestion}" Background="Transparent" MaxHeight="150" IsVisible="{Binding FormulaSuggestions.Count}"> <ListBox.ItemTemplate> <DataTemplate x:DataType="vm:FormulaSuggestionRow"> <TextBlock Text="{Binding Description}" FontSize="11" Foreground="#C8CEDA" TextWrapping="Wrap" /> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </StackPanel> <StackPanel Grid.Row="2" Spacing="8" Margin="0,12,0,0"> <StackPanel Orientation="Horizontal" Spacing="8"> <Button Content="Отменить" Command="{Binding UndoCommand}" /> <Button Content="Повторить" Command="{Binding RedoCommand}" /> <Button Content="Удалить" Command="{Binding DeleteSelectedCommand}" /> </StackPanel> <Button x:Name="FitButton" Content="Вписать в окно" HorizontalAlignment="Stretch" /> </StackPanel> <StackPanel Grid.Row="3" Margin="0,14,0,0" Spacing="6"> <TextBlock Text="Подложка" Foreground="#A8B0C0" FontSize="12" /> <Button Content="Подложить изображение…" Command="{Binding Underlays.AddCommand}" HorizontalAlignment="Stretch" /> <!-- Обводка привязывается к двум последним выбранным точкам каркаса: пара задаёт и направление, и длину, чего довольно для подобия. --> <Button Content="Обвести по подложке" Command="{Binding StartTracingCommand}" IsVisible="{Binding !IsTracing}" HorizontalAlignment="Stretch" /> <Button Content="Прервать обводку" Command="{Binding CancelTracingCommand}" IsVisible="{Binding IsTracing}" HorizontalAlignment="Stretch" /> <TextBlock Text="{Binding TraceHint}" FontSize="11" Foreground="#FFD08A" TextWrapping="Wrap" IsVisible="{Binding IsTracing}" /> <!-- Контекст переводится на список подложек явно: команды строк принадлежат ему, а не чертёжной вкладке. --> <ItemsControl DataContext="{Binding Underlays}" x:DataType="vm:UnderlayViewModel" ItemsSource="{Binding Rows}"> <ItemsControl.ItemTemplate> <DataTemplate x:DataType="vm:UnderlayRowViewModel"> <Border Background="#22262F" CornerRadius="4" Padding="8" Margin="0,4"> <StackPanel Spacing="4"> <DockPanel> <CheckBox DockPanel.Dock="Left" IsChecked="{Binding IsVisible}" /> <TextBlock Text="{Binding Name}" Foreground="#D6DBE6" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" /> </DockPanel> <TextBlock Text="{Binding Status}" FontSize="11" Foreground="#8A93A6" /> <DockPanel> <TextBlock DockPanel.Dock="Left" Text="Ширина" FontSize="11" Foreground="#8A93A6" VerticalAlignment="Center" Margin="0,0,6,0" /> <TextBox Text="{Binding RealWidth}" FontSize="11" /> </DockPanel> <Grid ColumnDefinitions="*,6,*"> <DockPanel Grid.Column="0"> <TextBlock DockPanel.Dock="Left" Text="x" FontSize="11" Foreground="#8A93A6" VerticalAlignment="Center" Margin="0,0,6,0" /> <TextBox Text="{Binding X}" FontSize="11" /> </DockPanel> <DockPanel Grid.Column="2"> <TextBlock DockPanel.Dock="Left" Text="y" FontSize="11" Foreground="#8A93A6" VerticalAlignment="Center" Margin="0,0,6,0" /> <TextBox Text="{Binding Y}" FontSize="11" /> </DockPanel> </Grid> <DockPanel> <TextBlock DockPanel.Dock="Left" Text="Поворот, °" FontSize="11" Foreground="#8A93A6" VerticalAlignment="Center" Margin="0,0,6,0" /> <NumericUpDown Value="{Binding Rotation}" Minimum="-180" Maximum="180" Increment="1" FormatString="0.#" FontSize="11" /> </DockPanel> <TextBlock Text="Прозрачность" FontSize="11" Foreground="#8A93A6" /> <Slider Value="{Binding Opacity}" Minimum="0.05" Maximum="1" TickFrequency="0.05" IsSnapToTickEnabled="True" /> <StackPanel Orientation="Horizontal" Spacing="4"> <Button Content="выше" FontSize="11" Padding="8,2" Command="{Binding $parent[ItemsControl].((vm:UnderlayViewModel)DataContext).MoveUpCommand}" CommandParameter="{Binding}" /> <Button Content="ниже" FontSize="11" Padding="8,2" Command="{Binding $parent[ItemsControl].((vm:UnderlayViewModel)DataContext).MoveDownCommand}" CommandParameter="{Binding}" /> <Button Content="убрать" FontSize="11" Padding="8,2" Command="{Binding $parent[ItemsControl].((vm:UnderlayViewModel)DataContext).RemoveCommand}" CommandParameter="{Binding}" /> </StackPanel> </StackPanel> </Border> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> <Border IsVisible="{Binding Underlays.Warning, Converter={x:Static ObjectConverters.IsNotNull}}" Background="#18FFB020" BorderBrush="#40FFB020" BorderThickness="1" CornerRadius="4" Padding="8"> <TextBlock Text="{Binding Underlays.Warning}" Foreground="#FFD08A" TextWrapping="Wrap" FontSize="11" /> </Border> <TextBlock Text="Показать размеры поверх" Foreground="#A8B0C0" FontSize="12" Margin="0,8,0,0" /> <ItemsControl ItemsSource="{Binding OverlaidSizes}"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <WrapPanel /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate x:DataType="vm:SizeOverlayOption"> <CheckBox Content="{Binding Size}" IsChecked="{Binding IsShown}" Margin="0,0,10,0" /> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> <!-- Поправки перечислимы и снимаются поштучно: иначе документ незаметно превращается в набор ручных правок, происхождение которых никто не помнит. --> <TextBlock Text="Ручные поправки" Foreground="#A8B0C0" FontSize="12" Margin="0,8,0,0" IsVisible="{Binding HasAdjustments}" /> <ItemsControl ItemsSource="{Binding Adjustments}"> <ItemsControl.ItemTemplate> <DataTemplate x:DataType="vm:AdjustmentRow"> <Border Background="#22262F" CornerRadius="4" Padding="8" Margin="0,3"> <DockPanel> <Button DockPanel.Dock="Right" Content="снять" FontSize="11" Padding="8,2" Margin="6,0,0,0" Command="{Binding $parent[ItemsControl].((vm:DraftViewModel)DataContext).RemoveAdjustmentCommand}" CommandParameter="{Binding}" /> <TextBlock Text="{Binding Text}" FontSize="11" Foreground="#C8CEDA" TextWrapping="Wrap" VerticalAlignment="Center" /> </DockPanel> </Border> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> <TextBlock Text="{Binding EditorError}" Foreground="#FF8080" TextWrapping="Wrap" FontSize="12" /> </StackPanel> <!-- Список неразрешимых построений: пользователю нужно видеть не только что чертёж неполон, но и какое именно построение и почему. --> <Border Grid.Row="4" Margin="0,16,0,0" IsVisible="{Binding HasFailures}" BorderThickness="1" BorderBrush="#40FF6B6B" Background="#18FF6B6B" CornerRadius="4" Padding="10"> <StackPanel Spacing="6"> <TextBlock Text="Неразрешимые построения" FontSize="13" Foreground="#FF9B9B" /> <ItemsControl ItemsSource="{Binding Failures}"> <ItemsControl.ItemTemplate> <DataTemplate x:DataType="vm:DraftFailureMarker"> <StackPanel Margin="0,4"> <TextBlock Text="{Binding Name}" Foreground="#FFC4C4" FontSize="12" /> <TextBlock Text="{Binding Reason}" Foreground="#C89898" FontSize="11" TextWrapping="Wrap" /> </StackPanel> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </StackPanel> </Border> </Grid> </Border> </Grid> </UserControl>