Teacher editor
This commit is contained in:
@@ -12,6 +12,20 @@ namespace TimetableDesigner.Core
|
|||||||
|
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
|
public IDictionary<TimetableDay, TimetableSpanCollection> AvailabilityHours { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public Teacher()
|
||||||
|
{
|
||||||
|
Name = string.Empty;
|
||||||
|
Description = string.Empty;
|
||||||
|
AvailabilityHours = new Dictionary<TimetableDay, TimetableSpanCollection>();
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace TimetableDesigner.Core
|
namespace TimetableDesigner.Core
|
||||||
{
|
{
|
||||||
public struct TimetableDay
|
[Serializable]
|
||||||
|
public class TimetableDay
|
||||||
{
|
{
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
namespace TimetableDesigner.Core
|
namespace TimetableDesigner.Core
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public struct TimetableSlot
|
public class TimetableSpan
|
||||||
{
|
{
|
||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ namespace TimetableDesigner.Core
|
|||||||
|
|
||||||
#region CONSTRUCTORS
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
public TimetableSlot(TimeOnly from, TimeOnly to)
|
public TimetableSpan(TimeOnly from, TimeOnly to)
|
||||||
{
|
{
|
||||||
if (to <= from)
|
if (to <= from)
|
||||||
{
|
{
|
||||||
@@ -33,29 +33,29 @@ namespace TimetableDesigner.Core
|
|||||||
|
|
||||||
#region PUBLIC METHODS
|
#region PUBLIC METHODS
|
||||||
|
|
||||||
internal TimetableSlotsCollision CheckCollision(TimetableSlot slot)
|
internal TimetableSpansCollision CheckCollision(TimetableSpan slot)
|
||||||
{
|
{
|
||||||
if (slot.To <= this.From)
|
if (slot.To <= this.From)
|
||||||
{
|
{
|
||||||
return TimetableSlotsCollision.CheckedSlotBefore;
|
return TimetableSpansCollision.CheckedSlotBefore;
|
||||||
}
|
}
|
||||||
else if (this.To <= slot.From)
|
else if (this.To <= slot.From)
|
||||||
{
|
{
|
||||||
return TimetableSlotsCollision.CheckedSlotAfter;
|
return TimetableSpansCollision.CheckedSlotAfter;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (this.From < slot.From && slot.To < this.To)
|
if (this.From < slot.From && slot.To < this.To)
|
||||||
{
|
{
|
||||||
return TimetableSlotsCollision.CheckedSlotIn;
|
return TimetableSpansCollision.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 TimetableSlotsCollision.CheckedSlotFromIn;
|
return TimetableSpansCollision.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 TimetableSlotsCollision.CheckedSlotToIn;
|
return TimetableSpansCollision.CheckedSlotToIn;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -64,7 +64,7 @@ namespace TimetableDesigner.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object? obj) => obj is TimetableSlot slot && From == slot.From && To == slot.To;
|
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 int GetHashCode() => HashCode.Combine(From, To);
|
||||||
|
|
||||||
75
TimetableDesigner.Core/TimetableSpanCollection.cs
Normal file
75
TimetableDesigner.Core/TimetableSpanCollection.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Core
|
||||||
|
{
|
||||||
|
public class TimetableSpanCollection : ICollection<TimetableSpan>
|
||||||
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private IList<TimetableSpan> _list;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PROPERTIES
|
||||||
|
|
||||||
|
public int Count => _list.Count;
|
||||||
|
public bool IsReadOnly => _list.IsReadOnly;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public TimetableSpanCollection()
|
||||||
|
{
|
||||||
|
_list = new List<TimetableSpan>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PUBLIC METHODS
|
||||||
|
|
||||||
|
public void Add(TimetableSpan item)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
if (Count > 0)
|
||||||
|
{
|
||||||
|
bool done = false;
|
||||||
|
while (i < Count && !done)
|
||||||
|
{
|
||||||
|
switch (item.CheckCollision(_list.ElementAt(i)))
|
||||||
|
{
|
||||||
|
case TimetableSpansCollision.CheckedSlotBefore: i++; break;
|
||||||
|
case TimetableSpansCollision.CheckedSlotAfter: done ^= true; break;
|
||||||
|
default: throw new ArgumentException("Slot collide with another slot");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_list.Insert(i, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear() => _list.Clear();
|
||||||
|
|
||||||
|
public bool Contains(TimetableSpan item) => _list.Contains(item);
|
||||||
|
|
||||||
|
public void CopyTo(TimetableSpan[] array, int arrayIndex) => _list.CopyTo(array, arrayIndex);
|
||||||
|
|
||||||
|
public IEnumerator<TimetableSpan> GetEnumerator() => _list.GetEnumerator();
|
||||||
|
|
||||||
|
public bool Remove(TimetableSpan item) => _list.Remove(item);
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_list).GetEnumerator();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace TimetableDesigner.Core
|
namespace TimetableDesigner.Core
|
||||||
{
|
{
|
||||||
internal enum TimetableSlotsCollision
|
internal enum TimetableSpansCollision
|
||||||
{
|
{
|
||||||
CheckedSlotBefore,
|
CheckedSlotBefore,
|
||||||
CheckedSlotAfter,
|
CheckedSlotAfter,
|
||||||
@@ -12,7 +12,7 @@ namespace TimetableDesigner.Core
|
|||||||
#region FIELDS
|
#region FIELDS
|
||||||
|
|
||||||
private List<TimetableDay> _days;
|
private List<TimetableDay> _days;
|
||||||
private List<TimetableSlot> _slots;
|
private TimetableSpanCollection _slots;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ namespace TimetableDesigner.Core
|
|||||||
#region PROPERTIES
|
#region PROPERTIES
|
||||||
|
|
||||||
public IEnumerable<TimetableDay> Days => _days;
|
public IEnumerable<TimetableDay> Days => _days;
|
||||||
public IEnumerable<TimetableSlot> Slots => _slots;
|
public IEnumerable<TimetableSpan> Slots => _slots;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ namespace TimetableDesigner.Core
|
|||||||
public TimetableTemplate()
|
public TimetableTemplate()
|
||||||
{
|
{
|
||||||
_days = new List<TimetableDay>();
|
_days = new List<TimetableDay>();
|
||||||
_slots = new List<TimetableSlot>();
|
_slots = new TimetableSpanCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -41,39 +41,13 @@ namespace TimetableDesigner.Core
|
|||||||
|
|
||||||
#region PUBLIC METHODS
|
#region PUBLIC METHODS
|
||||||
|
|
||||||
public void AddDay(TimetableDay name)
|
public void AddDay(TimetableDay name) => _days.Add(name);
|
||||||
{
|
|
||||||
_days.Add(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool RemoveDay(TimetableDay day)
|
public bool RemoveDay(TimetableDay day) => _days.Remove(day);
|
||||||
{
|
|
||||||
return _days.Remove(day);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddSlot(TimetableSlot slot)
|
public void AddSlot(TimetableSpan slot) => _slots.Add(slot);
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
if (_slots.Count > 0)
|
|
||||||
{
|
|
||||||
bool done = false;
|
|
||||||
while (i < _slots.Count && !done)
|
|
||||||
{
|
|
||||||
switch (slot.CheckCollision(_slots[i]))
|
|
||||||
{
|
|
||||||
case TimetableSlotsCollision.CheckedSlotBefore: i++; break;
|
|
||||||
case TimetableSlotsCollision.CheckedSlotAfter: done ^= true; break;
|
|
||||||
default: throw new ArgumentException("Slot collide with another slot");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_slots.Insert(i, slot);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool RemoveSlot(TimetableSlot slot)
|
public bool RemoveSlot(TimetableSpan slot) => _slots.Remove(slot);
|
||||||
{
|
|
||||||
return _slots.Remove(slot);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
153
TimetableDesigner.Customs/Collections/ObservableDictionary.cs
Normal file
153
TimetableDesigner.Customs/Collections/ObservableDictionary.cs
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Customs.Collections
|
||||||
|
{
|
||||||
|
public class ObservableDictionary<TKey, TValue> : ObservableCollection<ObservableKeyValuePair<TKey, TValue>>, IDictionary<TKey, TValue>
|
||||||
|
{
|
||||||
|
#region PROPERTIES
|
||||||
|
|
||||||
|
public ICollection<TKey> Keys => Items.Select(p => p.Key).ToList();
|
||||||
|
public ICollection<TValue> Values => Items.Select(p => p.Value).ToList();
|
||||||
|
public bool IsReadOnly => false;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region INDEXERS
|
||||||
|
|
||||||
|
public TValue this[TKey key]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!TryGetValue(key, out TValue result))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Key not found");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (ContainsKey(key))
|
||||||
|
{
|
||||||
|
GetKeyValuePairByTheKey(key).Value = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Add(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public ObservableDictionary() : base()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public ObservableDictionary(IDictionary<TKey, TValue> dictionary) : base()
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<TKey, TValue> pair in dictionary)
|
||||||
|
{
|
||||||
|
this.Add(pair);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PUBLIC METHODS
|
||||||
|
|
||||||
|
public void Add(TKey key, TValue value)
|
||||||
|
{
|
||||||
|
if (ContainsKey(key))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The dictionary already contains the key");
|
||||||
|
}
|
||||||
|
Add(new ObservableKeyValuePair<TKey, TValue>(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(KeyValuePair<TKey, TValue> item) => Add(item.Key, item.Value);
|
||||||
|
|
||||||
|
public bool Contains(KeyValuePair<TKey, TValue> item)
|
||||||
|
{
|
||||||
|
ObservableKeyValuePair<TKey, TValue> pair = GetKeyValuePairByTheKey(item.Key);
|
||||||
|
if (Equals(pair, default(ObservableKeyValuePair<TKey, TValue>)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Equals(pair.Value, item.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ContainsKey(TKey key)
|
||||||
|
{
|
||||||
|
ObservableKeyValuePair<TKey, TValue> pair = ((ObservableCollection<ObservableKeyValuePair<TKey, TValue>>)this).FirstOrDefault((i) => Equals(key, i.Key));
|
||||||
|
|
||||||
|
return !Equals(default(ObservableKeyValuePair<TKey, TValue>), pair);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(TKey key)
|
||||||
|
{
|
||||||
|
List<ObservableKeyValuePair<TKey, TValue>> remove = ((ObservableCollection<ObservableKeyValuePair<TKey, TValue>>)this).Where(pair => Equals(key, pair.Key)).ToList();
|
||||||
|
foreach (ObservableKeyValuePair<TKey, TValue> pair in remove)
|
||||||
|
{
|
||||||
|
Remove(pair);
|
||||||
|
}
|
||||||
|
return remove.Count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(KeyValuePair<TKey, TValue> item)
|
||||||
|
{
|
||||||
|
ObservableKeyValuePair<TKey, TValue> pair = GetKeyValuePairByTheKey(item.Key);
|
||||||
|
if (Equals(pair, default(ObservableKeyValuePair<TKey, TValue>)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Equals(pair.Value, item.Value))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Remove(pair);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
|
||||||
|
{
|
||||||
|
value = default;
|
||||||
|
var pair = GetKeyValuePairByTheKey(key);
|
||||||
|
if (Equals(pair, default(ObservableKeyValuePair<TKey, TValue>)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
value = pair.Value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator() => ((ObservableCollection<ObservableKeyValuePair<TKey, TValue>>)this).Select(i => new KeyValuePair<TKey, TValue>(i.Key, i.Value)).GetEnumerator();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PRIVATE METHODS
|
||||||
|
|
||||||
|
private ObservableKeyValuePair<TKey, TValue> GetKeyValuePairByTheKey(TKey key) => ((ObservableCollection<ObservableKeyValuePair<TKey, TValue>>)this).FirstOrDefault(i => i.Key.Equals(key));
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace TimetableDesigner.Customs.Collections
|
||||||
|
{
|
||||||
|
public class ObservableKeyValuePair<TKey, TValue> : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private TKey _key;
|
||||||
|
private TValue _value;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PROPERTIES
|
||||||
|
|
||||||
|
public TKey Key
|
||||||
|
{
|
||||||
|
get => _key;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_key = value;
|
||||||
|
NotifyPropertyChanged(nameof(Key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public TValue Value
|
||||||
|
{
|
||||||
|
get => _value;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_value = value;
|
||||||
|
NotifyPropertyChanged(nameof(Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public ObservableKeyValuePair() : this(default, default)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public ObservableKeyValuePair(TKey key, TValue value)
|
||||||
|
{
|
||||||
|
_key = key;
|
||||||
|
_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PRIVATE METHODS
|
||||||
|
|
||||||
|
private void NotifyPropertyChanged(string name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region EVENTS
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -10,14 +10,14 @@ namespace TimetableDesigner.Tests
|
|||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void CreateValidSlotTest()
|
public void CreateValidSlotTest()
|
||||||
{
|
{
|
||||||
TimetableSlot slot = new TimetableSlot(new TimeOnly(8, 0), new TimeOnly(9, 0));
|
TimetableSpan slot = new TimetableSpan(new TimeOnly(8, 0), new TimeOnly(9, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
[ExpectedException(typeof(ArgumentException))]
|
[ExpectedException(typeof(ArgumentException))]
|
||||||
public void CreateInvalidSlotTest()
|
public void CreateInvalidSlotTest()
|
||||||
{
|
{
|
||||||
TimetableSlot slot = new TimetableSlot(new TimeOnly(9, 0), new TimeOnly(8, 0));
|
TimetableSpan slot = new TimetableSpan(new TimeOnly(9, 0), new TimeOnly(8, 0));
|
||||||
|
|
||||||
Assert.Fail();
|
Assert.Fail();
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ namespace TimetableDesigner.Tests
|
|||||||
[ExpectedException(typeof(ArgumentException))]
|
[ExpectedException(typeof(ArgumentException))]
|
||||||
public void CreateSlotWithZeroLengthTest()
|
public void CreateSlotWithZeroLengthTest()
|
||||||
{
|
{
|
||||||
TimetableSlot slot = new TimetableSlot(new TimeOnly(8, 0), new TimeOnly(8, 0));
|
TimetableSpan slot = new TimetableSpan(new TimeOnly(8, 0), new TimeOnly(8, 0));
|
||||||
|
|
||||||
Assert.Fail();
|
Assert.Fail();
|
||||||
}
|
}
|
||||||
@@ -58,12 +58,12 @@ namespace TimetableDesigner.Tests
|
|||||||
{
|
{
|
||||||
TimetableTemplate model = new TimetableTemplate();
|
TimetableTemplate model = new TimetableTemplate();
|
||||||
|
|
||||||
TimetableSlot slot = new TimetableSlot(new TimeOnly(8, 0), new TimeOnly(9, 0));
|
TimetableSpan slot = new TimetableSpan(new TimeOnly(8, 0), new TimeOnly(9, 0));
|
||||||
|
|
||||||
model.AddSlot(slot);
|
model.AddSlot(slot);
|
||||||
|
|
||||||
Assert.AreEqual(1, model.Slots.Count());
|
Assert.AreEqual(1, model.Slots.Count());
|
||||||
Assert.AreEqual(new TimetableSlot(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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
@@ -71,15 +71,15 @@ namespace TimetableDesigner.Tests
|
|||||||
{
|
{
|
||||||
TimetableTemplate model = new TimetableTemplate();
|
TimetableTemplate model = new TimetableTemplate();
|
||||||
|
|
||||||
TimetableSlot slot1 = new TimetableSlot(new TimeOnly(8, 15), new TimeOnly(9, 0));
|
TimetableSpan slot1 = new TimetableSpan(new TimeOnly(8, 15), new TimeOnly(9, 0));
|
||||||
TimetableSlot slot2 = new TimetableSlot(new TimeOnly(9, 15), new TimeOnly(10, 0));
|
TimetableSpan slot2 = new TimetableSpan(new TimeOnly(9, 15), new TimeOnly(10, 0));
|
||||||
|
|
||||||
model.AddSlot(slot1);
|
model.AddSlot(slot1);
|
||||||
model.AddSlot(slot2);
|
model.AddSlot(slot2);
|
||||||
|
|
||||||
Assert.AreEqual(2, model.Slots.Count());
|
Assert.AreEqual(2, model.Slots.Count());
|
||||||
Assert.AreEqual(new TimetableSlot(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]);
|
||||||
Assert.AreEqual(new TimetableSlot(new TimeOnly(9, 15), new TimeOnly(10, 0)), model.Slots.ToList()[1]);
|
Assert.AreEqual(new TimetableSpan(new TimeOnly(9, 15), new TimeOnly(10, 0)), model.Slots.ToList()[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
@@ -87,15 +87,15 @@ namespace TimetableDesigner.Tests
|
|||||||
{
|
{
|
||||||
TimetableTemplate model = new TimetableTemplate();
|
TimetableTemplate model = new TimetableTemplate();
|
||||||
|
|
||||||
TimetableSlot slot1 = new TimetableSlot(new TimeOnly(8, 0), new TimeOnly(9, 0));
|
TimetableSpan slot1 = new TimetableSpan(new TimeOnly(8, 0), new TimeOnly(9, 0));
|
||||||
TimetableSlot slot2 = new TimetableSlot(new TimeOnly(9, 0), new TimeOnly(10, 0));
|
TimetableSpan slot2 = new TimetableSpan(new TimeOnly(9, 0), new TimeOnly(10, 0));
|
||||||
|
|
||||||
model.AddSlot(slot1);
|
model.AddSlot(slot1);
|
||||||
model.AddSlot(slot2);
|
model.AddSlot(slot2);
|
||||||
|
|
||||||
Assert.AreEqual(2, model.Slots.Count());
|
Assert.AreEqual(2, model.Slots.Count());
|
||||||
Assert.AreEqual(new TimetableSlot(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]);
|
||||||
Assert.AreEqual(new TimetableSlot(new TimeOnly(9, 0), new TimeOnly(10, 0)), model.Slots.ToList()[1]);
|
Assert.AreEqual(new TimetableSpan(new TimeOnly(9, 0), new TimeOnly(10, 0)), model.Slots.ToList()[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
@@ -104,8 +104,8 @@ namespace TimetableDesigner.Tests
|
|||||||
{
|
{
|
||||||
TimetableTemplate model = new TimetableTemplate();
|
TimetableTemplate model = new TimetableTemplate();
|
||||||
|
|
||||||
TimetableSlot slot1 = new TimetableSlot(new TimeOnly(8, 0), new TimeOnly(9, 30));
|
TimetableSpan slot1 = new TimetableSpan(new TimeOnly(8, 0), new TimeOnly(9, 30));
|
||||||
TimetableSlot slot2 = new TimetableSlot(new TimeOnly(8, 30), new TimeOnly(10, 0));
|
TimetableSpan slot2 = new TimetableSpan(new TimeOnly(8, 30), new TimeOnly(10, 0));
|
||||||
|
|
||||||
model.AddSlot(slot1);
|
model.AddSlot(slot1);
|
||||||
model.AddSlot(slot2);
|
model.AddSlot(slot2);
|
||||||
@@ -119,9 +119,9 @@ namespace TimetableDesigner.Tests
|
|||||||
{
|
{
|
||||||
TimetableTemplate model = new TimetableTemplate();
|
TimetableTemplate model = new TimetableTemplate();
|
||||||
|
|
||||||
TimetableSlot slot1 = new TimetableSlot(new TimeOnly(8, 0), new TimeOnly(9, 0));
|
TimetableSpan slot1 = new TimetableSpan(new TimeOnly(8, 0), new TimeOnly(9, 0));
|
||||||
TimetableSlot slot2 = new TimetableSlot(new TimeOnly(10, 0), new TimeOnly(11, 0));
|
TimetableSpan slot2 = new TimetableSpan(new TimeOnly(10, 0), new TimeOnly(11, 0));
|
||||||
TimetableSlot slot3 = new TimetableSlot(new TimeOnly(8, 59), new TimeOnly(10, 1));
|
TimetableSpan slot3 = new TimetableSpan(new TimeOnly(8, 59), new TimeOnly(10, 1));
|
||||||
|
|
||||||
model.AddSlot(slot1);
|
model.AddSlot(slot1);
|
||||||
model.AddSlot(slot2);
|
model.AddSlot(slot2);
|
||||||
@@ -135,13 +135,13 @@ namespace TimetableDesigner.Tests
|
|||||||
{
|
{
|
||||||
TimetableTemplate model = new TimetableTemplate();
|
TimetableTemplate model = new TimetableTemplate();
|
||||||
|
|
||||||
TimetableSlot slot1 = new TimetableSlot(new TimeOnly(12, 0), new TimeOnly(13, 0));
|
TimetableSpan slot1 = new TimetableSpan(new TimeOnly(12, 0), new TimeOnly(13, 0));
|
||||||
TimetableSlot slot2 = new TimetableSlot(new TimeOnly(8, 0), new TimeOnly(9, 0));
|
TimetableSpan slot2 = new TimetableSpan(new TimeOnly(8, 0), new TimeOnly(9, 0));
|
||||||
TimetableSlot slot3 = new TimetableSlot(new TimeOnly(10, 0), new TimeOnly(11, 0));
|
TimetableSpan slot3 = new TimetableSpan(new TimeOnly(10, 0), new TimeOnly(11, 0));
|
||||||
TimetableSlot slot4 = new TimetableSlot(new TimeOnly(14, 0), new TimeOnly(15, 0));
|
TimetableSpan slot4 = new TimetableSpan(new TimeOnly(14, 0), new TimeOnly(15, 0));
|
||||||
TimetableSlot slot5 = new TimetableSlot(new TimeOnly(13, 0), new TimeOnly(14, 0));
|
TimetableSpan slot5 = new TimetableSpan(new TimeOnly(13, 0), new TimeOnly(14, 0));
|
||||||
TimetableSlot slot6 = new TimetableSlot(new TimeOnly(9, 0), new TimeOnly(10, 0));
|
TimetableSpan slot6 = new TimetableSpan(new TimeOnly(9, 0), new TimeOnly(10, 0));
|
||||||
TimetableSlot slot7 = new TimetableSlot(new TimeOnly(11, 0), new TimeOnly(12, 0));
|
TimetableSpan slot7 = new TimetableSpan(new TimeOnly(11, 0), new TimeOnly(12, 0));
|
||||||
|
|
||||||
model.AddSlot(slot1);
|
model.AddSlot(slot1);
|
||||||
model.AddSlot(slot2);
|
model.AddSlot(slot2);
|
||||||
@@ -151,9 +151,9 @@ namespace TimetableDesigner.Tests
|
|||||||
model.AddSlot(slot6);
|
model.AddSlot(slot6);
|
||||||
model.AddSlot(slot7);
|
model.AddSlot(slot7);
|
||||||
|
|
||||||
List<TimetableSlot> slots = model.Slots.ToList();
|
List<TimetableSpan> slots = model.Slots.ToList();
|
||||||
|
|
||||||
TimetableSlot testSlot = slots[0];
|
TimetableSpan testSlot = slots[0];
|
||||||
for (int i = 1; i < slots.Count; i++)
|
for (int i = 1; i < slots.Count; i++)
|
||||||
{
|
{
|
||||||
if (testSlot.To > slots[i].From)
|
if (testSlot.To > slots[i].From)
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TimetableDesigner.Core", "T
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TimetableDesigner.Tests", "TimetableDesigner.Tests\TimetableDesigner.Tests.csproj", "{A9B4DB89-A007-472A-9C80-B6340458AC1B}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TimetableDesigner.Tests", "TimetableDesigner.Tests\TimetableDesigner.Tests.csproj", "{A9B4DB89-A007-472A-9C80-B6340458AC1B}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TimetableDesigner.MessageBox", "TimetableDesigner.MessageBox\TimetableDesigner.MessageBox.csproj", "{95992646-6D81-4FF4-885E-8F0BE2312D54}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TimetableDesigner.MessageBox", "TimetableDesigner.MessageBox\TimetableDesigner.MessageBox.csproj", "{95992646-6D81-4FF4-885E-8F0BE2312D54}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TimetableDesigner.Customs", "TimetableDesigner.Customs\TimetableDesigner.Customs.csproj", "{BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@@ -51,6 +53,14 @@ Global
|
|||||||
{95992646-6D81-4FF4-885E-8F0BE2312D54}.Release|Any CPU.Build.0 = Release|Any CPU
|
{95992646-6D81-4FF4-885E-8F0BE2312D54}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{95992646-6D81-4FF4-885E-8F0BE2312D54}.Release|x64.ActiveCfg = Release|Any CPU
|
{95992646-6D81-4FF4-885E-8F0BE2312D54}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{95992646-6D81-4FF4-885E-8F0BE2312D54}.Release|x64.Build.0 = Release|Any CPU
|
{95992646-6D81-4FF4-885E-8F0BE2312D54}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}.Release|x64.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ namespace TimetableDesigner.Converters
|
|||||||
{ typeof(WelcomeTabViewModel), typeof(WelcomeTabView) },
|
{ typeof(WelcomeTabViewModel), typeof(WelcomeTabView) },
|
||||||
{ typeof(ProjectSettingsTabViewModel), typeof(ProjectSettingsTabView) },
|
{ typeof(ProjectSettingsTabViewModel), typeof(ProjectSettingsTabView) },
|
||||||
{ typeof(ClassroomEditTabViewModel), typeof(ClassroomEditTabView) },
|
{ typeof(ClassroomEditTabViewModel), typeof(ClassroomEditTabView) },
|
||||||
|
{ typeof(TeacherEditTabViewModel), typeof(TeacherEditTabView) },
|
||||||
};
|
};
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
81
TimetableDesigner/Properties/Resources.Designer.cs
generated
81
TimetableDesigner/Properties/Resources.Designer.cs
generated
@@ -114,6 +114,15 @@ namespace TimetableDesigner.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to New teacher.
|
||||||
|
/// </summary>
|
||||||
|
public static string Global_DefaultTeacherName {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Global.DefaultTeacherName", 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>
|
||||||
@@ -321,6 +330,24 @@ namespace TimetableDesigner.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Teachers.
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Treeview_Teachers {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Treeview.Teachers", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Edit teacher.
|
||||||
|
/// </summary>
|
||||||
|
public static string Main_Treeview_Teachers_ContextMenu_Edit {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Main.Treeview.Teachers.ContextMenu.Edit", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Error.
|
/// Looks up a localized string similar to Error.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -429,6 +456,15 @@ namespace TimetableDesigner.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Teacher editing.
|
||||||
|
/// </summary>
|
||||||
|
public static string Tabs_TeacherEdit {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Tabs.TeacherEdit", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Welcome.
|
/// Looks up a localized string similar to Welcome.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -437,5 +473,50 @@ namespace TimetableDesigner.Properties {
|
|||||||
return ResourceManager.GetString("Tabs.Welcome", resourceCulture);
|
return ResourceManager.GetString("Tabs.Welcome", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Availability hours.
|
||||||
|
/// </summary>
|
||||||
|
public static string TeacherEdit_AvailabilityHours {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TeacherEdit.AvailabilityHours", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Description.
|
||||||
|
/// </summary>
|
||||||
|
public static string TeacherEdit_Description {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TeacherEdit.Description", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to "From" value is higher or equal to "To" value.
|
||||||
|
/// </summary>
|
||||||
|
public static string TeacherEdit_Message_FromHigherThanTo {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TeacherEdit.Message.FromHigherThanTo", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Hour collide with another hour.
|
||||||
|
/// </summary>
|
||||||
|
public static string TeacherEdit_Message_HourCollision {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TeacherEdit.Message.HourCollision", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Name.
|
||||||
|
/// </summary>
|
||||||
|
public static string TeacherEdit_Name {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TeacherEdit.Name", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,6 +135,9 @@
|
|||||||
<data name="Global.DefaultProjectName" xml:space="preserve">
|
<data name="Global.DefaultProjectName" xml:space="preserve">
|
||||||
<value>New project</value>
|
<value>New project</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Global.DefaultTeacherName" xml:space="preserve">
|
||||||
|
<value>New teacher</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>
|
||||||
@@ -204,6 +207,12 @@
|
|||||||
<data name="Main.Treeview.ContextMenu.Remove" xml:space="preserve">
|
<data name="Main.Treeview.ContextMenu.Remove" xml:space="preserve">
|
||||||
<value>Remove</value>
|
<value>Remove</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Main.Treeview.Teachers" xml:space="preserve">
|
||||||
|
<value>Teachers</value>
|
||||||
|
</data>
|
||||||
|
<data name="Main.Treeview.Teachers.ContextMenu.Edit" xml:space="preserve">
|
||||||
|
<value>Edit teacher</value>
|
||||||
|
</data>
|
||||||
<data name="MessageBox.Error" xml:space="preserve">
|
<data name="MessageBox.Error" xml:space="preserve">
|
||||||
<value>Error</value>
|
<value>Error</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -240,7 +249,25 @@
|
|||||||
<data name="Tabs.ProjectSettings" xml:space="preserve">
|
<data name="Tabs.ProjectSettings" xml:space="preserve">
|
||||||
<value>Project settings</value>
|
<value>Project settings</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Tabs.TeacherEdit" xml:space="preserve">
|
||||||
|
<value>Teacher 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>
|
||||||
|
<data name="TeacherEdit.AvailabilityHours" xml:space="preserve">
|
||||||
|
<value>Availability hours</value>
|
||||||
|
</data>
|
||||||
|
<data name="TeacherEdit.Description" xml:space="preserve">
|
||||||
|
<value>Description</value>
|
||||||
|
</data>
|
||||||
|
<data name="TeacherEdit.Message.FromHigherThanTo" xml:space="preserve">
|
||||||
|
<value>"From" value is higher or equal to "To" value</value>
|
||||||
|
</data>
|
||||||
|
<data name="TeacherEdit.Message.HourCollision" xml:space="preserve">
|
||||||
|
<value>Hour collide with another hour</value>
|
||||||
|
</data>
|
||||||
|
<data name="TeacherEdit.Name" xml:space="preserve">
|
||||||
|
<value>Name</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -8,9 +8,12 @@
|
|||||||
<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"/>
|
||||||
<BitmapImage x:Key="ClassroomAddImage" UriSource="Images/ClassroomAdd.png"/>
|
<BitmapImage x:Key="ClassroomAddImage" UriSource="Images/ClassroomAdd.png"/>
|
||||||
|
<BitmapImage x:Key="TeacherImage" UriSource="Images/Teacher.png"/>
|
||||||
|
<BitmapImage x:Key="TeacherAddImage" UriSource="Images/TeacherAdd.png"/>
|
||||||
<BitmapImage x:Key="OpenImage" UriSource="Images/Open.png"/>
|
<BitmapImage x:Key="OpenImage" UriSource="Images/Open.png"/>
|
||||||
<BitmapImage x:Key="OpenRecentImage" UriSource="Images/OpenRecent.png"/>
|
<BitmapImage x:Key="OpenRecentImage" UriSource="Images/OpenRecent.png"/>
|
||||||
<BitmapImage x:Key="SaveImage" UriSource="Images/Save.png"/>
|
<BitmapImage x:Key="SaveImage" UriSource="Images/Save.png"/>
|
||||||
<BitmapImage x:Key="SaveAsImage" UriSource="Images/SaveAs.png"/>
|
<BitmapImage x:Key="SaveAsImage" UriSource="Images/SaveAs.png"/>
|
||||||
<BitmapImage x:Key="NewImage" UriSource="Images/New.png"/>
|
<BitmapImage x:Key="NewImage" UriSource="Images/New.png"/>
|
||||||
|
<BitmapImage x:Key="RightArrowImage" UriSource="Images/RightArrow.png"/>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
BIN
TimetableDesigner/Resources/Images/RightArrow.png
Normal file
BIN
TimetableDesigner/Resources/Images/RightArrow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 223 B |
BIN
TimetableDesigner/Resources/Images/Teacher.png
Normal file
BIN
TimetableDesigner/Resources/Images/Teacher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
BIN
TimetableDesigner/Resources/Images/TeacherAdd.png
Normal file
BIN
TimetableDesigner/Resources/Images/TeacherAdd.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
@@ -20,8 +20,11 @@
|
|||||||
<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\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\TeacherAdd.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -52,12 +55,21 @@
|
|||||||
<Content Include="Resources\Images\Remove.png">
|
<Content Include="Resources\Images\Remove.png">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="Resources\Images\RightArrow.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<Content Include="Resources\Images\Save.png">
|
<Content Include="Resources\Images\Save.png">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="Resources\Images\SaveAs.png">
|
<Content Include="Resources\Images\SaveAs.png">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="Resources\Images\Teacher.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Resources\Images\TeacherAdd.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -67,6 +79,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\TimetableDesigner.Core\TimetableDesigner.Core.csproj" />
|
<ProjectReference Include="..\TimetableDesigner.Core\TimetableDesigner.Core.csproj" />
|
||||||
|
<ProjectReference Include="..\TimetableDesigner.Customs\TimetableDesigner.Customs.csproj" />
|
||||||
<ProjectReference Include="..\TimetableDesigner.MessageBox\TimetableDesigner.MessageBox.csproj" />
|
<ProjectReference Include="..\TimetableDesigner.MessageBox\TimetableDesigner.MessageBox.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ namespace TimetableDesigner.ViewModels
|
|||||||
public ClassroomEditTabViewModel() : this(new ClassroomViewModel(new Core.Classroom()))
|
public ClassroomEditTabViewModel() : this(new ClassroomViewModel(new Core.Classroom()))
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public ClassroomEditTabViewModel(ClassroomViewModel classroom)
|
public ClassroomEditTabViewModel(ClassroomViewModel classroom) : base()
|
||||||
{
|
{
|
||||||
_classroom = classroom;
|
_classroom = classroom;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,9 @@ namespace TimetableDesigner.ViewModels
|
|||||||
public ICommand NewClassroomCommand { get; set; }
|
public ICommand NewClassroomCommand { get; set; }
|
||||||
public ICommand EditClassroomCommand { get; set; }
|
public ICommand EditClassroomCommand { get; set; }
|
||||||
public ICommand RemoveClassroomCommand { get; set; }
|
public ICommand RemoveClassroomCommand { get; set; }
|
||||||
|
public ICommand NewTeacherCommand { get; set; }
|
||||||
|
public ICommand EditTeacherCommand { get; set; }
|
||||||
|
public ICommand RemoveTeacherCommand { get; set; }
|
||||||
|
|
||||||
public ObservableCollection<BaseTabViewModel> Tabs
|
public ObservableCollection<BaseTabViewModel> Tabs
|
||||||
{
|
{
|
||||||
@@ -95,6 +98,9 @@ namespace TimetableDesigner.ViewModels
|
|||||||
NewClassroomCommand = new RelayCommand<object>(param => NewClassroom());
|
NewClassroomCommand = new RelayCommand<object>(param => NewClassroom());
|
||||||
EditClassroomCommand = new RelayCommand<ClassroomViewModel>(EditClassroom);
|
EditClassroomCommand = new RelayCommand<ClassroomViewModel>(EditClassroom);
|
||||||
RemoveClassroomCommand = new RelayCommand<ClassroomViewModel>(DeleteClassroom);
|
RemoveClassroomCommand = new RelayCommand<ClassroomViewModel>(DeleteClassroom);
|
||||||
|
NewTeacherCommand = new RelayCommand<object>(param => NewTeacher());
|
||||||
|
EditTeacherCommand = new RelayCommand<TeacherViewModel>(EditTeacher);
|
||||||
|
RemoveTeacherCommand = new RelayCommand<TeacherViewModel>(DeleteTeacher);
|
||||||
|
|
||||||
_tabs = new ObservableCollection<BaseTabViewModel>
|
_tabs = new ObservableCollection<BaseTabViewModel>
|
||||||
{
|
{
|
||||||
@@ -189,10 +195,8 @@ namespace TimetableDesigner.ViewModels
|
|||||||
|
|
||||||
private void EditClassroom(ClassroomViewModel classroomViewModel)
|
private void EditClassroom(ClassroomViewModel classroomViewModel)
|
||||||
{
|
{
|
||||||
Debug.WriteLine("textedit");
|
ClassroomEditTabViewModel classroomEdit = new ClassroomEditTabViewModel(classroomViewModel)
|
||||||
ClassroomEditTabViewModel classroomEdit = new ClassroomEditTabViewModel()
|
|
||||||
{
|
{
|
||||||
Classroom = classroomViewModel,
|
|
||||||
TabTitle = $"{Resources.Tabs_ClassroomEdit}: {classroomViewModel.Name}",
|
TabTitle = $"{Resources.Tabs_ClassroomEdit}: {classroomViewModel.Name}",
|
||||||
IsTabClosable = true
|
IsTabClosable = true
|
||||||
};
|
};
|
||||||
@@ -202,13 +206,50 @@ namespace TimetableDesigner.ViewModels
|
|||||||
|
|
||||||
private void DeleteClassroom(ClassroomViewModel classroomViewModel)
|
private void DeleteClassroom(ClassroomViewModel classroomViewModel)
|
||||||
{
|
{
|
||||||
Debug.WriteLine("textdelete");
|
|
||||||
if (Project is not null)
|
if (Project is not null)
|
||||||
{
|
{
|
||||||
Project.Classrooms.Remove(classroomViewModel);
|
Project.Classrooms.Remove(classroomViewModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void NewTeacher()
|
||||||
|
{
|
||||||
|
if (Project is not null)
|
||||||
|
{
|
||||||
|
Teacher teacher = new Teacher()
|
||||||
|
{
|
||||||
|
Name = Resources.Global_DefaultTeacherName
|
||||||
|
};
|
||||||
|
TeacherViewModel teacherVM = new TeacherViewModel(teacher);
|
||||||
|
Project.Teachers.Add(teacherVM);
|
||||||
|
EditTeacher(teacherVM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EditTeacher(TeacherViewModel teacherViewModel)
|
||||||
|
{
|
||||||
|
if (Project is not null)
|
||||||
|
{
|
||||||
|
TeacherEditTabViewModel teacherEdit = new TeacherEditTabViewModel(teacherViewModel, Project.TimetableTemplate)
|
||||||
|
{
|
||||||
|
Teacher = teacherViewModel,
|
||||||
|
TabTitle = $"{Resources.Tabs_TeacherEdit}: {teacherViewModel.Name}",
|
||||||
|
IsTabClosable = true
|
||||||
|
};
|
||||||
|
Tabs.Add(teacherEdit);
|
||||||
|
SelectedTab = teacherEdit;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DeleteTeacher(TeacherViewModel teacherViewModel)
|
||||||
|
{
|
||||||
|
if (Project is not null)
|
||||||
|
{
|
||||||
|
Project.Teachers.Remove(teacherViewModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
}
|
}
|
||||||
public TimetableTemplateViewModel TimetableTemplate { get; set; }
|
public TimetableTemplateViewModel TimetableTemplate { get; set; }
|
||||||
public ObservableCollection<ClassroomViewModel> Classrooms { get; set; }
|
public ObservableCollection<ClassroomViewModel> Classrooms { get; set; }
|
||||||
|
public ObservableCollection<TeacherViewModel> Teachers { get; set; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -76,6 +77,9 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
|
|
||||||
Classrooms = new ObservableCollection<ClassroomViewModel>();
|
Classrooms = new ObservableCollection<ClassroomViewModel>();
|
||||||
Classrooms.CollectionChanged += Classrooms_CollectionChanged;
|
Classrooms.CollectionChanged += Classrooms_CollectionChanged;
|
||||||
|
|
||||||
|
Teachers = new ObservableCollection<TeacherViewModel>();
|
||||||
|
Teachers.CollectionChanged += Teachers_CollectionChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -106,6 +110,28 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
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.Collections;
|
||||||
using TimetableDesigner.ViewModels.Base;
|
using TimetableDesigner.ViewModels.Base;
|
||||||
|
|
||||||
namespace TimetableDesigner.ViewModels.Models
|
namespace TimetableDesigner.ViewModels.Models
|
||||||
@@ -46,6 +48,7 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public ObservableDictionary<TimetableDay, ObservableCollection<TimetableSpan>> AvailabilityHours => new ObservableDictionary<TimetableDay, ObservableCollection<TimetableSpan>>(Teacher.AvailabilityHours.ToDictionary(i => i.Key, i => new ObservableCollection<TimetableSpan>(i.Value)));
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -59,5 +62,44 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PUBLIC METHODS
|
||||||
|
|
||||||
|
public void AddDay(TimetableDay day)
|
||||||
|
{
|
||||||
|
if (day is not null)
|
||||||
|
{
|
||||||
|
Teacher.AvailabilityHours.Add(day, new TimetableSpanCollection());
|
||||||
|
NotifyPropertyChanged(nameof(AvailabilityHours));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveDay(TimetableDay day)
|
||||||
|
{
|
||||||
|
Teacher.AvailabilityHours.Remove(day);
|
||||||
|
NotifyPropertyChanged(nameof(AvailabilityHours));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddHours(TimetableDay day, TimetableSpan hours)
|
||||||
|
{
|
||||||
|
if (day is not null && hours is not null)
|
||||||
|
{
|
||||||
|
Teacher.AvailabilityHours[day].Add(hours);
|
||||||
|
NotifyPropertyChanged(nameof(AvailabilityHours));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveHours(TimetableDay day, TimetableSpan hours)
|
||||||
|
{
|
||||||
|
if (day is not null)
|
||||||
|
{
|
||||||
|
Teacher.AvailabilityHours[day].Remove(hours);
|
||||||
|
NotifyPropertyChanged(nameof(AvailabilityHours));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
public TimetableTemplate TimetableTemplate => _timetableTemplate;
|
public TimetableTemplate TimetableTemplate => _timetableTemplate;
|
||||||
|
|
||||||
public ObservableCollection<TimetableDay> Days => new ObservableCollection<TimetableDay>(_timetableTemplate.Days);
|
public ObservableCollection<TimetableDay> Days => new ObservableCollection<TimetableDay>(_timetableTemplate.Days);
|
||||||
public ObservableCollection<TimetableSlot> Slots => new ObservableCollection<TimetableSlot>(_timetableTemplate.Slots);
|
public ObservableCollection<TimetableSpan> Slots => new ObservableCollection<TimetableSpan>(_timetableTemplate.Slots);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -55,13 +55,13 @@ namespace TimetableDesigner.ViewModels.Models
|
|||||||
NotifyPropertyChanged(nameof(Days));
|
NotifyPropertyChanged(nameof(Days));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddSlot(TimetableSlot slot)
|
public void AddSlot(TimetableSpan slot)
|
||||||
{
|
{
|
||||||
_timetableTemplate.AddSlot(slot);
|
_timetableTemplate.AddSlot(slot);
|
||||||
NotifyPropertyChanged(nameof(Slots));
|
NotifyPropertyChanged(nameof(Slots));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveSlot(TimetableSlot slot)
|
public void RemoveSlot(TimetableSpan slot)
|
||||||
{
|
{
|
||||||
_timetableTemplate.RemoveSlot(slot);
|
_timetableTemplate.RemoveSlot(slot);
|
||||||
NotifyPropertyChanged(nameof(Slots));
|
NotifyPropertyChanged(nameof(Slots));
|
||||||
|
|||||||
@@ -73,14 +73,14 @@ namespace TimetableDesigner.ViewModels
|
|||||||
|
|
||||||
#region CONSTRUCTORS
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
public ProjectSettingsTabViewModel()
|
public ProjectSettingsTabViewModel() : base()
|
||||||
{
|
{
|
||||||
Project = new ProjectViewModel(new Project());
|
Project = new ProjectViewModel(new Project());
|
||||||
|
|
||||||
AddDayCommand = new RelayCommand<object>(param => AddDay());
|
AddDayCommand = new RelayCommand<object>(param => AddDay());
|
||||||
AddSlotCommand = new RelayCommand<object>(param => AddSlot());
|
AddSlotCommand = new RelayCommand<object>(param => AddSlot());
|
||||||
RemoveDayCommand = new RelayCommand<TimetableDay>(RemoveDay);
|
RemoveDayCommand = new RelayCommand<TimetableDay>(RemoveDay);
|
||||||
RemoveSlotCommand = new RelayCommand<TimetableSlot>(RemoveSlot);
|
RemoveSlotCommand = new RelayCommand<TimetableSpan>(RemoveSlot);
|
||||||
|
|
||||||
_newDayName = string.Empty;
|
_newDayName = string.Empty;
|
||||||
_newSlotFrom = new DateTime(1, 1, 1, 8, 0, 0);
|
_newSlotFrom = new DateTime(1, 1, 1, 8, 0, 0);
|
||||||
@@ -118,7 +118,7 @@ namespace TimetableDesigner.ViewModels
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Project.TimetableTemplate.AddSlot(new TimetableSlot(from, to));
|
Project.TimetableTemplate.AddSlot(new TimetableSpan(from, to));
|
||||||
|
|
||||||
double delta = (to - from).TotalMinutes;
|
double delta = (to - from).TotalMinutes;
|
||||||
DateTime newFrom = NewSlotTo.Value;
|
DateTime newFrom = NewSlotTo.Value;
|
||||||
@@ -133,7 +133,7 @@ namespace TimetableDesigner.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveSlot(TimetableSlot slot) => Project.TimetableTemplate.RemoveSlot(slot);
|
private void RemoveSlot(TimetableSpan slot) => Project.TimetableTemplate.RemoveSlot(slot);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,188 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using TimetableDesigner.Commands;
|
||||||
|
using TimetableDesigner.Core;
|
||||||
|
using TimetableDesigner.MessageBox;
|
||||||
|
using TimetableDesigner.Properties;
|
||||||
using TimetableDesigner.ViewModels.Base;
|
using TimetableDesigner.ViewModels.Base;
|
||||||
|
using TimetableDesigner.ViewModels.Models;
|
||||||
|
|
||||||
namespace TimetableDesigner.ViewModels
|
namespace TimetableDesigner.ViewModels
|
||||||
{
|
{
|
||||||
public class TeacherEditTabViewModel : BaseViewModel
|
public class TeacherEditTabViewModel : BaseTabViewModel
|
||||||
{
|
{
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
private TeacherViewModel _teacher;
|
||||||
|
private TimetableTemplateViewModel _timetableTemplate;
|
||||||
|
|
||||||
|
private TimetableDay _selectedDay;
|
||||||
|
|
||||||
|
private TimetableDay _selectedNewDay;
|
||||||
|
private DateTime? _newHourFrom;
|
||||||
|
private DateTime? _newHourTo;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PROPERTIES
|
||||||
|
|
||||||
|
public TeacherViewModel Teacher
|
||||||
|
{
|
||||||
|
get => _teacher;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _teacher)
|
||||||
|
{
|
||||||
|
_teacher = value;
|
||||||
|
NotifyPropertyChanged(nameof(Teacher));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public TimetableTemplateViewModel TimetableTemplate
|
||||||
|
{
|
||||||
|
get => _timetableTemplate;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _timetableTemplate)
|
||||||
|
{
|
||||||
|
_timetableTemplate = value;
|
||||||
|
NotifyPropertyChanged(nameof(TimetableTemplate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICommand AddDayCommand { get; set; }
|
||||||
|
public ICommand RemoveDayCommand { get; set; }
|
||||||
|
public ICommand AddHourCommand { get; set; }
|
||||||
|
public ICommand RemoveHourCommand { get; set; }
|
||||||
|
|
||||||
|
public TimetableDay SelectedDay
|
||||||
|
{
|
||||||
|
get => _selectedDay;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_selectedDay != value)
|
||||||
|
{
|
||||||
|
_selectedDay = value;
|
||||||
|
NotifyPropertyChanged(nameof(SelectedDay));
|
||||||
|
NotifyPropertyChanged(nameof(SelectedDayHours));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimetableDay SelectedNewDay
|
||||||
|
{
|
||||||
|
get => _selectedNewDay;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_selectedNewDay != value)
|
||||||
|
{
|
||||||
|
_selectedNewDay = value;
|
||||||
|
NotifyPropertyChanged(nameof(SelectedNewDay));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime? NewHourFrom
|
||||||
|
{
|
||||||
|
get => _newHourFrom;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_newHourFrom = value;
|
||||||
|
NotifyPropertyChanged(nameof(NewHourFrom));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public DateTime? NewHourTo
|
||||||
|
{
|
||||||
|
get => _newHourTo;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_newHourTo = value;
|
||||||
|
NotifyPropertyChanged(nameof(NewHourTo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObservableCollection<TimetableSpan> SelectedDayHours => SelectedDay is not null ? Teacher.AvailabilityHours[SelectedDay] : new ObservableCollection<TimetableSpan>();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public TeacherEditTabViewModel() : this(new TeacherViewModel(new Core.Teacher()), new TimetableTemplateViewModel(new Core.TimetableTemplate()))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public TeacherEditTabViewModel(TeacherViewModel teacher, TimetableTemplateViewModel timetableTemplate) : base()
|
||||||
|
{
|
||||||
|
_teacher = teacher;
|
||||||
|
_timetableTemplate = timetableTemplate;
|
||||||
|
|
||||||
|
AddDayCommand = new RelayCommand<object>(param => AddDay());
|
||||||
|
RemoveDayCommand = new RelayCommand<TimetableDay>(RemoveDay);
|
||||||
|
AddHourCommand = new RelayCommand<object>(param => AddHour());
|
||||||
|
RemoveHourCommand = new RelayCommand<TimetableSpan>(RemoveHour);
|
||||||
|
|
||||||
|
_newHourFrom = new DateTime(1, 1, 1, 8, 0, 0);
|
||||||
|
_newHourTo = new DateTime(1, 1, 1, 16, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PRIVATE METHODS
|
||||||
|
|
||||||
|
private void AddDay()
|
||||||
|
{
|
||||||
|
if (!Teacher.AvailabilityHours.ContainsKey(SelectedNewDay))
|
||||||
|
{
|
||||||
|
Teacher.AddDay(SelectedNewDay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveDay(TimetableDay day)
|
||||||
|
{
|
||||||
|
Teacher.RemoveDay(day);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddHour()
|
||||||
|
{
|
||||||
|
if (NewHourFrom.HasValue && NewHourTo.HasValue)
|
||||||
|
{
|
||||||
|
TimeOnly from = new TimeOnly(NewHourFrom.Value.Hour, NewHourFrom.Value.Minute);
|
||||||
|
TimeOnly to = new TimeOnly(NewHourTo.Value.Hour, NewHourTo.Value.Minute);
|
||||||
|
if (from >= to)
|
||||||
|
{
|
||||||
|
MessageBoxService.ShowError(Resources.TeacherEdit_Message_FromHigherThanTo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Teacher.AddHours(SelectedDay, new TimetableSpan(from, to));
|
||||||
|
}
|
||||||
|
catch (ArgumentException)
|
||||||
|
{
|
||||||
|
MessageBoxService.ShowError(Resources.TeacherEdit_Message_HourCollision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NotifyPropertyChanged(nameof(SelectedDayHours));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveHour(TimetableSpan hour)
|
||||||
|
{
|
||||||
|
Teacher.RemoveHours(SelectedDay, hour);
|
||||||
|
NotifyPropertyChanged(nameof(SelectedDayHours));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
</rib:RibbonGroupBox>
|
</rib:RibbonGroupBox>
|
||||||
<rib:RibbonGroupBox Header="{x:Static p:Resources.Main_Ribbon_Project_New}">
|
<rib:RibbonGroupBox Header="{x:Static p:Resources.Main_Ribbon_Project_New}">
|
||||||
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_New_NewClassroom}" Icon="{StaticResource ClassroomAddImage}" Command="{Binding NewClassroomCommand}"/>
|
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_New_NewClassroom}" Icon="{StaticResource ClassroomAddImage}" Command="{Binding NewClassroomCommand}"/>
|
||||||
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_New_NewTeacher}"/>
|
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_New_NewTeacher}" Icon="{StaticResource TeacherAddImage}" Command="{Binding NewTeacherCommand}"/>
|
||||||
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_New_NewGroup}"/>
|
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_New_NewGroup}"/>
|
||||||
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_New_NewSubgroup}"/>
|
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_New_NewSubgroup}"/>
|
||||||
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_New_NewClass}"/>
|
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_New_NewClass}"/>
|
||||||
@@ -76,9 +76,7 @@
|
|||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<TreeViewItem Header="{Binding Name}" Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=rib:RibbonWindow}, Path=DataContext}">
|
<TreeViewItem Header="{Binding Name}" Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=rib:RibbonWindow}, Path=DataContext}">
|
||||||
<TreeViewItem.InputBindings>
|
<TreeViewItem.InputBindings>
|
||||||
<MouseBinding Gesture="LeftDoubleClick"
|
<MouseBinding Gesture="LeftDoubleClick"/>
|
||||||
Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=rib:RibbonWindow}, Path=DataContext.EditClassroomCommand}"
|
|
||||||
CommandParameter="{Binding}"/>
|
|
||||||
</TreeViewItem.InputBindings>
|
</TreeViewItem.InputBindings>
|
||||||
<TreeViewItem.ContextMenu>
|
<TreeViewItem.ContextMenu>
|
||||||
<ContextMenu>
|
<ContextMenu>
|
||||||
@@ -96,6 +94,35 @@
|
|||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</TreeViewItem.ItemTemplate>
|
</TreeViewItem.ItemTemplate>
|
||||||
</TreeViewItem>
|
</TreeViewItem>
|
||||||
|
<TreeViewItem ItemsSource="{Binding Teachers}">
|
||||||
|
<TreeViewItem.Header>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Image Source="{StaticResource TeacherImage}" Width="18" Height="18"/>
|
||||||
|
<Label Content="{x:Static p:Resources.Main_Treeview_Teachers}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</TreeViewItem.Header>
|
||||||
|
<TreeViewItem.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<TreeViewItem Header="{Binding Name}" Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=rib:RibbonWindow}, Path=DataContext}">
|
||||||
|
<TreeViewItem.InputBindings>
|
||||||
|
<MouseBinding Gesture="LeftDoubleClick"/>
|
||||||
|
</TreeViewItem.InputBindings>
|
||||||
|
<TreeViewItem.ContextMenu>
|
||||||
|
<ContextMenu>
|
||||||
|
<MenuItem Header="{x:Static p:Resources.Main_Treeview_ContextMenu_EditTimetable}"/>
|
||||||
|
<MenuItem Header="{x:Static p:Resources.Main_Treeview_Teachers_ContextMenu_Edit}"
|
||||||
|
Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}, Path=PlacementTarget.Tag.EditTeacherCommand}"
|
||||||
|
CommandParameter="{Binding}"/>
|
||||||
|
<Separator/>
|
||||||
|
<MenuItem Header="{x:Static p:Resources.Main_Treeview_ContextMenu_Remove}"
|
||||||
|
Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}, Path=PlacementTarget.Tag.RemoveTeacherCommand}"
|
||||||
|
CommandParameter="{Binding}"/>
|
||||||
|
</ContextMenu>
|
||||||
|
</TreeViewItem.ContextMenu>
|
||||||
|
</TreeViewItem>
|
||||||
|
</DataTemplate>
|
||||||
|
</TreeViewItem.ItemTemplate>
|
||||||
|
</TreeViewItem>
|
||||||
</TreeViewItem>
|
</TreeViewItem>
|
||||||
</TreeView>
|
</TreeView>
|
||||||
<GridSplitter Grid.Row="1" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Stretch" ShowsPreview="True" Width="2"/>
|
<GridSplitter Grid.Row="1" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Stretch" ShowsPreview="True" Width="2"/>
|
||||||
|
|||||||
@@ -3,10 +3,117 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:TimetableDesigner.Views"
|
xmlns:p = "clr-namespace:TimetableDesigner.Properties"
|
||||||
|
xmlns:vm="clr-namespace:TimetableDesigner.ViewModels"
|
||||||
|
xmlns:local="clr-namespace:TimetableDesigner.Views" xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450" d:DesignWidth="800">
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
<Grid>
|
<UserControl.DataContext>
|
||||||
|
<vm:TeacherEditTabViewModel/>
|
||||||
</Grid>
|
</UserControl.DataContext>
|
||||||
|
<ScrollViewer>
|
||||||
|
<StackPanel>
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Label Grid.Column="0" Grid.Row="0" Content="{x:Static p:Resources.TeacherEdit_Name}"/>
|
||||||
|
<TextBox Grid.Column="1" Grid.Row="0" Margin="5" Text="{Binding Teacher.Name}" MaxLines="1"/>
|
||||||
|
<Label Grid.Column="0" Grid.Row="1" Content="{x:Static p:Resources.TeacherEdit_Description}"/>
|
||||||
|
<TextBox Grid.Column="1" Grid.Row="1" Margin="5" MinLines="3" Text="{Binding Teacher.Description}"/>
|
||||||
|
</Grid>
|
||||||
|
<StackPanel>
|
||||||
|
<Label Content="{x:Static p:Resources.TeacherEdit_AvailabilityHours}"/>
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Border Grid.Column="0" Grid.Row="0" Margin="5" BorderThickness="1" BorderBrush="DarkGray">
|
||||||
|
<ListBox MinHeight="100" ItemsSource="{Binding Teacher.AvailabilityHours.Keys}" SelectedItem="{Binding SelectedDay}" HorizontalContentAlignment="Stretch">
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid HorizontalAlignment="Stretch" Margin="5">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Grid.Column="0" HorizontalAlignment="Stretch" Content="{Binding Name}"/>
|
||||||
|
<Button Grid.Column="1"
|
||||||
|
Width="26"
|
||||||
|
Height="26"
|
||||||
|
Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}, Path=DataContext.RemoveDayCommand}"
|
||||||
|
CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=DataContext}">
|
||||||
|
<Image Source="{StaticResource RemoveImage}" Width="20" Height="20"/>
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListBox.ItemTemplate>
|
||||||
|
</ListBox>
|
||||||
|
</Border>
|
||||||
|
<Image Grid.Column="1" Grid.Row="0" VerticalAlignment="Center" Source="{StaticResource RightArrowImage}" Width="20" Height="20"/>
|
||||||
|
<Border Grid.Column="2" Grid.Row="0" Margin="5" BorderThickness="1" BorderBrush="DarkGray">
|
||||||
|
<ListBox ItemsSource="{Binding SelectedDayHours}" HorizontalContentAlignment="Stretch">
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid HorizontalAlignment="Stretch" Margin="5">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<StackPanel Grid.Column="0" HorizontalAlignment="Stretch" Orientation="Horizontal">
|
||||||
|
<Label Content="{Binding From}"/>
|
||||||
|
<Label Content=" - "/>
|
||||||
|
<Label Content="{Binding To}"/>
|
||||||
|
</StackPanel>
|
||||||
|
<Button Grid.Column="1"
|
||||||
|
Width="26"
|
||||||
|
Height="26"
|
||||||
|
Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}, Path=DataContext.RemoveHourCommand}"
|
||||||
|
CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=DataContext}">
|
||||||
|
<Image Source="{StaticResource RemoveImage}" Width="20" Height="20"/>
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListBox.ItemTemplate>
|
||||||
|
</ListBox>
|
||||||
|
</Border>
|
||||||
|
<Grid Grid.Column="0" Grid.Row="1">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<ComboBox Grid.Column="0" Margin="5" ItemsSource="{Binding TimetableTemplate.Days}" SelectedItem="{Binding SelectedNewDay}" DisplayMemberPath="Name"/>
|
||||||
|
<Button Grid.Column="1" Margin="5" Width="26" Height="26" Command="{Binding AddDayCommand}">
|
||||||
|
<Image Source="{StaticResource AddImage}" Width="20" Height="20"/>
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
<Grid Grid.Column="2" Grid.Row="1">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<xctk:DateTimeUpDown Grid.Column="0" Margin="5" Format="ShortTime" Value="{Binding NewHourFrom}"/>
|
||||||
|
<Label Grid.Column="1" Margin="5" Content="-"/>
|
||||||
|
<xctk:DateTimeUpDown Grid.Column="2" Margin="5" Format="ShortTime" Value="{Binding NewHourTo}"/>
|
||||||
|
<Button Grid.Column="3" Margin="5" Command="{Binding AddHourCommand}" Width="26" Height="26">
|
||||||
|
<Image Source="{StaticResource AddImage}" Width="20" Height="20"/>
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
Reference in New Issue
Block a user