1
0
Files
OAiP-Presnyakov_Ilya-Labora…/Main/MainWindow.xaml.cs
2026-02-26 12:12:38 +03:00

506 lines
16 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using DrawFigureLibrary;
using DrawFigureLibrary.Figures;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace Main
{
public partial class MainWindow : Window
{
private RenderTargetBitmap? _renderTarget ;
private int _polyExpected ;
private List<Point> _polyPoints = new List<Point>() ;
private DrawFigureLibrary.Figure? _mouseSelected ;
private bool _isDragging ;
private Point _lastMouse ;
private int CanvasW => _renderTarget?.PixelWidth ?? 800;
private int CanvasH => _renderTarget?.PixelHeight ?? 400;
private void ClickAddRectangle(object sender, RoutedEventArgs e)
{
try
{
if (!TryReadName(RectName, out string name)) return;
if (!TryReadInt(RectX.Text, "X", 0, CanvasW - 1, out int x)) return;
if (!TryReadInt(RectY.Text, "Y", 0, CanvasH - 1, out int y)) return;
if (!TryReadInt(RectW.Text, "W", 1, CanvasW, out int w)) return;
if (!TryReadInt(RectH.Text, "H", 1, CanvasH, out int h)) return;
if (x + w > CanvasW || y + h > CanvasH)
{
MessageBox.Show("Фигура не помещается в область рисования.");
return;
}
ShapeContainer.AddFigure(new RectangleFigure(name, x, y, w, h));
Upd();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void ClickAddSquare(object sender, RoutedEventArgs e)
{
try
{
if (!TryReadName(SquareName, out string name)) return;
if (!TryReadInt(SquareX.Text, "X", 0, CanvasW - 1, out int x)) return;
if (!TryReadInt(SquareY.Text, "Y", 0, CanvasH - 1, out int y)) return;
int maxSide = Math.Min(CanvasW, CanvasH);
if (!TryReadInt(SquareSide.Text, "Side", 1, maxSide, out int side)) return;
if (x + side > CanvasW || y + side > CanvasH)
{
MessageBox.Show("Фигура не помещается в область рисования.");
return;
}
ShapeContainer.AddFigure(new SquareFigure(name, x, y, side));
Upd();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void ClickAddEllipse(object sender, RoutedEventArgs e)
{
try
{
if (!TryReadName(EllipseName, out string name)) return;
if (!TryReadInt(EllipseX.Text, "X", 0, CanvasW - 1, out int x)) return;
if (!TryReadInt(EllipseY.Text, "Y", 0, CanvasH - 1, out int y)) return;
if (!TryReadInt(EllipseW.Text, "W", 1, CanvasW, out int w)) return;
if (!TryReadInt(EllipseH.Text, "H", 1, CanvasH, out int h)) return;
if (x + w > CanvasW || y + h > CanvasH)
{
MessageBox.Show("Фигура не помещается в область рисования.");
return;
}
ShapeContainer.AddFigure(new EllipseFigure(name, x, y, w, h));
Upd();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void ClickAddCircle(object sender, RoutedEventArgs e)
{
try
{
if (!TryReadName(CircleName, out string name)) return;
if (!TryReadInt(CircleX.Text, "X", 0, CanvasW - 1, out int x)) return;
if (!TryReadInt(CircleY.Text, "Y", 0, CanvasH - 1, out int y)) return;
int maxD = Math.Min(CanvasW, CanvasH);
if (!TryReadInt(CircleD.Text, "Диаметр", 1, maxD, out int d)) return;
if (x + d > CanvasW || y + d > CanvasH)
{
MessageBox.Show("Фигура не помещается в область рисования.");
return;
}
ShapeContainer.AddFigure(new CircleFigure(name, x, y, d));
Upd();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void ClickPolyStart(object sender, RoutedEventArgs e)
{
try
{
if (!TryReadName(PolyName, out string name)) return;
if (!TryReadInt(PolyCount.Text, "Кол-во вершин", 3, 50, out _polyExpected)) return;
_polyPoints = new List<Point>();
PolyCount.IsEnabled = false;
PolyX.IsEnabled = true;
PolyY.IsEnabled = true;
PolyAddPointBtn.IsEnabled = true;
PolyFinishBtn.IsEnabled = false;
PolyStatus.Text = $"Точек: 0 / {_polyExpected}";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void ClickPolyAddPoint(object sender, RoutedEventArgs e)
{
try
{
if (!TryReadInt(PolyX.Text, "X точки", 0, CanvasW - 1, out int x)) return;
if (!TryReadInt(PolyY.Text, "Y точки", 0, CanvasH - 1, out int y)) return;
if (_polyPoints.Count >= _polyExpected)
{
MessageBox.Show("Все точки уже введены.");
return;
}
_polyPoints.Add(new Point(x, y));
PolyStatus.Text = $"Точек: {_polyPoints.Count} / {_polyExpected}";
if (_polyPoints.Count == _polyExpected)
{
PolyAddPointBtn.IsEnabled = false;
PolyFinishBtn.IsEnabled = true;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void ClickPolyFinish(object sender, RoutedEventArgs e)
{
try
{
if (!TryReadName(PolyName, out string name)) return;
if (_polyPoints.Count != _polyExpected)
{
MessageBox.Show("Не все точки введены.");
return;
}
if (_polyPoints.Count < 3)
{
MessageBox.Show("Минимум 3 точки.");
return;
}
ShapeContainer.AddFigure(new PolygonFigure(name, _polyPoints.ToArray()));
Upd();
PolyCount.IsEnabled = true;
PolyX.IsEnabled = false;
PolyY.IsEnabled = false;
PolyAddPointBtn.IsEnabled = false;
PolyFinishBtn.IsEnabled = false;
PolyStatus.Text = "";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void ClickAddTriangle(object sender, RoutedEventArgs e)
{
try
{
if (!TryReadName(TriName, out string name)) return;
if (!TryReadInt(Ax.Text, "Ax", 0, CanvasW - 1, out int ax)) return;
if (!TryReadInt(Ay.Text, "Ay", 0, CanvasH - 1, out int ay)) return;
if (!TryReadInt(Bx.Text, "Bx", 0, CanvasW - 1, out int bx)) return;
if (!TryReadInt(By.Text, "By", 0, CanvasH - 1, out int by)) return;
if (!TryReadInt(Cx.Text, "Cx", 0, CanvasW - 1, out int cx)) return;
if (!TryReadInt(Cy.Text, "Cy", 0, CanvasH - 1, out int cy)) return;
var a = new Point(ax, ay);
var b = new Point(bx, by);
var c = new Point(cx, cy);
ShapeContainer.AddFigure(new Triangle(name, a, b, c));
Upd();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void ClickAddTerrainPointSunPointHumanPointText(object sender, RoutedEventArgs e)
{
try
{
if (!TryReadName(SceneName, out string name)) return;
if (!TryReadInt(SceneX.Text, "X", 0, CanvasW - 1, out int x)) return;
if (!TryReadInt(SceneY.Text, "Y", 0, CanvasH - 1, out int y)) return;
if (!TryReadInt(SceneW.Text, "W", 1, CanvasW, out int sceneW)) return;
if (!TryReadInt(SceneH.Text, "H", 1, CanvasH, out int sceneH)) return;
if (x + sceneW > CanvasW || y + sceneH > CanvasH)
{
MessageBox.Show("Сцена не помещается в область рисования.");
return;
}
ShapeContainer.AddFigure(new TerrainPointSunPointHumanPointText(name, x, y, sceneW, sceneH));
Upd();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void ClickMoveSelected(object sender, RoutedEventArgs e)
{
try
{
var fig = GetSelectedFigureOrThrow();
if (!TryReadInt(MoveDx.Text, "dX", -CanvasW, CanvasW, out int dx)) return;
if (!TryReadInt(MoveDy.Text, "dY", -CanvasH, CanvasH, out int dy)) return;
if (fig.MoveByChecked(dx, dy))
Redraw();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void ClickDeleteSelected(object sender, RoutedEventArgs e)
{
try
{
var fig = GetSelectedFigureOrThrow();
bool ok = ShapeContainer.RemoveFigure(fig);
if (!ok) throw new Exception("Фигура для удаления не найдена.");
Upd();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void ClickResizeSelected(object sender, RoutedEventArgs e)
{
try
{
var fig = GetSelectedFigureOrThrow();
if (!TryReadInt(ResizeW.Text, "W", 1, CanvasW, out int newW)) return;
if (!TryReadInt(ResizeH.Text, "H", 1, CanvasH, out int newH)) return;
if (fig is SquareFigure || fig is CircleFigure)
{
if (newW != newH)
{
MessageBox.Show("Для квадрата/круга W должен быть равен H.");
return;
}
}
if (!fig.ResizeToChecked(newW, newH))
{
MessageBox.Show("Фигура не помещается в область рисования.");
return;
}
Redraw();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Init.DrawingImage = DrawingImage;
int width = (int)DrawingImage.Width;
int height = (int)DrawingImage.Height;
if (width <= 0) width = 800;
if (height <= 0) height = 400;
_renderTarget = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
DrawingImage.Source = _renderTarget;
ImgBorder.Width = width;
ImgBorder.Height = height;
Upd();
}
private void Redraw()
{
if (_renderTarget == null) return;
DrawingVisual drawVis = new DrawingVisual();
using (var ctx = drawVis.RenderOpen())
{
foreach (var fig in ShapeContainer.FigureList)
{
fig.Draw(ctx);
}
}
_renderTarget.Clear();
_renderTarget.Render(drawVis);
DrawingImage.Source = _renderTarget;
}
private void RefreshCombo()
{
FigureCombo.ItemsSource = null;
FigureCombo.ItemsSource = ShapeContainer.FigureList.Select(f => f.Name);
if (FigureCombo.Items.Count > 0 && FigureCombo.SelectedIndex < 0)
{
FigureCombo.SelectedIndex = 0;
}
}
private void Upd()
{
Redraw();
RefreshCombo();
}
private Figure GetSelectedFigureOrThrow()
{
if (FigureCombo.SelectedItem == null) throw new Exception("Фигура не выбрана.");
string name = FigureCombo.SelectedItem.ToString()!;
var fig = ShapeContainer.FindByName(name);
if (fig == null) throw new Exception("Фигура для операции не найдена.");
return fig;
}
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var p = e.GetPosition(DrawingImage);
_mouseSelected =
ShapeContainer.FigureList
.AsEnumerable()
.Reverse()
.FirstOrDefault(f => f.HitTest(p));
if (_mouseSelected != null)
{
FigureCombo.SelectedItem = _mouseSelected.Name;
_isDragging = true;
_lastMouse = p;
DrawingImage.CaptureMouse();
e.Handled = true;
}
}
private void MouseMove(object sender, MouseEventArgs e)
{
if (!_isDragging || _mouseSelected == null) return;
if (e.LeftButton != MouseButtonState.Pressed) return;
var p = e.GetPosition(DrawingImage);
int dx = (int)Math.Round(p.X - _lastMouse.X);
int dy = (int)Math.Round(p.Y - _lastMouse.Y);
if (dx == 0 && dy == 0) return;
if (_mouseSelected.MoveByChecked(dx, dy))
{
_lastMouse = p;
Redraw();
}
e.Handled = true;
}
private void MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (!_isDragging) return;
_isDragging = false;
_mouseSelected = null;
DrawingImage.ReleaseMouseCapture();
e.Handled = true;
}
private bool TryReadInt(string raw, string field, int min, int max, out int value)
{
if (!int.TryParse(raw?.Trim(), out value))
{
MessageBox.Show($"Поле \"{field}\": нужно целое число.");
return false;
}
if (value < min || value > max)
{
MessageBox.Show($"Поле \"{field}\": допустимо [{min}..{max}].");
return false;
}
return true;
}
private bool TryReadName(TextBox tb, out string name)
{
name = (tb.Text ?? "").Trim();
if (string.IsNullOrWhiteSpace(name))
{
MessageBox.Show("Имя фигуры не должно быть пустым.");
return false;
}
if (name.Length > 40)
{
MessageBox.Show("Имя фигуры слишком длинное (максимум 40 символов).");
return false;
}
string kostil = name;
if (ShapeContainer.FigureList.Any(f => string.Equals(f.Name, kostil, StringComparison.OrdinalIgnoreCase)))
{
MessageBox.Show("Фигура с таким именем уже существует.");
return false;
}
return true;
}
}
}