From 4dcfd1c4e3366d2e21d8944f3bc6fddc7de8b4f7 Mon Sep 17 00:00:00 2001 From: maj00r Date: Wed, 11 Nov 2026 01:50:40 +0100 Subject: [PATCH] fix(blackbox): the timeline's labels on a narrow timeline, marks out of view, the cab on a short window - The hover label and the clock bubble keep to the left edge on a narrow timeline instead of throwing in Render. - A mark is told under the pointer only when it is drawn: within the plot and the time shown. - The device groups are clipped at their own width, not 4 px short. - On a short window the cab card scrolls, so the list above it keeps room for a few rows. --- Eu07.BlackBox.Views/BlackBoxWindow.cs | 4 +++- Eu07.BlackBox.Views/CabPanel.cs | 2 +- Eu07.BlackBox.Views/TimelineView.cs | 9 ++++++--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Eu07.BlackBox.Views/BlackBoxWindow.cs b/Eu07.BlackBox.Views/BlackBoxWindow.cs index 076376a..1ba8362 100644 --- a/Eu07.BlackBox.Views/BlackBoxWindow.cs +++ b/Eu07.BlackBox.Views/BlackBoxWindow.cs @@ -174,9 +174,11 @@ public sealed class BlackBoxWindow : Window DockPanel.SetDock(_tabs, Dock.Top); side.Children.Add(_tabs); side.Children.Add(new Panel { Children = { _events, _timetableScroll, _summaryScroll } }); - var cabCard = UiKit.Group(_strings["Cab"], _cab); + var cabCard = UiKit.Group(_strings["Cab"], new ScrollViewer { Content = _cab, HorizontalScrollBarVisibility = Avalonia.Controls.Primitives.ScrollBarVisibility.Disabled }); cabCard.Margin = new Thickness(0, UiKit.Gap, 0, 0); var sideColumn = new DockPanel(); + // On a short window the cab scrolls, so the list above keeps room for a few rows. + sideColumn.SizeChanged += (_, e) => cabCard.MaxHeight = Math.Max(160, e.NewSize.Height - 200); DockPanel.SetDock(cabCard, Dock.Bottom); sideColumn.Children.Add(cabCard); sideColumn.Children.Add(UiKit.Frame(side)); diff --git a/Eu07.BlackBox.Views/CabPanel.cs b/Eu07.BlackBox.Views/CabPanel.cs index 2f65eeb..26c365c 100644 --- a/Eu07.BlackBox.Views/CabPanel.cs +++ b/Eu07.BlackBox.Views/CabPanel.cs @@ -163,7 +163,7 @@ public sealed class CabPanel : Control for (int g = 0; g < groups.Length; g++) { double groupWidth = Math.Max(20, widths[g] + spare); - using (context.PushClip(new Rect(x, top, groupWidth - 4, size.Height - top))) + using (context.PushClip(new Rect(x, top, groupWidth, size.Height - top))) { context.DrawText(MapView.Text(Strings[groups[g].Title], Palette.DimText, 10, FontWeight.SemiBold), new Point(x, top)); double y = top + 16; diff --git a/Eu07.BlackBox.Views/TimelineView.cs b/Eu07.BlackBox.Views/TimelineView.cs index 3a9c435..6105c5a 100644 --- a/Eu07.BlackBox.Views/TimelineView.cs +++ b/Eu07.BlackBox.Views/TimelineView.cs @@ -127,7 +127,7 @@ public sealed class TimelineView : Control context.DrawLine(new Pen(Palette.Cursor, 1.5), new Point(cursor, Top - 6), new Point(cursor, size.Height - AxisHeight)); // The moment played, on the axis. var clock = MapView.Text(recording.ClockAt(_time).ToString(@"hh\:mm\:ss", CultureInfo.InvariantCulture), Palette.Cursor, 10, FontWeight.SemiBold); - var bubble = new Rect(Math.Clamp(cursor - clock.Width / 2 - 5, Left, size.Width - Right - clock.Width - 10), size.Height - AxisHeight + 2, + var bubble = new Rect(Math.Max(Left, Math.Min(cursor - clock.Width / 2 - 5, size.Width - Right - clock.Width - 10)), size.Height - AxisHeight + 2, clock.Width + 10, clock.Height + 2); context.DrawRectangle(Palette.Card, new Pen(Palette.Cursor, 1), bubble); context.DrawText(clock, new Point(bubble.X + 5, bubble.Y + 1)); @@ -477,13 +477,16 @@ public sealed class TimelineView : Control double marks = chartBottom + 6 + Bands * (BandHeight + BandGap); bool inPlates = pointer.Y >= Top - 16 && pointer.Y <= Top - 2; bool inMarks = pointer.Y >= marks - 2 && pointer.Y <= marks + MarksHeight + 2; - if (!inPlates && !inMarks) + if (!inPlates && !inMarks || pointer.X < Left || pointer.X > Left + PlotWidth) return null; + double end = _start + PlotWidth * _secondsPerPixel; var culture = CultureInfo.CurrentCulture; string? found = null; double best = 5; void Consider(double time, Func text) { + if (time < _start || time > end) + return; double d = Math.Abs(X(time) - pointer.X); if (d < best) { @@ -533,7 +536,7 @@ public sealed class TimelineView : Control if (_pointer is not { } pointer) return; var label = MapView.Text(text, Palette.Text, 11); - double x = Math.Clamp(pointer.X + 10, Left, size.Width - Right - label.Width - 12); + double x = Math.Max(Left, Math.Min(pointer.X + 10, size.Width - Right - label.Width - 12)); double y = Math.Max(2, pointer.Y - label.Height - 12); var box = new Rect(x, y, label.Width + 12, label.Height + 6); context.DrawRectangle(Palette.Card, new Pen(Palette.CardBorder, 1), box, 3, 3);