From 6b03c881a3140d505fc7d8169ae8df5f381b1e99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Erbsh=C3=A4u=C3=9Fer?= Date: Tue, 9 Jun 2020 15:46:44 +0200 Subject: [PATCH] Implemented new dialog. --- .gitignore | 5 + ucalc.sln | 25 ++ ucalc/App.xaml | 9 + ucalc/App.xaml.cs | 15 ++ ucalc/AssemblyInfo.cs | 10 + ucalc/BillingWindow.xaml | 10 + ucalc/BillingWindow.xaml.cs | 17 ++ ucalc/Constants.cs | 10 + ucalc/Data/Billing.cs | 488 +++++++++++++++++++++++++++++++++++ ucalc/Data/RecentlyOpened.cs | 99 +++++++ ucalc/MainWindow.xaml | 112 ++++++++ ucalc/MainWindow.xaml.cs | 67 +++++ ucalc/NewWindow.xaml | 81 ++++++ ucalc/NewWindow.xaml.cs | 129 +++++++++ ucalc/ucalc.csproj | 25 ++ 15 files changed, 1102 insertions(+) create mode 100644 .gitignore create mode 100644 ucalc.sln create mode 100644 ucalc/App.xaml create mode 100644 ucalc/App.xaml.cs create mode 100644 ucalc/AssemblyInfo.cs create mode 100644 ucalc/BillingWindow.xaml create mode 100644 ucalc/BillingWindow.xaml.cs create mode 100644 ucalc/Constants.cs create mode 100644 ucalc/Data/Billing.cs create mode 100644 ucalc/Data/RecentlyOpened.cs create mode 100644 ucalc/MainWindow.xaml create mode 100644 ucalc/MainWindow.xaml.cs create mode 100644 ucalc/NewWindow.xaml create mode 100644 ucalc/NewWindow.xaml.cs create mode 100644 ucalc/ucalc.csproj diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e922920 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +bin +obj +.idea +.vs +*.user diff --git a/ucalc.sln b/ucalc.sln new file mode 100644 index 0000000..334ef9b --- /dev/null +++ b/ucalc.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30128.74 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ucalc", "ucalc\ucalc.csproj", "{E565705A-BAF4-4653-99A1-199C314A21EC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E565705A-BAF4-4653-99A1-199C314A21EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E565705A-BAF4-4653-99A1-199C314A21EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E565705A-BAF4-4653-99A1-199C314A21EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E565705A-BAF4-4653-99A1-199C314A21EC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C5D953C3-5DB1-48E7-BC85-31079EB37F26} + EndGlobalSection +EndGlobal diff --git a/ucalc/App.xaml b/ucalc/App.xaml new file mode 100644 index 0000000..cf9553a --- /dev/null +++ b/ucalc/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/ucalc/App.xaml.cs b/ucalc/App.xaml.cs new file mode 100644 index 0000000..a703461 --- /dev/null +++ b/ucalc/App.xaml.cs @@ -0,0 +1,15 @@ +using UCalc.Data; + +namespace UCalc +{ + public partial class App + { + private readonly RecentlyOpenedList _recentlyOpenedList; + public static RecentlyOpenedList RecentlyOpenedList => ((App) Current)._recentlyOpenedList; + + public App() + { + _recentlyOpenedList = new RecentlyOpenedList(); + } + } +} \ No newline at end of file diff --git a/ucalc/AssemblyInfo.cs b/ucalc/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/ucalc/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) +)] \ No newline at end of file diff --git a/ucalc/BillingWindow.xaml b/ucalc/BillingWindow.xaml new file mode 100644 index 0000000..70c020c --- /dev/null +++ b/ucalc/BillingWindow.xaml @@ -0,0 +1,10 @@ + + + diff --git a/ucalc/BillingWindow.xaml.cs b/ucalc/BillingWindow.xaml.cs new file mode 100644 index 0000000..1c09c9f --- /dev/null +++ b/ucalc/BillingWindow.xaml.cs @@ -0,0 +1,17 @@ +using UCalc.Data; + +namespace UCalc +{ + public partial class BillingWindow + { + private readonly Billing _savedBilling; + public Billing Billing { get; } + + public BillingWindow(Billing savedBilling, Billing billing) + { + _savedBilling = savedBilling; + Billing = billing; + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/ucalc/Constants.cs b/ucalc/Constants.cs new file mode 100644 index 0000000..5e77612 --- /dev/null +++ b/ucalc/Constants.cs @@ -0,0 +1,10 @@ +using System.Windows.Media; + +namespace UCalc +{ + public static class Constants + { + public static readonly SolidColorBrush MainColor = Brushes.White; + public static readonly SolidColorBrush SubMainColor = new SolidColorBrush(Color.FromRgb(0x00, 0x7A, 0xCC)); + } +} \ No newline at end of file diff --git a/ucalc/Data/Billing.cs b/ucalc/Data/Billing.cs new file mode 100644 index 0000000..dd9ac93 --- /dev/null +++ b/ucalc/Data/Billing.cs @@ -0,0 +1,488 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; + +#pragma warning disable 659 + +namespace UCalc.Data +{ + public enum Salutation + { + Sir, + SirDr, + Madam, + MadamDr, + SirAndMadam, + Family + } + + public static class Salutations + { + public static string AsString(this Salutation salutation) + { + switch (salutation) + { + case Salutation.Sir: + return "Herr"; + case Salutation.SirDr: + return "Herr Dr."; + case Salutation.Madam: + return "Frau"; + case Salutation.MadamDr: + return "Frau Dr."; + case Salutation.SirAndMadam: + return "Herr und Frau"; + case Salutation.Family: + return "Familie"; + default: + throw new InvalidOperationException(); + } + } + } + + public class Address + { + public string Street { get; set; } + public string HouseNumber { get; set; } + public string City { get; set; } + public string Postcode { get; set; } + + public Address() + { + Street = ""; + HouseNumber = ""; + City = ""; + Postcode = ""; + } + + private bool Equals(Address other) + { + return Street == other.Street && HouseNumber == other.HouseNumber && City == other.City && + Postcode == other.Postcode; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((Address) obj); + } + + public Address Clone() + { + return new Address + { + Street = Street, + HouseNumber = HouseNumber, + City = City, + Postcode = Postcode + }; + } + } + + public class BankAccount + { + public string Iban { get; set; } + public string Bic { get; set; } + public string BankName { get; set; } + + public BankAccount() + { + Iban = ""; + Bic = ""; + BankName = ""; + } + + private bool Equals(BankAccount other) + { + return Iban == other.Iban && Bic == other.Bic && BankName == other.BankName; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((BankAccount) obj); + } + + public BankAccount Clone() + { + return new BankAccount + { + Iban = Iban, + Bic = Bic, + BankName = BankName + }; + } + } + + public class Flat + { + public Guid Id { get; private set; } + public string Name { get; set; } + public int Size { get; set; } + + public Flat() + { + Id = Guid.NewGuid(); + Name = ""; + } + + private bool Equals(Flat other) + { + return Id.Equals(other.Id) && Name == other.Name && Size == other.Size; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((Flat) obj); + } + + public override int GetHashCode() + { + // ReSharper disable NonReadonlyMemberInGetHashCode + return Id.GetHashCode(); + // ReSharper restore NonReadonlyMemberInGetHashCode + } + + public Flat Clone() + { + return new Flat + { + Id = Id, + Name = Name, + Size = Size + }; + } + } + + public class Tenant + { + public Guid Id { get; private set; } + public Salutation Salutation { get; set; } + public string Name { get; set; } + public int PersonCount { get; set; } + public BankAccount BankAccount { get; private set; } + public DateTime? EntryDate { get; set; } + public DateTime? DepatureDate { get; set; } + public HashSet RentedFlats { get; private set; } + public decimal PaidRent { get; set; } + public string CustomMessage1 { get; set; } + public string CustomMessage2 { get; set; } + + public Tenant() + { + Id = Guid.NewGuid(); + Name = ""; + BankAccount = new BankAccount(); + RentedFlats = new HashSet(); + } + + private bool Equals(Tenant other) + { + return Id.Equals(other.Id) && Salutation == other.Salutation && Name == other.Name && + PersonCount == other.PersonCount && Equals(BankAccount, other.BankAccount) && + Nullable.Equals(EntryDate, other.EntryDate) && Nullable.Equals(DepatureDate, other.DepatureDate) && + RentedFlats.SequenceEqual(other.RentedFlats) && PaidRent == other.PaidRent && + CustomMessage1 == other.CustomMessage1 && CustomMessage2 == other.CustomMessage2; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((Tenant) obj); + } + + public Tenant Clone(Dictionary flatMapper) + { + return new Tenant + { + Id = Id, + Salutation = Salutation, + Name = Name, + PersonCount = PersonCount, + BankAccount = BankAccount.Clone(), + EntryDate = EntryDate, + DepatureDate = DepatureDate, + RentedFlats = new HashSet(RentedFlats.Select(flat => flatMapper[flat])), + PaidRent = PaidRent, + CustomMessage1 = CustomMessage1, + CustomMessage2 = CustomMessage2 + }; + } + } + + public class Landlord + { + public Salutation Salutation { get; set; } + public string Name { get; set; } + public string MailAddress { get; set; } + public string Phone { get; set; } + public Address Address { get; private set; } + public BankAccount BankAccount { get; private set; } + + public Landlord() + { + Name = ""; + MailAddress = ""; + Phone = ""; + Address = new Address(); + BankAccount = new BankAccount(); + } + + private bool Equals(Landlord other) + { + return Salutation == other.Salutation && Name == other.Name && MailAddress == other.MailAddress && + Phone == other.Phone && Equals(Address, other.Address) && Equals(BankAccount, other.BankAccount); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((Landlord) obj); + } + + public Landlord Clone() + { + return new Landlord + { + Salutation = Salutation, + Name = Name, + MailAddress = MailAddress, + Phone = Phone, + Address = Address.Clone(), + BankAccount = BankAccount.Clone() + }; + } + } + + public class House + { + public Address Address { get; private set; } + public List Flats { get; private set; } + + public House() + { + Address = new Address(); + Flats = new List(); + } + + private bool Equals(House other) + { + return Equals(Address, other.Address) && Flats.SequenceEqual(other.Flats); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((House) obj); + } + + public House Clone() + { + return new House + { + Address = Address.Clone(), + Flats = new List(Flats.Select(flat => flat.Clone())) + }; + } + } + + public class CostEntryDetails + { + public decimal TotalPrice { get; set; } + public decimal UnitCount { get; set; } + public List DiscountsInUnits { get; private set; } + + public CostEntryDetails() + { + DiscountsInUnits = new List(); + } + + private bool Equals(CostEntryDetails other) + { + return TotalPrice == other.TotalPrice && UnitCount == other.UnitCount && + DiscountsInUnits.SequenceEqual(other.DiscountsInUnits); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((CostEntryDetails) obj); + } + + public CostEntryDetails Clone() + { + return new CostEntryDetails + { + TotalPrice = TotalPrice, + UnitCount = UnitCount, + DiscountsInUnits = new List(DiscountsInUnits) + }; + } + } + + public class CostEntry + { + public DateTime StartDate { get; set; } + public DateTime EndDate { get; set; } + public decimal Price { get; set; } + public CostEntryDetails Details { get; set; } + + public CostEntry() + { + Details = new CostEntryDetails(); + } + + private bool Equals(CostEntry other) + { + return StartDate.Equals(other.StartDate) && EndDate.Equals(other.EndDate) && Price == other.Price && + Details.Equals(other.Details); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((CostEntry) obj); + } + + public CostEntry Clone() + { + return new CostEntry + { + StartDate = StartDate, + EndDate = EndDate, + Price = Price, + Details = Details?.Clone() + }; + } + } + + public enum CostDivision + { + Person, + Flat, + Size + } + + public class Cost + { + public string Name { get; set; } + public CostDivision Division { get; set; } + public bool AffectsAll { get; set; } + public bool IncludeUnrented { get; set; } + public HashSet AffectedFlats { get; private set; } + public List Entries { get; private set; } + public bool DisplayInBill { get; set; } + + public Cost() + { + Name = ""; + AffectedFlats = new HashSet(); + Entries = new List(); + } + + private bool Equals(Cost other) + { + return Name == other.Name && Division == other.Division && AffectsAll == other.AffectsAll && + IncludeUnrented == other.IncludeUnrented && AffectedFlats.SequenceEqual(other.AffectedFlats) && + Entries.SequenceEqual(other.Entries) && DisplayInBill == other.DisplayInBill; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((Cost) obj); + } + + public Cost Clone(Dictionary flatMapper) + { + return new Cost + { + Name = Name, + Division = Division, + AffectsAll = AffectsAll, + IncludeUnrented = IncludeUnrented, + AffectedFlats = new HashSet(AffectedFlats.Select(flat => flatMapper[flat])), + Entries = new List(Entries.Select(entry => entry.Clone())), + DisplayInBill = DisplayInBill + }; + } + } + + public class Billing + { + public DateTime StartDate { get; set; } + public DateTime EndDate { get; set; } + public Landlord Landlord { get; private set; } + public House House { get; private set; } + public List Tenants { get; private set; } + public List Costs { get; private set; } + + public Billing() + { + Landlord = new Landlord(); + House = new House(); + Tenants = new List(); + Costs = new List(); + } + + private bool Equals(Billing other) + { + return StartDate.Equals(other.StartDate) && EndDate.Equals(other.EndDate) && + Landlord.Equals(other.Landlord) && House.Equals(other.House) && + Tenants.SequenceEqual(other.Tenants) && Costs.SequenceEqual(other.Costs); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((Billing) obj); + } + + public Billing Clone() + { + var house = House.Clone(); + var flatMapper = new Dictionary(new ObjectReferenceEqualityComparer()); + + for (var i = 0; i < House.Flats.Count; ++i) + { + flatMapper.Add(House.Flats[i], house.Flats[i]); + } + + return new Billing + { + StartDate = StartDate, + EndDate = EndDate, + Landlord = Landlord.Clone(), + House = House, + Tenants = new List(Tenants.Select(tenant => tenant.Clone(flatMapper))), + Costs = new List(Costs.Select(cost => cost.Clone(flatMapper))) + }; + } + } + + public class ObjectReferenceEqualityComparer : EqualityComparer + where T : class + { + public override bool Equals(T x, T y) + { + return ReferenceEquals(x, y); + } + + public override int GetHashCode(T obj) + { + return RuntimeHelpers.GetHashCode(obj); + } + } +} \ No newline at end of file diff --git a/ucalc/Data/RecentlyOpened.cs b/ucalc/Data/RecentlyOpened.cs new file mode 100644 index 0000000..fefb881 --- /dev/null +++ b/ucalc/Data/RecentlyOpened.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace UCalc.Data +{ + public class RecentlyOpenedItem + { + public string DisplayText { get; } + public string Path { get; } + + public RecentlyOpenedItem(string path) + { + DisplayText = System.IO.Path.GetFileNameWithoutExtension(path); + Path = path; + } + + private bool Equals(RecentlyOpenedItem other) + { + return DisplayText == other.DisplayText && Path == other.Path; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((RecentlyOpenedItem) obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(DisplayText, Path); + } + + public override string ToString() + { + return DisplayText; + } + } + + public class RecentlyOpenedList : ICollection + { + private readonly List _list; + + public RecentlyOpenedList() + { + _list = new List(); + } + + public IEnumerator GetEnumerator() + { + return _list.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return _list.GetEnumerator(); + } + + public void Add(RecentlyOpenedItem item) + { + var index = _list.IndexOf(item); + if (index != -1) + { + _list.RemoveAt(index); + } + + _list.Insert(0, item); + + if (_list.Count > 10) + { + _list.RemoveAt(10); + } + } + + public void Clear() + { + _list.Clear(); + } + + public bool Contains(RecentlyOpenedItem item) + { + return _list.Contains(item); + } + + public void CopyTo(RecentlyOpenedItem[] array, int arrayIndex) + { + _list.CopyTo(array, arrayIndex); + } + + public bool Remove(RecentlyOpenedItem item) + { + return _list.Remove(item); + } + + public int Count => _list.Count; + public bool IsReadOnly => false; + } +} \ No newline at end of file diff --git a/ucalc/MainWindow.xaml b/ucalc/MainWindow.xaml new file mode 100644 index 0000000..1397d60 --- /dev/null +++ b/ucalc/MainWindow.xaml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ucalc/MainWindow.xaml.cs b/ucalc/MainWindow.xaml.cs new file mode 100644 index 0000000..129bfcd --- /dev/null +++ b/ucalc/MainWindow.xaml.cs @@ -0,0 +1,67 @@ +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using Microsoft.Win32; + +namespace UCalc +{ + public partial class MainWindow + { + public MainWindow() + { + InitializeComponent(); + } + + private void OnNewClick(object sender, RoutedEventArgs e) + { + var newWindow = new NewWindow {Owner = this}; + + if (newWindow.ShowDialog() == true) + { + new BillingWindow(newWindow.SavedBilling, newWindow.Billing).Show(); + Hide(); + } + } + + private void OnOpenClick(object sender, MouseButtonEventArgs e) + { + if (App.RecentlyOpenedList.Count == 0) + { + OnOpenFromDiskClick(null, null); + } + else + { + var button = (Button) sender; + var contextMenu = button.ContextMenu; + // ReSharper disable once PossibleNullReferenceException + contextMenu.PlacementTarget = button; + contextMenu.Placement = PlacementMode.Bottom; + contextMenu.IsOpen = true; + } + + e.Handled = true; + } + + private void OnOpenFromDiskClick(object sender, RoutedEventArgs e) + { + var dialog = new OpenFileDialog {Filter = "MietRechner Datei (*.mr) | *.mr"}; + + if (dialog.ShowDialog() == true) + { + throw new NotImplementedException(); + } + + if (e != null) + { + e.Handled = true; + } + } + + private void OnOpenRecentClick(object sender, RoutedEventArgs e) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/ucalc/NewWindow.xaml b/ucalc/NewWindow.xaml new file mode 100644 index 0000000..dac42d6 --- /dev/null +++ b/ucalc/NewWindow.xaml @@ -0,0 +1,81 @@ + + + + +