Zoom the text of the log, check, available and bandmap windows
Ctrl+wheel and Ctrl+plus / Ctrl+minus change the text size of the window in front, and Ctrl+0 puts it back. Each size is kept in the settings file. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -63,6 +63,14 @@ public sealed record Settings
|
|||||||
/// The height of the callsigns on the bandmap, in points.
|
/// The height of the callsigns on the bandmap, in points.
|
||||||
public int BandmapTextSize { get; init; } = 12;
|
public int BandmapTextSize { get; init; } = 12;
|
||||||
|
|
||||||
|
/// The text size of the log, check and available windows, in points. Ctrl
|
||||||
|
/// with the mouse wheel or plus and minus changes the one in front.
|
||||||
|
public int LogFontSize { get; init; } = 12;
|
||||||
|
|
||||||
|
public int CheckFontSize { get; init; } = 14;
|
||||||
|
|
||||||
|
public int AvailableFontSize { get; init; } = 13;
|
||||||
|
|
||||||
/// Moves each incoming CW spot by a few tens of hertz, so the operator has
|
/// Moves each incoming CW spot by a few tens of hertz, so the operator has
|
||||||
/// to find the station by ear. N1MM calls it randomising.
|
/// to find the station by ear. N1MM calls it randomising.
|
||||||
public bool RandomizeSpots { get; init; }
|
public bool RandomizeSpots { get; init; }
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Nonemm.App.Configuration;
|
||||||
using Nonemm.App.Theming;
|
using Nonemm.App.Theming;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
@@ -23,6 +24,11 @@ public sealed partial class AvailableWindow : RefreshableWindow
|
|||||||
this.session = session;
|
this.session = session;
|
||||||
this.tune = tune;
|
this.tune = tune;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
_ = new FontZoom(this, new Settings().AvailableFontSize, () => session.Settings.AvailableFontSize, size =>
|
||||||
|
{
|
||||||
|
session.Save(session.Settings with { AvailableFontSize = size });
|
||||||
|
Refresh();
|
||||||
|
});
|
||||||
MultsOnlyBox.IsCheckedChanged += (_, _) => Refresh();
|
MultsOnlyBox.IsCheckedChanged += (_, _) => Refresh();
|
||||||
session.Bandmap.Changed += (_, _) => Dispatcher.UIThread.Post(Refresh);
|
session.Bandmap.Changed += (_, _) => Dispatcher.UIThread.Post(Refresh);
|
||||||
Refresh();
|
Refresh();
|
||||||
@@ -70,7 +76,7 @@ public sealed partial class AvailableWindow : RefreshableWindow
|
|||||||
panel.Children.Add(new TextBlock
|
panel.Children.Add(new TextBlock
|
||||||
{
|
{
|
||||||
Text = $"{band.Name} {stations.Count}",
|
Text = $"{band.Name} {stations.Count}",
|
||||||
FontSize = 11,
|
FontSize = session.Settings.AvailableFontSize - 2,
|
||||||
Opacity = 0.7,
|
Opacity = 0.7,
|
||||||
Margin = new Avalonia.Thickness(0, 0, 0, 4),
|
Margin = new Avalonia.Thickness(0, 0, 0, 4),
|
||||||
});
|
});
|
||||||
@@ -87,7 +93,7 @@ public sealed partial class AvailableWindow : RefreshableWindow
|
|||||||
{
|
{
|
||||||
Text = Label(station),
|
Text = Label(station),
|
||||||
FontFamily = Fonts.Mono,
|
FontFamily = Fonts.Mono,
|
||||||
FontSize = 13,
|
FontSize = session.Settings.AvailableFontSize,
|
||||||
Foreground = Verdicts.Colour(station.Verdict),
|
Foreground = Verdicts.Colour(station.Verdict),
|
||||||
HorizontalAlignment = HorizontalAlignment.Left,
|
HorizontalAlignment = HorizontalAlignment.Left,
|
||||||
Cursor = new Cursor(StandardCursorType.Hand),
|
Cursor = new Cursor(StandardCursorType.Hand),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Nonemm.App.Configuration;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using Nonemm.Contests;
|
using Nonemm.Contests;
|
||||||
@@ -25,9 +26,6 @@ public sealed partial class BandmapWindow : RefreshableWindow
|
|||||||
("whole band", Frequency.Zero),
|
("whole band", Frequency.Zero),
|
||||||
];
|
];
|
||||||
|
|
||||||
private const int MinTextSize = 8;
|
|
||||||
private const int MaxTextSize = 24;
|
|
||||||
|
|
||||||
private readonly AppSession session;
|
private readonly AppSession session;
|
||||||
private readonly Action<Frequency, string> tune;
|
private readonly Action<Frequency, string> tune;
|
||||||
|
|
||||||
@@ -46,6 +44,11 @@ public sealed partial class BandmapWindow : RefreshableWindow
|
|||||||
Array.FindIndex(Spans, s => s.Span.Hertz == session.Settings.BandmapSpanHertz));
|
Array.FindIndex(Spans, s => s.Span.Hertz == session.Settings.BandmapSpanHertz));
|
||||||
CentreBox.IsChecked = session.Settings.BandmapCentred;
|
CentreBox.IsChecked = session.Settings.BandmapCentred;
|
||||||
View.TextSize = session.Settings.BandmapTextSize;
|
View.TextSize = session.Settings.BandmapTextSize;
|
||||||
|
_ = new FontZoom(this, new Settings().BandmapTextSize, () => (int)View.TextSize, size =>
|
||||||
|
{
|
||||||
|
View.TextSize = size;
|
||||||
|
SaveView();
|
||||||
|
});
|
||||||
SmallerButton.Click += (_, _) => ResizeText(-1);
|
SmallerButton.Click += (_, _) => ResizeText(-1);
|
||||||
LargerButton.Click += (_, _) => ResizeText(1);
|
LargerButton.Click += (_, _) => ResizeText(1);
|
||||||
SpanBox.SelectionChanged += (_, _) => SaveView();
|
SpanBox.SelectionChanged += (_, _) => SaveView();
|
||||||
@@ -60,7 +63,7 @@ public sealed partial class BandmapWindow : RefreshableWindow
|
|||||||
|
|
||||||
private void ResizeText(int by)
|
private void ResizeText(int by)
|
||||||
{
|
{
|
||||||
View.TextSize = Math.Clamp(View.TextSize + by, MinTextSize, MaxTextSize);
|
View.TextSize = Math.Clamp(View.TextSize + by, FontZoom.Smallest, FontZoom.Largest);
|
||||||
SaveView();
|
SaveView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Nonemm.App.Configuration;
|
||||||
using Nonemm.App.Theming;
|
using Nonemm.App.Theming;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Layout;
|
using Avalonia.Layout;
|
||||||
@@ -17,6 +18,11 @@ public sealed partial class CheckWindow : RefreshableWindow
|
|||||||
{
|
{
|
||||||
this.session = session;
|
this.session = session;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
_ = new FontZoom(this, new Settings().CheckFontSize, () => session.Settings.CheckFontSize, size =>
|
||||||
|
{
|
||||||
|
session.Save(session.Settings with { CheckFontSize = size });
|
||||||
|
Refresh();
|
||||||
|
});
|
||||||
Refresh();
|
Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,19 +43,19 @@ public sealed partial class CheckWindow : RefreshableWindow
|
|||||||
int at = 0;
|
int at = 0;
|
||||||
foreach (CheckColumn column in columns)
|
foreach (CheckColumn column in columns)
|
||||||
{
|
{
|
||||||
Control panel = BuildColumn(column);
|
Control panel = BuildColumn(column, session.Settings.CheckFontSize);
|
||||||
Grid.SetColumn(panel, at++);
|
Grid.SetColumn(panel, at++);
|
||||||
Columns.Children.Add(panel);
|
Columns.Children.Add(panel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Control BuildColumn(CheckColumn column)
|
private static Control BuildColumn(CheckColumn column, int fontSize)
|
||||||
{
|
{
|
||||||
StackPanel panel = new() { Margin = new Avalonia.Thickness(0, 0, 8, 0) };
|
StackPanel panel = new() { Margin = new Avalonia.Thickness(0, 0, 8, 0) };
|
||||||
panel.Children.Add(new TextBlock
|
panel.Children.Add(new TextBlock
|
||||||
{
|
{
|
||||||
Text = $"{Heading(column.Source)} {Count(column)}",
|
Text = $"{Heading(column.Source)} {Count(column)}",
|
||||||
FontSize = 11,
|
FontSize = fontSize - 3,
|
||||||
Opacity = 0.7,
|
Opacity = 0.7,
|
||||||
Margin = new Avalonia.Thickness(0, 0, 0, 4),
|
Margin = new Avalonia.Thickness(0, 0, 0, 4),
|
||||||
});
|
});
|
||||||
@@ -59,7 +65,7 @@ public sealed partial class CheckWindow : RefreshableWindow
|
|||||||
{
|
{
|
||||||
Text = candidate.Text,
|
Text = candidate.Text,
|
||||||
FontFamily = Fonts.Mono,
|
FontFamily = Fonts.Mono,
|
||||||
FontSize = 14,
|
FontSize = fontSize,
|
||||||
Foreground = Verdicts.Colour(candidate.Verdict),
|
Foreground = Verdicts.Colour(candidate.Verdict),
|
||||||
HorizontalAlignment = HorizontalAlignment.Left,
|
HorizontalAlignment = HorizontalAlignment.Left,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
using Avalonia.Input;
|
||||||
|
using Avalonia.Interactivity;
|
||||||
|
|
||||||
|
namespace Nonemm.App.Windows;
|
||||||
|
|
||||||
|
/// Ctrl+wheel and Ctrl+plus / Ctrl+minus on a window change the size of its
|
||||||
|
/// text, and Ctrl+0 puts it back to `normal`. The handlers run before the controls inside get the event, so a grid
|
||||||
|
/// or a scroll viewer does not take the wheel first.
|
||||||
|
public sealed class FontZoom
|
||||||
|
{
|
||||||
|
public const int Smallest = 8;
|
||||||
|
public const int Largest = 32;
|
||||||
|
|
||||||
|
private readonly int normal;
|
||||||
|
private readonly Func<int> size;
|
||||||
|
private readonly Action<int> apply;
|
||||||
|
|
||||||
|
public FontZoom(InputElement target, int normal, Func<int> size, Action<int> apply)
|
||||||
|
{
|
||||||
|
this.normal = normal;
|
||||||
|
this.size = size;
|
||||||
|
this.apply = apply;
|
||||||
|
target.AddHandler(InputElement.PointerWheelChangedEvent, OnWheel, RoutingStrategies.Tunnel);
|
||||||
|
target.AddHandler(InputElement.KeyDownEvent, OnKeyDown, RoutingStrategies.Tunnel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnWheel(object? sender, PointerWheelEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.KeyModifiers.HasFlag(KeyModifiers.Control) && e.Delta.Y != 0)
|
||||||
|
{
|
||||||
|
Step(e.Delta.Y > 0 ? 1 : -1);
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnKeyDown(object? sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
if (!e.KeyModifiers.HasFlag(KeyModifiers.Control))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.Key is Key.D0 or Key.NumPad0)
|
||||||
|
{
|
||||||
|
Set(normal);
|
||||||
|
e.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int by = e.Key switch
|
||||||
|
{
|
||||||
|
Key.OemPlus or Key.Add => 1,
|
||||||
|
Key.OemMinus or Key.Subtract => -1,
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
if (by != 0)
|
||||||
|
{
|
||||||
|
Step(by);
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Step(int by) => Set(Math.Clamp(size() + by, Smallest, Largest));
|
||||||
|
|
||||||
|
private void Set(int wanted)
|
||||||
|
{
|
||||||
|
if (wanted != size())
|
||||||
|
{
|
||||||
|
apply(wanted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
columns are sized from the width of the text in this font -->
|
columns are sized from the width of the text in this font -->
|
||||||
<Style Selector="DataGridCell TextBlock">
|
<Style Selector="DataGridCell TextBlock">
|
||||||
<Setter Property="FontFamily" Value="{x:Static theming:Fonts.Mono}" />
|
<Setter Property="FontFamily" Value="{x:Static theming:Fonts.Mono}" />
|
||||||
<Setter Property="FontSize" Value="12" />
|
<Setter Property="FontSize" Value="{DynamicResource LogFontSize}" />
|
||||||
<!-- half of what the theme leaves either side of the text, so more
|
<!-- half of what the theme leaves either side of the text, so more
|
||||||
columns fit across the window -->
|
columns fit across the window -->
|
||||||
<Setter Property="Margin" Value="6,0" />
|
<Setter Property="Margin" Value="6,0" />
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
sideways as the box opens -->
|
sideways as the box opens -->
|
||||||
<Style Selector="DataGridCell TextBox">
|
<Style Selector="DataGridCell TextBox">
|
||||||
<Setter Property="FontFamily" Value="{x:Static theming:Fonts.Mono}" />
|
<Setter Property="FontFamily" Value="{x:Static theming:Fonts.Mono}" />
|
||||||
<Setter Property="FontSize" Value="12" />
|
<Setter Property="FontSize" Value="{DynamicResource LogFontSize}" />
|
||||||
<Setter Property="MinHeight" Value="0" />
|
<Setter Property="MinHeight" Value="0" />
|
||||||
<Setter Property="Margin" Value="0" />
|
<Setter Property="Margin" Value="0" />
|
||||||
<Setter Property="Padding" Value="6,0" />
|
<Setter Property="Padding" Value="6,0" />
|
||||||
@@ -53,11 +53,11 @@
|
|||||||
</Style>
|
</Style>
|
||||||
</Grid.Styles>
|
</Grid.Styles>
|
||||||
<DataGrid Name="Rows" Grid.Row="0" GridLinesVisibility="Horizontal" CanUserSortColumns="True"
|
<DataGrid Name="Rows" Grid.Row="0" GridLinesVisibility="Horizontal" CanUserSortColumns="True"
|
||||||
CanUserReorderColumns="True" FontSize="12" FontFamily="{x:Static theming:Fonts.Mono}" />
|
CanUserReorderColumns="True" FontFamily="{x:Static theming:Fonts.Mono}" />
|
||||||
<GridSplitter Grid.Row="1" Height="5" ResizeDirection="Rows" Background="{DynamicResource DataGridGridLinesBrush}" />
|
<GridSplitter Grid.Row="1" Height="5" ResizeDirection="Rows" Background="{DynamicResource DataGridGridLinesBrush}" />
|
||||||
<DataGrid Name="Earlier" Grid.Row="2" IsReadOnly="True" GridLinesVisibility="Horizontal"
|
<DataGrid Name="Earlier" Grid.Row="2" IsReadOnly="True" GridLinesVisibility="Horizontal"
|
||||||
CanUserSortColumns="False" HeadersVisibility="None"
|
CanUserSortColumns="False" HeadersVisibility="None"
|
||||||
FontSize="12" FontFamily="{x:Static theming:Fonts.Mono}" />
|
FontFamily="{x:Static theming:Fonts.Mono}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
</local:RefreshableWindow>
|
</local:RefreshableWindow>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Nonemm.App.Configuration;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Collections;
|
using Avalonia.Collections;
|
||||||
@@ -63,7 +64,25 @@ public sealed partial class LogWindow : RefreshableWindow
|
|||||||
};
|
};
|
||||||
Colour(Rows);
|
Colour(Rows);
|
||||||
Colour(Earlier);
|
Colour(Earlier);
|
||||||
|
ApplyFontSize();
|
||||||
|
_ = new FontZoom(this, new Settings().LogFontSize, () => session.Settings.LogFontSize, size =>
|
||||||
|
{
|
||||||
|
session.Save(session.Settings with { LogFontSize = size });
|
||||||
|
ApplyFontSize();
|
||||||
|
builtFor = "";
|
||||||
Refresh();
|
Refresh();
|
||||||
|
});
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The cells take their size from the `LogFontSize` resource, and the
|
||||||
|
/// grids need it too because the column widths are measured from it.
|
||||||
|
private void ApplyFontSize()
|
||||||
|
{
|
||||||
|
double size = session.Settings.LogFontSize;
|
||||||
|
Resources["LogFontSize"] = size;
|
||||||
|
Rows.FontSize = size;
|
||||||
|
Earlier.FontSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// What the operator picked. The grid raises this for the picks this window
|
/// What the operator picked. The grid raises this for the picks this window
|
||||||
|
|||||||
Reference in New Issue
Block a user