Browse Source

Fix SplitView pane to work with popups

pull/4595/head
amwx 6 years ago
parent
commit
cf0ea3581a
  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> <SplitView.Pane>
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="*" /> <RowDefinition Height="*" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBlock Text="PANE CONTENT" FontWeight="Bold" Name="PaneHeader" Margin="5,12,0,0" /> <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"> <StackPanel Orientation="Horizontal">
<!--Path glyph from materialdesignicons.com--> <!--Path glyph from materialdesignicons.com-->
<Border Width="48"> <Border Width="48">
@ -76,7 +82,7 @@
<TextBlock Text="People" VerticalAlignment="Center" /> <TextBlock Text="People" VerticalAlignment="Center" />
</StackPanel> </StackPanel>
</ListBoxItem> </ListBoxItem>
<TextBlock Grid.Row="2" Text="Item at bottom" Margin="60,12" /> <TextBlock Grid.Row="3" Text="Item at bottom" Margin="60,12" />
</Grid> </Grid>
</SplitView.Pane> </SplitView.Pane>

62
src/Avalonia.Controls/SplitView.cs

@ -145,7 +145,7 @@ namespace Avalonia.Controls
private bool _isPaneOpen; private bool _isPaneOpen;
private Panel _pane; private Panel _pane;
private CompositeDisposable _pointerDisposables; private IDisposable _pointerDisposable;
public SplitView() public SplitView()
{ {
@ -320,37 +320,14 @@ namespace Avalonia.Controls
var topLevel = this.VisualRoot; var topLevel = this.VisualRoot;
if (topLevel is Window window) if (topLevel is Window window)
{ {
//Logic adapted from Popup _pointerDisposable = window.AddDisposableHandler(PointerPressedEvent, PointerPressedOutside, RoutingStrategies.Tunnel);
//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));
} }
} }
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{ {
base.OnDetachedFromVisualTree(e); base.OnDetachedFromVisualTree(e);
_pointerDisposables?.Dispose(); _pointerDisposable?.Dispose();
}
private void OnWindowLostFocus()
{
if (IsPaneOpen && ShouldClosePane())
{
IsPaneOpen = false;
}
} }
private void PointerPressedOutside(object sender, PointerPressedEventArgs e) private void PointerPressedOutside(object sender, PointerPressedEventArgs e)
@ -371,7 +348,12 @@ namespace Avalonia.Controls
var src = e.Source as IVisual; var src = e.Source as IVisual;
while (src != null) 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; closePane = false;
break; break;
@ -385,31 +367,7 @@ namespace Avalonia.Controls
e.Handled = true; 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() private bool ShouldClosePane()
{ {
return (DisplayMode == SplitViewDisplayMode.CompactOverlay || DisplayMode == SplitViewDisplayMode.Overlay); return (DisplayMode == SplitViewDisplayMode.CompactOverlay || DisplayMode == SplitViewDisplayMode.Overlay);

Loading…
Cancel
Save