Skip to content

Commit

Permalink
Add IReportState so that we do not keep entire report on the undo stack.
Browse files Browse the repository at this point in the history
Fix report disposal so event handlers are removed so that reports are properly garbage collected.
  • Loading branch information
clovett committed Jun 24, 2024
1 parent fc3c044 commit 18f05fd
Show file tree
Hide file tree
Showing 14 changed files with 829 additions and 244 deletions.
255 changes: 218 additions & 37 deletions Source/WPF/MyMoney/MainWindow.xaml.cs

Large diffs are not rendered by default.

236 changes: 139 additions & 97 deletions Source/WPF/MyMoney/Reports/CashFlowReport.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
Expand All @@ -16,130 +17,96 @@

namespace Walkabout.Reports
{
internal class CashFlowCell
{
internal List<Transaction> Data; // or splits
internal decimal Value;
}

internal class CashFlowColumns
//=========================================================================================
public class CashFlowReport : Report
{
private readonly Dictionary<string, CashFlowCell> columns = new Dictionary<string, CashFlowCell>();
private MyMoney myMoney;
private bool byYear;
private int fiscalYearStart;
private DateTime startDate;
private DateTime endDate;
private Dictionary<Category, CashFlowColumns> byCategory;
private Dictionary<string, int> monthMap;
private List<string> columns;

public void AddValue(string key, Transaction data, decimal amount)
public CashFlowReport()
{
CashFlowCell cell;
this.columns.TryGetValue(key, out cell);
if (cell == null)
{
cell = new CashFlowCell();
cell.Data = new List<Transaction>();
this.columns[key] = cell;
}
cell.Value += amount;
if (data != null)
{
cell.Data.Add(data);
}
this.startDate = new DateTime(DateTime.Now.Year, 1, 1);
this.byYear = true;
this.endDate = this.startDate.AddYears(1);
this.startDate = this.startDate.AddYears(-4); // show 5 years by default.
}

public CashFlowCell GetCell(string key)
~CashFlowReport()
{
CashFlowCell cell = null;
if (!this.columns.TryGetValue(key, out cell))
{
cell = new CashFlowCell();
}
return cell;
Debug.WriteLine("CashFlowReport disposed!");
}

public decimal GetValue(string key)
public int FiscalYearStart
{
CashFlowCell cell;
this.columns.TryGetValue(key, out cell);
if (cell != null)
get => this.fiscalYearStart;
set
{
return cell.Value;
this.fiscalYearStart = value;
this.startDate = new DateTime(DateTime.Now.Year, this.fiscalYearStart + 1, 1);
if (this.startDate > DateTime.Today)
{
this.startDate = this.startDate.AddYears(-1);
}
}
return 0;
}

public List<Transaction> GetData(string key)
public override void OnSiteChanged()
{
CashFlowCell cell;
this.columns.TryGetValue(key, out cell);
if (cell != null)
{
return cell.Data;
}
return new List<Transaction>();
this.myMoney = (MyMoney)this.ServiceProvider.GetService(typeof(MyMoney));
}

public List<decimal> GetOrderedValues(IEnumerable<string> columnKeys)
class CashFlowReportState : IReportState
{
List<decimal> result = new List<decimal>();
foreach (string name in columnKeys)
public int FiscalYearStart { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }

public CashFlowReportState()
{
result.Add(this.GetValue(name));
}
return result;
}

public int Count { get { return this.columns.Count; } }
}

//=========================================================================================
public class CashFlowReport : Report
{
private readonly FlowDocumentView view;
private readonly MyMoney myMoney;
private bool byYear;
private readonly int fiscalYearStart;
private DateTime startDate;
private DateTime endDate;
private Dictionary<Category, CashFlowColumns> byCategory;
private Dictionary<string, int> monthMap;
private List<string> columns;
private readonly IServiceProvider serviceProvider;

public CashFlowReport(FlowDocumentView view, MyMoney money, IServiceProvider sp, int fiscalYearStart)
{
this.myMoney = money;
this.fiscalYearStart = fiscalYearStart;
this.startDate = new DateTime(DateTime.Now.Year, 1, 1);
this.byYear = true;
if (this.fiscalYearStart > 0)
public Type GetReportType()
{
this.startDate = new DateTime(DateTime.Now.Year, this.fiscalYearStart + 1, 1);
if (this.startDate > DateTime.Today)
{
this.startDate = this.startDate.AddYears(-1);
}
return typeof(CashFlowReport);
}
}

this.endDate = this.startDate.AddYears(1);
this.startDate = this.startDate.AddYears(-4); // show 5 years by default.
this.view = view;
this.serviceProvider = sp;
view.Unloaded += (s, e) =>
public override IReportState GetState()
{
return new CashFlowReportState()
{
this.view.PreviewMouseLeftButtonUp -= this.OnPreviewMouseLeftButtonUp;
FiscalYearStart = this.fiscalYearStart,
StartDate = this.startDate,
EndDate = this.endDate
};
view.Loaded += (s, e) =>
}

public override void ApplyState(IReportState state)
{
if (state is CashFlowReportState cashFlowReportState)
{
view.PreviewMouseLeftButtonUp -= this.OnPreviewMouseLeftButtonUp;
view.PreviewMouseLeftButtonUp += this.OnPreviewMouseLeftButtonUp;
};
this.FiscalYearStart = cashFlowReportState.FiscalYearStart;
this.startDate = cashFlowReportState.StartDate;
this.endDate = cashFlowReportState.EndDate;
}
}

private void OnPreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)

