diff --git a/TimetableDesigner.Core/Class.cs b/TimetableDesigner.Core/Class.cs index ff5275b..c401feb 100644 --- a/TimetableDesigner.Core/Class.cs +++ b/TimetableDesigner.Core/Class.cs @@ -11,10 +11,23 @@ namespace TimetableDesigner.Core #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; } + public Teacher? Teacher { get; set; } + public IGroup? Group { get; set; } + public Classroom? Classroom { get; set; } + + #endregion + + + + #region CONSTRUCTORS + + public Class() + { + Name = string.Empty; + Teacher = null; + Group = null; + Classroom = null; + } #endregion } diff --git a/TimetableDesigner.Core/Group.cs b/TimetableDesigner.Core/Group.cs index dd3321f..e4c9e55 100644 --- a/TimetableDesigner.Core/Group.cs +++ b/TimetableDesigner.Core/Group.cs @@ -6,15 +6,27 @@ using System.Threading.Tasks; namespace TimetableDesigner.Core { - public class Group + public class Group : IGroup { #region PROPERTIES public string Name { get; set; } public string Description { get; set; } - public Subgroup MainSubgroup { get; set; } public ICollection AssignedSubgroups { get; set; } #endregion + + + + #region CONSTRUCTORS + + public Group() + { + Name = string.Empty; + Description = string.Empty; + AssignedSubgroups = new HashSet(); + } + + #endregion } } diff --git a/TimetableDesigner.Core/IGroup.cs b/TimetableDesigner.Core/IGroup.cs new file mode 100644 index 0000000..d4d6b83 --- /dev/null +++ b/TimetableDesigner.Core/IGroup.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TimetableDesigner.Core +{ + public interface IGroup + { + #region PROPERTIES + + string Name { get; } + + #endregion + } +} diff --git a/TimetableDesigner.Core/Project.cs b/TimetableDesigner.Core/Project.cs index 5f2d38a..85d9cb2 100644 --- a/TimetableDesigner.Core/Project.cs +++ b/TimetableDesigner.Core/Project.cs @@ -33,8 +33,10 @@ namespace TimetableDesigner.Core Author = string.Empty; Description = string.Empty; TimetableTemplate = new TimetableTemplate(); - Classrooms = new List(); - Teachers = new List(); + Classrooms = new HashSet(); + Teachers = new HashSet(); + Groups = new HashSet(); + Subgroups = new HashSet(); } #endregion diff --git a/TimetableDesigner.Core/Subgroup.cs b/TimetableDesigner.Core/Subgroup.cs index 268358c..2079fed 100644 --- a/TimetableDesigner.Core/Subgroup.cs +++ b/TimetableDesigner.Core/Subgroup.cs @@ -6,12 +6,22 @@ using System.Threading.Tasks; namespace TimetableDesigner.Core { - public class Subgroup + public class Subgroup : IGroup { #region PROPERTIES public string Name { get; set; } - public string Description { get; set; } + + #endregion + + + + #region CONSTRUCTORS + + public Subgroup() + { + Name = string.Empty; + } #endregion } diff --git a/TimetableDesigner.Core/TimetableSpan.cs b/TimetableDesigner.Core/TimetableSpan.cs index cbacd6f..273c930 100644 --- a/TimetableDesigner.Core/TimetableSpan.cs +++ b/TimetableDesigner.Core/TimetableSpan.cs @@ -33,29 +33,29 @@ namespace TimetableDesigner.Core #region PUBLIC METHODS - internal TimetableSpansCollision CheckCollision(TimetableSpan slot) + internal TimetableSpanCollision CheckCollision(TimetableSpan slot) { if (slot.To <= this.From) { - return TimetableSpansCollision.CheckedSlotBefore; + return TimetableSpanCollision.CheckedSlotBefore; } else if (this.To <= slot.From) { - return TimetableSpansCollision.CheckedSlotAfter; + return TimetableSpanCollision.CheckedSlotAfter; } else { if (this.From < slot.From && slot.To < this.To) { - return TimetableSpansCollision.CheckedSlotIn; + return TimetableSpanCollision.CheckedSlotIn; } else if (this.From < slot.From && slot.From < this.To && this.To < slot.To) { - return TimetableSpansCollision.CheckedSlotFromIn; + return TimetableSpanCollision.CheckedSlotFromIn; } else if (slot.From < this.From && this.From < slot.To && slot.To < this.To) { - return TimetableSpansCollision.CheckedSlotToIn; + return TimetableSpanCollision.CheckedSlotToIn; } else { diff --git a/TimetableDesigner.Core/TimetableSpanCollection.cs b/TimetableDesigner.Core/TimetableSpanCollection.cs index 34f0dc4..c1df85e 100644 --- a/TimetableDesigner.Core/TimetableSpanCollection.cs +++ b/TimetableDesigner.Core/TimetableSpanCollection.cs @@ -49,8 +49,8 @@ namespace TimetableDesigner.Core { switch (item.CheckCollision(_list.ElementAt(i))) { - case TimetableSpansCollision.CheckedSlotBefore: i++; break; - case TimetableSpansCollision.CheckedSlotAfter: done ^= true; break; + case TimetableSpanCollision.CheckedSlotBefore: i++; break; + case TimetableSpanCollision.CheckedSlotAfter: done ^= true; break; default: throw new ArgumentException("Slot collide with another slot"); } } diff --git a/TimetableDesigner.Core/TimetableSpansCollision.cs b/TimetableDesigner.Core/TimetableSpanCollision.cs similarity index 87% rename from TimetableDesigner.Core/TimetableSpansCollision.cs rename to TimetableDesigner.Core/TimetableSpanCollision.cs index 6ef758b..6b5229f 100644 --- a/TimetableDesigner.Core/TimetableSpansCollision.cs +++ b/TimetableDesigner.Core/TimetableSpanCollision.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace TimetableDesigner.Core { - internal enum TimetableSpansCollision + internal enum TimetableSpanCollision { CheckedSlotBefore, CheckedSlotAfter, diff --git a/TimetableDesigner.Customs/Collections/ObservableDictionary.cs b/TimetableDesigner.Customs/ObservableDictionary.cs similarity index 98% rename from TimetableDesigner.Customs/Collections/ObservableDictionary.cs rename to TimetableDesigner.Customs/ObservableDictionary.cs index 08de624..88fa142 100644 --- a/TimetableDesigner.Customs/Collections/ObservableDictionary.cs +++ b/TimetableDesigner.Customs/ObservableDictionary.cs @@ -7,7 +7,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace TimetableDesigner.Customs.Collections +namespace TimetableDesigner.Customs { public class ObservableDictionary : ObservableCollection>, IDictionary { @@ -59,7 +59,7 @@ namespace TimetableDesigner.Customs.Collections { foreach (KeyValuePair pair in dictionary) { - this.Add(pair); + Add(pair); } } diff --git a/TimetableDesigner.Customs/Collections/ObservableKeyValuePair.cs b/TimetableDesigner.Customs/ObservableKeyValuePair.cs similarity index 96% rename from TimetableDesigner.Customs/Collections/ObservableKeyValuePair.cs rename to TimetableDesigner.Customs/ObservableKeyValuePair.cs index b8703f6..5d2f725 100644 --- a/TimetableDesigner.Customs/Collections/ObservableKeyValuePair.cs +++ b/TimetableDesigner.Customs/ObservableKeyValuePair.cs @@ -5,7 +5,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace TimetableDesigner.Customs.Collections +namespace TimetableDesigner.Customs { public class ObservableKeyValuePair : INotifyPropertyChanged { diff --git a/TimetableDesigner/ViewModels/Base/BaseViewModel.cs b/TimetableDesigner.Customs/ObservableObject.cs similarity index 75% rename from TimetableDesigner/ViewModels/Base/BaseViewModel.cs rename to TimetableDesigner.Customs/ObservableObject.cs index c996524..d197fdb 100644 --- a/TimetableDesigner/ViewModels/Base/BaseViewModel.cs +++ b/TimetableDesigner.Customs/ObservableObject.cs @@ -5,11 +5,11 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace TimetableDesigner.ViewModels.Base +namespace TimetableDesigner.Customs { - public abstract class BaseViewModel : INotifyPropertyChanged + public class ObservableObject : INotifyPropertyChanged { - #region PROTECTED METHODS + #region PRIVATE METHODS protected void NotifyPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); diff --git a/TimetableDesigner.MessageBox/MessageBoxService.cs b/TimetableDesigner.MessageBox/MessageBoxService.cs deleted file mode 100644 index 3b722b0..0000000 --- a/TimetableDesigner.MessageBox/MessageBoxService.cs +++ /dev/null @@ -1,33 +0,0 @@ -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/Properties/Resources.Designer.cs b/TimetableDesigner.MessageBox/Properties/Resources.Designer.cs deleted file mode 100644 index 29b46ad..0000000 --- a/TimetableDesigner.MessageBox/Properties/Resources.Designer.cs +++ /dev/null @@ -1,81 +0,0 @@ -//------------------------------------------------------------------------------ -// -// 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 deleted file mode 100644 index 5a67b65..0000000 --- a/TimetableDesigner.MessageBox/Properties/Resources.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 deleted file mode 100644 index 9201700..0000000 --- a/TimetableDesigner.MessageBox/TimetableDesigner.MessageBox.csproj +++ /dev/null @@ -1,24 +0,0 @@ - - - - net7.0-windows - enable - true - - - - - True - True - Resources.resx - - - - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - diff --git a/TimetableDesigner.sln b/TimetableDesigner.sln index e180e15..00fd91c 100644 --- a/TimetableDesigner.sln +++ b/TimetableDesigner.sln @@ -9,9 +9,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TimetableDesigner.Core", "T EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TimetableDesigner.Tests", "TimetableDesigner.Tests\TimetableDesigner.Tests.csproj", "{A9B4DB89-A007-472A-9C80-B6340458AC1B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TimetableDesigner.MessageBox", "TimetableDesigner.MessageBox\TimetableDesigner.MessageBox.csproj", "{95992646-6D81-4FF4-885E-8F0BE2312D54}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TimetableDesigner.Customs", "TimetableDesigner.Customs\TimetableDesigner.Customs.csproj", "{BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TimetableDesigner.Customs", "TimetableDesigner.Customs\TimetableDesigner.Customs.csproj", "{BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -45,14 +43,6 @@ Global {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 {BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}.Debug|Any CPU.Build.0 = Debug|Any CPU {BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}.Debug|x64.ActiveCfg = Debug|Any CPU diff --git a/TimetableDesigner/App.xaml.cs b/TimetableDesigner/App.xaml.cs index 8114ebc..3fb8fd4 100644 --- a/TimetableDesigner/App.xaml.cs +++ b/TimetableDesigner/App.xaml.cs @@ -1,10 +1,15 @@ using System; using System.Collections.Generic; +using System.ComponentModel.Design; using System.Configuration; using System.Data; using System.Linq; using System.Threading.Tasks; using System.Windows; +using TimetableDesigner.Services; +using TimetableDesigner.Services.MessageBox; +using TimetableDesigner.Services.Project; +using TimetableDesigner.Services.TabNavigation; namespace TimetableDesigner { @@ -12,6 +17,9 @@ namespace TimetableDesigner { public App() { + ServiceProvider.Instance.AddService(new MessageBoxService()); + ServiceProvider.Instance.AddService(new TabNavigationService()); + ServiceProvider.Instance.AddService(new ProjectService()); } } } diff --git a/TimetableDesigner/Controls/TimetableEditorControl.xaml b/TimetableDesigner/Controls/TimetableEditorControl.xaml new file mode 100644 index 0000000..52d4b1e --- /dev/null +++ b/TimetableDesigner/Controls/TimetableEditorControl.xaml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TimetableDesigner/Controls/TimetableEditorControl.xaml.cs b/TimetableDesigner/Controls/TimetableEditorControl.xaml.cs new file mode 100644 index 0000000..83bed66 --- /dev/null +++ b/TimetableDesigner/Controls/TimetableEditorControl.xaml.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using TimetableDesigner.Services; +using TimetableDesigner.Services.Project; +using TimetableDesigner.ViewModels.Models; + +namespace TimetableDesigner.Controls +{ + public partial class TimetableEditorControl : UserControl + { + #region FIELDS + + private IProjectService _projectService; + + #endregion + + + + #region PROPERTIES + + public IGroupViewModel Group + { + get => (IGroupViewModel)GetValue(GroupProperty); + set => SetValue(GroupProperty, value); + } + public static readonly DependencyProperty GroupProperty = DependencyProperty.Register("Group", typeof(IGroupViewModel), typeof(TimetableEditorControl)); + + #endregion + + + + #region CONSTRUCTORS + + public TimetableEditorControl() + { + _projectService = ServiceProvider.Instance.GetService(); + + InitializeComponent(); + } + + #endregion + } +} diff --git a/TimetableDesigner/Converters/IntegerAddConstantConverter.cs b/TimetableDesigner/Converters/IntegerAddConstantConverter.cs new file mode 100644 index 0000000..b0d0637 --- /dev/null +++ b/TimetableDesigner/Converters/IntegerAddConstantConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; + +namespace TimetableDesigner.Converters +{ + public class IntegerAddConstantConverter : IValueConverter + { + #region PUBLIC METHODS + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => (int)value + (int)parameter; + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => (int)value - (int)parameter; + + #endregion + } +} diff --git a/TimetableDesigner/Converters/ViewModelToViewConverter.cs b/TimetableDesigner/Converters/ViewModelToViewConverter.cs index ced4095..de6717c 100644 --- a/TimetableDesigner/Converters/ViewModelToViewConverter.cs +++ b/TimetableDesigner/Converters/ViewModelToViewConverter.cs @@ -8,7 +8,7 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Data; using TimetableDesigner.ViewModels; -using TimetableDesigner.ViewModels.Base; +using TimetableDesigner.ViewModels.Views; using TimetableDesigner.Views; namespace TimetableDesigner.Converters @@ -20,10 +20,11 @@ namespace TimetableDesigner.Converters private static readonly Dictionary _viewModelViewPairs = new Dictionary { { typeof(MainViewModel), typeof(MainWindow) }, - { typeof(WelcomeTabViewModel), typeof(WelcomeTabView) }, - { typeof(ProjectSettingsTabViewModel), typeof(ProjectSettingsTabView) }, - { typeof(ClassroomEditTabViewModel), typeof(ClassroomEditTabView) }, - { typeof(TeacherEditTabViewModel), typeof(TeacherEditTabView) }, + { typeof(WelcomeViewModel), typeof(WelcomeView) }, + { typeof(ProjectSettingsViewModel), typeof(ProjectSettingsView) }, + { typeof(ClassroomEditViewModel), typeof(ClassroomEditView) }, + { typeof(TeacherEditViewModel), typeof(TeacherEditView) }, + { typeof(GroupEditViewModel), typeof(GroupEditView) }, }; #endregion @@ -34,7 +35,7 @@ namespace TimetableDesigner.Converters public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - BaseViewModel? viewModel = value as BaseViewModel; + BaseViewViewModel? viewModel = value as BaseViewViewModel; if (viewModel is not null) { Type view = _viewModelViewPairs[viewModel.GetType()]; diff --git a/TimetableDesigner/Properties/Resources.Designer.cs b/TimetableDesigner/Properties/Resources.Designer.cs index 0e48220..b16c91b 100644 --- a/TimetableDesigner/Properties/Resources.Designer.cs +++ b/TimetableDesigner/Properties/Resources.Designer.cs @@ -87,6 +87,24 @@ namespace TimetableDesigner.Properties { } } + /// + /// Looks up a localized string similar to Basics. + /// + public static string ClassroomEdit_Groups_Basics { + get { + return ResourceManager.GetString("ClassroomEdit.Groups.Basics", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Capacity. + /// + public static string ClassroomEdit_Groups_Capacity { + get { + return ResourceManager.GetString("ClassroomEdit.Groups.Capacity", resourceCulture); + } + } + /// /// Looks up a localized string similar to Name. /// @@ -105,6 +123,15 @@ namespace TimetableDesigner.Properties { } } + /// + /// Looks up a localized string similar to New group. + /// + public static string Global_DefaultGroupName { + get { + return ResourceManager.GetString("Global.DefaultGroupName", resourceCulture); + } + } + /// /// Looks up a localized string similar to New project. /// @@ -132,6 +159,78 @@ namespace TimetableDesigner.Properties { } } + /// + /// Looks up a localized string similar to Delete. + /// + public static string GroupEdit_DeleteSubgroup { + get { + return ResourceManager.GetString("GroupEdit.DeleteSubgroup", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Description. + /// + public static string GroupEdit_Description { + get { + return ResourceManager.GetString("GroupEdit.Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Basics. + /// + public static string GroupEdit_Groups_Basics { + get { + return ResourceManager.GetString("GroupEdit.Groups.Basics", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Subgroups. + /// + public static string GroupEdit_Groups_Subgroups { + get { + return ResourceManager.GetString("GroupEdit.Groups.Subgroups", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to delete this subgroup. This operation is irreversible. Subgroup will be unassigned for all groups.. + /// + public static string GroupEdit_Message_SubgroupDelete { + get { + return ResourceManager.GetString("GroupEdit.Message.SubgroupDelete", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Name. + /// + public static string GroupEdit_Name { + get { + return ResourceManager.GetString("GroupEdit.Name", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New subgroup name. + /// + public static string GroupEdit_NewSubgroupLabel { + get { + return ResourceManager.GetString("GroupEdit.NewSubgroupLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Subgroups. + /// + public static string GroupEdit_Subgroups { + get { + return ResourceManager.GetString("GroupEdit.Subgroups", resourceCulture); + } + } + /// /// Looks up a localized string similar to Project is loaded. Do you want to save?. /// @@ -141,6 +240,42 @@ namespace TimetableDesigner.Properties { } } + /// + /// Looks up a localized string similar to Export. + /// + public static string Main_Ribbon_Export { + get { + return ResourceManager.GetString("Main.Ribbon.Export", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Timetable. + /// + public static string Main_Ribbon_Export_Timetable { + get { + return ResourceManager.GetString("Main.Ribbon.Export.Timetable", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to PDF. + /// + public static string Main_Ribbon_Export_Timetable_PDF { + get { + return ResourceManager.GetString("Main.Ribbon.Export.Timetable.PDF", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to XLS. + /// + public static string Main_Ribbon_Export_Timetable_XLS { + get { + return ResourceManager.GetString("Main.Ribbon.Export.Timetable.XLS", resourceCulture); + } + } + /// /// Looks up a localized string similar to File. /// @@ -222,6 +357,42 @@ namespace TimetableDesigner.Properties { } } + /// + /// Looks up a localized string similar to Import. + /// + public static string Main_Ribbon_Project_Import { + get { + return ResourceManager.GetString("Main.Ribbon.Project.Import", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Import classrooms. + /// + public static string Main_Ribbon_Project_Import_ImportClassrooms { + get { + return ResourceManager.GetString("Main.Ribbon.Project.Import.ImportClassrooms", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Import groups. + /// + public static string Main_Ribbon_Project_Import_ImportGroups { + get { + return ResourceManager.GetString("Main.Ribbon.Project.Import.ImportGroups", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Import teachers. + /// + public static string Main_Ribbon_Project_Import_ImportTeachers { + get { + return ResourceManager.GetString("Main.Ribbon.Project.Import.ImportTeachers", resourceCulture); + } + } + /// /// Looks up a localized string similar to New. /// @@ -330,6 +501,33 @@ namespace TimetableDesigner.Properties { } } + /// + /// Looks up a localized string similar to Groups. + /// + public static string Main_Treeview_Groups { + get { + return ResourceManager.GetString("Main.Treeview.Groups", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Edit group. + /// + public static string Main_Treeview_Groups_ContextMenu_Edit { + get { + return ResourceManager.GetString("Main.Treeview.Groups.ContextMenu.Edit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to delete this subgroup. This operation is irreversible. Subgroup will be unassigned for all groups.. + /// + public static string Main_Treeview_Subgroups_Message_Remove { + get { + return ResourceManager.GetString("Main.Treeview.Subgroups.Message.Remove", resourceCulture); + } + } + /// /// Looks up a localized string similar to Teachers. /// @@ -357,6 +555,15 @@ namespace TimetableDesigner.Properties { } } + /// + /// Looks up a localized string similar to Question. + /// + public static string MessageBox_Question { + get { + return ResourceManager.GetString("MessageBox.Question", resourceCulture); + } + } + /// /// Looks up a localized string similar to Author. /// @@ -447,6 +654,15 @@ namespace TimetableDesigner.Properties { } } + /// + /// Looks up a localized string similar to Group editing. + /// + public static string Tabs_GroupEdit { + get { + return ResourceManager.GetString("Tabs.GroupEdit", resourceCulture); + } + } + /// /// Looks up a localized string similar to Project settings. /// @@ -475,11 +691,11 @@ namespace TimetableDesigner.Properties { } /// - /// Looks up a localized string similar to Availability hours. + /// Looks up a localized string similar to Days. /// - public static string TeacherEdit_AvailabilityHours { + public static string TeacherEdit_Days { get { - return ResourceManager.GetString("TeacherEdit.AvailabilityHours", resourceCulture); + return ResourceManager.GetString("TeacherEdit.Days", resourceCulture); } } @@ -492,6 +708,33 @@ namespace TimetableDesigner.Properties { } } + /// + /// Looks up a localized string similar to Availability hours. + /// + public static string TeacherEdit_Groups_AvailabilityHours { + get { + return ResourceManager.GetString("TeacherEdit.Groups.AvailabilityHours", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Basics. + /// + public static string TeacherEdit_Groups_Basics { + get { + return ResourceManager.GetString("TeacherEdit.Groups.Basics", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hours. + /// + public static string TeacherEdit_Hours { + get { + return ResourceManager.GetString("TeacherEdit.Hours", resourceCulture); + } + } + /// /// Looks up a localized string similar to "From" value is higher or equal to "To" value. /// diff --git a/TimetableDesigner/Properties/Resources.resx b/TimetableDesigner/Properties/Resources.resx index 5d3e4c2..186698c 100644 --- a/TimetableDesigner/Properties/Resources.resx +++ b/TimetableDesigner/Properties/Resources.resx @@ -126,12 +126,21 @@ Description + + Basics + + + Capacity + Name New classroom + + New group + New project @@ -141,9 +150,45 @@ no project loaded + + Delete + + + Description + + + Basics + + + Subgroups + + + Are you sure you want to delete this subgroup. This operation is irreversible. Subgroup will be unassigned for all groups. + + + Name + + + New subgroup name + + + Subgroups + Project is loaded. Do you want to save? + + Export + + + Timetable + + + PDF + + + XLS + File @@ -171,6 +216,18 @@ Project + + Import + + + Import classrooms + + + Import groups + + + Import teachers + New @@ -207,6 +264,15 @@ Remove + + Groups + + + Edit group + + + Are you sure you want to delete this subgroup. This operation is irreversible. Subgroup will be unassigned for all groups. + Teachers @@ -216,6 +282,9 @@ Error + + Question + Author @@ -246,6 +315,9 @@ Classroom editing + + Group editing + Project settings @@ -255,12 +327,21 @@ Welcome - - Availability hours + + Days Description + + Availability hours + + + Basics + + + Hours + "From" value is higher or equal to "To" value diff --git a/TimetableDesigner/Resources/Converters.xaml b/TimetableDesigner/Resources/Converters.xaml index c98d563..5007b48 100644 --- a/TimetableDesigner/Resources/Converters.xaml +++ b/TimetableDesigner/Resources/Converters.xaml @@ -4,4 +4,5 @@ + \ No newline at end of file diff --git a/TimetableDesigner/Resources/Images.xaml b/TimetableDesigner/Resources/Images.xaml index 27aff9f..e57d965 100644 --- a/TimetableDesigner/Resources/Images.xaml +++ b/TimetableDesigner/Resources/Images.xaml @@ -16,4 +16,6 @@ + + \ No newline at end of file diff --git a/TimetableDesigner/Resources/Images/Group.png b/TimetableDesigner/Resources/Images/Group.png new file mode 100644 index 0000000..7f92400 Binary files /dev/null and b/TimetableDesigner/Resources/Images/Group.png differ diff --git a/TimetableDesigner/Resources/Images/GroupAdd.png b/TimetableDesigner/Resources/Images/GroupAdd.png new file mode 100644 index 0000000..904fca3 Binary files /dev/null and b/TimetableDesigner/Resources/Images/GroupAdd.png differ diff --git a/TimetableDesigner/Resources/Images/StudentsAdd.png b/TimetableDesigner/Resources/Images/StudentsAdd.png new file mode 100644 index 0000000..904fca3 Binary files /dev/null and b/TimetableDesigner/Resources/Images/StudentsAdd.png differ diff --git a/TimetableDesigner/Services/IService.cs b/TimetableDesigner/Services/IService.cs new file mode 100644 index 0000000..a5125ee --- /dev/null +++ b/TimetableDesigner/Services/IService.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TimetableDesigner.Services +{ + public interface IService + { + } +} diff --git a/TimetableDesigner/Services/MessageBox/IMessageBoxService.cs b/TimetableDesigner/Services/MessageBox/IMessageBoxService.cs new file mode 100644 index 0000000..4a9ef90 --- /dev/null +++ b/TimetableDesigner/Services/MessageBox/IMessageBoxService.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TimetableDesigner.Services.MessageBox +{ + public interface IMessageBoxService : IService + { + #region METHODS + + void ShowError(string message); + void ShowError(string message, string title); + + MessageBoxQuestionResult ShowQuestion(string message, bool hideCancelButton = false); + MessageBoxQuestionResult ShowQuestion(string message, string title, bool hideCancelButton = false); + + #endregion + } +} diff --git a/TimetableDesigner.MessageBox/MessageBoxYesNoCancelResult.cs b/TimetableDesigner/Services/MessageBox/MessageBoxQuestionResult.cs similarity index 58% rename from TimetableDesigner.MessageBox/MessageBoxYesNoCancelResult.cs rename to TimetableDesigner/Services/MessageBox/MessageBoxQuestionResult.cs index 0ac9306..f7adc35 100644 --- a/TimetableDesigner.MessageBox/MessageBoxYesNoCancelResult.cs +++ b/TimetableDesigner/Services/MessageBox/MessageBoxQuestionResult.cs @@ -4,13 +4,12 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace TimetableDesigner.MessageBox +namespace TimetableDesigner.Services.MessageBox { - public enum MessageBoxYesNoCancelResult + public enum MessageBoxQuestionResult { Yes, No, - Cancel, - None + Cancel } } diff --git a/TimetableDesigner/Services/MessageBox/MessageBoxService.cs b/TimetableDesigner/Services/MessageBox/MessageBoxService.cs new file mode 100644 index 0000000..440f730 --- /dev/null +++ b/TimetableDesigner/Services/MessageBox/MessageBoxService.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Forms; +using TimetableDesigner.Properties; + +namespace TimetableDesigner.Services.MessageBox +{ + public class MessageBoxService : IMessageBoxService + { + #region PUBLIC METHODS + + public void ShowError(string message) => ShowError(message, Resources.MessageBox_Error); + public void ShowError(string message, string title) => System.Windows.Forms.MessageBox.Show(message, title, MessageBoxButtons.OK, MessageBoxIcon.Error); + + public MessageBoxQuestionResult ShowQuestion(string message, bool hideCancelButton = false) => ShowQuestion(message, Resources.MessageBox_Question, hideCancelButton); + public MessageBoxQuestionResult ShowQuestion(string message, string title, bool hideCancelButton = false) + { + MessageBoxButton buttons = MessageBoxButton.YesNoCancel; + if (hideCancelButton) + { + buttons = MessageBoxButton.YesNo; + } + + MessageBoxResult result = System.Windows.MessageBox.Show(message, title, buttons, MessageBoxImage.Question); + switch (result) + { + case MessageBoxResult.Yes: return MessageBoxQuestionResult.Yes; + case MessageBoxResult.No: return MessageBoxQuestionResult.No; + default: return MessageBoxQuestionResult.Cancel; + } + } + + #endregion + } +} diff --git a/TimetableDesigner/Services/Project/IProjectService.cs b/TimetableDesigner/Services/Project/IProjectService.cs new file mode 100644 index 0000000..d445589 --- /dev/null +++ b/TimetableDesigner/Services/Project/IProjectService.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TimetableDesigner.ViewModels.Models; + +namespace TimetableDesigner.Services.Project +{ + public interface IProjectService : IService + { + #region PROPERTIES + + Core.Project? Project { get; } + ProjectViewModel? ProjectViewModel { get; } + + #endregion + + + + #region METHODS + + void New(); + + void Load(string path); + + void Save(string path); + + #endregion + } +} diff --git a/TimetableDesigner/Services/Project/ProjectService.cs b/TimetableDesigner/Services/Project/ProjectService.cs new file mode 100644 index 0000000..fad1fa0 --- /dev/null +++ b/TimetableDesigner/Services/Project/ProjectService.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TimetableDesigner.Core; +using TimetableDesigner.Customs; +using TimetableDesigner.Properties; +using TimetableDesigner.ViewModels.Models; + +namespace TimetableDesigner.Services.Project +{ + public class ProjectService : ObservableObject, IProjectService + { + #region FIELDS + + private Core.Project? _project; + private ProjectViewModel? _projectViewModel; + + #endregion + + + + #region PROPERTIES + + public Core.Project? Project + { + get => _project; + private set + { + if (_project != value) + { + _project = value; + NotifyPropertyChanged(nameof(Project)); + } + } + } + public ProjectViewModel? ProjectViewModel + { + get => _projectViewModel; + private set + { + if (_projectViewModel != value) + { + _projectViewModel = value; + NotifyPropertyChanged(nameof(ProjectViewModel)); + } + } + } + + #endregion + + + + #region CONSTRUCTORS + + public ProjectService() + { + _project = null; + _projectViewModel = null; + } + + #endregion + + + + #region PUBLIC METHODS + + public void New() + { + Project = new Core.Project() + { + Name = Resources.Global_DefaultProjectName, + }; + ProjectViewModel = new ProjectViewModel(Project); + } + + public void Load(string path) + { + + } + + public void Save(string path) + { + + } + + #endregion + } +} diff --git a/TimetableDesigner/Services/ServiceProvider.cs b/TimetableDesigner/Services/ServiceProvider.cs new file mode 100644 index 0000000..7007c9b --- /dev/null +++ b/TimetableDesigner/Services/ServiceProvider.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TimetableDesigner.Services +{ + public class ServiceProvider + { + #region FIELDS + + private Dictionary _services; + + #endregion + + + + #region CONSTRUCTORS + + public static readonly ServiceProvider Instance = new ServiceProvider(); + + private ServiceProvider() + { + _services = new Dictionary(); + } + + #endregion + + + + #region PUBLIC METHODS + + public void AddService(T service) where T : IService + { + _services[typeof(T)] = service; + } + + public T GetService() where T : IService + { + return (T)_services[typeof(T)]; + } + + #endregion + } +} diff --git a/TimetableDesigner/Services/TabNavigation/ITabNavigationService.cs b/TimetableDesigner/Services/TabNavigation/ITabNavigationService.cs new file mode 100644 index 0000000..c42573e --- /dev/null +++ b/TimetableDesigner/Services/TabNavigation/ITabNavigationService.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TimetableDesigner.Services.TabNavigation +{ + public interface ITabNavigationService : IService, INotifyPropertyChanged + { + #region PROPERTIES + + ObservableCollection Tabs { get; } + TabItem SelectedTab { get; } + + #endregion + + + + #region PUBLIC METHODS + + void AddAndActivate(TabItem item); + + void Add(TabItem item); + + void InsertAndActivate(int index, TabItem item); + + void Insert(int index, TabItem item); + + void Close(TabItem item); + void Close(IEnumerable item); + + void CloseAt(int index); + void CloseAt(IEnumerable indexes); + + void CloseAll(); + + void Activate(TabItem item); + + #endregion + } +} diff --git a/TimetableDesigner/Services/TabNavigation/TabItem.cs b/TimetableDesigner/Services/TabNavigation/TabItem.cs new file mode 100644 index 0000000..a1ffebf --- /dev/null +++ b/TimetableDesigner/Services/TabNavigation/TabItem.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; +using System.Windows.Media; +using TimetableDesigner.Commands; +using TimetableDesigner.Customs; +using TimetableDesigner.ViewModels; + +namespace TimetableDesigner.Services.TabNavigation +{ + public class TabItem : ObservableObject + { + #region FIELDS + + private ITabNavigationService _tabNavigationService; + + private ImageSource _image; + private string _title; + private bool _isClosable; + private BaseViewViewModel _viewModel; + + #endregion + + + + #region PROPERTIES + + public ImageSource Image + { + get => _image; + set + { + if (_image != value) + { + _image = value; + NotifyPropertyChanged(nameof(Image)); + } + } + } + public string Title + { + get => _title; + set + { + if (_title != value) + { + _title = value; + NotifyPropertyChanged(nameof(Title)); + } + } + } + public bool IsClosable + { + get => _isClosable; + set + { + if (_isClosable != value) + { + _isClosable = value; + NotifyPropertyChanged(nameof(IsClosable)); + } + } + } + public BaseViewViewModel ViewModel + { + get => _viewModel; + set + { + if (_viewModel != value) + { + _viewModel = value; + NotifyPropertyChanged(nameof(ViewModel)); + } + } + } + + public ICommand CloseCommand { get; set; } + public ICommand ActivateCommand { get; set; } + + #endregion + + + + #region CONSTRUCTORS + + public TabItem() + { + _tabNavigationService = ServiceProvider.Instance.GetService(); + + CloseCommand = new RelayCommand(args => Close()); + ActivateCommand = new RelayCommand(args => Activate()); + } + + #endregion + + + + #region PUBLIC METHODS + + public void Close() => _tabNavigationService.Close(this); + + public void Activate() => _tabNavigationService.Activate(this); + + #endregion + } +} diff --git a/TimetableDesigner/Services/TabNavigation/TabNavigationService.cs b/TimetableDesigner/Services/TabNavigation/TabNavigationService.cs new file mode 100644 index 0000000..b29f838 --- /dev/null +++ b/TimetableDesigner/Services/TabNavigation/TabNavigationService.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Controls; +using TimetableDesigner.Customs; + +namespace TimetableDesigner.Services.TabNavigation +{ + public class TabNavigationService : ObservableObject, ITabNavigationService + { + #region FIELDS + + private TabItem _selectedTab; + + #endregion + + + + #region PROPERTIES + + public ObservableCollection Tabs { get; private set; } + public TabItem? SelectedTab + { + get => _selectedTab; + private set + { + if (_selectedTab != value) + { + _selectedTab = value; + NotifyPropertyChanged(nameof(SelectedTab)); + } + } + } + + #endregion + + + + #region CONSTRUCTORS + + public TabNavigationService() + { + Tabs = new ObservableCollection(); + SelectedTab = null; + } + + #endregion + + + + #region PUBLIC METHODS + + public void AddAndActivate(TabItem item) + { + Add(item); + Activate(item); + } + + public void Add(TabItem item) => Tabs.Add(item); + + public void InsertAndActivate(int index, TabItem item) + { + Insert(index, item); + Activate(item); + } + + public void Insert(int index, TabItem item) => Tabs.Insert(index, item); + + public void Close(TabItem item) => Close(new List() { item }); + public void Close(IEnumerable items) + { + TabItem selected = SelectedTab; + while (items.Contains(selected) && selected != null) + { + int nextIndex = Tabs.IndexOf(selected) + 1; + if (Tabs.Count > nextIndex) + { + selected = Tabs[nextIndex]; + } + else + { + selected = null; + } + } + if (selected == null) + { + selected = SelectedTab; + while (items.Contains(selected) && selected != null) + { + int prevIndex = Tabs.IndexOf(selected) - 1; + if (prevIndex >= 0) + { + selected = Tabs[prevIndex]; + } + else + { + selected = null; + } + } + } + foreach (TabItem item in items) + { + Tabs.Remove(item); + } + SelectedTab = selected; + } + + public void CloseAt(int index) => CloseAt(new List() { index }); + public void CloseAt(IEnumerable indexes) + { + List items = new List(); + foreach (int index in indexes) + { + if (Tabs.Count > index) + { + items.Add(Tabs[index]); + } + } + Close(items); + } + + public void CloseAll() + { + Tabs.Clear(); + SelectedTab = null; + } + + public void Activate(TabItem item) + { + if (Tabs.Contains(item)) + { + SelectedTab = item; + } + } + + #endregion + } +} diff --git a/TimetableDesigner/TimetableDesigner.csproj b/TimetableDesigner/TimetableDesigner.csproj index ced6d28..3e0ee7c 100644 --- a/TimetableDesigner/TimetableDesigner.csproj +++ b/TimetableDesigner/TimetableDesigner.csproj @@ -8,12 +8,20 @@ AnyCPU;x64 + + + + + + + + @@ -27,6 +35,10 @@ + + + + Always @@ -37,6 +49,12 @@ Always + + Always + + + Always + Always @@ -80,7 +98,6 @@ - diff --git a/TimetableDesigner/ViewModels/Base/BaseTabViewModel.cs b/TimetableDesigner/ViewModels/Base/BaseTabViewModel.cs deleted file mode 100644 index b1b5798..0000000 --- a/TimetableDesigner/ViewModels/Base/BaseTabViewModel.cs +++ /dev/null @@ -1,56 +0,0 @@ -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/BaseModelViewModel.cs b/TimetableDesigner/ViewModels/BaseModelViewModel.cs new file mode 100644 index 0000000..37898b9 --- /dev/null +++ b/TimetableDesigner/ViewModels/BaseModelViewModel.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TimetableDesigner.Customs; + +namespace TimetableDesigner.ViewModels +{ + public abstract class BaseModelViewModel : ObservableObject + { + } +} diff --git a/TimetableDesigner/ViewModels/BaseViewViewModel.cs b/TimetableDesigner/ViewModels/BaseViewViewModel.cs new file mode 100644 index 0000000..d86ea09 --- /dev/null +++ b/TimetableDesigner/ViewModels/BaseViewViewModel.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TimetableDesigner.Customs; + +namespace TimetableDesigner.ViewModels +{ + public abstract class BaseViewViewModel : ObservableObject + { + } +} diff --git a/TimetableDesigner/ViewModels/ClassroomEditTabViewModel.cs b/TimetableDesigner/ViewModels/ClassroomEditTabViewModel.cs deleted file mode 100644 index 0a8f315..0000000 --- a/TimetableDesigner/ViewModels/ClassroomEditTabViewModel.cs +++ /dev/null @@ -1,52 +0,0 @@ -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) : base() - { - _classroom = classroom; - } - - #endregion - } -} diff --git a/TimetableDesigner/ViewModels/MainViewModel.cs b/TimetableDesigner/ViewModels/MainViewModel.cs deleted file mode 100644 index 172feb8..0000000 --- a/TimetableDesigner/ViewModels/MainViewModel.cs +++ /dev/null @@ -1,255 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.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 ICommand NewTeacherCommand { get; set; } - public ICommand EditTeacherCommand { get; set; } - public ICommand RemoveTeacherCommand { 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); - NewTeacherCommand = new RelayCommand(param => NewTeacher()); - EditTeacherCommand = new RelayCommand(EditTeacher); - RemoveTeacherCommand = new RelayCommand(DeleteTeacher); - - _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) - { - ClassroomEditTabViewModel classroomEdit = new ClassroomEditTabViewModel(classroomViewModel) - { - TabTitle = $"{Resources.Tabs_ClassroomEdit}: {classroomViewModel.Name}", - IsTabClosable = true - }; - Tabs.Add(classroomEdit); - SelectedTab = classroomEdit; - } - - private void DeleteClassroom(ClassroomViewModel classroomViewModel) - { - if (Project is not null) - { - Project.Classrooms.Remove(classroomViewModel); - } - } - - private void NewTeacher() - { - if (Project is not null) - { - Teacher teacher = new Teacher() - { - Name = Resources.Global_DefaultTeacherName - }; - TeacherViewModel teacherVM = new TeacherViewModel(teacher); - Project.Teachers.Add(teacherVM); - EditTeacher(teacherVM); - } - } - - private void EditTeacher(TeacherViewModel teacherViewModel) - { - if (Project is not null) - { - TeacherEditTabViewModel teacherEdit = new TeacherEditTabViewModel(teacherViewModel, Project.TimetableTemplate) - { - Teacher = teacherViewModel, - TabTitle = $"{Resources.Tabs_TeacherEdit}: {teacherViewModel.Name}", - IsTabClosable = true - }; - Tabs.Add(teacherEdit); - SelectedTab = teacherEdit; - } - - } - - private void DeleteTeacher(TeacherViewModel teacherViewModel) - { - if (Project is not null) - { - Project.Teachers.Remove(teacherViewModel); - } - } - - #endregion - } -} diff --git a/TimetableDesigner/ViewModels/Models/ClassViewModel.cs b/TimetableDesigner/ViewModels/Models/ClassViewModel.cs new file mode 100644 index 0000000..1fdfc03 --- /dev/null +++ b/TimetableDesigner/ViewModels/Models/ClassViewModel.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Design; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TimetableDesigner.Core; +using TimetableDesigner.Services; +using TimetableDesigner.Services.Project; + +namespace TimetableDesigner.ViewModels.Models +{ + public class ClassViewModel : BaseModelViewModel + { + #region FIELDS + + private IProjectService _projectService; + + private Class _class; + + #endregion + + + + #region PROPERTIES + + public Class Class => _class; + + public string Name + { + get => _class.Name; + set + { + if (_class.Name != value) + { + _class.Name = value; + NotifyPropertyChanged(nameof(Name)); + } + } + } + public TeacherViewModel? Teacher + { + get => _projectService.ProjectViewModel?.Teachers.Where(vm => vm.Teacher == _class.Teacher).FirstOrDefault(); + set + { + if (_class.Teacher != value?.Teacher) + { + _class.Teacher = value?.Teacher; + NotifyPropertyChanged(nameof(Teacher)); + } + } + } + public IGroupViewModel? Group + { + get + { + if (_class.Group?.GetType() == typeof(GroupViewModel)) + { + return _projectService.ProjectViewModel?.Groups.Where(vm => vm.Group == _class.Group).FirstOrDefault(); + } + else if (_class.Group?.GetType() == typeof(SubgroupViewModel)) + { + return _projectService.ProjectViewModel?.Subgroups.Where(vm => vm.Subgroup == _class.Group).FirstOrDefault(); + } + else + { + return null; + } + } + set + { + if (_class.Group != value?.Group) + { + _class.Group = value?.Group; + NotifyPropertyChanged(nameof(Group)); + } + } + } + public ClassroomViewModel? Classroom + { + get => _projectService.ProjectViewModel?.Classrooms.Where(vm => vm.Classroom == _class.Classroom).FirstOrDefault(); + set + { + if (_class.Classroom != value?.Classroom) + { + _class.Classroom = value?.Classroom; + NotifyPropertyChanged(nameof(Classroom)); + } + } + } + + #endregion + + + + #region CONSTRUCTORS + + public ClassViewModel(Class @class) + { + _projectService = ServiceProvider.Instance.GetService(); + + _class = @class; + } + + #endregion + } +} diff --git a/TimetableDesigner/ViewModels/Models/ClassroomViewModel.cs b/TimetableDesigner/ViewModels/Models/ClassroomViewModel.cs index 60ca273..337405e 100644 --- a/TimetableDesigner/ViewModels/Models/ClassroomViewModel.cs +++ b/TimetableDesigner/ViewModels/Models/ClassroomViewModel.cs @@ -4,11 +4,10 @@ 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 + public class ClassroomViewModel : BaseModelViewModel { #region FIELDS diff --git a/TimetableDesigner/ViewModels/Models/GroupViewModel.cs b/TimetableDesigner/ViewModels/Models/GroupViewModel.cs new file mode 100644 index 0000000..a64c978 --- /dev/null +++ b/TimetableDesigner/ViewModels/Models/GroupViewModel.cs @@ -0,0 +1,88 @@ +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.Services; +using TimetableDesigner.Services.Project; + +namespace TimetableDesigner.ViewModels.Models +{ + public class GroupViewModel : BaseModelViewModel, IGroupViewModel + { + #region FIELDS + + private IProjectService _projectService; + + private Group _group; + + #endregion + + + + #region PROPERTIES + + IGroup IGroupViewModel.Group => _group; + public Group Group => _group; + + public string Name + { + get => _group.Name; + set + { + if (_group.Name != value) + { + _group.Name = value; + NotifyPropertyChanged(nameof(Name)); + } + } + } + public string Description + { + get => _group.Description; + set + { + if (_group.Description != value) + { + _group.Description = value; + NotifyPropertyChanged(nameof(Description)); + } + } + } + public ObservableCollection AssignedSubgroups => new ObservableCollection(_projectService.ProjectViewModel.Subgroups.Where(vm => Group.AssignedSubgroups.Contains(vm.Subgroup))); + + #endregion + + + + #region CONSTRUCTORS + + public GroupViewModel(Group group) + { + _projectService = ServiceProvider.Instance.GetService(); + _group = group; + } + + #endregion + + + + #region PUBLIC METHODS + + public void AddSubgroup(SubgroupViewModel subgroup) + { + Group.AssignedSubgroups.Add(subgroup.Subgroup); + NotifyPropertyChanged(nameof(AssignedSubgroups)); + } + + public void RemoveSubgroup(SubgroupViewModel subgroup) + { + Group.AssignedSubgroups.Remove(subgroup.Subgroup); + NotifyPropertyChanged(nameof(AssignedSubgroups)); + } + + #endregion + } +} diff --git a/TimetableDesigner/ViewModels/Models/IGroupViewModel.cs b/TimetableDesigner/ViewModels/Models/IGroupViewModel.cs new file mode 100644 index 0000000..2b054d9 --- /dev/null +++ b/TimetableDesigner/ViewModels/Models/IGroupViewModel.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TimetableDesigner.Core; + +namespace TimetableDesigner.ViewModels.Models +{ + public interface IGroupViewModel + { + #region PROPERTIES + + IGroup Group { get; } + string Name { get; } + + #endregion + } +} diff --git a/TimetableDesigner/ViewModels/Models/ProjectViewModel.cs b/TimetableDesigner/ViewModels/Models/ProjectViewModel.cs index 01f853b..5046821 100644 --- a/TimetableDesigner/ViewModels/Models/ProjectViewModel.cs +++ b/TimetableDesigner/ViewModels/Models/ProjectViewModel.cs @@ -5,11 +5,10 @@ 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 + public class ProjectViewModel : BaseModelViewModel { #region FIELDS @@ -62,6 +61,8 @@ namespace TimetableDesigner.ViewModels.Models public TimetableTemplateViewModel TimetableTemplate { get; set; } public ObservableCollection Classrooms { get; set; } public ObservableCollection Teachers { get; set; } + public ObservableCollection Groups { get; set; } + public ObservableCollection Subgroups { get; set; } #endregion @@ -80,6 +81,12 @@ namespace TimetableDesigner.ViewModels.Models Teachers = new ObservableCollection(); Teachers.CollectionChanged += Teachers_CollectionChanged; + + Groups = new ObservableCollection(); + Groups.CollectionChanged += Groups_CollectionChanged; + + Subgroups = new ObservableCollection(); + Subgroups.CollectionChanged += Subgroups_CollectionChanged; } #endregion @@ -132,6 +139,50 @@ namespace TimetableDesigner.ViewModels.Models } } + private void Groups_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 (GroupViewModel vm in removed) + { + _project.Groups.Remove(vm.Group); + } + } + + if (added is not null) + { + foreach (GroupViewModel vm in added) + { + _project.Groups.Add(vm.Group); + } + } + } + + private void Subgroups_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + IList? added = e.NewItems as IList; + IList? removed = e.OldItems as IList; + + if (removed is not null) + { + foreach (SubgroupViewModel vm in removed) + { + _project.Subgroups.Remove(vm.Subgroup); + } + } + + if (added is not null) + { + foreach (SubgroupViewModel vm in added) + { + _project.Subgroups.Add(vm.Subgroup); + } + } + } + #endregion } } diff --git a/TimetableDesigner/ViewModels/Models/SubgroupViewModel.cs b/TimetableDesigner/ViewModels/Models/SubgroupViewModel.cs new file mode 100644 index 0000000..3f6ac8e --- /dev/null +++ b/TimetableDesigner/ViewModels/Models/SubgroupViewModel.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TimetableDesigner.Core; + +namespace TimetableDesigner.ViewModels.Models +{ + public class SubgroupViewModel : BaseModelViewModel, IGroupViewModel + { + #region FIELDS + + private Subgroup _subgroup; + + #endregion + + + + #region PROPERTIES + + IGroup IGroupViewModel.Group => _subgroup; + public Subgroup Subgroup => _subgroup; + + public string Name + { + get => _subgroup.Name; + set + { + if (_subgroup.Name != value) + { + _subgroup.Name = value; + NotifyPropertyChanged(nameof(Name)); + } + } + } + + #endregion + + + + #region CONSTRUCTORS + + public SubgroupViewModel(Subgroup subgroup) + { + _subgroup = subgroup; + } + + #endregion + } +} diff --git a/TimetableDesigner/ViewModels/Models/TeacherViewModel.cs b/TimetableDesigner/ViewModels/Models/TeacherViewModel.cs index b899218..77e207d 100644 --- a/TimetableDesigner/ViewModels/Models/TeacherViewModel.cs +++ b/TimetableDesigner/ViewModels/Models/TeacherViewModel.cs @@ -5,12 +5,11 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using TimetableDesigner.Core; -using TimetableDesigner.Customs.Collections; -using TimetableDesigner.ViewModels.Base; +using TimetableDesigner.Customs; namespace TimetableDesigner.ViewModels.Models { - public class TeacherViewModel : BaseViewModel + public class TeacherViewModel : BaseModelViewModel { #region FIELDS diff --git a/TimetableDesigner/ViewModels/Models/TimetableTemplateViewModel.cs b/TimetableDesigner/ViewModels/Models/TimetableTemplateViewModel.cs index f2be1a8..4e14e68 100644 --- a/TimetableDesigner/ViewModels/Models/TimetableTemplateViewModel.cs +++ b/TimetableDesigner/ViewModels/Models/TimetableTemplateViewModel.cs @@ -5,11 +5,10 @@ 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 + public class TimetableTemplateViewModel : BaseModelViewModel { #region FIELDS diff --git a/TimetableDesigner/ViewModels/Views/ClassroomEditViewModel.cs b/TimetableDesigner/ViewModels/Views/ClassroomEditViewModel.cs new file mode 100644 index 0000000..9e761ef --- /dev/null +++ b/TimetableDesigner/ViewModels/Views/ClassroomEditViewModel.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TimetableDesigner.Core; +using TimetableDesigner.Customs; +using TimetableDesigner.Properties; +using TimetableDesigner.Services; +using TimetableDesigner.Services.TabNavigation; +using TimetableDesigner.ViewModels.Models; + +namespace TimetableDesigner.ViewModels.Views +{ + public class ClassroomEditViewModel : BaseViewViewModel + { + #region FIELDS + + private ClassroomViewModel _classroom; + + #endregion + + + + #region PROPERTIES + + public ClassroomViewModel Classroom + { + get => _classroom; + set + { + if (_classroom != value) + { + _classroom = value; + NotifyPropertyChanged(nameof(Classroom)); + } + } + } + + public string Name + { + get => _classroom.Name; + set + { + if (_classroom.Name != value) + { + _classroom.Name = value; + NotifyPropertyChanged(nameof(Name)); + + TabItem? tab = ServiceProvider.Instance.GetService().Tabs.Where(tab => tab.ViewModel == this).FirstOrDefault(); + if (tab != null) + { + tab.Title = $"{Resources.Tabs_ClassroomEdit}: {_classroom.Name}"; + } + } + } + } + + #endregion + + + + #region CONSTRUCTORS + + public ClassroomEditViewModel() : this(new ClassroomViewModel(new Classroom())) + { } + + public ClassroomEditViewModel(ClassroomViewModel classroom) + { + _classroom = classroom; + } + + #endregion + } +} diff --git a/TimetableDesigner/ViewModels/Views/GroupEditViewModel.cs b/TimetableDesigner/ViewModels/Views/GroupEditViewModel.cs new file mode 100644 index 0000000..16e06f0 --- /dev/null +++ b/TimetableDesigner/ViewModels/Views/GroupEditViewModel.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TimetableDesigner.Core; +using TimetableDesigner.Services.TabNavigation; +using TimetableDesigner.Services; +using TimetableDesigner.ViewModels.Models; +using TimetableDesigner.Properties; +using TimetableDesigner.Customs; +using TimetableDesigner.Services.Project; +using System.Windows.Input; +using TimetableDesigner.Commands; +using System.Diagnostics; +using TimetableDesigner.Services.MessageBox; + +namespace TimetableDesigner.ViewModels.Views +{ + public class GroupEditViewModel : BaseViewViewModel + { + #region FIELDS + + private IProjectService _projectService; + private IMessageBoxService _messageBoxService; + + private GroupViewModel _group; + + private string _newSubgroupName; + + #endregion + + + + #region PROPERTIES + + public GroupViewModel Group + { + get => _group; + set + { + if (_group != value) + { + _group = value; + NotifyPropertyChanged(nameof(Group)); + } + } + } + + public string Name + { + get => _group.Name; + set + { + if (_group.Name != value) + { + _group.Name = value; + NotifyPropertyChanged(nameof(Name)); + + TabItem? tab = ServiceProvider.Instance.GetService().Tabs.Where(tab => tab.ViewModel == this).FirstOrDefault(); + if (tab != null) + { + tab.Title = $"{Resources.Tabs_GroupEdit}: {_group.Name}"; + } + } + } + } + + public ObservableDictionary Subgroups => new ObservableDictionary(_projectService.ProjectViewModel.Subgroups.ToDictionary(sg => sg, Group.AssignedSubgroups.Contains)); + + public string NewSubgroupName + { + get => _newSubgroupName; + set + { + if (_newSubgroupName != value) + { + _newSubgroupName = value; + NotifyPropertyChanged(nameof(NewSubgroupName)); + } + } + } + + public ICommand AddSubgroupCommand { get; set; } + public ICommand EditSubgroupAssignmentCommand { get; set; } + public ICommand DeleteSubgroupCommand { get; set; } + + #endregion + + + + #region CONSTRUCTORS + + public GroupEditViewModel() : this(new GroupViewModel(new Group())) + { } + + public GroupEditViewModel(GroupViewModel group) + { + _projectService = ServiceProvider.Instance.GetService(); + _messageBoxService = ServiceProvider.Instance.GetService(); + + _group = group; + _newSubgroupName = string.Empty; + + AddSubgroupCommand = new RelayCommand(args => AddSubgroup()); + EditSubgroupAssignmentCommand = new RelayCommand(EditSubgroupAssignment); + DeleteSubgroupCommand = new RelayCommand(DeleteSubgroup); + } + + #endregion + + + + #region PRIVATE METHODS + + private void AddSubgroup() + { + Subgroup subgroup = new Subgroup() + { + Name = NewSubgroupName + }; + SubgroupViewModel subgroupViewModel = new SubgroupViewModel(subgroup); + + _projectService.ProjectViewModel.Subgroups.Add(subgroupViewModel); + Group.AddSubgroup(subgroupViewModel); + NotifyPropertyChanged(nameof(Subgroups)); + + NewSubgroupName = string.Empty; + } + + private void EditSubgroupAssignment(SubgroupViewModel subgroup) + { + bool assigned = Subgroups[subgroup]; + if (assigned) + { + Group.RemoveSubgroup(subgroup); + } + else + { + Group.AddSubgroup(subgroup); + } + NotifyPropertyChanged(nameof(Subgroups)); + } + + private void DeleteSubgroup(SubgroupViewModel subgroup) + { + MessageBoxQuestionResult result = _messageBoxService.ShowQuestion(Resources.GroupEdit_Message_SubgroupDelete, true); + if (result == MessageBoxQuestionResult.Yes) + { + foreach (GroupViewModel group in _projectService.ProjectViewModel.Groups) + { + group.RemoveSubgroup(subgroup); + } + _projectService.ProjectViewModel.Subgroups.Remove(subgroup); + NotifyPropertyChanged(nameof(Subgroups)); + } + } + + #endregion + } +} diff --git a/TimetableDesigner/ViewModels/Views/MainViewModel.cs b/TimetableDesigner/ViewModels/Views/MainViewModel.cs new file mode 100644 index 0000000..a443db7 --- /dev/null +++ b/TimetableDesigner/ViewModels/Views/MainViewModel.cs @@ -0,0 +1,271 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; +using TimetableDesigner.Commands; +using System.Windows.Navigation; +using TimetableDesigner.Core; +using System.Windows; +using TimetableDesigner.Properties; +using System.Reflection; +using TimetableDesigner.ViewModels.Models; +using System.Windows.Data; +using TimetableDesigner.Services.MessageBox; +using System.ComponentModel.Design; +using TimetableDesigner.Services; +using TimetableDesigner.Services.TabNavigation; +using TimetableDesigner.Services.Project; +using System.Drawing; + +namespace TimetableDesigner.ViewModels.Views +{ + class MainViewModel : BaseViewViewModel + { + #region FIELDS + + private IMessageBoxService _messageBoxService; + private ITabNavigationService _tabNavigationService; + private IProjectService _projectService; + + #endregion + + + + #region PROPERTIES + + // Observable services + public IProjectService ProjectService => _projectService; + public ITabNavigationService TabNavigationService => _tabNavigationService; + + // Tabs + public ObservableCollection Tabs => _tabNavigationService.Tabs; + public TabItem SelectedTab => _tabNavigationService.SelectedTab; + + // Commands + public ICommand NewProjectCommand { get; set; } + public ICommand OpenProjectCommand { get; set; } + public ICommand ProjectSettingsCommand { get; set; } + public ICommand NewClassroomCommand { get; set; } + public ICommand EditClassroomCommand { get; set; } + public ICommand RemoveClassroomCommand { get; set; } + public ICommand NewTeacherCommand { get; set; } + public ICommand EditTeacherCommand { get; set; } + public ICommand RemoveTeacherCommand { get; set; } + public ICommand NewGroupCommand { get; set; } + public ICommand EditGroupCommand { get; set; } + public ICommand RemoveGroupCommand { get; set; } + public ICommand RemoveSubgroupCommand { get; set; } + + // Others + public string Version { get; set; } + + #endregion + + + + #region CONSTRUCTORS + + public MainViewModel() + { + _messageBoxService = ServiceProvider.Instance.GetService(); + _tabNavigationService = ServiceProvider.Instance.GetService(); + _projectService = ServiceProvider.Instance.GetService(); + + 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); + NewTeacherCommand = new RelayCommand(param => NewTeacher()); + EditTeacherCommand = new RelayCommand(EditTeacher); + RemoveTeacherCommand = new RelayCommand(DeleteTeacher); + NewGroupCommand = new RelayCommand(param => NewGroup()); + EditGroupCommand = new RelayCommand(EditGroup); + RemoveGroupCommand = new RelayCommand(DeleteGroup); + RemoveSubgroupCommand = new RelayCommand(DeleteSubgroup); + + Version = Assembly.GetExecutingAssembly().GetName().Version.ToString(); + + TabItem welcomeTab = new TabItem() + { + Title = Resources.Tabs_Welcome, + ViewModel = new WelcomeViewModel() + }; + _tabNavigationService.AddAndActivate(welcomeTab); + } + + #endregion + + + + #region PRIVATE METHODS + + private void OpenProject() + { + } + + private void NewProject() + { + if (ProjectService.ProjectViewModel is not null) + { + MessageBoxQuestionResult result = _messageBoxService.ShowQuestion(Resources.Main_Message_SaveCurrentProject); + + switch (result) + { + case MessageBoxQuestionResult.Yes: break; + case MessageBoxQuestionResult.No: break; + default: return; + } + } + _tabNavigationService.CloseAll(); + _projectService.New(); + ProjectSettings(); + } + + private void ProjectSettings() + { + if (ProjectService.ProjectViewModel is not null) + { + TabItem projectSettingsTab = new TabItem() + { + Title = Resources.Tabs_ProjectSettings, + IsClosable = true, + ViewModel = new ProjectSettingsViewModel() + }; + _tabNavigationService.AddAndActivate(projectSettingsTab); + } + } + + private void NewClassroom() + { + if (ProjectService.ProjectViewModel is not null) + { + Classroom classroom = new Classroom() + { + Name = Resources.Global_DefaultClassroomName + }; + ClassroomViewModel classroomVM = new ClassroomViewModel(classroom); + ProjectService.ProjectViewModel.Classrooms.Add(classroomVM); + EditClassroom(classroomVM); + } + } + + private void EditClassroom(ClassroomViewModel classroomViewModel) + { + if (ProjectService.ProjectViewModel is not null) + { + TabItem classroomEditTab = new TabItem() + { + Title = $"{Resources.Tabs_ClassroomEdit}: {classroomViewModel.Name}", + IsClosable = true, + ViewModel = new ClassroomEditViewModel(classroomViewModel) + }; + _tabNavigationService.AddAndActivate(classroomEditTab); + } + } + + private void DeleteClassroom(ClassroomViewModel classroomViewModel) + { + if (ProjectService.ProjectViewModel is not null) + { + ProjectService.ProjectViewModel.Classrooms.Remove(classroomViewModel); + } + } + + private void NewTeacher() + { + if (ProjectService.ProjectViewModel is not null) + { + Teacher teacher = new Teacher() + { + Name = Resources.Global_DefaultTeacherName + }; + TeacherViewModel teacherVM = new TeacherViewModel(teacher); + ProjectService.ProjectViewModel.Teachers.Add(teacherVM); + EditTeacher(teacherVM); + } + } + + private void EditTeacher(TeacherViewModel teacherViewModel) + { + if (ProjectService.ProjectViewModel is not null) + { + TabItem teacherEditTab = new TabItem() + { + Title = $"{Resources.Tabs_TeacherEdit}: {teacherViewModel.Name}", + IsClosable = true, + ViewModel = new TeacherEditViewModel(teacherViewModel) + }; + _tabNavigationService.AddAndActivate(teacherEditTab); + } + } + + private void DeleteTeacher(TeacherViewModel teacherViewModel) + { + if (ProjectService.ProjectViewModel is not null) + { + ProjectService.ProjectViewModel.Teachers.Remove(teacherViewModel); + } + } + + private void NewGroup() + { + if (ProjectService.ProjectViewModel is not null) + { + Group group = new Group() + { + Name = Resources.Global_DefaultGroupName + }; + GroupViewModel groupVM = new GroupViewModel(group); + ProjectService.ProjectViewModel.Groups.Add(groupVM); + EditGroup(groupVM); + } + } + + private void EditGroup(GroupViewModel groupViewModel) + { + if (ProjectService.ProjectViewModel is not null) + { + TabItem groupEditTab = new TabItem() + { + Title = $"{Resources.Tabs_GroupEdit}: {groupViewModel.Name}", + IsClosable = true, + ViewModel = new GroupEditViewModel(groupViewModel) + }; + _tabNavigationService.AddAndActivate(groupEditTab); + } + } + + private void DeleteGroup(GroupViewModel groupViewModel) + { + if (ProjectService.ProjectViewModel is not null) + { + ProjectService.ProjectViewModel.Groups.Remove(groupViewModel); + } + } + + private void DeleteSubgroup(SubgroupViewModel subgroupViewModel) + { + if (ProjectService.ProjectViewModel is not null) + { + MessageBoxQuestionResult result = _messageBoxService.ShowQuestion(Resources.Main_Treeview_Subgroups_Message_Remove, true); + if (result == MessageBoxQuestionResult.Yes) + { + foreach (GroupViewModel group in ProjectService.ProjectViewModel.Groups) + { + group.RemoveSubgroup(subgroupViewModel); + } + _projectService.ProjectViewModel.Subgroups.Remove(subgroupViewModel); + } + } + } + + #endregion + } +} diff --git a/TimetableDesigner/ViewModels/ProjectSettingsTabViewModel.cs b/TimetableDesigner/ViewModels/Views/ProjectSettingsViewModel.cs similarity index 69% rename from TimetableDesigner/ViewModels/ProjectSettingsTabViewModel.cs rename to TimetableDesigner/ViewModels/Views/ProjectSettingsViewModel.cs index 2c3d1fd..249154e 100644 --- a/TimetableDesigner/ViewModels/ProjectSettingsTabViewModel.cs +++ b/TimetableDesigner/ViewModels/Views/ProjectSettingsViewModel.cs @@ -10,17 +10,22 @@ using System.Windows; using System.Windows.Input; using TimetableDesigner.Commands; using TimetableDesigner.Core; -using TimetableDesigner.MessageBox; +using TimetableDesigner.Customs; using TimetableDesigner.Properties; -using TimetableDesigner.ViewModels.Base; +using TimetableDesigner.Services; +using TimetableDesigner.Services.MessageBox; +using TimetableDesigner.Services.Project; using TimetableDesigner.ViewModels.Models; -namespace TimetableDesigner.ViewModels +namespace TimetableDesigner.ViewModels.Views { - public class ProjectSettingsTabViewModel : BaseTabViewModel + public class ProjectSettingsViewModel : BaseViewViewModel { #region FIELDS + private IMessageBoxService _messageBoxService; + private IProjectService _projectService; + private string _newDayName; private DateTime? _newSlotFrom; private DateTime? _newSlotTo; @@ -31,13 +36,10 @@ namespace TimetableDesigner.ViewModels #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; } + // Project + public ProjectViewModel? Project => _projectService.ProjectViewModel; + // Fields public string NewDayName { get => _newDayName; @@ -67,15 +69,22 @@ namespace TimetableDesigner.ViewModels } } + // Commands + public ICommand AddDayCommand { get; set; } + public ICommand AddSlotCommand { get; set; } + public ICommand RemoveDayCommand { get; set; } + public ICommand RemoveSlotCommand { get; set; } + #endregion #region CONSTRUCTORS - public ProjectSettingsTabViewModel() : base() + public ProjectSettingsViewModel() { - Project = new ProjectViewModel(new Project()); + _messageBoxService = ServiceProvider.Instance.GetService(); + _projectService = ServiceProvider.Instance.GetService(); AddDayCommand = new RelayCommand(param => AddDay()); AddSlotCommand = new RelayCommand(param => AddSlot()); @@ -95,24 +104,34 @@ namespace TimetableDesigner.ViewModels private void AddDay() { - if (!string.IsNullOrWhiteSpace(NewDayName)) + if (Project is not null && !string.IsNullOrWhiteSpace(NewDayName)) { Project.TimetableTemplate.AddDay(new TimetableDay(NewDayName)); NewDayName = string.Empty; } } - private void RemoveDay(TimetableDay day) => Project.TimetableTemplate.RemoveDay(day); + private void RemoveDay(TimetableDay day) + { + if (Project is not null) + { + foreach (TeacherViewModel teacher in Project.Teachers) + { + teacher.RemoveDay(day); + } + Project.TimetableTemplate.RemoveDay(day); + } + } private void AddSlot() { - if (NewSlotFrom.HasValue && NewSlotTo.HasValue) + if (Project is not null && 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); + _messageBoxService.ShowError(Resources.ProjectSettings_Message_FromHigherThanTo); return; } @@ -128,7 +147,7 @@ namespace TimetableDesigner.ViewModels } catch (ArgumentException) { - MessageBoxService.ShowError(Resources.ProjectSettings_Message_SlotCollision); + _messageBoxService.ShowError(Resources.ProjectSettings_Message_SlotCollision); } } } diff --git a/TimetableDesigner/ViewModels/TeacherEditTabViewModel.cs b/TimetableDesigner/ViewModels/Views/TeacherEditViewModel.cs similarity index 73% rename from TimetableDesigner/ViewModels/TeacherEditTabViewModel.cs rename to TimetableDesigner/ViewModels/Views/TeacherEditViewModel.cs index b99e56b..7711d00 100644 --- a/TimetableDesigner/ViewModels/TeacherEditTabViewModel.cs +++ b/TimetableDesigner/ViewModels/Views/TeacherEditViewModel.cs @@ -7,19 +7,24 @@ using System.Threading.Tasks; using System.Windows.Input; using TimetableDesigner.Commands; using TimetableDesigner.Core; -using TimetableDesigner.MessageBox; +using TimetableDesigner.Customs; using TimetableDesigner.Properties; -using TimetableDesigner.ViewModels.Base; +using TimetableDesigner.Services; +using TimetableDesigner.Services.MessageBox; +using TimetableDesigner.Services.Project; +using TimetableDesigner.Services.TabNavigation; using TimetableDesigner.ViewModels.Models; -namespace TimetableDesigner.ViewModels +namespace TimetableDesigner.ViewModels.Views { - public class TeacherEditTabViewModel : BaseTabViewModel + public class TeacherEditViewModel : BaseViewViewModel { #region FIELDS + private IMessageBoxService _messageBoxService; + private IProjectService _projectService; + private TeacherViewModel _teacher; - private TimetableTemplateViewModel _timetableTemplate; private TimetableDay _selectedDay; @@ -45,15 +50,23 @@ namespace TimetableDesigner.ViewModels } } } - public TimetableTemplateViewModel TimetableTemplate + public TimetableTemplateViewModel? TimetableTemplate => _projectService.ProjectViewModel?.TimetableTemplate; + + public string Name { - get => _timetableTemplate; + get => _teacher.Name; set { - if (value != _timetableTemplate) + if (_teacher.Name != value) { - _timetableTemplate = value; - NotifyPropertyChanged(nameof(TimetableTemplate)); + _teacher.Name = value; + NotifyPropertyChanged(nameof(Teacher)); + + TabItem? tab = ServiceProvider.Instance.GetService().Tabs.Where(tab => tab.ViewModel == this).FirstOrDefault(); + if (tab != null) + { + tab.Title = $"{Resources.Tabs_ClassroomEdit}: {_teacher.Name}"; + } } } } @@ -117,13 +130,15 @@ namespace TimetableDesigner.ViewModels #region CONSTRUCTORS - public TeacherEditTabViewModel() : this(new TeacherViewModel(new Core.Teacher()), new TimetableTemplateViewModel(new Core.TimetableTemplate())) + public TeacherEditViewModel() : this(new TeacherViewModel(new Teacher())) { } - public TeacherEditTabViewModel(TeacherViewModel teacher, TimetableTemplateViewModel timetableTemplate) : base() + public TeacherEditViewModel(TeacherViewModel teacher) { + _messageBoxService = ServiceProvider.Instance.GetService(); + _projectService = ServiceProvider.Instance.GetService(); + _teacher = teacher; - _timetableTemplate = timetableTemplate; AddDayCommand = new RelayCommand(param => AddDay()); RemoveDayCommand = new RelayCommand(RemoveDay); @@ -161,7 +176,7 @@ namespace TimetableDesigner.ViewModels TimeOnly to = new TimeOnly(NewHourTo.Value.Hour, NewHourTo.Value.Minute); if (from >= to) { - MessageBoxService.ShowError(Resources.TeacherEdit_Message_FromHigherThanTo); + _messageBoxService.ShowError(Resources.TeacherEdit_Message_FromHigherThanTo); return; } @@ -171,7 +186,7 @@ namespace TimetableDesigner.ViewModels } catch (ArgumentException) { - MessageBoxService.ShowError(Resources.TeacherEdit_Message_HourCollision); + _messageBoxService.ShowError(Resources.TeacherEdit_Message_HourCollision); } } NotifyPropertyChanged(nameof(SelectedDayHours)); diff --git a/TimetableDesigner/ViewModels/WelcomeTabViewModel.cs b/TimetableDesigner/ViewModels/Views/WelcomeViewModel.cs similarity index 53% rename from TimetableDesigner/ViewModels/WelcomeTabViewModel.cs rename to TimetableDesigner/ViewModels/Views/WelcomeViewModel.cs index 0c833ca..809b737 100644 --- a/TimetableDesigner/ViewModels/WelcomeTabViewModel.cs +++ b/TimetableDesigner/ViewModels/Views/WelcomeViewModel.cs @@ -3,15 +3,15 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -using TimetableDesigner.ViewModels.Base; +using TimetableDesigner.Customs; -namespace TimetableDesigner.ViewModels +namespace TimetableDesigner.ViewModels.Views { - public class WelcomeTabViewModel : BaseTabViewModel + public class WelcomeViewModel : BaseViewViewModel { #region CONSTRUCTORS - public WelcomeTabViewModel() + public WelcomeViewModel() { } #endregion diff --git a/TimetableDesigner/Views/ClassroomEditTabView.xaml b/TimetableDesigner/Views/ClassroomEditTabView.xaml deleted file mode 100644 index fdf5937..0000000 --- a/TimetableDesigner/Views/ClassroomEditTabView.xaml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/TimetableDesigner/Views/ClassroomEditView.xaml b/TimetableDesigner/Views/ClassroomEditView.xaml new file mode 100644 index 0000000..aee07bc --- /dev/null +++ b/TimetableDesigner/Views/ClassroomEditView.xaml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TimetableDesigner/Views/ProjectSettingsTabView.xaml.cs b/TimetableDesigner/Views/ClassroomEditView.xaml.cs similarity index 82% rename from TimetableDesigner/Views/ProjectSettingsTabView.xaml.cs rename to TimetableDesigner/Views/ClassroomEditView.xaml.cs index cbdd6f8..82bbe7f 100644 --- a/TimetableDesigner/Views/ProjectSettingsTabView.xaml.cs +++ b/TimetableDesigner/Views/ClassroomEditView.xaml.cs @@ -15,9 +15,9 @@ using System.Windows.Shapes; namespace TimetableDesigner.Views { - public partial class ProjectSettingsTabView : UserControl + public partial class ClassroomEditView : UserControl { - public ProjectSettingsTabView() + public ClassroomEditView() { InitializeComponent(); } diff --git a/TimetableDesigner/Views/GroupEditView.xaml b/TimetableDesigner/Views/GroupEditView.xaml new file mode 100644 index 0000000..9f91fec --- /dev/null +++ b/TimetableDesigner/Views/GroupEditView.xaml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TimetableDesigner/Views/WelcomeTabView.xaml.cs b/TimetableDesigner/Views/GroupEditView.xaml.cs similarity index 73% rename from TimetableDesigner/Views/WelcomeTabView.xaml.cs rename to TimetableDesigner/Views/GroupEditView.xaml.cs index 3d87246..6cc425e 100644 --- a/TimetableDesigner/Views/WelcomeTabView.xaml.cs +++ b/TimetableDesigner/Views/GroupEditView.xaml.cs @@ -15,12 +15,9 @@ using System.Windows.Shapes; namespace TimetableDesigner.Views { - /// - /// Interaction logic for WelcomeTabView.xaml - /// - public partial class WelcomeTabView : UserControl + public partial class GroupEditView : UserControl { - public WelcomeTabView() + public GroupEditView() { InitializeComponent(); } diff --git a/TimetableDesigner/Views/MainWindow.xaml b/TimetableDesigner/Views/MainWindow.xaml index af9f8ff..824ae8a 100644 --- a/TimetableDesigner/Views/MainWindow.xaml +++ b/TimetableDesigner/Views/MainWindow.xaml @@ -1,8 +1,7 @@  - + @@ -33,12 +32,12 @@ - + - + - - - + + + + + + + + + + + + - + @@ -123,24 +131,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + + diff --git a/TimetableDesigner/Views/ClassroomEditTabView.xaml.cs b/TimetableDesigner/Views/TeacherEditView.xaml.cs similarity index 71% rename from TimetableDesigner/Views/ClassroomEditTabView.xaml.cs rename to TimetableDesigner/Views/TeacherEditView.xaml.cs index 539f58b..b923b69 100644 --- a/TimetableDesigner/Views/ClassroomEditTabView.xaml.cs +++ b/TimetableDesigner/Views/TeacherEditView.xaml.cs @@ -15,12 +15,9 @@ using System.Windows.Shapes; namespace TimetableDesigner.Views { - /// - /// Interaction logic for ClassroomEditTabView.xaml - /// - public partial class ClassroomEditTabView : UserControl + public partial class TeacherEditView : UserControl { - public ClassroomEditTabView() + public TeacherEditView() { InitializeComponent(); } diff --git a/TimetableDesigner/Views/WelcomeTabView.xaml b/TimetableDesigner/Views/WelcomeView.xaml similarity index 75% rename from TimetableDesigner/Views/WelcomeTabView.xaml rename to TimetableDesigner/Views/WelcomeView.xaml index 118f515..484390f 100644 --- a/TimetableDesigner/Views/WelcomeTabView.xaml +++ b/TimetableDesigner/Views/WelcomeView.xaml @@ -1,14 +1,16 @@ - - + diff --git a/TimetableDesigner/Views/WelcomeView.xaml.cs b/TimetableDesigner/Views/WelcomeView.xaml.cs new file mode 100644 index 0000000..f0b7180 --- /dev/null +++ b/TimetableDesigner/Views/WelcomeView.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 WelcomeView : UserControl + { + public WelcomeView() + { + InitializeComponent(); + } + } +}