Skip to content
79 changes: 20 additions & 59 deletions src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.ComponentModel;
using CommunityToolkit.Maui.Extensions;

namespace CommunityToolkit.Maui.Views;
Expand All @@ -7,31 +8,6 @@ namespace CommunityToolkit.Maui.Views;
/// </summary>
public partial class Popup : ContentView
{
/// <summary>
/// Bindable property to set the margin between the <see cref="Popup"/> and the edge of the window
/// </summary>
public static new readonly BindableProperty MarginProperty = View.MarginProperty;

/// <summary>
/// Bindable property to set the padding between the <see cref="Popup"/> border and the <see cref="Popup"/> content
/// </summary>
public static new readonly BindableProperty PaddingProperty = ContentView.PaddingProperty;

/// <summary>
/// Bindable property to set the horizontal position of the <see cref="Popup"/> when displayed on screen
/// </summary>
public static new readonly BindableProperty HorizontalOptionsProperty = View.HorizontalOptionsProperty;

/// <summary>
/// Bindable property to set the vertical position of the <see cref="Popup"/> when displayed on screen
/// </summary>
public static new readonly BindableProperty VerticalOptionsProperty = View.VerticalOptionsProperty;

/// <summary>
/// Backing BindableProperty for the <see cref="CanBeDismissedByTappingOutsideOfPopup"/> property.
/// </summary>
public static readonly BindableProperty CanBeDismissedByTappingOutsideOfPopupProperty = BindableProperty.Create(nameof(CanBeDismissedByTappingOutsideOfPopup), typeof(bool), typeof(Popup), Options.DefaultPopupSettings.CanBeDismissedByTappingOutsideOfPopup);

/// <summary>
/// Initializes Popup
/// </summary>
Expand All @@ -55,51 +31,34 @@ public Popup()
public event EventHandler? Closed;

/// <summary>
/// Sets the margin between the <see cref="Popup"/> and the edge of the window
/// Gets or sets the margin between the <see cref="Popup"/> and the edge of the window.
/// </summary>
public new Thickness Margin
{
get => base.Margin;
set => base.Margin = value;
}
[BindableProperty]
public new partial Thickness Margin { get; set; } = Options.DefaultPopupSettings.Margin;

/// <summary>
/// Sets the padding between the <see cref="Popup"/> border and the <see cref="Popup"/> content
/// Gets or sets the padding between the <see cref="Popup"/> border and the <see cref="Popup"/> content.
/// </summary>
public new Thickness Padding
{
get => base.Padding;
set => base.Padding = value;
}
[BindableProperty]
public new partial Thickness Padding { get; set; } = Options.DefaultPopupSettings.Padding;

/// <summary>
/// Sets the horizontal position of the <see cref="Popup"/> when displayed on screen
/// Gets or sets the horizontal layout options used to position the <see cref="Popup"/> when displayed on screen.
/// </summary>
public new LayoutOptions HorizontalOptions
{
get => base.HorizontalOptions;
set => base.HorizontalOptions = value;
}
[BindableProperty]
public new partial LayoutOptions HorizontalOptions { get; set; } = Options.DefaultPopupSettings.HorizontalOptions;

/// <summary>
/// Sets the vertical position of the <see cref="Popup"/> when displayed on screen
/// Gets or sets the vertical layout options used to position the <see cref="Popup"/> when displayed on screen.
/// </summary>
public new LayoutOptions VerticalOptions
{
get => base.VerticalOptions;
set => base.VerticalOptions = value;
}
[BindableProperty]
public new partial LayoutOptions VerticalOptions { get; set; } = Options.DefaultPopupSettings.VerticalOptions;

/// <inheritdoc cref="IPopupOptions.CanBeDismissedByTappingOutsideOfPopup"/> />
/// <remarks>
/// When true and the user taps outside the popup, it will dismiss.
/// On Android - when false the hardware back button is disabled.
/// </remarks>
public bool CanBeDismissedByTappingOutsideOfPopup
{
get => (bool)GetValue(CanBeDismissedByTappingOutsideOfPopupProperty);
set => SetValue(CanBeDismissedByTappingOutsideOfPopupProperty, value);
}
/// <summary>
/// Gets or sets a value indicating whether the <see cref="Popup"/> can be dismissed by tapping outside the popup.
/// </summary>
[BindableProperty]
public partial bool CanBeDismissedByTappingOutsideOfPopup { get; set; } = Options.DefaultPopupSettings.CanBeDismissedByTappingOutsideOfPopup;

/// <summary>
/// Close the Popup.
Expand Down Expand Up @@ -148,5 +107,7 @@ public partial class Popup<T> : Popup
}

sealed class PopupNotFoundException() : InvalidPopupOperationException($"Unable to close popup: could not locate {nameof(PopupPage)}. {nameof(PopupExtensions.ShowPopup)} or {nameof(PopupExtensions.ShowPopupAsync)} must be called before {nameof(Popup.CloseAsync)}. If using a custom implementation of {nameof(Popup)}, override the {nameof(Popup.CloseAsync)} method");

sealed class PopupBlockedException(in Page currentVisibleModalPage) : InvalidPopupOperationException($"Unable to close Popup because it is blocked by the Modal Page {currentVisibleModalPage.GetType().FullName}. Please call `{nameof(Page.Navigation)}.{nameof(Page.Navigation.PopModalAsync)}()` to first remove {currentVisibleModalPage.GetType().FullName} from the {nameof(Page.Navigation.ModalStack)}");

