Browse Source

Merge pull request #4595 from amwx/master

Fix SplitView pane auto close to work with popups
pull/4598/head
danwalmsley 6 years ago
committed by GitHub
parent
commit
c5b42fc68d
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      samples/ControlCatalog/Pages/SplitViewPage.xaml
  2. 62
      src/Avalonia.Controls/SplitView.cs

10
samples/ControlCatalog/Pages/SplitViewPage.xaml

@ -58,12 +58,18 @@
<SplitView.Pane>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Text="PANE CONTENT" FontWeight="Bold" Name="PaneHeader" Margin="5,12,0,0" />
<ListBoxItem Grid.Row="1" VerticalAlignment="Top" Margin="0 10">
<ComboBox Width="150" Grid.Row="1">
<ComboBoxItem Content="Item1"/>
<ComboBoxItem Content="Item2"/>
<ComboBoxItem Content="Item3"/>
</ComboBox>
<ListBoxItem Grid.Row="2" VerticalAlignment="Top" Margin="0 10">
<StackPanel Orientation="Horizontal">
<!--Path glyph from materialdesignicons.com-->
<Border Width="48">
@ -76,7 +82,7 @@
<TextBlock Text="People" VerticalAlignment="Center" />
</StackPanel>
</ListBoxItem>
<TextBlock Grid.Row="2" Text="Item at bottom" Margin="60,12" />
<TextBlock Grid.Row="3" Text="Item at bottom" Margin="60,12" />
</Grid>
</SplitView.Pane>

62
src/Avalonia.Controls/SplitView.cs

@ -145,7 +145,7 @@ namespace Avalonia.Controls
private bool _isPaneOpen;
private Panel _pane;
private CompositeDisposable _pointerDisposables;
private IDisposable _pointerDisposable;
public SplitView()
{
@ -320,37 +320,14 @@ namespace Avalonia.Controls
var topLevel = this.VisualRoot;
if (topLevel is Window window)
{
//Logic adapted from Popup
//Basically if we're using an overlay DisplayMode, close the pane if we don't click on the pane
IDisposable subscribeToEventHandler<T, TEventHandler>(T target, TEventHandler handler,
Action<T, TEventHandler> subscribe, Action<T, TEventHandler> unsubscribe)
{
subscribe(target, handler);
return Disposable.Create((unsubscribe, target, handler), state => state.unsubscribe(state.target, state.handler));
}
_pointerDisposables = new CompositeDisposable(
window.AddDisposableHandler(PointerPressedEvent, PointerPressedOutside, RoutingStrategies.Tunnel),
InputManager.Instance?.Process.Subscribe(OnNonClientClick),
subscribeToEventHandler<Window, EventHandler>(window, Window_Deactivated,
(x, handler) => x.Deactivated += handler, (x, handler) => x.Deactivated -= handler),
subscribeToEventHandler<IWindowImpl, Action>(window.PlatformImpl, OnWindowLostFocus,
(x, handler) => x.LostFocus += handler, (x, handler) => x.LostFocus -= handler));
_pointerDisposable = window.AddDisposableHandler(PointerPressedEvent, PointerPressedOutside, RoutingStrategies.Tunnel);
}
}
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnDetachedFromVisualTree(e);
_pointerDisposables?.Dispose();
}
private void OnWindowLostFocus()
{
if (IsPaneOpen && ShouldClosePane())
{
IsPaneOpen = false;
}
_pointerDisposable?.Dispose();
}
private void PointerPressedOutside(object sender, PointerPressedEventArgs e)
@ -371,7 +348,12 @@ namespace Avalonia.Controls
var src = e.Source as IVisual;
while (src != null)
{
if (src == _pane)
// Make assumption that if Popup is in visual tree,
// owning control is within pane
// This works because if pane is triggered to close
// when clicked anywhere else in Window, the pane
// would close before the popup is opened
if (src == _pane || src is PopupRoot)
{
closePane = false;
break;
@ -385,31 +367,7 @@ namespace Avalonia.Controls
e.Handled = true;
}
}
private void OnNonClientClick(RawInputEventArgs obj)
{
if (!IsPaneOpen)
{
return;
}
var mouse = obj as RawPointerEventArgs;
if (mouse?.Type == RawPointerEventType.NonClientLeftButtonDown)
{
if (ShouldClosePane())
IsPaneOpen = false;
}
}
private void Window_Deactivated(object sender, EventArgs e)
{
if (IsPaneOpen && ShouldClosePane())
{
IsPaneOpen = false;
}
}
private bool ShouldClosePane()
{
return (DisplayMode == SplitViewDisplayMode.CompactOverlay || DisplayMode == SplitViewDisplayMode.Overlay);

Loading…
Cancel
Save