MessageBox revision and more async loading

This commit is contained in:
Michael Bucari-Tovo 2022-07-14 12:51:50 -06:00
parent a5d225dc44
commit 61a529e62b
10 changed files with 141 additions and 103 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 B

View File

@ -214,42 +214,28 @@ namespace LibationWinForms.AvaloniaUI
var vm = new MessageBoxViewModel(message, caption, buttons, icon, defaultButton);
dialog.DataContext = vm;
dialog.CanResize = false;
var thisScreen = (owner ?? dialog).Screens.ScreenFromVisual(owner ?? dialog);
var tbx = dialog.FindControl<TextBlock>("messageTextBlock");
tbx.MinWidth = vm.TextBlockMinWidth;
tbx.Text = message;
var maxSize = new Size(0.6 * thisScreen.Bounds.Width - 72, 0.9 * thisScreen.Bounds.Height);
var thisScreen = (owner ?? dialog).Screens.ScreenFromVisual(owner ?? dialog);
var desiredMax = maxSize;
var maxSize = new Size(0.20 * thisScreen.Bounds.Width, 0.9 * thisScreen.Bounds.Height - 55);
var desiredMax = new Size(maxSize.Width, maxSize.Height);
//Try to minimize the TextBlock area.
List<(double, Size)> areas = new();
for (int i = 0; i < 20; i++)
{
tbx.Measure(desiredMax);
var area = tbx.DesiredSize.Width * tbx.DesiredSize.Height;
areas.Add((area, new Size(tbx.DesiredSize.Width, tbx.DesiredSize.Height)));
tbx.Height = tbx.DesiredSize.Height;
tbx.Width = tbx.DesiredSize.Width;
dialog.MinHeight = vm.FormHeightFromTboxHeight((int)tbx.DesiredSize.Height);
dialog.MinWidth = vm.FormWidthFromTboxWidth((int)tbx.DesiredSize.Width);
dialog.MaxHeight = dialog.MinHeight;
dialog.MaxWidth = dialog.MinWidth;
dialog.Height = dialog.MinHeight;
dialog.Width = dialog.MinWidth;
if (tbx.DesiredSize.Height < maxSize.Height - 20)
{
if (desiredMax.Width / 2 < tbx.MinWidth)
desiredMax = new Size(desiredMax.Width * 1.5 + 1, desiredMax.Height);
else
desiredMax = new Size(desiredMax.Width / 2, desiredMax.Height);
}
}
var min = areas.Min(a => a.Item1);
var mindim = areas.First(a => a.Item1 == min);
var desiredSize = new Size(dialog.MinWidth - tbx.MinWidth + mindim.Item2.Width, dialog.MinHeight - tbx.MinHeight + mindim.Item2.Height);
dialog.Width = desiredSize.Width;
dialog.Height = desiredSize.Height;
tbx.Width = mindim.Item2.Width;
tbx.Height = mindim.Item2.Height;
if (owner is null)
{

View File

@ -63,6 +63,15 @@ namespace LibationWinForms.AvaloniaUI.ViewModels.Dialogs
_ => string.Empty,
};
public int TextBlockMinWidth { get; }
public double FormHeightFromTboxHeight(double tboxHeight) => tboxHeight + 65;
public double FormWidthFromTboxWidth(double tboxWidth)
{
int iconWidth = _icon is MessageBoxIcon.None ? 0 : 42;
return tboxWidth + 20 + iconWidth;
}
public MessageBoxViewModel() { }
public MessageBoxViewModel(string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultBtn)
{
@ -72,6 +81,11 @@ namespace LibationWinForms.AvaloniaUI.ViewModels.Dialogs
_button = buttons;
_icon = icon;
_defaultButton = defaultBtn;
int numBtns = HasButton3 ? 3 : HasButton2 ? 2 : 1;
int iconWidth = icon is MessageBoxIcon.None ? 0 : 42;
int formMinWidth = Math.Max(85 * numBtns + 10, 71 + iconWidth + 20);
TextBlockMinWidth = formMinWidth - 20 - iconWidth;
}
}
}

View File

