mirror of
https://github.com/unclshura/splitter.git
synced 2026-06-22 00:22:01 +00:00
Back/Forward buttons fixed
This commit is contained in:
parent
f412db219f
commit
2058ae0f7e
@ -1,5 +1,6 @@
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
@ -68,14 +69,15 @@ public class TimelinePreviewSlider : Control, IDisposable
|
|||||||
private readonly object _cacheLock = new();
|
private readonly object _cacheLock = new();
|
||||||
|
|
||||||
private IDisposable? _segmentsSubscription;
|
private IDisposable? _segmentsSubscription;
|
||||||
|
private bool _isInternalSliderUpdate;
|
||||||
|
private JobViewModel? _currentVm;
|
||||||
|
|
||||||
// Interaction state
|
// Interaction state
|
||||||
private bool _isPointerCaptured;
|
private bool _isPointerCaptured;
|
||||||
private Point _lastPointerPoint;
|
private Point _lastPointerPoint;
|
||||||
private double _lastPointerXForDrag; // used to compute delta for segment drag
|
private DragMode _dragMode = DragMode.None;
|
||||||
private DragMode _dragMode = DragMode.None;
|
private int _activeSegmentIndex = -1;
|
||||||
private int _activeSegmentIndex = -1;
|
private bool _isSplitModifierActive;
|
||||||
private bool _isSplitModifierActive;
|
|
||||||
|
|
||||||
// Throttle invalidation during drag
|
// Throttle invalidation during drag
|
||||||
private DateTime _lastInvalidate = DateTime.MinValue;
|
private DateTime _lastInvalidate = DateTime.MinValue;
|
||||||
@ -83,17 +85,17 @@ public class TimelinePreviewSlider : Control, IDisposable
|
|||||||
|
|
||||||
public TimelinePreviewSlider()
|
public TimelinePreviewSlider()
|
||||||
{
|
{
|
||||||
Focusable = true;
|
Focusable = true;
|
||||||
Height = _timelineHeight;
|
Height = _timelineHeight;
|
||||||
ClipToBounds = true;
|
ClipToBounds = true;
|
||||||
|
|
||||||
// Use property change override instead of GetObservable.Subscribe to avoid IObserver compile issues.
|
// Use property change override instead of GetObservable.Subscribe to avoid IObserver compile issues.
|
||||||
PointerPressed += OnPointerPressed;
|
PointerPressed += OnPointerPressed;
|
||||||
PointerMoved += OnPointerMoved;
|
PointerMoved += OnPointerMoved;
|
||||||
PointerReleased += OnPointerReleased;
|
PointerReleased += OnPointerReleased;
|
||||||
PointerCaptureLost += OnPointerCaptureLost;
|
PointerCaptureLost += OnPointerCaptureLost;
|
||||||
KeyDown += OnKeyDown;
|
KeyDown += OnKeyDown;
|
||||||
KeyUp += OnKeyUp;
|
KeyUp += OnKeyUp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override to detect ViewModel property changes
|
// Override to detect ViewModel property changes
|
||||||
@ -116,11 +118,24 @@ public class TimelinePreviewSlider : Control, IDisposable
|
|||||||
if (vm != null)
|
if (vm != null)
|
||||||
{
|
{
|
||||||
_segmentsSubscription = SubscribeToSegments(vm.Segments);
|
_segmentsSubscription = SubscribeToSegments(vm.Segments);
|
||||||
|
vm.PropertyChanged += OnVmPropertyChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
InvalidateVisual();
|
InvalidateVisual();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void OnVmPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.PropertyName == nameof(JobViewModel.SliderLiveValue))
|
||||||
|
{
|
||||||
|
if (_isInternalSliderUpdate)
|
||||||
|
return;
|
||||||
|
|
||||||
|
InvalidateVisual();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private IDisposable SubscribeToSegments(ObservableCollection<Segment> segments)
|
private IDisposable SubscribeToSegments(ObservableCollection<Segment> segments)
|
||||||
{
|
{
|
||||||
NotifyCollectionChangedEventHandler handler = (s, e) =>
|
NotifyCollectionChangedEventHandler handler = (s, e) =>
|
||||||
@ -135,6 +150,11 @@ public class TimelinePreviewSlider : Control, IDisposable
|
|||||||
|
|
||||||
private void UnsubscribeFromViewModel()
|
private void UnsubscribeFromViewModel()
|
||||||
{
|
{
|
||||||
|
if (_currentVm != null)
|
||||||
|
_currentVm.PropertyChanged -= OnVmPropertyChanged;
|
||||||
|
|
||||||
|
_currentVm = null;
|
||||||
|
|
||||||
_segmentsSubscription?.Dispose();
|
_segmentsSubscription?.Dispose();
|
||||||
_segmentsSubscription = null;
|
_segmentsSubscription = null;
|
||||||
}
|
}
|
||||||
@ -519,7 +539,6 @@ public class TimelinePreviewSlider : Control, IDisposable
|
|||||||
|
|
||||||
var p = e.GetPosition(this);
|
var p = e.GetPosition(this);
|
||||||
_lastPointerPoint = p;
|
_lastPointerPoint = p;
|
||||||
_lastPointerXForDrag = p.X;
|
|
||||||
_isSplitModifierActive = e.KeyModifiers.HasFlag(KeyModifiers.Control);
|
_isSplitModifierActive = e.KeyModifiers.HasFlag(KeyModifiers.Control);
|
||||||
|
|
||||||
var hit = HitTestAtPoint(p);
|
var hit = HitTestAtPoint(p);
|
||||||
@ -576,7 +595,9 @@ public class TimelinePreviewSlider : Control, IDisposable
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_isInternalSliderUpdate = true;
|
||||||
vm.SliderLiveValue = sec;
|
vm.SliderLiveValue = sec;
|
||||||
|
_isInternalSliderUpdate = false;
|
||||||
|
|
||||||
ThrottledInvalidate();
|
ThrottledInvalidate();
|
||||||
_lastPointerPoint = p;
|
_lastPointerPoint = p;
|
||||||
@ -665,7 +686,6 @@ public class TimelinePreviewSlider : Control, IDisposable
|
|||||||
_dragMode = mode;
|
_dragMode = mode;
|
||||||
_activeSegmentIndex = segmentIndex;
|
_activeSegmentIndex = segmentIndex;
|
||||||
_lastPointerPoint = e.GetPosition(this);
|
_lastPointerPoint = e.GetPosition(this);
|
||||||
_lastPointerXForDrag = _lastPointerPoint.X;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThrottledInvalidate()
|
private void ThrottledInvalidate()
|
||||||
@ -681,10 +701,16 @@ public class TimelinePreviewSlider : Control, IDisposable
|
|||||||
private void SetPlayheadFromPoint(Point p)
|
private void SetPlayheadFromPoint(Point p)
|
||||||
{
|
{
|
||||||
var vm = ViewModel;
|
var vm = ViewModel;
|
||||||
if (vm == null) return;
|
if (vm == null)
|
||||||
var sec = PixelToSeconds(p.X);
|
return;
|
||||||
|
|
||||||
|
double sec = PixelToSeconds(p.X);
|
||||||
sec = Math.Max(0, Math.Min(vm.DurationSeconds, sec));
|
sec = Math.Max(0, Math.Min(vm.DurationSeconds, sec));
|
||||||
|
|
||||||
|
_isInternalSliderUpdate = true;
|
||||||
vm.SliderLiveValue = sec;
|
vm.SliderLiveValue = sec;
|
||||||
|
_isInternalSliderUpdate = false;
|
||||||
|
|
||||||
InvalidateVisual();
|
InvalidateVisual();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -462,26 +462,48 @@ public partial class JobViewModel : ObservableObject
|
|||||||
|
|
||||||
private void StepForward()
|
private void StepForward()
|
||||||
{
|
{
|
||||||
if (DurationSeconds <= 0)
|
if (Segments.Count <= 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var duration = SegmentDuration;
|
var current = GetCurrentSegment();
|
||||||
var segment = Math.Round(SliderLiveValue / duration, MidpointRounding.ToZero)+1;
|
if ( current < 0 || current >= Segments.Count - 1 )
|
||||||
|
return;
|
||||||
|
|
||||||
SliderLiveValue = Math.Min(DurationSeconds - duration, segment * duration);
|
SliderLiveValue = Segments[current + 1].Start;
|
||||||
// trigger seek in your playback pipeline here
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StepBackward()
|
private void StepBackward()
|
||||||
{
|
{
|
||||||
if (DurationSeconds <= 0)
|
if (Segments.Count <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var duration = SegmentDuration;
|
var current = GetCurrentSegment();
|
||||||
var segment = Math.Max(0, Math.Round(SliderLiveValue / duration, MidpointRounding.ToZero)-1);
|
if (current <= 0)
|
||||||
|
{
|
||||||
|
SliderLiveValue = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SliderLiveValue = segment * duration;
|
if (SliderLiveValue > Segments[current].Start)
|
||||||
// trigger seek in your playback pipeline here
|
SliderLiveValue = Segments[current].Start;
|
||||||
|
else
|
||||||
|
SliderLiveValue = Segments[current - 1].Start;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetCurrentSegment()
|
||||||
|
{
|
||||||
|
double pos = SliderLiveValue;
|
||||||
|
|
||||||
|
for (int i = 0; i < Segments.Count; i++)
|
||||||
|
{
|
||||||
|
var s = Segments[i];
|
||||||
|
if (pos < s.Start)
|
||||||
|
return i - 1;
|
||||||
|
if (pos == s.Start)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void OnSliderLiveValueChanged(double value)
|
partial void OnSliderLiveValueChanged(double value)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user