diff --git a/.idea/.idea.MCCAD/.idea/avalonia.xml b/.idea/.idea.MCCAD/.idea/avalonia.xml
index d1d87b8..dbe0298 100644
--- a/.idea/.idea.MCCAD/.idea/avalonia.xml
+++ b/.idea/.idea.MCCAD/.idea/avalonia.xml
@@ -4,8 +4,12 @@
diff --git a/MCCAD/MCCAD.csproj b/MCCAD/MCCAD.csproj
index 3768e4d..04797ee 100644
--- a/MCCAD/MCCAD.csproj
+++ b/MCCAD/MCCAD.csproj
@@ -21,6 +21,17 @@
None
All
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
diff --git a/MCCAD/Models/CadDBContext.cs b/MCCAD/Models/CadDBContext.cs
new file mode 100644
index 0000000..1aa9888
--- /dev/null
+++ b/MCCAD/Models/CadDBContext.cs
@@ -0,0 +1,21 @@
+using Microsoft.EntityFrameworkCore;
+
+namespace MCCAD.Models;
+
+public class CadDBContext : DbContext
+{
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ optionsBuilder.UseLazyLoadingProxies()
+ .UseNpgsql("Host=localhost;User id=postgres;Password=1234;Database=cad_db");
+ }
+
+ public DbSet Users { get; set; }
+ public DbSet Drawings { get; set; }
+ public DbSet Collaborators { get; set; }
+ public DbSet Teams { get; set; }
+ public DbSet Memberships { get; set; }
+
+ public static readonly CadDBContext Instance = new();
+ public static User User;
+}
\ No newline at end of file
diff --git a/MCCAD/Models/Collaborators.cs b/MCCAD/Models/Collaborators.cs
new file mode 100644
index 0000000..e19f5ba
--- /dev/null
+++ b/MCCAD/Models/Collaborators.cs
@@ -0,0 +1,15 @@
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace MCCAD.Models;
+
+
+public class Collaborators
+{
+ public int Id { get; set; }
+ [ForeignKey(nameof(User))]
+ public int UserId { get; set; }
+ public virtual User User { get; set; }
+ [ForeignKey(nameof(Drawing))]
+ public int DrawingId { get; set; }
+ public virtual Drawing Drawing { get; set; }
+}
\ No newline at end of file
diff --git a/MCCAD/Models/Drawing.cs b/MCCAD/Models/Drawing.cs
new file mode 100644
index 0000000..eca0158
--- /dev/null
+++ b/MCCAD/Models/Drawing.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Runtime.CompilerServices;
+
+namespace MCCAD.Models;
+
+public class Drawing: INotifyPropertyChanged
+{
+ private string _name;
+
+ [Key]
+ public int Id { get; set; }
+
+ [Required]
+ public string Name
+ {
+ get => _name;
+ set
+ {
+ if (value == _name) return;
+ _name = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public string Data { get; set; } = "[]";
+ [ForeignKey(nameof(User))]
+ public int UserId { get; set; }
+ public virtual User User { get; set; }
+ public DateTime CreationDate { get; set; }
+ public DateTime LastChange { get; set; }
+ public double Size => double.Round(Data.Length / 1024.0, 2);
+
+ public Drawing()
+ {
+ CreationDate = DateTime.Now.ToUniversalTime();
+ }
+
+ public event PropertyChangedEventHandler? PropertyChanged;
+
+ protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+
+ protected bool SetField(ref T field, T value, [CallerMemberName] string? propertyName = null)
+ {
+ if (EqualityComparer.Default.Equals(field, value)) return false;
+ field = value;
+ OnPropertyChanged(propertyName);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/MCCAD/Models/Membership.cs b/MCCAD/Models/Membership.cs
new file mode 100644
index 0000000..a87796b
--- /dev/null
+++ b/MCCAD/Models/Membership.cs
@@ -0,0 +1,14 @@
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace MCCAD.Models;
+
+public class Membership
+{
+ public int Id { get; set; }
+ [ForeignKey(nameof(User))]
+ public int UserId { get; set; }
+ public virtual User User { get; set; }
+ [ForeignKey(nameof(Team))]
+ public int TeamId { get; set; }
+ public virtual Team Team { get; set; }
+}
\ No newline at end of file
diff --git a/MCCAD/Models/Team.cs b/MCCAD/Models/Team.cs
new file mode 100644
index 0000000..99e3d16
--- /dev/null
+++ b/MCCAD/Models/Team.cs
@@ -0,0 +1,20 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+
+namespace MCCAD.Models;
+
+public class Team
+{
+ public int Id { get; set; }
+ [Required]
+ public string Name { get; set; }
+
+ public string Description { get; set; } = "";
+ [ForeignKey(nameof(Creator))]
+ public int CreatorId { get; set; }
+ public virtual User Creator { get; set; }
+ public int MemberCount => CadDBContext.Instance.Memberships.Count(i => i.TeamId == Id);
+ public DateTime CreatedAt { get; set; } = DateTime.Now.ToUniversalTime();
+}
\ No newline at end of file
diff --git a/MCCAD/Models/User.cs b/MCCAD/Models/User.cs
new file mode 100644
index 0000000..b55e6dc
--- /dev/null
+++ b/MCCAD/Models/User.cs
@@ -0,0 +1,11 @@
+namespace MCCAD.Models;
+
+public class User
+{
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public string Login { get; set; }
+ public string Password { get; set; }
+ public int RoleId { get; set; }
+ public string Description { get; set; } = "";
+}
\ No newline at end of file
diff --git a/MCCAD/ViewLocator.cs b/MCCAD/ViewLocator.cs
index 8892d45..4b2564b 100644
--- a/MCCAD/ViewLocator.cs
+++ b/MCCAD/ViewLocator.cs
@@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using MCCAD.ViewModels;
+using ReactiveUI;
namespace MCCAD;
@@ -34,4 +35,19 @@ public class ViewLocator : IDataTemplate
{
return data is ViewModelBase;
}
+}
+
+public class MainViewLocator : IViewLocator
+{
+
+ private ViewLocator _locator = new ViewLocator();
+ public IViewFor? ResolveView(string? contract = null) where TViewModel : class
+ {
+ return _locator.Build(contract) as IViewFor;
+ }
+
+ public IViewFor? ResolveView(object? instance, string? contract = null)
+ {
+ return _locator.Build(instance) as IViewFor;
+ }
}
\ No newline at end of file
diff --git a/MCCAD/ViewModels/DrawingViewModel.cs b/MCCAD/ViewModels/DrawingViewModel.cs
new file mode 100644
index 0000000..e7c9744
--- /dev/null
+++ b/MCCAD/ViewModels/DrawingViewModel.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text.Json;
+using System.Windows.Input;
+using MCCAD.Models;
+using ReactiveUI;
+
+namespace MCCAD.ViewModels;
+
+public class DrawingViewModel : ViewModelBase, IRoutableViewModel
+{
+ private OvalView _ov;
+ private PolygonView _pv;
+ private LineView _lv;
+ private Drawing _inner;
+
+ private static readonly List _deserializers =
+ [new LineView.Deserializer(), new PolygonView.Deserializer(), new OvalView.Deserializer()];
+
+ public DrawingViewModel(IScreen hostScreen, Drawing drawing)
+ {
+ HostScreen = hostScreen;
+ _inner = drawing;
+ LoadFigures();
+ }
+
+ private void LoadFigures()
+ {
+ foreach (var figure in JsonSerializer.Deserialize>(_inner.Data))
+ foreach (var deserializer in _deserializers)
+ {
+ if (deserializer.TryDeserialize(figure, out var view))
+ {
+ Figures.Add(view);
+ break;
+ }
+ }
+ }
+
+ public OvalView Ov
+ {
+ get => _ov;
+ set => this.RaiseAndSetIfChanged(ref _ov, value);
+ }
+
+ public PolygonView Pv
+ {
+ get => _pv;
+ set => this.RaiseAndSetIfChanged(ref _pv, value);
+ }
+
+ public LineView Lv
+ {
+ get => _lv;
+ set => this.RaiseAndSetIfChanged(ref _lv, value);
+ }
+
+ public ObservableCollection Figures { get; set; } = [];
+ public string? UrlPathSegment { get; } = Guid.NewGuid().ToString();
+ public IScreen HostScreen { get; }
+
+ public ICommand OnSave => ReactiveCommand.Create(() =>
+ {
+ _inner.Data = JsonSerializer.Serialize(Figures.Select(i => i.Save()));
+ _inner.LastChange = DateTime.Now.ToUniversalTime();
+ CadDBContext.Instance.SaveChanges();
+ });
+
+ public ICommand Back => ReactiveCommand.Create(() => { HostScreen.Router.NavigateBack.Execute(); }
+ );
+}
\ No newline at end of file
diff --git a/MCCAD/ViewModels/DrawingsCollectionViewModel.cs b/MCCAD/ViewModels/DrawingsCollectionViewModel.cs
new file mode 100644
index 0000000..6c0b5e8
--- /dev/null
+++ b/MCCAD/ViewModels/DrawingsCollectionViewModel.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Windows.Input;
+using MCCAD.Models;
+using ReactiveUI;
+
+namespace MCCAD.ViewModels;
+
+public class DrawingsCollectionViewModel : ViewModelBase, IRoutableViewModel
+{
+ public DrawingsCollectionViewModel(IScreen hostScreen)
+ {
+ HostScreen = hostScreen;
+ User = CadDBContext.User;
+ }
+
+ public string? UrlPathSegment { get; } = Guid.NewGuid().ToString();
+ public IScreen HostScreen { get; }
+
+ public User User { get; set; }
+ public ObservableCollection Drawings { get; set; } = [];
+ public Drawing? SelectedDrawing { get; set; }
+ public ICommand Exit => ReactiveCommand.Create(() => HostScreen.Router.NavigateBack.Execute());
+
+ public ICommand Open => ReactiveCommand.Create(() =>
+ {
+ if (SelectedDrawing != null)
+ HostScreen.Router.Navigate.Execute(new DrawingViewModel(HostScreen, SelectedDrawing!));
+ });
+
+ public ICommand Delete => ReactiveCommand.Create(() =>
+ {
+ if (SelectedDrawing != null)
+ {
+ if (SelectedDrawing.Id != 0)
+ {
+ CadDBContext.Instance.Drawings.Remove(SelectedDrawing);
+ CadDBContext.Instance.SaveChanges();
+ }
+
+ Drawings.Remove(SelectedDrawing);
+ }
+ });
+
+ public ICommand Save => ReactiveCommand.Create(() =>
+ {
+ if (SelectedDrawing == null) return;
+ if (SelectedDrawing.Id == 0)
+ {
+ CadDBContext.Instance.Drawings.Add(SelectedDrawing);
+ }
+ else
+ {
+ CadDBContext.Instance.Drawings.Update(SelectedDrawing);
+ }
+
+ CadDBContext.Instance.SaveChanges();
+ });
+
+ public ICommand Create => ReactiveCommand.Create(() =>
+ {
+ var dr = new Drawing();
+ dr.User = User;
+ Drawings.Add(dr);
+ SelectedDrawing = dr;
+ });
+
+ public string SelectedDrawingName
+ {
+ get => (SelectedDrawing ?? new Drawing()).Name;
+ set
+ {
+ if (SelectedDrawing != null)
+ SelectedDrawing.Name = value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/MCCAD/ViewModels/LineView.cs b/MCCAD/ViewModels/LineView.cs
index 87c97a4..631f635 100644
--- a/MCCAD/ViewModels/LineView.cs
+++ b/MCCAD/ViewModels/LineView.cs
@@ -2,8 +2,11 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
+using System.Text.Json;
+using Avalonia.Controls.Shapes;
using MCCAD.Models;
using ReactiveUI;
+using Line = MCCAD.Models.Line;
namespace MCCAD.ViewModels;
@@ -17,23 +20,37 @@ public interface IFigureView
public event ShemeUpdate OnNewSheme;
PositionVM Position { get; set; }
public string Name { get; set; }
+ string Save();
+}
+
+public interface IFigureDeserializer
+{
+ bool TryDeserialize(string data, out IFigureView view);
}
public class LineView : ReactiveObject, IFigureView
{
private static int _counter = 1;
- public LineView () {
+ public LineView()
+ {
Position = new PositionVM
{
Chanded = Rebuild
};
- Name = "Line " + _counter++;
+ Name = "Line " + _counter++;
}
+
public event ShemeUpdate OnNewSheme;
- public PositionVM Position { get; set; } = new ();
+ public PositionVM Position { get; set; }
public string Name { get; set; }
+ public string Save()
+ {
+ var data = new Data() { Angle = Angle, Lenght = lenght, Position = Position, Name = Name };
+ return "line " + JsonSerializer.Serialize(data);
+ }
+
private double angle = 45;
private int lenght = 10;
@@ -67,7 +84,32 @@ public class LineView : ReactiveObject, IFigureView
shape = shape.Select(i => new IntPoint(i.X, -i.Y)).ToList();
var yMove = shape.Select(p => p.Y).Min();
shape = shape.Select(p => new IntPoint(p.X, p.Y - yMove)).ToList();
- OnNewSheme.Invoke(shape, this);
+ OnNewSheme?.Invoke(shape, this);
+ }
+
+ public class Data
+ {
+ public string Name { get; set; }
+ public int Angle { get; set; }
+ public int Lenght { get; set; }
+ public PositionVM Position { get; set; }
+ }
+
+ public class Deserializer : IFigureDeserializer
+ {
+ public bool TryDeserialize(string data, out IFigureView? view)
+ {
+ if (!data.StartsWith("line"))
+ {
+ view = null;
+ return false;
+ }
+
+ var parsed = JsonSerializer.Deserialize(data.Substring(data.IndexOf(' ') + 1));
+ view = new LineView()
+ { Name = parsed.Name, Lenght = parsed.Lenght, Position = parsed.Position, Angle = parsed.Angle };
+ return true;
+ }
}
}
@@ -76,20 +118,54 @@ public class PolygonView : ReactiveObject, IFigureView
public event ShemeUpdate OnNewSheme;
public PositionVM Position { get; set; }
public string Name { get; set; }
+
+ public class Data
+ {
+ public string Name { get; set; }
+ public int Corners { get; set; }
+ public int Radius { get; set; }
+ public PositionVM Position { get; set; }
+ }
+
+ public class Deserializer : IFigureDeserializer
+ {
+ public bool TryDeserialize(string data, out IFigureView? view)
+ {
+ if (!data.StartsWith("polygon"))
+ {
+ view = null;
+ return false;
+ }
+
+ var parsed = JsonSerializer.Deserialize(data.Substring(data.IndexOf(' ') + 1));
+
+ view = new PolygonView()
+ { Name = parsed.Name, radius = parsed.Radius, Position = parsed.Position, corners = parsed.Corners };
+ return true;
+ }
+ }
+
+ public string Save()
+ {
+ var data = new Data { Corners = corners, Radius = Radius, Position = Position, Name = Name };
+ return "polygon " + JsonSerializer.Serialize(data);
+ }
+
private int corners = 3;
private int radius = 5;
private int rotate;
private static int _counter = 1;
- public PolygonView() {
+ public PolygonView()
+ {
Position = new PositionVM
{
Chanded = Rebuild
};
- Name = "Polygon " + _counter++;
+ Name = "Polygon " + _counter++;
}
-
+
public int Rotate
{
get { return rotate; }
@@ -163,7 +239,7 @@ public class PolygonView : ReactiveObject, IFigureView
// start = start.Next;
//}
//DrawFromTo(vecs.First.Value, vecs.Last.Value);
- OnNewSheme.Invoke(shape, this);
+ OnNewSheme?.Invoke(shape, this);
}
}
@@ -240,10 +316,58 @@ public class OvalView : ReactiveObject, IFigureView
}
}
- public event ShemeUpdate OnNewSheme;
+ public event ShemeUpdate? OnNewSheme;
public PositionVM Position { get; set; }
public string Name { get; set; }
+ public class Data
+ {
+ public string Name { get; set; }
+ public int Height { get; set; }
+ public int Width { get; set; }
+ public int Top { get; set; }
+ public int Bottom { get; set; }
+ public int Left { get; set; }
+ public int Right { get; set; }
+ public PositionVM Position { get; set; }
+ }
+
+ public class Deserializer : IFigureDeserializer
+ {
+ public bool TryDeserialize(string data, out IFigureView? view)
+ {
+ if (!data.StartsWith("oval"))
+ {
+ view = null;
+ return false;
+ }
+
+ var parsed = JsonSerializer.Deserialize(data.Substring(data.IndexOf(' ') + 1));
+ view = new OvalView
+ {
+ Name = parsed.Name,
+ bottom = parsed.Bottom,
+ top = parsed.Top,
+ heigh = parsed.Height,
+ left = parsed.Left,
+ right = parsed.Right,
+ Position = parsed.Position,
+ width = parsed.Width,
+ };
+ return true;
+ }
+ }
+
+ public string Save()
+ {
+ var data = new Data
+ {
+ Height = heigh, Width = width, Position = Position, Name = Name, Top = top, Bottom = bottom, Left = left,
+ Right = right
+ };
+ return "oval " + JsonSerializer.Serialize(data);
+ }
+
public double NormalizedLenth(double x, double y)
{
var hWidth = width / 2;
@@ -252,15 +376,16 @@ public class OvalView : ReactiveObject, IFigureView
}
private static int _counter = 1;
-
+
public OvalView()
{
Position = new PositionVM
{
Chanded = Rebuild
};
- Name = "Oval " + _counter++;
+ Name = "Oval " + _counter++;
}
+
public void Rebuild()
{
int RoundToInt(double value) => (int)Math.Round(value);
diff --git a/MCCAD/ViewModels/LoginViewModel.cs b/MCCAD/ViewModels/LoginViewModel.cs
new file mode 100644
index 0000000..9fa4524
--- /dev/null
+++ b/MCCAD/ViewModels/LoginViewModel.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Linq;
+using System.Windows.Input;
+using MCCAD.Models;
+using ReactiveUI;
+
+namespace MCCAD.ViewModels;
+
+public class LoginViewModel : ViewModelBase, IRoutableViewModel
+{
+ public LoginViewModel(IScreen hostScreen)
+ {
+ HostScreen = hostScreen;
+ }
+
+ public string? UrlPathSegment { get; } = Guid.NewGuid().ToString();
+ public IScreen HostScreen { get; }
+ public bool InvalidData { get; set; }
+ public string Login { get; set; }
+ public string Password { get; set; }
+
+ public ICommand TryAuth => ReactiveCommand.Create(() =>
+ {
+ if (CadDBContext.Instance.Users.FirstOrDefault(x => x.Login == Login && Password == x.Password) is { } user)
+ {
+ CadDBContext.User = user;
+ switch (user.RoleId)
+ {
+ case 1:
+ HostScreen.Router.Navigate.Execute(new DrawingsCollectionViewModel(HostScreen));
+ break;
+ case 2:
+ HostScreen.Router.Navigate.Execute(new TeamsViewModel(HostScreen));
+ break;
+ }
+ }
+ });
+}
\ No newline at end of file
diff --git a/MCCAD/ViewModels/MainWindowViewModel.cs b/MCCAD/ViewModels/MainWindowViewModel.cs
index 5834d5e..eaca359 100644
--- a/MCCAD/ViewModels/MainWindowViewModel.cs
+++ b/MCCAD/ViewModels/MainWindowViewModel.cs
@@ -1,35 +1,23 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
+using MCCAD.Models;
using ReactiveUI;
namespace MCCAD.ViewModels;
-public class MainWindowViewModel : ViewModelBase
+public class MainWindowViewModel : ViewModelBase, IScreen
{
- private OvalView _ov;
- private PolygonView _pv;
- private LineView _lv;
+ public RoutingState Router { get; private set; }
- public OvalView Ov
+ public MainWindowViewModel()
{
- get => _ov;
- set => this.RaiseAndSetIfChanged(ref _ov, value);
+ Router = new RoutingState();
+ Router.Navigate.Execute(new LoginViewModel(this));
}
- public PolygonView Pv
- {
- get => _pv;
- set => this.RaiseAndSetIfChanged(ref _pv, value);
- }
+ public static string test_data = """
+ [ "oval {\"Name\":\"Oval 1\",\"Height\":10,\"Width\":10,\"Top\":0,\"Bottom\":10,\"Left\":0,\"Right\":10,\"Position\":{\"X\":0,\"Y\":0}}", "polygon {\"Name\":\"Polygon 1\",\"Corners\":7,\"Radius\":32,\"Position\":{\"X\":0,\"Y\":0}}", "line {\"Name\":\"Line 1\",\"Angle\":45,\"Lenght\":10,\"Position\":{\"X\":0,\"Y\":0}}" ]
+ """;
- public LineView Lv
- {
- get => _lv;
- set => this.RaiseAndSetIfChanged(ref _lv, value);
- }
+}
- public int A { get; set; }
- public string Greeting { get; set; }
-
- public ObservableCollection Figures { get; set; } = [];
-}
\ No newline at end of file
diff --git a/MCCAD/ViewModels/TeamsViewModel.cs b/MCCAD/ViewModels/TeamsViewModel.cs
new file mode 100644
index 0000000..7c16310
--- /dev/null
+++ b/MCCAD/ViewModels/TeamsViewModel.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Reactive;
+using System.Windows.Input;
+using DynamicData;
+using MCCAD.Models;
+using ReactiveUI;
+
+namespace MCCAD.ViewModels;
+
+public class TeamsViewModel : ViewModelBase, IRoutableViewModel
+{
+ private string _searchString = "";
+
+ public TeamsViewModel(IScreen hostScreen)
+ {
+ HostScreen = hostScreen;
+ teams = CadDBContext.Instance.Teams.Where(i => i.CreatorId == CadDBContext.User.Id).ToList();
+ Teams.AddRange(teams);
+ }
+
+ private List teams;
+ public ObservableCollection Teams { get; set; } = [];
+ public string? UrlPathSegment { get; } = Guid.NewGuid().ToString();
+ public IScreen HostScreen { get; }
+ public ICommand Exit => ReactiveCommand.Create(() => HostScreen.Router.NavigateBack.Execute());
+
+ public string SearchString
+ {
+ get => _searchString;
+ set
+ {
+ _searchString = value;
+ Teams.Clear();
+ Teams.AddRange(string.IsNullOrWhiteSpace(_searchString)
+ ? teams
+ : teams.Where(i => i.Name.Contains(SearchString, StringComparison.CurrentCultureIgnoreCase)));
+ }
+ }
+}
\ No newline at end of file
diff --git a/MCCAD/Views/DrawingView.axaml b/MCCAD/Views/DrawingView.axaml
new file mode 100644
index 0000000..824d32c
--- /dev/null
+++ b/MCCAD/Views/DrawingView.axaml
@@ -0,0 +1,156 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Новый элипс
+ Новый многоугольник
+ Новая линия
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Угол
+
+
+ Длина
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Слои
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MCCAD/Views/DrawingView.axaml.cs b/MCCAD/Views/DrawingView.axaml.cs
new file mode 100644
index 0000000..83c6473
--- /dev/null
+++ b/MCCAD/Views/DrawingView.axaml.cs
@@ -0,0 +1,237 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.Primitives;
+using Avalonia.Interactivity;
+using Avalonia.Layout;
+using Avalonia.Media;
+using MCCAD.Models;
+using MCCAD.ViewModels;
+using ReactiveUI.Avalonia;
+
+namespace MCCAD.Views;
+
+public partial class DrawingView : ReactiveUserControl
+{
+ public Dictionary _cache = new();
+ public bool mark = true;
+ private const int BlockSize = 15;
+
+ private bool _switching;
+
+ public DrawingView()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnDataContextChanged(EventArgs e)
+ {
+ if (ViewModel != null)
+ {
+ foreach (var viewModelFigure in ViewModel.Figures)
+ {
+ viewModelFigure.OnNewSheme += DrawShape;
+ viewModelFigure.Rebuild();
+ }
+ }
+ }
+
+
+ void DrawShape(List points, IFigureView view)
+ {
+ if (!_cache.TryGetValue(view, out Canvas canvas))
+ {
+ canvas = new Canvas();
+ _cache.Add(view, canvas);
+ SchemeCanvas.Children.Add(canvas);
+ }
+
+ canvas.Children.Clear();
+
+ canvas.Width = points.Select(i => i.X).Max() * BlockSize;
+ canvas.Height = points.Select(i => i.Y).Max() * BlockSize;
+ Dictionary markup = new Dictionary();
+
+ if (mark)
+ {
+ var lined = points.OrderBy(i => i.Y).GroupBy(i => i.Y);
+ foreach (var l in lined)
+ {
+ if (l.Count() < 3)
+ continue;
+ var line = l.OrderBy(i => i.X).ToList();
+ var linePoint = new List { 0 };
+ for (int i = 0; i < line.Count; i++)
+ {
+ if (i != line.Count - 1 && line[i].X != line[i + 1].X - 1)
+ {
+ linePoint.Add(i);
+ linePoint.Add(i + 1);
+ }
+ }
+
+ linePoint.Add(line.Count - 1);
+
+ var linesIds = linePoint.Chunk(2);
+ foreach (var microLineId in linesIds)
+ {
+ var micloLine = line.Skip(microLineId[0]).Take(microLineId[1] - microLineId[0] + 1).ToList();
+ if (micloLine.Count > 2)
+ {
+ markup.Add(micloLine.First(), "←");
+ markup.Add(micloLine.Last(), "→");
+ markup.Add(micloLine[micloLine.Count / 2], micloLine.Count.ToString());
+ }
+ }
+ }
+
+ lined = points.OrderBy(i => i.X).GroupBy(i => i.X);
+ foreach (var l in lined)
+ {
+ if (l.Count() < 3)
+ continue;
+ var line = l.OrderBy(i => i.Y).ToList();
+ var linePoint = new List() { 0 };
+ for (int i = 0; i < line.Count; i++)
+ {
+ if (i != line.Count - 1 && line[i].Y != line[i + 1].Y - 1)
+ {
+ linePoint.Add(i);
+ linePoint.Add(i + 1);
+ }
+ }
+
+ linePoint.Add(line.Count - 1);
+
+ var linesIds = linePoint.Chunk(2);
+ foreach (var microLineId in linesIds)
+ {
+ var micloLine = line.Skip(microLineId[0]).Take(microLineId[1] - microLineId[0] + 1).ToList();
+ if (micloLine.Count > 2)
+ {
+ if (!markup.TryAdd(micloLine.First(), "↑"))
+ {
+ markup[micloLine.First()] = "+";
+ }
+
+ if (!markup.TryAdd(micloLine.Last(), "↓"))
+ {
+ markup[micloLine.Last()] = "+";
+ }
+
+ markup.Add(micloLine[micloLine.Count / 2], micloLine.Count.ToString());
+ }
+ }
+ }
+ }
+
+ foreach (var point in points)
+ {
+ Border block = new Border();
+ block.Height = BlockSize;
+ block.Width = BlockSize;
+ block.BorderThickness = new Thickness(2);
+ block.Background = new SolidColorBrush(Colors.LightGray);
+ block.DataContext = point;
+ block.PointerEntered += (sender, e) => { CurrentBlock.Text = (sender as Border).DataContext.ToString(); };
+ if (mark)
+ {
+ if (markup.TryGetValue(point, out var text))
+ block.Child = new TextBlock
+ {
+ Text = text, HorizontalAlignment = HorizontalAlignment.Center,
+ VerticalAlignment = VerticalAlignment.Center, FontSize = 10
+ };
+ }
+
+ Canvas.SetLeft(block, (point.X + view.Position.X) * BlockSize);
+ Canvas.SetTop(block, (point.Y + view.Position.Y) * BlockSize);
+ canvas.Children.Add(block);
+ }
+
+ canvas.Width = BlockSize * (points.Select(i => i.X).Max() + 5);
+ canvas.Height = BlockSize * (points.Select(i => i.Y).Max() + 5);
+
+ TotalTB.Text = points.Count.ToString();
+ }
+
+
+ private void Slider_ValueChanged(object? sender, RangeBaseValueChangedEventArgs rangeBaseValueChangedEventArgs)
+ {
+ if (SchemeCanvas == null)
+ return;
+ var e = rangeBaseValueChangedEventArgs;
+ SchemeCanvas.RenderTransform = new ScaleTransform() { ScaleX = e.NewValue / 100, ScaleY = e.NewValue / 100 };
+ ScaleTB.Text = Math.Round(rangeBaseValueChangedEventArgs.NewValue) + "%";
+ }
+
+ private void CreateShape(object? sender, RoutedEventArgs routedEventArgs)
+ {
+ try
+ {
+ var x = (sender as Control).Tag;
+ switch (x)
+ {
+ case "Ov":
+ ViewModel.Ov = new OvalView();
+ ViewModel.Ov.OnNewSheme += DrawShape;
+ ViewModel.Ov.Rebuild();
+ ViewModel.Figures.Add(ViewModel.Ov);
+ SetupVisiblePanel(0);
+ break;
+ case "Pv":
+ ViewModel.Pv = new PolygonView();
+ ViewModel.Pv.OnNewSheme += DrawShape;
+ ViewModel.Pv.Rebuild();
+ ViewModel.Figures.Add(ViewModel.Pv);
+ SetupVisiblePanel(1);
+ break;
+ case "Lv":
+ ViewModel.Lv = new LineView();
+ ViewModel.Lv.OnNewSheme += DrawShape;
+ ViewModel.Lv.Rebuild();
+ ViewModel.Figures.Add(ViewModel.Lv);
+ SetupVisiblePanel(2);
+ break;
+ }
+ }
+ catch (Exception exception)
+ {
+ }
+ }
+
+ private void SetupSelected(object? sender, SelectionChangedEventArgs e)
+ {
+ if (Layers.SelectedItem == null)
+ {
+ return;
+ }
+
+ _switching = true;
+ switch (Layers.SelectedItem)
+ {
+ case OvalView ov:
+ ViewModel.Ov = ov;
+ SetupVisiblePanel(0);
+ break;
+ case PolygonView pv:
+ ViewModel.Pv = pv;
+ SetupVisiblePanel(1);
+ break;
+ case LineView lv:
+ ViewModel.Lv = lv;
+ SetupVisiblePanel(2);
+ break;
+ }
+ }
+
+ private void SetupVisiblePanel(int index)
+ {
+ for (var i = 0; i < ToolsTab.Children.Count; i++)
+ {
+ ToolsTab.Children[i].IsVisible = i == index;
+ }
+ }
+}
\ No newline at end of file
diff --git a/MCCAD/Views/DrawingsCollectionView.axaml b/MCCAD/Views/DrawingsCollectionView.axaml
new file mode 100644
index 0000000..c68595c
--- /dev/null
+++ b/MCCAD/Views/DrawingsCollectionView.axaml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Название
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MCCAD/Views/DrawingsCollectionView.axaml.cs b/MCCAD/Views/DrawingsCollectionView.axaml.cs
new file mode 100644
index 0000000..511b7dc
--- /dev/null
+++ b/MCCAD/Views/DrawingsCollectionView.axaml.cs
@@ -0,0 +1,15 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using MCCAD.ViewModels;
+using ReactiveUI.Avalonia;
+
+namespace MCCAD.Views;
+
+public partial class DrawingsCollectionView : ReactiveUserControl
+{
+ public DrawingsCollectionView()
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/MCCAD/Views/LoginView.axaml b/MCCAD/Views/LoginView.axaml
new file mode 100644
index 0000000..ca45402
--- /dev/null
+++ b/MCCAD/Views/LoginView.axaml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+ Авторизация
+ Введите ваш логин и пароль
+ Логин или пароль неверны
+
+
+
+
+
\ No newline at end of file
diff --git a/MCCAD/Views/LoginView.axaml.cs b/MCCAD/Views/LoginView.axaml.cs
new file mode 100644
index 0000000..6db62ae
--- /dev/null
+++ b/MCCAD/Views/LoginView.axaml.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Threading.Tasks;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using Avalonia.Threading;
+using Avalonia.VisualTree;
+using MCCAD.ViewModels;
+using ReactiveUI.Avalonia;
+
+namespace MCCAD.Views;
+
+public partial class LoginView : ReactiveUserControl
+{
+ private const double Button_VISIBLE = 30;
+
+ public LoginView()
+ {
+ InitializeComponent();
+ }
+
+ private void UpdateLoginVisibility(object? sender, TextChangedEventArgs e)
+ {
+ LoginButton.Height = string.IsNullOrWhiteSpace(LoginText.Text) ||
+ string.IsNullOrWhiteSpace(PasswordText.Text) || PasswordText.Text.Length < 6
+ ? 0
+ : Button_VISIBLE;
+ }
+}
\ No newline at end of file
diff --git a/MCCAD/Views/MainWindow.axaml b/MCCAD/Views/MainWindow.axaml
index 55589ff..1e3c03f 100644
--- a/MCCAD/Views/MainWindow.axaml
+++ b/MCCAD/Views/MainWindow.axaml
@@ -4,152 +4,17 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
- xmlns:mcd="using:MCCAD.ViewModels"
- xmlns:views="clr-namespace:MCCAD.Views"
x:Class="MCCAD.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
+ xmlns:rui="clr-namespace:ReactiveUI.Avalonia;assembly=ReactiveUI.Avalonia"
+ xmlns:mccad="clr-namespace:MCCAD"
Icon="/Assets/avalonia-logo.ico"
Title="MCCAD">
-
-
-
-
-
-
-
-
-
-
-
- Новый элипс
- Новый многоугольник
- Новая линия
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Угол
-
-
- Длина
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Слои
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
\ No newline at end of file
diff --git a/MCCAD/Views/MainWindow.axaml.cs b/MCCAD/Views/MainWindow.axaml.cs
index 8d3e055..98cf828 100644
--- a/MCCAD/Views/MainWindow.axaml.cs
+++ b/MCCAD/Views/MainWindow.axaml.cs
@@ -14,217 +14,8 @@ namespace MCCAD.Views;
public partial class MainWindow : Window
{
- public Dictionary _cache = new();
- public bool mark = true;
- int blockSize = 15;
-
- private bool switching = false;
- private MainWindowViewModel DC => DataContext as MainWindowViewModel;
-
public MainWindow()
{
InitializeComponent();
}
-
- protected override void OnDataContextChanged(EventArgs e)
- {
-
- }
-
-
- void DrawShape(List points, IFigureView view)
- {
- if (!_cache.TryGetValue(view, out Canvas canvas))
- {
- canvas = new Canvas();
- _cache.Add(view, canvas);
- ShemeChanvas.Children.Add(canvas);
- }
- canvas.Children.Clear();
-
- canvas.Width = points.Select(i => i.X).Max() * blockSize;
- canvas.Height = points.Select(i => i.Y).Max() * blockSize;
- Dictionary markup = new Dictionary();
-
- if (mark)
- {
- var lined = points.OrderBy(i => i.Y).GroupBy(i => i.Y);
- foreach (var l in lined)
- {
- if (l.Count() < 3)
- continue;
- var line = l.OrderBy(i => i.X).ToList();
- var linePoint = new List { 0 };
- for (int i = 0; i < line.Count; i++)
- {
- if (i != line.Count - 1 && line[i].X != line[i + 1].X - 1)
- {
- linePoint.Add(i);
- linePoint.Add(i + 1);
- }
- }
-
- linePoint.Add(line.Count - 1);
-
- var linesIds = linePoint.Chunk(2);
- foreach (var microLineId in linesIds)
- {
- var micloLine = line.Skip(microLineId[0]).Take(microLineId[1] - microLineId[0] + 1).ToList();
- if (micloLine.Count > 2)
- {
- markup.Add(micloLine.First(), "←");
- markup.Add(micloLine.Last(), "→");
- markup.Add(micloLine[micloLine.Count / 2], micloLine.Count.ToString());
- }
- }
- }
-
- lined = points.OrderBy(i => i.X).GroupBy(i => i.X);
- foreach (var l in lined)
- {
- if (l.Count() < 3)
- continue;
- var line = l.OrderBy(i => i.Y).ToList();
- var linePoint = new List() { 0 };
- for (int i = 0; i < line.Count; i++)
- {
- if (i != line.Count - 1 && line[i].Y != line[i + 1].Y - 1)
- {
- linePoint.Add(i);
- linePoint.Add(i + 1);
- }
- }
-
- linePoint.Add(line.Count - 1);
-
- var linesIds = linePoint.Chunk(2);
- foreach (var microLineId in linesIds)
- {
- var micloLine = line.Skip(microLineId[0]).Take(microLineId[1] - microLineId[0] + 1).ToList();
- if (micloLine.Count > 2)
- {
- if (!markup.TryAdd(micloLine.First(), "↑"))
- {
- markup[micloLine.First()] = "+";
- }
-
- if (!markup.TryAdd(micloLine.Last(), "↓"))
- {
- markup[micloLine.Last()] = "+";
- }
-
- markup.Add(micloLine[micloLine.Count / 2], micloLine.Count.ToString());
- }
- }
- }
- }
-
- foreach (var point in points)
- {
- Border block = new Border();
- block.Height = blockSize;
- block.Width = blockSize;
- block.BorderThickness = new Thickness(2);
- block.Background = new SolidColorBrush(Colors.LightGray);
- block.DataContext = point;
- block.PointerEntered += (sender, e) => { CurrentBlock.Text = (sender as Border).DataContext.ToString(); };
- if (mark)
- {
- if (markup.TryGetValue(point, out var text))
- block.Child = new TextBlock
- {
- Text = text, HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center, FontSize = 10
- };
- }
-
- Canvas.SetLeft(block, (point.X + view.Position.X) * blockSize);
- Canvas.SetTop(block, (point.Y + view.Position.Y) * blockSize);
- canvas.Children.Add(block);
- }
-
- canvas.Width = blockSize * (points.Select(i => i.X).Max() + 5);
- canvas.Height = blockSize * (points.Select(i => i.Y).Max() + 5);
-
- TotalTB.Text = points.Count.ToString();
- }
-
-
- private void Slider_ValueChanged(object? sender, RangeBaseValueChangedEventArgs rangeBaseValueChangedEventArgs)
- {
- if (ShemeChanvas == null)
- return;
- var e = rangeBaseValueChangedEventArgs;
- ShemeChanvas.RenderTransform = new ScaleTransform() { ScaleX = e.NewValue / 100, ScaleY = e.NewValue / 100 };
- // ShemeChanvas.transf.LayoutTransform = new ScaleTransform() { ScaleX = e.NewValue / 95, ScaleY = e.NewValue / 95 };
- ScaleTB.Text = Math.Round(rangeBaseValueChangedEventArgs.NewValue) + "%";
- }
-
- private void CreateShape(object? sender, RoutedEventArgs routedEventArgs)
- {
- try
- {
- var x = (sender as Control).Tag;
- switch (x)
- {
- case "Ov":
- DC.Ov = new OvalView();
- DC.Ov.OnNewSheme += DrawShape;
- DC.Ov.Rebuild();
- DC.Figures.Add(DC.Ov);
- SetupVisiblePanel(0);
- break;
- case "Pv":
- DC.Pv = new PolygonView();
- DC.Pv.OnNewSheme += DrawShape;
- DC.Pv.Rebuild();
- DC.Figures.Add(DC.Pv);
- SetupVisiblePanel(1);
- break;
- case "Lv":
- DC.Lv = new LineView();
- DC.Lv.OnNewSheme += DrawShape;
- DC.Lv.Rebuild();
- DC.Figures.Add(DC.Lv);
- SetupVisiblePanel(2);
- break;
- }
- }
- catch (Exception exception)
- {
- }
- }
-
- private void SetupSelected(object? sender, SelectionChangedEventArgs e)
- {
- if (Layers.SelectedItem == null)
- {
- return;
- }
-
- switching = true;
- switch (Layers.SelectedItem)
- {
- case OvalView ov:
- DC.Ov = ov;
- SetupVisiblePanel(0);
- break;
- case PolygonView pv:
- DC.Pv = pv;
- SetupVisiblePanel(1);
- break;
- case LineView lv:
- DC.Lv = lv;
- SetupVisiblePanel(2);
- break;
- }
- }
-
- private void SetupVisiblePanel(int index)
- {
- for (var i = 0; i < ToolsTab.Children.Count; i++)
- {
- ToolsTab.Children[i].IsVisible = i == index;
- }
- }
}
\ No newline at end of file
diff --git a/MCCAD/Views/PositionControl.axaml b/MCCAD/Views/PositionControl.axaml
index 8ad982e..20879ca 100644
--- a/MCCAD/Views/PositionControl.axaml
+++ b/MCCAD/Views/PositionControl.axaml
@@ -7,11 +7,11 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="MCCAD.Views.PositionControl"
x:DataType="viewModels:PositionVM">
-
- X:
- Y:
-
-
-
+
+ X:
+ Y:
+
+
+
-
+
\ No newline at end of file
diff --git a/MCCAD/Views/TeamsView.axaml b/MCCAD/Views/TeamsView.axaml
new file mode 100644
index 0000000..8ea4a4c
--- /dev/null
+++ b/MCCAD/Views/TeamsView.axaml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MCCAD/Views/TeamsView.axaml.cs b/MCCAD/Views/TeamsView.axaml.cs
new file mode 100644
index 0000000..ada22ea
--- /dev/null
+++ b/MCCAD/Views/TeamsView.axaml.cs
@@ -0,0 +1,20 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using MCCAD.ViewModels;
+using ReactiveUI.Avalonia;
+
+namespace MCCAD.Views;
+
+public partial class TeamsView : ReactiveUserControl
+{
+ public TeamsView()
+ {
+ InitializeComponent();
+ }
+
+ private void SelectingItemsControl_OnSelectionChanged(object? sender, SelectionChangedEventArgs e)
+ {
+
+ }
+}
\ No newline at end of file