From c3a9971df62f366aca783bd7d198fdcb984228ad Mon Sep 17 00:00:00 2001 From: webwarrior Date: Sat, 2 Jul 2022 12:44:29 +0200 Subject: [PATCH 01/14] Frontend.XF: Replaced circle chart with hoop chart https://github.com/nblockchain/geewallet/issues/172 (cherry picked from commit bfeb0b790034e281fc69cdf52a9e1136635aafe8) --- src/GWallet.Frontend.XF/BalancesPage.xaml | 8 +- src/GWallet.Frontend.XF/BalancesPage.xaml.fs | 20 +-- src/GWallet.Frontend.XF/HoopChart.fs | 164 ++++++++++++++----- 3 files changed, 133 insertions(+), 59 deletions(-) diff --git a/src/GWallet.Frontend.XF/BalancesPage.xaml b/src/GWallet.Frontend.XF/BalancesPage.xaml index d255e34a0..9cc772d3f 100644 --- a/src/GWallet.Frontend.XF/BalancesPage.xaml +++ b/src/GWallet.Frontend.XF/BalancesPage.xaml @@ -2,7 +2,7 @@ - - - diff --git a/src/GWallet.Frontend.XF/BalancesPage.xaml.fs b/src/GWallet.Frontend.XF/BalancesPage.xaml.fs index 40efd2c67..0ec5a672e 100644 --- a/src/GWallet.Frontend.XF/BalancesPage.xaml.fs +++ b/src/GWallet.Frontend.XF/BalancesPage.xaml.fs @@ -9,9 +9,9 @@ open Xamarin.Forms open Xamarin.Forms.Xaml open Xamarin.Essentials -open GWallet.Frontend.XF.Controls open GWallet.Backend open GWallet.Backend.FSharpUtil.UwpHacks +open Frontend.FSharp // this type allows us to represent the idea that if we have, for example, 3 LTC and an unknown number of ETC (might @@ -45,8 +45,8 @@ type BalancesPage(state: FrontendHelpers.IGlobalAppState, let totalFiatAmountFrame = mainLayout.FindByName "totalFiatAmountFrame" let totalReadOnlyFiatAmountFrame = mainLayout.FindByName "totalReadOnlyFiatAmountFrame" let contentLayout = base.FindByName "contentLayout" - let normalChartView = base.FindByName "normalChartView" - let readonlyChartView = base.FindByName "readonlyChartView" + let normalChartView = base.FindByName "normalChartView" + let readonlyChartView = base.FindByName "readonlyChartView" let standardTimeToRefreshBalances = TimeSpan.FromMinutes 5.0 let standardTimeToRefreshBalancesWhenThereIsImminentIncomingPaymentOrNotEnoughInfoToKnow = TimeSpan.FromMinutes 1.0 @@ -164,18 +164,12 @@ type BalancesPage(state: FrontendHelpers.IGlobalAppState, readonlyChartView else normalChartView - let fullAmount = balances.Sum(fun b -> GetAmountOrDefault b.FiatAmount) - + let chartSourceList = balances |> Seq.map (fun balanceState -> - let percentage = - if fullAmount = 0m then - 0m - else - GetAmountOrDefault balanceState.FiatAmount / fullAmount { Color = FrontendHelpers.GetCryptoColor balanceState.BalanceSet.Account.Currency - Percentage = float(percentage) + Amount = GetAmountOrDefault balanceState.FiatAmount } ) chartView.SegmentsSource <- chartSourceList @@ -408,8 +402,8 @@ type BalancesPage(state: FrontendHelpers.IGlobalAppState, mainLayout.FindByName totalOtherFiatAmountFrameName let currentChartView,otherChartView = - mainLayout.FindByName currentChartViewName, - mainLayout.FindByName otherChartViewName + mainLayout.FindByName currentChartViewName, + mainLayout.FindByName otherChartViewName let tapGestureRecognizer = TapGestureRecognizer() tapGestureRecognizer.Tapped.Add(fun _ -> diff --git a/src/GWallet.Frontend.XF/HoopChart.fs b/src/GWallet.Frontend.XF/HoopChart.fs index d5ea30cbb..6a9b308ba 100644 --- a/src/GWallet.Frontend.XF/HoopChart.fs +++ b/src/GWallet.Frontend.XF/HoopChart.fs @@ -11,16 +11,20 @@ open System.Threading.Tasks open System.ComponentModel open Microsoft.FSharp.Collections -type Wallet = { CryptoValue: double ; Stroke: Brush } +type SegmentInfo = + { + Color: Color + Amount: decimal + } type Percentage = { mutable Percent: double; Stroke: Brush } module HoopChart = - let computeCartesianCoordinate (angle:double) (radius:double) = + let centerX = 50. + let centerY = 50. - let centerX = 50. - let centerY = 50. + let computeCartesianCoordinate (angle:double) (radius:double) = let angleRad = (Math.PI / 180.) * (angle - 90.) @@ -64,32 +68,32 @@ module HoopChart = arcAngle + lengthOfArc arcAngle - let Normalize (wallets: seq) = + let Normalize (segments: seq) = let minimumShowablePercentage = 2. let visiblePercentageLimit = 1. let fullPie = 100. - let total = wallets |> Seq.sumBy(fun x -> x.CryptoValue) + let total = segments |> Seq.sumBy(fun x -> x.Amount) |> float - let innerNormalize (wallet: Wallet) : Option = + let innerNormalize (segments: SegmentInfo) : Option = - let percent = wallet.CryptoValue * fullPie / total + let percent = float(segments.Amount) * fullPie / total if fullPie >= percent && percent >= minimumShowablePercentage then - {Percentage.Percent = percent; Stroke = wallet.Stroke} |> Some + {Percentage.Percent = percent; Stroke = SolidColorBrush(segments.Color)} |> Some elif minimumShowablePercentage > percent && percent >= visiblePercentageLimit then - {Percentage.Percent = minimumShowablePercentage; Stroke = wallet.Stroke} |> Some + {Percentage.Percent = minimumShowablePercentage; Stroke = SolidColorBrush(segments.Color)} |> Some else None let pies = - wallets |> Seq.choose innerNormalize//List.choose innerNormalize + segments |> Seq.choose innerNormalize//List.choose innerNormalize @@ -114,34 +118,22 @@ module HoopChart = result - let beautifyAmount (wallet:seq) = + let beautifyAmount (wallet:seq) = let total = - wallet |> Seq.sumBy(fun x -> x.CryptoValue) - - let value = total.ToString() - let mutable balance = value - let mutable digits = balance.Length - - let place = 4 + wallet |> Seq.sumBy(fun x -> x.Amount) + let format = if total - floor(total) < 0.01m then "N0" else "N2" + total.ToString(format, CultureInfo.InvariantCulture) - for digit in 1..digits do - if place*digit <= digits then - - balance <- balance.Insert(digits+1-place*digit,",") - digits <- balance.Length - - balance - - - let makePies (grid:Grid) (wallet:seq) = + let makePies (segments: seq) : Grid = let mutable arcAngle = 0. - let slices = Seq.length(wallet) - let pies = Normalize wallet + let slices = Seq.length(segments) + let pies = Normalize segments + let grid = Grid(HorizontalOptions = LayoutOptions.Center) for pie in pies do @@ -188,25 +180,113 @@ module HoopChart = grid.Children.Add(path) + grid - - let create (wallet:seq) = - - + let create (wallet:seq) = + let beautifiedAmount = beautifyAmount wallet let grid = Grid() - let approx = Label( Text = "~", FontSize = 25., HorizontalOptions = LayoutOptions.Center, TranslationY = 160., TranslationX = -40.) - let balance = Label( Text = beautifiedAmount, FontSize = 25., HorizontalOptions = LayoutOptions.Center, TranslationY = 160., TranslationX = 0.) - let currency = Label( Text = "U.S.D.", FontSize = 24., HorizontalOptions = LayoutOptions.Center, TranslationY = 160., TranslationX = 65.) - let total_tag = Label( Text = "Amount Balance", FontSize = 15., HorizontalOptions = LayoutOptions.Center, TranslationY = 200.) + let balanceString = "~ " + beautifiedAmount + " U.S.D." + let balance = + Label( + Text = balanceString, + FontSize = 25., + HorizontalOptions = LayoutOptions.Center, + VerticalOptions = LayoutOptions.Center, + TranslationX = centerX / 2.0) + let total_tag = + Label( + Text = "Amount Balance", + FontSize = 15., + HorizontalOptions = LayoutOptions.Center, + VerticalOptions = LayoutOptions.Center, + TranslationY = 40.0, + TranslationX = centerX / 2.0) - grid.Children.Add(approx) grid.Children.Add(balance) - grid.Children.Add(currency) grid.Children.Add(total_tag) - makePies grid wallet + let pies = makePies wallet + grid.Children.Add(pies) + grid + + + +type HoopChartView() = + inherit ContentView() + + static let segmentsSourceProperty = + BindableProperty.Create("SegmentsSource", + typeof>, typeof, null) + static let defaultImageSourceProperty = + BindableProperty.Create("DefaultImageSource", + typeof, typeof, null) + + static member SegmentsSourceProperty = segmentsSourceProperty + static member DefaultImageSourceProperty = defaultImageSourceProperty + + member self.SegmentsSource + with get () = self.GetValue segmentsSourceProperty :?> seq + and set (value: seq) = self.SetValue(segmentsSourceProperty, value) + + member self.DefaultImageSource + with get () = self.GetValue defaultImageSourceProperty :?> ImageSource + and set (value: ImageSource) = self.SetValue(defaultImageSourceProperty, value) + + member private self.CreateAndSetImageSource (imageSource : ImageSource) = + let image = + Image ( + HorizontalOptions = LayoutOptions.FillAndExpand, + VerticalOptions = LayoutOptions.FillAndExpand, + Aspect = Aspect.AspectFit, + Source = imageSource + ) + self.Content <- image + + member self.Draw () = + let width = + if base.WidthRequest > 0. then + base.WidthRequest + else + base.Width + let height = + if base.HeightRequest > 0. then + base.HeightRequest + else + base.Height + + if width <= 0. || + height <= 0. || + not base.IsVisible then + () + else + let nonZeroItems = + if self.SegmentsSource <> null then + self.SegmentsSource.Where(fun s -> s.Amount > 0.0m) |> Some + else + None + + match nonZeroItems with + | None -> () + | Some items when items.Any() -> + let chart = HoopChart.create items + chart.MinimumWidthRequest <- width + chart.MinimumHeightRequest <- height + self.Content <- chart + | Some _ -> + self.CreateAndSetImageSource self.DefaultImageSource + + override self.OnPropertyChanged(propertyName: string) = + base.OnPropertyChanged(propertyName) + if propertyName = VisualElement.HeightProperty.PropertyName || + propertyName = VisualElement.WidthProperty.PropertyName || + propertyName = VisualElement.HeightRequestProperty.PropertyName || + propertyName = VisualElement.WidthRequestProperty.PropertyName || + propertyName = VisualElement.IsVisibleProperty.PropertyName || + propertyName = HoopChartView.SegmentsSourceProperty.PropertyName || + propertyName = HoopChartView.DefaultImageSourceProperty.PropertyName then + self.Draw() From bb061c390f396f5f897a7a9553fa2e6dd09a800c Mon Sep 17 00:00:00 2001 From: webwarrior Date: Sun, 3 Jul 2022 14:08:34 +0200 Subject: [PATCH 02/14] Frontend.XF: Moved total amount label inside new hoop chart Also removed no longer used CircleChartView.fs file https://github.com/nblockchain/geewallet/issues/172 (cherry picked from commit f4219b9a223008ffb64a71819cee9cf51ae0b851) --- src/GWallet.Frontend.XF/BalancesPage.xaml | 47 --- src/GWallet.Frontend.XF/BalancesPage.xaml.fs | 32 +- .../Controls/CircleChartView.fs | 303 ------------------ .../GWallet.Frontend.XF.fsproj | 1 - src/GWallet.Frontend.XF/HoopChart.fs | 95 +++--- 5 files changed, 57 insertions(+), 421 deletions(-) delete mode 100644 src/GWallet.Frontend.XF/Controls/CircleChartView.fs diff --git a/src/GWallet.Frontend.XF/BalancesPage.xaml b/src/GWallet.Frontend.XF/BalancesPage.xaml index 9cc772d3f..d75dbe9cc 100644 --- a/src/GWallet.Frontend.XF/BalancesPage.xaml +++ b/src/GWallet.Frontend.XF/BalancesPage.xaml @@ -14,53 +14,6 @@ VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"> - - - - - - - - - - - - diff --git a/src/GWallet.Frontend.XF/BalancesPage.xaml.fs b/src/GWallet.Frontend.XF/BalancesPage.xaml.fs index 0ec5a672e..648fac1ef 100644 --- a/src/GWallet.Frontend.XF/BalancesPage.xaml.fs +++ b/src/GWallet.Frontend.XF/BalancesPage.xaml.fs @@ -40,10 +40,6 @@ type BalancesPage(state: FrontendHelpers.IGlobalAppState, let normalAccountsBalanceSets = normalBalanceStates.Select(fun balState -> balState.BalanceSet) let readOnlyAccountsBalanceSets = readOnlyBalanceStates.Select(fun balState -> balState.BalanceSet) let mainLayout = base.FindByName("mainLayout") - let totalFiatAmountLabel = mainLayout.FindByName