更新
This commit is contained in:
@@ -280,22 +280,7 @@ public sealed class RealtimeForceChart : FrameworkElement
|
||||
|
||||
private static int ResolveXAxisDivisions(double plotWidth)
|
||||
{
|
||||
if (plotWidth >= 700)
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
if (plotWidth >= 520)
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
if (plotWidth >= 360)
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
return 4;
|
||||
return Math.Clamp((int)Math.Ceiling(plotWidth / 110), 4, 240);
|
||||
}
|
||||
|
||||
private void DrawCenteredText(
|
||||
|
||||
@@ -251,21 +251,31 @@
|
||||
<RowDefinition Height="300" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<controls:RealtimeForceChart x:Name="RealtimeForceChart"
|
||||
Grid.Row="0"
|
||||
Margin="0,0,0,8"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Samples="{Binding RealtimeForceSamples}"
|
||||
PeakLineSamples="{Binding RealtimePeakLineSamples}"
|
||||
AverageLineSamples="{Binding RealtimeAverageLineSamples}"
|
||||
CurrentPointSamples="{Binding RealtimeCurrentPointSamples}"
|
||||
XMax="{Binding RealtimeChartXMax}"
|
||||
YMax="{Binding RealtimeChartYMax}"
|
||||
TravelMm="{Binding Recipe.TravelMm}"
|
||||
SledMassGrams="{Binding Recipe.SledMassGrams}"
|
||||
Loaded="RealtimeForceChart_Loaded"
|
||||
SizeChanged="RealtimeForceChart_SizeChanged" />
|
||||
<ScrollViewer x:Name="RealtimeChartScrollViewer"
|
||||
Grid.Row="0"
|
||||
Margin="0,0,0,8"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
VerticalScrollBarVisibility="Disabled"
|
||||
CanContentScroll="False"
|
||||
Loaded="RealtimeChartScrollViewer_Loaded"
|
||||
ScrollChanged="RealtimeChartScrollViewer_ScrollChanged">
|
||||
<controls:RealtimeForceChart x:Name="RealtimeForceChart"
|
||||
Width="{Binding RealtimeChartCanvasWidth}"
|
||||
MinWidth="{Binding ViewportWidth, ElementName=RealtimeChartScrollViewer}"
|
||||
Height="{Binding ViewportHeight, ElementName=RealtimeChartScrollViewer}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Stretch"
|
||||
Samples="{Binding RealtimeForceSamples}"
|
||||
PeakLineSamples="{Binding RealtimePeakLineSamples}"
|
||||
AverageLineSamples="{Binding RealtimeAverageLineSamples}"
|
||||
CurrentPointSamples="{Binding RealtimeCurrentPointSamples}"
|
||||
XMax="{Binding RealtimeChartXMax}"
|
||||
YMax="{Binding RealtimeChartYMax}"
|
||||
TravelMm="{Binding Recipe.TravelMm}"
|
||||
SledMassGrams="{Binding Recipe.SledMassGrams}"
|
||||
Loaded="RealtimeForceChart_Loaded"
|
||||
SizeChanged="RealtimeForceChart_SizeChanged" />
|
||||
</ScrollViewer>
|
||||
|
||||
<Border Grid.Row="1" Style="{StaticResource PanelBorderStyle}" Padding="10" Margin="0,0,0,8">
|
||||
<Grid>
|
||||
|
||||
@@ -15,6 +15,7 @@ public partial class MainWindow : Window
|
||||
private readonly MainViewModel _viewModel = new();
|
||||
private readonly DispatcherTimer _realtimeChartRenderTimer;
|
||||
private bool _isRealtimeChartLayoutRefreshQueued;
|
||||
private bool _isRealtimeChartAutoScrollPinned = true;
|
||||
private DateTime _realtimeChartRenderUntilUtc = DateTime.MinValue;
|
||||
|
||||
public MainWindow()
|
||||
@@ -73,6 +74,30 @@ public partial class MainWindow : Window
|
||||
RequestRealtimeChartRender(RealtimeChartStartupRenderPulseDuration);
|
||||
}
|
||||
|
||||
private void RealtimeChartScrollViewer_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_isRealtimeChartAutoScrollPinned = true;
|
||||
RequestRealtimeChartRender(RealtimeChartStartupRenderPulseDuration);
|
||||
}
|
||||
|
||||
private void RealtimeChartScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
|
||||
{
|
||||
if (e.ExtentWidthChange < -1)
|
||||
{
|
||||
_isRealtimeChartAutoScrollPinned = true;
|
||||
ScrollRealtimeChartToEndIfPinned();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Math.Abs(e.ExtentWidthChange) > 0 || Math.Abs(e.ViewportWidthChange) > 0)
|
||||
{
|
||||
ScrollRealtimeChartToEndIfPinned();
|
||||
return;
|
||||
}
|
||||
|
||||
_isRealtimeChartAutoScrollPinned = IsRealtimeChartScrolledToEnd();
|
||||
}
|
||||
|
||||
private void RealtimeForceChart_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
if (e.NewSize.Width <= 0 || e.NewSize.Height <= 0)
|
||||
@@ -196,5 +221,29 @@ public partial class MainWindow : Window
|
||||
RealtimeForceChart.InvalidateArrange();
|
||||
RealtimeForceChart.InvalidateVisual();
|
||||
RealtimeForceChart.UpdateLayout();
|
||||
RealtimeChartScrollViewer.UpdateLayout();
|
||||
ScrollRealtimeChartToEndIfPinned();
|
||||
}
|
||||
|
||||
private bool IsRealtimeChartScrolledToEnd()
|
||||
{
|
||||
const double tolerance = 8;
|
||||
return RealtimeChartScrollViewer.HorizontalOffset >= RealtimeChartScrollViewer.ScrollableWidth - tolerance;
|
||||
}
|
||||
|
||||
private void ScrollRealtimeChartToEndIfPinned()
|
||||
{
|
||||
if (!_isRealtimeChartAutoScrollPinned)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (RealtimeChartScrollViewer.ScrollableWidth <= 0)
|
||||
{
|
||||
RealtimeChartScrollViewer.ScrollToHorizontalOffset(0);
|
||||
return;
|
||||
}
|
||||
|
||||
RealtimeChartScrollViewer.ScrollToHorizontalOffset(RealtimeChartScrollViewer.ScrollableWidth);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,8 @@ public sealed class MainViewModel : ObservableObject, IDisposable
|
||||
private static readonly TimeSpan RealtimeChartRefreshInterval = TimeSpan.FromMilliseconds(250);
|
||||
private const double RealtimeChartTimeStepSeconds = 0.05;
|
||||
private const double RealtimeChartXAxisPaddingSeconds = 1;
|
||||
private const double RealtimeChartMinimumCanvasWidth = 900;
|
||||
private const double RealtimeChartPixelsPerSecond = 18;
|
||||
private const double MinimumEmptyChartXAxisMaxLimit = 1;
|
||||
private const double EmptyChartYAxisMaxLimit = 0.5;
|
||||
private const double EmptyChartPointForceN = 0.001;
|
||||
@@ -308,6 +310,8 @@ public sealed class MainViewModel : ObservableObject, IDisposable
|
||||
|
||||
public double RealtimeChartXMax => _lastForceXAxisMaxLimit;
|
||||
|
||||
public double RealtimeChartCanvasWidth => Math.Max(RealtimeChartMinimumCanvasWidth, _lastForceXAxisMaxLimit * RealtimeChartPixelsPerSecond);
|
||||
|
||||
public double RealtimeChartYMax => _lastForceYAxisMaxLimit;
|
||||
|
||||
public RelayCommand StartCommand => _startCommand;
|
||||
@@ -1306,6 +1310,7 @@ public sealed class MainViewModel : ObservableObject, IDisposable
|
||||
OnPropertyChanged(nameof(ForceXAxes));
|
||||
OnPropertyChanged(nameof(ForceYAxes));
|
||||
OnPropertyChanged(nameof(RealtimeChartXMax));
|
||||
OnPropertyChanged(nameof(RealtimeChartCanvasWidth));
|
||||
OnPropertyChanged(nameof(RealtimeChartYMax));
|
||||
}
|
||||
}
|
||||
@@ -1319,6 +1324,7 @@ public sealed class MainViewModel : ObservableObject, IDisposable
|
||||
OnPropertyChanged(nameof(ForceXAxes));
|
||||
OnPropertyChanged(nameof(ForceYAxes));
|
||||
OnPropertyChanged(nameof(RealtimeChartXMax));
|
||||
OnPropertyChanged(nameof(RealtimeChartCanvasWidth));
|
||||
OnPropertyChanged(nameof(RealtimeChartYMax));
|
||||
NotifyRealtimeChartChanged();
|
||||
}
|
||||
|
||||
BIN
COFTester/摩擦仪.jpg
Normal file
BIN
COFTester/摩擦仪.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 293 KiB |
Reference in New Issue
Block a user