public override void OnMouseLeftButtonClick(object sender, MouseButtonEventArgs e)
{
Point pos = e.GetPosition(this.view);
var view = (FlowDocumentView)sender;
Point pos = e.GetPosition(view);

if (this.mouseDownCell != null && Math.Abs(this.downPos.X - pos.X) < 5 && Math.Abs(this.downPos.Y - pos.Y) < 5)
{
// navigate to show the cell.Data rows.
IViewNavigator nav = this.serviceProvider.GetService(typeof(IViewNavigator)) as IViewNavigator;
IViewNavigator nav = this.ServiceProvider.GetService(typeof(IViewNavigator)) as IViewNavigator;
nav.ViewTransactions(this.mouseDownCell.Data);
}
}
Expand Down Expand Up @@ -200,11 +167,6 @@ private bool IsInvestment(Category c)
return c.Type == CategoryType.Investments;
}

public void Regenerate()
{
_ = this.view.Generate(this);
}

public override Task Generate(IReportWriter writer)
{
this.byCategory = new Dictionary<Category, CashFlowColumns>();
Expand Down Expand Up @@ -378,6 +340,12 @@ private void OnByYearMonthChanged(object sender, SelectionChangedEventArgs e)
this.Regenerate();
}

public void Regenerate()
{
var view = (FlowDocumentView)this.ServiceProvider.GetService(typeof(FlowDocumentView));
_ = view.Generate(this);
}

private Button CreateExportReportButton()
{
Button button = this.CreateReportButton("Icons/Excel.png", "Export", "Export .csv spreadsheet file format");
Expand Down Expand Up @@ -591,9 +559,10 @@ private void WriteRow(IReportWriter writer, bool header, bool addExpanderCell, s

private void OnReportCellMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
var view = (FlowDocumentView)this.ServiceProvider.GetService(typeof(FlowDocumentView));
Paragraph p = (Paragraph)sender;
this.mouseDownCell = (CashFlowCell)p.Tag;
this.downPos = e.GetPosition(this.view);
this.downPos = e.GetPosition(view);
}


Expand Down Expand Up @@ -652,6 +621,79 @@ private void GenerateCsvGroup(StreamWriter writer, Dictionary<Category, CashFlow
}
writer.WriteLine();
}

internal class CashFlowCell
{
internal List<Transaction> Data; // or splits
internal decimal Value;
}

internal class CashFlowColumns
{
private readonly Dictionary<string, CashFlowCell> columns = new Dictionary<string, CashFlowCell>();

public void AddValue(string key, Transaction data, decimal amount)
{
CashFlowCell cell;
this.columns.TryGetValue(key, out cell);
if (cell == null)
{
cell = new CashFlowCell();
cell.Data = new List<Transaction>();
this.columns[key] = cell;
}
cell.Value += amount;
if (data != null)
{
cell.Data.Add(data);
}
}

public CashFlowCell GetCell(string key)
{
CashFlowCell cell = null;
if (!this.columns.TryGetValue(key, out cell))
{
cell = new CashFlowCell();
}
return cell;
}

public decimal GetValue(string key)
{
CashFlowCell cell;
this.columns.TryGetValue(key, out cell);
if (cell != null)
{
return cell.Value;
}
return 0;
}

public List<Transaction> GetData(string key)
{
CashFlowCell cell;
this.columns.TryGetValue(key, out cell);
if (cell != null)
{
return cell.Data;
}
return new List<Transaction>();
}

public List<decimal> GetOrderedValues(IEnumerable<string> columnKeys)
{
List<decimal> result = new List<decimal>();
foreach (string name in columnKeys)
{
result.Add(this.GetValue(name));
}
return result;
}

public int Count { get { return this.columns.Count; } }
}

}

}
28 changes: 23 additions & 5 deletions Source/WPF/MyMoney/Reports/FutureBillsReport.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
Expand All @@ -16,7 +17,7 @@ namespace Walkabout.Reports
/// </summary>
public class FutureBillsReport : Report
{
private readonly MyMoney myMoney;
private MyMoney myMoney;
private const int ALLOWED_MISSED_PAYMENTS = 2;

internal struct PaymentKey
Expand Down Expand Up @@ -102,8 +103,6 @@ internal class Payments
internal const double AmountSensitivity = 0.1; // % stderr
internal const double TimeSensitivity = 0.5; // % stderr on date

private List<Transaction> transactions;

public Payee Payee { get; internal set; }
public Category Category { get; internal set; }

Expand Down Expand Up @@ -285,9 +284,27 @@ public Payments()
}
}

public FutureBillsReport(MyMoney money)
public FutureBillsReport()
{
}

~FutureBillsReport()
{
Debug.WriteLine("FutureBillsReport disposed!");
}

public override void OnSiteChanged()
{
this.myMoney = (MyMoney)this.ServiceProvider.GetService(typeof(MyMoney));
}

public override IReportState GetState()
{
return new SimpleReportState(typeof(FutureBillsReport));
}

public override void ApplyState(IReportState state)
{
this.myMoney = money;
}

public override Task Generate(IReportWriter writer)
Expand Down Expand Up @@ -466,6 +483,7 @@ public override void Export(string filename)
{
throw new NotImplementedException();
}

}


Expand Down
Loading

0 comments on commit 18f05fd

Please sign in to comment.