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

463 lines
15 KiB
C#
Raw 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;
ShapeContainer.AddFigure(new RectangleFigure(name, x, y, w, h));
Upd();
}
catch (FormatException)
{
MessageBox.Show("Некорректный формат числа");
}
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;
if (!TryReadInt(SquareSide.Text, "Side", 1, Math.Min(CanvasW, CanvasH), out int side)) return;
ShapeContainer.AddFigure(new SquareFigure(name, x, y, side));
Upd();
}
catch (FormatException)
{
MessageBox.Show("Некорректный формат числа");
}
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;
ShapeContainer.AddFigure(new EllipseFigure(name, x, y, w, h));
Upd();
}
catch (FormatException)
{
MessageBox.Show("Некорректный формат числа");
}
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;
if (!TryReadInt(CircleD.Text, "Диаметр", 1, Math.Min(CanvasW, CanvasH), out int d)) return;
ShapeContainer.AddFigure(new CircleFigure(name, x, y, d));
Upd();
}
catch (FormatException)
{
MessageBox.Show("Некорректный формат числа");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void ClickPolyStart(object sender, RoutedEventArgs e)
{
try
{
string name = PolyName.Text.Trim();
if (!NameIsValid(name)) throw new Exception("Имя пустое или уже занято.");
_polyExpected = int.Parse(PolyCount.Text);
if (_polyExpected < 3) throw new Exception("Минимум 3 вершины.");
_polyPoints = new List<Point>();
PolyCount.IsEnabled = false;
PolyX.IsEnabled = true;
PolyY.IsEnabled = true;
PolyAddPointBtn.IsEnabled = true;
PolyFinishBtn.IsEnabled = false;
PolyStatus.Text = $"Точек: 0 / {_polyExpected}";
}
catch (FormatException)
{
MessageBox.Show("Некорректный формат числа");
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}
private void ClickPolyAddPoint(object sender, RoutedEventArgs e)
{
try
{
int x = int.Parse(PolyX.Text);
int y = int.Parse(PolyY.Text);
if (_polyPoints.Count >= _polyExpected) throw new Exception("Все точки уже введены.");
_polyPoints.Add(new Point(x, y));
PolyStatus.Text = $"Точек: {_polyPoints.Count} / {_polyExpected}";
if (_polyPoints.Count == _polyExpected)
{
PolyAddPointBtn.IsEnabled = false;
PolyFinishBtn.IsEnabled = true;
}
}
catch (FormatException)
{
MessageBox.Show("Некорректный формат числа");
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}
private void ClickPolyFinish(object sender, RoutedEventArgs e)
{
try
{
string name = PolyName.Text.Trim();
if (!NameIsValid(name)) throw new Exception("Имя пустое или уже занято.");
if (_polyPoints.Count != _polyExpected) throw new Exception("Не все точки введены.");
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
{
string name = TriName.Text.Trim();
if (!NameIsValid(name)) throw new Exception("Имя пустое или уже занято.");
var a = new Point(int.Parse(Ax.Text), int.Parse(Ay.Text));
var b = new Point(int.Parse(Bx.Text), int.Parse(By.Text));
var c = new Point(int.Parse(Cx.Text), int.Parse(Cy.Text));
ShapeContainer.AddFigure(new Triangle(name, a, b, c));
Upd();
}
catch (FormatException)
{
MessageBox.Show("Некорректный формат числа");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void ClickAddTerrainPointSunPointHumanPointText(object sender, RoutedEventArgs e)
{
try
{
string name = SceneName.Text.Trim();
if (!NameIsValid(name)) throw new Exception("Имя пустое или уже занято.");
int x = int.Parse(SceneX.Text);
int y = int.Parse(SceneY.Text);
int sceneW = int.Parse(SceneW.Text);
int sceneH = int.Parse(SceneH.Text);
ShapeContainer.AddFigure(new TerrainPointSunPointHumanPointText(name, x, y, sceneW, sceneH));
Upd();
}
catch (FormatException)
{
MessageBox.Show("Некорректный формат числа");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void ClickMoveSelected(object sender, RoutedEventArgs e)
{
try
{
var fig = GetSelectedFigureOrThrow();
int dx = int.Parse(MoveDx.Text);
int dy = int.Parse(MoveDy.Text);
fig.MoveBy(dx, dy);
Redraw();
}
catch (FormatException)
{
MessageBox.Show("Некорректный формат числа");
}
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);
}
}
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 bool NameIsValid(string? name)
{
if (string.IsNullOrWhiteSpace(name)) return false;
if (ShapeContainer.FigureList.Any(f => f.Name == name)) return false;
return true;
}
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;
}
}
}