class InvalidPopupOperationException(in string message) : InvalidOperationException(message);
73 changes: 22 additions & 51 deletions src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,71 +8,42 @@ namespace CommunityToolkit.Maui;
public partial class PopupOptions : BindableObject, IPopupOptions
{
/// <summary>
/// Backing BindableProperty for the <see cref="CanBeDismissedByTappingOutsideOfPopup"/> property.
/// An empty instance of <see cref="IPopupOptions"/> containing default values.
/// </summary>
public static readonly BindableProperty CanBeDismissedByTappingOutsideOfPopupProperty = BindableProperty.Create(nameof(CanBeDismissedByTappingOutsideOfPopup), typeof(bool), typeof(PopupOptions), Options.DefaultPopupOptionsSettings.CanBeDismissedByTappingOutsideOfPopup);
public static IPopupOptions Empty { get; } = new PopupOptions();

/// <summary>
/// Backing BindableProperty for the <see cref="OnTappingOutsideOfPopup"/> property.
/// Gets or sets a value indicating whether the popup can be dismissed by tapping outside the popup.
/// Default is provided by <see cref="Options.DefaultPopupOptionsSettings"/>.
/// </summary>
public static readonly BindableProperty OnTappingOutsideOfPopupProperty = BindableProperty.Create(nameof(OnTappingOutsideOfPopup), typeof(Action), typeof(PopupOptions), Options.DefaultPopupOptionsSettings.OnTappingOutsideOfPopup);
[BindableProperty]
public partial bool CanBeDismissedByTappingOutsideOfPopup { get; set; } = Options.DefaultPopupOptionsSettings.CanBeDismissedByTappingOutsideOfPopup;

/// <summary>
/// Backing BindableProperty for the <see cref="PageOverlayColor"/> property.
/// Gets or sets an <see cref="Action"/> invoked when the user taps outside the popup.
/// Default is provided by <see cref="Options.DefaultPopupOptionsSettings"/>.
/// </summary>
public static readonly BindableProperty PageOverlayColorProperty = BindableProperty.Create(nameof(PageOverlayColor), typeof(Color), typeof(PopupOptions), Options.DefaultPopupOptionsSettings.PageOverlayColor);
[BindableProperty]
public partial Action? OnTappingOutsideOfPopup { get; set; } = Options.DefaultPopupOptionsSettings.OnTappingOutsideOfPopup;

/// <summary>
/// Backing BindableProperty for the <see cref="Shape"/> property.
/// Gets or sets the overlay <see cref="Color"/> applied to the page while the popup is displayed.
/// Default is provided by <see cref="Options.DefaultPopupOptionsSettings"/>.
/// </summary>
public static readonly BindableProperty ShapeProperty = BindableProperty.Create(nameof(Shape), typeof(Shape), typeof(PopupOptions), Options.DefaultPopupOptionsSettings.Shape);
[BindableProperty]
public partial Color PageOverlayColor { get; set; } = Options.DefaultPopupOptionsSettings.PageOverlayColor;

/// <summary>
/// Backing BindableProperty for the <see cref="Shadow"/> property.
/// Gets or sets the <see cref="Shape"/> used to render the popup's outline.
/// Default is provided by <see cref="Options.DefaultPopupOptionsSettings"/>.
/// </summary>
public static readonly BindableProperty ShadowProperty = BindableProperty.Create(nameof(Shadow), typeof(Shadow), typeof(PopupOptions), Options.DefaultPopupOptionsSettings.Shadow);
[BindableProperty]
public partial Shape? Shape { get; set; } = Options.DefaultPopupOptionsSettings.Shape;

/// <summary>
/// An empty instance of <see cref="IPopupOptions"/> containing default values.
/// Gets or sets the <see cref="Shadow"/> applied to the popup.
/// Default is provided by <see cref="Options.DefaultPopupOptionsSettings"/>.
/// </summary>
public static IPopupOptions Empty { get; } = new PopupOptions();

/// <inheritdoc/>
/// <remarks>
/// When true and the user taps outside the popup, it will dismiss.
/// On Android - when false the hardware back button is disabled.
/// </remarks>
public bool CanBeDismissedByTappingOutsideOfPopup
{
get => (bool)GetValue(CanBeDismissedByTappingOutsideOfPopupProperty);
set => SetValue(CanBeDismissedByTappingOutsideOfPopupProperty, value);
}

/// <inheritdoc/>
public Color PageOverlayColor
{
get => (Color)GetValue(PageOverlayColorProperty);
set => SetValue(PageOverlayColorProperty, value);
}

/// <inheritdoc/>
public Action? OnTappingOutsideOfPopup
{
get => (Action?)GetValue(OnTappingOutsideOfPopupProperty);
set => SetValue(OnTappingOutsideOfPopupProperty, value);
}

/// <inheritdoc/>
public Shape? Shape
{
get => (Shape?)GetValue(ShapeProperty);
set => SetValue(ShapeProperty, value);
}

/// <inheritdoc/>
public Shadow? Shadow
{
get => (Shadow?)GetValue(ShadowProperty);
set => SetValue(ShadowProperty, value);
}
[BindableProperty]
public partial Shadow? Shadow { get; set; } = Options.DefaultPopupOptionsSettings.Shadow;
}
Loading