Skip to content

Commit

Permalink
Added support to override URL clicks in PopupViewer
Browse files Browse the repository at this point in the history
  • Loading branch information
prathameshnarkhede committed Jul 16, 2024
1 parent ae34e71 commit 7d6cf97
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 17 deletions.
45 changes: 44 additions & 1 deletion src/Toolkit/Toolkit/UI/Controls/PopupViewer/PopupViewer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,29 @@ internal bool OnPopupAttachmentClicked(PopupAttachment attachment)
if (handler is not null)
{
var args = new PopupAttachmentClickedEventArgs(attachment);
PopupAttachmentClicked?.Invoke(this, args);
handler.Invoke(this, args);
return args.Handled;
}
return false;
}

/// <summary>
/// Raised when a link is clicked
/// </summary>
/// <remarks>
/// <para>By default, when an link is clicked, the default application (Browser) for the file type (if any) is launched. To override this,
/// listen to this event, set the <see cref="HyperLinkClickedEventArgs.Handled"/> property to <c>true</c> and perform
/// your own logic. </para>
/// </remarks>
public event EventHandler<HyperLinkClickedEventArgs>? HyperLinkClicked;

internal bool OnHyperLinkClicked(Uri uri)
{
var handler = HyperLinkClicked;
if (handler is not null)
{
var args = new HyperLinkClickedEventArgs(uri);
handler.Invoke(this, args);
return args.Handled;
}
return false;
Expand All @@ -271,5 +293,26 @@ internal PopupAttachmentClickedEventArgs(PopupAttachment attachment)
/// </summary>
public PopupAttachment Attachment { get; }
}

/// <summary>
/// Event argument for the <see cref="PopupViewer.HyperLinkClicked"/> event.
/// </summary>
public class HyperLinkClickedEventArgs : EventArgs
{
internal HyperLinkClickedEventArgs(Uri uri)
{
Uri = uri;
}

/// <summary>
/// Gets or sets a value indicating whether the event handler has handled the event and the default action should be prevented.
/// </summary>
public bool Handled { get; set; }

/// <summary>
/// Gets the URI that was clicked.
/// </summary>
public Uri Uri { get; }
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ private void OnElementPropertyChanged()
}
}

private static IEnumerable<View> VisitChildren(MarkupNode parent)
private IEnumerable<View> VisitChildren(MarkupNode parent)
{
// Create views for all the children of a given node.
// Nodes with blocks are converted individually, but consecutive inline-only nodes are grouped into labels.
Expand Down Expand Up @@ -116,7 +116,7 @@ private static IEnumerable<View> VisitChildren(MarkupNode parent)
}
}

private static View CreateBlock(MarkupNode node)
private View CreateBlock(MarkupNode node)
{
// Create a view for a single block node.
switch (node.Type)
Expand Down Expand Up @@ -218,7 +218,7 @@ static View VerticallyAlignTableCell(MarkupNode node, View cellContent)
}
}

private static Label CreateFormattedText(IEnumerable<MarkupNode> nodes)
private Label CreateFormattedText(IEnumerable<MarkupNode> nodes)
{
// Flattens given tree of inline nodes into a single label.
var str = new FormattedString();
Expand All @@ -232,7 +232,7 @@ private static Label CreateFormattedText(IEnumerable<MarkupNode> nodes)
return new Label { FormattedText = str, LineBreakMode = LineBreakMode.WordWrap };
}

private static IEnumerable<Span> VisitInline(MarkupNode node)
private IEnumerable<Span> VisitInline(MarkupNode node)
{
// Converts a single inline node into a sequence of spans.
// The whole tree is expected to only contain inline nodes. Other nodes are handled by VisitBlock.
Expand All @@ -245,11 +245,7 @@ private static IEnumerable<Span> VisitInline(MarkupNode node)
var tapRecognizer = new TapGestureRecognizer();
tapRecognizer.Tapped += (s, e) =>
{
try
{
Browser.OpenAsync(node.Content, BrowserLaunchMode.SystemPreferred);
}
catch { }
OnHyperlinkClicked(linkUri);
};
foreach (var subNode in node.Children)
{
Expand Down Expand Up @@ -298,7 +294,7 @@ private static IEnumerable<Span> VisitInline(MarkupNode node)
}
}

