From 95364c8a310822b2a61f38b6c2ae3e911a8ab4af Mon Sep 17 00:00:00 2001 From: Mateusz Skoczek Date: Sun, 12 Mar 2023 12:32:26 +0100 Subject: [PATCH] Project creation, basics --- .gitignore | 135 ++++++ README.md | 0 TimetableDesigner.Core/Class.cs | 21 + TimetableDesigner.Core/Classroom.cs | 35 ++ TimetableDesigner.Core/Group.cs | 20 + TimetableDesigner.Core/Project.cs | 42 ++ TimetableDesigner.Core/Subgroup.cs | 18 + TimetableDesigner.Core/Teacher.cs | 18 + TimetableDesigner.Core/TimetableDay.cs | 28 ++ .../TimetableDesigner.Core.csproj | 9 + TimetableDesigner.Core/TimetableSlot.cs | 75 +++ .../TimetableSlotsCollision.cs | 17 + TimetableDesigner.Core/TimetableTemplate.cs | 80 ++++ .../MessageBoxService.cs | 33 ++ .../MessageBoxYesNoCancelResult.cs | 16 + .../Properties/Resources.Designer.cs | 81 ++++ .../Properties/Resources.resx | 126 +++++ .../TimetableDesigner.MessageBox.csproj | 24 + .../TimetableDesigner.Tests.csproj | 22 + TimetableDesigner.Tests/TimetableTest.cs | 167 +++++++ TimetableDesigner.sln | 61 +++ TimetableDesigner/App.xaml | 15 + TimetableDesigner/App.xaml.cs | 17 + TimetableDesigner/AssemblyInfo.cs | 10 + TimetableDesigner/Commands/RelayCommand.cs | 61 +++ .../Converters/IsNotNullToBooleanConverter.cs | 24 + .../Converters/IsNullToVisibilityConverter.cs | 24 + .../Converters/ViewModelToViewConverter.cs | 57 +++ .../Properties/Resources.Designer.cs | 441 ++++++++++++++++++ .../Properties/Resources.pl-PL.Designer.cs | 63 +++ .../Properties/Resources.pl-PL.resx | 101 ++++ TimetableDesigner/Properties/Resources.resx | 246 ++++++++++ TimetableDesigner/Resources/Converters.xaml | 7 + TimetableDesigner/Resources/Images.xaml | 16 + TimetableDesigner/Resources/Images/Add.png | Bin 0 -> 246 bytes .../Resources/Images/Classroom.png | Bin 0 -> 537 bytes .../Resources/Images/ClassroomAdd.png | Bin 0 -> 3137 bytes TimetableDesigner/Resources/Images/Close.png | Bin 0 -> 360 bytes TimetableDesigner/Resources/Images/New.png | Bin 0 -> 696 bytes TimetableDesigner/Resources/Images/Open.png | Bin 0 -> 599 bytes .../Resources/Images/OpenRecent.png | Bin 0 -> 3050 bytes .../Resources/Images/Project.png | Bin 0 -> 853 bytes .../Resources/Images/ProjectSettings.png | Bin 0 -> 1736 bytes TimetableDesigner/Resources/Images/Remove.png | Bin 0 -> 401 bytes TimetableDesigner/Resources/Images/Save.png | Bin 0 -> 1219 bytes TimetableDesigner/Resources/Images/SaveAs.png | Bin 0 -> 1462 bytes TimetableDesigner/TimetableDesigner.csproj | 103 ++++ .../ViewModels/Base/BaseTabViewModel.cs | 56 +++ .../ViewModels/Base/BaseViewModel.cs | 26 ++ .../ViewModels/ClassroomEditTabViewModel.cs | 52 +++ TimetableDesigner/ViewModels/MainViewModel.cs | 214 +++++++++ .../ViewModels/Models/ClassroomViewModel.cs | 87 ++++ .../ViewModels/Models/ProjectViewModel.cs | 111 +++++ .../ViewModels/Models/TeacherViewModel.cs | 63 +++ .../Models/TimetableTemplateViewModel.cs | 72 +++ .../ViewModels/ProjectSettingsTabViewModel.cs | 140 ++++++ .../ViewModels/TeacherEditTabViewModel.cs | 13 + .../ViewModels/WelcomeTabViewModel.cs | 19 + .../Views/ClassroomEditTabView.xaml | 35 ++ .../Views/ClassroomEditTabView.xaml.cs | 28 ++ TimetableDesigner/Views/MainWindow.xaml | 131 ++++++ TimetableDesigner/Views/MainWindow.xaml.cs | 26 ++ .../Views/ProjectSettingsTabView.xaml | 124 +++++ .../Views/ProjectSettingsTabView.xaml.cs | 25 + .../Views/TeacherEditTabView.xaml | 12 + .../Views/TeacherEditTabView.xaml.cs | 28 ++ TimetableDesigner/Views/WelcomeTabView.xaml | 14 + .../Views/WelcomeTabView.xaml.cs | 28 ++ 68 files changed, 3517 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 TimetableDesigner.Core/Class.cs create mode 100644 TimetableDesigner.Core/Classroom.cs create mode 100644 TimetableDesigner.Core/Group.cs create mode 100644 TimetableDesigner.Core/Project.cs create mode 100644 TimetableDesigner.Core/Subgroup.cs create mode 100644 TimetableDesigner.Core/Teacher.cs create mode 100644 TimetableDesigner.Core/TimetableDay.cs create mode 100644 TimetableDesigner.Core/TimetableDesigner.Core.csproj create mode 100644 TimetableDesigner.Core/TimetableSlot.cs create mode 100644 TimetableDesigner.Core/TimetableSlotsCollision.cs create mode 100644 TimetableDesigner.Core/TimetableTemplate.cs create mode 100644 TimetableDesigner.MessageBox/MessageBoxService.cs create mode 100644 TimetableDesigner.MessageBox/MessageBoxYesNoCancelResult.cs create mode 100644 TimetableDesigner.MessageBox/Properties/Resources.Designer.cs create mode 100644 TimetableDesigner.MessageBox/Properties/Resources.resx create mode 100644 TimetableDesigner.MessageBox/TimetableDesigner.MessageBox.csproj create mode 100644 TimetableDesigner.Tests/TimetableDesigner.Tests.csproj create mode 100644 TimetableDesigner.Tests/TimetableTest.cs create mode 100644 TimetableDesigner.sln create mode 100644 TimetableDesigner/App.xaml create mode 100644 TimetableDesigner/App.xaml.cs create mode 100644 TimetableDesigner/AssemblyInfo.cs create mode 100644 TimetableDesigner/Commands/RelayCommand.cs create mode 100644 TimetableDesigner/Converters/IsNotNullToBooleanConverter.cs create mode 100644 TimetableDesigner/Converters/IsNullToVisibilityConverter.cs create mode 100644 TimetableDesigner/Converters/ViewModelToViewConverter.cs create mode 100644 TimetableDesigner/Properties/Resources.Designer.cs create mode 100644 TimetableDesigner/Properties/Resources.pl-PL.Designer.cs create mode 100644 TimetableDesigner/Properties/Resources.pl-PL.resx create mode 100644 TimetableDesigner/Properties/Resources.resx create mode 100644 TimetableDesigner/Resources/Converters.xaml create mode 100644 TimetableDesigner/Resources/Images.xaml create mode 100644 TimetableDesigner/Resources/Images/Add.png create mode 100644 TimetableDesigner/Resources/Images/Classroom.png create mode 100644 TimetableDesigner/Resources/Images/ClassroomAdd.png create mode 100644 TimetableDesigner/Resources/Images/Close.png create mode 100644 TimetableDesigner/Resources/Images/New.png create mode 100644 TimetableDesigner/Resources/Images/Open.png create mode 100644 TimetableDesigner/Resources/Images/OpenRecent.png create mode 100644 TimetableDesigner/Resources/Images/Project.png create mode 100644 TimetableDesigner/Resources/Images/ProjectSettings.png create mode 100644 TimetableDesigner/Resources/Images/Remove.png create mode 100644 TimetableDesigner/Resources/Images/Save.png create mode 100644 TimetableDesigner/Resources/Images/SaveAs.png create mode 100644 TimetableDesigner/TimetableDesigner.csproj create mode 100644 TimetableDesigner/ViewModels/Base/BaseTabViewModel.cs create mode 100644 TimetableDesigner/ViewModels/Base/BaseViewModel.cs create mode 100644 TimetableDesigner/ViewModels/ClassroomEditTabViewModel.cs create mode 100644 TimetableDesigner/ViewModels/MainViewModel.cs create mode 100644 TimetableDesigner/ViewModels/Models/ClassroomViewModel.cs create mode 100644 TimetableDesigner/ViewModels/Models/ProjectViewModel.cs create mode 100644 TimetableDesigner/ViewModels/Models/TeacherViewModel.cs create mode 100644 TimetableDesigner/ViewModels/Models/TimetableTemplateViewModel.cs create mode 100644 TimetableDesigner/ViewModels/ProjectSettingsTabViewModel.cs create mode 100644 TimetableDesigner/ViewModels/TeacherEditTabViewModel.cs create mode 100644 TimetableDesigner/ViewModels/WelcomeTabViewModel.cs create mode 100644 TimetableDesigner/Views/ClassroomEditTabView.xaml create mode 100644 TimetableDesigner/Views/ClassroomEditTabView.xaml.cs create mode 100644 TimetableDesigner/Views/MainWindow.xaml create mode 100644 TimetableDesigner/Views/MainWindow.xaml.cs create mode 100644 TimetableDesigner/Views/ProjectSettingsTabView.xaml create mode 100644 TimetableDesigner/Views/ProjectSettingsTabView.xaml.cs create mode 100644 TimetableDesigner/Views/TeacherEditTabView.xaml create mode 100644 TimetableDesigner/Views/TeacherEditTabView.xaml.cs create mode 100644 TimetableDesigner/Views/WelcomeTabView.xaml create mode 100644 TimetableDesigner/Views/WelcomeTabView.xaml.cs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0809395 --- /dev/null +++ b/.gitignore @@ -0,0 +1,135 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +[Bb]in/ +[Oo]bj/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.svclog +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml +*.pubxml +*.azurePubxml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +packages/ +## TODO: If the tool you use requires repositories.config, also uncomment the next line +!packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +![Ss]tyle[Cc]op.targets +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml + +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store + +_NCrunch* + +.vs/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/TimetableDesigner.Core/Class.cs b/TimetableDesigner.Core/Class.cs new file mode 100644 index 0000000..ff5275b --- /dev/null +++ b/TimetableDesigner.Core/Class.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TimetableDesigner.Core +{ + public class Class + { + #region PROPERTIES + + public string Name { get; set; } + public string Description { get; set; } + public Teacher Teacher { get; set; } + public Subgroup Subgroup { get; set; } + public Classroom Classroom { get; set; } + + #endregion + } +} diff --git a/TimetableDesigner.Core/Classroom.cs b/TimetableDesigner.Core/Classroom.cs new file mode 100644 index 0000000..a3d7573 --- /dev/null +++ b/TimetableDesigner.Core/Classroom.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading.Tasks; + +namespace TimetableDesigner.Core +{ + public class Classroom + { + #region PROPERTIES + + public string Name { get; set; } + public string Description { get; set; } + public bool IsCapacityLimited { get; set; } + public uint Capacity { get; set; } + + #endregion + + + + #region CONSTRUCTORS + + public Classroom() + { + Name = string.Empty; + Description = string.Empty; + IsCapacityLimited = false; + Capacity = 1; + } + + #endregion + } +} diff --git a/TimetableDesigner.Core/Group.cs b/TimetableDesigner.Core/Group.cs new file mode 100644 index 0000000..dd3321f --- /dev/null +++ b/TimetableDesigner.Core/Group.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TimetableDesigner.Core +{ + public class Group + { + #region PROPERTIES + + public string Name { get; set; } + public string Description { get; set; } + public Subgroup MainSubgroup { get; set; } + public ICollection AssignedSubgroups { get; set; } + + #endregion + } +} diff --git a/TimetableDesigner.Core/Project.cs b/TimetableDesigner.Core/Project.cs new file mode 100644 index 0000000..5f2d38a --- /dev/null +++ b/TimetableDesigner.Core/Project.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TimetableDesigner.Core +{ + [Serializable] + public class Project + { + #region PROPERTIES + + public string Name { get; set; } + public string Author { get; set; } + public string Description { get; set; } + public TimetableTemplate TimetableTemplate { get; set; } + public ICollection Classrooms { get; set; } + public ICollection Teachers { get; set; } + public ICollection Groups { get; set; } + public ICollection Subgroups { get; set; } + public ICollection Classes { get; set; } + + #endregion + + + + #region CONSTRUCTORS + + public Project() + { + Name = string.Empty; + Author = string.Empty; + Description = string.Empty; + TimetableTemplate = new TimetableTemplate(); + Classrooms = new List(); + Teachers = new List(); + } + + #endregion + } +} diff --git a/TimetableDesigner.Core/Subgroup.cs b/TimetableDesigner.Core/Subgroup.cs new file mode 100644 index 0000000..268358c --- /dev/null +++ b/TimetableDesigner.Core/Subgroup.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TimetableDesigner.Core +{ + public class Subgroup + { + #region PROPERTIES + + public string Name { get; set; } + public string Description { get; set; } + + #endregion + } +} diff --git a/TimetableDesigner.Core/Teacher.cs b/TimetableDesigner.Core/Teacher.cs new file mode 100644 index 0000000..fb0cacb --- /dev/null +++ b/TimetableDesigner.Core/Teacher.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TimetableDesigner.Core +{ + public class Teacher + { + #region PROPERTIES + + public string Name { get; set; } + public string Description { get; set; } + + #endregion + } +} diff --git a/TimetableDesigner.Core/TimetableDay.cs b/TimetableDesigner.Core/TimetableDay.cs new file mode 100644 index 0000000..a3d19a9 --- /dev/null +++ b/TimetableDesigner.Core/TimetableDay.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TimetableDesigner.Core +{ + public struct TimetableDay + { + #region PROPERTIES + + public string Name { get; set; } + + #endregion + + + + #region CONSTRUCTORS + + public TimetableDay(string name) + { + Name = name; + } + + #endregion + } +} diff --git a/TimetableDesigner.Core/TimetableDesigner.Core.csproj b/TimetableDesigner.Core/TimetableDesigner.Core.csproj new file mode 100644 index 0000000..cb6a55a --- /dev/null +++ b/TimetableDesigner.Core/TimetableDesigner.Core.csproj @@ -0,0 +1,9 @@ + + + + net7.0-windows + enable + enable + + + diff --git a/TimetableDesigner.Core/TimetableSlot.cs b/TimetableDesigner.Core/TimetableSlot.cs new file mode 100644 index 0000000..8bac068 --- /dev/null +++ b/TimetableDesigner.Core/TimetableSlot.cs @@ -0,0 +1,75 @@ +using System; + +namespace TimetableDesigner.Core +{ + [Serializable] + public struct TimetableSlot + { + #region PROPERTIES + + public TimeOnly From { get; private set; } + public TimeOnly To { get; private set; } + + #endregion + + + + #region CONSTRUCTORS + + public TimetableSlot(TimeOnly from, TimeOnly to) + { + if (to <= from) + { + throw new ArgumentException("\"to\" cannot be less or equal to \"from\""); + } + + From = from; + To = to; + } + + #endregion + + + + #region PUBLIC METHODS + + internal TimetableSlotsCollision CheckCollision(TimetableSlot slot) + { + if (slot.To <= this.From) + { + return TimetableSlotsCollision.CheckedSlotBefore; + } + else if (this.To <= slot.From) + { + return TimetableSlotsCollision.CheckedSlotAfter; + } + else + { + if (this.From < slot.From && slot.To < this.To) + { + return TimetableSlotsCollision.CheckedSlotIn; + } + else if (this.From < slot.From && slot.From < this.To && this.To < slot.To) + { + return TimetableSlotsCollision.CheckedSlotFromIn; + } + else if (slot.From < this.From && this.From < slot.To && slot.To < this.To) + { + return TimetableSlotsCollision.CheckedSlotToIn; + } + else + { + throw new ArgumentException("Unknown collision"); + } + } + } + + public override bool Equals(object? obj) => obj is TimetableSlot slot && From == slot.From && To == slot.To; + + public override int GetHashCode() => HashCode.Combine(From, To); + + public override string? ToString() => $"{From}-{To}"; + + #endregion + } +} diff --git a/TimetableDesigner.Core/TimetableSlotsCollision.cs b/TimetableDesigner.Core/TimetableSlotsCollision.cs new file mode 100644 index 0000000..c698a1e --- /dev/null +++ b/TimetableDesigner.Core/TimetableSlotsCollision.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TimetableDesigner.Core +{ + internal enum TimetableSlotsCollision + { + CheckedSlotBefore, + CheckedSlotAfter, + CheckedSlotIn, + CheckedSlotFromIn, + CheckedSlotToIn + } +} diff --git a/TimetableDesigner.Core/TimetableTemplate.cs b/TimetableDesigner.Core/TimetableTemplate.cs new file mode 100644 index 0000000..a242915 --- /dev/null +++ b/TimetableDesigner.Core/TimetableTemplate.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TimetableDesigner.Core +{ + [Serializable] + public class TimetableTemplate + { + #region FIELDS + + private List _days; + private List _slots; + + #endregion + + + + #region PROPERTIES + + public IEnumerable Days => _days; + public IEnumerable Slots => _slots; + + #endregion + + + + #region CONSTRUCTORS + + public TimetableTemplate() + { + _days = new List(); + _slots = new List(); + } + + #endregion + + + + #region PUBLIC METHODS + + public void AddDay(TimetableDay name) + { + _days.Add(name); + } + + public bool RemoveDay(TimetableDay day) + { + return _days.Remove(day); + } + + public void AddSlot(TimetableSlot 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) + { + return _slots.Remove(slot); + } + + #endregion + } +} diff --git a/TimetableDesigner.MessageBox/MessageBoxService.cs b/TimetableDesigner.MessageBox/MessageBoxService.cs new file mode 100644 index 0000000..3b722b0 --- /dev/null +++ b/TimetableDesigner.MessageBox/MessageBoxService.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Versioning; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using TimetableDesigner.MessageBox.Properties; + +namespace TimetableDesigner.MessageBox +{ + public static class MessageBoxService + { + #region PUBLIC METHODS + + public static void ShowError(string message) => System.Windows.MessageBox.Show(message, Resources.Error, MessageBoxButton.OK, MessageBoxImage.Error); + + public static MessageBoxYesNoCancelResult ShowYesNoCancelQuestion(string message) + { + MessageBoxResult result = System.Windows.MessageBox.Show(message, Resources.Error, MessageBoxButton.YesNoCancel, MessageBoxImage.Question); + switch (result) + { + case MessageBoxResult.Yes: return MessageBoxYesNoCancelResult.Yes; + case MessageBoxResult.No: return MessageBoxYesNoCancelResult.No; + case MessageBoxResult.Cancel: return MessageBoxYesNoCancelResult.Cancel; + default: return MessageBoxYesNoCancelResult.None; + } + } + + #endregion + + } +} diff --git a/TimetableDesigner.MessageBox/MessageBoxYesNoCancelResult.cs b/TimetableDesigner.MessageBox/MessageBoxYesNoCancelResult.cs new file mode 100644 index 0000000..0ac9306 --- /dev/null +++ b/TimetableDesigner.MessageBox/MessageBoxYesNoCancelResult.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TimetableDesigner.MessageBox +{ + public enum MessageBoxYesNoCancelResult + { + Yes, + No, + Cancel, + None + } +} diff --git a/TimetableDesigner.MessageBox/Properties/Resources.Designer.cs b/TimetableDesigner.MessageBox/Properties/Resources.Designer.cs new file mode 100644 index 0000000..29b46ad --- /dev/null +++ b/TimetableDesigner.MessageBox/Properties/Resources.Designer.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace TimetableDesigner.MessageBox.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TimetableDesigner.MessageBox.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Error. + /// + internal static string Error { + get { + return ResourceManager.GetString("Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Question. + /// + internal static string Question { + get { + return ResourceManager.GetString("Question", resourceCulture); + } + } + } +} diff --git a/TimetableDesigner.MessageBox/Properties/Resources.resx b/TimetableDesigner.MessageBox/Properties/Resources.resx new file mode 100644 index 0000000..5a67b65 --- /dev/null +++ b/TimetableDesigner.MessageBox/Properties/Resources.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Error + + + Question + + \ No newline at end of file diff --git a/TimetableDesigner.MessageBox/TimetableDesigner.MessageBox.csproj b/TimetableDesigner.MessageBox/TimetableDesigner.MessageBox.csproj new file mode 100644 index 0000000..9201700 --- /dev/null +++ b/TimetableDesigner.MessageBox/TimetableDesigner.MessageBox.csproj @@ -0,0 +1,24 @@ + + + + net7.0-windows + enable + true + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + diff --git a/TimetableDesigner.Tests/TimetableDesigner.Tests.csproj b/TimetableDesigner.Tests/TimetableDesigner.Tests.csproj new file mode 100644 index 0000000..97a0658 --- /dev/null +++ b/TimetableDesigner.Tests/TimetableDesigner.Tests.csproj @@ -0,0 +1,22 @@ + + + + net7.0-windows + enable + enable + + false + + + + + + + + + + + + + + diff --git a/TimetableDesigner.Tests/TimetableTest.cs b/TimetableDesigner.Tests/TimetableTest.cs new file mode 100644 index 0000000..dc97190 --- /dev/null +++ b/TimetableDesigner.Tests/TimetableTest.cs @@ -0,0 +1,167 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Diagnostics; +using TimetableDesigner.Core; + +namespace TimetableDesigner.Tests +{ + [TestClass] + public class TimetableTest + { + [TestMethod] + public void CreateValidSlotTest() + { + TimetableSlot slot = new TimetableSlot(new TimeOnly(8, 0), new TimeOnly(9, 0)); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void CreateInvalidSlotTest() + { + TimetableSlot slot = new TimetableSlot(new TimeOnly(9, 0), new TimeOnly(8, 0)); + + Assert.Fail(); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void CreateSlotWithZeroLengthTest() + { + TimetableSlot slot = new TimetableSlot(new TimeOnly(8, 0), new TimeOnly(8, 0)); + + Assert.Fail(); + } + + [TestMethod] + public void CreateModelTest() + { + TimetableTemplate model = new TimetableTemplate(); + } + + [TestMethod] + public void AddDayTest() + { + TimetableTemplate model = new TimetableTemplate(); + + TimetableDay day = new TimetableDay + { + Name = "Monday" + }; + + model.AddDay(day); + + Assert.AreEqual(1, model.Days.Count()); + Assert.AreEqual(day, model.Days.ToList()[0]); + } + + [TestMethod] + public void AddSlotTest() + { + TimetableTemplate model = new TimetableTemplate(); + + TimetableSlot slot = new TimetableSlot(new TimeOnly(8, 0), new TimeOnly(9, 0)); + + model.AddSlot(slot); + + Assert.AreEqual(1, model.Slots.Count()); + Assert.AreEqual(new TimetableSlot(new TimeOnly(8, 0), new TimeOnly(9, 0)), model.Slots.ToList()[0]); + } + + [TestMethod] + public void AddNoCollidingSlotsTest() + { + TimetableTemplate model = new TimetableTemplate(); + + TimetableSlot slot1 = new TimetableSlot(new TimeOnly(8, 15), new TimeOnly(9, 0)); + TimetableSlot slot2 = new TimetableSlot(new TimeOnly(9, 15), new TimeOnly(10, 0)); + + model.AddSlot(slot1); + model.AddSlot(slot2); + + 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 TimetableSlot(new TimeOnly(9, 15), new TimeOnly(10, 0)), model.Slots.ToList()[1]); + } + + [TestMethod] + public void AddSlotsWithoutBreakTest() + { + TimetableTemplate model = new TimetableTemplate(); + + TimetableSlot slot1 = new TimetableSlot(new TimeOnly(8, 0), new TimeOnly(9, 0)); + TimetableSlot slot2 = new TimetableSlot(new TimeOnly(9, 0), new TimeOnly(10, 0)); + + model.AddSlot(slot1); + model.AddSlot(slot2); + + 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 TimetableSlot(new TimeOnly(9, 0), new TimeOnly(10, 0)), model.Slots.ToList()[1]); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void AddCollidingSlotsTest() + { + TimetableTemplate model = new TimetableTemplate(); + + TimetableSlot slot1 = new TimetableSlot(new TimeOnly(8, 0), new TimeOnly(9, 30)); + TimetableSlot slot2 = new TimetableSlot(new TimeOnly(8, 30), new TimeOnly(10, 0)); + + model.AddSlot(slot1); + model.AddSlot(slot2); + + Assert.Fail(); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void AddBetweenCollidingSlotsTest() + { + TimetableTemplate model = new TimetableTemplate(); + + TimetableSlot slot1 = new TimetableSlot(new TimeOnly(8, 0), new TimeOnly(9, 0)); + TimetableSlot slot2 = new TimetableSlot(new TimeOnly(10, 0), new TimeOnly(11, 0)); + TimetableSlot slot3 = new TimetableSlot(new TimeOnly(8, 59), new TimeOnly(10, 1)); + + model.AddSlot(slot1); + model.AddSlot(slot2); + model.AddSlot(slot3); + + Assert.Fail(); + } + + [TestMethod] + public void SortSlotsTest() + { + TimetableTemplate model = new TimetableTemplate(); + + TimetableSlot slot1 = new TimetableSlot(new TimeOnly(12, 0), new TimeOnly(13, 0)); + TimetableSlot slot2 = new TimetableSlot(new TimeOnly(8, 0), new TimeOnly(9, 0)); + TimetableSlot slot3 = new TimetableSlot(new TimeOnly(10, 0), new TimeOnly(11, 0)); + TimetableSlot slot4 = new TimetableSlot(new TimeOnly(14, 0), new TimeOnly(15, 0)); + TimetableSlot slot5 = new TimetableSlot(new TimeOnly(13, 0), new TimeOnly(14, 0)); + TimetableSlot slot6 = new TimetableSlot(new TimeOnly(9, 0), new TimeOnly(10, 0)); + TimetableSlot slot7 = new TimetableSlot(new TimeOnly(11, 0), new TimeOnly(12, 0)); + + model.AddSlot(slot1); + model.AddSlot(slot2); + model.AddSlot(slot3); + model.AddSlot(slot4); + model.AddSlot(slot5); + model.AddSlot(slot6); + model.AddSlot(slot7); + + List slots = model.Slots.ToList(); + + TimetableSlot testSlot = slots[0]; + for (int i = 1; i < slots.Count; i++) + { + if (testSlot.To > slots[i].From) + { + Assert.Fail(); + } + testSlot = slots[i]; + } + } + } +} diff --git a/TimetableDesigner.sln b/TimetableDesigner.sln new file mode 100644 index 0000000..ca65abf --- /dev/null +++ b/TimetableDesigner.sln @@ -0,0 +1,61 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33213.308 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TimetableDesigner", "TimetableDesigner\TimetableDesigner.csproj", "{739E5B4E-09D0-468C-9FA0-4BB6D89C1FE0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TimetableDesigner.Core", "TimetableDesigner.Core\TimetableDesigner.Core.csproj", "{A00B17BE-238D-4241-BECC-30119F8CBEE0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TimetableDesigner.Tests", "TimetableDesigner.Tests\TimetableDesigner.Tests.csproj", "{A9B4DB89-A007-472A-9C80-B6340458AC1B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TimetableDesigner.MessageBox", "TimetableDesigner.MessageBox\TimetableDesigner.MessageBox.csproj", "{95992646-6D81-4FF4-885E-8F0BE2312D54}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {739E5B4E-09D0-468C-9FA0-4BB6D89C1FE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {739E5B4E-09D0-468C-9FA0-4BB6D89C1FE0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {739E5B4E-09D0-468C-9FA0-4BB6D89C1FE0}.Debug|x64.ActiveCfg = Debug|x64 + {739E5B4E-09D0-468C-9FA0-4BB6D89C1FE0}.Debug|x64.Build.0 = Debug|x64 + {739E5B4E-09D0-468C-9FA0-4BB6D89C1FE0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {739E5B4E-09D0-468C-9FA0-4BB6D89C1FE0}.Release|Any CPU.Build.0 = Release|Any CPU + {739E5B4E-09D0-468C-9FA0-4BB6D89C1FE0}.Release|x64.ActiveCfg = Release|x64 + {739E5B4E-09D0-468C-9FA0-4BB6D89C1FE0}.Release|x64.Build.0 = Release|x64 + {A00B17BE-238D-4241-BECC-30119F8CBEE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A00B17BE-238D-4241-BECC-30119F8CBEE0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A00B17BE-238D-4241-BECC-30119F8CBEE0}.Debug|x64.ActiveCfg = Debug|Any CPU + {A00B17BE-238D-4241-BECC-30119F8CBEE0}.Debug|x64.Build.0 = Debug|Any CPU + {A00B17BE-238D-4241-BECC-30119F8CBEE0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A00B17BE-238D-4241-BECC-30119F8CBEE0}.Release|Any CPU.Build.0 = Release|Any CPU + {A00B17BE-238D-4241-BECC-30119F8CBEE0}.Release|x64.ActiveCfg = Release|Any CPU + {A00B17BE-238D-4241-BECC-30119F8CBEE0}.Release|x64.Build.0 = Release|Any CPU + {A9B4DB89-A007-472A-9C80-B6340458AC1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A9B4DB89-A007-472A-9C80-B6340458AC1B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A9B4DB89-A007-472A-9C80-B6340458AC1B}.Debug|x64.ActiveCfg = Debug|Any CPU + {A9B4DB89-A007-472A-9C80-B6340458AC1B}.Debug|x64.Build.0 = Debug|Any CPU + {A9B4DB89-A007-472A-9C80-B6340458AC1B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A9B4DB89-A007-472A-9C80-B6340458AC1B}.Release|Any CPU.Build.0 = Release|Any CPU + {A9B4DB89-A007-472A-9C80-B6340458AC1B}.Release|x64.ActiveCfg = Release|Any CPU + {A9B4DB89-A007-472A-9C80-B6340458AC1B}.Release|x64.Build.0 = Release|Any CPU + {95992646-6D81-4FF4-885E-8F0BE2312D54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {95992646-6D81-4FF4-885E-8F0BE2312D54}.Debug|Any CPU.Build.0 = Debug|Any CPU + {95992646-6D81-4FF4-885E-8F0BE2312D54}.Debug|x64.ActiveCfg = Debug|Any CPU + {95992646-6D81-4FF4-885E-8F0BE2312D54}.Debug|x64.Build.0 = Debug|Any CPU + {95992646-6D81-4FF4-885E-8F0BE2312D54}.Release|Any CPU.ActiveCfg = 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.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {948AE685-3476-4374-9ADE-9F57FDE2D8D7} + EndGlobalSection +EndGlobal diff --git a/TimetableDesigner/App.xaml b/TimetableDesigner/App.xaml new file mode 100644 index 0000000..15164af --- /dev/null +++ b/TimetableDesigner/App.xaml @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/TimetableDesigner/App.xaml.cs b/TimetableDesigner/App.xaml.cs new file mode 100644 index 0000000..8114ebc --- /dev/null +++ b/TimetableDesigner/App.xaml.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace TimetableDesigner +{ + public partial class App : Application + { + public App() + { + } + } +} diff --git a/TimetableDesigner/AssemblyInfo.cs b/TimetableDesigner/AssemblyInfo.cs new file mode 100644 index 0000000..8b5504e --- /dev/null +++ b/TimetableDesigner/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/TimetableDesigner/Commands/RelayCommand.cs b/TimetableDesigner/Commands/RelayCommand.cs new file mode 100644 index 0000000..4873f1b --- /dev/null +++ b/TimetableDesigner/Commands/RelayCommand.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; + +namespace TimetableDesigner.Commands +{ + public class RelayCommand : ICommand + { + #region FIELDS + + private readonly Action _execute; + private readonly Predicate _canExecute; + + #endregion + + + + #region CONSTRUCTORS + + public RelayCommand(Action execute) : this(execute, null) { } + + public RelayCommand(Action execute, Predicate canExecute) + { + if (execute == null) + throw new ArgumentNullException("execute"); + + _execute = execute; + _canExecute = canExecute; + } + + #endregion + + + + #region PUBLIC METHODS + + public bool CanExecute(object parameter) => _canExecute == null || _canExecute((T)parameter); + + public void Execute(object parameter) + { + _execute((T)parameter); + } + + #endregion + + + + #region EVENTS + + public event EventHandler CanExecuteChanged + { + add { CommandManager.RequerySuggested += value; } + remove { CommandManager.RequerySuggested -= value; } + } + + #endregion + } +} diff --git a/TimetableDesigner/Converters/IsNotNullToBooleanConverter.cs b/TimetableDesigner/Converters/IsNotNullToBooleanConverter.cs new file mode 100644 index 0000000..f619a64 --- /dev/null +++ b/TimetableDesigner/Converters/IsNotNullToBooleanConverter.cs @@ -0,0 +1,24 @@ +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 +{ + public class IsNotNullToBooleanConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return value is not null; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/TimetableDesigner/Converters/IsNullToVisibilityConverter.cs b/TimetableDesigner/Converters/IsNullToVisibilityConverter.cs new file mode 100644 index 0000000..b707449 --- /dev/null +++ b/TimetableDesigner/Converters/IsNullToVisibilityConverter.cs @@ -0,0 +1,24 @@ +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 +{ + public class IsNullToVisibilityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return value is null ? Visibility.Collapsed : Visibility.Visible; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/TimetableDesigner/Converters/ViewModelToViewConverter.cs b/TimetableDesigner/Converters/ViewModelToViewConverter.cs new file mode 100644 index 0000000..880572f --- /dev/null +++ b/TimetableDesigner/Converters/ViewModelToViewConverter.cs @@ -0,0 +1,57 @@ +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; +using TimetableDesigner.ViewModels; +using TimetableDesigner.ViewModels.Base; +using TimetableDesigner.Views; + +namespace TimetableDesigner.Converters +{ + public class ViewModelToViewConverter : IValueConverter + { + #region FIELDS + + private static readonly Dictionary _viewModelViewPairs = new Dictionary + { + { typeof(MainViewModel), typeof(MainWindow) }, + { typeof(WelcomeTabViewModel), typeof(WelcomeTabView) }, + { typeof(ProjectSettingsTabViewModel), typeof(ProjectSettingsTabView) }, + { typeof(ClassroomEditTabViewModel), typeof(ClassroomEditTabView) }, + }; + + #endregion + + + + #region PUBLIC METHODS + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + BaseViewModel? viewModel = value as BaseViewModel; + if (viewModel is not null) + { + Type view = _viewModelViewPairs[viewModel.GetType()]; + FrameworkElement? viewInstance = Activator.CreateInstance(view) as FrameworkElement; + if (viewInstance is not null ) + { + viewInstance.DataContext = viewModel; + return viewInstance; + } + } + return null; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + + #endregion + } +} diff --git a/TimetableDesigner/Properties/Resources.Designer.cs b/TimetableDesigner/Properties/Resources.Designer.cs new file mode 100644 index 0000000..a4ad81d --- /dev/null +++ b/TimetableDesigner/Properties/Resources.Designer.cs @@ -0,0 +1,441 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace TimetableDesigner.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TimetableDesigner.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Capacity. + /// + public static string ClassroomEdit_Capacity { + get { + return ResourceManager.GetString("ClassroomEdit.Capacity", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Is limited?. + /// + public static string ClassroomEdit_CapacityIsLimited { + get { + return ResourceManager.GetString("ClassroomEdit.CapacityIsLimited", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Description. + /// + public static string ClassroomEdit_Description { + get { + return ResourceManager.GetString("ClassroomEdit.Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Name. + /// + public static string ClassroomEdit_Name { + get { + return ResourceManager.GetString("ClassroomEdit.Name", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New classroom. + /// + public static string Global_DefaultClassroomName { + get { + return ResourceManager.GetString("Global.DefaultClassroomName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New project. + /// + public static string Global_DefaultProjectName { + get { + return ResourceManager.GetString("Global.DefaultProjectName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to no project loaded. + /// + public static string Global_NoProjectLoadedTitle { + get { + return ResourceManager.GetString("Global.NoProjectLoadedTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Project is loaded. Do you want to save?. + /// + public static string Main_Message_SaveCurrentProject { + get { + return ResourceManager.GetString("Main.Message.SaveCurrentProject", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to File. + /// + public static string Main_Ribbon_File { + get { + return ResourceManager.GetString("Main.Ribbon.File", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New/Open. + /// + public static string Main_Ribbon_File_NewOpen { + get { + return ResourceManager.GetString("Main.Ribbon.File.NewOpen", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New. + /// + public static string Main_Ribbon_File_NewOpen_New { + get { + return ResourceManager.GetString("Main.Ribbon.File.NewOpen.New", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Open. + /// + public static string Main_Ribbon_File_NewOpen_Open { + get { + return ResourceManager.GetString("Main.Ribbon.File.NewOpen.Open", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Open recent. + /// + public static string Main_Ribbon_File_NewOpen_OpenRecent { + get { + return ResourceManager.GetString("Main.Ribbon.File.NewOpen.OpenRecent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Save. + /// + public static string Main_Ribbon_File_Save { + get { + return ResourceManager.GetString("Main.Ribbon.File.Save", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Save. + /// + public static string Main_Ribbon_File_Save_Save { + get { + return ResourceManager.GetString("Main.Ribbon.File.Save.Save", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Save as. + /// + public static string Main_Ribbon_File_Save_SaveAs { + get { + return ResourceManager.GetString("Main.Ribbon.File.Save.SaveAs", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Project. + /// + public static string Main_Ribbon_Project { + get { + return ResourceManager.GetString("Main.Ribbon.Project", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New. + /// + public static string Main_Ribbon_Project_New { + get { + return ResourceManager.GetString("Main.Ribbon.Project.New", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New class. + /// + public static string Main_Ribbon_Project_New_NewClass { + get { + return ResourceManager.GetString("Main.Ribbon.Project.New.NewClass", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New classroom. + /// + public static string Main_Ribbon_Project_New_NewClassroom { + get { + return ResourceManager.GetString("Main.Ribbon.Project.New.NewClassroom", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New group. + /// + public static string Main_Ribbon_Project_New_NewGroup { + get { + return ResourceManager.GetString("Main.Ribbon.Project.New.NewGroup", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New subgroup. + /// + public static string Main_Ribbon_Project_New_NewSubgroup { + get { + return ResourceManager.GetString("Main.Ribbon.Project.New.NewSubgroup", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New teacher. + /// + public static string Main_Ribbon_Project_New_NewTeacher { + get { + return ResourceManager.GetString("Main.Ribbon.Project.New.NewTeacher", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Settings. + /// + public static string Main_Ribbon_Project_Settings { + get { + return ResourceManager.GetString("Main.Ribbon.Project.Settings", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Project settings. + /// + public static string Main_Ribbon_Project_Settings_ProjectSettings { + get { + return ResourceManager.GetString("Main.Ribbon.Project.Settings.ProjectSettings", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Classrooms. + /// + public static string Main_Treeview_Classrooms { + get { + return ResourceManager.GetString("Main.Treeview.Classrooms", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Edit classroom. + /// + public static string Main_Treeview_Classrooms_ContextMenu_Edit { + get { + return ResourceManager.GetString("Main.Treeview.Classrooms.ContextMenu.Edit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Edit timetable. + /// + public static string Main_Treeview_ContextMenu_EditTimetable { + get { + return ResourceManager.GetString("Main.Treeview.ContextMenu.EditTimetable", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Remove. + /// + public static string Main_Treeview_ContextMenu_Remove { + get { + return ResourceManager.GetString("Main.Treeview.ContextMenu.Remove", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Error. + /// + public static string MessageBox_Error { + get { + return ResourceManager.GetString("MessageBox.Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Author. + /// + public static string ProjectSettings_Author { + get { + return ResourceManager.GetString("ProjectSettings.Author", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Basics. + /// + public static string ProjectSettings_Basics { + get { + return ResourceManager.GetString("ProjectSettings.Basics", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Days. + /// + public static string ProjectSettings_Days { + get { + return ResourceManager.GetString("ProjectSettings.Days", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Description. + /// + public static string ProjectSettings_Description { + get { + return ResourceManager.GetString("ProjectSettings.Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hours. + /// + public static string ProjectSettings_Hours { + get { + return ResourceManager.GetString("ProjectSettings.Hours", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Length of the class have to be higher than 0 minutes. + /// + public static string ProjectSettings_Message_FromHigherThanTo { + get { + return ResourceManager.GetString("ProjectSettings.Message.FromHigherThanTo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Slot collide with another slot. + /// + public static string ProjectSettings_Message_SlotCollision { + get { + return ResourceManager.GetString("ProjectSettings.Message.SlotCollision", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Name. + /// + public static string ProjectSettings_Name { + get { + return ResourceManager.GetString("ProjectSettings.Name", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Timetable model. + /// + public static string ProjectSettings_TimetableModel { + get { + return ResourceManager.GetString("ProjectSettings.TimetableModel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Classroom editing. + /// + public static string Tabs_ClassroomEdit { + get { + return ResourceManager.GetString("Tabs.ClassroomEdit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Project settings. + /// + public static string Tabs_ProjectSettings { + get { + return ResourceManager.GetString("Tabs.ProjectSettings", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Welcome. + /// + public static string Tabs_Welcome { + get { + return ResourceManager.GetString("Tabs.Welcome", resourceCulture); + } + } + } +} diff --git a/TimetableDesigner/Properties/Resources.pl-PL.Designer.cs b/TimetableDesigner/Properties/Resources.pl-PL.Designer.cs new file mode 100644 index 0000000..8022880 --- /dev/null +++ b/TimetableDesigner/Properties/Resources.pl-PL.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace TimetableDesigner.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Resources___Copy { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources___Copy() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TimetableDesigner.Properties.Resources - Copy", typeof(Resources___Copy).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/TimetableDesigner/Properties/Resources.pl-PL.resx b/TimetableDesigner/Properties/Resources.pl-PL.resx new file mode 100644 index 0000000..4fdb1b6 --- /dev/null +++ b/TimetableDesigner/Properties/Resources.pl-PL.resx @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TimetableDesigner/Properties/Resources.resx b/TimetableDesigner/Properties/Resources.resx new file mode 100644 index 0000000..fba3efd --- /dev/null +++ b/TimetableDesigner/Properties/Resources.resx @@ -0,0 +1,246 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Capacity + + + Is limited? + + + Description + + + Name + + + New classroom + + + New project + + + no project loaded + + + Project is loaded. Do you want to save? + + + File + + + New/Open + + + New + + + Open + + + Open recent + + + Save + + + Save + + + Save as + + + Project + + + New + + + New class + + + New classroom + + + New group + + + New subgroup + + + New teacher + + + Settings + + + Project settings + + + Classrooms + + + Edit classroom + + + Edit timetable + + + Remove + + + Error + + + Author + + + Basics + + + Days + + + Description + + + Hours + + + Length of the class have to be higher than 0 minutes + + + Slot collide with another slot + + + Name + + + Timetable model + + + Classroom editing + + + Project settings + + + Welcome + + \ No newline at end of file diff --git a/TimetableDesigner/Resources/Converters.xaml b/TimetableDesigner/Resources/Converters.xaml new file mode 100644 index 0000000..c98d563 --- /dev/null +++ b/TimetableDesigner/Resources/Converters.xaml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/TimetableDesigner/Resources/Images.xaml b/TimetableDesigner/Resources/Images.xaml new file mode 100644 index 0000000..89c8dbe --- /dev/null +++ b/TimetableDesigner/Resources/Images.xaml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TimetableDesigner/Resources/Images/Add.png b/TimetableDesigner/Resources/Images/Add.png new file mode 100644 index 0000000000000000000000000000000000000000..0032cb4aaa6f24f9ee825d7546629f2a19c52011 GIT binary patch literal 246 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?3oVGw3ym^DWND7eDY z#WAE}&fDvTT!$P4S|9$`(SF1j%;G!wlJ(NFhT8=67qJBSBn!G#@a^Ll3wmqxM=|B# znK#YcA6VoL%xua#kR2b+HR~|L?PAN#>;lD%rs4r`;)Dewvw_+*p?_}EpTsd==;OI? z_~HIdzv6i>G;r=vzb3^OKe^i1J$_;Shj5RxtXEL<(5DUE8*!mvy6>b4)zt+2TlpmZp<>f$Lw0A z<-utioKE|HvELWx=VF(^C+chQH3`c15no&g9gPSx3sxHn9krRI`Q8i7&5c0F+oZb& zdPR-X9mM)*@MJ-IY3kef7&Sq=N$W8%$OLkY_L|jD7bjN_7!+FTfq39tgH@dl+iI0U z8?bEE$=U9};-fI2we}5wRU9|`3D_=DXQ1lfe;e>TFVtrKd%X-OrO0K{ zjG`9Z>qx?6j8@8#Gxj^QwQak<-yh$Z@B4l}&*ypG=Xu^|=A@Iuen~L}F%SqOiL_LL(@200)6g_eIe00U<;d*q=xu zQ!$X~hGqzuOu#@q4D8|dbSq*I**1znbd7Rw3y2B{FeX6unTeT3paB62k%b3GP(rCp zbOZ*np^FCI`P(oEc!R z4TG`SY$#g~N@I{<2xDVo7#s;hB6R_VE;EwK!bj**nQDBAO$}=zGk`&+v&b|mn6HWV zr-idH5D0*SKZvu)fuGc=%n!#05&`2QFa#71`#YT&LH-XqANhh#52CSX%pe;5;{iT% z@e%&Q5J=y@n?&I0|31OU?8 z2;&okv$Aqx&;rS!0LFCLZwba>txyPK6iOEf-IM`}h6ZfOfsxjD7QjNnk$SptJzWIS z4URzT8=?)2b$}N*d_#GI4cr9+o`wH^e11oRO#usgd$cW?$)YhLH?}t0+?5!%x!PQY zk~jJr4Bn_R8Xv&VItD^#&CK12rN-?+a*GlhK-yy*tvZ&wts+uQ@LJ}^UIABPCA_&A1$ zRABZnfFa|bH@pV~68N4Bl;w+ZfIxfF!_&KUtexeP3$j)H^-m=xcBq%8L_co7?awJG zmoJn+v9H(Z1)EV9j^L{Ax;y)ig|zy%xO?efFA?tL^uc|m5y9$A2kx10ERAYQR+(roPGyFGbSC(qJZ6Ms-JQFu&-E6o{}r85Sdomv^69Ej9X<y@JcfMcaN5~pH^BA>9Ex$qlEUx8z_~>6=wa2Ubwh*q6Zc}wl}3OwIU#_ zg0($NY8ESByP`W5R&!s(z!6Q6oDyt1pE%Bo5z~t2`Qgi_Zts4b+3zTbgu>* zq_?fA)Wq4|xCjEx&#g&6Xhr4?ig!qq>>5MeU+)W^@w%m87JSvS6ZL*=6pCN*9r$Ko zu3ysLE(a`kT9>?PlHk>}ygC8yQ6AqpluW8IbW>2T96sNFuIqQ9!3G6^diYe?<0H=B z<9+Vof}PAKmUWq@PX-XmX==Qj_rIl>gPkgL+Wu;}KQ6eWUg~ju zv3TozrI5-KrK?^o4D%Cj|JZV8jB9*Bo?!G|pes5_^YEP?6)m4Vh|w!(ChLHUeUv?P zg-7dT%WNF!eiPr=oKrz&_nz(I(tGgIB>$`lMKj!0p22GCFPCI$TzK!Qv`y$5GTb`x zGCF4lr#VYD?Nu#`Z_K@gi@bDY%V{q|6_>Ao4w z{MqsAH@STkVT$`!+7hC}9#J|YA8|A|qFqazIkooN?}~0!g9YrcN0g5h7VWy%u03cY znE9~kz8SWuR;B}?%6+EnsBifV)6Z;LD5B@>z#E=1XGmgrCvWG9-*1|}%g;quJyl8seRy!m8r;6});URLOjaB2eIoU27s-y3?n*_En;OY=(><=5 z{eE|w9{R#y-C21Hhm;~2)9+AidPTn4eRr9wFW$i&pU+Cg8Z99mRaSIv_(MU+1Dtf0 z=$m3ODFyw~SFe(7vJOU1G>3tHo7rMw_+rO)$K99WqTS&Mq2s-I+l2JsnPt&h>FWZV zpCKG_)W^d)@lueojWIB;C!LI8;8B z$W|=V6m$d)Yb`JK>i0i?*Rxa5HufBA*n4J_;h!6jz?DClmiZ)!F|!?4CPcdu^Drxc zxR^mRJ07#pJ#V=HnaX%nRMgoZSeM#86+M$AwKE`VS8lD#$<8W19MR%7L zPHSb4%5ypFDZ6^CgJEW;9VFkLp@leLs^@ibwV5*)^1>;K7F#UK#BK$tt8p2+3p7lc zY^Ljl+`&EMW5)en`Hlyc8!nNKH=gewRDq?{T$Iz^ztSX}lTOWetV2%Dt?sIGxFlzM zStGTRS8(pR<>Y>JhW6nlX?J^&`JJ+(*`z95sKw;DIYh2P9@7iwk)EX9D4b*azIJ^e eE8U<}a7|dH4%rslP&v&1=a0iWSYNmFi~kdXLn|`? literal 0 HcmV?d00001 diff --git a/TimetableDesigner/Resources/Images/Close.png b/TimetableDesigner/Resources/Images/Close.png new file mode 100644 index 0000000000000000000000000000000000000000..8417c2f40811d33d84471079239436222ff5239d GIT binary patch literal 360 zcmV-u0hj)XP)o}Yo<5Rk0xp-!<;ti9Z~=BeKu-bK16N>~Qs@jk+fge)gx2fr+hmB=rc+1*BJ{#H zW1Uh^fMc)VDHDX`^3s5i+#Wd%MC&Q%FcQUAbaF%W@KYMk7QP$c5E)=7e674tMne=6 zJ_e$=@c%#*8~zuF;=_;iG4+RQ#f2Yx5@y1GgD?@E5AVGCLN#@G6A;1jM=T>#WlGzj zqF?6uVj<*@MXERmiCAHafslmuV0H+ZptqR~LM;DMishervAnG!mN&M<`qtuBxsM40 zy;GG^@IFHm7J3l3lwvF3(cT5^1CFZoPCDRlxm+$6V|oD@AqnaOJb}yr0000F6XU=$305cvGRcfhm%PXeC(|4%74opb*P-96y{ z?EhnGI39$xYA(^=69H6mJP2!7Uxs*M?t|k))&q3+L;w{%pi_N?{+_<_e1~{Jz(5=o1iDm7CbyMXg%P5{4@PM5kN%` zkb)UTJpcuxG4O0O2~h?{lhCu#Bt#h)O+wE`lMrQKGzmS!pM?CM{{C-w?%02wZIk}X zFDv*jJ}3IW*sRF^LX!h-2u$=_#y8P7jG;c1ZBWL5{e@Hil~x!2mz*E@Ut(_ff3ewN z|3znp{1=%P^j~;Nz<{{ICg`2Oeb^S;C1?G-d=JmCNI?|+lS%l}I+j`=UOFq#+- z{O9ZO`p?tp-px>7&otm3Fgdc~zwFXD(ml}S@t?cht#d#<;Be{8f4LP2lz8AjXRBMl zfOr6uVbwO5gD z0mB0`spo+vrzLdvfclmy>Up5q`3BuRptL>Y7n`Qu!s%UT|zgGSL0000Od>3l_|;Z9c{6+BB-0)8J0jrl4z6_*k375L&T~C#Y;pf;O^Jgha?p*A*fW8ECrzlHb|8{`NM&deql9DhR?RK6(ruVX5?4=}3 zMGiUvi#<`D>7gXdNA@@Y=@X_-cT)JFtNE*&>g!3jc zhs6Zghx^?Dwiy)@@HW)t4wyF&Xsh+d>Az5xLB2k;ANBU_Rold``H*V$k=n!0HzD=) lW!qTYJ^1RYU|4 zQ3PcXQ9+>;P!>_7wg_&;rxYoh%C2Z#!18XuYOU>iKW=i*`M&vP&di)i(wN@v8VDo; z27_tPJ!rnrH(v3m!J*GU+zF5W=2~i47 zc9B58z3{NVtf zxcC5nW(cM4?@i*^;=dy^82_6t5PWhBsmyf?l!*69{UoM897z4+#URcXl!{^{9ME+O zD3qZWGNH%|i7sG=gI=I8ToyqAZ0!F61oF9m-B$=j$0{ljAml@?i62dZK4KKWj))_C zgjjzIDN;>h^5ekhAR1o)3Z;1w9BI1eG7`!!xK=j8G zNVe7_ytNhdg2yi?FR-Dzz-7zW|BtWeXcQT;U@%A?e5p(%iC@@SY;!*_W^uK+jOH)& zHwv{-WfGgC$T|fOOGMmQ4#-__4#_Q|QV~xkXG=imaHzl(z?sM6L-mPAF%_MQB47!4 z?3zz4Jb8ierz;BCE$%^AADSV!4?_f6d>BKZ5Sl#_ zXvnZHmat(kr6fL7me0xogIQ$7W_4M$u~%N-{4h1oLNmSXw*3)a&G+`v1VqZ4Rc+wx z1FhQ5x+(c>Nx(TP&yYFN^a^pnO-~)mdWkvq$=J*umZ(DQv2w_jfZ!syI>2@Y(Holb32M_x8GFvy| z$i7x))ZKADqIB_*?|) zD}F-8%W~-l0r&IeXM8DGf@wmCTmGec^Ud3Abyb>tW5Z#QgZOeuY{ zO?AKf_Z_)2ftsODHob6RNvEhY@PbXbwf8j(L@u+t^zWT?{lQe|^Hu*#)qJ2kK|@2m zI%gpXN=A2HD|5VT+IP@g z^>lWjOh>coLuHe{ciB@HT9WQMwLHVYHy)Y9*KJ z`QCUDMfWVy%<-(BCnzUh*EcpZDbY?Va9n+?M1yl*+;pI!+Ogv&*AQx_dpc4wOOwYK;DeK`xO(tA!_M?`MhQsuRHo(Gvm;$d<&Jt#^)1G>s^!? zy8`^m?5TI7Mt-E2H08a6JzD$xz%ilejA!WMlHL<-Fj&~z4e&I3rzwk!)WGy~XOrYa za*YxEqI|r#`Xt(1puFi=&C*>%JRZ^Pp;1B~_U*(9g!L@`#MYvU^x0=oKIhOHeR*V^ zox@ADs>fWGEje1Jl#hOlgKOkYt%bD=@Z}Fi4xx(6qrNOK&Nb$b*vtiDTgRx`Pt$@| zEw9ruR&L2ma+}>A9PHH!T;`g=$mw$2xWQ!Pmu< zmUZ1TUwJxAqz}_LD<}$|h&f$;+(4z_E3EQKKP397-t;YYqis+yD@mBYExiYm4Zi9V zWX=zV9-_CNkr$>Bb|&LCz$@U!@=BtSPr<1>c*|+tGnc0w-KF|Enc(xeJYU3x%Q8c_ z(SDPR2er%hJe^p36^TFXb5}^V9z4a#$*Qr@-`Z%jGv`(BwJvEz-e@Oq`Aqid|FBl( z*`>UiJgV6;hl|S6JACq`L8V-zC3PfyKl0$pOA}GMpQR=Cn7vC;OtZ)&@qs!ztI8`9 zp&n!>gSf zjPJ;${#c1wFWyp#I8<>#zd6{b)3C?C9=ZC9NgCZ2aJhRyO*udL2{IyK^MEVOq_*<7 z@nwhEVQSEPXlIZyYnO*vam}=*k>enc`u2+`eca%up)~{2Fzvy&VZ`wJR(0~6IeWbml literal 0 HcmV?d00001 diff --git a/TimetableDesigner/Resources/Images/Project.png b/TimetableDesigner/Resources/Images/Project.png new file mode 100644 index 0000000000000000000000000000000000000000..efc105328095d47fdbed4199a8167a694dcecbc4 GIT binary patch literal 853 zcmV-b1FHOqP)Be=hSde zak76obfRY&$BbU28J4gCINY*;r2B8Y#MNY3f(prCU@f!Xk1YYsZ$Vs)#2OTzHU&eH zp&)n(IBWgXlx6-1-U701D=&EsIAacA#{k7+P+1SCtQT~l7gXK{D(?qfd;+Q%096cv zE)9Vyhe4Gl&}9>-$_%QqfT~A8N-Icd1F7tw8V9Jx395C1)Gm;E6jV0`(u{*N6CkbI zN4m-FZ@z5X3ReLjt=r3QfX=i1u@wO2!W#guj!@$DDda!~g+BmN+K}Ed z8v|e$uK=R@apZbdxCvm?He~AO!PMC|1u*qvkUIV0qH{f;xdmWqt&lpF!v*Cy17Ng{ z7=TDO3aMkg_#9UdOoJQ8TVI8HBJKdDb_7!Udhr`g%3{_L7BD(jWarr@(=ZYFkR7-& z6JG#RV}aD+`?>ReBwihlU~*gmBwlkz-;65&=E?+jzQl~m94R)u<7!*DiP;|5C_3^+ zoc?eR#ATE?cxV1M0HZQNYLD(bqqfG}LZV*~;hnD^i_a{SeD^g(we}bQqa2PD&pz26 z*z6i*dmz&=50TdO?}xbz<06u8PJ^i)!ahYesN^B2)CiJygXE8504a@6qs7-);y;b1 z-Ftxqxe+8YfQk*ElCD1j*dvtEI1Q1?9RG3pX!9&c)(Mj7cLm_Y?}4mA9}-HtKt((S z9BG^Z6?X6!uwOawSAe|9=p3`xmA991I-%6SZvYjvg?N30sGxn0?||F<1{8OQsh~Z? zUjUoJHaQh_tnnAXrm#~^GW{y20NNe=wHOmccPhyYw@7A~rQ)t{aRq25yrl7*+Z{lN f5FtW@{O|bzZo|BbU;drf00000NkvXXu0mjfTPSzR literal 0 HcmV?d00001 diff --git a/TimetableDesigner/Resources/Images/ProjectSettings.png b/TimetableDesigner/Resources/Images/ProjectSettings.png new file mode 100644 index 0000000000000000000000000000000000000000..2efceaaca6aa3da7ad9e77f8ac9039ffb85e838b GIT binary patch literal 1736 zcmV;(1~>VMP)zTAO3UGodu_UJzoZzZw z3UId9!LjBJ3%#o0FY6NEY^{J}^=%etMNJntyy{^BwjsyhSZ#z~QQHm9&U(C;`3u_< zQ!c>SdK8XTMtD<`GBQSqa&SUw&6#IDIXh377ug%(O;ant2`qP$k>MOb?i#%{NkWhwXtWc}lz~Z5<`R3DCi@ zYB2Mhpo(Er$aaVXoB8c^Q}Y(Gll=06FJ^TyjCKdCwJKN@yOx5w-#P@h>ueMzk2@tp#~%K%4SGoAN-O1t70N zkndrTUl}N{62v<(et~!77eUTykaNz21SYhJeT!LW8#gu9?^R)C@BxrhD#%F=+L#J* zPRB}~3g7Hg!^Y>3@n(XLSr%AY+6f!CJkZ9;63~IXv>-P%*6vY4nwE{E^lV7dvfmbNgg zd}5l41%DQNeDVSK$7Wa-uyMu}Wmh)=TW;VCbi5WG;9fv-Z6$MLV6 z4a&YrDIrfS$R!i>eIjUWEPTRKhQa4+OVQMP4hDk(t*xzSIe!6~BApptkdzMBy|VEL zs4h*4fO{UuNdfvc9`k>Qg(OvFhA*!=#)4nDas}6}T|--28`|63(b3U?x`xv%JU=lF zF%ktLL?Q=E0^*l0;9CN6RpZN$G;m|nAyEv^yuo0=&xXs`p>BkIs2)p0_1K%=gqt0= zarf?BXo~gNFI6B`oQmj#lz*e+lk36+NxPmc;F7(7HmLeus(|-lkc$#x#ps%EYCgwi zey6$-cH9!!`4?l(7A@xbY7kX$2KVpZ$K|WnSoj!`98n1=h!D!KFD~)#v2Vdi=}sH7 zpT0B!uR|c`EOzFPY}iW%16wvs=7+-1^UlMv;6n8D^x(n6ha=#VuxG#Y>GMm;N$pO~ zIlV7Wz__$VPMa&Ot!&LRWiu51EzfK$4=zA|e?NM9dWXaFrPv)SwjjWShh{!G=ZeTV z_aeFEJ$msHDgwEv*o``JRJNSIz&0#X^F!g^_Q-_rU=tocevIGR+DE`k5E>>IY z&?Uu;N@m(TeAt8D-afW$hGw2Ao1IajGP0Hs$TEZ`cxFkN=KQE>W2*UR5q5+Ngk&ut zkY${m5PW0;c>9FSWG%r@NgcRg2VWYWK9t(NsWsUr#@le zBNLMUiHVc0HGQ``CShG@wCITuUhrgFxFBw7X~zhmP-q(&pCXPBBzunhju##8%?lHV enco@f5Bvw!zf3NYeASo$0000Jj`o zLA63G6g~+|VF*>5ewjM8^T2HKCi9bdlf?%?5Ohre41qE5A#n$siRPL^;1NjQ#Dm=9 zl6`3~{Sx@CrIN`K!(Lsvkx zf~T#c0?M|{?={}&U&nNv4V2rwfo15VRwT*ubt^=tlk;*DWo1BsshIb`3EZhvq64tRe>id*u^Fa;8b!h@{cg!2zcATVeSOzW5mFC vhzW3lF@0I_OXI^{H|COSWclWU;J@+(OD*fZIYUMU00000NkvXXu0mjf?MAK< literal 0 HcmV?d00001 diff --git a/TimetableDesigner/Resources/Images/Save.png b/TimetableDesigner/Resources/Images/Save.png new file mode 100644 index 0000000000000000000000000000000000000000..b551de1827bbed9c9fa7c16a128e780a2ccd646d GIT binary patch literal 1219 zcmV;!1U&nRP)K>Aus}jWEJlJg zTlOqi@&ni*F`BlNGSD=X%TSnMiMYeWN$fbWZjIzil zy>hc@p6Ba#KA*0vENfZITGm3=%a7dGZa?(2+Yde5^3%rZZgZ3?pUCL-2I%#lpx=Mu zKgs8Aw-2w=L)+`ZX?M_a+OTXFhSfsTu+eCmP#XpmRfnW#sK|Act2OYVjLfcpts~3Z z%-QeFEf9yl_2Z;Kr`toP+xMY6!-Vjz5AVTlxiD=9O|u2PX+hIX)U_sR^#-JxhKf{& zP_3aPO33W;*!s#2a%g=pufQ1mO^N^kB_Yt>@Mi+_F==2&q3FNv5CTy(TNL)qwY&6@D-%D`7wB3;Lt+)z?}U| z#NlZI1d_mB#<>J1GarE`2RANIj&z^nMQnru5%^5j7iiBc5Ql&1*qsnC%vKO<_%sQ) z?RQ-_tTA}9b>aeir2F|&IS`1!2Lcvm7l^^r1jtq)prq5mGk_+mG6W|ZhrrAA#)Lpg zlu!@|yokp|0UP&9RQU9P$u1DW(*y`)JOnxlUaRYn6|yqb34!8pbRHMW_?zQ>0UA8B zKotJQ_mctyG9G0F-tfClURGpXl8qA=;D+%36a@U0FCj$)DDdeo83f|+69RV?{94w0 z&@gfsMe|=$AvoDKeAUxJL&T)A6A zYEPRA&m<6szy83%_3whb_-!QLwD3ZhuUmMY z2~0b%Ny1B#M1{Y)$0|VCHc7%)Dita`o4}M+nIya@id1+efoXd_N%(TPOod?BgwN;mBZ2UH3H<6#V|Ibf zoTbsO#3emB_(y+mV`CG-U)k2wnFZ2W`_)X=QsejecYdDl$ hYgx-$*2@1;{{h6#&PR)8b)x_P002ovPDHLkV1g77S{wiX literal 0 HcmV?d00001 diff --git a/TimetableDesigner/Resources/Images/SaveAs.png b/TimetableDesigner/Resources/Images/SaveAs.png new file mode 100644 index 0000000000000000000000000000000000000000..e1f8fd1f4875ef5e52c45ae834e6aa5dd4d0b61b GIT binary patch literal 1462 zcmV;n1xfmeP)1opsESLGzzn1F;eF1Vc@r>E&*+L`H0r-y|Fx%ip)o6c-I zGmSg5S(b}_$uH9;P5V6Wyx%)t2L}49zxu1cp33#stoGi{8+vi)4IMjJYS?(TY-Pib zSu~rAXtwU7)w<8F^uEz(L9aJa(;HB0byU?FWJN?U?WygV&){HAsqzvQ&jwmQfTX z*;hxmtlP`0XwN1WF-jz5SZNRSTY~ud?ck z6$LLGyV#Xtua_L^xmkt(Kem%)H-$n-l~2Ek$4Kj z6NN5#CU8l{&_&7np0LBa2@oW~E=OGkr=IVCr;TeDNOn}8i}MJW0v+&yX(mwfEMSL! z^P1)ms7O^Ka{DR~xWcL~R^%>tnmTrYct`cav7{kjgEs_Zco(q2y9v-#AyBHcaW$Z6 zRGQ#4aR@$}FF6Ead7^r@NNPGX%9hng6HxgvI33Fff_68E?`6L5p~Ezk+S?W$9NAng$>@Di&!J*;S4(!{X~aBcX1A_?3L$1p?!F7QK> z74HIec!$6#0dvVB12vO1BNW*~$^@rrLmQS&96n=JK5W8sF;)CfFZpQ`I9_fw{bT_y$ZPbzx9fWt(T3w@moiJt>Sevzf|!WWyVbVT+?wpaGUdi9&K~< z@*IJ8rfS@Yz2B@%U>)JVn>>JA=oS2N?;euLq?JS>ab!h%V7=kB&;W}t`yyuN=Lwv0 zVny(#z(ttp-ig zpsFgW)hZN4fh0*Nm&@RJ9+^M)JK!lN#=o%OH(ywdfUWXR0{-O0=Uwpr1zg%@&EdyC zbHH!*)j~abel6jXH$TPZ(@uC_0=+iu+QA=0I2?9`-*nEefXlS;17E3B7<~4&bJ}R3 z0r0mBc>0VRygz{+qtXw2sZ>HV8ik%b>4d*|z=F2~Z1BDWdd+#S@YFi_e4ZV|>h*e; z1b=gX7d(B&4Sw(^(T6~fhm==%Q4|^6)YKFNK`J_X#52VUW+eIk(vlOR9>HvgdTHh9`6Zt#O=eF*eA z+jxO56beirm&>tavsq*^nV#^GNW>L>qi=zrf@eP-!*d_~U>(f7!c*U`6rSTa3*7u& zf~Wu9-UZrKr!RT_!%^#0xt8$ZaM%(sf0y7lo+)`37!Jxsw(Ts!#LzqziqG2u6i z6$_pPhNhKw1JiQBexBbGlED?_HGzLWn01AJd93h`XMz6eum0+ + + + WinExe + net7.0-windows + enable + true + AnyCPU;x64 + + + + + + + + + + + + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + + + + + + + + + + + + + + Always + + + + + + Resources.pl-PL.resx + True + True + + + True + True + Resources.resx + + + + + + Resources.pl-PL.Designer.cs + PublicResXFileCodeGenerator + + + PublicResXFileCodeGenerator + Resources.Designer.cs + + + + diff --git a/TimetableDesigner/ViewModels/Base/BaseTabViewModel.cs b/TimetableDesigner/ViewModels/Base/BaseTabViewModel.cs new file mode 100644 index 0000000..b1b5798 --- /dev/null +++ b/TimetableDesigner/ViewModels/Base/BaseTabViewModel.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; +using System.Windows.Media; + +namespace TimetableDesigner.ViewModels.Base +{ + public abstract class BaseTabViewModel : BaseViewModel + { + #region FIELDS + + private ImageSource _tabImage; + private string _tabTitle; + private bool _isTabClosable; + + #endregion + + + + #region PROPERTIES + + public ImageSource TabImage + { + get => _tabImage; + set + { + _tabImage = value; + NotifyPropertyChanged(nameof(TabImage)); + } + } + public string TabTitle + { + get => _tabTitle; + set + { + _tabTitle = value; + NotifyPropertyChanged(nameof(TabTitle)); + } + } + public bool IsTabClosable + { + get => _isTabClosable; + set + { + _isTabClosable = value; + NotifyPropertyChanged(nameof(IsTabClosable)); + } + } + + #endregion + } +} diff --git a/TimetableDesigner/ViewModels/Base/BaseViewModel.cs b/TimetableDesigner/ViewModels/Base/BaseViewModel.cs new file mode 100644 index 0000000..c996524 --- /dev/null +++ b/TimetableDesigner/ViewModels/Base/BaseViewModel.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TimetableDesigner.ViewModels.Base +{ + public abstract class BaseViewModel : INotifyPropertyChanged + { + #region PROTECTED METHODS + + protected void NotifyPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + + #endregion + + + + #region EVENTS + + public event PropertyChangedEventHandler? PropertyChanged; + + #endregion + } +} diff --git a/TimetableDesigner/ViewModels/ClassroomEditTabViewModel.cs b/TimetableDesigner/ViewModels/ClassroomEditTabViewModel.cs new file mode 100644 index 0000000..6e15a52 --- /dev/null +++ b/TimetableDesigner/ViewModels/ClassroomEditTabViewModel.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TimetableDesigner.ViewModels.Base; +using TimetableDesigner.ViewModels.Models; + +namespace TimetableDesigner.ViewModels +{ + public class ClassroomEditTabViewModel : BaseTabViewModel + { + #region FIELDS + + private ClassroomViewModel _classroom; + + #endregion + + + + #region PROPERTIES + + public ClassroomViewModel Classroom + { + get => _classroom; + set + { + if (_classroom != value) + { + _classroom = value; + NotifyPropertyChanged(nameof(Classroom)); + } + } + } + + #endregion + + + + #region CONSTRUCTORS + + public ClassroomEditTabViewModel() : this(new ClassroomViewModel(new Core.Classroom())) + { } + + public ClassroomEditTabViewModel(ClassroomViewModel classroom) + { + _classroom = classroom; + } + + #endregion + } +} diff --git a/TimetableDesigner/ViewModels/MainViewModel.cs b/TimetableDesigner/ViewModels/MainViewModel.cs new file mode 100644 index 0000000..70c3c6b --- /dev/null +++ b/TimetableDesigner/ViewModels/MainViewModel.cs @@ -0,0 +1,214 @@ +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.Controls; +using System.Windows.Input; +using TimetableDesigner.Commands; +using TimetableDesigner.ViewModels.Base; +using System.Windows.Navigation; +using TimetableDesigner.Core; +using System.Windows; +using TimetableDesigner.Properties; +using TimetableDesigner.MessageBox; +using System.Reflection; +using TimetableDesigner.ViewModels.Models; +using System.Windows.Data; + +namespace TimetableDesigner.ViewModels +{ + class MainViewModel : BaseViewModel + { + #region FIELDS + + private ProjectViewModel? _project; + + private ObservableCollection _tabs; + private BaseTabViewModel? _selectedTab; + + #endregion + + + + #region PROPERTIES + + public string Version { get; set; } + + public ICommand CloseTabCommand { get; set; } + 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 ObservableCollection Tabs + { + get => _tabs; + set + { + _tabs = value; + NotifyPropertyChanged(nameof(Tabs)); + } + } + public BaseTabViewModel? SelectedTab + { + get => _selectedTab; + set + { + _selectedTab = value; + NotifyPropertyChanged(nameof(SelectedTab)); + } + } + + public ProjectViewModel? Project + { + get => _project; + set + { + if (value != _project) + { + _project = value; + NotifyPropertyChanged(nameof(Project)); + } + } + } + + #endregion + + + + #region CONSTRUCTORS + + public MainViewModel() + { + Version = Assembly.GetExecutingAssembly().GetName().Version.ToString(); + + CloseTabCommand = new RelayCommand(CloseTab); + NewProjectCommand = new RelayCommand(param => NewProject()); + OpenProjectCommand = new RelayCommand(param => OpenProject()); + ProjectSettingsCommand = new RelayCommand(param => ProjectSettings()); + NewClassroomCommand = new RelayCommand(param => NewClassroom()); + EditClassroomCommand = new RelayCommand(EditClassroom); + RemoveClassroomCommand = new RelayCommand(DeleteClassroom); + + _tabs = new ObservableCollection + { + new WelcomeTabViewModel() { TabTitle = Resources.Tabs_Welcome } + }; + _selectedTab = Tabs.Last(); + } + + #endregion + + + + #region PUBLIC METHODS + + private void CloseTab(BaseTabViewModel tab) + { + if (SelectedTab == tab) + { + int index = Tabs.IndexOf(tab); + int before = index - 1; + int after = index + 1; + + BaseTabViewModel newSelectedTab = null; + if (before >= 0) + { + newSelectedTab = Tabs[before]; + } + else if (after >= 0 && after < Tabs.Count - 1) + { + newSelectedTab = Tabs[after]; + } + SelectedTab = newSelectedTab; + } + Tabs.Remove(tab); + } + + private void OpenProject() + { + } + + private void NewProject() + { + if (Project is not null) + { + MessageBoxYesNoCancelResult result = MessageBoxService.ShowYesNoCancelQuestion(Resources.Main_Message_SaveCurrentProject); + + switch (result) + { + case MessageBoxYesNoCancelResult.Yes: break; + case MessageBoxYesNoCancelResult.No: break; + default: return; + } + } + Tabs.Clear(); + + Project project = new Project() + { + Name = Resources.Global_DefaultProjectName, + }; + Project = new ProjectViewModel(project); + ProjectSettings(); + } + + private void ProjectSettings() + { + if (Project is not null) + { + ProjectSettingsTabViewModel projectSettingsTabVM = new ProjectSettingsTabViewModel() + { + Project = Project, + TabTitle = Resources.Tabs_ProjectSettings, + IsTabClosable = true, + }; + Tabs.Add(projectSettingsTabVM); + SelectedTab = Tabs.Last(); + } + } + + private void NewClassroom() + { + if (Project is not null) + { + Classroom classroom = new Classroom() + { + Name = Resources.Global_DefaultClassroomName + }; + ClassroomViewModel classroomVM = new ClassroomViewModel(classroom); + Project.Classrooms.Add(classroomVM); + EditClassroom(classroomVM); + } + } + + private void EditClassroom(ClassroomViewModel classroomViewModel) + { + Debug.WriteLine("textedit"); + ClassroomEditTabViewModel classroomEdit = new ClassroomEditTabViewModel() + { + Classroom = classroomViewModel, + TabTitle = $"{Resources.Tabs_ClassroomEdit}: {classroomViewModel.Name}", + IsTabClosable = true + }; + Tabs.Add(classroomEdit); + SelectedTab = classroomEdit; + } + + private void DeleteClassroom(ClassroomViewModel classroomViewModel) + { + Debug.WriteLine("textdelete"); + if (Project is not null) + { + Project.Classrooms.Remove(classroomViewModel); + } + } + + #endregion + } +} diff --git a/TimetableDesigner/ViewModels/Models/ClassroomViewModel.cs b/TimetableDesigner/ViewModels/Models/ClassroomViewModel.cs new file mode 100644 index 0000000..60ca273 --- /dev/null +++ b/TimetableDesigner/ViewModels/Models/ClassroomViewModel.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TimetableDesigner.Core; +using TimetableDesigner.ViewModels.Base; + +namespace TimetableDesigner.ViewModels.Models +{ + public class ClassroomViewModel : BaseViewModel + { + #region FIELDS + + private Classroom _classroom; + + #endregion + + + + #region PROPERTIES + + public Classroom Classroom => _classroom; + + public string Name + { + get => _classroom.Name; + set + { + if (_classroom.Name != value) + { + _classroom.Name = value; + NotifyPropertyChanged(nameof(Name)); + } + } + } + public string Description + { + get => _classroom.Description; + set + { + if (_classroom.Description != value) + { + _classroom.Description = value; + NotifyPropertyChanged(nameof(Description)); + } + } + } + public bool IsCapacityLimited + { + get => _classroom.IsCapacityLimited; + set + { + if (_classroom.IsCapacityLimited != value) + { + _classroom.IsCapacityLimited = value; + NotifyPropertyChanged(nameof(IsCapacityLimited)); + } + } + } + public uint Capacity + { + get => _classroom.Capacity; + set + { + if (_classroom.Capacity != value) + { + _classroom.Capacity = value; + NotifyPropertyChanged(nameof(Capacity)); + } + } + } + + #endregion + + + + #region CONSTRUCTORS + + public ClassroomViewModel(Classroom classroom) + { + _classroom = classroom; + } + + #endregion + } +} diff --git a/TimetableDesigner/ViewModels/Models/ProjectViewModel.cs b/TimetableDesigner/ViewModels/Models/ProjectViewModel.cs new file mode 100644 index 0000000..b4a5b2d --- /dev/null +++ b/TimetableDesigner/ViewModels/Models/ProjectViewModel.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TimetableDesigner.Core; +using TimetableDesigner.ViewModels.Base; + +namespace TimetableDesigner.ViewModels.Models +{ + public class ProjectViewModel : BaseViewModel + { + #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 Classrooms { get; set; } + + #endregion + + + + #region CONSTRUCTORS + + public ProjectViewModel(Project project) + { + _project = project; + + TimetableTemplate = new TimetableTemplateViewModel(_project.TimetableTemplate); + + Classrooms = new ObservableCollection(); + Classrooms.CollectionChanged += Classrooms_CollectionChanged; + } + + #endregion + + + + #region PRIVATE METHODS + + private void Classrooms_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + IList? added = e.NewItems as IList; + IList? removed = e.OldItems as IList; + + 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); + } + } + } + + #endregion + } +} diff --git a/TimetableDesigner/ViewModels/Models/TeacherViewModel.cs b/TimetableDesigner/ViewModels/Models/TeacherViewModel.cs new file mode 100644 index 0000000..679ed7f --- /dev/null +++ b/TimetableDesigner/ViewModels/Models/TeacherViewModel.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TimetableDesigner.Core; +using TimetableDesigner.ViewModels.Base; + +namespace TimetableDesigner.ViewModels.Models +{ + public class TeacherViewModel : BaseViewModel + { + #region FIELDS + + private Teacher _teacher; + + #endregion + + + + #region PROPERTIES + + public Teacher Teacher => _teacher; + + public string Name + { + get => _teacher.Name; + set + { + if (_teacher.Name != value) + { + _teacher.Name = value; + NotifyPropertyChanged(nameof(Name)); + } + } + } + public string Description + { + get => _teacher.Description; + set + { + if (_teacher.Description != value) + { + _teacher.Description = value; + NotifyPropertyChanged(nameof(Description)); + } + } + } + + #endregion + + + + #region CONSTRUCTORS + + public TeacherViewModel(Teacher teacher) + { + _teacher = teacher; + } + + #endregion + } +} diff --git a/TimetableDesigner/ViewModels/Models/TimetableTemplateViewModel.cs b/TimetableDesigner/ViewModels/Models/TimetableTemplateViewModel.cs new file mode 100644 index 0000000..d434c83 --- /dev/null +++ b/TimetableDesigner/ViewModels/Models/TimetableTemplateViewModel.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TimetableDesigner.Core; +using TimetableDesigner.ViewModels.Base; + +namespace TimetableDesigner.ViewModels.Models +{ + public class TimetableTemplateViewModel : BaseViewModel + { + #region FIELDS + + private TimetableTemplate _timetableTemplate; + + #endregion + + + + #region PROPERTIES + + public TimetableTemplate TimetableTemplate => _timetableTemplate; + + public ObservableCollection Days => new ObservableCollection(_timetableTemplate.Days); + public ObservableCollection Slots => new ObservableCollection(_timetableTemplate.Slots); + + #endregion + + + + #region CONSTRUCTORS + + public TimetableTemplateViewModel(TimetableTemplate timetableTemplate) + { + _timetableTemplate = timetableTemplate; + } + + #endregion + + + + #region PUBLIC METHODS + + public void AddDay(TimetableDay day) + { + _timetableTemplate.AddDay(day); + NotifyPropertyChanged(nameof(Days)); + } + + public void RemoveDay(TimetableDay day) + { + _timetableTemplate.RemoveDay(day); + NotifyPropertyChanged(nameof(Days)); + } + + public void AddSlot(TimetableSlot slot) + { + _timetableTemplate.AddSlot(slot); + NotifyPropertyChanged(nameof(Slots)); + } + + public void RemoveSlot(TimetableSlot slot) + { + _timetableTemplate.RemoveSlot(slot); + NotifyPropertyChanged(nameof(Slots)); + } + + #endregion + } +} diff --git a/TimetableDesigner/ViewModels/ProjectSettingsTabViewModel.cs b/TimetableDesigner/ViewModels/ProjectSettingsTabViewModel.cs new file mode 100644 index 0000000..9de6f09 --- /dev/null +++ b/TimetableDesigner/ViewModels/ProjectSettingsTabViewModel.cs @@ -0,0 +1,140 @@ +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; +using System.Windows.Input; +using TimetableDesigner.Commands; +using TimetableDesigner.Core; +using TimetableDesigner.MessageBox; +using TimetableDesigner.Properties; +using TimetableDesigner.ViewModels.Base; +using TimetableDesigner.ViewModels.Models; + +namespace TimetableDesigner.ViewModels +{ + public class ProjectSettingsTabViewModel : BaseTabViewModel + { + #region FIELDS + + private string _newDayName; + private DateTime? _newSlotFrom; + private DateTime? _newSlotTo; + + #endregion + + + + #region PROPERTIES + + public ICommand AddDayCommand { get; set; } + public ICommand AddSlotCommand { get; set; } + public ICommand RemoveDayCommand { get; set; } + public ICommand RemoveSlotCommand { get; set; } + + public ProjectViewModel? Project { get; set; } + + public string NewDayName + { + get => _newDayName; + set + { + _newDayName = value; + NotifyPropertyChanged(nameof(NewDayName)); + } + } + + public DateTime? NewSlotFrom + { + get => _newSlotFrom; + set + { + _newSlotFrom = value; + NotifyPropertyChanged(nameof(NewSlotFrom)); + } + } + public DateTime? NewSlotTo + { + get => _newSlotTo; + set + { + _newSlotTo = value; + NotifyPropertyChanged(nameof(NewSlotTo)); + } + } + + #endregion + + + + #region CONSTRUCTORS + + public ProjectSettingsTabViewModel() + { + Project = new ProjectViewModel(new Project()); + + AddDayCommand = new RelayCommand(param => AddDay()); + AddSlotCommand = new RelayCommand(param => AddSlot()); + RemoveDayCommand = new RelayCommand(RemoveDay); + RemoveSlotCommand = new RelayCommand(RemoveSlot); + + _newDayName = string.Empty; + _newSlotFrom = new DateTime(1, 1, 1, 8, 0, 0); + _newSlotTo = new DateTime(1, 1, 1, 9, 0, 0); + } + + #endregion + + + + #region PRIVATE METHODS + + private void AddDay() + { + if (!string.IsNullOrWhiteSpace(NewDayName)) + { + Project.TimetableTemplate.AddDay(new TimetableDay(NewDayName)); + NewDayName = string.Empty; + } + } + + private void RemoveDay(TimetableDay day) => Project.TimetableTemplate.RemoveDay(day); + + private void AddSlot() + { + if (NewSlotFrom.HasValue && NewSlotTo.HasValue) + { + TimeOnly from = new TimeOnly(NewSlotFrom.Value.Hour, NewSlotFrom.Value.Minute); + TimeOnly to = new TimeOnly(NewSlotTo.Value.Hour, NewSlotTo.Value.Minute); + if (from >= to) + { + MessageBoxService.ShowError(Resources.ProjectSettings_Message_FromHigherThanTo); + return; + } + + try + { + Project.TimetableTemplate.AddSlot(new TimetableSlot(from, to)); + + double delta = (to - from).TotalMinutes; + DateTime newFrom = NewSlotTo.Value; + DateTime newTo = NewSlotTo.Value.AddMinutes(delta); + NewSlotFrom = newFrom; + NewSlotTo = newTo; + } + catch (ArgumentException) + { + MessageBoxService.ShowError(Resources.ProjectSettings_Message_SlotCollision); + } + } + } + + private void RemoveSlot(TimetableSlot slot) => Project.TimetableTemplate.RemoveSlot(slot); + + #endregion + } +} diff --git a/TimetableDesigner/ViewModels/TeacherEditTabViewModel.cs b/TimetableDesigner/ViewModels/TeacherEditTabViewModel.cs new file mode 100644 index 0000000..eadf0dd --- /dev/null +++ b/TimetableDesigner/ViewModels/TeacherEditTabViewModel.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TimetableDesigner.ViewModels.Base; + +namespace TimetableDesigner.ViewModels +{ + public class TeacherEditTabViewModel : BaseViewModel + { + } +} diff --git a/TimetableDesigner/ViewModels/WelcomeTabViewModel.cs b/TimetableDesigner/ViewModels/WelcomeTabViewModel.cs new file mode 100644 index 0000000..0c833ca --- /dev/null +++ b/TimetableDesigner/ViewModels/WelcomeTabViewModel.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TimetableDesigner.ViewModels.Base; + +namespace TimetableDesigner.ViewModels +{ + public class WelcomeTabViewModel : BaseTabViewModel + { + #region CONSTRUCTORS + + public WelcomeTabViewModel() + { } + + #endregion + } +} diff --git a/TimetableDesigner/Views/ClassroomEditTabView.xaml b/TimetableDesigner/Views/ClassroomEditTabView.xaml new file mode 100644 index 0000000..fdf5937 --- /dev/null +++ b/TimetableDesigner/Views/ClassroomEditTabView.xaml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + diff --git a/TimetableDesigner/Views/ClassroomEditTabView.xaml.cs b/TimetableDesigner/Views/ClassroomEditTabView.xaml.cs new file mode 100644 index 0000000..539f58b --- /dev/null +++ b/TimetableDesigner/Views/ClassroomEditTabView.xaml.cs @@ -0,0 +1,28 @@ +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; + +namespace TimetableDesigner.Views +{ + /// + /// Interaction logic for ClassroomEditTabView.xaml + /// + public partial class ClassroomEditTabView : UserControl + { + public ClassroomEditTabView() + { + InitializeComponent(); + } + } +} diff --git a/TimetableDesigner/Views/MainWindow.xaml b/TimetableDesigner/Views/MainWindow.xaml new file mode 100644 index 0000000..9e9613d --- /dev/null +++ b/TimetableDesigner/Views/MainWindow.xaml @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TimetableDesigner/Views/MainWindow.xaml.cs b/TimetableDesigner/Views/MainWindow.xaml.cs new file mode 100644 index 0000000..034ff1d --- /dev/null +++ b/TimetableDesigner/Views/MainWindow.xaml.cs @@ -0,0 +1,26 @@ +using Fluent; +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; + +namespace TimetableDesigner.Views +{ + public partial class MainWindow : RibbonWindow + { + public MainWindow() + { + InitializeComponent(); + } + } +} diff --git a/TimetableDesigner/Views/ProjectSettingsTabView.xaml b/TimetableDesigner/Views/ProjectSettingsTabView.xaml new file mode 100644 index 0000000..d20a100 --- /dev/null +++ b/TimetableDesigner/Views/ProjectSettingsTabView.xaml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TimetableDesigner/Views/ProjectSettingsTabView.xaml.cs b/TimetableDesigner/Views/ProjectSettingsTabView.xaml.cs new file mode 100644 index 0000000..cbdd6f8 --- /dev/null +++ b/TimetableDesigner/Views/ProjectSettingsTabView.xaml.cs @@ -0,0 +1,25 @@ +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; + +namespace TimetableDesigner.Views +{ + public partial class ProjectSettingsTabView : UserControl + { + public ProjectSettingsTabView() + { + InitializeComponent(); + } + } +} diff --git a/TimetableDesigner/Views/TeacherEditTabView.xaml b/TimetableDesigner/Views/TeacherEditTabView.xaml new file mode 100644 index 0000000..e29592f --- /dev/null +++ b/TimetableDesigner/Views/TeacherEditTabView.xaml @@ -0,0 +1,12 @@ + + + + + diff --git a/TimetableDesigner/Views/TeacherEditTabView.xaml.cs b/TimetableDesigner/Views/TeacherEditTabView.xaml.cs new file mode 100644 index 0000000..4836e41 --- /dev/null +++ b/TimetableDesigner/Views/TeacherEditTabView.xaml.cs @@ -0,0 +1,28 @@ +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; + +namespace TimetableDesigner.Views +{ + /// + /// Interaction logic for TeacherEditTabView.xaml + /// + public partial class TeacherEditTabView : UserControl + { + public TeacherEditTabView() + { + InitializeComponent(); + } + } +} diff --git a/TimetableDesigner/Views/WelcomeTabView.xaml b/TimetableDesigner/Views/WelcomeTabView.xaml new file mode 100644 index 0000000..118f515 --- /dev/null +++ b/TimetableDesigner/Views/WelcomeTabView.xaml @@ -0,0 +1,14 @@ + + + + + + + diff --git a/TimetableDesigner/Views/WelcomeTabView.xaml.cs b/TimetableDesigner/Views/WelcomeTabView.xaml.cs new file mode 100644 index 0000000..3d87246 --- /dev/null +++ b/TimetableDesigner/Views/WelcomeTabView.xaml.cs @@ -0,0 +1,28 @@ +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; + +namespace TimetableDesigner.Views +{ + /// + /// Interaction logic for WelcomeTabView.xaml + /// + public partial class WelcomeTabView : UserControl + { + public WelcomeTabView() + { + InitializeComponent(); + } + } +}