@ -3,39 +3,41 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:LibationWinForms.AvaloniaUI.ViewModels"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
mc:Ignorable="d" d:DesignWidth="375" d:DesignHeight="130" MinWidth="385" MinHeight="150"
mc:Ignorable="d" d:DesignWidth="265" d:DesignHeight="110"
MinWidth="265" MinHeight="110"
x:Class="LibationWinForms.AvaloniaUI.Views.Dialogs.MessageBoxWindow"
Title="{Binding Caption}" HasSystemDecorations="True" ShowInTaskbar="True">
Title="{Binding Caption}" HasSystemDecorations="True" ShowInTaskbar="True"
Icon="/AvaloniaUI/Assets/1x1.png">
<Grid ColumnDefinitions="*" RowDefinitions="*,Auto">
<StackPanel Orientation="Horizontal"
Grid.Row="0" Grid.Column="0"
Margin="10" VerticalAlignment="Top">
<Panel
Grid.Column="0"
Margin="10" VerticalAlignment="Top">
<DockPanel Margin="5,10,10,10" Grid.Row="0" Background="White">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal"
VerticalAlignment="Top">
<Panel Grid.Column="0" Margin="5,0,5,0" VerticalAlignment="Top">
<Image IsVisible="{Binding IsAsterisk}" Stretch="None" Source="/AvaloniaUI/Assets/MBIcons/Asterisk.png"/>
<Image IsVisible="{Binding IsError}" Stretch="None" Source="/AvaloniaUI/Assets/MBIcons/error.png"/>
<Image IsVisible="{Binding IsQuestion}" Stretch="None" Source="/AvaloniaUI/Assets/MBIcons/Question.png"/>
<Image IsVisible="{Binding IsExclamation}" Stretch="None" Source="/AvaloniaUI/Assets/MBIcons/Exclamation.png"/>
</Panel>
<TextBlock Name="messageTextBlock" Background="Snow" MinHeight="80" MinWidth="300" TextWrapping="WrapWithOverflow" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="12" Text="{Binding Message}" />
<TextBlock Margin="5,0,0,0" Name="messageTextBlock" MinHeight="45" MinWidth="203" TextWrapping="WrapWithOverflow" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="12" Text="{Binding Message}" />
</StackPanel>
</DockPanel>
<Grid Grid.Row="1" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="0,0,15,10" ColumnDefinitions="Auto, Auto, Auto">
<Button Grid.Column="0" MinWidth="80" MinHeight="25" Name="Button1" Click="Button1_Click" Margin="5">
<DockPanel Height="45" Grid.Row="1" Background="LightGray">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="5" DockPanel.Dock="Bottom">
<Button Grid.Column="0" MinWidth="75" MinHeight="25" Name="Button1" Click="Button1_Click" Margin="5">
<TextBlock VerticalAlignment="Center" Text="{Binding Button1Text}"/>
</Button>
<Button Grid.Column="1" IsVisible="{Binding HasButton2}" MinWidth="80" MinHeight="25" Name="Button2" Click="Button2_Click" Margin="5">
<Button Grid.Column="1" IsVisible="{Binding HasButton2}" MinWidth="75" MinHeight="25" Name="Button2" Click="Button2_Click" Margin="5">
<TextBlock VerticalAlignment="Center" Text="{Binding Button2Text}"/>
</Button>
<Button Grid.Column="2" IsVisible="{Binding HasButton3}" MinWidth="80" MinHeight="25" Name="Button3" Click="Button3_Click" Content="Cancel" Margin="5">
<Button Grid.Column="2" IsVisible="{Binding HasButton3}" MinWidth="75" MinHeight="25" Name="Button3" Click="Button3_Click" Content="Cancel" Margin="5">
<TextBlock VerticalAlignment="Center" Text="{Binding Button3Text}"/>
</Button>
</Grid>
</StackPanel>
</DockPanel>
</Grid>
</Window>

View File

