chart improvements, synch working
This commit is contained in:
@@ -234,7 +234,6 @@ class _OverviewScreenState extends State<OverviewScreen> {
|
||||
_period,
|
||||
includedLabelIds: _includedLabelIds,
|
||||
flow: _labelFlow,
|
||||
invertExpensePerspective: _labelInvertChart,
|
||||
);
|
||||
labelSpend = labels.spend;
|
||||
labelAmountByPeriod = labels.amountByPeriod;
|
||||
@@ -277,6 +276,7 @@ class _OverviewScreenState extends State<OverviewScreen> {
|
||||
labelSpend: labelSpend,
|
||||
labelAmountByMonth: labelAmountByPeriod,
|
||||
labelBarStyle: _labelBarStyle,
|
||||
invertChart: _labelFlow == TxFlowFilter.all && _labelInvertChart,
|
||||
currency: currency,
|
||||
onPickLabels: () => _pickChartLabels(context),
|
||||
includedLabelCount: _includedLabelIds.isEmpty &&
|
||||
@@ -555,8 +555,9 @@ class _LabelAggregates {
|
||||
/// One pass over labeled amounts: totals, per-period series, and history.
|
||||
///
|
||||
/// Amounts are summed with sign (refunds offset spend). For [TxFlowFilter.all]
|
||||
/// the signed net is kept (can be negative). With [invertExpensePerspective],
|
||||
/// signs flip so spending plots upward. For In/Out, bars use absolute nets.
|
||||
/// the signed net is kept (can be negative). For In/Out, bars use absolute nets.
|
||||
/// Chart-only invert is applied later in [_LabelMonthBars], not here — history
|
||||
/// always follows bank transaction signs.
|
||||
_LabelAggregates _labelAggregates(
|
||||
List<BankTransaction> txs,
|
||||
TxMetaController meta,
|
||||
@@ -564,7 +565,6 @@ _LabelAggregates _labelAggregates(
|
||||
_PeriodMode mode, {
|
||||
Set<String> includedLabelIds = const {},
|
||||
TxFlowFilter flow = TxFlowFilter.expense,
|
||||
bool invertExpensePerspective = false,
|
||||
}) {
|
||||
final keys = {for (final p in periods) _periodKey(p, mode)};
|
||||
final allByLabel = <String, double>{};
|
||||
@@ -576,7 +576,6 @@ _LabelAggregates _labelAggregates(
|
||||
};
|
||||
final filtering = includedLabelIds.isNotEmpty;
|
||||
final keepSigned = flow == TxFlowFilter.all;
|
||||
final invert = keepSigned && invertExpensePerspective;
|
||||
|
||||
for (final tx in txs) {
|
||||
if (meta.metaFor(tx).internalTransfer) continue;
|
||||
@@ -608,7 +607,7 @@ _LabelAggregates _labelAggregates(
|
||||
|
||||
double displayAmount(double signed) {
|
||||
if (!keepSigned) return signed.abs();
|
||||
return invert ? -signed : signed;
|
||||
return signed;
|
||||
}
|
||||
|
||||
final allSpend = <_LabelSpend>[
|
||||
@@ -756,6 +755,7 @@ class _ChartCard extends StatelessWidget {
|
||||
required this.labelSpend,
|
||||
required this.labelAmountByMonth,
|
||||
required this.labelBarStyle,
|
||||
required this.invertChart,
|
||||
required this.currency,
|
||||
required this.onPickLabels,
|
||||
required this.includedLabelCount,
|
||||
@@ -776,6 +776,7 @@ class _ChartCard extends StatelessWidget {
|
||||
final List<_LabelSpend> labelSpend;
|
||||
final Map<DateTime, Map<String, double>> labelAmountByMonth;
|
||||
final LabelChartBarStyle labelBarStyle;
|
||||
final bool invertChart;
|
||||
final String currency;
|
||||
final VoidCallback onPickLabels;
|
||||
final int? includedLabelCount;
|
||||
@@ -951,6 +952,7 @@ class _ChartCard extends StatelessWidget {
|
||||
currency: currency,
|
||||
period: period,
|
||||
barStyle: labelBarStyle,
|
||||
invertChart: invertChart,
|
||||
onMonthTap: onMonthTap,
|
||||
),
|
||||
),
|
||||
@@ -1118,6 +1120,7 @@ class _LabelMonthBars extends StatelessWidget {
|
||||
required this.currency,
|
||||
required this.period,
|
||||
required this.barStyle,
|
||||
required this.invertChart,
|
||||
required this.onMonthTap,
|
||||
});
|
||||
|
||||
@@ -1129,8 +1132,11 @@ class _LabelMonthBars extends StatelessWidget {
|
||||
final String currency;
|
||||
final _PeriodMode period;
|
||||
final LabelChartBarStyle barStyle;
|
||||
final bool invertChart;
|
||||
final void Function(DateTime month) onMonthTap;
|
||||
|
||||
double _plot(double value) => invertChart ? -value : value;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
@@ -1172,10 +1178,11 @@ class _LabelMonthBars extends StatelessWidget {
|
||||
var pos = 0.0;
|
||||
var neg = 0.0;
|
||||
void accumulate(double value) {
|
||||
if (value > 0) {
|
||||
pos += value;
|
||||
} else if (value < 0) {
|
||||
neg += value;
|
||||
final plotted = _plot(value);
|
||||
if (plotted > 0) {
|
||||
pos += plotted;
|
||||
} else if (plotted < 0) {
|
||||
neg += plotted;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1187,11 +1194,11 @@ class _LabelMonthBars extends StatelessWidget {
|
||||
if (neg < minY) minY = neg;
|
||||
} else {
|
||||
for (final row in topLabels) {
|
||||
final value = bucket[row.label.id] ?? 0;
|
||||
final value = _plot(bucket[row.label.id] ?? 0);
|
||||
if (value > maxY) maxY = value;
|
||||
if (value < minY) minY = value;
|
||||
}
|
||||
final other = otherFor(month);
|
||||
final other = _plot(otherFor(month));
|
||||
if (other > maxY) maxY = other;
|
||||
if (other < minY) minY = other;
|
||||
}
|
||||
@@ -1229,12 +1236,13 @@ class _LabelMonthBars extends StatelessWidget {
|
||||
var neg = 0.0;
|
||||
|
||||
void addSegment(double value, Color color) {
|
||||
if (value > 0) {
|
||||
stackItems.add(BarChartRodStackItem(pos, pos + value, color));
|
||||
pos += value;
|
||||
} else if (value < 0) {
|
||||
stackItems.add(BarChartRodStackItem(neg + value, neg, color));
|
||||
neg += value;
|
||||
final plotted = _plot(value);
|
||||
if (plotted > 0) {
|
||||
stackItems.add(BarChartRodStackItem(pos, pos + plotted, color));
|
||||
pos += plotted;
|
||||
} else if (plotted < 0) {
|
||||
stackItems.add(BarChartRodStackItem(neg + plotted, neg, color));
|
||||
neg += plotted;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1277,16 +1285,16 @@ class _LabelMonthBars extends StatelessWidget {
|
||||
return [
|
||||
for (final row in topLabels)
|
||||
BarChartRodData(
|
||||
toY: bucket[row.label.id] ?? 0,
|
||||
toY: _plot(bucket[row.label.id] ?? 0),
|
||||
width: rodWidth,
|
||||
borderRadius: rodRadius(bucket[row.label.id] ?? 0),
|
||||
borderRadius: rodRadius(_plot(bucket[row.label.id] ?? 0)),
|
||||
color: row.label.color,
|
||||
),
|
||||
if (hasOther)
|
||||
BarChartRodData(
|
||||
toY: otherFor(month),
|
||||
toY: _plot(otherFor(month)),
|
||||
width: rodWidth,
|
||||
borderRadius: rodRadius(otherFor(month)),
|
||||
borderRadius: rodRadius(_plot(otherFor(month))),
|
||||
color: otherColor,
|
||||
),
|
||||
];
|
||||
@@ -1342,7 +1350,7 @@ class _LabelMonthBars extends StatelessWidget {
|
||||
return BarTooltipItem(
|
||||
'${_periodAxisLabel(month, period)}\n'
|
||||
'$name\n'
|
||||
'${formatMoney(rod.toY, currency)}',
|
||||
'${formatMoney(invertChart ? -rod.toY : rod.toY, currency)}',
|
||||
TextStyle(color: colors.onInverseSurface),
|
||||
);
|
||||
},
|
||||
@@ -1627,19 +1635,17 @@ class _LabelHistoryCard extends StatelessWidget {
|
||||
|
||||
/// Display amount + color for history rows.
|
||||
///
|
||||
/// Keeps the original `-amount` sign convention; for All, color follows the
|
||||
/// displayed value (positive → green, negative → red).
|
||||
/// Keep the aggregate sign (All already signed; In/Out use abs then restore
|
||||
/// bank-like sign). Color follows the displayed value.
|
||||
(double display, Color color) _styleFor(double amount) {
|
||||
switch (flow) {
|
||||
case TxFlowFilter.expense:
|
||||
case TxFlowFilter.income:
|
||||
return (-amount.abs(), _kExpenseColor);
|
||||
case TxFlowFilter.all:
|
||||
final display = -amount;
|
||||
if (display > 0) return (display, _kIncomeColor);
|
||||
if (display < 0) return (display, _kExpenseColor);
|
||||
return (0, _kExpenseColor);
|
||||
}
|
||||
final signed = switch (flow) {
|
||||
TxFlowFilter.expense => -amount.abs(),
|
||||
TxFlowFilter.income => amount.abs(),
|
||||
TxFlowFilter.all => amount,
|
||||
};
|
||||
if (signed > 0) return (signed, _kIncomeColor);
|
||||
if (signed < 0) return (signed, _kExpenseColor);
|
||||
return (0, _kExpenseColor);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
Reference in New Issue
Block a user