update
47
TimetableDesigner.Core/BaseGroup.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Core
|
||||||
|
{
|
||||||
|
public abstract class BaseGroup : IUnit
|
||||||
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private string _name;
|
||||||
|
private string _shortName;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PROPERTIES
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get => _name;
|
||||||
|
set => _name = value;
|
||||||
|
}
|
||||||
|
public string ShortName
|
||||||
|
{
|
||||||
|
get => _shortName;
|
||||||
|
set => _shortName = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public BaseGroup()
|
||||||
|
{
|
||||||
|
_name = string.Empty;
|
||||||
|
_shortName = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,14 +6,60 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace TimetableDesigner.Core
|
namespace TimetableDesigner.Core
|
||||||
{
|
{
|
||||||
|
[Serializable]
|
||||||
public class Class
|
public class Class
|
||||||
{
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private string _name;
|
||||||
|
private Teacher? _teacher;
|
||||||
|
private BaseGroup? _group;
|
||||||
|
private Classroom? _classroom;
|
||||||
|
private TimetableDay? _day;
|
||||||
|
private TimetableSpan? _slot;
|
||||||
|
private byte[] _color;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
public string Name { get; set; }
|
public string Name
|
||||||
public Teacher? Teacher { get; set; }
|
{
|
||||||
public IGroup? Group { get; set; }
|
get => _name;
|
||||||
public Classroom? Classroom { get; set; }
|
set => _name = value;
|
||||||
|
}
|
||||||
|
public Teacher? Teacher
|
||||||
|
{
|
||||||
|
get => _teacher;
|
||||||
|
set => _teacher = value;
|
||||||
|
}
|
||||||
|
public BaseGroup? Group
|
||||||
|
{
|
||||||
|
get => _group;
|
||||||
|
set => _group = value;
|
||||||
|
}
|
||||||
|
public Classroom? Classroom
|
||||||
|
{
|
||||||
|
get => _classroom;
|
||||||
|
set => _classroom = value;
|
||||||
|
}
|
||||||
|
public TimetableDay? Day
|
||||||
|
{
|
||||||
|
get => _day;
|
||||||
|
set => _day = value;
|
||||||
|
}
|
||||||
|
public TimetableSpan? Slot
|
||||||
|
{
|
||||||
|
get => _slot;
|
||||||
|
set => _slot = value;
|
||||||
|
}
|
||||||
|
public byte[] Color
|
||||||
|
{
|
||||||
|
get => _color;
|
||||||
|
set => _color = value;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -23,10 +69,13 @@ namespace TimetableDesigner.Core
|
|||||||
|
|
||||||
public Class()
|
public Class()
|
||||||
{
|
{
|
||||||
Name = string.Empty;
|
_name = string.Empty;
|
||||||
Teacher = null;
|
_teacher = null;
|
||||||
Group = null;
|
_group = null;
|
||||||
Classroom = null;
|
_classroom = null;
|
||||||
|
_day = null;
|
||||||
|
_slot = null;
|
||||||
|
_color = new byte[3] { 0xFA, 0x5A, 0x5A };
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -7,14 +7,48 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace TimetableDesigner.Core
|
namespace TimetableDesigner.Core
|
||||||
{
|
{
|
||||||
public class Classroom
|
[Serializable]
|
||||||
|
public class Classroom : IUnit
|
||||||
{
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private string _name;
|
||||||
|
private string _shortName;
|
||||||
|
private string _description;
|
||||||
|
private bool _isCapacityLimited;
|
||||||
|
private uint _capacity;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
public string Name { get; set; }
|
public string Name
|
||||||
public string Description { get; set; }
|
{
|
||||||
public bool IsCapacityLimited { get; set; }
|
get => _name;
|
||||||
public uint Capacity { get; set; }
|
set => _name = value;
|
||||||
|
}
|
||||||
|
public string ShortName
|
||||||
|
{
|
||||||
|
get => _shortName;
|
||||||
|
set => _shortName = value;
|
||||||
|
}
|
||||||
|
public string Description
|
||||||
|
{
|
||||||
|
get => _description;
|
||||||
|
set => _description = value;
|
||||||
|
}
|
||||||
|
public bool IsCapacityLimited
|
||||||
|
{
|
||||||
|
get => _isCapacityLimited;
|
||||||
|
set => _isCapacityLimited = value;
|
||||||
|
}
|
||||||
|
public uint Capacity
|
||||||
|
{
|
||||||
|
get => _capacity;
|
||||||
|
set => _capacity = value;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -24,10 +58,11 @@ namespace TimetableDesigner.Core
|
|||||||
|
|
||||||
public Classroom()
|
public Classroom()
|
||||||
{
|
{
|
||||||
Name = string.Empty;
|
_name = string.Empty;
|
||||||
Description = string.Empty;
|
_shortName = string.Empty;
|
||||||
IsCapacityLimited = false;
|
_description = string.Empty;
|
||||||
Capacity = 1;
|
_isCapacityLimited = false;
|
||||||
|
_capacity = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -6,13 +6,26 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace TimetableDesigner.Core
|
namespace TimetableDesigner.Core
|
||||||
{
|
{
|
||||||
public class Group : IGroup
|
[Serializable]
|
||||||
|
public class Group : BaseGroup
|
||||||
{
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private string _description;
|
||||||
|
private HashSet<Subgroup> _assignedSubgroups;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
public string Name { get; set; }
|
public string Description
|
||||||
public string Description { get; set; }
|
{
|
||||||
public ICollection<Subgroup> AssignedSubgroups { get; set; }
|
get => _description;
|
||||||
|
set => _description = value;
|
||||||
|
}
|
||||||
|
public ICollection<Subgroup> AssignedSubgroups => _assignedSubgroups;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -20,11 +33,10 @@ namespace TimetableDesigner.Core
|
|||||||
|
|
||||||
#region CONSTRUCTORS
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
public Group()
|
public Group() : base()
|
||||||
{
|
{
|
||||||
Name = string.Empty;
|
_description = string.Empty;
|
||||||
Description = string.Empty;
|
_assignedSubgroups = new HashSet<Subgroup>();
|
||||||
AssignedSubgroups = new HashSet<Subgroup>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace TimetableDesigner.Core
|
namespace TimetableDesigner.Core
|
||||||
{
|
{
|
||||||
public interface IGroup
|
public interface IUnit
|
||||||
{
|
{
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
@@ -9,17 +9,47 @@ namespace TimetableDesigner.Core
|
|||||||
[Serializable]
|
[Serializable]
|
||||||
public class Project
|
public class Project
|
||||||
{
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private Guid _guid;
|
||||||
|
private string _name;
|
||||||
|
private string _author;
|
||||||
|
private string _description;
|
||||||
|
private TimetableTemplate _timetableTemplate;
|
||||||
|
private HashSet<Classroom> _classrooms;
|
||||||
|
private HashSet<Teacher> _teachers;
|
||||||
|
private HashSet<Group> _groups;
|
||||||
|
private HashSet<Subgroup> _subgroups;
|
||||||
|
private HashSet<Class> _classes;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
public string Name { get; set; }
|
public Guid Guid => _guid;
|
||||||
public string Author { get; set; }
|
public string Name
|
||||||
public string Description { get; set; }
|
{
|
||||||
public TimetableTemplate TimetableTemplate { get; set; }
|
get => _name;
|
||||||
public ICollection<Classroom> Classrooms { get; set; }
|
set => _name = value;
|
||||||
public ICollection<Teacher> Teachers { get; set; }
|
}
|
||||||
public ICollection<Group> Groups { get; set; }
|
public string Author
|
||||||
public ICollection<Subgroup> Subgroups { get; set; }
|
{
|
||||||
public ICollection<Class> Classes { get; set; }
|
get => _author;
|
||||||
|
set => _author = value;
|
||||||
|
}
|
||||||
|
public string Description
|
||||||
|
{
|
||||||
|
get => _description;
|
||||||
|
set => _description = value;
|
||||||
|
}
|
||||||
|
public TimetableTemplate TimetableTemplate => _timetableTemplate;
|
||||||
|
public ICollection<Classroom> Classrooms => _classrooms;
|
||||||
|
public ICollection<Teacher> Teachers => _teachers;
|
||||||
|
public ICollection<Group> Groups => _groups;
|
||||||
|
public ICollection<Subgroup> Subgroups => _subgroups;
|
||||||
|
public ICollection<Class> Classes => _classes;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -29,14 +59,16 @@ namespace TimetableDesigner.Core
|
|||||||
|
|
||||||
public Project()
|
public Project()
|
||||||
{
|
{
|
||||||
Name = string.Empty;
|
_guid = Guid.NewGuid();
|
||||||
Author = string.Empty;
|
_name = string.Empty;
|
||||||
Description = string.Empty;
|
_author = string.Empty;
|
||||||
TimetableTemplate = new TimetableTemplate();
|
_description = string.Empty;
|
||||||
Classrooms = new HashSet<Classroom>();
|
_timetableTemplate = new TimetableTemplate();
|
||||||
Teachers = new HashSet<Teacher>();
|
_classrooms = new HashSet<Classroom>();
|
||||||
Groups = new HashSet<Group>();
|
_teachers = new HashSet<Teacher>();
|
||||||
Subgroups = new HashSet<Subgroup>();
|
_groups = new HashSet<Group>();
|
||||||
|
_subgroups = new HashSet<Subgroup>();
|
||||||
|
_classes = new HashSet<Class>();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -6,22 +6,13 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace TimetableDesigner.Core
|
namespace TimetableDesigner.Core
|
||||||
{
|
{
|
||||||
public class Subgroup : IGroup
|
[Serializable]
|
||||||
|
public class Subgroup : BaseGroup
|
||||||
{
|
{
|
||||||
#region PROPERTIES
|
|
||||||
|
|
||||||
public string Name { get; set; }
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region CONSTRUCTORS
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
public Subgroup()
|
public Subgroup() : base()
|
||||||
{
|
{ }
|
||||||
Name = string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,16 +3,42 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using TimetableDesigner.Customs;
|
||||||
|
|
||||||
namespace TimetableDesigner.Core
|
namespace TimetableDesigner.Core
|
||||||
{
|
{
|
||||||
public class Teacher
|
[Serializable]
|
||||||
|
public class Teacher : IUnit
|
||||||
{
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private string _name;
|
||||||
|
private string _shortName;
|
||||||
|
private string _description;
|
||||||
|
private JsonSerializableDictionary<TimetableDay, TimetableSpanCollection> _availabilityHours;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
public string Name { get; set; }
|
public string Name
|
||||||
public string Description { get; set; }
|
{
|
||||||
public IDictionary<TimetableDay, TimetableSpanCollection> AvailabilityHours { get; set; }
|
get => _name;
|
||||||
|
set => _name = value;
|
||||||
|
}
|
||||||
|
public string ShortName
|
||||||
|
{
|
||||||
|
get => _shortName;
|
||||||
|
set => _shortName = value;
|
||||||
|
}
|
||||||
|
public string Description
|
||||||
|
{
|
||||||
|
get => _description;
|
||||||
|
set => _description = value;
|
||||||
|
}
|
||||||
|
public IDictionary<TimetableDay, TimetableSpanCollection> AvailabilityHours => _availabilityHours;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -22,9 +48,10 @@ namespace TimetableDesigner.Core
|
|||||||
|
|
||||||
public Teacher()
|
public Teacher()
|
||||||
{
|
{
|
||||||
Name = string.Empty;
|
_name = string.Empty;
|
||||||
Description = string.Empty;
|
_shortName = string.Empty;
|
||||||
AvailabilityHours = new Dictionary<TimetableDay, TimetableSpanCollection>();
|
_description = string.Empty;
|
||||||
|
_availabilityHours = new JsonSerializableDictionary<TimetableDay, TimetableSpanCollection>();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -9,9 +9,21 @@ namespace TimetableDesigner.Core
|
|||||||
[Serializable]
|
[Serializable]
|
||||||
public class TimetableDay
|
public class TimetableDay
|
||||||
{
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private string _name;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
public string Name { get; set; }
|
public string Name
|
||||||
|
{
|
||||||
|
get => _name;
|
||||||
|
set => _name = value;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -20,8 +32,8 @@ namespace TimetableDesigner.Core
|
|||||||
#region CONSTRUCTORS
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
public TimetableDay(string name)
|
public TimetableDay(string name)
|
||||||
{
|
{
|
||||||
Name = name;
|
_name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -6,4 +6,8 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\TimetableDesigner.Customs\TimetableDesigner.Customs.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,14 +1,24 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace TimetableDesigner.Core
|
namespace TimetableDesigner.Core
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class TimetableSpan
|
public class TimetableSpan
|
||||||
{
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private TimeOnly _from;
|
||||||
|
private TimeOnly _to;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
public TimeOnly From { get; private set; }
|
public TimeOnly From => _from;
|
||||||
public TimeOnly To { get; private set; }
|
public TimeOnly To => _to;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -20,11 +30,11 @@ namespace TimetableDesigner.Core
|
|||||||
{
|
{
|
||||||
if (to <= from)
|
if (to <= from)
|
||||||
{
|
{
|
||||||
throw new ArgumentException("\"to\" cannot be less or equal to \"from\"");
|
throw new ArgumentException("Ending value (\"to\") of TimetableSpan have to be greater than starting value (\"from\")");
|
||||||
}
|
}
|
||||||
|
|
||||||
From = from;
|
_from = from;
|
||||||
To = to;
|
_to = to;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -33,27 +43,33 @@ namespace TimetableDesigner.Core
|
|||||||
|
|
||||||
#region PUBLIC METHODS
|
#region PUBLIC METHODS
|
||||||
|
|
||||||
internal TimetableSpanCollision CheckCollision(TimetableSpan slot)
|
public override bool Equals(object? obj) => obj is TimetableSpan slot && From == slot.From && To == slot.To;
|
||||||
|
|
||||||
|
public override int GetHashCode() => HashCode.Combine(From, To);
|
||||||
|
|
||||||
|
public override string? ToString() => $"{From} - {To}";
|
||||||
|
|
||||||
|
public TimetableSpanCollision CheckCollision(TimetableSpan slot)
|
||||||
{
|
{
|
||||||
if (slot.To <= this.From)
|
if (slot.To <= this.From)
|
||||||
{
|
{
|
||||||
return TimetableSpanCollision.CheckedSlotBefore;
|
return TimetableSpanCollision.CheckedSlotBefore;
|
||||||
}
|
}
|
||||||
else if (this.To <= slot.From)
|
else if (this.To <= slot.From)
|
||||||
{
|
{
|
||||||
return TimetableSpanCollision.CheckedSlotAfter;
|
return TimetableSpanCollision.CheckedSlotAfter;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (this.From < slot.From && slot.To < this.To)
|
if (this.From <= slot.From && slot.To <= this.To)
|
||||||
{
|
{
|
||||||
return TimetableSpanCollision.CheckedSlotIn;
|
return TimetableSpanCollision.CheckedSlotIn;
|
||||||
}
|
}
|
||||||
else if (this.From < slot.From && slot.From < this.To && this.To < slot.To)
|
else if (this.From < slot.From && slot.From < this.To && this.To <= slot.To)
|
||||||
{
|
{
|
||||||
return TimetableSpanCollision.CheckedSlotFromIn;
|
return TimetableSpanCollision.CheckedSlotFromIn;
|
||||||
}
|
}
|
||||||
else if (slot.From < this.From && this.From < slot.To && slot.To < this.To)
|
else if (slot.From < this.From && this.From < slot.To && slot.To <= this.To)
|
||||||
{
|
{
|
||||||
return TimetableSpanCollision.CheckedSlotToIn;
|
return TimetableSpanCollision.CheckedSlotToIn;
|
||||||
}
|
}
|
||||||
@@ -64,12 +80,6 @@ namespace TimetableDesigner.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object? obj) => obj is TimetableSpan slot && From == slot.From && To == slot.To;
|
|
||||||
|
|
||||||
public override int GetHashCode() => HashCode.Combine(From, To);
|
|
||||||
|
|
||||||
public override string? ToString() => $"{From}-{To}";
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,12 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace TimetableDesigner.Core
|
namespace TimetableDesigner.Core
|
||||||
{
|
{
|
||||||
|
[Serializable]
|
||||||
public class TimetableSpanCollection : ICollection<TimetableSpan>
|
public class TimetableSpanCollection : ICollection<TimetableSpan>
|
||||||
{
|
{
|
||||||
#region FIELDS
|
#region FIELDS
|
||||||
|
|
||||||
private IList<TimetableSpan> _list;
|
private List<TimetableSpan> _list;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ namespace TimetableDesigner.Core
|
|||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
public int Count => _list.Count;
|
public int Count => _list.Count;
|
||||||
public bool IsReadOnly => _list.IsReadOnly;
|
public bool IsReadOnly => ((ICollection<TimetableSpan>)_list).IsReadOnly;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace TimetableDesigner.Core
|
namespace TimetableDesigner.Core
|
||||||
{
|
{
|
||||||
internal enum TimetableSpanCollision
|
public enum TimetableSpanCollision
|
||||||
{
|
{
|
||||||
CheckedSlotBefore,
|
CheckedSlotBefore,
|
||||||
CheckedSlotAfter,
|
CheckedSlotAfter,
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ namespace TimetableDesigner.Core
|
|||||||
|
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
public IEnumerable<TimetableDay> Days => _days;
|
public ICollection<TimetableDay> Days => _days;
|
||||||
public IEnumerable<TimetableSpan> Slots => _slots;
|
public ICollection<TimetableSpan> Slots => _slots;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -36,19 +36,5 @@ namespace TimetableDesigner.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region PUBLIC METHODS
|
|
||||||
|
|
||||||
public void AddDay(TimetableDay name) => _days.Add(name);
|
|
||||||
|
|
||||||
public bool RemoveDay(TimetableDay day) => _days.Remove(day);
|
|
||||||
|
|
||||||
public void AddSlot(TimetableSpan slot) => _slots.Add(slot);
|
|
||||||
|
|
||||||
public bool RemoveSlot(TimetableSpan slot) => _slots.Remove(slot);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
14
TimetableDesigner.Customs/JsonSerializableDictionary.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Customs
|
||||||
|
{
|
||||||
|
[JsonArray]
|
||||||
|
public class JsonSerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue> where TKey : notnull
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,4 +6,8 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
7
TimetableDesigner.Scheduler/Scheduler.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace TimetableDesigner.Scheduler
|
||||||
|
{
|
||||||
|
public class Class1
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -42,12 +42,9 @@ namespace TimetableDesigner.Tests
|
|||||||
{
|
{
|
||||||
TimetableTemplate model = new TimetableTemplate();
|
TimetableTemplate model = new TimetableTemplate();
|
||||||
|
|
||||||
TimetableDay day = new TimetableDay
|
TimetableDay day = new TimetableDay("Monday");
|
||||||
{
|
|
||||||
Name = "Monday"
|
|
||||||
};
|
|
||||||
|
|
||||||
model.AddDay(day);
|
model.Days.Add(day);
|
||||||
|
|
||||||
Assert.AreEqual(1, model.Days.Count());
|
Assert.AreEqual(1, model.Days.Count());
|
||||||
Assert.AreEqual(day, model.Days.ToList()[0]);
|
Assert.AreEqual(day, model.Days.ToList()[0]);
|
||||||
@@ -60,7 +57,7 @@ namespace TimetableDesigner.Tests
|
|||||||
|
|
||||||
TimetableSpan slot = new TimetableSpan(new TimeOnly(8, 0), new TimeOnly(9, 0));
|
TimetableSpan slot = new TimetableSpan(new TimeOnly(8, 0), new TimeOnly(9, 0));
|
||||||
|
|
||||||
model.AddSlot(slot);
|
model.Slots.Add(slot);
|
||||||
|
|
||||||
Assert.AreEqual(1, model.Slots.Count());
|
Assert.AreEqual(1, model.Slots.Count());
|
||||||
Assert.AreEqual(new TimetableSpan(new TimeOnly(8, 0), new TimeOnly(9, 0)), model.Slots.ToList()[0]);
|
Assert.AreEqual(new TimetableSpan(new TimeOnly(8, 0), new TimeOnly(9, 0)), model.Slots.ToList()[0]);
|
||||||
@@ -74,8 +71,8 @@ namespace TimetableDesigner.Tests
|
|||||||
TimetableSpan slot1 = new TimetableSpan(new TimeOnly(8, 15), new TimeOnly(9, 0));
|
TimetableSpan slot1 = new TimetableSpan(new TimeOnly(8, 15), new TimeOnly(9, 0));
|
||||||
TimetableSpan slot2 = new TimetableSpan(new TimeOnly(9, 15), new TimeOnly(10, 0));
|
TimetableSpan slot2 = new TimetableSpan(new TimeOnly(9, 15), new TimeOnly(10, 0));
|
||||||
|
|
||||||
model.AddSlot(slot1);
|
model.Slots.Add(slot1);
|
||||||
model.AddSlot(slot2);
|
model.Slots.Add(slot2);
|
||||||
|
|
||||||
Assert.AreEqual(2, model.Slots.Count());
|
Assert.AreEqual(2, model.Slots.Count());
|
||||||
Assert.AreEqual(new TimetableSpan(new TimeOnly(8, 15), new TimeOnly(9, 0)), model.Slots.ToList()[0]);
|
Assert.AreEqual(new TimetableSpan(new TimeOnly(8, 15), new TimeOnly(9, 0)), model.Slots.ToList()[0]);
|
||||||
@@ -90,8 +87,8 @@ namespace TimetableDesigner.Tests
|
|||||||
TimetableSpan slot1 = new TimetableSpan(new TimeOnly(8, 0), new TimeOnly(9, 0));
|
TimetableSpan slot1 = new TimetableSpan(new TimeOnly(8, 0), new TimeOnly(9, 0));
|
||||||
TimetableSpan slot2 = new TimetableSpan(new TimeOnly(9, 0), new TimeOnly(10, 0));
|
TimetableSpan slot2 = new TimetableSpan(new TimeOnly(9, 0), new TimeOnly(10, 0));
|
||||||
|
|
||||||
model.AddSlot(slot1);
|
model.Slots.Add(slot1);
|
||||||
model.AddSlot(slot2);
|
model.Slots.Add(slot2);
|
||||||
|
|
||||||
Assert.AreEqual(2, model.Slots.Count());
|
Assert.AreEqual(2, model.Slots.Count());
|
||||||
Assert.AreEqual(new TimetableSpan(new TimeOnly(8, 0), new TimeOnly(9, 0)), model.Slots.ToList()[0]);
|
Assert.AreEqual(new TimetableSpan(new TimeOnly(8, 0), new TimeOnly(9, 0)), model.Slots.ToList()[0]);
|
||||||
@@ -107,8 +104,8 @@ namespace TimetableDesigner.Tests
|
|||||||
TimetableSpan slot1 = new TimetableSpan(new TimeOnly(8, 0), new TimeOnly(9, 30));
|
TimetableSpan slot1 = new TimetableSpan(new TimeOnly(8, 0), new TimeOnly(9, 30));
|
||||||
TimetableSpan slot2 = new TimetableSpan(new TimeOnly(8, 30), new TimeOnly(10, 0));
|
TimetableSpan slot2 = new TimetableSpan(new TimeOnly(8, 30), new TimeOnly(10, 0));
|
||||||
|
|
||||||
model.AddSlot(slot1);
|
model.Slots.Add(slot1);
|
||||||
model.AddSlot(slot2);
|
model.Slots.Add(slot2);
|
||||||
|
|
||||||
Assert.Fail();
|
Assert.Fail();
|
||||||
}
|
}
|
||||||
@@ -123,9 +120,9 @@ namespace TimetableDesigner.Tests
|
|||||||
TimetableSpan slot2 = new TimetableSpan(new TimeOnly(10, 0), new TimeOnly(11, 0));
|
TimetableSpan slot2 = new TimetableSpan(new TimeOnly(10, 0), new TimeOnly(11, 0));
|
||||||
TimetableSpan slot3 = new TimetableSpan(new TimeOnly(8, 59), new TimeOnly(10, 1));
|
TimetableSpan slot3 = new TimetableSpan(new TimeOnly(8, 59), new TimeOnly(10, 1));
|
||||||
|
|
||||||
model.AddSlot(slot1);
|
model.Slots.Add(slot1);
|
||||||
model.AddSlot(slot2);
|
model.Slots.Add(slot2);
|
||||||
model.AddSlot(slot3);
|
model.Slots.Add(slot3);
|
||||||
|
|
||||||
Assert.Fail();
|
Assert.Fail();
|
||||||
}
|
}
|
||||||
@@ -143,13 +140,13 @@ namespace TimetableDesigner.Tests
|
|||||||
TimetableSpan slot6 = new TimetableSpan(new TimeOnly(9, 0), new TimeOnly(10, 0));
|
TimetableSpan slot6 = new TimetableSpan(new TimeOnly(9, 0), new TimeOnly(10, 0));
|
||||||
TimetableSpan slot7 = new TimetableSpan(new TimeOnly(11, 0), new TimeOnly(12, 0));
|
TimetableSpan slot7 = new TimetableSpan(new TimeOnly(11, 0), new TimeOnly(12, 0));
|
||||||
|
|
||||||
model.AddSlot(slot1);
|
model.Slots.Add(slot1);
|
||||||
model.AddSlot(slot2);
|
model.Slots.Add(slot2);
|
||||||
model.AddSlot(slot3);
|
model.Slots.Add(slot3);
|
||||||
model.AddSlot(slot4);
|
model.Slots.Add(slot4);
|
||||||
model.AddSlot(slot5);
|
model.Slots.Add(slot5);
|
||||||
model.AddSlot(slot6);
|
model.Slots.Add(slot6);
|
||||||
model.AddSlot(slot7);
|
model.Slots.Add(slot7);
|
||||||
|
|
||||||
List<TimetableSpan> slots = model.Slots.ToList();
|
List<TimetableSpan> slots = model.Slots.ToList();
|
||||||
|
|
||||||
|
|||||||
15
TimetableDesigner/App.config
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<configuration>
|
||||||
|
<configSections>
|
||||||
|
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
|
||||||
|
<section name="TimetableDesigner.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
||||||
|
</sectionGroup>
|
||||||
|
</configSections>
|
||||||
|
<userSettings>
|
||||||
|
<TimetableDesigner.Properties.Settings>
|
||||||
|
<setting name="RecentProjectsCount" serializeAs="String">
|
||||||
|
<value>10</value>
|
||||||
|
</setting>
|
||||||
|
</TimetableDesigner.Properties.Settings>
|
||||||
|
</userSettings>
|
||||||
|
</configuration>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
ShutdownMode="OnMainWindowClose"
|
ShutdownMode="OnMainWindowClose"
|
||||||
StartupUri="Views/MainWindow.xaml">
|
Startup="OnStartup">
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<ResourceDictionary.MergedDictionaries>
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
|||||||
@@ -1,25 +1,88 @@
|
|||||||
using System;
|
global using TimetableDesigner.Services;
|
||||||
|
using Microsoft.ML.Data;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.Design;
|
using System.ComponentModel.Design;
|
||||||
using System.Configuration;
|
using System.Configuration;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using TimetableDesigner.Services;
|
using TimetableDesigner.Services.FileDialog;
|
||||||
using TimetableDesigner.Services.MessageBox;
|
using TimetableDesigner.Services.MessageBox;
|
||||||
using TimetableDesigner.Services.Project;
|
using TimetableDesigner.Services.Project;
|
||||||
|
using TimetableDesigner.Services.Scheduler;
|
||||||
using TimetableDesigner.Services.TabNavigation;
|
using TimetableDesigner.Services.TabNavigation;
|
||||||
|
using TimetableDesigner.ViewModels.Views;
|
||||||
|
using TimetableDesigner.Views;
|
||||||
|
|
||||||
namespace TimetableDesigner
|
namespace TimetableDesigner
|
||||||
{
|
{
|
||||||
public partial class App : Application
|
public partial class App : Application
|
||||||
{
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private IMessageBoxService _messageBoxService;
|
||||||
|
private IFileDialogService _fileDialogService;
|
||||||
|
private ITabNavigationService _tabNavigationService;
|
||||||
|
private IProjectService _projectService;
|
||||||
|
private ISchedulerService _schedulerService;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
public App()
|
public App()
|
||||||
{
|
{
|
||||||
ServiceProvider.Instance.AddService<IMessageBoxService>(new MessageBoxService());
|
_messageBoxService = new MessageBoxService();
|
||||||
ServiceProvider.Instance.AddService<ITabNavigationService>(new TabNavigationService());
|
_fileDialogService = new FileDialogService();
|
||||||
ServiceProvider.Instance.AddService<IProjectService>(new ProjectService());
|
_tabNavigationService = new TabNavigationService();
|
||||||
|
_projectService = new ProjectService();
|
||||||
|
_schedulerService = new SchedulerService(_projectService);
|
||||||
|
|
||||||
|
ServiceProvider.Instance.AddService(_messageBoxService);
|
||||||
|
ServiceProvider.Instance.AddService(_fileDialogService);
|
||||||
|
ServiceProvider.Instance.AddService(_tabNavigationService);
|
||||||
|
ServiceProvider.Instance.AddService(_projectService);
|
||||||
|
ServiceProvider.Instance.AddService(_schedulerService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PRIVATE METHODS
|
||||||
|
|
||||||
|
private void OnStartup(object sender, StartupEventArgs e)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(Globals.Path.ApplicationData))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(Globals.Path.ApplicationData);
|
||||||
|
}
|
||||||
|
|
||||||
|
_projectService.LoadRecentProjectsList();
|
||||||
|
|
||||||
|
MainWindow mainWindow = new MainWindow();
|
||||||
|
mainWindow.Show();
|
||||||
|
|
||||||
|
if (e.Args.Length > 0 && File.Exists(e.Args[0]))
|
||||||
|
{
|
||||||
|
_projectService.Load(e.Args[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TabItem welcomeTab = new TabItem()
|
||||||
|
{
|
||||||
|
Title = TimetableDesigner.Properties.Resources.Tabs_Welcome,
|
||||||
|
ViewModel = new WelcomeViewVM()
|
||||||
|
};
|
||||||
|
_tabNavigationService.AddAndActivate(welcomeTab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,10 +39,7 @@ namespace TimetableDesigner.Commands
|
|||||||
|
|
||||||
public bool CanExecute(object parameter) => _canExecute == null || _canExecute((T)parameter);
|
public bool CanExecute(object parameter) => _canExecute == null || _canExecute((T)parameter);
|
||||||
|
|
||||||
public void Execute(object parameter)
|
public void Execute(object parameter) => _execute((T)parameter);
|
||||||
{
|
|
||||||
_execute((T)parameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
355
TimetableDesigner/Controls/ClassControl.xaml
Normal file
@@ -0,0 +1,355 @@
|
|||||||
|
<UserControl x:Class="TimetableDesigner.Controls.ClassControl"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:local="clr-namespace:TimetableDesigner.Controls"
|
||||||
|
xmlns:s="clr-namespace:System;assembly=mscorlib"
|
||||||
|
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
x:Name="control"
|
||||||
|
MinWidth="100"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
|
<Border BorderBrush="Black"
|
||||||
|
BorderThickness="1"
|
||||||
|
CornerRadius="8"
|
||||||
|
Padding="2">
|
||||||
|
<Border.Background>
|
||||||
|
<SolidColorBrush Color="{Binding Color, Converter={StaticResource ByteArrayToColorConverter}}"/>
|
||||||
|
</Border.Background>
|
||||||
|
<Grid Margin="5">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition/>
|
||||||
|
<RowDefinition/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid Grid.Row="0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Grid.Column="0"
|
||||||
|
Text="{Binding Name}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
TextTrimming="CharacterEllipsis">
|
||||||
|
<TextBlock.Visibility>
|
||||||
|
<Binding Path="IsChecked"
|
||||||
|
ElementName="EditButton"
|
||||||
|
Converter="{StaticResource BooleanToVisibilityConverter}">
|
||||||
|
<Binding.ConverterParameter>
|
||||||
|
<s:Boolean>
|
||||||
|
true
|
||||||
|
</s:Boolean>
|
||||||
|
</Binding.ConverterParameter>
|
||||||
|
</Binding>
|
||||||
|
</TextBlock.Visibility>
|
||||||
|
<TextBlock.Background>
|
||||||
|
<SolidColorBrush Color="Transparent"/>
|
||||||
|
</TextBlock.Background>
|
||||||
|
<TextBlock.Style>
|
||||||
|
<Style TargetType="TextBlock">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="True">
|
||||||
|
<Setter Property="Foreground" Value="Black"/>
|
||||||
|
</DataTrigger>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="False">
|
||||||
|
<Setter Property="Foreground" Value="White"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</TextBlock.Style>
|
||||||
|
</TextBlock>
|
||||||
|
<TextBox Grid.Column="0"
|
||||||
|
Margin="2"
|
||||||
|
Text="{Binding Name}"
|
||||||
|
MaxLines="1"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Visibility="{Binding IsChecked, ElementName=EditButton, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||||
|
<TextBox.Background>
|
||||||
|
<SolidColorBrush Color="Transparent"/>
|
||||||
|
</TextBox.Background>
|
||||||
|
<TextBox.Style>
|
||||||
|
<Style TargetType="TextBox">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="True">
|
||||||
|
<Setter Property="Foreground" Value="Black"/>
|
||||||
|
</DataTrigger>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="False">
|
||||||
|
<Setter Property="Foreground" Value="White"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</TextBox.Style>
|
||||||
|
</TextBox>
|
||||||
|
<xctk:ColorPicker Grid.Column="1"
|
||||||
|
SelectedColor="{Binding Color, Converter={StaticResource ByteArrayToColorConverter}}"
|
||||||
|
Margin="2"
|
||||||
|
Width="20"
|
||||||
|
UsingAlphaChannel="False"
|
||||||
|
ShowStandardColors="False"
|
||||||
|
ShowDropDownButton="False"
|
||||||
|
Visibility="{Binding IsChecked, ElementName=EditButton, Converter={StaticResource BooleanToVisibilityConverter}}"/>
|
||||||
|
<Button Grid.Column="2"
|
||||||
|
Margin="2"
|
||||||
|
Background="Transparent"
|
||||||
|
BorderBrush="Transparent"
|
||||||
|
Visibility="{Binding IsChecked, ElementName=EditButton, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||||
|
Click="RemoveButton_Click">
|
||||||
|
<Button.Content>
|
||||||
|
<Image Width="15"
|
||||||
|
Height="15">
|
||||||
|
<Image.Style>
|
||||||
|
<Style TargetType="Image">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="True">
|
||||||
|
<Setter Property="Source" Value="{StaticResource RemoveBlackImage}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="False">
|
||||||
|
<Setter Property="Source" Value="{StaticResource RemoveWhiteImage}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</Image.Style>
|
||||||
|
</Image>
|
||||||
|
</Button.Content>
|
||||||
|
</Button>
|
||||||
|
<Button Grid.Column="3"
|
||||||
|
Margin="2"
|
||||||
|
Background="Transparent"
|
||||||
|
BorderBrush="Transparent"
|
||||||
|
Visibility="{Binding IsChecked, ElementName=EditButton, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||||
|
Click="CloneButton_Click">
|
||||||
|
<Button.Content>
|
||||||
|
<Image Width="15"
|
||||||
|
Height="15">
|
||||||
|
<Image.Style>
|
||||||
|
<Style TargetType="Image">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="True">
|
||||||
|
<Setter Property="Source" Value="{StaticResource CloneBlackImage}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="False">
|
||||||
|
<Setter Property="Source" Value="{StaticResource CloneWhiteImage}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</Image.Style>
|
||||||
|
</Image>
|
||||||
|
</Button.Content>
|
||||||
|
</Button>
|
||||||
|
<ToggleButton Grid.Column="4"
|
||||||
|
x:Name="EditButton"
|
||||||
|
Margin="2"
|
||||||
|
Background="Transparent"
|
||||||
|
BorderBrush="Transparent">
|
||||||
|
<ToggleButton.Content>
|
||||||
|
<Image Width="15"
|
||||||
|
Height="15">
|
||||||
|
<Image.Style>
|
||||||
|
<Style TargetType="Image">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="True">
|
||||||
|
<Setter Property="Source" Value="{StaticResource EditBlackImage}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="False">
|
||||||
|
<Setter Property="Source" Value="{StaticResource EditWhiteImage}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</Image.Style>
|
||||||
|
</Image>
|
||||||
|
</ToggleButton.Content>
|
||||||
|
</ToggleButton>
|
||||||
|
</Grid>
|
||||||
|
<Grid Grid.Row="1">
|
||||||
|
<Grid.Visibility>
|
||||||
|
<Binding Path="IsChecked"
|
||||||
|
ElementName="EditButton"
|
||||||
|
Converter="{StaticResource BooleanToVisibilityConverter}">
|
||||||
|
<Binding.ConverterParameter>
|
||||||
|
<s:Boolean>
|
||||||
|
true
|
||||||
|
</s:Boolean>
|
||||||
|
</Binding.ConverterParameter>
|
||||||
|
</Binding>
|
||||||
|
</Grid.Visibility>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition x:Name="GroupPreviewColumn"/>
|
||||||
|
<ColumnDefinition x:Name="TeacherPreviewColumn"/>
|
||||||
|
<ColumnDefinition x:Name="ClassroomPreviewColumn"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Image Grid.Column="0"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Width="20"
|
||||||
|
Height="20"
|
||||||
|
ToolTip="{Binding Group.Name}">
|
||||||
|
<Image.Style>
|
||||||
|
<Style TargetType="Image">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="True">
|
||||||
|
<Setter Property="Source" Value="{StaticResource GroupBlackImage}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="False">
|
||||||
|
<Setter Property="Source" Value="{StaticResource GroupWhiteImage}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</Image.Style>
|
||||||
|
</Image>
|
||||||
|
<Image Grid.Column="1"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Width="20"
|
||||||
|
Height="20"
|
||||||
|
ToolTip="{Binding Teacher.Name}">
|
||||||
|
<Image.Style>
|
||||||
|
<Style TargetType="Image">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="True">
|
||||||
|
<Setter Property="Source" Value="{StaticResource TeacherBlackImage}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="False">
|
||||||
|
<Setter Property="Source" Value="{StaticResource TeacherWhiteImage}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</Image.Style>
|
||||||
|
</Image>
|
||||||
|
<Image Grid.Column="2"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Width="20"
|
||||||
|
Height="20"
|
||||||
|
ToolTip="{Binding Classroom.Name}">
|
||||||
|
<Image.Style>
|
||||||
|
<Style TargetType="Image">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="True">
|
||||||
|
<Setter Property="Source" Value="{StaticResource ClassroomBlackImage}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="False">
|
||||||
|
<Setter Property="Source" Value="{StaticResource ClassroomWhiteImage}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</Image.Style>
|
||||||
|
</Image>
|
||||||
|
</Grid>
|
||||||
|
<Grid Grid.Row="1"
|
||||||
|
Margin="5"
|
||||||
|
Visibility="{Binding IsChecked, ElementName=EditButton, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" x:Name="GroupEditRow"/>
|
||||||
|
<RowDefinition Height="Auto" x:Name="TeacherEditRow"/>
|
||||||
|
<RowDefinition Height="Auto" x:Name="ClassroomEditRow"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Image Grid.Row="0"
|
||||||
|
Grid.Column="0"
|
||||||
|
Width="20"
|
||||||
|
Height="20">
|
||||||
|
<Image.Style>
|
||||||
|
<Style TargetType="Image">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="True">
|
||||||
|
<Setter Property="Source" Value="{StaticResource GroupBlackImage}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="False">
|
||||||
|
<Setter Property="Source" Value="{StaticResource GroupWhiteImage}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</Image.Style>
|
||||||
|
</Image>
|
||||||
|
<ComboBox Grid.Row="0"
|
||||||
|
Grid.Column="1"
|
||||||
|
Margin="5,0,0,0"
|
||||||
|
SelectedItem="{Binding Group, Mode=TwoWay}"
|
||||||
|
DisplayMemberPath="Name">
|
||||||
|
<ComboBox.Resources>
|
||||||
|
<CollectionViewSource x:Key="Groups" Source="{Binding ElementName=control, Path=ProjectService.ProjectViewModel.Groups}"/>
|
||||||
|
<CollectionViewSource x:Key="Subgroups" Source="{Binding ElementName=control, Path=ProjectService.ProjectViewModel.Subgroups}"/>
|
||||||
|
</ComboBox.Resources>
|
||||||
|
<ComboBox.ItemsSource>
|
||||||
|
<CompositeCollection>
|
||||||
|
<CollectionContainer Collection="{Binding Source={StaticResource Groups}}"/>
|
||||||
|
<CollectionContainer Collection="{Binding Source={StaticResource Subgroups}}"/>
|
||||||
|
</CompositeCollection>
|
||||||
|
</ComboBox.ItemsSource>
|
||||||
|
</ComboBox>
|
||||||
|
<Image Grid.Row="1"
|
||||||
|
Width="20"
|
||||||
|
Height="20">
|
||||||
|
<Image.Style>
|
||||||
|
<Style TargetType="Image">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="True">
|
||||||
|
<Setter Property="Source" Value="{StaticResource TeacherBlackImage}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="False">
|
||||||
|
<Setter Property="Source" Value="{StaticResource TeacherWhiteImage}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</Image.Style>
|
||||||
|
</Image>
|
||||||
|
<ComboBox Grid.Row="1"
|
||||||
|
Grid.Column="1"
|
||||||
|
Margin="5,2,0,2"
|
||||||
|
SelectedItem="{Binding Teacher, Mode=TwoWay}"
|
||||||
|
ItemsSource="{Binding ElementName=control, Path=ProjectService.ProjectViewModel.Teachers}"
|
||||||
|
DisplayMemberPath="Name"/>
|
||||||
|
<Image Grid.Row="2"
|
||||||
|
Width="20"
|
||||||
|
Height="20">
|
||||||
|
<Image.Style>
|
||||||
|
<Style TargetType="Image">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="True">
|
||||||
|
<Setter Property="Source" Value="{StaticResource ClassroomBlackImage}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
<DataTrigger Binding="{Binding Color, Converter={StaticResource ColorBrightnessIsHigherToBooleanConverter}, ConverterParameter=130}"
|
||||||
|
Value="False">
|
||||||
|
<Setter Property="Source" Value="{StaticResource ClassroomWhiteImage}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</Image.Style>
|
||||||
|
</Image>
|
||||||
|
<ComboBox Grid.Row="2"
|
||||||
|
Grid.Column="1"
|
||||||
|
Margin="5,0,0,0"
|
||||||
|
SelectedItem="{Binding Classroom, Mode=TwoWay}"
|
||||||
|
ItemsSource="{Binding ElementName=control, Path=ProjectService.ProjectViewModel.Classrooms}"
|
||||||
|
DisplayMemberPath="Name"/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</UserControl>
|
||||||
119
TimetableDesigner/Controls/ClassControl.xaml.cs
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
using TimetableDesigner.Core;
|
||||||
|
using TimetableDesigner.Services;
|
||||||
|
using TimetableDesigner.Services.Project;
|
||||||
|
using TimetableDesigner.Services.TabNavigation;
|
||||||
|
using TimetableDesigner.ViewModels.Models;
|
||||||
|
using TimetableDesigner.ViewModels.Models.Base;
|
||||||
|
using TimetableDesigner.ViewModels.Views;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Controls
|
||||||
|
{
|
||||||
|
public partial class ClassControl : UserControl
|
||||||
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private IProjectService _projectService;
|
||||||
|
private ITabNavigationService _tabNavigationService;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PROPERTIES
|
||||||
|
|
||||||
|
private static DependencyProperty RemoveButtonCommandProperty = DependencyProperty.Register(
|
||||||
|
"RemoveButtonCommand",
|
||||||
|
typeof(ICommand),
|
||||||
|
typeof(ClassControl),
|
||||||
|
new PropertyMetadata(null)
|
||||||
|
);
|
||||||
|
public ICommand RemoveButtonCommand
|
||||||
|
{
|
||||||
|
get => (ICommand)GetValue(RemoveButtonCommandProperty);
|
||||||
|
set => SetValue(RemoveButtonCommandProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DependencyProperty RemoveButtonCommandParameterProperty = DependencyProperty.Register(
|
||||||
|
"RemoveButtonCommandParameter",
|
||||||
|
typeof(object),
|
||||||
|
typeof(ClassControl),
|
||||||
|
new PropertyMetadata(null)
|
||||||
|
);
|
||||||
|
public object RemoveButtonCommandParameter
|
||||||
|
{
|
||||||
|
get => GetValue(RemoveButtonCommandParameterProperty);
|
||||||
|
set => SetValue(RemoveButtonCommandParameterProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DependencyProperty CloneButtonCommandProperty = DependencyProperty.Register(
|
||||||
|
"CloneButtonCommand",
|
||||||
|
typeof(ICommand),
|
||||||
|
typeof(ClassControl),
|
||||||
|
new PropertyMetadata(null)
|
||||||
|
);
|
||||||
|
public ICommand CloneButtonCommand
|
||||||
|
{
|
||||||
|
get => (ICommand)GetValue(CloneButtonCommandProperty);
|
||||||
|
set => SetValue(CloneButtonCommandProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DependencyProperty CloneButtonCommandParameterProperty = DependencyProperty.Register(
|
||||||
|
"CloneButtonCommandParameter",
|
||||||
|
typeof(object),
|
||||||
|
typeof(ClassControl),
|
||||||
|
new PropertyMetadata(null)
|
||||||
|
);
|
||||||
|
public object CloneButtonCommandParameter
|
||||||
|
{
|
||||||
|
get => GetValue(CloneButtonCommandParameterProperty);
|
||||||
|
set => SetValue(CloneButtonCommandParameterProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public IProjectService ProjectService => _projectService;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public ClassControl()
|
||||||
|
{
|
||||||
|
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
|
||||||
|
_tabNavigationService = ServiceProvider.Instance.GetService<ITabNavigationService>();
|
||||||
|
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PRIVATE METHODS
|
||||||
|
|
||||||
|
private void RemoveButton_Click(object sender, RoutedEventArgs e) => RemoveButtonCommand?.Execute(RemoveButtonCommandParameter);
|
||||||
|
|
||||||
|
private void CloneButton_Click(object sender, RoutedEventArgs e) => CloneButtonCommand?.Execute(CloneButtonCommandParameter);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
10
TimetableDesigner/Controls/DynamicGrid.xaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<UserControl x:Class="TimetableDesigner.Controls.DynamicGrid"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:local="clr-namespace:TimetableDesigner.Controls"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
|
<Grid x:Name="BaseGrid"/>
|
||||||
|
</UserControl>
|
||||||
602
TimetableDesigner/Controls/DynamicGrid.xaml.cs
Normal file
@@ -0,0 +1,602 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Controls.Primitives;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Threading;
|
||||||
|
using static TimetableDesigner.ViewModels.Views.TimetableEditorViewVM;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Controls
|
||||||
|
{
|
||||||
|
public partial class DynamicGrid : UserControl
|
||||||
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private Border[,]? _contentCells;
|
||||||
|
private Border[]? _columnHeadersCells;
|
||||||
|
private Border[]? _rowHeadersCells;
|
||||||
|
private List<DispatcherOperation> _dispatcherOperations;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PROPERTIES
|
||||||
|
|
||||||
|
private static DependencyProperty ColumnsProperty = DependencyProperty.Register(
|
||||||
|
"Columns",
|
||||||
|
typeof(int),
|
||||||
|
typeof(DynamicGrid),
|
||||||
|
new PropertyMetadata(0, new PropertyChangedCallback(OnLayoutChanged))
|
||||||
|
);
|
||||||
|
public int Columns
|
||||||
|
{
|
||||||
|
get => (int)GetValue(ColumnsProperty);
|
||||||
|
set => SetValue(ColumnsProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DependencyProperty RowsProperty = DependencyProperty.Register(
|
||||||
|
"Rows",
|
||||||
|
typeof(int),
|
||||||
|
typeof(DynamicGrid),
|
||||||
|
new PropertyMetadata(0, new PropertyChangedCallback(OnLayoutChanged))
|
||||||
|
);
|
||||||
|
public int Rows
|
||||||
|
{
|
||||||
|
get => (int)GetValue(RowsProperty);
|
||||||
|
set => SetValue(RowsProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static DependencyProperty ColumnHeadersSourceProperty = DependencyProperty.Register(
|
||||||
|
"ColumnHeadersSource",
|
||||||
|
typeof(IEnumerable),
|
||||||
|
typeof(DynamicGrid),
|
||||||
|
new PropertyMetadata(new PropertyChangedCallback(OnColumnHeadersChanged))
|
||||||
|
);
|
||||||
|
public IEnumerable ColumnHeadersSource
|
||||||
|
{
|
||||||
|
get => (IEnumerable)GetValue(ColumnHeadersSourceProperty);
|
||||||
|
set => SetValue(ColumnHeadersSourceProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static DependencyProperty ColumnHeadersTemplateProperty = DependencyProperty.Register(
|
||||||
|
"ColumnHeadersTemplate",
|
||||||
|
typeof(DataTemplate),
|
||||||
|
typeof(DynamicGrid),
|
||||||
|
new PropertyMetadata(new PropertyChangedCallback(OnColumnHeadersChanged))
|
||||||
|
);
|
||||||
|
public DataTemplate ColumnHeadersTemplate
|
||||||
|
{
|
||||||
|
get => (DataTemplate)GetValue(ColumnHeadersTemplateProperty);
|
||||||
|
set => SetValue(ColumnHeadersTemplateProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static DependencyProperty RowHeadersSourceProperty = DependencyProperty.Register(
|
||||||
|
"RowHeadersSource",
|
||||||
|
typeof(IEnumerable),
|
||||||
|
typeof(DynamicGrid),
|
||||||
|
new PropertyMetadata(new PropertyChangedCallback(OnRowHeadersChanged))
|
||||||
|
);
|
||||||
|
public IEnumerable RowHeadersSource
|
||||||
|
{
|
||||||
|
get => (IEnumerable)GetValue(RowHeadersSourceProperty);
|
||||||
|
set => SetValue(RowHeadersSourceProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DependencyProperty RowHeadersTemplateProperty = DependencyProperty.Register(
|
||||||
|
"RowHeadersTemplate",
|
||||||
|
typeof(DataTemplate),
|
||||||
|
typeof(DynamicGrid),
|
||||||
|
new PropertyMetadata(new PropertyChangedCallback(OnRowHeadersChanged))
|
||||||
|
);
|
||||||
|
public DataTemplate RowHeadersTemplate
|
||||||
|
{
|
||||||
|
get => (DataTemplate)GetValue(RowHeadersTemplateProperty);
|
||||||
|
set => SetValue(RowHeadersTemplateProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static DependencyProperty ItemsSourceProperty = DependencyProperty.Register(
|
||||||
|
"ItemsSource",
|
||||||
|
typeof(IEnumerable),
|
||||||
|
typeof(DynamicGrid),
|
||||||
|
new PropertyMetadata(new PropertyChangedCallback(OnItemsChanged))
|
||||||
|
);
|
||||||
|
public IEnumerable ItemsSource
|
||||||
|
{
|
||||||
|
get => (IEnumerable)GetValue(ItemsSourceProperty);
|
||||||
|
set => SetValue(ItemsSourceProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DependencyProperty ItemTemplateProperty = DependencyProperty.Register(
|
||||||
|
"ItemTemplate",
|
||||||
|
typeof(DataTemplate),
|
||||||
|
typeof(DynamicGrid),
|
||||||
|
new PropertyMetadata(new PropertyChangedCallback(OnItemsChanged))
|
||||||
|
);
|
||||||
|
public DataTemplate ItemTemplate
|
||||||
|
{
|
||||||
|
get => (DataTemplate)GetValue(ItemTemplateProperty);
|
||||||
|
set => SetValue(ItemTemplateProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DependencyProperty CellBorderThicknessProperty = DependencyProperty.Register(
|
||||||
|
"CellBorderThickness",
|
||||||
|
typeof(Thickness),
|
||||||
|
typeof(DynamicGrid),
|
||||||
|
new PropertyMetadata(new Thickness(0), new PropertyChangedCallback(OnCellBorderThicknessChanged))
|
||||||
|
);
|
||||||
|
public Thickness CellBorderThickness
|
||||||
|
{
|
||||||
|
get => (Thickness)GetValue(CellBorderThicknessProperty);
|
||||||
|
set => SetValue(CellBorderThicknessProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DependencyProperty CellBorderBrushProperty = DependencyProperty.Register(
|
||||||
|
"CellBorderBrush",
|
||||||
|
typeof(Brush),
|
||||||
|
typeof(DynamicGrid),
|
||||||
|
new PropertyMetadata(Brushes.Black, new PropertyChangedCallback(OnCellBorderBrushChanged))
|
||||||
|
);
|
||||||
|
public Brush CellBorderBrush
|
||||||
|
{
|
||||||
|
get => (Brush)GetValue(CellBorderBrushProperty);
|
||||||
|
set => SetValue(CellBorderBrushProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DependencyProperty HeaderCellBorderThicknessProperty = DependencyProperty.Register(
|
||||||
|
"HeaderCellBorderThickness",
|
||||||
|
typeof(Thickness?),
|
||||||
|
typeof(DynamicGrid),
|
||||||
|
new PropertyMetadata(null, new PropertyChangedCallback(OnHeaderCellBorderThicknessChanged))
|
||||||
|
);
|
||||||
|
public Thickness HeaderCellBorderThickness
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Thickness? headerThickness = (Thickness)GetValue(HeaderCellBorderThicknessProperty);
|
||||||
|
if (headerThickness is null)
|
||||||
|
{
|
||||||
|
return CellBorderThickness;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return headerThickness.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set => SetValue(HeaderCellBorderThicknessProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DependencyProperty HeaderCellBorderBrushProperty = DependencyProperty.Register(
|
||||||
|
"HeaderCellBorderBrush",
|
||||||
|
typeof(Brush),
|
||||||
|
typeof(DynamicGrid),
|
||||||
|
new PropertyMetadata(null, new PropertyChangedCallback(OnHeaderCellBorderBrushChanged))
|
||||||
|
);
|
||||||
|
public Brush? HeaderCellBorderBrush
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Brush headerBrush = (Brush)GetValue(HeaderCellBorderBrushProperty);
|
||||||
|
if (headerBrush is null)
|
||||||
|
{
|
||||||
|
headerBrush = CellBorderBrush;
|
||||||
|
}
|
||||||
|
return headerBrush;
|
||||||
|
}
|
||||||
|
set => SetValue(HeaderCellBorderBrushProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DependencyProperty StrechHeaderCellsToContentCellsSizeProperty = DependencyProperty.Register(
|
||||||
|
"StrechHeaderCellsToContentCellsSize",
|
||||||
|
typeof(bool),
|
||||||
|
typeof(DynamicGrid),
|
||||||
|
new PropertyMetadata(false, new PropertyChangedCallback(OnStrechHeaderCellsToContentCellsSizeChanged))
|
||||||
|
);
|
||||||
|
public bool StrechHeaderCellsToContentCellsSize
|
||||||
|
{
|
||||||
|
get => (bool)GetValue(StrechHeaderCellsToContentCellsSizeProperty);
|
||||||
|
set => SetValue(StrechHeaderCellsToContentCellsSizeProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region EVENTS
|
||||||
|
|
||||||
|
private static DependencyProperty ItemMovedCommandProperty = DependencyProperty.Register(
|
||||||
|
"ItemMovedCommand",
|
||||||
|
typeof(ICommand),
|
||||||
|
typeof(DynamicGrid),
|
||||||
|
new PropertyMetadata(null)
|
||||||
|
);
|
||||||
|
public ICommand ItemMovedCommand
|
||||||
|
{
|
||||||
|
get => (ICommand)GetValue(ItemMovedCommandProperty);
|
||||||
|
set => SetValue(ItemMovedCommandProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DependencyProperty ItemMovedCommandParameterProperty = DependencyProperty.Register(
|
||||||
|
"ItemMovedCommandParameter",
|
||||||
|
typeof(object),
|
||||||
|
typeof(DynamicGrid),
|
||||||
|
new PropertyMetadata(null)
|
||||||
|
);
|
||||||
|
public object ItemMovedCommandParameter
|
||||||
|
{
|
||||||
|
get => (object)GetValue(ItemMovedCommandParameterProperty);
|
||||||
|
set => SetValue(ItemMovedCommandParameterProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Browsable(true)]
|
||||||
|
[Category("Action")]
|
||||||
|
[Description("Invoked when item moved to another cell")]
|
||||||
|
public event EventHandler ItemMoved;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public DynamicGrid()
|
||||||
|
{
|
||||||
|
_columnHeadersCells = null;
|
||||||
|
_rowHeadersCells = null;
|
||||||
|
_contentCells = null;
|
||||||
|
_dispatcherOperations = new List<DispatcherOperation>();
|
||||||
|
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PRIVATE METHODS
|
||||||
|
|
||||||
|
private void LayoutRefresh()
|
||||||
|
{
|
||||||
|
BaseGrid.Children.Clear();
|
||||||
|
BaseGrid.ColumnDefinitions.Clear();
|
||||||
|
BaseGrid.RowDefinitions.Clear();
|
||||||
|
|
||||||
|
if (Rows <= 0 || Columns <= 0)
|
||||||
|
{
|
||||||
|
_rowHeadersCells = null;
|
||||||
|
_columnHeadersCells = null;
|
||||||
|
_contentCells = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_rowHeadersCells = null;
|
||||||
|
_columnHeadersCells = null;
|
||||||
|
_contentCells = new Border[Rows, Columns];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool columnHeaders = ColumnHeadersSource != null && ColumnHeadersSource.Cast<object>().Any();
|
||||||
|
short columnHeadersNum = Convert.ToInt16(columnHeaders);
|
||||||
|
|
||||||
|
bool rowHeaders = RowHeadersSource != null && RowHeadersSource.Cast<object>().Any();
|
||||||
|
short rowHeadersNum = Convert.ToInt16(rowHeaders);
|
||||||
|
|
||||||
|
if (columnHeaders)
|
||||||
|
{
|
||||||
|
RowDefinition columnHeaderRow = new RowDefinition();
|
||||||
|
if (!StrechHeaderCellsToContentCellsSize)
|
||||||
|
{
|
||||||
|
columnHeaderRow.Height = GridLength.Auto;
|
||||||
|
}
|
||||||
|
BaseGrid.RowDefinitions.Add(columnHeaderRow);
|
||||||
|
_columnHeadersCells = new Border[Columns];
|
||||||
|
|
||||||
|
for (int column = 0; column < Columns; column++)
|
||||||
|
{
|
||||||
|
Border border = new Border()
|
||||||
|
{
|
||||||
|
BorderBrush = HeaderCellBorderBrush,
|
||||||
|
BorderThickness = HeaderCellBorderThickness,
|
||||||
|
};
|
||||||
|
Grid.SetColumn(border, column + rowHeadersNum);
|
||||||
|
Grid.SetRow(border, 0);
|
||||||
|
BaseGrid.Children.Add(border);
|
||||||
|
_columnHeadersCells[column] = border;
|
||||||
|
}
|
||||||
|
ColumnHeadersRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rowHeaders)
|
||||||
|
{
|
||||||
|
ColumnDefinition rowHeaderColumn = new ColumnDefinition();
|
||||||
|
if (!StrechHeaderCellsToContentCellsSize)
|
||||||
|
{
|
||||||
|
rowHeaderColumn.Width = GridLength.Auto;
|
||||||
|
}
|
||||||
|
BaseGrid.ColumnDefinitions.Add(rowHeaderColumn);
|
||||||
|
_rowHeadersCells = new Border[Rows];
|
||||||
|
|
||||||
|
for (int row = 0; row < Rows; row++)
|
||||||
|
{
|
||||||
|
Border border = new Border()
|
||||||
|
{
|
||||||
|
BorderBrush = HeaderCellBorderBrush,
|
||||||
|
BorderThickness = HeaderCellBorderThickness,
|
||||||
|
};
|
||||||
|
Grid.SetColumn(border, 0);
|
||||||
|
Grid.SetRow(border, row + columnHeadersNum);
|
||||||
|
BaseGrid.Children.Add(border);
|
||||||
|
_rowHeadersCells[row] = border;
|
||||||
|
}
|
||||||
|
RowHeadersRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int _ = 0; _ < Rows; _++)
|
||||||
|
{
|
||||||
|
BaseGrid.RowDefinitions.Add(new RowDefinition()
|
||||||
|
{
|
||||||
|
Height = GridLength.Auto,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for (int _ = 0; _ < Columns; _++)
|
||||||
|
{
|
||||||
|
BaseGrid.ColumnDefinitions.Add(new ColumnDefinition()
|
||||||
|
{
|
||||||
|
Width = GridLength.Auto,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int row = 0; row < Rows; row++)
|
||||||
|
{
|
||||||
|
for (int column = 0; column < Columns; column++)
|
||||||
|
{
|
||||||
|
Border border = new Border()
|
||||||
|
{
|
||||||
|
BorderBrush = CellBorderBrush,
|
||||||
|
BorderThickness = CellBorderThickness,
|
||||||
|
};
|
||||||
|
Grid.SetColumn(border, column + rowHeadersNum);
|
||||||
|
Grid.SetRow(border, row + columnHeadersNum);
|
||||||
|
|
||||||
|
UniformGrid grid = new UniformGrid()
|
||||||
|
{
|
||||||
|
Rows = 1,
|
||||||
|
AllowDrop = true,
|
||||||
|
Background = Brushes.Transparent,
|
||||||
|
};
|
||||||
|
grid.Drop += OnItemMoved;
|
||||||
|
|
||||||
|
border.Child = grid;
|
||||||
|
|
||||||
|
BaseGrid.Children.Add(border);
|
||||||
|
_contentCells[row, column] = border;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ItemsRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ColumnHeadersRefresh(bool switched = false) => HeadersRefresh(switched, ColumnHeadersSource, _columnHeadersCells, ColumnHeadersTemplate);
|
||||||
|
private void RowHeadersRefresh(bool switched = false) => HeadersRefresh(switched, RowHeadersSource, _rowHeadersCells, RowHeadersTemplate);
|
||||||
|
private void HeadersRefresh(bool switched, IEnumerable headerSource, Border[]? headerCells, DataTemplate headerTemplate)
|
||||||
|
{
|
||||||
|
if (switched)
|
||||||
|
{
|
||||||
|
LayoutRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headerSource is not null && headerCells is not null)
|
||||||
|
{
|
||||||
|
IEnumerable<object> headersSourceCollection = headerSource.Cast<object>();
|
||||||
|
for (int index = 0; index < headerCells.Length; index++)
|
||||||
|
{
|
||||||
|
headerCells[index].Child = null;
|
||||||
|
if (index < headersSourceCollection.Count())
|
||||||
|
{
|
||||||
|
object headerItem = headersSourceCollection.ElementAt(index);
|
||||||
|
|
||||||
|
FrameworkElement? control = null;
|
||||||
|
if (headerTemplate is not null)
|
||||||
|
{
|
||||||
|
control = headerTemplate.LoadContent() as FrameworkElement;
|
||||||
|
if (control is not null)
|
||||||
|
{
|
||||||
|
control.DataContext = headerItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control ??= new Label()
|
||||||
|
{
|
||||||
|
Content = headerItem.ToString()
|
||||||
|
};
|
||||||
|
|
||||||
|
headerCells[index].Child = control;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CellBorderRefresh(CellBorderRefreshProperty mode, CellBorderRefreshType type)
|
||||||
|
{
|
||||||
|
if ((type & CellBorderRefreshType.Headers) == CellBorderRefreshType.Headers)
|
||||||
|
{
|
||||||
|
List<IEnumerable<Border>> headerCellsCollection = new List<IEnumerable<Border>>();
|
||||||
|
if (_columnHeadersCells is not null) headerCellsCollection.Add(_columnHeadersCells);
|
||||||
|
if (_rowHeadersCells is not null) headerCellsCollection.Add(_rowHeadersCells);
|
||||||
|
foreach (IEnumerable<Border> cells in headerCellsCollection)
|
||||||
|
{
|
||||||
|
foreach (Border cell in cells)
|
||||||
|
{
|
||||||
|
if ((mode & CellBorderRefreshProperty.Thickness) == CellBorderRefreshProperty.Thickness) cell.BorderThickness = HeaderCellBorderThickness;
|
||||||
|
if ((mode & CellBorderRefreshProperty.Brush) == CellBorderRefreshProperty.Brush) cell.BorderBrush = HeaderCellBorderBrush;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((type & CellBorderRefreshType.Content) == CellBorderRefreshType.Content && _contentCells is not null)
|
||||||
|
{
|
||||||
|
foreach (Border cell in _contentCells)
|
||||||
|
{
|
||||||
|
if ((mode & CellBorderRefreshProperty.Thickness) == CellBorderRefreshProperty.Thickness) cell.BorderThickness = CellBorderThickness;
|
||||||
|
if ((mode & CellBorderRefreshProperty.Brush) == CellBorderRefreshProperty.Brush) cell.BorderBrush = CellBorderBrush;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ItemsRefresh()
|
||||||
|
{
|
||||||
|
if (ItemsSource is not null && _contentCells is not null)
|
||||||
|
{
|
||||||
|
foreach (DispatcherOperation operation in _dispatcherOperations)
|
||||||
|
{
|
||||||
|
operation.Abort();
|
||||||
|
}
|
||||||
|
_dispatcherOperations.Clear();
|
||||||
|
|
||||||
|
foreach (Border cell in _contentCells)
|
||||||
|
{
|
||||||
|
((UniformGrid)cell.Child).Children.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<object> itemsSourceCollection = ItemsSource.Cast<object>();
|
||||||
|
foreach (object item in itemsSourceCollection)
|
||||||
|
{
|
||||||
|
FrameworkElement? control = null;
|
||||||
|
if (ItemTemplate is not null)
|
||||||
|
{
|
||||||
|
control = ItemTemplate.LoadContent() as FrameworkElement;
|
||||||
|
if (control is not null)
|
||||||
|
{
|
||||||
|
control.DataContext = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control ??= new Label()
|
||||||
|
{
|
||||||
|
Content = item.ToString()
|
||||||
|
};
|
||||||
|
|
||||||
|
DispatcherOperation operation = Dispatcher.BeginInvoke(() =>
|
||||||
|
{
|
||||||
|
int row = GetRow(control);
|
||||||
|
int column = GetColumn(control);
|
||||||
|
Border cell = _contentCells[row, column];
|
||||||
|
UniformGrid cellGrid = (UniformGrid)cell.Child;
|
||||||
|
if (!cellGrid.Children.Contains(control))
|
||||||
|
{
|
||||||
|
cellGrid.Children.Add(control);
|
||||||
|
}
|
||||||
|
}, DispatcherPriority.Loaded);
|
||||||
|
_dispatcherOperations.Add(operation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnItemMoved(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
UniformGrid? target = sender as UniformGrid;
|
||||||
|
object item = e.Data.GetData(DataFormats.Serializable);
|
||||||
|
if (target is not null && item is UIElement element && _contentCells is not null)
|
||||||
|
{
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
for (x = 0; x < _contentCells.GetLength(0); x++)
|
||||||
|
{
|
||||||
|
for (y = 0; y < _contentCells.GetLength(1); y++)
|
||||||
|
{
|
||||||
|
if (_contentCells[x, y].Child.Equals(target))
|
||||||
|
{
|
||||||
|
goto LoopEnd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LoopEnd:
|
||||||
|
if (x != GetRow(element) || y != GetColumn(element))
|
||||||
|
{
|
||||||
|
SetRow(element, x);
|
||||||
|
SetColumn(element, y);
|
||||||
|
ItemMoved?.Invoke(this, EventArgs.Empty);
|
||||||
|
ItemMovedCommand?.Execute(ItemMovedCommandParameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HeaderRowColumnSizeRefresh()
|
||||||
|
{
|
||||||
|
GridLength size;
|
||||||
|
if (StrechHeaderCellsToContentCellsSize)
|
||||||
|
{
|
||||||
|
size = new GridLength(1, GridUnitType.Star);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size = GridLength.Auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BaseGrid.RowDefinitions.Count > 1 && ColumnHeadersSource is not null)
|
||||||
|
{
|
||||||
|
BaseGrid.RowDefinitions[0].Height = size;
|
||||||
|
}
|
||||||
|
if (BaseGrid.ColumnDefinitions.Count > 1 && RowHeadersSource is not null)
|
||||||
|
{
|
||||||
|
BaseGrid.ColumnDefinitions[0].Width = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnLayoutChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) => ((DynamicGrid)obj).LayoutRefresh();
|
||||||
|
private static void OnColumnHeadersChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) => ((DynamicGrid)obj).ColumnHeadersRefresh((args.OldValue is null && args.NewValue is not null) || (args.OldValue is not null && args.NewValue is null));
|
||||||
|
private static void OnRowHeadersChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) => ((DynamicGrid)obj).RowHeadersRefresh((args.OldValue is null && args.NewValue is not null) || (args.OldValue is not null && args.NewValue is null));
|
||||||
|
private static void OnItemsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) => ((DynamicGrid)obj).ItemsRefresh();
|
||||||
|
private static void OnCellBorderThicknessChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) => ((DynamicGrid)obj).CellBorderRefresh(CellBorderRefreshProperty.Thickness, obj.GetValue(HeaderCellBorderThicknessProperty) is null ? CellBorderRefreshType.Headers | CellBorderRefreshType.Content : CellBorderRefreshType.Content);
|
||||||
|
private static void OnCellBorderBrushChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) => ((DynamicGrid)obj).CellBorderRefresh(CellBorderRefreshProperty.Brush, obj.GetValue(HeaderCellBorderBrushProperty) is null ? CellBorderRefreshType.Headers | CellBorderRefreshType.Content : CellBorderRefreshType.Content);
|
||||||
|
private static void OnHeaderCellBorderThicknessChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) => ((DynamicGrid)obj).CellBorderRefresh(CellBorderRefreshProperty.Thickness, CellBorderRefreshType.Headers);
|
||||||
|
private static void OnHeaderCellBorderBrushChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) => ((DynamicGrid)obj).CellBorderRefresh(CellBorderRefreshProperty.Brush, CellBorderRefreshType.Headers);
|
||||||
|
private static void OnStrechHeaderCellsToContentCellsSizeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) => ((DynamicGrid)obj).HeaderRowColumnSizeRefresh();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region COLUMN/ROW SET/GET STATIC METHODS
|
||||||
|
|
||||||
|
private static DependencyProperty ColumnProperty = DependencyProperty.RegisterAttached("Column", typeof(int), typeof(DynamicGrid), new PropertyMetadata(0));
|
||||||
|
public static int GetColumn(UIElement element) => (int)element.GetValue(ColumnProperty);
|
||||||
|
public static void SetColumn(UIElement element, int value) => element.SetValue(ColumnProperty, value);
|
||||||
|
|
||||||
|
private static DependencyProperty RowProperty = DependencyProperty.RegisterAttached("Row", typeof(int), typeof(DynamicGrid), new PropertyMetadata(0));
|
||||||
|
public static int GetRow(UIElement element) => (int)element.GetValue(RowProperty);
|
||||||
|
public static void SetRow(UIElement element, int value) => element.SetValue(RowProperty, value);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region ENUMS
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
private enum CellBorderRefreshProperty
|
||||||
|
{
|
||||||
|
Brush = 1,
|
||||||
|
Thickness = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
private enum CellBorderRefreshType
|
||||||
|
{
|
||||||
|
Headers = 1,
|
||||||
|
Content = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
<UserControl x:Class="TimetableDesigner.Controls.TimetableEditorControl"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:local="clr-namespace:TimetableDesigner.Controls"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignHeight="450" d:DesignWidth="800">
|
|
||||||
<Grid>
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition/>
|
|
||||||
<ColumnDefinition Width="Auto"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<ItemsControl Grid.Column="0" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=_projectService.ProjectViewModel}">
|
|
||||||
<ItemsControl.ItemsPanel>
|
|
||||||
<ItemsPanelTemplate>
|
|
||||||
<UniformGrid Grid.Column="0"
|
|
||||||
Rows="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=_projectService.ProjectViewModel.TimetableTemplate.Slots.Count, Converter={StaticResource IntegerAddConstantConverter}, ConverterParameter=1}"
|
|
||||||
Columns="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=_projectService.ProjectViewModel.TimetableTemplate.Days.Count, Converter={StaticResource IntegerAddConstantConverter}, ConverterParameter=1}"/>
|
|
||||||
</ItemsPanelTemplate>
|
|
||||||
</ItemsControl.ItemsPanel>
|
|
||||||
<ItemsControl.ItemTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
|
|
||||||
</DataTemplate>
|
|
||||||
</ItemsControl.ItemTemplate>
|
|
||||||
</ItemsControl>
|
|
||||||
<ScrollViewer Grid.Column="1">
|
|
||||||
<StackPanel>
|
|
||||||
|
|
||||||
</StackPanel>
|
|
||||||
</ScrollViewer>
|
|
||||||
</Grid>
|
|
||||||
</UserControl>
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Controls;
|
|
||||||
using System.Windows.Data;
|
|
||||||
using System.Windows.Documents;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using System.Windows.Media;
|
|
||||||
using System.Windows.Media.Imaging;
|
|
||||||
using System.Windows.Navigation;
|
|
||||||
using System.Windows.Shapes;
|
|
||||||
using TimetableDesigner.Services;
|
|
||||||
using TimetableDesigner.Services.Project;
|
|
||||||
using TimetableDesigner.ViewModels.Models;
|
|
||||||
|
|
||||||
namespace TimetableDesigner.Controls
|
|
||||||
{
|
|
||||||
public partial class TimetableEditorControl : UserControl
|
|
||||||
{
|
|
||||||
#region FIELDS
|
|
||||||
|
|
||||||
private IProjectService _projectService;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region PROPERTIES
|
|
||||||
|
|
||||||
public IGroupViewModel Group
|
|
||||||
{
|
|
||||||
get => (IGroupViewModel)GetValue(GroupProperty);
|
|
||||||
set => SetValue(GroupProperty, value);
|
|
||||||
}
|
|
||||||
public static readonly DependencyProperty GroupProperty = DependencyProperty.Register("Group", typeof(IGroupViewModel), typeof(TimetableEditorControl));
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region CONSTRUCTORS
|
|
||||||
|
|
||||||
public TimetableEditorControl()
|
|
||||||
{
|
|
||||||
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
|
|
||||||
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Data;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Converters
|
||||||
|
{
|
||||||
|
class BooleanToGridColumnRowVisibilityConverter : IValueConverter
|
||||||
|
{
|
||||||
|
private static GridLength _notVisible = new GridLength(0, GridUnitType.Pixel);
|
||||||
|
private static GridLength _visible = new GridLength(1, GridUnitType.Star);
|
||||||
|
|
||||||
|
// (bool)parameter - reverse output
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is null || value.GetType() != typeof(bool))
|
||||||
|
{
|
||||||
|
return new GridLength(1, GridUnitType.Star);
|
||||||
|
}
|
||||||
|
bool isVisible = (bool)value;
|
||||||
|
|
||||||
|
bool reverse = false;
|
||||||
|
if (parameter is not null && parameter.GetType() == typeof(bool))
|
||||||
|
{
|
||||||
|
reverse = (bool)parameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isVisible ^ reverse ? _visible : _notVisible;
|
||||||
|
}
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is null || value.GetType() != typeof(GridLength))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
GridLength visibility = (GridLength)value;
|
||||||
|
|
||||||
|
bool reverse = false;
|
||||||
|
if (parameter is not null && parameter.GetType() == typeof(bool))
|
||||||
|
{
|
||||||
|
reverse = (bool)parameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return visibility != _notVisible ^ reverse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
49
TimetableDesigner/Converters/BooleanToVisibilityConverter.cs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Data;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Converters
|
||||||
|
{
|
||||||
|
public class BooleanToVisibilityConverter : IValueConverter
|
||||||
|
{
|
||||||
|
// (bool)parameter - reverse output
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is null || value.GetType() != typeof(bool))
|
||||||
|
{
|
||||||
|
return Visibility.Visible;
|
||||||
|
}
|
||||||
|
bool isVisible = (bool)value;
|
||||||
|
|
||||||
|
bool reverse = false;
|
||||||
|
if (parameter is not null && parameter.GetType() == typeof(bool))
|
||||||
|
{
|
||||||
|
reverse = (bool)parameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isVisible ^ reverse ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is null || value.GetType() != typeof(Visibility))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Visibility visibility = (Visibility)value;
|
||||||
|
|
||||||
|
bool reverse = false;
|
||||||
|
if (parameter is not null && parameter.GetType() == typeof(bool))
|
||||||
|
{
|
||||||
|
reverse = (bool)parameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return visibility == Visibility.Visible ^ reverse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
TimetableDesigner/Converters/ByteArrayToColorConverter.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Converters
|
||||||
|
{
|
||||||
|
public class ByteArrayToColorConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
byte[] bytes = (byte[])value;
|
||||||
|
Color color;
|
||||||
|
switch (bytes.Length)
|
||||||
|
{
|
||||||
|
case < 3: color = Colors.Red; break;
|
||||||
|
case 3: color = Color.FromRgb(bytes[0], bytes[1], bytes[2]); break;
|
||||||
|
case > 4: color = Color.FromArgb(bytes[0], bytes[1], bytes[2], bytes[3]); break;
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
Color color = (Color)value;
|
||||||
|
List<byte> bytes = new List<byte>();
|
||||||
|
|
||||||
|
if (color.A != 0xFF) bytes.Add(color.A);
|
||||||
|
bytes.Add(color.R);
|
||||||
|
bytes.Add(color.G);
|
||||||
|
bytes.Add(color.B);
|
||||||
|
|
||||||
|
return bytes.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using ControlzEx.Standard;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Data;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Converters
|
||||||
|
{
|
||||||
|
public class ColorBrightnessIsHigherToBooleanConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is byte[] color && (parameter is int min || (parameter is string minStr && int.TryParse(minStr, out min))))
|
||||||
|
{
|
||||||
|
int start = 0;
|
||||||
|
if (color.Length == 4)
|
||||||
|
{
|
||||||
|
start = 1;
|
||||||
|
}
|
||||||
|
int result = (int)Math.Sqrt(color[start] * color[start] * .241 +
|
||||||
|
color[start + 1] * color[start + 1] * .691 +
|
||||||
|
color[start + 2] * color[start + 2] * .068);
|
||||||
|
return min < result;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
TimetableDesigner/Converters/IUnitVMToUnitNameConverter.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using TimetableDesigner.Core;
|
||||||
|
using TimetableDesigner.Properties;
|
||||||
|
using TimetableDesigner.ViewModels.Models;
|
||||||
|
using TimetableDesigner.ViewModels.Models.Base;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Converters
|
||||||
|
{
|
||||||
|
internal class IUnitVMToUnitNameConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is IUnitVM unit)
|
||||||
|
{
|
||||||
|
switch (unit)
|
||||||
|
{
|
||||||
|
case ClassroomVM classroom: return Resources.Global_Classroom;
|
||||||
|
case TeacherVM teacher: return Resources.Global_Teacher;
|
||||||
|
case GroupVM group: return Resources.Global_Group;
|
||||||
|
case SubgroupVM subgroup: return Resources.Global_Subgroup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@ namespace TimetableDesigner.Converters
|
|||||||
{
|
{
|
||||||
#region PUBLIC METHODS
|
#region PUBLIC METHODS
|
||||||
|
|
||||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => (int)value + (int)parameter;
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => (int)value + int.Parse((string)parameter);
|
||||||
|
|
||||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => (int)value - (int)parameter;
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => (int)value - (int)parameter;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
using System;
|
||||||
|
using System.CodeDom;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using TimetableDesigner.Core;
|
||||||
|
using TimetableDesigner.Services;
|
||||||
|
using TimetableDesigner.Services.Project;
|
||||||
|
using TimetableDesigner.ViewModels.Models;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Converters
|
||||||
|
{
|
||||||
|
internal class TimetableDayToColumnNumberConverter : IValueConverter
|
||||||
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private readonly IProjectService _projectService;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public TimetableDayToColumnNumberConverter()
|
||||||
|
{
|
||||||
|
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PUBLIC METHODS
|
||||||
|
|
||||||
|
//value - TimetableDay
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is TimetableDay day)
|
||||||
|
{
|
||||||
|
return _projectService.ProjectViewModel.TimetableTemplate.Days.IndexOf(day);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is int index && index >= 0)
|
||||||
|
{
|
||||||
|
return _projectService.ProjectViewModel.TimetableTemplate.Days[index];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using TimetableDesigner.Core;
|
||||||
|
using TimetableDesigner.Services.Project;
|
||||||
|
using TimetableDesigner.Services;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Converters
|
||||||
|
{
|
||||||
|
internal class TimetableSlotToRowNumberConverter : IValueConverter
|
||||||
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private readonly IProjectService _projectService;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public TimetableSlotToRowNumberConverter()
|
||||||
|
{
|
||||||
|
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PUBLIC METHODS
|
||||||
|
|
||||||
|
//value - TimetableSlot
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is TimetableSpan slot)
|
||||||
|
{
|
||||||
|
return _projectService.ProjectViewModel.TimetableTemplate.Slots.IndexOf(slot);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is int index && index >= 0)
|
||||||
|
{
|
||||||
|
return _projectService.ProjectViewModel.TimetableTemplate.Slots[index];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,12 +19,13 @@ namespace TimetableDesigner.Converters
|
|||||||
|
|
||||||
private static readonly Dictionary<Type, Type> _viewModelViewPairs = new Dictionary<Type, Type>
|
private static readonly Dictionary<Type, Type> _viewModelViewPairs = new Dictionary<Type, Type>
|
||||||
{
|
{
|
||||||
{ typeof(MainViewModel), typeof(MainWindow) },
|
{ typeof(MainWindowVM), typeof(MainWindow) },
|
||||||
{ typeof(WelcomeViewModel), typeof(WelcomeView) },
|
{ typeof(WelcomeViewVM), typeof(WelcomeView) },
|
||||||
{ typeof(ProjectSettingsViewModel), typeof(ProjectSettingsView) },
|
{ typeof(ProjectSettingsViewVM), typeof(ProjectSettingsView) },
|
||||||
{ typeof(ClassroomEditViewModel), typeof(ClassroomEditView) },
|
{ typeof(ClassroomEditorViewVM), typeof(ClassroomEditorView) },
|
||||||
{ typeof(TeacherEditViewModel), typeof(TeacherEditView) },
|
{ typeof(TeacherEditorViewVM), typeof(TeacherEditorView) },
|
||||||
{ typeof(GroupEditViewModel), typeof(GroupEditView) },
|
{ typeof(GroupEditorViewVM), typeof(GroupEditorView) },
|
||||||
|
{ typeof(TimetableEditorViewVM), typeof(TimetableEditorView) },
|
||||||
};
|
};
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -35,7 +36,7 @@ namespace TimetableDesigner.Converters
|
|||||||
|
|
||||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
{
|
{
|
||||||
BaseViewViewModel? viewModel = value as BaseViewViewModel;
|
IViewVM? viewModel = value as IViewVM;
|
||||||
if (viewModel is not null)
|
if (viewModel is not null)
|
||||||
{
|
{
|
||||||
Type view = _viewModelViewPairs[viewModel.GetType()];
|
Type view = _viewModelViewPairs[viewModel.GetType()];
|
||||||
|
|||||||
14
TimetableDesigner/Globals/Path.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Globals
|
||||||
|
{
|
||||||
|
public static class Path
|
||||||
|
{
|
||||||
|
public static readonly string ApplicationData = $"{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}\\TimetableDesigner";
|
||||||
|
public static readonly string RecentProjectsFile = $"{ApplicationData}\\recent";
|
||||||
|
}
|
||||||
|
}
|
||||||
381
TimetableDesigner/Properties/Resources.Designer.cs
generated
@@ -114,6 +114,114 @@ namespace TimetableDesigner.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to During this class, other classes are taking place in this classroom.
|
||||||
|
/// </summary>
|
||||||
|
public static string Errors_ClassroomBusy {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Errors.ClassroomBusy", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Class has no assigned classroom.
|
||||||
|
/// </summary>
|
||||||
|
public static string Errors_ClassroomNotAssigned {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Errors.ClassroomNotAssigned", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to During this class, group, to which selected subgroup is assigned, already has other classes.
|
||||||
|
/// </summary>
|
||||||
|
public static string Errors_GroupAllBusy {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Errors.GroupAllBusy", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to During this class, the selected group already has other classes.
|
||||||
|
/// </summary>
|
||||||
|
public static string Errors_GroupBusy {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Errors.GroupBusy", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Class has no assigned group.
|
||||||
|
/// </summary>
|
||||||
|
public static string Errors_GroupNotAssigned {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Errors.GroupNotAssigned", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to During this class, part of selected group already has other classes in subgroup.
|
||||||
|
/// </summary>
|
||||||
|
public static string Errors_GroupPartBusy {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Errors.GroupPartBusy", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Class is not scheduled.
|
||||||
|
/// </summary>
|
||||||
|
public static string Errors_SlotNotAssigned {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Errors.SlotNotAssigned", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to During this class, the selected teacher conducts other classes.
|
||||||
|
/// </summary>
|
||||||
|
public static string Errors_TeacherBusy {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Errors.TeacherBusy", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Class has no assigned teacher.
|
||||||
|
/// </summary>
|
||||||
|
public static string Errors_TeacherNotAssigned {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Errors.TeacherNotAssigned", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Selected teacher is not available during the class.
|
||||||
|
/// </summary>
|
||||||
|
public static string Errors_TeacherNotAvailable {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Errors.TeacherNotAvailable", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to All files.
|
||||||
|
/// </summary>
|
||||||
|
public static string Global_AllFiles {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Global.AllFiles", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Classroom.
|
||||||
|
/// </summary>
|
||||||
|
public static string Global_Classroom {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Global.Classroom", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to New classroom.
|
/// Looks up a localized string similar to New classroom.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -150,6 +258,15 @@ namespace TimetableDesigner.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Group.
|
||||||
|
/// </summary>
|
||||||
|
public static string Global_Group {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Global.Group", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to no project loaded.
|
/// Looks up a localized string similar to no project loaded.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -159,6 +276,33 @@ namespace TimetableDesigner.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to TimetableEditor project file.
|
||||||
|
/// </summary>
|
||||||
|
public static string Global_ProjectFiletypeDescription {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Global.ProjectFiletypeDescription", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Subgroup.
|
||||||
|
/// </summary>
|
||||||
|
public static string Global_Subgroup {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Global.Subgroup", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Teacher.
|
||||||
|
/// </summary>
|
||||||
|
public static string Global_Teacher {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Global.Teacher", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Delete.
|
/// Looks up a localized string similar to Delete.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -231,6 +375,51 @@ namespace TimetableDesigner.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Class name.
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Errors_ClassName {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Errors.ClassName", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Day.
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Errors_Day {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Errors.Day", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Description.
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Errors_Description {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Errors.Description", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Slot.
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Errors_Slot {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Errors.Slot", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Source.
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Errors_Source {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Errors.Source", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Project is loaded. Do you want to save?.
|
/// Looks up a localized string similar to Project is loaded. Do you want to save?.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -240,6 +429,97 @@ namespace TimetableDesigner.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Edit.
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Ribbon_Edit {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Ribbon.Edit", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Timetable.
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Ribbon_Edit_Timetable {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Ribbon.Edit.Timetable", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Autoschedule all unscheduled classes.
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Ribbon_Edit_Timetable_Autoschedule {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Ribbon.Edit.Timetable.Autoschedule", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Following classes could not be scheduled.
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Ribbon_Edit_Timetable_Autoschedule_Message_FollowingClassesCouldNotBeScheduled {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Ribbon.Edit.Timetable.Autoschedule.Message.FollowingClassesCouldNotBeSchedul" +
|
||||||
|
"ed", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to more.
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Ribbon_Edit_Timetable_Autoschedule_Message_More {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Ribbon.Edit.Timetable.Autoschedule.Message.More", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to There is no unscheduled classes.
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Ribbon_Edit_Timetable_Autoschedule_Message_NoUnscheduledClasses {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Ribbon.Edit.Timetable.Autoschedule.Message.NoUnscheduledClasses", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Successfully scheduled classes.
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Ribbon_Edit_Timetable_Autoschedule_Message_SuccessfullyScheduled {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Ribbon.Edit.Timetable.Autoschedule.Message.SuccessfullyScheduled", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Classroom.
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Ribbon_Edit_Timetable_Autoschedule_Message_UnitClassroom {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Ribbon.Edit.Timetable.Autoschedule.Message.UnitClassroom", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Group.
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Ribbon_Edit_Timetable_Autoschedule_Message_UnitGroup {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Ribbon.Edit.Timetable.Autoschedule.Message.UnitGroup", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Teacher.
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Ribbon_Edit_Timetable_Autoschedule_Message_UnitTeacher {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Ribbon.Edit.Timetable.Autoschedule.Message.UnitTeacher", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Export.
|
/// Looks up a localized string similar to Export.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -286,38 +566,47 @@ namespace TimetableDesigner.Properties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to New/Open.
|
/// Looks up a localized string similar to New.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Main_Ribbon_File_NewOpen {
|
public static string Main_Ribbon_File_New {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("Main.Ribbon.File.NewOpen", resourceCulture);
|
return ResourceManager.GetString("Main.Ribbon.File.New", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to New.
|
/// Looks up a localized string similar to New.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Main_Ribbon_File_NewOpen_New {
|
public static string Main_Ribbon_File_New_New {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("Main.Ribbon.File.NewOpen.New", resourceCulture);
|
return ResourceManager.GetString("Main.Ribbon.File.New.New", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Open.
|
/// Looks up a localized string similar to Open.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Main_Ribbon_File_NewOpen_Open {
|
public static string Main_Ribbon_File_Open {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("Main.Ribbon.File.NewOpen.Open", resourceCulture);
|
return ResourceManager.GetString("Main.Ribbon.File.Open", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Open.
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Ribbon_File_Open_Open {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Ribbon.File.Open.Open", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Open recent.
|
/// Looks up a localized string similar to Open recent.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Main_Ribbon_File_NewOpen_OpenRecent {
|
public static string Main_Ribbon_File_Open_OpenRecent {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("Main.Ribbon.File.NewOpen.OpenRecent", resourceCulture);
|
return ResourceManager.GetString("Main.Ribbon.File.Open.OpenRecent", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -483,6 +772,15 @@ namespace TimetableDesigner.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Are you sure you want to delete this classroom. This operation is irreversible. Classroom will be unassigned for all classes..
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Treeview_Classrooms_Message_Remove {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Treeview.Classrooms.Message.Remove", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Edit timetable.
|
/// Looks up a localized string similar to Edit timetable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -520,7 +818,16 @@ namespace TimetableDesigner.Properties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Are you sure you want to delete this subgroup. This operation is irreversible. Subgroup will be unassigned for all groups..
|
/// Looks up a localized string similar to Are you sure you want to delete this group. This operation is irreversible. Group will be unassigned for all classes..
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Treeview_Groups_Message_Remove {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Treeview.Groups.Message.Remove", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Are you sure you want to delete this subgroup. This operation is irreversible. Subgroup will be unassigned for all groups and classes..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Main_Treeview_Subgroups_Message_Remove {
|
public static string Main_Treeview_Subgroups_Message_Remove {
|
||||||
get {
|
get {
|
||||||
@@ -546,6 +853,15 @@ namespace TimetableDesigner.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Are you sure you want to delete this teacher. This operation is irreversible. Teacher will be unassigned for all classes..
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Treeview_Teachers_Message_Remove {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Treeview.Teachers.Message.Remove", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Error.
|
/// Looks up a localized string similar to Error.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -555,6 +871,15 @@ namespace TimetableDesigner.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Information.
|
||||||
|
/// </summary>
|
||||||
|
public static string MessageBox_Information {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("MessageBox.Information", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Question.
|
/// Looks up a localized string similar to Question.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -564,6 +889,15 @@ namespace TimetableDesigner.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Warning.
|
||||||
|
/// </summary>
|
||||||
|
public static string MessageBox_Warning {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("MessageBox.Warning", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Author.
|
/// Looks up a localized string similar to Author.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -681,6 +1015,15 @@ namespace TimetableDesigner.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Timetable editing.
|
||||||
|
/// </summary>
|
||||||
|
public static string Tabs_TimetableEdit {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Tabs.TimetableEdit", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Welcome.
|
/// Looks up a localized string similar to Welcome.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -761,5 +1104,23 @@ namespace TimetableDesigner.Properties {
|
|||||||
return ResourceManager.GetString("TeacherEdit.Name", resourceCulture);
|
return ResourceManager.GetString("TeacherEdit.Name", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Autoschedule.
|
||||||
|
/// </summary>
|
||||||
|
public static string TimetableEditor_Autoschedule {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TimetableEditor.Autoschedule", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Unscheduled.
|
||||||
|
/// </summary>
|
||||||
|
public static string TimetableEditor_Unscheduled {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TimetableEditor.Unscheduled", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,6 +135,42 @@
|
|||||||
<data name="ClassroomEdit.Name" xml:space="preserve">
|
<data name="ClassroomEdit.Name" xml:space="preserve">
|
||||||
<value>Name</value>
|
<value>Name</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Errors.ClassroomBusy" xml:space="preserve">
|
||||||
|
<value>During this class, other classes are taking place in this classroom</value>
|
||||||
|
</data>
|
||||||
|
<data name="Errors.ClassroomNotAssigned" xml:space="preserve">
|
||||||
|
<value>Class has no assigned classroom</value>
|
||||||
|
</data>
|
||||||
|
<data name="Errors.GroupAllBusy" xml:space="preserve">
|
||||||
|
<value>During this class, group, to which selected subgroup is assigned, already has other classes</value>
|
||||||
|
</data>
|
||||||
|
<data name="Errors.GroupBusy" xml:space="preserve">
|
||||||
|
<value>During this class, the selected group already has other classes</value>
|
||||||
|
</data>
|
||||||
|
<data name="Errors.GroupNotAssigned" xml:space="preserve">
|
||||||
|
<value>Class has no assigned group</value>
|
||||||
|
</data>
|
||||||
|
<data name="Errors.GroupPartBusy" xml:space="preserve">
|
||||||
|
<value>During this class, part of selected group already has other classes in subgroup</value>
|
||||||
|
</data>
|
||||||
|
<data name="Errors.SlotNotAssigned" xml:space="preserve">
|
||||||
|
<value>Class is not scheduled</value>
|
||||||
|
</data>
|
||||||
|
<data name="Errors.TeacherBusy" xml:space="preserve">
|
||||||
|
<value>During this class, the selected teacher conducts other classes</value>
|
||||||
|
</data>
|
||||||
|
<data name="Errors.TeacherNotAssigned" xml:space="preserve">
|
||||||
|
<value>Class has no assigned teacher</value>
|
||||||
|
</data>
|
||||||
|
<data name="Errors.TeacherNotAvailable" xml:space="preserve">
|
||||||
|
<value>Selected teacher is not available during the class</value>
|
||||||
|
</data>
|
||||||
|
<data name="Global.AllFiles" xml:space="preserve">
|
||||||
|
<value>All files</value>
|
||||||
|
</data>
|
||||||
|
<data name="Global.Classroom" xml:space="preserve">
|
||||||
|
<value>Classroom</value>
|
||||||
|
</data>
|
||||||
<data name="Global.DefaultClassroomName" xml:space="preserve">
|
<data name="Global.DefaultClassroomName" xml:space="preserve">
|
||||||
<value>New classroom</value>
|
<value>New classroom</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -147,9 +183,21 @@
|
|||||||
<data name="Global.DefaultTeacherName" xml:space="preserve">
|
<data name="Global.DefaultTeacherName" xml:space="preserve">
|
||||||
<value>New teacher</value>
|
<value>New teacher</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Global.Group" xml:space="preserve">
|
||||||
|
<value>Group</value>
|
||||||
|
</data>
|
||||||
<data name="Global.NoProjectLoadedTitle" xml:space="preserve">
|
<data name="Global.NoProjectLoadedTitle" xml:space="preserve">
|
||||||
<value>no project loaded</value>
|
<value>no project loaded</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Global.ProjectFiletypeDescription" xml:space="preserve">
|
||||||
|
<value>TimetableEditor project file</value>
|
||||||
|
</data>
|
||||||
|
<data name="Global.Subgroup" xml:space="preserve">
|
||||||
|
<value>Subgroup</value>
|
||||||
|
</data>
|
||||||
|
<data name="Global.Teacher" xml:space="preserve">
|
||||||
|
<value>Teacher</value>
|
||||||
|
</data>
|
||||||
<data name="GroupEdit.DeleteSubgroup" xml:space="preserve">
|
<data name="GroupEdit.DeleteSubgroup" xml:space="preserve">
|
||||||
<value>Delete</value>
|
<value>Delete</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -174,9 +222,54 @@
|
|||||||
<data name="GroupEdit.Subgroups" xml:space="preserve">
|
<data name="GroupEdit.Subgroups" xml:space="preserve">
|
||||||
<value>Subgroups</value>
|
<value>Subgroups</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Main.Errors.ClassName" xml:space="preserve">
|
||||||
|
<value>Class name</value>
|
||||||
|
</data>
|
||||||
|
<data name="Main.Errors.Day" xml:space="preserve">
|
||||||
|
<value>Day</value>
|
||||||
|
</data>
|
||||||
|
<data name="Main.Errors.Description" xml:space="preserve">
|
||||||
|
<value>Description</value>
|
||||||
|
</data>
|
||||||
|
<data name="Main.Errors.Slot" xml:space="preserve">
|
||||||
|
<value>Slot</value>
|
||||||
|
</data>
|
||||||
|
<data name="Main.Errors.Source" xml:space="preserve">
|
||||||
|
<value>Source</value>
|
||||||
|
</data>
|
||||||
<data name="Main.Message.SaveCurrentProject" xml:space="preserve">
|
<data name="Main.Message.SaveCurrentProject" xml:space="preserve">
|
||||||
<value>Project is loaded. Do you want to save?</value>
|
<value>Project is loaded. Do you want to save?</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Main.Ribbon.Edit" xml:space="preserve">
|
||||||
|
<value>Edit</value>
|
||||||
|
</data>
|
||||||
|
<data name="Main.Ribbon.Edit.Timetable" xml:space="preserve">
|
||||||
|
<value>Timetable</value>
|
||||||
|
</data>
|
||||||
|
<data name="Main.Ribbon.Edit.Timetable.Autoschedule" xml:space="preserve">
|
||||||
|
<value>Autoschedule all unscheduled classes</value>
|
||||||
|
</data>
|
||||||
|
<data name="Main.Ribbon.Edit.Timetable.Autoschedule.Message.FollowingClassesCouldNotBeScheduled" xml:space="preserve">
|
||||||
|
<value>Following classes could not be scheduled</value>
|
||||||
|
</data>
|
||||||
|
<data name="Main.Ribbon.Edit.Timetable.Autoschedule.Message.More" xml:space="preserve">
|
||||||
|
<value>more</value>
|
||||||
|
</data>
|
||||||
|
<data name="Main.Ribbon.Edit.Timetable.Autoschedule.Message.NoUnscheduledClasses" xml:space="preserve">
|
||||||
|
<value>There is no unscheduled classes</value>
|
||||||
|
</data>
|
||||||
|
<data name="Main.Ribbon.Edit.Timetable.Autoschedule.Message.SuccessfullyScheduled" xml:space="preserve">
|
||||||
|
<value>Successfully scheduled classes</value>
|
||||||
|
</data>
|
||||||
|
<data name="Main.Ribbon.Edit.Timetable.Autoschedule.Message.UnitClassroom" xml:space="preserve">
|
||||||
|
<value>Classroom</value>
|
||||||
|
</data>
|
||||||
|
<data name="Main.Ribbon.Edit.Timetable.Autoschedule.Message.UnitGroup" xml:space="preserve">
|
||||||
|
<value>Group</value>
|
||||||
|
</data>
|
||||||
|
<data name="Main.Ribbon.Edit.Timetable.Autoschedule.Message.UnitTeacher" xml:space="preserve">
|
||||||
|
<value>Teacher</value>
|
||||||
|
</data>
|
||||||
<data name="Main.Ribbon.Export" xml:space="preserve">
|
<data name="Main.Ribbon.Export" xml:space="preserve">
|
||||||
<value>Export</value>
|
<value>Export</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -192,16 +285,19 @@
|
|||||||
<data name="Main.Ribbon.File" xml:space="preserve">
|
<data name="Main.Ribbon.File" xml:space="preserve">
|
||||||
<value>File</value>
|
<value>File</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Main.Ribbon.File.NewOpen" xml:space="preserve">
|
<data name="Main.Ribbon.File.New" xml:space="preserve">
|
||||||
<value>New/Open</value>
|
|
||||||
</data>
|
|
||||||
<data name="Main.Ribbon.File.NewOpen.New" xml:space="preserve">
|
|
||||||
<value>New</value>
|
<value>New</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Main.Ribbon.File.NewOpen.Open" xml:space="preserve">
|
<data name="Main.Ribbon.File.New.New" xml:space="preserve">
|
||||||
|
<value>New</value>
|
||||||
|
</data>
|
||||||
|
<data name="Main.Ribbon.File.Open" xml:space="preserve">
|
||||||
<value>Open</value>
|
<value>Open</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Main.Ribbon.File.NewOpen.OpenRecent" xml:space="preserve">
|
<data name="Main.Ribbon.File.Open.Open" xml:space="preserve">
|
||||||
|
<value>Open</value>
|
||||||
|
</data>
|
||||||
|
<data name="Main.Ribbon.File.Open.OpenRecent" xml:space="preserve">
|
||||||
<value>Open recent</value>
|
<value>Open recent</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Main.Ribbon.File.Save" xml:space="preserve">
|
<data name="Main.Ribbon.File.Save" xml:space="preserve">
|
||||||
@@ -258,6 +354,9 @@
|
|||||||
<data name="Main.Treeview.Classrooms.ContextMenu.Edit" xml:space="preserve">
|
<data name="Main.Treeview.Classrooms.ContextMenu.Edit" xml:space="preserve">
|
||||||
<value>Edit classroom</value>
|
<value>Edit classroom</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Main.Treeview.Classrooms.Message.Remove" xml:space="preserve">
|
||||||
|
<value>Are you sure you want to delete this classroom. This operation is irreversible. Classroom will be unassigned for all classes.</value>
|
||||||
|
</data>
|
||||||
<data name="Main.Treeview.ContextMenu.EditTimetable" xml:space="preserve">
|
<data name="Main.Treeview.ContextMenu.EditTimetable" xml:space="preserve">
|
||||||
<value>Edit timetable</value>
|
<value>Edit timetable</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -270,8 +369,11 @@
|
|||||||
<data name="Main.Treeview.Groups.ContextMenu.Edit" xml:space="preserve">
|
<data name="Main.Treeview.Groups.ContextMenu.Edit" xml:space="preserve">
|
||||||
<value>Edit group</value>
|
<value>Edit group</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Main.Treeview.Groups.Message.Remove" xml:space="preserve">
|
||||||
|
<value>Are you sure you want to delete this group. This operation is irreversible. Group will be unassigned for all classes.</value>
|
||||||
|
</data>
|
||||||
<data name="Main.Treeview.Subgroups.Message.Remove" xml:space="preserve">
|
<data name="Main.Treeview.Subgroups.Message.Remove" xml:space="preserve">
|
||||||
<value>Are you sure you want to delete this subgroup. This operation is irreversible. Subgroup will be unassigned for all groups.</value>
|
<value>Are you sure you want to delete this subgroup. This operation is irreversible. Subgroup will be unassigned for all groups and classes.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Main.Treeview.Teachers" xml:space="preserve">
|
<data name="Main.Treeview.Teachers" xml:space="preserve">
|
||||||
<value>Teachers</value>
|
<value>Teachers</value>
|
||||||
@@ -279,12 +381,21 @@
|
|||||||
<data name="Main.Treeview.Teachers.ContextMenu.Edit" xml:space="preserve">
|
<data name="Main.Treeview.Teachers.ContextMenu.Edit" xml:space="preserve">
|
||||||
<value>Edit teacher</value>
|
<value>Edit teacher</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Main.Treeview.Teachers.Message.Remove" xml:space="preserve">
|
||||||
|
<value>Are you sure you want to delete this teacher. This operation is irreversible. Teacher will be unassigned for all classes.</value>
|
||||||
|
</data>
|
||||||
<data name="MessageBox.Error" xml:space="preserve">
|
<data name="MessageBox.Error" xml:space="preserve">
|
||||||
<value>Error</value>
|
<value>Error</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="MessageBox.Information" xml:space="preserve">
|
||||||
|
<value>Information</value>
|
||||||
|
</data>
|
||||||
<data name="MessageBox.Question" xml:space="preserve">
|
<data name="MessageBox.Question" xml:space="preserve">
|
||||||
<value>Question</value>
|
<value>Question</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="MessageBox.Warning" xml:space="preserve">
|
||||||
|
<value>Warning</value>
|
||||||
|
</data>
|
||||||
<data name="ProjectSettings.Author" xml:space="preserve">
|
<data name="ProjectSettings.Author" xml:space="preserve">
|
||||||
<value>Author</value>
|
<value>Author</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -324,6 +435,9 @@
|
|||||||
<data name="Tabs.TeacherEdit" xml:space="preserve">
|
<data name="Tabs.TeacherEdit" xml:space="preserve">
|
||||||
<value>Teacher editing</value>
|
<value>Teacher editing</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Tabs.TimetableEdit" xml:space="preserve">
|
||||||
|
<value>Timetable editing</value>
|
||||||
|
</data>
|
||||||
<data name="Tabs.Welcome" xml:space="preserve">
|
<data name="Tabs.Welcome" xml:space="preserve">
|
||||||
<value>Welcome</value>
|
<value>Welcome</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -351,4 +465,10 @@
|
|||||||
<data name="TeacherEdit.Name" xml:space="preserve">
|
<data name="TeacherEdit.Name" xml:space="preserve">
|
||||||
<value>Name</value>
|
<value>Name</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TimetableEditor.Autoschedule" xml:space="preserve">
|
||||||
|
<value>Autoschedule</value>
|
||||||
|
</data>
|
||||||
|
<data name="TimetableEditor.Unscheduled" xml:space="preserve">
|
||||||
|
<value>Unscheduled</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
38
TimetableDesigner/Properties/Settings.Designer.cs
generated
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:4.0.30319.42000
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Properties {
|
||||||
|
|
||||||
|
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0")]
|
||||||
|
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||||
|
|
||||||
|
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||||
|
|
||||||
|
public static Settings Default {
|
||||||
|
get {
|
||||||
|
return defaultInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("10")]
|
||||||
|
public uint RecentProjectsCount {
|
||||||
|
get {
|
||||||
|
return ((uint)(this["RecentProjectsCount"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["RecentProjectsCount"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
TimetableDesigner/Properties/Settings.settings
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="TimetableDesigner.Properties" GeneratedClassName="Settings">
|
||||||
|
<Profiles />
|
||||||
|
<Settings>
|
||||||
|
<Setting Name="RecentProjectsCount" Type="System.UInt32" Scope="User">
|
||||||
|
<Value Profile="(Default)">10</Value>
|
||||||
|
</Setting>
|
||||||
|
</Settings>
|
||||||
|
</SettingsFile>
|
||||||
@@ -5,4 +5,10 @@
|
|||||||
<c:IsNullToVisibilityConverter x:Key="IsNullToVisibilityConverter"/>
|
<c:IsNullToVisibilityConverter x:Key="IsNullToVisibilityConverter"/>
|
||||||
<c:IsNotNullToBooleanConverter x:Key="IsNotNullToBooleanConverter"/>
|
<c:IsNotNullToBooleanConverter x:Key="IsNotNullToBooleanConverter"/>
|
||||||
<c:IntegerAddConstantConverter x:Key="IntegerAddConstantConverter"/>
|
<c:IntegerAddConstantConverter x:Key="IntegerAddConstantConverter"/>
|
||||||
|
<c:TimetableDayToColumnNumberConverter x:Key="TimetableDayToColumnNumberConverter"/>
|
||||||
|
<c:TimetableSlotToRowNumberConverter x:Key="TimetableSlotToRowNumberConverter"/>
|
||||||
|
<c:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||||
|
<c:ByteArrayToColorConverter x:Key="ByteArrayToColorConverter"/>
|
||||||
|
<c:IUnitVMToUnitNameConverter x:Key="IUnitVMToUnitNameConverter"/>
|
||||||
|
<c:ColorBrightnessIsHigherToBooleanConverter x:Key="ColorBrightnessIsHigherToBooleanConverter"/>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:s="clr-namespace:System;assembly=mscorlib">
|
xmlns:s="clr-namespace:System;assembly=mscorlib">
|
||||||
<BitmapImage x:Key="CloseImage" UriSource="Images/Close.png"/>
|
<BitmapImage x:Key="CloseImage" UriSource="Images/Close.png"/>
|
||||||
|
<BitmapImage x:Key="AutoscheduleImage" UriSource="Images/Autoschedule.png"/>
|
||||||
<BitmapImage x:Key="AddImage" UriSource="Images/Add.png"/>
|
<BitmapImage x:Key="AddImage" UriSource="Images/Add.png"/>
|
||||||
<BitmapImage x:Key="RemoveImage" UriSource="Images/Remove.png"/>
|
|
||||||
<BitmapImage x:Key="ProjectImage" UriSource="Images/Project.png"/>
|
<BitmapImage x:Key="ProjectImage" UriSource="Images/Project.png"/>
|
||||||
<BitmapImage x:Key="ProjectSettingsImage" UriSource="Images/ProjectSettings.png"/>
|
<BitmapImage x:Key="ProjectSettingsImage" UriSource="Images/ProjectSettings.png"/>
|
||||||
<BitmapImage x:Key="ClassroomImage" UriSource="Images/Classroom.png"/>
|
<BitmapImage x:Key="ClassroomImage" UriSource="Images/Classroom.png"/>
|
||||||
@@ -18,4 +18,19 @@
|
|||||||
<BitmapImage x:Key="RightArrowImage" UriSource="Images/RightArrow.png"/>
|
<BitmapImage x:Key="RightArrowImage" UriSource="Images/RightArrow.png"/>
|
||||||
<BitmapImage x:Key="GroupImage" UriSource="Images/Group.png"/>
|
<BitmapImage x:Key="GroupImage" UriSource="Images/Group.png"/>
|
||||||
<BitmapImage x:Key="GroupAddImage" UriSource="Images/GroupAdd.png"/>
|
<BitmapImage x:Key="GroupAddImage" UriSource="Images/GroupAdd.png"/>
|
||||||
|
<BitmapImage x:Key="ErrorImage" UriSource="Images/Error.png"/>
|
||||||
|
<BitmapImage x:Key="WarningImage" UriSource="Images/Warning.png"/>
|
||||||
|
<BitmapImage x:Key="InfoImage" UriSource="Images/Info.png"/>
|
||||||
|
<BitmapImage x:Key="CloneBlackImage" UriSource="Images/CloneBlack.png"/>
|
||||||
|
<BitmapImage x:Key="CloneWhiteImage" UriSource="Images/CloneWhite.png"/>
|
||||||
|
<BitmapImage x:Key="ClassroomBlackImage" UriSource="Images/ClassroomBlack.png"/>
|
||||||
|
<BitmapImage x:Key="ClassroomWhiteImage" UriSource="Images/ClassroomWhite.png"/>
|
||||||
|
<BitmapImage x:Key="TeacherBlackImage" UriSource="Images/TeacherBlack.png"/>
|
||||||
|
<BitmapImage x:Key="TeacherWhiteImage" UriSource="Images/TeacherWhite.png"/>
|
||||||
|
<BitmapImage x:Key="GroupBlackImage" UriSource="Images/GroupBlack.png"/>
|
||||||
|
<BitmapImage x:Key="GroupWhiteImage" UriSource="Images/GroupWhite.png"/>
|
||||||
|
<BitmapImage x:Key="RemoveBlackImage" UriSource="Images/RemoveBlack.png"/>
|
||||||
|
<BitmapImage x:Key="RemoveWhiteImage" UriSource="Images/RemoveWhite.png"/>
|
||||||
|
<BitmapImage x:Key="EditBlackImage" UriSource="Images/EditBlack.png"/>
|
||||||
|
<BitmapImage x:Key="EditWhiteImage" UriSource="Images/EditWhite.png"/>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
BIN
TimetableDesigner/Resources/Images/Autoschedule.png
Normal file
|
After Width: | Height: | Size: 401 B |
BIN
TimetableDesigner/Resources/Images/ClassroomBlack.png
Normal file
|
After Width: | Height: | Size: 616 B |
BIN
TimetableDesigner/Resources/Images/ClassroomWhite.png
Normal file
|
After Width: | Height: | Size: 633 B |
BIN
TimetableDesigner/Resources/Images/CloneBlack.png
Normal file
|
After Width: | Height: | Size: 436 B |
BIN
TimetableDesigner/Resources/Images/CloneWhite.png
Normal file
|
After Width: | Height: | Size: 453 B |
BIN
TimetableDesigner/Resources/Images/EditBlack.png
Normal file
|
After Width: | Height: | Size: 486 B |
BIN
TimetableDesigner/Resources/Images/EditWhite.png
Normal file
|
After Width: | Height: | Size: 525 B |
BIN
TimetableDesigner/Resources/Images/Error.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
TimetableDesigner/Resources/Images/GroupBlack.png
Normal file
|
After Width: | Height: | Size: 910 B |
BIN
TimetableDesigner/Resources/Images/GroupWhite.png
Normal file
|
After Width: | Height: | Size: 923 B |
BIN
TimetableDesigner/Resources/Images/Info.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 401 B After Width: | Height: | Size: 401 B |
BIN
TimetableDesigner/Resources/Images/RemoveWhite.png
Normal file
|
After Width: | Height: | Size: 422 B |
|
Before Width: | Height: | Size: 3.9 KiB |
BIN
TimetableDesigner/Resources/Images/TeacherBlack.png
Normal file
|
After Width: | Height: | Size: 446 B |
BIN
TimetableDesigner/Resources/Images/TeacherWhite.png
Normal file
|
After Width: | Height: | Size: 453 B |
BIN
TimetableDesigner/Resources/Images/Warning.png
Normal file
|
After Width: | Height: | Size: 1022 B |
78
TimetableDesigner/Services/FileDialog/FileDialogService.cs
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
using Microsoft.Win32;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TimetableDesigner.Properties;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Services.FileDialog
|
||||||
|
{
|
||||||
|
public class FileDialogService : IFileDialogService
|
||||||
|
{
|
||||||
|
#region PUBLIC METHODS
|
||||||
|
|
||||||
|
public string? OpenFile() => OpenFile(new Dictionary<string, IEnumerable<string>>(), true);
|
||||||
|
public string? OpenFile(IDictionary<string, IEnumerable<string>> types, bool allowAllFiles = false)
|
||||||
|
{
|
||||||
|
OpenFileDialog fileDialog = new OpenFileDialog();
|
||||||
|
return BuildAndShowDialog(fileDialog, types, allowAllFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? SaveFile() => SaveFile(new Dictionary<string, IEnumerable<string>>(), true);
|
||||||
|
public string? SaveFile(IDictionary<string, IEnumerable<string>> types, bool allowAllFiles = false)
|
||||||
|
{
|
||||||
|
SaveFileDialog fileDialog = new SaveFileDialog();
|
||||||
|
return BuildAndShowDialog(fileDialog, types, allowAllFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PRIVATE METHODS
|
||||||
|
|
||||||
|
private static string? BuildAndShowDialog(Microsoft.Win32.FileDialog fileDialog, IDictionary<string, IEnumerable<string>> types, bool allowAllFiles)
|
||||||
|
{
|
||||||
|
fileDialog.Filter = BuildFilterString(types, allowAllFiles);
|
||||||
|
|
||||||
|
if (fileDialog.ShowDialog() == true)
|
||||||
|
{
|
||||||
|
return fileDialog.FileName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string BuildFilterString(IDictionary<string, IEnumerable<string>> types, bool allFiles)
|
||||||
|
{
|
||||||
|
List<string> typeStrings = new List<string>();
|
||||||
|
foreach (KeyValuePair<string, IEnumerable<string>> type in types)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.Append($"{type.Key}|");
|
||||||
|
|
||||||
|
List<string> extensionStrings = new List<string>();
|
||||||
|
foreach (string extension in type.Value)
|
||||||
|
{
|
||||||
|
extensionStrings.Add($"*.{extension}");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Append(string.Join(';', extensionStrings));
|
||||||
|
|
||||||
|
typeStrings.Add(sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allFiles)
|
||||||
|
{
|
||||||
|
typeStrings.Add($"{Resources.Global_AllFiles}|*.*");
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Join(" | ", typeStrings);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
17
TimetableDesigner/Services/FileDialog/IFileDialogService.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Services.FileDialog
|
||||||
|
{
|
||||||
|
public interface IFileDialogService : IService
|
||||||
|
{
|
||||||
|
string? OpenFile();
|
||||||
|
string? OpenFile(IDictionary<string, IEnumerable<string>> types, bool allowAllFiles = false);
|
||||||
|
|
||||||
|
string? SaveFile();
|
||||||
|
string? SaveFile(IDictionary<string, IEnumerable<string>> types, bool allowAllFiles = false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,12 @@ namespace TimetableDesigner.Services.MessageBox
|
|||||||
MessageBoxQuestionResult ShowQuestion(string message, bool hideCancelButton = false);
|
MessageBoxQuestionResult ShowQuestion(string message, bool hideCancelButton = false);
|
||||||
MessageBoxQuestionResult ShowQuestion(string message, string title, bool hideCancelButton = false);
|
MessageBoxQuestionResult ShowQuestion(string message, string title, bool hideCancelButton = false);
|
||||||
|
|
||||||
|
void ShowWarning(string message);
|
||||||
|
void ShowWarning(string message, string title);
|
||||||
|
|
||||||
|
void ShowInformation(string message);
|
||||||
|
void ShowInformation(string message, string title);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,12 @@ namespace TimetableDesigner.Services.MessageBox
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ShowWarning(string message) => ShowWarning(message, Resources.MessageBox_Warning);
|
||||||
|
public void ShowWarning(string message, string title) => System.Windows.Forms.MessageBox.Show(message, title, MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
|
||||||
|
public void ShowInformation(string message) => ShowInformation(message, Resources.MessageBox_Information);
|
||||||
|
public void ShowInformation(string message, string title) => System.Windows.Forms.MessageBox.Show(message, title, MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Data;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using TimetableDesigner.Customs;
|
||||||
using TimetableDesigner.ViewModels.Models;
|
using TimetableDesigner.ViewModels.Models;
|
||||||
|
|
||||||
namespace TimetableDesigner.Services.Project
|
namespace TimetableDesigner.Services.Project
|
||||||
@@ -12,7 +15,12 @@ namespace TimetableDesigner.Services.Project
|
|||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
Core.Project? Project { get; }
|
Core.Project? Project { get; }
|
||||||
ProjectViewModel? ProjectViewModel { get; }
|
ProjectVM? ProjectViewModel { get; }
|
||||||
|
|
||||||
|
ObservableCollection<ProjectError> Errors { get; }
|
||||||
|
|
||||||
|
string? SavePath { get; }
|
||||||
|
ObservableDictionary<Guid, RecentProjectEntry> RecentProjects { get; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -21,11 +29,14 @@ namespace TimetableDesigner.Services.Project
|
|||||||
#region METHODS
|
#region METHODS
|
||||||
|
|
||||||
void New();
|
void New();
|
||||||
|
|
||||||
void Load(string path);
|
void Load(string path);
|
||||||
|
|
||||||
void Save(string path);
|
void Save(string path);
|
||||||
|
|
||||||
|
void RefreshErrors();
|
||||||
|
|
||||||
|
void LoadRecentProjectsList();
|
||||||
|
void SaveRecentProjectsList();
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
92
TimetableDesigner/Services/Project/ProjectError.cs
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TimetableDesigner.Customs;
|
||||||
|
using TimetableDesigner.ViewModels.Models;
|
||||||
|
using TimetableDesigner.ViewModels.Models.Base;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Services.Project
|
||||||
|
{
|
||||||
|
public class ProjectError : ObservableObject
|
||||||
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private ProjectErrorType _type;
|
||||||
|
private IUnitVM _unit;
|
||||||
|
private ClassVM _class;
|
||||||
|
private string _description;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PROPERTIES
|
||||||
|
|
||||||
|
public ProjectErrorType Type
|
||||||
|
{
|
||||||
|
get => _type;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_type != value)
|
||||||
|
{
|
||||||
|
_type = value;
|
||||||
|
NotifyPropertyChanged(nameof(Type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public IUnitVM Unit
|
||||||
|
{
|
||||||
|
get => _unit;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_unit != value)
|
||||||
|
{
|
||||||
|
_unit = value;
|
||||||
|
NotifyPropertyChanged(nameof(Unit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public ClassVM Class
|
||||||
|
{
|
||||||
|
get => _class;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _class)
|
||||||
|
{
|
||||||
|
_class = value;
|
||||||
|
NotifyPropertyChanged(nameof(Class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string Description
|
||||||
|
{
|
||||||
|
get => _description;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _description)
|
||||||
|
{
|
||||||
|
_description = value;
|
||||||
|
NotifyPropertyChanged(nameof(Description));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public ProjectError(ProjectErrorType type, IUnitVM unit, ClassVM @class, string description)
|
||||||
|
{
|
||||||
|
Type = type;
|
||||||
|
Unit = unit;
|
||||||
|
Class = @class;
|
||||||
|
Description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
15
TimetableDesigner/Services/Project/ProjectErrorType.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Services.Project
|
||||||
|
{
|
||||||
|
public enum ProjectErrorType
|
||||||
|
{
|
||||||
|
Error,
|
||||||
|
Warning,
|
||||||
|
Information
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,20 @@
|
|||||||
using System;
|
using Microsoft.VisualBasic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Data;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Windows.Input;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using TimetableDesigner.Core;
|
using TimetableDesigner.Core;
|
||||||
using TimetableDesigner.Customs;
|
using TimetableDesigner.Customs;
|
||||||
using TimetableDesigner.Properties;
|
using TimetableDesigner.Properties;
|
||||||
using TimetableDesigner.ViewModels.Models;
|
using TimetableDesigner.ViewModels.Models;
|
||||||
|
using TimetableDesigner.ViewModels.Models.Base;
|
||||||
|
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||||
|
|
||||||
namespace TimetableDesigner.Services.Project
|
namespace TimetableDesigner.Services.Project
|
||||||
{
|
{
|
||||||
@@ -15,7 +23,19 @@ namespace TimetableDesigner.Services.Project
|
|||||||
#region FIELDS
|
#region FIELDS
|
||||||
|
|
||||||
private Core.Project? _project;
|
private Core.Project? _project;
|
||||||
private ProjectViewModel? _projectViewModel;
|
private ProjectVM? _projectViewModel;
|
||||||
|
|
||||||
|
private string? _savePath;
|
||||||
|
private ObservableDictionary<Guid, RecentProjectEntry> _recentProjects;
|
||||||
|
|
||||||
|
private ObservableCollection<ProjectError> _errors;
|
||||||
|
|
||||||
|
private static readonly JsonSerializerSettings _serializationSettings = new JsonSerializerSettings()
|
||||||
|
{
|
||||||
|
Formatting = Formatting.Indented,
|
||||||
|
PreserveReferencesHandling = PreserveReferencesHandling.All,
|
||||||
|
NullValueHandling = NullValueHandling.Include,
|
||||||
|
};
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -35,7 +55,7 @@ namespace TimetableDesigner.Services.Project
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public ProjectViewModel? ProjectViewModel
|
public ProjectVM? ProjectViewModel
|
||||||
{
|
{
|
||||||
get => _projectViewModel;
|
get => _projectViewModel;
|
||||||
private set
|
private set
|
||||||
@@ -48,6 +68,44 @@ namespace TimetableDesigner.Services.Project
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string? SavePath
|
||||||
|
{
|
||||||
|
get => _savePath;
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
if (_savePath != value)
|
||||||
|
{
|
||||||
|
_savePath = value;
|
||||||
|
NotifyPropertyChanged(nameof(SavePath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public ObservableDictionary<Guid, RecentProjectEntry> RecentProjects
|
||||||
|
{
|
||||||
|
get => _recentProjects;
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
if (_recentProjects != value)
|
||||||
|
{
|
||||||
|
_recentProjects = value;
|
||||||
|
NotifyPropertyChanged(nameof(RecentProjects));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObservableCollection<ProjectError> Errors
|
||||||
|
{
|
||||||
|
get => _errors;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_errors != value)
|
||||||
|
{
|
||||||
|
_errors = value;
|
||||||
|
NotifyPropertyChanged(nameof(Errors));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
@@ -56,8 +114,13 @@ namespace TimetableDesigner.Services.Project
|
|||||||
|
|
||||||
public ProjectService()
|
public ProjectService()
|
||||||
{
|
{
|
||||||
_project = null;
|
Project = null;
|
||||||
_projectViewModel = null;
|
ProjectViewModel = null;
|
||||||
|
|
||||||
|
SavePath = null;
|
||||||
|
RecentProjects = new ObservableDictionary<Guid, RecentProjectEntry>();
|
||||||
|
|
||||||
|
Errors = new ObservableCollection<ProjectError>();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -72,17 +135,234 @@ namespace TimetableDesigner.Services.Project
|
|||||||
{
|
{
|
||||||
Name = Resources.Global_DefaultProjectName,
|
Name = Resources.Global_DefaultProjectName,
|
||||||
};
|
};
|
||||||
ProjectViewModel = new ProjectViewModel(Project);
|
ProjectViewModel = new ProjectVM(Project);
|
||||||
|
SavePath = null;
|
||||||
|
RefreshErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Load(string path)
|
public async void Load(string path)
|
||||||
{
|
{
|
||||||
|
using (FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read))
|
||||||
|
using (StreamReader reader = new StreamReader(stream))
|
||||||
|
{
|
||||||
|
string content = reader.ReadToEnd();
|
||||||
|
|
||||||
|
Project = JsonConvert.DeserializeObject<Core.Project>(content, _serializationSettings);
|
||||||
|
ProjectViewModel = new ProjectVM(Project);
|
||||||
|
}
|
||||||
|
SavePath = path;
|
||||||
|
RefreshErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Save(string path)
|
public void Save(string path)
|
||||||
{
|
{
|
||||||
|
using (FileStream stream = File.Open(path, FileMode.Create, FileAccess.Write))
|
||||||
|
using (StreamWriter writer = new StreamWriter(stream))
|
||||||
|
{
|
||||||
|
string content = JsonConvert.SerializeObject(Project, _serializationSettings);
|
||||||
|
|
||||||
|
writer.Write(content);
|
||||||
|
}
|
||||||
|
SavePath = path;
|
||||||
|
|
||||||
|
if (!RecentProjects.ContainsKey(Project.Guid))
|
||||||
|
{
|
||||||
|
if (RecentProjects.Count == Settings.Default.RecentProjectsCount)
|
||||||
|
{
|
||||||
|
IEnumerable<ObservableKeyValuePair<Guid, RecentProjectEntry>> kvp = RecentProjects.Cast<ObservableKeyValuePair<Guid, RecentProjectEntry>>();
|
||||||
|
RecentProjects.Remove(kvp.Where(x => x.Value.SaveDate <= kvp.Min(y => y.Value.SaveDate)).FirstOrDefault());
|
||||||
|
}
|
||||||
|
RecentProjects.Add(Project.Guid, new(Project.Name, DateTime.Now, SavePath));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RecentProjects[Project.Guid] = new(Project.Name, DateTime.Now, SavePath);
|
||||||
|
}
|
||||||
|
SaveRecentProjectsList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void RefreshErrors()
|
||||||
|
{
|
||||||
|
Errors.Clear();
|
||||||
|
|
||||||
|
foreach (ClassVM class1 in ProjectViewModel.Classes)
|
||||||
|
{
|
||||||
|
foreach (ClassVM class2 in ProjectViewModel.Classes)
|
||||||
|
{
|
||||||
|
if (class1.Equals(class2))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (class1.Day is not null
|
||||||
|
&&
|
||||||
|
class2.Day is not null
|
||||||
|
&&
|
||||||
|
class1.Day.Equals(class2.Day)
|
||||||
|
&&
|
||||||
|
class1.Slot is not null
|
||||||
|
&&
|
||||||
|
class2.Slot is not null
|
||||||
|
&&
|
||||||
|
class1.Slot.Equals(class2.Slot))
|
||||||
|
{
|
||||||
|
// same classroom at the same time
|
||||||
|
bool classroomCondition = class1.Classroom is not null
|
||||||
|
&&
|
||||||
|
class2.Classroom is not null
|
||||||
|
&&
|
||||||
|
class1.Classroom.Equals(class2.Classroom);
|
||||||
|
if (classroomCondition)
|
||||||
|
{
|
||||||
|
ProjectError newEntry = new ProjectError(ProjectErrorType.Error, class2.Classroom, class2, Resources.Errors_ClassroomBusy);
|
||||||
|
Errors.Add(newEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// same teacher at the same time
|
||||||
|
bool teacherCondition = class1.Teacher is not null
|
||||||
|
&&
|
||||||
|
class2.Teacher is not null
|
||||||
|
&&
|
||||||
|
class1.Teacher.Equals(class2.Teacher);
|
||||||
|
if (teacherCondition)
|
||||||
|
{
|
||||||
|
ProjectError newEntry = new ProjectError(ProjectErrorType.Error, class2.Teacher, class2, Resources.Errors_TeacherBusy);
|
||||||
|
Errors.Add(newEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// same group at the same time
|
||||||
|
if (class1.Group is not null && class2.Group is not null)
|
||||||
|
{
|
||||||
|
if (class1.Group.Equals(class2.Group))
|
||||||
|
{
|
||||||
|
ProjectError newEntry = new ProjectError(ProjectErrorType.Error, class2.Group, class2, Resources.Errors_GroupBusy);
|
||||||
|
Errors.Add(newEntry);
|
||||||
|
}
|
||||||
|
else if (class1.Group is GroupVM group1 && class2.Group is SubgroupVM subgroup2 && group1.AssignedSubgroups.Contains(subgroup2))
|
||||||
|
{
|
||||||
|
ProjectError newEntry = new ProjectError(ProjectErrorType.Error, class2.Group, class2, Resources.Errors_GroupPartBusy);
|
||||||
|
Errors.Add(newEntry);
|
||||||
|
}
|
||||||
|
else if (class1.Group is SubgroupVM subgroup1 && class2.Group is GroupVM group2 && group2.AssignedSubgroups.Contains(subgroup1))
|
||||||
|
{
|
||||||
|
ProjectError newEntry = new ProjectError(ProjectErrorType.Error, class2.Group, class2, Resources.Errors_GroupAllBusy);
|
||||||
|
Errors.Add(newEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool teacherHoursCondition = class1.Teacher is not null
|
||||||
|
&&
|
||||||
|
class1.Day is not null
|
||||||
|
&&
|
||||||
|
class1.Slot is not null
|
||||||
|
&&
|
||||||
|
(
|
||||||
|
!class1.Teacher.AvailabilityHours.ContainsKey(class1.Day)
|
||||||
|
||
|
||||||
|
(
|
||||||
|
class1.Teacher.AvailabilityHours.ContainsKey(class1.Day)
|
||||||
|
&&
|
||||||
|
!class1.Teacher.AvailabilityHours[class1.Day].Any(x => x.CheckCollision(class1.Slot) == TimetableSpanCollision.CheckedSlotIn)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (teacherHoursCondition)
|
||||||
|
{
|
||||||
|
ProjectError newEntry = new ProjectError(ProjectErrorType.Warning, class1.Teacher, class1, Resources.Errors_TeacherNotAvailable);
|
||||||
|
Errors.Add(newEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool teacherAssigned = class1.Teacher is not null;
|
||||||
|
bool classroomAssigned = class1.Classroom is not null;
|
||||||
|
bool groupAssigned = class1.Group is not null;
|
||||||
|
|
||||||
|
List<IUnitVM> assigned = new List<IUnitVM>();
|
||||||
|
if (groupAssigned)
|
||||||
|
{
|
||||||
|
assigned.Add(class1.Group);
|
||||||
|
}
|
||||||
|
if (teacherAssigned)
|
||||||
|
{
|
||||||
|
assigned.Add(class1.Teacher);
|
||||||
|
}
|
||||||
|
if (classroomAssigned)
|
||||||
|
{
|
||||||
|
assigned.Add(class1.Classroom);
|
||||||
|
}
|
||||||
|
IUnitVM unit = assigned.FirstOrDefault();
|
||||||
|
|
||||||
|
if (!teacherAssigned)
|
||||||
|
{
|
||||||
|
ProjectError newEntry = new ProjectError(ProjectErrorType.Warning, unit, class1, Resources.Errors_TeacherNotAssigned);
|
||||||
|
Errors.Add(newEntry);
|
||||||
|
}
|
||||||
|
if (!classroomAssigned)
|
||||||
|
{
|
||||||
|
ProjectError newEntry = new ProjectError(ProjectErrorType.Warning, unit, class1, Resources.Errors_ClassroomNotAssigned);
|
||||||
|
Errors.Add(newEntry);
|
||||||
|
}
|
||||||
|
if (!groupAssigned)
|
||||||
|
{
|
||||||
|
ProjectError newEntry = new ProjectError(ProjectErrorType.Warning, unit, class1, Resources.Errors_GroupNotAssigned);
|
||||||
|
Errors.Add(newEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (class1.Slot is null || class1.Day is null)
|
||||||
|
{
|
||||||
|
ProjectError newEntry = new ProjectError(ProjectErrorType.Information, unit, class1, Resources.Errors_SlotNotAssigned);
|
||||||
|
Errors.Add(newEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void LoadRecentProjectsList()
|
||||||
|
{
|
||||||
|
RecentProjects.Clear();
|
||||||
|
|
||||||
|
if (!File.Exists(Globals.Path.RecentProjectsFile))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] projects;
|
||||||
|
using (FileStream stream = File.Open(Globals.Path.RecentProjectsFile, FileMode.Open, FileAccess.Read))
|
||||||
|
using (StreamReader reader = new StreamReader(stream))
|
||||||
|
{
|
||||||
|
projects = reader.ReadToEnd().Split('\n');
|
||||||
|
}
|
||||||
|
foreach (string project in projects)
|
||||||
|
{
|
||||||
|
string[] projectData = project.Split(" : ");
|
||||||
|
if (projectData.Length < 4)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
string name = projectData[1];
|
||||||
|
string path = projectData[3];
|
||||||
|
if (Guid.TryParse(projectData[0], out Guid guid) && DateTime.TryParse(projectData[2], out DateTime saveDate) && !string.IsNullOrWhiteSpace(path) && File.Exists(path) && !string.IsNullOrWhiteSpace(name))
|
||||||
|
{
|
||||||
|
RecentProjects.Add(guid, new(name, saveDate, path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveRecentProjectsList()
|
||||||
|
{
|
||||||
|
List<string> lines = new List<string>();
|
||||||
|
foreach (ObservableKeyValuePair<Guid, RecentProjectEntry> project in RecentProjects)
|
||||||
|
{
|
||||||
|
lines.Add($"{project.Key} : {project.Value.Name} : {project.Value.SaveDate} : {project.Value.Path}");
|
||||||
|
}
|
||||||
|
|
||||||
|
using (FileStream stream = File.Open(Globals.Path.RecentProjectsFile, FileMode.Create, FileAccess.Write))
|
||||||
|
using (StreamWriter reader = new StreamWriter(stream))
|
||||||
|
{
|
||||||
|
reader.Write(string.Join('\n', lines));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
76
TimetableDesigner/Services/Project/RecentProjectEntry.cs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TimetableDesigner.Customs;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Services.Project
|
||||||
|
{
|
||||||
|
public class RecentProjectEntry : ObservableObject
|
||||||
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private string _name;
|
||||||
|
private DateTime _saveDate;
|
||||||
|
private string _path;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PROPERTIES
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get => _name;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_name != value)
|
||||||
|
{
|
||||||
|
_name = value;
|
||||||
|
NotifyPropertyChanged(nameof(Name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public DateTime SaveDate
|
||||||
|
{
|
||||||
|
get => _saveDate;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_saveDate != value)
|
||||||
|
{
|
||||||
|
_saveDate = value;
|
||||||
|
NotifyPropertyChanged(nameof(SaveDate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string Path
|
||||||
|
{
|
||||||
|
get => _path;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_path != value)
|
||||||
|
{
|
||||||
|
_path = value;
|
||||||
|
NotifyPropertyChanged(nameof(Path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public RecentProjectEntry(string name, DateTime saveDate, string path)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
SaveDate = saveDate;
|
||||||
|
Path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
19
TimetableDesigner/Services/Scheduler/ISchedulerService.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TimetableDesigner.Core;
|
||||||
|
using TimetableDesigner.ViewModels.Models;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Services.Scheduler
|
||||||
|
{
|
||||||
|
public interface ISchedulerService : IService
|
||||||
|
{
|
||||||
|
#region METHODS
|
||||||
|
|
||||||
|
(TimetableDay? Day, TimetableSpan? Slot) Schedule(ClassVM @class);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
201
TimetableDesigner/Services/Scheduler/SchedulerService.cs
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
using Microsoft.ML;
|
||||||
|
using Microsoft.ML.Data;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Data;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using TimetableDesigner.Core;
|
||||||
|
using TimetableDesigner.Services.Project;
|
||||||
|
using TimetableDesigner.ViewModels.Models;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Services.Scheduler
|
||||||
|
{
|
||||||
|
public class SchedulerService : ISchedulerService
|
||||||
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private IProjectService _projectService;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public SchedulerService(IProjectService projectService)
|
||||||
|
{
|
||||||
|
_projectService = projectService;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PUBLIC METHODS
|
||||||
|
|
||||||
|
public (TimetableDay? Day, TimetableSpan? Slot) Schedule(ClassVM @class)
|
||||||
|
{
|
||||||
|
IEnumerable<(TimetableDay Day, TimetableSpan Slot)> freeSlots = GetFreeSlots(@class);
|
||||||
|
|
||||||
|
List<(TimetableDay Day, TimetableSpan Slot)> allMidBreaks = new List<(TimetableDay Day, TimetableSpan Slot)>();
|
||||||
|
List<(TimetableDay Day, TimetableSpan Slot)> secondTierBreaks = new List<(TimetableDay Day, TimetableSpan Slot)>();
|
||||||
|
|
||||||
|
IEnumerable<TimetableDay> days = freeSlots.Select(x => x.Day).Distinct();
|
||||||
|
foreach (TimetableDay day in days)
|
||||||
|
{
|
||||||
|
IEnumerable<int> unusedIndexes = freeSlots.Where(x => x.Day == day).Select(x => _projectService.ProjectViewModel.TimetableTemplate.Slots.IndexOf(x.Slot));
|
||||||
|
Debug.WriteLine(day.Name);
|
||||||
|
foreach (int unusedIndex in unusedIndexes)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(unusedIndex);
|
||||||
|
}
|
||||||
|
Debug.WriteLine("");
|
||||||
|
|
||||||
|
IEnumerable<(int Start, int End)> breaks = FindBreaks(unusedIndexes);
|
||||||
|
int last = _projectService.ProjectViewModel.TimetableTemplate.Slots.Count - 1;
|
||||||
|
|
||||||
|
IEnumerable<(int Start, int End)> midBreaks = breaks.Where(x => x.Start != 0 && x.End != last);
|
||||||
|
if (midBreaks.Any())
|
||||||
|
{
|
||||||
|
allMidBreaks.Add((day, _projectService.ProjectViewModel.TimetableTemplate.Slots.ElementAt(midBreaks.First().Start)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(int start, int end) = breaks.First();
|
||||||
|
int selIndex = start == 0 && end != last ? end : start;
|
||||||
|
secondTierBreaks.Add((day, _projectService.ProjectViewModel.TimetableTemplate.Slots.ElementAt(selIndex)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allMidBreaks.Any())
|
||||||
|
{
|
||||||
|
return allMidBreaks.First();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secondTierBreaks.Any())
|
||||||
|
{
|
||||||
|
Random rd = new Random();
|
||||||
|
return secondTierBreaks.ElementAt(rd.Next(secondTierBreaks.Count));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PRIVATE METHODS
|
||||||
|
|
||||||
|
private IEnumerable<(int Start, int End)> FindBreaks(IEnumerable<int> unusedIndexes)
|
||||||
|
{
|
||||||
|
unusedIndexes = unusedIndexes.Order();
|
||||||
|
|
||||||
|
int prev = unusedIndexes.ElementAt(0);
|
||||||
|
int first = unusedIndexes.ElementAt(0);
|
||||||
|
List<(int Start, int End)> breaks = new List<(int Start, int End)>();
|
||||||
|
foreach (int index in unusedIndexes.Skip(1))
|
||||||
|
{
|
||||||
|
if (prev + 1 != index)
|
||||||
|
{
|
||||||
|
breaks.Add((first, prev));
|
||||||
|
first = index;
|
||||||
|
}
|
||||||
|
prev = index;
|
||||||
|
}
|
||||||
|
breaks.Add((first, prev));
|
||||||
|
return breaks;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<TimetableDay, List<TimetableSpan>> CreateSlotsDictionary()
|
||||||
|
{
|
||||||
|
Dictionary<TimetableDay, List<TimetableSpan>> slotsDictionary = new Dictionary<TimetableDay, List<TimetableSpan>>();
|
||||||
|
foreach (TimetableDay day in _projectService.ProjectViewModel.TimetableTemplate.Days)
|
||||||
|
{
|
||||||
|
slotsDictionary[day] = new List<TimetableSpan>();
|
||||||
|
foreach (TimetableSpan slot in _projectService.ProjectViewModel.TimetableTemplate.Slots)
|
||||||
|
{
|
||||||
|
slotsDictionary[day].Add(slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return slotsDictionary;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<(TimetableDay Day, TimetableSpan Slot)> GetFreeSlots(ClassVM @class)
|
||||||
|
{
|
||||||
|
Dictionary<TimetableDay, List<TimetableSpan>> classroomFreeSlotsDict = CreateSlotsDictionary();
|
||||||
|
if (@class.Classroom is not null)
|
||||||
|
{
|
||||||
|
IEnumerable<ClassVM> classroomClasses = _projectService.ProjectViewModel.Classes.Where(x => x.Classroom == @class.Classroom).Where(x => x.Day is not null && x.Slot is not null);
|
||||||
|
foreach (ClassVM classroomClass in classroomClasses)
|
||||||
|
{
|
||||||
|
classroomFreeSlotsDict[classroomClass.Day].Remove(classroomClass.Slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ICollection<(TimetableDay Day, TimetableSpan Slot)> classroomFreeSlots = new List<(TimetableDay Day, TimetableSpan Slot)>();
|
||||||
|
foreach (KeyValuePair<TimetableDay, List<TimetableSpan>> pair in classroomFreeSlotsDict)
|
||||||
|
{
|
||||||
|
foreach (TimetableSpan slot in pair.Value)
|
||||||
|
{
|
||||||
|
classroomFreeSlots.Add((pair.Key, slot));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<TimetableDay, List<TimetableSpan>> teacherFreeSlotsDict = CreateSlotsDictionary();
|
||||||
|
if (@class.Teacher is not null)
|
||||||
|
{
|
||||||
|
IEnumerable<ClassVM> teacherClasses = _projectService.ProjectViewModel.Classes.Where(x => x.Teacher == @class.Teacher).Where(x => x.Day is not null && x.Slot is not null);
|
||||||
|
foreach (ClassVM teacherClass in teacherClasses)
|
||||||
|
{
|
||||||
|
teacherFreeSlotsDict[teacherClass.Day].Remove(teacherClass.Slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ICollection<(TimetableDay Day, TimetableSpan Slot)> teacherFreeSlots = new List<(TimetableDay Day, TimetableSpan Slot)>();
|
||||||
|
foreach (KeyValuePair<TimetableDay, List<TimetableSpan>> pair in teacherFreeSlotsDict)
|
||||||
|
{
|
||||||
|
foreach (TimetableSpan slot in pair.Value)
|
||||||
|
{
|
||||||
|
teacherFreeSlots.Add((pair.Key, slot));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<TimetableDay, List<TimetableSpan>> groupFreeSlotsDict = CreateSlotsDictionary();
|
||||||
|
if (@class.Group is not null)
|
||||||
|
{
|
||||||
|
IEnumerable<ClassVM> groupClasses;
|
||||||
|
if (@class.Group is SubgroupVM subgroup)
|
||||||
|
{
|
||||||
|
IEnumerable<GroupVM> groups = _projectService.ProjectViewModel.Groups.Where(x => x.AssignedSubgroups.Contains(subgroup));
|
||||||
|
groupClasses = _projectService.ProjectViewModel.Classes.Where(x => (x.Group is GroupVM group && groups.Contains(group)) || x.Group == subgroup);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GroupVM group = @class.Group as GroupVM;
|
||||||
|
groupClasses = _projectService.ProjectViewModel.Classes.Where(x => x.Group == group || (x.Group is SubgroupVM subgroup && group.AssignedSubgroups.Contains(subgroup)));
|
||||||
|
}
|
||||||
|
groupClasses = groupClasses.Where(x => x.Day is not null && x.Slot is not null);
|
||||||
|
foreach (ClassVM groupClass in groupClasses)
|
||||||
|
{
|
||||||
|
groupFreeSlotsDict[groupClass.Day].Remove(groupClass.Slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ICollection<(TimetableDay Day, TimetableSpan Slot)> groupFreeSlots = new List<(TimetableDay Day, TimetableSpan Slot)>();
|
||||||
|
foreach (KeyValuePair<TimetableDay, List<TimetableSpan>> pair in groupFreeSlotsDict)
|
||||||
|
{
|
||||||
|
foreach (TimetableSpan slot in pair.Value)
|
||||||
|
{
|
||||||
|
groupFreeSlots.Add((pair.Key, slot));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return classroomFreeSlots.Intersect(teacherFreeSlots).Intersect(groupFreeSlots);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,7 +21,7 @@ namespace TimetableDesigner.Services.TabNavigation
|
|||||||
private ImageSource _image;
|
private ImageSource _image;
|
||||||
private string _title;
|
private string _title;
|
||||||
private bool _isClosable;
|
private bool _isClosable;
|
||||||
private BaseViewViewModel _viewModel;
|
private IViewVM _viewModel;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ namespace TimetableDesigner.Services.TabNavigation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public BaseViewViewModel ViewModel
|
public IViewVM ViewModel
|
||||||
{
|
{
|
||||||
get => _viewModel;
|
get => _viewModel;
|
||||||
set
|
set
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ namespace TimetableDesigner.Services.TabNavigation
|
|||||||
public void Close(TabItem item) => Close(new List<TabItem>() { item });
|
public void Close(TabItem item) => Close(new List<TabItem>() { item });
|
||||||
public void Close(IEnumerable<TabItem> items)
|
public void Close(IEnumerable<TabItem> items)
|
||||||
{
|
{
|
||||||
TabItem selected = SelectedTab;
|
TabItem? selected = SelectedTab;
|
||||||
while (items.Contains(selected) && selected != null)
|
while (items.Contains(selected) && selected != null)
|
||||||
{
|
{
|
||||||
int nextIndex = Tabs.IndexOf(selected) + 1;
|
int nextIndex = Tabs.IndexOf(selected) + 1;
|
||||||
@@ -102,7 +102,7 @@ namespace TimetableDesigner.Services.TabNavigation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (TabItem item in items)
|
foreach (TabItem item in items.ToList())
|
||||||
{
|
{
|
||||||
Tabs.Remove(item);
|
Tabs.Remove(item);
|
||||||
}
|
}
|
||||||
|
|||||||
28
TimetableDesigner/Settings.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
namespace TimetableDesigner.Properties {
|
||||||
|
|
||||||
|
|
||||||
|
// This class allows you to handle specific events on the settings class:
|
||||||
|
// The SettingChanging event is raised before a setting's value is changed.
|
||||||
|
// The PropertyChanged event is raised after a setting's value is changed.
|
||||||
|
// The SettingsLoaded event is raised after the setting values are loaded.
|
||||||
|
// The SettingsSaving event is raised before the setting values are saved.
|
||||||
|
internal sealed partial class Settings {
|
||||||
|
|
||||||
|
public Settings() {
|
||||||
|
// // To add event handlers for saving and changing settings, uncomment the lines below:
|
||||||
|
//
|
||||||
|
// this.SettingChanging += this.SettingChangingEventHandler;
|
||||||
|
//
|
||||||
|
// this.SettingsSaving += this.SettingsSavingEventHandler;
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
|
||||||
|
// Add code to handle the SettingChangingEvent event here.
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
|
||||||
|
// Add code to handle the SettingsSaving event here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,29 +16,86 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="Resources\Images\Add.png" />
|
<None Remove="Resources\Images\Add.png" />
|
||||||
|
<None Remove="Resources\Images\Autoschedule.png" />
|
||||||
<None Remove="Resources\Images\Classroom.png" />
|
<None Remove="Resources\Images\Classroom.png" />
|
||||||
<None Remove="Resources\Images\ClassroomAdd.png" />
|
<None Remove="Resources\Images\ClassroomAdd.png" />
|
||||||
|
<None Remove="Resources\Images\ClassroomBlack.png" />
|
||||||
|
<None Remove="Resources\Images\ClassroomGrey.png" />
|
||||||
|
<None Remove="Resources\Images\ClassroomWhite.png" />
|
||||||
|
<None Remove="Resources\Images\CloneBlack.png" />
|
||||||
|
<None Remove="Resources\Images\CloneWhite.png" />
|
||||||
<None Remove="Resources\Images\Close.png" />
|
<None Remove="Resources\Images\Close.png" />
|
||||||
<None Remove="Resources\Images\CloseButtonImage.png" />
|
<None Remove="Resources\Images\CloseButtonImage.png" />
|
||||||
|
<None Remove="Resources\Images\EditBlack.png" />
|
||||||
|
<None Remove="Resources\Images\EditGrey.png" />
|
||||||
|
<None Remove="Resources\Images\EditWhite.png" />
|
||||||
|
<None Remove="Resources\Images\Error.png" />
|
||||||
<None Remove="Resources\Images\Group.png" />
|
<None Remove="Resources\Images\Group.png" />
|
||||||
<None Remove="Resources\Images\GroupAdd.png" />
|
<None Remove="Resources\Images\GroupAdd.png" />
|
||||||
|
<None Remove="Resources\Images\GroupBlack.png" />
|
||||||
|
<None Remove="Resources\Images\GroupGrey.png" />
|
||||||
|
<None Remove="Resources\Images\GroupWhite.png" />
|
||||||
|
<None Remove="Resources\Images\Info.png" />
|
||||||
<None Remove="Resources\Images\New.png" />
|
<None Remove="Resources\Images\New.png" />
|
||||||
<None Remove="Resources\Images\Open.png" />
|
<None Remove="Resources\Images\Open.png" />
|
||||||
<None Remove="Resources\Images\OpenRecent.png" />
|
<None Remove="Resources\Images\OpenRecent.png" />
|
||||||
<None Remove="Resources\Images\Project.png" />
|
<None Remove="Resources\Images\Project.png" />
|
||||||
<None Remove="Resources\Images\ProjectSettings.png" />
|
<None Remove="Resources\Images\ProjectSettings.png" />
|
||||||
<None Remove="Resources\Images\Remove.png" />
|
<None Remove="Resources\Images\Remove.png" />
|
||||||
|
<None Remove="Resources\Images\RemoveBlack.png" />
|
||||||
|
<None Remove="Resources\Images\RemoveGrey.png" />
|
||||||
|
<None Remove="Resources\Images\RemoveWhite.png" />
|
||||||
<None Remove="Resources\Images\RightArrow.png" />
|
<None Remove="Resources\Images\RightArrow.png" />
|
||||||
<None Remove="Resources\Images\Save.png" />
|
<None Remove="Resources\Images\Save.png" />
|
||||||
<None Remove="Resources\Images\SaveAs.png" />
|
<None Remove="Resources\Images\SaveAs.png" />
|
||||||
<None Remove="Resources\Images\Teacher.png" />
|
<None Remove="Resources\Images\Teacher.png" />
|
||||||
<None Remove="Resources\Images\TeacherAdd.png" />
|
<None Remove="Resources\Images\TeacherAdd.png" />
|
||||||
|
<None Remove="Resources\Images\TeacherBlack.png" />
|
||||||
|
<None Remove="Resources\Images\TeacherGrey.png" />
|
||||||
|
<None Remove="Resources\Images\TeacherWhite.png" />
|
||||||
|
<None Remove="Resources\Images\Warning.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Page Remove="Views\ProjectSettingsTabView.xaml" />
|
<Page Remove="Views\ProjectSettingsTabView.xaml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Resources\Images\Autoschedule.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Resources\Images\ClassroomBlack.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Resources\Images\ClassroomWhite.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Resources\Images\CloneBlack.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Resources\Images\CloneWhite.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Resources\Images\EditBlack.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Resources\Images\EditWhite.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Resources\Images\Error.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Resources\Images\GroupBlack.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Resources\Images\GroupWhite.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Resources\Images\Info.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Resources\Images\Classroom.png">
|
<Content Include="Resources\Images\Classroom.png">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
@@ -70,7 +127,10 @@
|
|||||||
<Content Include="Resources\Images\ProjectSettings.png">
|
<Content Include="Resources\Images\ProjectSettings.png">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="Resources\Images\Remove.png">
|
<Content Include="Resources\Images\RemoveBlack.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Resources\Images\RemoveWhite.png">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="Resources\Images\RightArrow.png">
|
<Content Include="Resources\Images\RightArrow.png">
|
||||||
@@ -88,11 +148,23 @@
|
|||||||
<Content Include="Resources\Images\TeacherAdd.png">
|
<Content Include="Resources\Images\TeacherAdd.png">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="Resources\Images\TeacherBlack.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Resources\Images\TeacherWhite.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Resources\Images\Warning.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Extended.Wpf.Toolkit" Version="4.5.0" />
|
<PackageReference Include="Extended.Wpf.Toolkit" Version="4.5.0" />
|
||||||
<PackageReference Include="Fluent.Ribbon" Version="9.0.4" />
|
<PackageReference Include="Fluent.Ribbon" Version="9.0.4" />
|
||||||
|
<PackageReference Include="Microsoft.ML" Version="2.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -117,6 +189,11 @@
|
|||||||
<AutoGen>True</AutoGen>
|
<AutoGen>True</AutoGen>
|
||||||
<DependentUpon>Resources.resx</DependentUpon>
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Update="Properties\Settings.Designer.cs">
|
||||||
|
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Settings.settings</DependentUpon>
|
||||||
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -130,4 +207,11 @@
|
|||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="Properties\Settings.settings">
|
||||||
|
<Generator>SettingsSingleFileGenerator</Generator>
|
||||||
|
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -3,11 +3,10 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using TimetableDesigner.Customs;
|
|
||||||
|
|
||||||
namespace TimetableDesigner.ViewModels
|
namespace TimetableDesigner.ViewModels
|
||||||
{
|
{
|
||||||
public abstract class BaseViewViewModel : ObservableObject
|
public interface IModelVM
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
12
TimetableDesigner/ViewModels/IRemovableVM.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.ViewModels.Models.Base
|
||||||
|
{
|
||||||
|
public interface IRemovableVM : IUnitVM
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
18
TimetableDesigner/ViewModels/IUnitEditorViewVM.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TimetableDesigner.ViewModels.Models.Base;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.ViewModels
|
||||||
|
{
|
||||||
|
internal interface IUnitEditorViewVM : IViewVM
|
||||||
|
{
|
||||||
|
#region PROPERTIES
|
||||||
|
|
||||||
|
IUnitVM Unit { get; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,13 +5,13 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using TimetableDesigner.Core;
|
using TimetableDesigner.Core;
|
||||||
|
|
||||||
namespace TimetableDesigner.ViewModels.Models
|
namespace TimetableDesigner.ViewModels.Models.Base
|
||||||
{
|
{
|
||||||
public interface IGroupViewModel
|
public interface IUnitVM : IModelVM
|
||||||
{
|
{
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
IGroup Group { get; }
|
IUnit Unit { get; }
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -1,14 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using TimetableDesigner.Customs;
|
|
||||||
|
|
||||||
namespace TimetableDesigner.ViewModels
|
namespace TimetableDesigner.ViewModels
|
||||||
{
|
{
|
||||||
public abstract class BaseModelViewModel : ObservableObject
|
public interface IViewVM
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
65
TimetableDesigner/ViewModels/Models/BaseGroupVM.cs
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TimetableDesigner.Core;
|
||||||
|
using TimetableDesigner.Customs;
|
||||||
|
using TimetableDesigner.ViewModels.Models.Base;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.ViewModels.Models
|
||||||
|
{
|
||||||
|
public abstract class BaseGroupVM : ObservableObject, IModelVM, IUnitVM
|
||||||
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
protected BaseGroup _baseGroup;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PROPERTIES
|
||||||
|
|
||||||
|
IUnit IUnitVM.Unit => _baseGroup;
|
||||||
|
public BaseGroup BaseGroup => _baseGroup;
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get => _baseGroup.Name;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_baseGroup.Name != value)
|
||||||
|
{
|
||||||
|
_baseGroup.Name = value;
|
||||||
|
NotifyPropertyChanged(nameof(Name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string ShortName
|
||||||
|
{
|
||||||
|
get => _baseGroup.ShortName;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_baseGroup.ShortName != value)
|
||||||
|
{
|
||||||
|
_baseGroup.ShortName = value;
|
||||||
|
NotifyPropertyChanged(nameof(ShortName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public BaseGroupVM(BaseGroup baseGroup)
|
||||||
|
{
|
||||||
|
_baseGroup = baseGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,20 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.Design;
|
using System.ComponentModel.Design;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using TimetableDesigner.Core;
|
using TimetableDesigner.Core;
|
||||||
|
using TimetableDesigner.Customs;
|
||||||
using TimetableDesigner.Services;
|
using TimetableDesigner.Services;
|
||||||
using TimetableDesigner.Services.Project;
|
using TimetableDesigner.Services.Project;
|
||||||
|
using TimetableDesigner.ViewModels.Models.Base;
|
||||||
|
|
||||||
namespace TimetableDesigner.ViewModels.Models
|
namespace TimetableDesigner.ViewModels.Models
|
||||||
{
|
{
|
||||||
public class ClassViewModel : BaseModelViewModel
|
public class ClassVM : ObservableObject, IModelVM
|
||||||
{
|
{
|
||||||
#region FIELDS
|
#region FIELDS
|
||||||
|
|
||||||
@@ -38,7 +42,7 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public TeacherViewModel? Teacher
|
public TeacherVM? Teacher
|
||||||
{
|
{
|
||||||
get => _projectService.ProjectViewModel?.Teachers.Where(vm => vm.Teacher == _class.Teacher).FirstOrDefault();
|
get => _projectService.ProjectViewModel?.Teachers.Where(vm => vm.Teacher == _class.Teacher).FirstOrDefault();
|
||||||
set
|
set
|
||||||
@@ -47,18 +51,22 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
{
|
{
|
||||||
_class.Teacher = value?.Teacher;
|
_class.Teacher = value?.Teacher;
|
||||||
NotifyPropertyChanged(nameof(Teacher));
|
NotifyPropertyChanged(nameof(Teacher));
|
||||||
|
|
||||||
|
//REFRESH: Errors
|
||||||
|
_projectService.RefreshErrors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public IGroupViewModel? Group
|
public BaseGroupVM? Group
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_class.Group?.GetType() == typeof(GroupViewModel))
|
|
||||||
|
if (_class.Group?.GetType() == typeof(Group))
|
||||||
{
|
{
|
||||||
return _projectService.ProjectViewModel?.Groups.Where(vm => vm.Group == _class.Group).FirstOrDefault();
|
return _projectService.ProjectViewModel?.Groups.Where(vm => vm.Group == _class.Group).FirstOrDefault();
|
||||||
}
|
}
|
||||||
else if (_class.Group?.GetType() == typeof(SubgroupViewModel))
|
else if (_class.Group?.GetType() == typeof(Subgroup))
|
||||||
{
|
{
|
||||||
return _projectService.ProjectViewModel?.Subgroups.Where(vm => vm.Subgroup == _class.Group).FirstOrDefault();
|
return _projectService.ProjectViewModel?.Subgroups.Where(vm => vm.Subgroup == _class.Group).FirstOrDefault();
|
||||||
}
|
}
|
||||||
@@ -69,14 +77,17 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (_class.Group != value?.Group)
|
if (_class.Group != value?.BaseGroup)
|
||||||
{
|
{
|
||||||
_class.Group = value?.Group;
|
_class.Group = value?.BaseGroup;
|
||||||
NotifyPropertyChanged(nameof(Group));
|
NotifyPropertyChanged(nameof(Group));
|
||||||
|
|
||||||
|
//REFRESH: Errors
|
||||||
|
_projectService.RefreshErrors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public ClassroomViewModel? Classroom
|
public ClassroomVM? Classroom
|
||||||
{
|
{
|
||||||
get => _projectService.ProjectViewModel?.Classrooms.Where(vm => vm.Classroom == _class.Classroom).FirstOrDefault();
|
get => _projectService.ProjectViewModel?.Classrooms.Where(vm => vm.Classroom == _class.Classroom).FirstOrDefault();
|
||||||
set
|
set
|
||||||
@@ -85,6 +96,45 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
{
|
{
|
||||||
_class.Classroom = value?.Classroom;
|
_class.Classroom = value?.Classroom;
|
||||||
NotifyPropertyChanged(nameof(Classroom));
|
NotifyPropertyChanged(nameof(Classroom));
|
||||||
|
|
||||||
|
//REFRESH: Errors
|
||||||
|
_projectService.RefreshErrors();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public TimetableDay? Day
|
||||||
|
{
|
||||||
|
get => _class.Day;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _class.Day)
|
||||||
|
{
|
||||||
|
_class.Day = value;
|
||||||
|
NotifyPropertyChanged(nameof(Day));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public TimetableSpan? Slot
|
||||||
|
{
|
||||||
|
get => _class.Slot;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _class.Slot)
|
||||||
|
{
|
||||||
|
_class.Slot = value;
|
||||||
|
NotifyPropertyChanged(nameof(Slot));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public byte[] Color
|
||||||
|
{
|
||||||
|
get => _class.Color;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _class.Color)
|
||||||
|
{
|
||||||
|
_class.Color = value;
|
||||||
|
NotifyPropertyChanged(nameof(Color));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,7 +145,7 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
|
|
||||||
#region CONSTRUCTORS
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
public ClassViewModel(Class @class)
|
public ClassVM(Class @class)
|
||||||
{
|
{
|
||||||
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
|
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
|
||||||
|
|
||||||
@@ -4,10 +4,12 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using TimetableDesigner.Core;
|
using TimetableDesigner.Core;
|
||||||
|
using TimetableDesigner.Customs;
|
||||||
|
using TimetableDesigner.ViewModels.Models.Base;
|
||||||
|
|
||||||
namespace TimetableDesigner.ViewModels.Models
|
namespace TimetableDesigner.ViewModels.Models
|
||||||
{
|
{
|
||||||
public class ClassroomViewModel : BaseModelViewModel
|
public class ClassroomVM : ObservableObject, IModelVM, IUnitVM, IRemovableVM
|
||||||
{
|
{
|
||||||
#region FIELDS
|
#region FIELDS
|
||||||
|
|
||||||
@@ -19,6 +21,7 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
|
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
|
IUnit IUnitVM.Unit => _classroom;
|
||||||
public Classroom Classroom => _classroom;
|
public Classroom Classroom => _classroom;
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
@@ -76,7 +79,7 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
|
|
||||||
#region CONSTRUCTORS
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
public ClassroomViewModel(Classroom classroom)
|
public ClassroomVM(Classroom classroom)
|
||||||
{
|
{
|
||||||
_classroom = classroom;
|
_classroom = classroom;
|
||||||
}
|
}
|
||||||
@@ -5,53 +5,40 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using TimetableDesigner.Core;
|
using TimetableDesigner.Core;
|
||||||
|
using TimetableDesigner.Customs;
|
||||||
using TimetableDesigner.Services;
|
using TimetableDesigner.Services;
|
||||||
using TimetableDesigner.Services.Project;
|
using TimetableDesigner.Services.Project;
|
||||||
|
using TimetableDesigner.ViewModels.Models.Base;
|
||||||
|
|
||||||
namespace TimetableDesigner.ViewModels.Models
|
namespace TimetableDesigner.ViewModels.Models
|
||||||
{
|
{
|
||||||
public class GroupViewModel : BaseModelViewModel, IGroupViewModel
|
public class GroupVM : BaseGroupVM, IRemovableVM
|
||||||
{
|
{
|
||||||
#region FIELDS
|
#region FIELDS
|
||||||
|
|
||||||
private IProjectService _projectService;
|
private IProjectService _projectService;
|
||||||
|
|
||||||
private Group _group;
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
IGroup IGroupViewModel.Group => _group;
|
public Group Group => (Group)_baseGroup;
|
||||||
public Group Group => _group;
|
|
||||||
|
|
||||||
public string Name
|
|
||||||
{
|
|
||||||
get => _group.Name;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_group.Name != value)
|
|
||||||
{
|
|
||||||
_group.Name = value;
|
|
||||||
NotifyPropertyChanged(nameof(Name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public string Description
|
public string Description
|
||||||
{
|
{
|
||||||
get => _group.Description;
|
get => Group.Description;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (_group.Description != value)
|
if (Group.Description != value)
|
||||||
{
|
{
|
||||||
_group.Description = value;
|
Group.Description = value;
|
||||||
NotifyPropertyChanged(nameof(Description));
|
NotifyPropertyChanged(nameof(Description));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public ObservableCollection<SubgroupViewModel> AssignedSubgroups => new ObservableCollection<SubgroupViewModel>(_projectService.ProjectViewModel.Subgroups.Where(vm => Group.AssignedSubgroups.Contains(vm.Subgroup)));
|
public ObservableCollection<SubgroupVM> AssignedSubgroups => new ObservableCollection<SubgroupVM>(_projectService.ProjectViewModel.Subgroups.Where(vm => Group.AssignedSubgroups.Contains(vm.Subgroup)));
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -59,10 +46,9 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
|
|
||||||
#region CONSTRUCTORS
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
public GroupViewModel(Group group)
|
public GroupVM(Group group) : base(group)
|
||||||
{
|
{
|
||||||
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
|
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
|
||||||
_group = group;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -71,16 +57,22 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
|
|
||||||
#region PUBLIC METHODS
|
#region PUBLIC METHODS
|
||||||
|
|
||||||
public void AddSubgroup(SubgroupViewModel subgroup)
|
public void AddSubgroup(SubgroupVM subgroup)
|
||||||
{
|
{
|
||||||
Group.AssignedSubgroups.Add(subgroup.Subgroup);
|
Group.AssignedSubgroups.Add(subgroup.Subgroup);
|
||||||
NotifyPropertyChanged(nameof(AssignedSubgroups));
|
NotifyPropertyChanged(nameof(AssignedSubgroups));
|
||||||
|
|
||||||
|
//REFRESH: Errors
|
||||||
|
_projectService.RefreshErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveSubgroup(SubgroupViewModel subgroup)
|
public void RemoveSubgroup(SubgroupVM subgroup)
|
||||||
{
|
{
|
||||||
Group.AssignedSubgroups.Remove(subgroup.Subgroup);
|
Group.AssignedSubgroups.Remove(subgroup.Subgroup);
|
||||||
NotifyPropertyChanged(nameof(AssignedSubgroups));
|
NotifyPropertyChanged(nameof(AssignedSubgroups));
|
||||||
|
|
||||||
|
//REFRESH: Errors
|
||||||
|
_projectService.RefreshErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
222
TimetableDesigner/ViewModels/Models/ProjectVM.cs
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TimetableDesigner.Core;
|
||||||
|
using TimetableDesigner.Customs;
|
||||||
|
using TimetableDesigner.Services.Project;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.ViewModels.Models
|
||||||
|
{
|
||||||
|
public class ProjectVM : ObservableObject, IModelVM
|
||||||
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private Project _project;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PROPERTIES
|
||||||
|
|
||||||
|
public Project Project => _project;
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get => Project.Name;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (Project.Name != value)
|
||||||
|
{
|
||||||
|
Project.Name = value;
|
||||||
|
NotifyPropertyChanged(nameof(Name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string Author
|
||||||
|
{
|
||||||
|
get => Project.Author;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (Project.Author != value)
|
||||||
|
{
|
||||||
|
Project.Author = value;
|
||||||
|
NotifyPropertyChanged(nameof(Author));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string Description
|
||||||
|
{
|
||||||
|
get => Project.Description;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (Project.Description != value)
|
||||||
|
{
|
||||||
|
Project.Description = value;
|
||||||
|
NotifyPropertyChanged(nameof(Description));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public TimetableTemplateVM TimetableTemplate { get; set; }
|
||||||
|
public ObservableCollection<ClassroomVM> Classrooms { get; set; }
|
||||||
|
public ObservableCollection<TeacherVM> Teachers { get; set; }
|
||||||
|
public ObservableCollection<GroupVM> Groups { get; set; }
|
||||||
|
public ObservableCollection<SubgroupVM> Subgroups { get; set; }
|
||||||
|
public ObservableCollection<ClassVM> Classes { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public ProjectVM(Project project)
|
||||||
|
{
|
||||||
|
_project = project;
|
||||||
|
|
||||||
|
TimetableTemplate = new TimetableTemplateVM(_project.TimetableTemplate);
|
||||||
|
|
||||||
|
Classrooms = new ObservableCollection<ClassroomVM>(_project.Classrooms.Select(item => new ClassroomVM(item)));
|
||||||
|
Classrooms.CollectionChanged += Classrooms_CollectionChanged;
|
||||||
|
|
||||||
|
Teachers = new ObservableCollection<TeacherVM>(_project.Teachers.Select(item => new TeacherVM(item)));
|
||||||
|
Teachers.CollectionChanged += Teachers_CollectionChanged;
|
||||||
|
|
||||||
|
Groups = new ObservableCollection<GroupVM>(_project.Groups.Select(item => new GroupVM(item)));
|
||||||
|
Groups.CollectionChanged += Groups_CollectionChanged;
|
||||||
|
|
||||||
|
Subgroups = new ObservableCollection<SubgroupVM>(_project.Subgroups.Select(item => new SubgroupVM(item)));
|
||||||
|
Subgroups.CollectionChanged += Subgroups_CollectionChanged;
|
||||||
|
|
||||||
|
Classes = new ObservableCollection<ClassVM>(_project.Classes.Select(item => new ClassVM(item)));
|
||||||
|
Classes.CollectionChanged += Classes_CollectionChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PRIVATE METHODS
|
||||||
|
|
||||||
|
private void Classrooms_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.OldItems is not null)
|
||||||
|
{
|
||||||
|
foreach (ClassroomVM vm in e.OldItems)
|
||||||
|
{
|
||||||
|
foreach (ClassVM cvm in Classes.Where(x => x.Classroom == vm))
|
||||||
|
{
|
||||||
|
cvm.Classroom = null;
|
||||||
|
}
|
||||||
|
_project.Classrooms.Remove(vm.Classroom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.NewItems is not null)
|
||||||
|
{
|
||||||
|
foreach (ClassroomVM vm in e.NewItems)
|
||||||
|
{
|
||||||
|
_project.Classrooms.Add(vm.Classroom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Teachers_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.OldItems is not null)
|
||||||
|
{
|
||||||
|
foreach (TeacherVM vm in e.OldItems)
|
||||||
|
{
|
||||||
|
foreach (ClassVM cvm in Classes.Where(x => x.Teacher == vm))
|
||||||
|
{
|
||||||
|
cvm.Teacher = null;
|
||||||
|
}
|
||||||
|
_project.Teachers.Remove(vm.Teacher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.NewItems is not null)
|
||||||
|
{
|
||||||
|
foreach (TeacherVM vm in e.NewItems)
|
||||||
|
{
|
||||||
|
_project.Teachers.Add(vm.Teacher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Groups_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.OldItems is not null)
|
||||||
|
{
|
||||||
|
foreach (GroupVM vm in e.OldItems)
|
||||||
|
{
|
||||||
|
foreach (ClassVM cvm in Classes.Where(x => x.Group == vm))
|
||||||
|
{
|
||||||
|
cvm.Group = null;
|
||||||
|
}
|
||||||
|
_project.Groups.Remove(vm.Group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.NewItems is not null)
|
||||||
|
{
|
||||||
|
foreach (GroupVM vm in e.NewItems)
|
||||||
|
{
|
||||||
|
_project.Groups.Add(vm.Group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Subgroups_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.OldItems is not null)
|
||||||
|
{
|
||||||
|
foreach (SubgroupVM vm in e.OldItems)
|
||||||
|
{
|
||||||
|
foreach (ClassVM cvm in Classes.Where(x => x.Group == vm))
|
||||||
|
{
|
||||||
|
cvm.Group = null;
|
||||||
|
}
|
||||||
|
foreach (GroupVM gvm in Groups.Where(x => x.AssignedSubgroups.Contains(vm)))
|
||||||
|
{
|
||||||
|
gvm.RemoveSubgroup(vm);
|
||||||
|
}
|
||||||
|
_project.Subgroups.Remove(vm.Subgroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.NewItems is not null)
|
||||||
|
{
|
||||||
|
foreach (SubgroupVM vm in e.NewItems)
|
||||||
|
{
|
||||||
|
_project.Subgroups.Add(vm.Subgroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Classes_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.OldItems is not null)
|
||||||
|
{
|
||||||
|
foreach (ClassVM vm in e.OldItems)
|
||||||
|
{
|
||||||
|
_project.Classes.Remove(vm.Class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.NewItems is not null)
|
||||||
|
{
|
||||||
|
foreach (ClassVM vm in e.NewItems)
|
||||||
|
{
|
||||||
|
_project.Classes.Add(vm.Class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using TimetableDesigner.Core;
|
|
||||||
|
|
||||||
namespace TimetableDesigner.ViewModels.Models
|
|
||||||
{
|
|
||||||
public class ProjectViewModel : BaseModelViewModel
|
|
||||||
{
|
|
||||||
#region FIELDS
|
|
||||||
|
|
||||||
private Project _project;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region PROPERTIES
|
|
||||||
|
|
||||||
public Project Project => _project;
|
|
||||||
|
|
||||||
public string Name
|
|
||||||
{
|
|
||||||
get => Project.Name;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (Project.Name != value)
|
|
||||||
{
|
|
||||||
Project.Name = value;
|
|
||||||
NotifyPropertyChanged(nameof(Name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public string Author
|
|
||||||
{
|
|
||||||
get => Project.Author;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (Project.Author != value)
|
|
||||||
{
|
|
||||||
Project.Author = value;
|
|
||||||
NotifyPropertyChanged(nameof(Author));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public string Description
|
|
||||||
{
|
|
||||||
get => Project.Description;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (Project.Description != value)
|
|
||||||
{
|
|
||||||
Project.Description = value;
|
|
||||||
NotifyPropertyChanged(nameof(Description));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public TimetableTemplateViewModel TimetableTemplate { get; set; }
|
|
||||||
public ObservableCollection<ClassroomViewModel> Classrooms { get; set; }
|
|
||||||
public ObservableCollection<TeacherViewModel> Teachers { get; set; }
|
|
||||||
public ObservableCollection<GroupViewModel> Groups { get; set; }
|
|
||||||
public ObservableCollection<SubgroupViewModel> Subgroups { get; set; }
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region CONSTRUCTORS
|
|
||||||
|
|
||||||
public ProjectViewModel(Project project)
|
|
||||||
{
|
|
||||||
_project = project;
|
|
||||||
|
|
||||||
TimetableTemplate = new TimetableTemplateViewModel(_project.TimetableTemplate);
|
|
||||||
|
|
||||||
Classrooms = new ObservableCollection<ClassroomViewModel>();
|
|
||||||
Classrooms.CollectionChanged += Classrooms_CollectionChanged;
|
|
||||||
|
|
||||||
Teachers = new ObservableCollection<TeacherViewModel>();
|
|
||||||
Teachers.CollectionChanged += Teachers_CollectionChanged;
|
|
||||||
|
|
||||||
Groups = new ObservableCollection<GroupViewModel>();
|
|
||||||
Groups.CollectionChanged += Groups_CollectionChanged;
|
|
||||||
|
|
||||||
Subgroups = new ObservableCollection<SubgroupViewModel>();
|
|
||||||
Subgroups.CollectionChanged += Subgroups_CollectionChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region PRIVATE METHODS
|
|
||||||
|
|
||||||
private void Classrooms_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
|
||||||
{
|
|
||||||
IList<ClassroomViewModel>? added = e.NewItems as IList<ClassroomViewModel>;
|
|
||||||
IList<ClassroomViewModel>? removed = e.OldItems as IList<ClassroomViewModel>;
|
|
||||||
|
|
||||||
if (removed is not null)
|
|
||||||
{
|
|
||||||
foreach (ClassroomViewModel vm in removed)
|
|
||||||
{
|
|
||||||
_project.Classrooms.Remove(vm.Classroom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (added is not null)
|
|
||||||
{
|
|
||||||
foreach (ClassroomViewModel vm in added)
|
|
||||||
{
|
|
||||||
_project.Classrooms.Add(vm.Classroom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Teachers_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
|
||||||
{
|
|
||||||
IList<TeacherViewModel>? added = e.NewItems as IList<TeacherViewModel>;
|
|
||||||
IList<TeacherViewModel>? removed = e.OldItems as IList<TeacherViewModel>;
|
|
||||||
|
|
||||||
if (removed is not null)
|
|
||||||
{
|
|
||||||
foreach (TeacherViewModel vm in removed)
|
|
||||||
{
|
|
||||||
_project.Teachers.Remove(vm.Teacher);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (added is not null)
|
|
||||||
{
|
|
||||||
foreach (TeacherViewModel vm in added)
|
|
||||||
{
|
|
||||||
_project.Teachers.Add(vm.Teacher);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Groups_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
|
||||||
{
|
|
||||||
IList<GroupViewModel>? added = e.NewItems as IList<GroupViewModel>;
|
|
||||||
IList<GroupViewModel>? removed = e.OldItems as IList<GroupViewModel>;
|
|
||||||
|
|
||||||
if (removed is not null)
|
|
||||||
{
|
|
||||||
foreach (GroupViewModel vm in removed)
|
|
||||||
{
|
|
||||||
_project.Groups.Remove(vm.Group);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (added is not null)
|
|
||||||
{
|
|
||||||
foreach (GroupViewModel vm in added)
|
|
||||||
{
|
|
||||||
_project.Groups.Add(vm.Group);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Subgroups_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
|
||||||
{
|
|
||||||
IList<SubgroupViewModel>? added = e.NewItems as IList<SubgroupViewModel>;
|
|
||||||
IList<SubgroupViewModel>? removed = e.OldItems as IList<SubgroupViewModel>;
|
|
||||||
|
|
||||||
if (removed is not null)
|
|
||||||
{
|
|
||||||
foreach (SubgroupViewModel vm in removed)
|
|
||||||
{
|
|
||||||
_project.Subgroups.Remove(vm.Subgroup);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (added is not null)
|
|
||||||
{
|
|
||||||
foreach (SubgroupViewModel vm in added)
|
|
||||||
{
|
|
||||||
_project.Subgroups.Add(vm.Subgroup);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
29
TimetableDesigner/ViewModels/Models/SubgroupVM.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TimetableDesigner.Core;
|
||||||
|
using TimetableDesigner.Customs;
|
||||||
|
using TimetableDesigner.ViewModels.Models.Base;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.ViewModels.Models
|
||||||
|
{
|
||||||
|
public class SubgroupVM : BaseGroupVM, IRemovableVM
|
||||||
|
{
|
||||||
|
#region PROPERTIES
|
||||||
|
|
||||||
|
public Subgroup Subgroup => (Subgroup)_baseGroup;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public SubgroupVM(Subgroup subgroup) : base(subgroup)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using TimetableDesigner.Core;
|
|
||||||
|
|
||||||
namespace TimetableDesigner.ViewModels.Models
|
|
||||||
{
|
|
||||||
public class SubgroupViewModel : BaseModelViewModel, IGroupViewModel
|
|
||||||
{
|
|
||||||
#region FIELDS
|
|
||||||
|
|
||||||
private Subgroup _subgroup;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region PROPERTIES
|
|
||||||
|
|
||||||
IGroup IGroupViewModel.Group => _subgroup;
|
|
||||||
public Subgroup Subgroup => _subgroup;
|
|
||||||
|
|
||||||
public string Name
|
|
||||||
{
|
|
||||||
get => _subgroup.Name;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_subgroup.Name != value)
|
|
||||||
{
|
|
||||||
_subgroup.Name = value;
|
|
||||||
NotifyPropertyChanged(nameof(Name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region CONSTRUCTORS
|
|
||||||
|
|
||||||
public SubgroupViewModel(Subgroup subgroup)
|
|
||||||
{
|
|
||||||
_subgroup = subgroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,13 +6,16 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using TimetableDesigner.Core;
|
using TimetableDesigner.Core;
|
||||||
using TimetableDesigner.Customs;
|
using TimetableDesigner.Customs;
|
||||||
|
using TimetableDesigner.Services.Project;
|
||||||
|
using TimetableDesigner.ViewModels.Models.Base;
|
||||||
|
|
||||||
namespace TimetableDesigner.ViewModels.Models
|
namespace TimetableDesigner.ViewModels.Models
|
||||||
{
|
{
|
||||||
public class TeacherViewModel : BaseModelViewModel
|
public class TeacherVM : ObservableObject, IModelVM, IUnitVM, IRemovableVM
|
||||||
{
|
{
|
||||||
#region FIELDS
|
#region FIELDS
|
||||||
|
|
||||||
|
private IProjectService _projectService;
|
||||||
private Teacher _teacher;
|
private Teacher _teacher;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -21,6 +24,7 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
|
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
|
IUnit IUnitVM.Unit => _teacher;
|
||||||
public Teacher Teacher => _teacher;
|
public Teacher Teacher => _teacher;
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
@@ -55,8 +59,9 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
|
|
||||||
#region CONSTRUCTORS
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
public TeacherViewModel(Teacher teacher)
|
public TeacherVM(Teacher teacher)
|
||||||
{
|
{
|
||||||
|
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
|
||||||
_teacher = teacher;
|
_teacher = teacher;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +77,9 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
{
|
{
|
||||||
Teacher.AvailabilityHours.Add(day, new TimetableSpanCollection());
|
Teacher.AvailabilityHours.Add(day, new TimetableSpanCollection());
|
||||||
NotifyPropertyChanged(nameof(AvailabilityHours));
|
NotifyPropertyChanged(nameof(AvailabilityHours));
|
||||||
|
|
||||||
|
//REFRESH: Errors
|
||||||
|
_projectService.RefreshErrors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +87,9 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
{
|
{
|
||||||
Teacher.AvailabilityHours.Remove(day);
|
Teacher.AvailabilityHours.Remove(day);
|
||||||
NotifyPropertyChanged(nameof(AvailabilityHours));
|
NotifyPropertyChanged(nameof(AvailabilityHours));
|
||||||
|
|
||||||
|
//REFRESH: Errors
|
||||||
|
_projectService.RefreshErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddHours(TimetableDay day, TimetableSpan hours)
|
public void AddHours(TimetableDay day, TimetableSpan hours)
|
||||||
@@ -87,6 +98,9 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
{
|
{
|
||||||
Teacher.AvailabilityHours[day].Add(hours);
|
Teacher.AvailabilityHours[day].Add(hours);
|
||||||
NotifyPropertyChanged(nameof(AvailabilityHours));
|
NotifyPropertyChanged(nameof(AvailabilityHours));
|
||||||
|
|
||||||
|
//REFRESH: Errors
|
||||||
|
_projectService.RefreshErrors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +110,9 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
{
|
{
|
||||||
Teacher.AvailabilityHours[day].Remove(hours);
|
Teacher.AvailabilityHours[day].Remove(hours);
|
||||||
NotifyPropertyChanged(nameof(AvailabilityHours));
|
NotifyPropertyChanged(nameof(AvailabilityHours));
|
||||||
|
|
||||||
|
//REFRESH: Errors
|
||||||
|
_projectService.RefreshErrors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5,10 +5,11 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using TimetableDesigner.Core;
|
using TimetableDesigner.Core;
|
||||||
|
using TimetableDesigner.Customs;
|
||||||
|
|
||||||
namespace TimetableDesigner.ViewModels.Models
|
namespace TimetableDesigner.ViewModels.Models
|
||||||
{
|
{
|
||||||
public class TimetableTemplateViewModel : BaseModelViewModel
|
public class TimetableTemplateVM : ObservableObject, IModelVM
|
||||||
{
|
{
|
||||||
#region FIELDS
|
#region FIELDS
|
||||||
|
|
||||||
@@ -31,7 +32,7 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
|
|
||||||
#region CONSTRUCTORS
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
public TimetableTemplateViewModel(TimetableTemplate timetableTemplate)
|
public TimetableTemplateVM(TimetableTemplate timetableTemplate)
|
||||||
{
|
{
|
||||||
_timetableTemplate = timetableTemplate;
|
_timetableTemplate = timetableTemplate;
|
||||||
}
|
}
|
||||||
@@ -44,25 +45,25 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
|
|
||||||
public void AddDay(TimetableDay day)
|
public void AddDay(TimetableDay day)
|
||||||
{
|
{
|
||||||
_timetableTemplate.AddDay(day);
|
_timetableTemplate.Days.Add(day);
|
||||||
NotifyPropertyChanged(nameof(Days));
|
NotifyPropertyChanged(nameof(Days));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveDay(TimetableDay day)
|
public void RemoveDay(TimetableDay day)
|
||||||
{
|
{
|
||||||
_timetableTemplate.RemoveDay(day);
|
_timetableTemplate.Days.Remove(day);
|
||||||
NotifyPropertyChanged(nameof(Days));
|
NotifyPropertyChanged(nameof(Days));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddSlot(TimetableSpan slot)
|
public void AddSlot(TimetableSpan slot)
|
||||||
{
|
{
|
||||||
_timetableTemplate.AddSlot(slot);
|
_timetableTemplate.Slots.Add(slot);
|
||||||
NotifyPropertyChanged(nameof(Slots));
|
NotifyPropertyChanged(nameof(Slots));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveSlot(TimetableSpan slot)
|
public void RemoveSlot(TimetableSpan slot)
|
||||||
{
|
{
|
||||||
_timetableTemplate.RemoveSlot(slot);
|
_timetableTemplate.Slots.Remove(slot);
|
||||||
NotifyPropertyChanged(nameof(Slots));
|
NotifyPropertyChanged(nameof(Slots));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9,14 +9,15 @@ using TimetableDesigner.Properties;
|
|||||||
using TimetableDesigner.Services;
|
using TimetableDesigner.Services;
|
||||||
using TimetableDesigner.Services.TabNavigation;
|
using TimetableDesigner.Services.TabNavigation;
|
||||||
using TimetableDesigner.ViewModels.Models;
|
using TimetableDesigner.ViewModels.Models;
|
||||||
|
using TimetableDesigner.ViewModels.Models.Base;
|
||||||
|
|
||||||
namespace TimetableDesigner.ViewModels.Views
|
namespace TimetableDesigner.ViewModels.Views
|
||||||
{
|
{
|
||||||
public class ClassroomEditViewModel : BaseViewViewModel
|
public class ClassroomEditorViewVM : ObservableObject, IViewVM, IUnitEditorViewVM
|
||||||
{
|
{
|
||||||
#region FIELDS
|
#region FIELDS
|
||||||
|
|
||||||
private ClassroomViewModel _classroom;
|
private ClassroomVM _classroom;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -24,7 +25,8 @@ namespace TimetableDesigner.ViewModels.Views
|
|||||||
|
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
public ClassroomViewModel Classroom
|
IUnitVM IUnitEditorViewVM.Unit => Classroom;
|
||||||
|
public ClassroomVM Classroom
|
||||||
{
|
{
|
||||||
get => _classroom;
|
get => _classroom;
|
||||||
set
|
set
|
||||||
@@ -62,10 +64,10 @@ namespace TimetableDesigner.ViewModels.Views
|
|||||||
|
|
||||||
#region CONSTRUCTORS
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
public ClassroomEditViewModel() : this(new ClassroomViewModel(new Classroom()))
|
public ClassroomEditorViewVM() : this(new ClassroomVM(new Classroom()))
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public ClassroomEditViewModel(ClassroomViewModel classroom)
|
public ClassroomEditorViewVM(ClassroomVM classroom)
|
||||||
{
|
{
|
||||||
_classroom = classroom;
|
_classroom = classroom;
|
||||||
}
|
}
|
||||||
@@ -14,17 +14,18 @@ using System.Windows.Input;
|
|||||||
using TimetableDesigner.Commands;
|
using TimetableDesigner.Commands;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using TimetableDesigner.Services.MessageBox;
|
using TimetableDesigner.Services.MessageBox;
|
||||||
|
using TimetableDesigner.ViewModels.Models.Base;
|
||||||
|
|
||||||
namespace TimetableDesigner.ViewModels.Views
|
namespace TimetableDesigner.ViewModels.Views
|
||||||
{
|
{
|
||||||
public class GroupEditViewModel : BaseViewViewModel
|
public class GroupEditorViewVM : ObservableObject, IViewVM, IUnitEditorViewVM
|
||||||
{
|
{
|
||||||
#region FIELDS
|
#region FIELDS
|
||||||
|
|
||||||
private IProjectService _projectService;
|
private IProjectService _projectService;
|
||||||
private IMessageBoxService _messageBoxService;
|
private IMessageBoxService _messageBoxService;
|
||||||
|
|
||||||
private GroupViewModel _group;
|
private GroupVM _group;
|
||||||
|
|
||||||
private string _newSubgroupName;
|
private string _newSubgroupName;
|
||||||
|
|
||||||
@@ -34,7 +35,8 @@ namespace TimetableDesigner.ViewModels.Views
|
|||||||
|
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
public GroupViewModel Group
|
IUnitVM IUnitEditorViewVM.Unit => Group;
|
||||||
|
public GroupVM Group
|
||||||
{
|
{
|
||||||
get => _group;
|
get => _group;
|
||||||
set
|
set
|
||||||
@@ -66,7 +68,7 @@ namespace TimetableDesigner.ViewModels.Views
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObservableDictionary<SubgroupViewModel, bool> Subgroups => new ObservableDictionary<SubgroupViewModel, bool>(_projectService.ProjectViewModel.Subgroups.ToDictionary(sg => sg, Group.AssignedSubgroups.Contains));
|
public ObservableDictionary<SubgroupVM, bool> Subgroups => new ObservableDictionary<SubgroupVM, bool>(_projectService.ProjectViewModel.Subgroups.ToDictionary(sg => sg, Group.AssignedSubgroups.Contains));
|
||||||
|
|
||||||
public string NewSubgroupName
|
public string NewSubgroupName
|
||||||
{
|
{
|
||||||
@@ -91,10 +93,10 @@ namespace TimetableDesigner.ViewModels.Views
|
|||||||
|
|
||||||
#region CONSTRUCTORS
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
public GroupEditViewModel() : this(new GroupViewModel(new Group()))
|
public GroupEditorViewVM() : this(new GroupVM(new Group()))
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public GroupEditViewModel(GroupViewModel group)
|
public GroupEditorViewVM(GroupVM group)
|
||||||
{
|
{
|
||||||
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
|
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
|
||||||
_messageBoxService = ServiceProvider.Instance.GetService<IMessageBoxService>();
|
_messageBoxService = ServiceProvider.Instance.GetService<IMessageBoxService>();
|
||||||
@@ -103,8 +105,8 @@ namespace TimetableDesigner.ViewModels.Views
|
|||||||
_newSubgroupName = string.Empty;
|
_newSubgroupName = string.Empty;
|
||||||
|
|
||||||
AddSubgroupCommand = new RelayCommand<object>(args => AddSubgroup());
|
AddSubgroupCommand = new RelayCommand<object>(args => AddSubgroup());
|
||||||
EditSubgroupAssignmentCommand = new RelayCommand<SubgroupViewModel>(EditSubgroupAssignment);
|
EditSubgroupAssignmentCommand = new RelayCommand<SubgroupVM>(EditSubgroupAssignment);
|
||||||
DeleteSubgroupCommand = new RelayCommand<SubgroupViewModel>(DeleteSubgroup);
|
DeleteSubgroupCommand = new RelayCommand<SubgroupVM>(DeleteSubgroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -119,7 +121,7 @@ namespace TimetableDesigner.ViewModels.Views
|
|||||||
{
|
{
|
||||||
Name = NewSubgroupName
|
Name = NewSubgroupName
|
||||||
};
|
};
|
||||||
SubgroupViewModel subgroupViewModel = new SubgroupViewModel(subgroup);
|
SubgroupVM subgroupViewModel = new SubgroupVM(subgroup);
|
||||||
|
|
||||||
_projectService.ProjectViewModel.Subgroups.Add(subgroupViewModel);
|
_projectService.ProjectViewModel.Subgroups.Add(subgroupViewModel);
|
||||||
Group.AddSubgroup(subgroupViewModel);
|
Group.AddSubgroup(subgroupViewModel);
|
||||||
@@ -128,7 +130,7 @@ namespace TimetableDesigner.ViewModels.Views
|
|||||||
NewSubgroupName = string.Empty;
|
NewSubgroupName = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EditSubgroupAssignment(SubgroupViewModel subgroup)
|
private void EditSubgroupAssignment(SubgroupVM subgroup)
|
||||||
{
|
{
|
||||||
bool assigned = Subgroups[subgroup];
|
bool assigned = Subgroups[subgroup];
|
||||||
if (assigned)
|
if (assigned)
|
||||||
@@ -142,12 +144,12 @@ namespace TimetableDesigner.ViewModels.Views
|
|||||||
NotifyPropertyChanged(nameof(Subgroups));
|
NotifyPropertyChanged(nameof(Subgroups));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DeleteSubgroup(SubgroupViewModel subgroup)
|
private void DeleteSubgroup(SubgroupVM subgroup)
|
||||||
{
|
{
|
||||||
MessageBoxQuestionResult result = _messageBoxService.ShowQuestion(Resources.GroupEdit_Message_SubgroupDelete, true);
|
MessageBoxQuestionResult result = _messageBoxService.ShowQuestion(Resources.GroupEdit_Message_SubgroupDelete, true);
|
||||||
if (result == MessageBoxQuestionResult.Yes)
|
if (result == MessageBoxQuestionResult.Yes)
|
||||||
{
|
{
|
||||||
foreach (GroupViewModel group in _projectService.ProjectViewModel.Groups)
|
foreach (GroupVM group in _projectService.ProjectViewModel.Groups)
|
||||||
{
|
{
|
||||||
group.RemoveSubgroup(subgroup);
|
group.RemoveSubgroup(subgroup);
|
||||||
}
|
}
|
||||||
@@ -1,271 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using TimetableDesigner.Commands;
|
|
||||||
using System.Windows.Navigation;
|
|
||||||
using TimetableDesigner.Core;
|
|
||||||
using System.Windows;
|
|
||||||
using TimetableDesigner.Properties;
|
|
||||||
using System.Reflection;
|
|
||||||
using TimetableDesigner.ViewModels.Models;
|
|
||||||
using System.Windows.Data;
|
|
||||||
using TimetableDesigner.Services.MessageBox;
|
|
||||||
using System.ComponentModel.Design;
|
|
||||||
using TimetableDesigner.Services;
|
|
||||||
using TimetableDesigner.Services.TabNavigation;
|
|
||||||
using TimetableDesigner.Services.Project;
|
|
||||||
using System.Drawing;
|
|
||||||
|
|
||||||
namespace TimetableDesigner.ViewModels.Views
|
|
||||||
{
|
|
||||||
class MainViewModel : BaseViewViewModel
|
|
||||||
{
|
|
||||||
#region FIELDS
|
|
||||||
|
|
||||||
private IMessageBoxService _messageBoxService;
|
|
||||||
private ITabNavigationService _tabNavigationService;
|
|
||||||
private IProjectService _projectService;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region PROPERTIES
|
|
||||||
|
|
||||||
// Observable services
|
|
||||||
public IProjectService ProjectService => _projectService;
|
|
||||||
public ITabNavigationService TabNavigationService => _tabNavigationService;
|
|
||||||
|
|
||||||
// Tabs
|
|
||||||
public ObservableCollection<TabItem> Tabs => _tabNavigationService.Tabs;
|
|
||||||
public TabItem SelectedTab => _tabNavigationService.SelectedTab;
|
|
||||||
|
|
||||||
// Commands
|
|
||||||
public ICommand NewProjectCommand { get; set; }
|
|
||||||
public ICommand OpenProjectCommand { get; set; }
|
|
||||||
public ICommand ProjectSettingsCommand { get; set; }
|
|
||||||
public ICommand NewClassroomCommand { get; set; }
|
|
||||||
public ICommand EditClassroomCommand { get; set; }
|
|
||||||
public ICommand RemoveClassroomCommand { get; set; }
|
|
||||||
public ICommand NewTeacherCommand { get; set; }
|
|
||||||
public ICommand EditTeacherCommand { get; set; }
|
|
||||||
public ICommand RemoveTeacherCommand { get; set; }
|
|
||||||
public ICommand NewGroupCommand { get; set; }
|
|
||||||
public ICommand EditGroupCommand { get; set; }
|
|
||||||
public ICommand RemoveGroupCommand { get; set; }
|
|
||||||
public ICommand RemoveSubgroupCommand { get; set; }
|
|
||||||
|
|
||||||
// Others
|
|
||||||
public string Version { get; set; }
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region CONSTRUCTORS
|
|
||||||
|
|
||||||
public MainViewModel()
|
|
||||||
{
|
|
||||||
_messageBoxService = ServiceProvider.Instance.GetService<IMessageBoxService>();
|
|
||||||
_tabNavigationService = ServiceProvider.Instance.GetService<ITabNavigationService>();
|
|
||||||
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
|
|
||||||
|
|
||||||
NewProjectCommand = new RelayCommand<object>(param => NewProject());
|
|
||||||
OpenProjectCommand = new RelayCommand<object>(param => OpenProject());
|
|
||||||
ProjectSettingsCommand = new RelayCommand<object>(param => ProjectSettings());
|
|
||||||
NewClassroomCommand = new RelayCommand<object>(param => NewClassroom());
|
|
||||||
EditClassroomCommand = new RelayCommand<ClassroomViewModel>(EditClassroom);
|
|
||||||
RemoveClassroomCommand = new RelayCommand<ClassroomViewModel>(DeleteClassroom);
|
|
||||||
NewTeacherCommand = new RelayCommand<object>(param => NewTeacher());
|
|
||||||
EditTeacherCommand = new RelayCommand<TeacherViewModel>(EditTeacher);
|
|
||||||
RemoveTeacherCommand = new RelayCommand<TeacherViewModel>(DeleteTeacher);
|
|
||||||
NewGroupCommand = new RelayCommand<object>(param => NewGroup());
|
|
||||||
EditGroupCommand = new RelayCommand<GroupViewModel>(EditGroup);
|
|
||||||
RemoveGroupCommand = new RelayCommand<GroupViewModel>(DeleteGroup);
|
|
||||||
RemoveSubgroupCommand = new RelayCommand<SubgroupViewModel>(DeleteSubgroup);
|
|
||||||
|
|
||||||
Version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
|
||||||
|
|
||||||
TabItem welcomeTab = new TabItem()
|
|
||||||
{
|
|
||||||
Title = Resources.Tabs_Welcome,
|
|
||||||
ViewModel = new WelcomeViewModel()
|
|
||||||
};
|
|
||||||
_tabNavigationService.AddAndActivate(welcomeTab);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region PRIVATE METHODS
|
|
||||||
|
|
||||||
private void OpenProject()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private void NewProject()
|
|
||||||
{
|
|
||||||
if (ProjectService.ProjectViewModel is not null)
|
|
||||||
{
|
|
||||||
MessageBoxQuestionResult result = _messageBoxService.ShowQuestion(Resources.Main_Message_SaveCurrentProject);
|
|
||||||
|
|
||||||
switch (result)
|
|
||||||
{
|
|
||||||
case MessageBoxQuestionResult.Yes: break;
|
|
||||||
case MessageBoxQuestionResult.No: break;
|
|
||||||
default: return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_tabNavigationService.CloseAll();
|
|
||||||
_projectService.New();
|
|
||||||
ProjectSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ProjectSettings()
|
|
||||||
{
|
|
||||||
if (ProjectService.ProjectViewModel is not null)
|
|
||||||
{
|
|
||||||
TabItem projectSettingsTab = new TabItem()
|
|
||||||
{
|
|
||||||
Title = Resources.Tabs_ProjectSettings,
|
|
||||||
IsClosable = true,
|
|
||||||
ViewModel = new ProjectSettingsViewModel()
|
|
||||||
};
|
|
||||||
_tabNavigationService.AddAndActivate(projectSettingsTab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void NewClassroom()
|
|
||||||
{
|
|
||||||
if (ProjectService.ProjectViewModel is not null)
|
|
||||||
{
|
|
||||||
Classroom classroom = new Classroom()
|
|
||||||
{
|
|
||||||
Name = Resources.Global_DefaultClassroomName
|
|
||||||
};
|
|
||||||
ClassroomViewModel classroomVM = new ClassroomViewModel(classroom);
|
|
||||||
ProjectService.ProjectViewModel.Classrooms.Add(classroomVM);
|
|
||||||
EditClassroom(classroomVM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void EditClassroom(ClassroomViewModel classroomViewModel)
|
|
||||||
{
|
|
||||||
if (ProjectService.ProjectViewModel is not null)
|
|
||||||
{
|
|
||||||
TabItem classroomEditTab = new TabItem()
|
|
||||||
{
|
|
||||||
Title = $"{Resources.Tabs_ClassroomEdit}: {classroomViewModel.Name}",
|
|
||||||
IsClosable = true,
|
|
||||||
ViewModel = new ClassroomEditViewModel(classroomViewModel)
|
|
||||||
};
|
|
||||||
_tabNavigationService.AddAndActivate(classroomEditTab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DeleteClassroom(ClassroomViewModel classroomViewModel)
|
|
||||||
{
|
|
||||||
if (ProjectService.ProjectViewModel is not null)
|
|
||||||
{
|
|
||||||
ProjectService.ProjectViewModel.Classrooms.Remove(classroomViewModel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void NewTeacher()
|
|
||||||
{
|
|
||||||
if (ProjectService.ProjectViewModel is not null)
|
|
||||||
{
|
|
||||||
Teacher teacher = new Teacher()
|
|
||||||
{
|
|
||||||
Name = Resources.Global_DefaultTeacherName
|
|
||||||
};
|
|
||||||
TeacherViewModel teacherVM = new TeacherViewModel(teacher);
|
|
||||||
ProjectService.ProjectViewModel.Teachers.Add(teacherVM);
|
|
||||||
EditTeacher(teacherVM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void EditTeacher(TeacherViewModel teacherViewModel)
|
|
||||||
{
|
|
||||||
if (ProjectService.ProjectViewModel is not null)
|
|
||||||
{
|
|
||||||
TabItem teacherEditTab = new TabItem()
|
|
||||||
{
|
|
||||||
Title = $"{Resources.Tabs_TeacherEdit}: {teacherViewModel.Name}",
|
|
||||||
IsClosable = true,
|
|
||||||
ViewModel = new TeacherEditViewModel(teacherViewModel)
|
|
||||||
};
|
|
||||||
_tabNavigationService.AddAndActivate(teacherEditTab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DeleteTeacher(TeacherViewModel teacherViewModel)
|
|
||||||
{
|
|
||||||
if (ProjectService.ProjectViewModel is not null)
|
|
||||||
{
|
|
||||||
ProjectService.ProjectViewModel.Teachers.Remove(teacherViewModel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void NewGroup()
|
|
||||||
{
|
|
||||||
if (ProjectService.ProjectViewModel is not null)
|
|
||||||
{
|
|
||||||
Group group = new Group()
|
|
||||||
{
|
|
||||||
Name = Resources.Global_DefaultGroupName
|
|
||||||
};
|
|
||||||
GroupViewModel groupVM = new GroupViewModel(group);
|
|
||||||
ProjectService.ProjectViewModel.Groups.Add(groupVM);
|
|
||||||
EditGroup(groupVM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void EditGroup(GroupViewModel groupViewModel)
|
|
||||||
{
|
|
||||||
if (ProjectService.ProjectViewModel is not null)
|
|
||||||
{
|
|
||||||
TabItem groupEditTab = new TabItem()
|
|
||||||
{
|
|
||||||
Title = $"{Resources.Tabs_GroupEdit}: {groupViewModel.Name}",
|
|
||||||
IsClosable = true,
|
|
||||||
ViewModel = new GroupEditViewModel(groupViewModel)
|
|
||||||
};
|
|
||||||
_tabNavigationService.AddAndActivate(groupEditTab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DeleteGroup(GroupViewModel groupViewModel)
|
|
||||||
{
|
|
||||||
if (ProjectService.ProjectViewModel is not null)
|
|
||||||
{
|
|
||||||
ProjectService.ProjectViewModel.Groups.Remove(groupViewModel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DeleteSubgroup(SubgroupViewModel subgroupViewModel)
|
|
||||||
{
|
|
||||||
if (ProjectService.ProjectViewModel is not null)
|
|
||||||
{
|
|
||||||
MessageBoxQuestionResult result = _messageBoxService.ShowQuestion(Resources.Main_Treeview_Subgroups_Message_Remove, true);
|
|
||||||
if (result == MessageBoxQuestionResult.Yes)
|
|
||||||
{
|
|
||||||
foreach (GroupViewModel group in ProjectService.ProjectViewModel.Groups)
|
|
||||||
{
|
|
||||||
group.RemoveSubgroup(subgroupViewModel);
|
|
||||||
}
|
|
||||||
_projectService.ProjectViewModel.Subgroups.Remove(subgroupViewModel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
387
TimetableDesigner/ViewModels/Views/MainWindowVM.cs
Normal file
@@ -0,0 +1,387 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using TimetableDesigner.Commands;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
using TimetableDesigner.Core;
|
||||||
|
using System.Windows;
|
||||||
|
using TimetableDesigner.Properties;
|
||||||
|
using System.Reflection;
|
||||||
|
using TimetableDesigner.ViewModels.Models;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using TimetableDesigner.Services.MessageBox;
|
||||||
|
using System.ComponentModel.Design;
|
||||||
|
using TimetableDesigner.Services;
|
||||||
|
using TimetableDesigner.Services.TabNavigation;
|
||||||
|
using TimetableDesigner.Services.Project;
|
||||||
|
using System.Drawing;
|
||||||
|
using TimetableDesigner.ViewModels.Models.Base;
|
||||||
|
using System.Collections;
|
||||||
|
using TimetableDesigner.Customs;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TimetableDesigner.Services.FileDialog;
|
||||||
|
using TimetableDesigner.Services.Scheduler;
|
||||||
|
using static TimetableDesigner.ViewModels.Views.TimetableEditorViewVM;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.ViewModels.Views
|
||||||
|
{
|
||||||
|
class MainWindowVM : ObservableObject, IViewVM
|
||||||
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private IMessageBoxService _messageBoxService;
|
||||||
|
private IFileDialogService _fileDialogService;
|
||||||
|
private ITabNavigationService _tabNavigationService;
|
||||||
|
private IProjectService _projectService;
|
||||||
|
private ISchedulerService _schedulerService;
|
||||||
|
|
||||||
|
private IDictionary<string, IEnumerable<string>> _projectFileTypes = new Dictionary<string, IEnumerable<string>>()
|
||||||
|
{
|
||||||
|
{ Resources.Global_ProjectFiletypeDescription, new List<string>() { "ttdp" } }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PROPERTIES
|
||||||
|
|
||||||
|
// Observable services
|
||||||
|
public IProjectService ProjectService => _projectService;
|
||||||
|
public ITabNavigationService TabNavigationService => _tabNavigationService;
|
||||||
|
|
||||||
|
// Tabs
|
||||||
|
public ObservableCollection<TabItem> Tabs => _tabNavigationService.Tabs;
|
||||||
|
public TabItem SelectedTab => _tabNavigationService.SelectedTab;
|
||||||
|
|
||||||
|
// Commands
|
||||||
|
public ICommand NewProjectCommand { get; set; }
|
||||||
|
public ICommand OpenProjectCommand { get; set; }
|
||||||
|
public ICommand OpenRecentProjectCommand { get; set; }
|
||||||
|
public ICommand SaveProjectCommand { get; set; }
|
||||||
|
public ICommand SaveAsProjectCommand { get; set; }
|
||||||
|
public ICommand ProjectSettingsCommand { get; set; }
|
||||||
|
public ICommand NewClassroomCommand { get; set; }
|
||||||
|
public ICommand NewTeacherCommand { get; set; }
|
||||||
|
public ICommand NewGroupCommand { get; set; }
|
||||||
|
public ICommand EditClassroomCommand { get; set; }
|
||||||
|
public ICommand EditTeacherCommand { get; set; }
|
||||||
|
public ICommand EditGroupCommand { get; set; }
|
||||||
|
public ICommand RemoveClassroomCommand { get; set; }
|
||||||
|
public ICommand RemoveTeacherCommand { get; set; }
|
||||||
|
public ICommand RemoveGroupCommand { get; set; }
|
||||||
|
public ICommand RemoveSubgroupCommand { get; set; }
|
||||||
|
public ICommand EditTimetableCommand { get; set; }
|
||||||
|
public ICommand AutoScheduleCommand { get; set; }
|
||||||
|
|
||||||
|
// Others
|
||||||
|
public string? Version { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public MainWindowVM()
|
||||||
|
{
|
||||||
|
_messageBoxService = ServiceProvider.Instance.GetService<IMessageBoxService>();
|
||||||
|
_fileDialogService = ServiceProvider.Instance.GetService<IFileDialogService>();
|
||||||
|
_tabNavigationService = ServiceProvider.Instance.GetService<ITabNavigationService>();
|
||||||
|
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
|
||||||
|
_schedulerService = ServiceProvider.Instance.GetService<ISchedulerService>();
|
||||||
|
|
||||||
|
NewProjectCommand = new RelayCommand<object>(param => NewProject());
|
||||||
|
OpenProjectCommand = new RelayCommand<object>(param => OpenProject());
|
||||||
|
OpenRecentProjectCommand = new RelayCommand<string>(OpenProject);
|
||||||
|
SaveProjectCommand = new RelayCommand<object>(param => SaveProject());
|
||||||
|
SaveAsProjectCommand = new RelayCommand<object>(param => SaveAsProject());
|
||||||
|
ProjectSettingsCommand = new RelayCommand<object>(param => ProjectSettings());
|
||||||
|
NewClassroomCommand = new RelayCommand<object>(param => NewClassroom());
|
||||||
|
NewTeacherCommand = new RelayCommand<object>(param => NewTeacher());
|
||||||
|
NewGroupCommand = new RelayCommand<object>(param => NewGroup());
|
||||||
|
EditClassroomCommand = new RelayCommand<ClassroomVM>(EditClassroom);
|
||||||
|
EditTeacherCommand = new RelayCommand<TeacherVM>(EditTeacher);
|
||||||
|
EditGroupCommand = new RelayCommand<GroupVM>(EditGroup);
|
||||||
|
RemoveClassroomCommand = new RelayCommand<ClassroomVM>(RemoveClassroom);
|
||||||
|
RemoveTeacherCommand = new RelayCommand<TeacherVM>(RemoveTeacher);
|
||||||
|
RemoveGroupCommand = new RelayCommand<GroupVM>(RemoveGroup);
|
||||||
|
RemoveSubgroupCommand = new RelayCommand<SubgroupVM>(RemoveSubgroup);
|
||||||
|
EditTimetableCommand = new RelayCommand<IUnitVM>(EditTimetable);
|
||||||
|
AutoScheduleCommand = new RelayCommand<object>(param => AutoSchedule());
|
||||||
|
|
||||||
|
Version = Assembly.GetExecutingAssembly().GetName().Version?.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PRIVATE METHODS
|
||||||
|
|
||||||
|
private void NewProject()
|
||||||
|
{
|
||||||
|
if (ProjectService.ProjectViewModel is not null)
|
||||||
|
{
|
||||||
|
MessageBoxQuestionResult result = _messageBoxService.ShowQuestion(Resources.Main_Message_SaveCurrentProject);
|
||||||
|
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case MessageBoxQuestionResult.Yes: SaveProject(); break;
|
||||||
|
case MessageBoxQuestionResult.No: break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_tabNavigationService.CloseAll();
|
||||||
|
_projectService.New();
|
||||||
|
ProjectSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OpenProject()
|
||||||
|
{
|
||||||
|
string? path = _fileDialogService.OpenFile(_projectFileTypes);
|
||||||
|
if (path is not null)
|
||||||
|
{
|
||||||
|
OpenProject(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OpenProject(string path)
|
||||||
|
{
|
||||||
|
if (ProjectService.ProjectViewModel is not null)
|
||||||
|
{
|
||||||
|
MessageBoxQuestionResult result = _messageBoxService.ShowQuestion(Resources.Main_Message_SaveCurrentProject);
|
||||||
|
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case MessageBoxQuestionResult.Yes: SaveProject(); break;
|
||||||
|
case MessageBoxQuestionResult.No: break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_projectService.Load(path);
|
||||||
|
_tabNavigationService.CloseAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveProject()
|
||||||
|
{
|
||||||
|
string? path = _projectService.SavePath;
|
||||||
|
if (_projectService.SavePath is null)
|
||||||
|
{
|
||||||
|
path = _fileDialogService.SaveFile(_projectFileTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path is not null)
|
||||||
|
{
|
||||||
|
_projectService.Save(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void SaveAsProject()
|
||||||
|
{
|
||||||
|
string? path = _fileDialogService.SaveFile(_projectFileTypes);
|
||||||
|
if (path is not null)
|
||||||
|
{
|
||||||
|
_projectService.Save(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProjectSettings()
|
||||||
|
{
|
||||||
|
if (ProjectService.ProjectViewModel is not null)
|
||||||
|
{
|
||||||
|
TabItem projectSettingsTab = new TabItem()
|
||||||
|
{
|
||||||
|
Title = Resources.Tabs_ProjectSettings,
|
||||||
|
IsClosable = true,
|
||||||
|
ViewModel = new ProjectSettingsViewVM()
|
||||||
|
};
|
||||||
|
_tabNavigationService.AddAndActivate(projectSettingsTab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NewClassroom()
|
||||||
|
{
|
||||||
|
if (ProjectService.ProjectViewModel is not null)
|
||||||
|
{
|
||||||
|
Classroom classroom = new Classroom()
|
||||||
|
{
|
||||||
|
Name = Resources.Global_DefaultClassroomName
|
||||||
|
};
|
||||||
|
ClassroomVM classroomVM = new ClassroomVM(classroom);
|
||||||
|
ProjectService.ProjectViewModel.Classrooms.Add(classroomVM);
|
||||||
|
EditClassroom(classroomVM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void NewTeacher()
|
||||||
|
{
|
||||||
|
if (ProjectService.ProjectViewModel is not null)
|
||||||
|
{
|
||||||
|
Teacher teacher = new Teacher()
|
||||||
|
{
|
||||||
|
Name = Resources.Global_DefaultTeacherName
|
||||||
|
};
|
||||||
|
TeacherVM teacherVM = new TeacherVM(teacher);
|
||||||
|
ProjectService.ProjectViewModel.Teachers.Add(teacherVM);
|
||||||
|
EditTeacher(teacherVM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void NewGroup()
|
||||||
|
{
|
||||||
|
if (ProjectService.ProjectViewModel is not null)
|
||||||
|
{
|
||||||
|
Group group = new Group()
|
||||||
|
{
|
||||||
|
Name = Resources.Global_DefaultGroupName
|
||||||
|
};
|
||||||
|
GroupVM groupVM = new GroupVM(group);
|
||||||
|
ProjectService.ProjectViewModel.Groups.Add(groupVM);
|
||||||
|
EditGroup(groupVM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EditClassroom(ClassroomVM classroom) => EditUnit(new ClassroomEditorViewVM(classroom), Resources.Tabs_ClassroomEdit);
|
||||||
|
private void EditTeacher(TeacherVM teacher) => EditUnit(new TeacherEditorViewVM(teacher), Resources.Tabs_TeacherEdit);
|
||||||
|
private void EditGroup(GroupVM group) => EditUnit(new GroupEditorViewVM(group), Resources.Tabs_GroupEdit);
|
||||||
|
private void EditUnit(IUnitEditorViewVM edit, string tabNamePrefix)
|
||||||
|
{
|
||||||
|
if (ProjectService.ProjectViewModel is not null)
|
||||||
|
{
|
||||||
|
TabItem groupEditTab = new TabItem()
|
||||||
|
{
|
||||||
|
Title = $"{tabNamePrefix}: {edit.Unit.Name}",
|
||||||
|
IsClosable = true,
|
||||||
|
ViewModel = edit
|
||||||
|
};
|
||||||
|
_tabNavigationService.AddAndActivate(groupEditTab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveClassroom(ClassroomVM classroom) => RemoveUnit(classroom, ProjectService.ProjectViewModel?.Classrooms, Resources.Main_Treeview_Classrooms_Message_Remove);
|
||||||
|
private void RemoveTeacher(TeacherVM teacher) => RemoveUnit(teacher, ProjectService.ProjectViewModel?.Teachers, Resources.Main_Treeview_Teachers_Message_Remove);
|
||||||
|
private void RemoveGroup(GroupVM group) => RemoveUnit(group, ProjectService.ProjectViewModel?.Groups, Resources.Main_Treeview_Groups_Message_Remove);
|
||||||
|
private void RemoveSubgroup(SubgroupVM subgroup) => RemoveUnit(subgroup, ProjectService.ProjectViewModel?.Subgroups, Resources.Main_Treeview_Subgroups_Message_Remove);
|
||||||
|
private void RemoveUnit(IRemovableVM unit, IList? collection, string questionMessage)
|
||||||
|
{
|
||||||
|
if (collection is not null)
|
||||||
|
{
|
||||||
|
MessageBoxQuestionResult result = _messageBoxService.ShowQuestion(questionMessage, true);
|
||||||
|
if (result == MessageBoxQuestionResult.Yes)
|
||||||
|
{
|
||||||
|
collection.Remove(unit);
|
||||||
|
_tabNavigationService.Close(_tabNavigationService.Tabs.Where(x => x.ViewModel is IUnitEditorViewVM model && model.Unit == unit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EditTimetable(IUnitVM classUnit)
|
||||||
|
{
|
||||||
|
if (ProjectService.ProjectViewModel is not null)
|
||||||
|
{
|
||||||
|
TabItem timetableEditTab = new TabItem()
|
||||||
|
{
|
||||||
|
Title = $"{Resources.Tabs_TimetableEdit}: {classUnit.Name}",
|
||||||
|
IsClosable = true,
|
||||||
|
ViewModel = new TimetableEditorViewVM(classUnit)
|
||||||
|
};
|
||||||
|
_tabNavigationService.AddAndActivate(timetableEditTab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AutoSchedule()
|
||||||
|
{
|
||||||
|
IEnumerable<ClassVM> unscheduledClasses = _projectService.ProjectViewModel.Classes.Where(x => x.Day is null || x.Slot is null);
|
||||||
|
if (unscheduledClasses.Any())
|
||||||
|
{
|
||||||
|
List<ClassVM> errors = new List<ClassVM>();
|
||||||
|
int successCount = 0;
|
||||||
|
foreach (ClassVM @class in unscheduledClasses)
|
||||||
|
{
|
||||||
|
(TimetableDay? day, TimetableSpan? slot) = _schedulerService.Schedule(@class);
|
||||||
|
if (day is not null && slot is not null)
|
||||||
|
{
|
||||||
|
@class.Day = day;
|
||||||
|
@class.Slot = slot;
|
||||||
|
successCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errors.Add(@class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//REFRESH: All editors & Errors
|
||||||
|
foreach (TimetableEditorViewVM editor in _tabNavigationService.Tabs.Select(x => x.ViewModel).OfType<TimetableEditorViewVM>().Distinct())
|
||||||
|
{
|
||||||
|
editor.RefreshClasses(RefreshMode.Scheduled | RefreshMode.Unscheduled);
|
||||||
|
}
|
||||||
|
_projectService.RefreshErrors();
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.Append($"{Resources.Main_Ribbon_Edit_Timetable_Autoschedule_Message_SuccessfullyScheduled}: {successCount}");
|
||||||
|
if (errors.Any())
|
||||||
|
{
|
||||||
|
sb.AppendLine();
|
||||||
|
sb.AppendLine();
|
||||||
|
sb.Append($"{Resources.Main_Ribbon_Edit_Timetable_Autoschedule_Message_FollowingClassesCouldNotBeScheduled}:");
|
||||||
|
sb.AppendLine();
|
||||||
|
int deleted = 0;
|
||||||
|
for (int i = 0; i < errors.Count && i < 5; i++)
|
||||||
|
{
|
||||||
|
ClassVM errorClass = errors[i];
|
||||||
|
string unit;
|
||||||
|
string unitName;
|
||||||
|
if (errorClass.Group is not null)
|
||||||
|
{
|
||||||
|
unit = Resources.Main_Ribbon_Edit_Timetable_Autoschedule_Message_UnitGroup;
|
||||||
|
unitName = errorClass.Group.Name;
|
||||||
|
}
|
||||||
|
else if (errorClass.Teacher is not null)
|
||||||
|
{
|
||||||
|
unit = Resources.Main_Ribbon_Edit_Timetable_Autoschedule_Message_UnitTeacher;
|
||||||
|
unitName = errorClass.Teacher.Name;
|
||||||
|
}
|
||||||
|
else if (errorClass.Classroom is not null)
|
||||||
|
{
|
||||||
|
unit = Resources.Main_Ribbon_Edit_Timetable_Autoschedule_Message_UnitClassroom;
|
||||||
|
unitName = errorClass.Classroom.Name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
deleted++;
|
||||||
|
i--;
|
||||||
|
_projectService.ProjectViewModel.Classes.Remove(errorClass);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sb.Append($"- {errorClass.Name} ({unit}: {unitName})");
|
||||||
|
sb.AppendLine();
|
||||||
|
}
|
||||||
|
if (errors.Count - deleted > 5)
|
||||||
|
{
|
||||||
|
sb.Append($"+ {errors.Count - deleted - 5} {Resources.Main_Ribbon_Edit_Timetable_Autoschedule_Message_More}");
|
||||||
|
}
|
||||||
|
|
||||||
|
_messageBoxService.ShowWarning(sb.ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_messageBoxService.ShowInformation(sb.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_messageBoxService.ShowInformation(Resources.Main_Ribbon_Edit_Timetable_Autoschedule_Message_NoUnscheduledClasses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,7 +19,7 @@ using TimetableDesigner.ViewModels.Models;
|
|||||||
|
|
||||||
namespace TimetableDesigner.ViewModels.Views
|
namespace TimetableDesigner.ViewModels.Views
|
||||||
{
|
{
|
||||||
public class ProjectSettingsViewModel : BaseViewViewModel
|
public class ProjectSettingsViewVM : ObservableObject, IViewVM
|
||||||
{
|
{
|
||||||
#region FIELDS
|
#region FIELDS
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ namespace TimetableDesigner.ViewModels.Views
|
|||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
// Project
|
// Project
|
||||||
public ProjectViewModel? Project => _projectService.ProjectViewModel;
|
public ProjectVM? Project => _projectService.ProjectViewModel;
|
||||||
|
|
||||||
// Fields
|
// Fields
|
||||||
public string NewDayName
|
public string NewDayName
|
||||||
@@ -81,7 +81,7 @@ namespace TimetableDesigner.ViewModels.Views
|
|||||||
|
|
||||||
#region CONSTRUCTORS
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
public ProjectSettingsViewModel()
|
public ProjectSettingsViewVM()
|
||||||
{
|
{
|
||||||
_messageBoxService = ServiceProvider.Instance.GetService<IMessageBoxService>();
|
_messageBoxService = ServiceProvider.Instance.GetService<IMessageBoxService>();
|
||||||
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
|
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
|
||||||
@@ -115,7 +115,7 @@ namespace TimetableDesigner.ViewModels.Views
|
|||||||
{
|
{
|
||||||
if (Project is not null)
|
if (Project is not null)
|
||||||
{
|
{
|
||||||
foreach (TeacherViewModel teacher in Project.Teachers)
|
foreach (TeacherVM teacher in Project.Teachers)
|
||||||
{
|
{
|
||||||
teacher.RemoveDay(day);
|
teacher.RemoveDay(day);
|
||||||
}
|
}
|
||||||
@@ -137,11 +137,19 @@ namespace TimetableDesigner.ViewModels.Views
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
TimetableSpan? lastSlot = Project.TimetableTemplate.Slots.LastOrDefault();
|
||||||
|
|
||||||
Project.TimetableTemplate.AddSlot(new TimetableSpan(from, to));
|
Project.TimetableTemplate.AddSlot(new TimetableSpan(from, to));
|
||||||
|
|
||||||
|
double offset = 0;
|
||||||
|
if (lastSlot != null)
|
||||||
|
{
|
||||||
|
offset = (from - lastSlot.To).TotalMinutes;
|
||||||
|
}
|
||||||
|
|
||||||
double delta = (to - from).TotalMinutes;
|
double delta = (to - from).TotalMinutes;
|
||||||
DateTime newFrom = NewSlotTo.Value;
|
DateTime newFrom = NewSlotTo.Value.AddMinutes(offset);
|
||||||
DateTime newTo = NewSlotTo.Value.AddMinutes(delta);
|
DateTime newTo = NewSlotTo.Value.AddMinutes(offset + delta);
|
||||||
NewSlotFrom = newFrom;
|
NewSlotFrom = newFrom;
|
||||||
NewSlotTo = newTo;
|
NewSlotTo = newTo;
|
||||||
}
|
}
|
||||||
@@ -14,17 +14,18 @@ using TimetableDesigner.Services.MessageBox;
|
|||||||
using TimetableDesigner.Services.Project;
|
using TimetableDesigner.Services.Project;
|
||||||
using TimetableDesigner.Services.TabNavigation;
|
using TimetableDesigner.Services.TabNavigation;
|
||||||
using TimetableDesigner.ViewModels.Models;
|
using TimetableDesigner.ViewModels.Models;
|
||||||
|
using TimetableDesigner.ViewModels.Models.Base;
|
||||||
|
|
||||||
namespace TimetableDesigner.ViewModels.Views
|
namespace TimetableDesigner.ViewModels.Views
|
||||||
{
|
{
|
||||||
public class TeacherEditViewModel : BaseViewViewModel
|
public class TeacherEditorViewVM : ObservableObject, IViewVM, IUnitEditorViewVM
|
||||||
{
|
{
|
||||||
#region FIELDS
|
#region FIELDS
|
||||||
|
|
||||||
private IMessageBoxService _messageBoxService;
|
private IMessageBoxService _messageBoxService;
|
||||||
private IProjectService _projectService;
|
private IProjectService _projectService;
|
||||||
|
|
||||||
private TeacherViewModel _teacher;
|
private TeacherVM _teacher;
|
||||||
|
|
||||||
private TimetableDay _selectedDay;
|
private TimetableDay _selectedDay;
|
||||||
|
|
||||||
@@ -38,7 +39,8 @@ namespace TimetableDesigner.ViewModels.Views
|
|||||||
|
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
public TeacherViewModel Teacher
|
IUnitVM IUnitEditorViewVM.Unit => Teacher;
|
||||||
|
public TeacherVM Teacher
|
||||||
{
|
{
|
||||||
get => _teacher;
|
get => _teacher;
|
||||||
set
|
set
|
||||||
@@ -50,7 +52,7 @@ namespace TimetableDesigner.ViewModels.Views
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public TimetableTemplateViewModel? TimetableTemplate => _projectService.ProjectViewModel?.TimetableTemplate;
|
public TimetableTemplateVM? TimetableTemplate => _projectService.ProjectViewModel?.TimetableTemplate;
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
@@ -65,7 +67,7 @@ namespace TimetableDesigner.ViewModels.Views
|
|||||||
TabItem? tab = ServiceProvider.Instance.GetService<ITabNavigationService>().Tabs.Where(tab => tab.ViewModel == this).FirstOrDefault();
|
TabItem? tab = ServiceProvider.Instance.GetService<ITabNavigationService>().Tabs.Where(tab => tab.ViewModel == this).FirstOrDefault();
|
||||||
if (tab != null)
|
if (tab != null)
|
||||||
{
|
{
|
||||||
tab.Title = $"{Resources.Tabs_ClassroomEdit}: {_teacher.Name}";
|
tab.Title = $"{Resources.Tabs_TeacherEdit}: {_teacher.Name}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,10 +132,10 @@ namespace TimetableDesigner.ViewModels.Views
|
|||||||
|
|
||||||
#region CONSTRUCTORS
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
public TeacherEditViewModel() : this(new TeacherViewModel(new Teacher()))
|
public TeacherEditorViewVM() : this(new TeacherVM(new Teacher()))
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public TeacherEditViewModel(TeacherViewModel teacher)
|
public TeacherEditorViewVM(TeacherVM teacher)
|
||||||
{
|
{
|
||||||
_messageBoxService = ServiceProvider.Instance.GetService<IMessageBoxService>();
|
_messageBoxService = ServiceProvider.Instance.GetService<IMessageBoxService>();
|
||||||
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
|
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
|
||||||
255
TimetableDesigner/ViewModels/Views/TimetableEditorViewVM.cs
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TimetableDesigner.Services;
|
||||||
|
using TimetableDesigner.Services.Project;
|
||||||
|
using TimetableDesigner.ViewModels.Models.Base;
|
||||||
|
using TimetableDesigner.ViewModels.Models;
|
||||||
|
using TimetableDesigner.Customs;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using TimetableDesigner.Commands;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using TimetableDesigner.Core;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using TimetableDesigner.Services.TabNavigation;
|
||||||
|
using System.Security.Policy;
|
||||||
|
using TimetableDesigner.Converters;
|
||||||
|
using System.Data;
|
||||||
|
using static TimetableDesigner.ViewModels.Views.TimetableEditorViewVM;
|
||||||
|
using TimetableDesigner.Services.Scheduler;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.ViewModels.Views
|
||||||
|
{
|
||||||
|
public class TimetableEditorViewVM : ObservableObject, IViewVM
|
||||||
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private IProjectService _projectService;
|
||||||
|
private ITabNavigationService _tabNavigationService;
|
||||||
|
private ISchedulerService _schedulerService;
|
||||||
|
|
||||||
|
private IUnitVM? _unit;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PROPERTIES
|
||||||
|
|
||||||
|
public TimetableTemplateVM TimetableTemplate => _projectService.ProjectViewModel.TimetableTemplate;
|
||||||
|
|
||||||
|
public IUnitVM? Unit
|
||||||
|
{
|
||||||
|
get => _unit;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _unit)
|
||||||
|
{
|
||||||
|
_unit = value;
|
||||||
|
NotifyPropertyChanged(nameof(Unit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ClassVM> AssignedClasses => _projectService.ProjectViewModel.Classes.Where(c => c.Classroom == Unit || c.Teacher == Unit || c.Group == Unit || (Unit is GroupVM g && c.Group is SubgroupVM s && g.AssignedSubgroups.Contains(s)));
|
||||||
|
public IEnumerable<ClassVM> ScheduledClasses => AssignedClasses.Where(c => c.Slot is not null && c.Day is not null);
|
||||||
|
public IEnumerable<ClassVM> UnscheduledClasses => AssignedClasses.Where(c => c.Slot is null || c.Day is null);
|
||||||
|
|
||||||
|
public ICommand AddClassCommand { get; set; }
|
||||||
|
public ICommand AutoScheduleCommand { get; set; }
|
||||||
|
public ICommand RemoveClassCommand { get; set; }
|
||||||
|
public ICommand CloneClassCommand { get; set; }
|
||||||
|
public ICommand RefreshScheduledClassesCommand { get; set; }
|
||||||
|
public ICommand RefreshUnscheduledClassesCommand { get; set; }
|
||||||
|
public ICommand RefreshAllClassesCommand { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public TimetableEditorViewVM() : this(null)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public TimetableEditorViewVM(IUnitVM? unit)
|
||||||
|
{
|
||||||
|
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
|
||||||
|
_tabNavigationService = ServiceProvider.Instance.GetService<ITabNavigationService>();
|
||||||
|
_schedulerService = ServiceProvider.Instance.GetService<ISchedulerService>();
|
||||||
|
|
||||||
|
_unit = unit;
|
||||||
|
|
||||||
|
AddClassCommand = new RelayCommand<object>(arg => AddClass());
|
||||||
|
AutoScheduleCommand = new RelayCommand<object>(arg => AutoSchedule());
|
||||||
|
RemoveClassCommand = new RelayCommand<ClassVM>(RemoveClass);
|
||||||
|
CloneClassCommand = new RelayCommand<ClassVM>(CloneClass);
|
||||||
|
RefreshScheduledClassesCommand = new RelayCommand<object>(arg => RefreshClassesAndErrors(RefreshMode.Scheduled));
|
||||||
|
RefreshUnscheduledClassesCommand = new RelayCommand<object>(arg => RefreshClassesAndErrors(RefreshMode.Unscheduled));
|
||||||
|
RefreshAllClassesCommand = new RelayCommand<object>(arg => RefreshClassesAndErrors(RefreshMode.Scheduled | RefreshMode.Unscheduled));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PUBLIC METHODS
|
||||||
|
|
||||||
|
public void RefreshClasses(RefreshMode mode)
|
||||||
|
{
|
||||||
|
if ((mode & RefreshMode.Scheduled) == RefreshMode.Scheduled)
|
||||||
|
NotifyPropertyChanged(nameof(ScheduledClasses));
|
||||||
|
if ((mode & RefreshMode.Unscheduled) == RefreshMode.Unscheduled)
|
||||||
|
NotifyPropertyChanged(nameof(UnscheduledClasses));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PRIVATE METHODS
|
||||||
|
|
||||||
|
private void AddClass()
|
||||||
|
{
|
||||||
|
Class @class = new Class()
|
||||||
|
{
|
||||||
|
Name = "New class",
|
||||||
|
Teacher = _unit is TeacherVM t ? t.Teacher : null,
|
||||||
|
Classroom = _unit is ClassroomVM c ? c.Classroom : null,
|
||||||
|
Group = _unit is BaseGroupVM g ? g.BaseGroup : null,
|
||||||
|
};
|
||||||
|
ClassVM classVM = new ClassVM(@class);
|
||||||
|
_projectService.ProjectViewModel.Classes.Add(classVM);
|
||||||
|
|
||||||
|
//REFRESH: Unassigned classes of this unit & Errors
|
||||||
|
RefreshClasses(RefreshMode.Unscheduled);
|
||||||
|
_projectService.RefreshErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AutoSchedule()
|
||||||
|
{
|
||||||
|
foreach (ClassVM @class in UnscheduledClasses)
|
||||||
|
{
|
||||||
|
(TimetableDay? day, TimetableSpan? slot) = _schedulerService.Schedule(@class);
|
||||||
|
@class.Day = day;
|
||||||
|
@class.Slot = slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
//REFRESH: Scheduled & Errors
|
||||||
|
foreach (TimetableEditorViewVM editors in _tabNavigationService.Tabs.Select(x => x.ViewModel).OfType<TimetableEditorViewVM>().Distinct())
|
||||||
|
{
|
||||||
|
editors.RefreshClasses(RefreshMode.Scheduled | RefreshMode.Unscheduled);
|
||||||
|
}
|
||||||
|
_projectService.RefreshErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveClass(ClassVM @class)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(@class.Name);
|
||||||
|
List<IUnitVM> units = new List<IUnitVM>();
|
||||||
|
if (@class.Teacher is not null)
|
||||||
|
{
|
||||||
|
units.Add(@class.Teacher);
|
||||||
|
}
|
||||||
|
if (@class.Classroom is not null)
|
||||||
|
{
|
||||||
|
units.Add(@class.Classroom);
|
||||||
|
}
|
||||||
|
if (@class.Group is not null)
|
||||||
|
{
|
||||||
|
units.Add(@class.Group);
|
||||||
|
if (@class.Group is SubgroupVM sg)
|
||||||
|
{
|
||||||
|
units.AddRange(_projectService.ProjectViewModel.Groups.Where(x => x.AssignedSubgroups.Contains(sg)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RefreshMode refreshMode = RefreshMode.Unscheduled;
|
||||||
|
if (@class.Day is not null && @class.Slot is not null)
|
||||||
|
{
|
||||||
|
refreshMode = RefreshMode.Scheduled;
|
||||||
|
}
|
||||||
|
|
||||||
|
_projectService.ProjectViewModel.Classes.Remove(@class);
|
||||||
|
|
||||||
|
//REFRESH: Assigned classes of units assigned to class & Errors
|
||||||
|
foreach (TimetableEditorViewVM editors in _tabNavigationService.Tabs.Select(x => x.ViewModel).OfType<TimetableEditorViewVM>().Where(x => units.Contains(x.Unit)).Distinct())
|
||||||
|
{
|
||||||
|
editors.RefreshClasses(refreshMode);
|
||||||
|
}
|
||||||
|
_projectService.RefreshErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CloneClass(ClassVM @class)
|
||||||
|
{
|
||||||
|
List<IUnitVM> units = new List<IUnitVM>();
|
||||||
|
if (@class.Teacher is not null)
|
||||||
|
{
|
||||||
|
units.Add(@class.Teacher);
|
||||||
|
}
|
||||||
|
if (@class.Classroom is not null)
|
||||||
|
{
|
||||||
|
units.Add(@class.Classroom);
|
||||||
|
}
|
||||||
|
if (@class.Group is not null)
|
||||||
|
{
|
||||||
|
units.Add(@class.Group);
|
||||||
|
if (@class.Group is SubgroupVM sg)
|
||||||
|
{
|
||||||
|
units.AddRange(_projectService.ProjectViewModel.Groups.Where(x => x.AssignedSubgroups.Contains(sg)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RefreshMode refreshMode = RefreshMode.Unscheduled;
|
||||||
|
if (@class.Day is not null && @class.Slot is not null)
|
||||||
|
{
|
||||||
|
refreshMode = RefreshMode.Scheduled;
|
||||||
|
}
|
||||||
|
|
||||||
|
Class newClass = new Class()
|
||||||
|
{
|
||||||
|
Name = @class.Name,
|
||||||
|
Teacher = @class.Teacher?.Teacher,
|
||||||
|
Classroom = @class.Classroom?.Classroom,
|
||||||
|
Group = @class.Group?.BaseGroup,
|
||||||
|
Day = @class.Day,
|
||||||
|
Slot = @class.Slot,
|
||||||
|
Color = @class.Color,
|
||||||
|
};
|
||||||
|
ClassVM classVM = new ClassVM(newClass);
|
||||||
|
_projectService.ProjectViewModel.Classes.Add(classVM);
|
||||||
|
|
||||||
|
//REFRESH: Assigned classes of units assigned to class & Errors
|
||||||
|
foreach (TimetableEditorViewVM editors in _tabNavigationService.Tabs.Select(x => x.ViewModel).OfType<TimetableEditorViewVM>().Where(x => units.Contains(x.Unit)).Distinct())
|
||||||
|
{
|
||||||
|
editors.RefreshClasses(refreshMode);
|
||||||
|
}
|
||||||
|
_projectService.RefreshErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshClassesAndErrors(RefreshMode mode)
|
||||||
|
{
|
||||||
|
RefreshClasses(mode);
|
||||||
|
_projectService.RefreshErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region ENUMS
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum RefreshMode
|
||||||
|
{
|
||||||
|
Scheduled,
|
||||||
|
Unscheduled
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,11 +7,11 @@ using TimetableDesigner.Customs;
|
|||||||
|
|
||||||
namespace TimetableDesigner.ViewModels.Views
|
namespace TimetableDesigner.ViewModels.Views
|
||||||
{
|
{
|
||||||
public class WelcomeViewModel : BaseViewViewModel
|
public class WelcomeViewVM : ObservableObject, IViewVM
|
||||||
{
|
{
|
||||||
#region CONSTRUCTORS
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
public WelcomeViewModel()
|
public WelcomeViewVM()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||