qwer
This commit is contained in:
Generated
+4
@@ -4,8 +4,12 @@
|
|||||||
<option name="projectPerEditor">
|
<option name="projectPerEditor">
|
||||||
<map>
|
<map>
|
||||||
<entry key="MCCAD/App.axaml" value="MCCAD/MCCAD.csproj" />
|
<entry key="MCCAD/App.axaml" value="MCCAD/MCCAD.csproj" />
|
||||||
|
<entry key="MCCAD/Views/DrawingView.axaml" value="MCCAD/MCCAD.csproj" />
|
||||||
|
<entry key="MCCAD/Views/DrawingsCollectionView.axaml" value="MCCAD/MCCAD.csproj" />
|
||||||
|
<entry key="MCCAD/Views/LoginView.axaml" value="MCCAD/MCCAD.csproj" />
|
||||||
<entry key="MCCAD/Views/MainWindow.axaml" value="MCCAD/MCCAD.csproj" />
|
<entry key="MCCAD/Views/MainWindow.axaml" value="MCCAD/MCCAD.csproj" />
|
||||||
<entry key="MCCAD/Views/PositiionControl.axaml" value="MCCAD/MCCAD.csproj" />
|
<entry key="MCCAD/Views/PositiionControl.axaml" value="MCCAD/MCCAD.csproj" />
|
||||||
|
<entry key="MCCAD/Views/TeamsView.axaml" value="MCCAD/MCCAD.csproj" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
@@ -21,6 +21,17 @@
|
|||||||
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
|
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
|
||||||
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.14" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.14">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="9.0.14" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.14">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
|
||||||
<PackageReference Include="ReactiveUI.Avalonia" Version="11.4.12" />
|
<PackageReference Include="ReactiveUI.Avalonia" Version="11.4.12" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -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<User> Users { get; set; }
|
||||||
|
public DbSet<Drawing> Drawings { get; set; }
|
||||||
|
public DbSet<Collaborators> Collaborators { get; set; }
|
||||||
|
public DbSet<Team> Teams { get; set; }
|
||||||
|
public DbSet<Membership> Memberships { get; set; }
|
||||||
|
|
||||||
|
public static readonly CadDBContext Instance = new();
|
||||||
|
public static User User;
|
||||||
|
}
|
||||||
@@ -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; }
|
||||||
|
}
|
||||||
@@ -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<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
|
||||||
|
{
|
||||||
|
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
|
||||||
|
field = value;
|
||||||
|
OnPropertyChanged(propertyName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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; }
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
@@ -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; } = "";
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis;
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Templates;
|
using Avalonia.Controls.Templates;
|
||||||
using MCCAD.ViewModels;
|
using MCCAD.ViewModels;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace MCCAD;
|
namespace MCCAD;
|
||||||
|
|
||||||
@@ -35,3 +36,18 @@ public class ViewLocator : IDataTemplate
|
|||||||
return data is ViewModelBase;
|
return data is ViewModelBase;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class MainViewLocator : IViewLocator
|
||||||
|
{
|
||||||
|
|
||||||
|
private ViewLocator _locator = new ViewLocator();
|
||||||
|
public IViewFor<TViewModel>? ResolveView<TViewModel>(string? contract = null) where TViewModel : class
|
||||||
|
{
|
||||||
|
return _locator.Build(contract) as IViewFor<TViewModel>;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IViewFor? ResolveView(object? instance, string? contract = null)
|
||||||
|
{
|
||||||
|
return _locator.Build(instance) as IViewFor;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<IFigureDeserializer> _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<List<string>>(_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<IFigureView> 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(); }
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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<Drawing> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,8 +2,11 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Avalonia.Controls.Shapes;
|
||||||
using MCCAD.Models;
|
using MCCAD.Models;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
using Line = MCCAD.Models.Line;
|
||||||
|
|
||||||
namespace MCCAD.ViewModels;
|
namespace MCCAD.ViewModels;
|
||||||
|
|
||||||
@@ -17,23 +20,37 @@ public interface IFigureView
|
|||||||
public event ShemeUpdate OnNewSheme;
|
public event ShemeUpdate OnNewSheme;
|
||||||
PositionVM Position { get; set; }
|
PositionVM Position { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
string Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IFigureDeserializer
|
||||||
|
{
|
||||||
|
bool TryDeserialize(string data, out IFigureView view);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LineView : ReactiveObject, IFigureView
|
public class LineView : ReactiveObject, IFigureView
|
||||||
{
|
{
|
||||||
private static int _counter = 1;
|
private static int _counter = 1;
|
||||||
|
|
||||||
public LineView () {
|
public LineView()
|
||||||
|
{
|
||||||
Position = new PositionVM
|
Position = new PositionVM
|
||||||
{
|
{
|
||||||
Chanded = Rebuild
|
Chanded = Rebuild
|
||||||
};
|
};
|
||||||
Name = "Line " + _counter++;
|
Name = "Line " + _counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public event ShemeUpdate OnNewSheme;
|
public event ShemeUpdate OnNewSheme;
|
||||||
public PositionVM Position { get; set; } = new ();
|
public PositionVM Position { get; set; }
|
||||||
public string Name { 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 double angle = 45;
|
||||||
private int lenght = 10;
|
private int lenght = 10;
|
||||||
|
|
||||||
@@ -67,7 +84,32 @@ public class LineView : ReactiveObject, IFigureView
|
|||||||
shape = shape.Select(i => new IntPoint(i.X, -i.Y)).ToList();
|
shape = shape.Select(i => new IntPoint(i.X, -i.Y)).ToList();
|
||||||
var yMove = shape.Select(p => p.Y).Min();
|
var yMove = shape.Select(p => p.Y).Min();
|
||||||
shape = shape.Select(p => new IntPoint(p.X, p.Y - yMove)).ToList();
|
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>(data.Substring(data.IndexOf(' ') + 1));
|
||||||
|
view = new LineView()
|
||||||
|
{ Name = parsed.Name, Lenght = parsed.Lenght, Position = parsed.Position, Angle = parsed.Angle };
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,13 +118,47 @@ public class PolygonView : ReactiveObject, IFigureView
|
|||||||
public event ShemeUpdate OnNewSheme;
|
public event ShemeUpdate OnNewSheme;
|
||||||
public PositionVM Position { get; set; }
|
public PositionVM Position { get; set; }
|
||||||
public string Name { 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>(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 corners = 3;
|
||||||
private int radius = 5;
|
private int radius = 5;
|
||||||
private int rotate;
|
private int rotate;
|
||||||
|
|
||||||
private static int _counter = 1;
|
private static int _counter = 1;
|
||||||
|
|
||||||
public PolygonView() {
|
public PolygonView()
|
||||||
|
{
|
||||||
Position = new PositionVM
|
Position = new PositionVM
|
||||||
{
|
{
|
||||||
Chanded = Rebuild
|
Chanded = Rebuild
|
||||||
@@ -163,7 +239,7 @@ public class PolygonView : ReactiveObject, IFigureView
|
|||||||
// start = start.Next;
|
// start = start.Next;
|
||||||
//}
|
//}
|
||||||
//DrawFromTo(vecs.First.Value, vecs.Last.Value);
|
//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 PositionVM Position { get; set; }
|
||||||
public string Name { 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>(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)
|
public double NormalizedLenth(double x, double y)
|
||||||
{
|
{
|
||||||
var hWidth = width / 2;
|
var hWidth = width / 2;
|
||||||
@@ -261,6 +385,7 @@ public class OvalView : ReactiveObject, IFigureView
|
|||||||
};
|
};
|
||||||
Name = "Oval " + _counter++;
|
Name = "Oval " + _counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Rebuild()
|
public void Rebuild()
|
||||||
{
|
{
|
||||||
int RoundToInt(double value) => (int)Math.Round(value);
|
int RoundToInt(double value) => (int)Math.Round(value);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,35 +1,23 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using MCCAD.Models;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace MCCAD.ViewModels;
|
namespace MCCAD.ViewModels;
|
||||||
|
|
||||||
public class MainWindowViewModel : ViewModelBase
|
public class MainWindowViewModel : ViewModelBase, IScreen
|
||||||
{
|
{
|
||||||
private OvalView _ov;
|
public RoutingState Router { get; private set; }
|
||||||
private PolygonView _pv;
|
|
||||||
private LineView _lv;
|
|
||||||
|
|
||||||
public OvalView Ov
|
public MainWindowViewModel()
|
||||||
{
|
{
|
||||||
get => _ov;
|
Router = new RoutingState();
|
||||||
set => this.RaiseAndSetIfChanged(ref _ov, value);
|
Router.Navigate.Execute(new LoginViewModel(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
public PolygonView Pv
|
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}}" ]
|
||||||
get => _pv;
|
""";
|
||||||
set => this.RaiseAndSetIfChanged(ref _pv, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LineView Lv
|
|
||||||
{
|
|
||||||
get => _lv;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _lv, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int A { get; set; }
|
|
||||||
public string Greeting { get; set; }
|
|
||||||
|
|
||||||
public ObservableCollection<IFigureView> Figures { get; set; } = [];
|
|
||||||
}
|
|
||||||
@@ -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<Team> teams;
|
||||||
|
public ObservableCollection<Team> 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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:viewModels="clr-namespace:MCCAD.ViewModels"
|
||||||
|
xmlns:views="clr-namespace:MCCAD.Views"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="MCCAD.Views.DrawingView"
|
||||||
|
x:DataType="viewModels:DrawingViewModel">
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="250" />
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition Width="250"></ColumnDefinition>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition Height="125" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<StackPanel Margin="5,5,5,5">
|
||||||
|
<Button Command="{Binding Back}">← Назад</Button>
|
||||||
|
<HyperlinkButton Click="CreateShape" Tag="Ov">Новый элипс</HyperlinkButton>
|
||||||
|
<HyperlinkButton Click="CreateShape" Tag="Pv">Новый многоугольник</HyperlinkButton>
|
||||||
|
<HyperlinkButton Click="CreateShape" Tag="Lv">Новая линия</HyperlinkButton>
|
||||||
|
<Panel Name="ToolsTab" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||||
|
<ScrollViewer DataContext="{Binding Path=Ov}" IsVisible="False">
|
||||||
|
<StackPanel>
|
||||||
|
<Expander HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
|
||||||
|
Header="Размеры">
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock Text="Ширина" />
|
||||||
|
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Top">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Slider Minimum="3" Maximum="50" VerticalAlignment="Center"
|
||||||
|
Value="{Binding Width}" />
|
||||||
|
<TextBox x:Name="WStr" Grid.Column="1" Margin="3" MaxLength="4"
|
||||||
|
Text="{Binding Width}" />
|
||||||
|
</Grid>
|
||||||
|
<TextBlock Text="Высота" />
|
||||||
|
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Top">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Slider Minimum="3" Maximum="50" VerticalAlignment="Center"
|
||||||
|
Value="{Binding Heigth}" />
|
||||||
|
<TextBox x:Name="HStr" Grid.Column="1" Margin="3" MaxLength="4"
|
||||||
|
Text="{Binding Heigth}" />
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
</Expander>
|
||||||
|
<Expander HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
|
||||||
|
Header="Ограничения">
|
||||||
|
<DockPanel LastChildFill="False" Name="LimitsDP">
|
||||||
|
<StackPanel DockPanel.Dock="Top">
|
||||||
|
<Slider Minimum="0" Maximum="{Binding Heigth}" Width="85" Margin="3"
|
||||||
|
Value="{Binding TopLimit}" />
|
||||||
|
<TextBlock HorizontalAlignment="Center" Name="TopTB"
|
||||||
|
Text="{Binding TopLimit, StringFormat={}от {0}}" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel DockPanel.Dock="Bottom">
|
||||||
|
<Slider Minimum="0" Maximum="{Binding Heigth}" Width="85" Margin="3"
|
||||||
|
Value="{Binding BottomLimit}" />
|
||||||
|
<TextBlock HorizontalAlignment="Center" Name="BotTB"
|
||||||
|
Text="{Binding BottomLimit, StringFormat={}до {0}}" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel DockPanel.Dock="Left">
|
||||||
|
<Slider Minimum="0" Maximum="{Binding Width}" Width="85" Margin="3"
|
||||||
|
Value="{Binding LeftLimit}" />
|
||||||
|
<TextBlock HorizontalAlignment="Center" Name="LeftTB"
|
||||||
|
Text="{Binding LeftLimit, StringFormat={}от {0}}" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel DockPanel.Dock="Right" Width="85">
|
||||||
|
<Slider Minimum="0" Maximum="{Binding Width}" Width="85" Margin="3"
|
||||||
|
Value="{Binding RightLimit}" />
|
||||||
|
<TextBlock HorizontalAlignment="Center" Name="RightTB"
|
||||||
|
Text="{Binding RightLimit, StringFormat={}до {0}}" />
|
||||||
|
</StackPanel>
|
||||||
|
</DockPanel>
|
||||||
|
</Expander>
|
||||||
|
<Expander HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
|
||||||
|
Header="Расположение">
|
||||||
|
<views:PositionControl DataContext="{Binding Position}" />
|
||||||
|
</Expander>
|
||||||
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
|
<ScrollViewer Margin="5" DataContext="{Binding Pv}" IsVisible="False">
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock Text="Сторона" />
|
||||||
|
<Slider Minimum="5" Maximum="100" VerticalAlignment="Center" Value="{Binding Radius}" />
|
||||||
|
<TextBlock Text="{Binding Radius}" />
|
||||||
|
<TextBlock Text="Углы" />
|
||||||
|
<Slider Minimum="3" Maximum="10" VerticalAlignment="Center" Value="{Binding Corners}" />
|
||||||
|
<TextBlock Text="{Binding Corners}" />
|
||||||
|
<Expander HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
|
||||||
|
Header="Расположение">
|
||||||
|
<views:PositionControl DataContext="{Binding Position}" />
|
||||||
|
</Expander>
|
||||||
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
|
<StackPanel Margin="5" DataContext="{Binding Lv}" IsVisible="False">
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock>Угол</TextBlock>
|
||||||
|
<Slider Value="{Binding Angle}" Minimum="0" Maximum="90" />
|
||||||
|
<TextBlock Text="{Binding Angle}" />
|
||||||
|
<TextBlock>Длина</TextBlock>
|
||||||
|
<Slider Value="{Binding Lenght}" Minimum="5" Maximum="90" />
|
||||||
|
<TextBlock Text="{Binding Lenght}" />
|
||||||
|
<Expander HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
|
||||||
|
Header="Расположение">
|
||||||
|
<views:PositionControl DataContext="{Binding Position}" />
|
||||||
|
</Expander>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
</Panel>
|
||||||
|
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Grid.Row="1" VerticalAlignment="Top">
|
||||||
|
<TextBlock x:Name="CurrentBlock" Margin="5" />
|
||||||
|
<Slider Minimum="50" Maximum="500" TickFrequency="5" ValueChanged="Slider_ValueChanged" Value="100" />
|
||||||
|
<TextBlock x:Name="ScaleTB" />
|
||||||
|
<TextBlock x:Name="TotalTB" Text="0" Margin="5" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
<ScrollViewer Grid.Column="1" Margin="5,5,5,5" HorizontalScrollBarVisibility="Visible"
|
||||||
|
VerticalScrollBarVisibility="Visible">
|
||||||
|
<Grid Name="SchemePanel">
|
||||||
|
<Ellipse x:Name="BaseElipse" Stroke="Black" StrokeThickness="10" Height="150" Margin="15" Width="150"
|
||||||
|
VerticalAlignment="Top" HorizontalAlignment="Left" IsVisible="False" />
|
||||||
|
<Canvas Name="SchemeCanvas" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="15" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</ScrollViewer>
|
||||||
|
<Grid Grid.Column="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10"
|
||||||
|
RowDefinitions="Auto * Auto">
|
||||||
|
<TextBlock>Слои</TextBlock>
|
||||||
|
<ListBox Margin="0,5" Grid.Row="1" SelectionChanged="SetupSelected" ItemsSource="{Binding Figures}"
|
||||||
|
Name="Layers">
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid ColumnDefinitions="Auto *">
|
||||||
|
<TextBox Grid.Column="1" Text="{Binding Name}" HorizontalAlignment="Stretch"></TextBox>
|
||||||
|
<Border Margin="5" Background="OrangeRed" Width="30"></Border>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListBox.ItemTemplate>
|
||||||
|
</ListBox>
|
||||||
|
<Button Command="{Binding OnSave}" Grid.Row="2">Сохранить</Button>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
@@ -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<DrawingViewModel>
|
||||||
|
{
|
||||||
|
public Dictionary<IFigureView, Canvas> _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<IntPoint> 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<IntPoint, string> markup = new Dictionary<IntPoint, string>();
|
||||||
|
|
||||||
|
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<int> { 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<int>() { 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:viewModels="clr-namespace:MCCAD.ViewModels"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="MCCAD.Views.DrawingsCollectionView"
|
||||||
|
x:DataType="viewModels:DrawingsCollectionViewModel">
|
||||||
|
<Grid RowDefinitions="Auto * Auto" ColumnDefinitions="* *">
|
||||||
|
<TextBlock Text="{Binding User.Name, StringFormat={}Добро пожаловать {1}}"></TextBlock>
|
||||||
|
<Button Grid.Column="1" Grid.Row="0" HorizontalAlignment="Right" Command="{Binding Exit}">Выйти</Button>
|
||||||
|
<ListBox Margin="10" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding Drawings}"
|
||||||
|
SelectedItem="{Binding SelectedDrawing}"
|
||||||
|
Grid.Column="0" Grid.Row="1">
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock Text="{Binding Name}" FontSize="20" FontWeight="Bold"></TextBlock>
|
||||||
|
<TextBlock Text="{Binding Size, StringFormat={}{0} кб.}"></TextBlock>
|
||||||
|
<DockPanel HorizontalAlignment="Stretch" LastChildFill="False">
|
||||||
|
<TextBlock DockPanel.Dock="Right"
|
||||||
|
Text="{Binding LastChange, StringFormat={}Дата последнего изменения: {0}}"
|
||||||
|
FontSize="18">
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock DockPanel.Dock="Left" Text="{Binding Size, StringFormat={}Дата создания: {0}}"
|
||||||
|
FontSize="18">
|
||||||
|
</TextBlock>
|
||||||
|
</DockPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListBox.ItemTemplate>
|
||||||
|
</ListBox>
|
||||||
|
<ScrollViewer Grid.Row="1" Grid.Column="1">
|
||||||
|
<StackPanel Spacing="10">
|
||||||
|
<TextBlock>Название</TextBlock>
|
||||||
|
<TextBox Text="{Binding SelectedDrawingName, Mode=TwoWay}"></TextBox>
|
||||||
|
<Button Command="{Binding Open}">Открыть</Button>
|
||||||
|
<Button Command="{Binding Save}">Сохранить</Button>
|
||||||
|
<Button Background="OrangeRed" Command="{Binding Delete}">Удалить</Button>
|
||||||
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
|
<Button Grid.Row="2" Grid.Column="0" Command="{Binding Create}">Создать чертеж</Button>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
@@ -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<DrawingsCollectionViewModel>
|
||||||
|
{
|
||||||
|
public DrawingsCollectionView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:viewModels="clr-namespace:MCCAD.ViewModels"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="MCCAD.Views.LoginView"
|
||||||
|
x:DataType="viewModels:LoginViewModel">
|
||||||
|
<UserControl.Styles>
|
||||||
|
<Style Selector="Button.LoginButton">
|
||||||
|
<Setter Property="Margin" Value="20, 5" />
|
||||||
|
<Setter Property="Transitions">
|
||||||
|
<Transitions>
|
||||||
|
<DoubleTransition Property="Height" Duration="0:0:0.3" />
|
||||||
|
</Transitions>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="TextBlock.AnimateHeight">
|
||||||
|
<Setter Property="Transitions">
|
||||||
|
<Transitions>
|
||||||
|
<DoubleTransition Property="Height" Duration="0:0:0.3" />
|
||||||
|
</Transitions>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</UserControl.Styles>
|
||||||
|
<StackPanel Width="250" Classes="Centred" HorizontalAlignment="Center" VerticalAlignment="Center" Spacing="10">
|
||||||
|
<TextBlock FontSize="24">Авторизация</TextBlock>
|
||||||
|
<TextBlock>Введите ваш логин и пароль</TextBlock>
|
||||||
|
<TextBlock Classes="AnimateHeight" Foreground="Red" IsVisible="{Binding InvalidData}">Логин или пароль неверны</TextBlock>
|
||||||
|
<TextBox TextChanged="UpdateLoginVisibility" Text="{Binding Login}" Name="LoginText" Watermark="Логин"
|
||||||
|
HorizontalAlignment="Stretch" />
|
||||||
|
<TextBox TextChanged="UpdateLoginVisibility" Text="{Binding Password}" Name="PasswordText"
|
||||||
|
HorizontalAlignment="Stretch" PasswordChar="~"
|
||||||
|
Watermark="Пароль" />
|
||||||
|
<Button Height="0" Name="LoginButton" VerticalAlignment="Top" Command="{Binding TryAuth}"
|
||||||
|
Classes="Long LoginButton" HorizontalAlignment="Center">
|
||||||
|
Войти
|
||||||
|
</Button>
|
||||||
|
</StackPanel>
|
||||||
|
</UserControl>
|
||||||
@@ -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<LoginViewModel>
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,152 +4,17 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
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:Class="MCCAD.Views.MainWindow"
|
||||||
x:DataType="vm:MainWindowViewModel"
|
x:DataType="vm:MainWindowViewModel"
|
||||||
|
xmlns:rui="clr-namespace:ReactiveUI.Avalonia;assembly=ReactiveUI.Avalonia"
|
||||||
|
xmlns:mccad="clr-namespace:MCCAD"
|
||||||
Icon="/Assets/avalonia-logo.ico"
|
Icon="/Assets/avalonia-logo.ico"
|
||||||
Title="MCCAD">
|
Title="MCCAD">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<rui:RoutedViewHost Margin="10" Router="{Binding Router}">
|
||||||
<ColumnDefinition Width="250" />
|
<rui:RoutedViewHost.ViewLocator>
|
||||||
<ColumnDefinition />
|
<mccad:MainViewLocator />
|
||||||
<ColumnDefinition Width="250"></ColumnDefinition>
|
</rui:RoutedViewHost.ViewLocator>
|
||||||
</Grid.ColumnDefinitions>
|
</rui:RoutedViewHost>
|
||||||
<Grid>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition />
|
|
||||||
<RowDefinition Height="125" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<StackPanel Margin="5,5,5,5">
|
|
||||||
<HyperlinkButton Click="CreateShape" Tag="Ov">Новый элипс</HyperlinkButton>
|
|
||||||
<HyperlinkButton Click="CreateShape" Tag="Pv">Новый многоугольник</HyperlinkButton>
|
|
||||||
<HyperlinkButton Click="CreateShape" Tag="Lv">Новая линия</HyperlinkButton>
|
|
||||||
<Panel Name="ToolsTab" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
|
||||||
<ScrollViewer DataContext="{Binding Path=Ov}" IsVisible="False">
|
|
||||||
<StackPanel>
|
|
||||||
<Expander HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
|
|
||||||
Header="Размеры">
|
|
||||||
<StackPanel>
|
|
||||||
<TextBlock Text="Ширина" />
|
|
||||||
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Top">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Slider Minimum="3" Maximum="50" VerticalAlignment="Center"
|
|
||||||
Value="{Binding Width}" />
|
|
||||||
<TextBox x:Name="WStr" Grid.Column="1" Margin="3" MaxLength="4"
|
|
||||||
Text="{Binding Width}" />
|
|
||||||
</Grid>
|
|
||||||
<TextBlock Text="Высота" />
|
|
||||||
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Top">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Slider Minimum="3" Maximum="50" VerticalAlignment="Center"
|
|
||||||
Value="{Binding Heigth}" />
|
|
||||||
<TextBox x:Name="HStr" Grid.Column="1" Margin="3" MaxLength="4"
|
|
||||||
Text="{Binding Heigth}" />
|
|
||||||
</Grid>
|
|
||||||
</StackPanel>
|
|
||||||
</Expander>
|
|
||||||
<Expander HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
|
|
||||||
Header="Ограничения">
|
|
||||||
<DockPanel LastChildFill="False" Name="LimitsDP">
|
|
||||||
<StackPanel DockPanel.Dock="Top">
|
|
||||||
<Slider Minimum="0" Maximum="{Binding Heigth}" Width="85" Margin="3"
|
|
||||||
Value="{Binding TopLimit}" />
|
|
||||||
<TextBlock HorizontalAlignment="Center" Name="TopTB"
|
|
||||||
Text="{Binding TopLimit, StringFormat={}от {0}}" />
|
|
||||||
</StackPanel>
|
|
||||||
<StackPanel DockPanel.Dock="Bottom">
|
|
||||||
<Slider Minimum="0" Maximum="{Binding Heigth}" Width="85" Margin="3"
|
|
||||||
Value="{Binding BottomLimit}" />
|
|
||||||
<TextBlock HorizontalAlignment="Center" Name="BotTB"
|
|
||||||
Text="{Binding BottomLimit, StringFormat={}до {0}}" />
|
|
||||||
</StackPanel>
|
|
||||||
<StackPanel DockPanel.Dock="Left">
|
|
||||||
<Slider Minimum="0" Maximum="{Binding Width}" Width="85" Margin="3"
|
|
||||||
Value="{Binding LeftLimit}" />
|
|
||||||
<TextBlock HorizontalAlignment="Center" Name="LeftTB"
|
|
||||||
Text="{Binding LeftLimit, StringFormat={}от {0}}" />
|
|
||||||
</StackPanel>
|
|
||||||
<StackPanel DockPanel.Dock="Right" Width="85">
|
|
||||||
<Slider Minimum="0" Maximum="{Binding Width}" Width="85" Margin="3"
|
|
||||||
Value="{Binding RightLimit}" />
|
|
||||||
<TextBlock HorizontalAlignment="Center" Name="RightTB"
|
|
||||||
Text="{Binding RightLimit, StringFormat={}до {0}}" />
|
|
||||||
</StackPanel>
|
|
||||||
</DockPanel>
|
|
||||||
</Expander>
|
|
||||||
<Expander HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
|
|
||||||
Header="Расположение">
|
|
||||||
<views:PositionControl DataContext="{Binding Position}" />
|
|
||||||
</Expander>
|
|
||||||
</StackPanel>
|
|
||||||
</ScrollViewer>
|
|
||||||
<ScrollViewer Margin="5" DataContext="{Binding Pv}" IsVisible="False">
|
|
||||||
<StackPanel>
|
|
||||||
<TextBlock Text="Сторона" />
|
|
||||||
<Slider Minimum="5" Maximum="100" VerticalAlignment="Center" Value="{Binding Radius}" />
|
|
||||||
<TextBlock Text="{Binding Radius}" />
|
|
||||||
<TextBlock Text="Углы" />
|
|
||||||
<Slider Minimum="3" Maximum="10" VerticalAlignment="Center" Value="{Binding Corners}" />
|
|
||||||
<TextBlock Text="{Binding Corners}" />
|
|
||||||
<Expander HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
|
|
||||||
Header="Расположение">
|
|
||||||
<views:PositionControl DataContext="{Binding Position}" />
|
|
||||||
</Expander>
|
|
||||||
</StackPanel>
|
|
||||||
</ScrollViewer>
|
|
||||||
<StackPanel Margin="5" DataContext="{Binding Lv}" IsVisible="False">
|
|
||||||
<StackPanel>
|
|
||||||
<TextBlock>Угол</TextBlock>
|
|
||||||
<Slider Value="{Binding Angle}" Minimum="0" Maximum="90" />
|
|
||||||
<TextBlock Text="{Binding Angle}" />
|
|
||||||
<TextBlock>Длина</TextBlock>
|
|
||||||
<Slider Value="{Binding Lenght}" Minimum="5" Maximum="90" />
|
|
||||||
<TextBlock Text="{Binding Lenght}" />
|
|
||||||
<Expander HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
|
|
||||||
Header="Расположение">
|
|
||||||
<views:PositionControl DataContext="{Binding Position}" />
|
|
||||||
</Expander>
|
|
||||||
</StackPanel>
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
</Panel>
|
|
||||||
|
|
||||||
</StackPanel>
|
|
||||||
<StackPanel Grid.Row="1" VerticalAlignment="Top">
|
|
||||||
<TextBlock x:Name="CurrentBlock" Margin="5" />
|
|
||||||
<Slider Minimum="50" Maximum="500" TickFrequency="5" ValueChanged="Slider_ValueChanged" Value="100" />
|
|
||||||
<TextBlock x:Name="ScaleTB" />
|
|
||||||
<TextBlock x:Name="TotalTB" Text="0" Margin="5" />
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
<ScrollViewer Grid.Column="1" Margin="5,5,5,5" HorizontalScrollBarVisibility="Visible">
|
|
||||||
<Grid>
|
|
||||||
<Ellipse x:Name="BaseElipse" Stroke="Black" StrokeThickness="10" Height="150" Margin="15" Width="150"
|
|
||||||
VerticalAlignment="Top" HorizontalAlignment="Left" IsVisible="False" />
|
|
||||||
<Canvas Name="ShemeChanvas" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="15" />
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
</ScrollViewer>
|
|
||||||
<StackPanel Grid.Column="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10" Spacing="10">
|
|
||||||
<TextBlock>Слои</TextBlock>
|
|
||||||
<ListBox SelectionChanged="SetupSelected" ItemsSource="{Binding Figures}" Name="Layers">
|
|
||||||
<ListBox.ItemTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<Grid ColumnDefinitions="Auto *">
|
|
||||||
<TextBox Grid.Column="1" Text="{Binding Name}" HorizontalAlignment="Stretch"></TextBox>
|
|
||||||
<Border Margin="5" Background="OrangeRed" Width="30"></Border>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
</DataTemplate>
|
|
||||||
</ListBox.ItemTemplate>
|
|
||||||
</ListBox>
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
@@ -14,217 +14,8 @@ namespace MCCAD.Views;
|
|||||||
|
|
||||||
public partial class MainWindow : Window
|
public partial class MainWindow : Window
|
||||||
{
|
{
|
||||||
public Dictionary<IFigureView, Canvas> _cache = new();
|
|
||||||
public bool mark = true;
|
|
||||||
int blockSize = 15;
|
|
||||||
|
|
||||||
private bool switching = false;
|
|
||||||
private MainWindowViewModel DC => DataContext as MainWindowViewModel;
|
|
||||||
|
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDataContextChanged(EventArgs e)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DrawShape(List<IntPoint> 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<IntPoint, string> markup = new Dictionary<IntPoint, string>();
|
|
||||||
|
|
||||||
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<int> { 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<int>() { 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:viewModels="clr-namespace:MCCAD.ViewModels"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="MCCAD.Views.TeamsView"
|
||||||
|
x:DataType="viewModels:TeamsViewModel">
|
||||||
|
<Grid RowDefinitions="35 Auto * Auto">
|
||||||
|
<TextBox Text="{Binding SearchString}" Margin="5" Grid.Row="1" HorizontalAlignment="Stretch"></TextBox>
|
||||||
|
<ListBox Margin="5" ItemsSource="{Binding Teams}" SelectionChanged="SelectingItemsControl_OnSelectionChanged">
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<DockPanel>
|
||||||
|
<TextBlock DockPanel.Dock="Right"
|
||||||
|
Text="{Binding MemberCount, StringFormat={}Количество членов: {0}}">
|
||||||
|
</TextBlock>
|
||||||
|
<StackPanel DockPanel.Dock="Left">
|
||||||
|
<TextBlock Text="{Binding Name}" FontSize="20" FontWeight="Bold"></TextBlock>
|
||||||
|
<TextBlock Text="{Binding CreatedAt, StringFormat={}Создана {0}}"></TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</DockPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListBox.ItemTemplate>
|
||||||
|
</ListBox>
|
||||||
|
<Button Grid.Row="3">Создать команду</Button>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
@@ -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<TeamsViewModel>
|
||||||
|
{
|
||||||
|
public TeamsView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SelectingItemsControl_OnSelectionChanged(object? sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user