Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Avalonia;
using Avalonia.Controls;
using Jc.PopupView.Avalonia.Controls;
using Jc.PopupView.Avalonia.Sample.Views.Sheets;
using Jc.PopupView.Avalonia.Services;
using ReactiveUI;

Expand All @@ -10,49 +11,61 @@ namespace Jc.PopupView.Avalonia.Sample.ViewModels;
public class MainViewModel : ViewModelBase
{
private bool _isSheet1Open;

public bool IsSheet1Open
{
get => _isSheet1Open;
set => this.RaiseAndSetIfChanged(ref _isSheet1Open, value);
}

public ICommand OpenSheet1Command { get; }

private bool _isSheet2Open;

public bool IsSheet2Open
{
get => _isSheet2Open;
set => this.RaiseAndSetIfChanged(ref _isSheet2Open, value);
}

public ICommand OpenSheet2Command { get; }

public ICommand OpenSheet3Command { get; }


public ICommand OpenSheet4Command { get; }

public ICommand OpenNativeSheet1Command { get; }

private bool _isToast1Open;

public bool IsToast1Open
{
get => _isToast1Open;
set => this.RaiseAndSetIfChanged(ref _isToast1Open, value);
}

public ICommand OpenToast1Command { get; }

private bool _isToast2Open;

public bool IsToast2Open
{
get => _isToast2Open;
set => this.RaiseAndSetIfChanged(ref _isToast2Open, value);
}

public ICommand OpenToast2Command { get; }

private bool _isToast3Open;

public bool IsToast3Open
{
get => _isToast3Open;
set => this.RaiseAndSetIfChanged(ref _isToast3Open, value);
}

public ICommand OpenToast3Command { get; }

public ICommand OpenToast4Command { get; }

private bool _isFloater1Open;
Expand Down Expand Up @@ -83,13 +96,18 @@ public MainViewModel()
{
OpenSheet1Command = ReactiveCommand.Create(() => IsSheet1Open = true);
OpenSheet2Command = ReactiveCommand.Create(() => IsSheet2Open = true);
OpenSheet3Command = ReactiveCommand.Create(() => new DialogService().OpenSheet(new TextBlock { Text = "Hello, from dynamic dialog!" }));
OpenSheet3Command = ReactiveCommand.Create(() =>
new DialogService().OpenSheet(new TextBlock { Text = "Hello, from dynamic dialog!" }));
OpenSheet4Command = ReactiveCommand.Create(() => new DialogService().OpenSheet(new InteractiveSheet()));
OpenNativeSheet1Command = ReactiveCommand.Create(() =>
Native.BottomSheetService.Current?.ShowBottomSheet(new TextBlock { Text = "Hello, from native bottom sheet!" }));
Native.BottomSheetService.Current?.ShowBottomSheet(new Sheet1()));
OpenToast1Command = ReactiveCommand.Create(() => IsToast1Open = true);
OpenToast2Command = ReactiveCommand.Create(() => IsToast2Open = true);
OpenToast3Command = ReactiveCommand.Create(() => IsToast3Open = true);
OpenToast4Command = ReactiveCommand.Create(() => new DialogService().OpenToast(new TextBlock { Text = "Hello, from dynamic dialog!", Padding = new Thickness(10)}, toast => toast.Location = ToastLocation.Bottom));
OpenToast4Command = ReactiveCommand.Create(() =>
new DialogService().OpenToast(
new TextBlock { Text = "Hello, from dynamic dialog!", Padding = new Thickness(10) },
toast => toast.Location = ToastLocation.Bottom));
OpenFloater1Command = ReactiveCommand.Create(() => IsFloater1Open = true);
OpenFloater2Command = ReactiveCommand.Create(() => IsFloater2Open = true);
OpenFloater3Command = ReactiveCommand.Create(() => IsFloater3Open = true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,28 @@
</Grid>
</Grid>
</Button>
<!-- Interactive Sheet -->
<Button Classes="panel" Command="{Binding OpenSheet4Command}">
<Button.Transitions>
<Transitions>
<DoubleTransition Property="Opacity" Duration="0:0:0.3"></DoubleTransition>
</Transitions>
</Button.Transitions>
<Grid ColumnSpacing="20" RowSpacing="10" ColumnDefinitions="Auto, *">
<Border Grid.Column="0" Classes="icon">
<Grid RowDefinitions="*, Auto">
<Border HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Height="40"
CornerRadius="5 5 10 10" />
</Grid>
</Border>
<Grid Grid.Column="1" RowDefinitions="Auto, Auto" ColumnDefinitions="*"
VerticalAlignment="Center">
<TextBlock Grid.Row="0" Classes="h2" Text="Action sheet 4" />
<TextBlock Grid.Row="1" Classes="p"
Text="Action sheet with interactive controls." />
</Grid>
</Grid>
</Button>
<TextBlock Classes="h1">Native Action sheets</TextBlock>
<!-- Pill Internal Sheet -->
<Button Classes="panel" Command="{Binding OpenNativeSheet1Command}">
Expand Down Expand Up @@ -272,7 +294,7 @@
</StackPanel>
</ScrollViewer>
<popup:DialogHost.Sheets>
<popup:Sheet IsOpen="{Binding IsSheet1Open}" ClickOutsideToDismiss="True" ShowBackgroundMask="False">
<popup:Sheet IsOpen="{Binding IsSheet1Open}" ClickOutsideToDismiss="True">
<sheets:Sheet1 />
</popup:Sheet>
<popup:Sheet IsOpen="{Binding IsSheet2Open}" PillLocation="External">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Jc.PopupView.Avalonia.Sample.Views.Sheets.InteractiveSheet">
<StackPanel Orientation="Vertical" Spacing="20">
<TextBox Watermark="Enter some text" />
<ListBox>
<ListBoxItem Content="Item 1" />
<ListBoxItem Content="Item 2" />
<ListBoxItem Content="Item 3" />
<ListBoxItem Content="Item 4" />
<ListBoxItem Content="Item 5" />
</ListBox>
<ComboBox>
<ComboBoxItem Content="Item 1" />
<ComboBoxItem Content="Item 2" />
<ComboBoxItem Content="Item 3" />
<ComboBoxItem Content="Item 4" />
<ComboBoxItem Content="Item 5" />
</ComboBox>
</StackPanel>
</UserControl>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;

namespace Jc.PopupView.Avalonia.Sample.Views.Sheets;

public partial class InteractiveSheet : UserControl
{
public InteractiveSheet()
{
InitializeComponent();
}
}
53 changes: 39 additions & 14 deletions src/Jc.PopupView.Avalonia/Behaviors/ScrollableDialogDragBehavior.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Media;
Expand All @@ -12,7 +13,7 @@

internal sealed class ScrollableDialogDragBehavior : Behavior<Grid>
{
private IDialog _dialog;

Check warning on line 16 in src/Jc.PopupView.Avalonia/Behaviors/ScrollableDialogDragBehavior.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable field '_dialog' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
private bool _isDragging;
private Point _dragStart;
private Point _lastDrag;
Expand Down Expand Up @@ -93,23 +94,47 @@
return;
}

if (e.GetCurrentPoint(AssociatedObject).Properties.IsLeftButtonPressed)
if (!e.GetCurrentPoint(AssociatedObject).Properties.IsLeftButtonPressed)
{
_isDragging = true;
_dragStart = e.GetPosition(AssociatedObject);
_lastDrag = _dragStart;
e.Pointer.Capture(AssociatedObject);
return;
}

if (AssociatedObject is { } grid)
{
grid.AddHandler(InputElement.PointerReleasedEvent, GridOnPointerReleased, handledEventsToo: true,
routes: RoutingStrategies.Tunnel);
grid.AddHandler(InputElement.PointerMovedEvent, GridOnPointerMoved, handledEventsToo: true,
routes: RoutingStrategies.Tunnel);
grid.AddHandler(InputElement.PointerCaptureLostEvent, GridOnPointerCaptureLost, handledEventsToo: true,
routes: RoutingStrategies.Tunnel);
}
if (IsInteractiveControl(e.Source as Visual))
{
// Let the underlying control handle the event if it's an interactive control
return;
}

_isDragging = true;
_dragStart = e.GetPosition(AssociatedObject);
_lastDrag = _dragStart;
e.Pointer.Capture(AssociatedObject);

if (AssociatedObject is { } grid)
{
grid.AddHandler(InputElement.PointerReleasedEvent, GridOnPointerReleased, handledEventsToo: false,
routes: RoutingStrategies.Tunnel);
grid.AddHandler(InputElement.PointerMovedEvent, GridOnPointerMoved, handledEventsToo: false,
routes: RoutingStrategies.Tunnel);
grid.AddHandler(InputElement.PointerCaptureLostEvent, GridOnPointerCaptureLost, handledEventsToo: false,
routes: RoutingStrategies.Tunnel);
}
}

private static bool IsInteractiveControl(Visual? visual)
{
while (visual is not null)
{
if (visual is InputElement { Focusable: true })
return true;

// Add explicit checks for controls where Focusable might be false by default
if (visual is ListBoxItem or ComboBoxItem)
return true;

visual = visual.GetVisualParent();
}
return false;
}

private void GridOnPointerReleased(object? sender, PointerReleasedEventArgs e)
Expand Down
3 changes: 2 additions & 1 deletion src/Jc.PopupView.Avalonia/Controls/Sheet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,12 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
_sheetPart = e.NameScope.Find<Grid>("PART_Sheet");
_maskPart = e.NameScope.Find<Rectangle>("PART_SheetMask");

_maskPart?.AddHandler(PointerPressedEvent, (_, _) =>
_maskPart?.AddHandler(PointerPressedEvent, (_, args) =>
{
if (ClickOutsideToDismiss)
{
IsOpen = false;
args.Handled = true;
}
});
}
Expand Down
Loading