private static Grid ConvertTableToGrid(MarkupNode table)
private Grid ConvertTableToGrid(MarkupNode table)
{
// Determines the dimensions of a grid necessary to hold a given table.
// Utilizes a dynamically-sized 2D bitmap (`gridMap`) to mark occupied cells while iterating over the table.
Expand Down Expand Up @@ -455,6 +451,16 @@ private static bool MapsToBlock(MarkupNode node)
{
return node.Type is MarkupType.List or MarkupType.Table or MarkupType.Block or MarkupType.Divider or MarkupType.Image;
}

private PopupViewer? GetPopupViewerParent()
{
var parent = this.Parent;
while (parent is not null && parent is not PopupViewer popup)
{
parent = parent.Parent;
}
return parent as PopupViewer;
}
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#if WPF
using Esri.ArcGISRuntime.Mapping.Popups;
using Esri.ArcGISRuntime.Toolkit.Internal;
using Esri.ArcGISRuntime.Toolkit.UI.Controls;
using Esri.ArcGISRuntime.UI;
using System.Windows.Documents;
using System.Windows.Input;
Expand Down Expand Up @@ -57,7 +58,7 @@ private void OnElementPropertyChanged()
}
}

private static IEnumerable<Block> VisitAndAddBlocks(IEnumerable<MarkupNode> nodes)
private IEnumerable<Block> VisitAndAddBlocks(IEnumerable<MarkupNode> nodes)
{
Paragraph? inlineHolder = null;
foreach (var node in nodes)
Expand All @@ -81,7 +82,7 @@ private static IEnumerable<Block> VisitAndAddBlocks(IEnumerable<MarkupNode> node
yield return inlineHolder;
}

private static IEnumerable<Inline> VisitAndAddInlines(IEnumerable<MarkupNode> nodes)
private IEnumerable<Inline> VisitAndAddInlines(IEnumerable<MarkupNode> nodes)
{
foreach (var node in nodes)
{
Expand All @@ -96,7 +97,7 @@ private static IEnumerable<Inline> VisitAndAddInlines(IEnumerable<MarkupNode> no
}
}

private static Block VisitBlock(MarkupNode node)
private Block VisitBlock(MarkupNode node)
{
switch (node.Type)
{
Expand Down Expand Up @@ -176,7 +177,7 @@ private static Block VisitBlock(MarkupNode node)
}
}

private static Inline VisitInline(MarkupNode node)
private Inline VisitInline(MarkupNode node)
{
switch (node.Type)
{
Expand Down Expand Up @@ -287,9 +288,19 @@ private static System.Windows.Media.Color ConvertColor(System.Drawing.Color colo
_ => TextAlignment.Left,
};

private static async void NavigateToUri(object sender, RequestNavigateEventArgs ea)
private void NavigateToUri(object sender, RequestNavigateEventArgs ea)
{
await Launcher.LaunchUriAsync(ea.Uri);
OnHyperlinkClicked(ea.Uri);
}

private PopupViewer? GetPopupViewerParent()
{
var parent = VisualTreeHelper.GetParent(this);
while (parent is not null and not PopupViewer)
{
parent = VisualTreeHelper.GetParent(parent);
}
return parent as PopupViewer;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@
using Esri.ArcGISRuntime.Toolkit.Internal;
using Esri.ArcGISRuntime.UI;
#if WPF
using Esri.ArcGISRuntime.Toolkit.UI.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Navigation;
#elif MAUI
using Esri.ArcGISRuntime.Toolkit.Maui;
using Microsoft.Maui.ApplicationModel;
#endif


Expand Down Expand Up @@ -70,6 +74,41 @@ public TextPopupElement? Element
/// </summary>
public static readonly DependencyProperty ElementProperty =
PropertyHelper.CreateProperty<TextPopupElement, TextPopupElementView>(nameof(Element), null, (s, oldValue, newValue) => s.OnElementPropertyChanged());

/// <summary>
/// Occurs when an URL is clicked.
/// </summary>
/// <remarks>
/// <para>Override this to prevent the default open action.</para>
/// </remarks>
/// <param name="uri">Clicked URL</param>
public virtual async void OnHyperlinkClicked(Uri uri)
{
if (uri is not null)
{
var viewer = GetPopupViewerParent();
if (viewer is not null)
{
var handled = viewer.OnHyperLinkClicked(uri);
if (handled)
return;
}

try
{
#if WPF
await Launcher.LaunchUriAsync(uri);
#elif MAUI
await Browser.OpenAsync(uri, BrowserLaunchMode.SystemPreferred);
#endif
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine($"Failed to open URL: " + ex.Message);
}
}

}
}
}
#endif

0 comments on commit 7d6cf97

Please sign in to comment.