@ -8,6 +8,7 @@ using Avalonia.Threading;
using LibationWinForms.AvaloniaUI.Views.ProductsGrid;
using Avalonia.ReactiveUI;
using LibationWinForms.AvaloniaUI.ViewModels;
using System.Threading.Tasks;
namespace LibationWinForms.AvaloniaUI.Views
{
@ -21,7 +22,6 @@ namespace LibationWinForms.AvaloniaUI.Views
#endif
this.FindAllControls();
// eg: if one of these init'd productsGrid, then another can't reliably subscribe to it
Configure_BackupCounts();
Configure_ScanAuto();
@ -38,11 +38,21 @@ namespace LibationWinForms.AvaloniaUI.Views
// misc which belongs in winforms app but doesn't have a UI element
Configure_NonUI();
async void DoDisplay(object _, EventArgs __)
{
this.Load += (_, _) => productsDisplay.Display();
LibraryCommands.LibrarySizeChanged += (_, __) => Dispatcher.UIThread.Post(() => productsDisplay.Display());
await productsDisplay.Display();
}
{
this.Load += DoDisplay;
LibraryCommands.LibrarySizeChanged += DoDisplay;
}
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
public event EventHandler Load;
public void OnLoad() => Load?.Invoke(this, EventArgs.Empty);
@ -114,10 +124,5 @@ namespace LibationWinForms.AvaloniaUI.Views
{
base.OnDataContextChanged(e);
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
}

View File

@ -5,6 +5,8 @@ using System;
using System.Collections;
using System.Linq;
using System.Reflection;
using Avalonia.Threading;
using System.Threading.Tasks;
namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
{
@ -12,7 +14,7 @@ namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
{
private void Configure_Display() { }
public void Display()
public async Task Display()
{
try
{
@ -21,8 +23,10 @@ namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
if (_viewModel is null)
{
_viewModel = new ProductsDisplayViewModel(dbBooks);
InitialLoaded?.Invoke(this, EventArgs.Empty);
VisibleCountChanged?.Invoke(this, bindingList.BookEntries().Count());
await Dispatcher.UIThread.InvokeAsync(() => InitialLoaded?.Invoke(this, EventArgs.Empty));
int bookEntryCount = bindingList.BookEntries().Count();
await Dispatcher.UIThread.InvokeAsync(() => VisibleCountChanged?.Invoke(this, bookEntryCount));
//Avalonia displays items in the DataConncetion from an internal copy of
//the bound list, not the actual bound list. So we need to reflect to get
@ -48,9 +52,13 @@ namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
{
//List is already displayed. Replace all items with new ones, refilter, and re-sort
string existingFilter = _viewModel?.GridEntries?.Filter;
bindingList.ReplaceList(ProductsDisplayViewModel.CreateGridEntries(dbBooks));
var newEntries = ProductsDisplayViewModel.CreateGridEntries(dbBooks);
await Dispatcher.UIThread.InvokeAsync(() =>
{
bindingList.ReplaceList(newEntries);
bindingList.Filter = existingFilter;
ReSort();
});
}
}
catch (Exception ex)

View File

@ -65,6 +65,27 @@ namespace LibationWinForms
if (this.DesignMode)
return;
string message =
@"Whats funny is how the alt-right completely misses the point with Rome.
Whats funny though is that Rome was actually quite diverse. Sure the power came from Italy but without Egypt, Spain, North Africa, and Gaul it's unlikely Rome would have been the power they are.
Romes great strength was its diversity. The fact they could work with countless cultures without prejudice allowed them to maintain such a massive Empire in the first place. They would adopt foreign gods and foreign cultures with ease and it allowed them to distill the best pieces of the Mediterranean world for themselves.
In the final years of the Western Roman Empire, there was this sudden focus on ethnic make up. Where Rome had once accepted all cultures and assimilated them they refused to do so with the new Germanic migrants like the Goths, Vandals, Burgundians, and Franks.
The Goths in particular just wanted a seat at the table. They were willing to fight for Rome and defend the borders. The 2 greatest generals of the final decades- Stilicho and Aetius- were both half barbarian themselves.
In previous periods of collapse, Rome would find ethnically new emperors to help turn the tide. In the third century crisis, the Illyrian Empires (Aurelian, Probus, Diocletian) rose to the challenge and restored the Empire fully. In the tumultuous collapse of the Flavian dynasty, the Spanish Emporers (Trajan, Hadrian) would lead Rome to its peak of power.
Had Rome accepted the Goths, assimilated them and treated them fairly, and brought them into the Empire they may have survived. Great men like Stilicho would have become Emperor and maybe they could have restored the Empire.
Instead, Rome chose to keep them at arm's length and forced them into desperation within turn led to the Goths sacking Rome.
Put simply the Rome that accepted all peoples regardless of race was the Rome of Trajan and glory- the Rome that demanded ethnic purity was the Rome of Honorius and collapse.";
System.Windows.Forms.MessageBox.Show("funny", "Caption", MessageBoxButtons.CancelTryContinue, MessageBoxIcon.Warning);
// I'm leaving this empty call here as a reminder that if we use this, it should probably be after DesignMode check
}
}

View File

@ -357,7 +357,9 @@ namespace LibationWinForms.GridView
{
var column = gridEntryDataGridView.Columns
.Cast<DataGridViewColumn>()
.Single(c => c.DataPropertyName == itemName);
.SingleOrDefault(c => c.DataPropertyName == itemName);
if (column is null) continue;
column.DisplayIndex = displayIndices.GetValueOrDefault(itemName, column.Index);
}

View File

@ -41,7 +41,7 @@ namespace LibationWinForms
//Otherwise we just ignore all the Avalonia app build stuff and continue with winforms.
//For debug purposes, always run AvaloniaUI.
if (true)// (startupTask.Result.useBeta)
if (true) //(startupTask.Result.useBeta)
{
await Task.WhenAll(appBuilderTask, classicLifetimeTask, startupTask);