@ -5,10 +5,13 @@
using System ;
using System.Collections.Generic ;
using System.Reactive.Disposables ;
using System.Reactive.Linq ;
using System.Threading.Tasks ;
using Avalonia.Layout ;
using Avalonia.Logging ;
using Avalonia.Media ;
using Avalonia.Reactive ;
using Avalonia.Threading ;
using Avalonia.VisualTree ;
@ -345,7 +348,6 @@ namespace Avalonia.Controls
////}
}
// Register action to go back to how things were before where any child can be the anchor.
// Register action to go back to how things were before where any child can be the anchor. Here,
// WinUI uses CompositionTarget.Rendering but we don't currently have that, so post an action to
// run *after* rendering has completed (priority needs to be lower than Render as Transformed
@ -404,17 +406,12 @@ namespace Avalonia.Controls
_ ensuredScroller = false ;
}
private void OnEffectiveViewportChanged ( TransformedBounds ? bounds )
private void OnEffectiveViewportChanged ( TransformedBounds t b)
{
if ( ! bounds . HasValue )
{
return ;
}
var globalClip = bounds . Value . Clip ;
var globalClip = tb . Clip ;
var transform = _ owner . GetVisualRoot ( ) . TransformToVisual ( _ owner ) . Value ;
var clip = globalClip . TransformToAABB ( transform ) ;
var effectiveViewport = clip . Intersect ( bounds . Value . Bounds ) ;
var effectiveViewport = clip . Intersect ( tb . Bounds ) ;
Logger . TryGet ( LogEventLevel . Verbose ) ? . Log ( "Repeater" , this , "{LayoutId}: EffectiveViewportChanged event callback" , _ owner . Layout . LayoutId ) ;
UpdateViewport ( effectiveViewport ) ;
@ -532,12 +529,68 @@ namespace Avalonia.Controls
//
// UWP uses the EffectiveViewportChanged event (which I think was implemented specially
// for this case): we need to implement that in Avalonia.
return control . GetObservable ( Visual . TransformedBoundsProperty )
. Merge ( control . GetObservable ( Visual . BoundsProperty ) . Select ( _ = > control . TransformedBounds ) )
. Skip ( 1 )
return new EffectiveViewportChangedObservable ( control )
. Subscribe ( OnEffectiveViewportChanged ) ;
}
private class EffectiveViewportChangedObservable : SingleSubscriberObservableBase < TransformedBounds > ,
IObserver < TransformedBounds ? > ,
IObserver < Rect >
{
private readonly IControl _ control ;
private IDisposable _ subscription ;
private TransformedBounds ? _l astBounds ;
private bool _ skipBounds ;
public EffectiveViewportChangedObservable ( IControl control ) = > _ control = control ;
void IObserver < TransformedBounds ? > . OnNext ( TransformedBounds ? value )
{
_l astBounds = value ;
if ( value ! = null )
{
PublishNext ( value . Value ) ;
}
}
void IObserver < Rect > . OnNext ( Rect value )
{
if ( _l astBounds . HasValue )
{
if ( ! _ skipBounds )
{
PublishNext ( new TransformedBounds (
new Rect ( value . Size ) ,
_l astBounds . Value . Clip ,
_l astBounds . Value . Transform ) ) ;
}
_ skipBounds = false ;
}
}
protected override void Subscribed ( )
{
_ subscription = new CompositeDisposable (
_ control . GetObservable ( Visual . TransformedBoundsProperty ) . Subscribe ( this ) ,
_ control . GetObservable ( Visual . BoundsProperty ) . Subscribe ( this ) ) ;
_l astBounds = null ;
_ skipBounds = true ;
}
protected override void Unsubscribed ( )
{
_ subscription . Dispose ( ) ;
_ subscription = null ;
}
void IObserver < TransformedBounds ? > . OnCompleted ( ) { }
void IObserver < TransformedBounds ? > . OnError ( Exception error ) { }
void IObserver < Rect > . OnCompleted ( ) { }
void IObserver < Rect > . OnError ( Exception error ) { }
}
private class ScrollerInfo
{
public ScrollerInfo ( ScrollViewer scroller )