Skip to content

Commit

Permalink
v200.5 (#588)
Browse files Browse the repository at this point in the history
* Set up v.next branch

* WPF/MAUI: FeatureForm attachments support (#581)

* Added missing trimming attribute

* Move code for getting parent to common location

* Add null-check

* Improve app theming and theme testing

* Adds support for the barcode input field (#583)

* Adds support for the barcode input field

* Added support to override URL clicks in PopupViewer (#584)

* Added support to override URL clicks in PopupViewer

* Added samples for reference

* Refactor PopupViewer and event handling

* Refactor hyperlink event handling and cleanup

- Corrected the event name from `HyperLinkClicked` to `HyperlinkClicked` in both XAML and code-behind files for consistency and to meet case sensitivity requirements.

* Refactor GetPopupViewerParent to generic

* Refactor GetParent<T> generic constraint

* Broaden type check in Tapped event handler

* Refine type checks and adjust imports

* Refactor PopupViewer parent traversal logic

* Add discard method to featureform that ensures the form is fully reset by re-evaluating expressions

All add Finish method for consistency

* Improve discards and avoiding cascading evaluations

* Add barcode scanner example to maui sample using ZXing

* Refetch attachment on discard

* Fix null warning

* Add error border below text field (#585)

Ensures on catalyst that the textfield isn't blocked form clicking when there's an error

* BugFix: BasemapGallery fails to load default Basemaps in WPF (#586)

* Optimize BasemapGallery initialization

Removed redundant initialization of `AvailableBasemaps` in the `BasemapGallery` constructor. Added a null check in `BasemapGallery_Loaded` to initialize `AvailableBasemaps` only if it is null, calling `_controller.LoadFromDefaultPortal()` asynchronously if needed. This change prevents unnecessary initialization and allows for external setting of `AvailableBasemaps` before the control is loaded.

* Initialize AvailableBasemaps and improve load check

Add initialization flag for BasemapGallery collection

* Raise hyperlink event for field links

#576

---------

Co-authored-by: Morten Nielsen <[email protected]>
Co-authored-by: Prathamesh Narkhede <[email protected]>
  • Loading branch information
3 people authored Aug 1, 2024
1 parent 5032f25 commit 94dbc05
Show file tree
Hide file tree
Showing 40 changed files with 2,169 additions and 101 deletions.
4 changes: 2 additions & 2 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project>

<PropertyGroup>
<ArcGISRuntimeToolkitPackageVersion Condition="'$(ArcGISRuntimeToolkitPackageVersion)'==''">200.4.0</ArcGISRuntimeToolkitPackageVersion>
<ArcGISRuntimePackageVersion Condition="'$(ArcGISRuntimePackageVersion)'==''">200.4.0</ArcGISRuntimePackageVersion>
<ArcGISRuntimeToolkitPackageVersion Condition="'$(ArcGISRuntimeToolkitPackageVersion)'==''">200.5.0</ArcGISRuntimeToolkitPackageVersion>
<ArcGISRuntimePackageVersion Condition="'$(ArcGISRuntimePackageVersion)'==''">200.5.0</ArcGISRuntimePackageVersion>

<!--Common package properties-->
<Authors>Esri Inc.</Authors>
Expand Down
8 changes: 8 additions & 0 deletions src/Samples/Toolkit.SampleApp.Maui/MainPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Esri.ArcGISRuntime;
using Esri.ArcGISRuntime.Mapping;
using Microsoft.Maui.ApplicationModel;

namespace Toolkit.SampleApp.Maui;

Expand All @@ -8,6 +9,13 @@ public partial class MainPage : ContentPage
public MainPage()
{
InitializeComponent();
ToolbarItems.Add(new ToolbarItem("Toggle Theme", null, () =>
{
if (App.Current!.RequestedTheme == AppTheme.Dark)
App.Current.UserAppTheme = AppTheme.Light;
else
App.Current.UserAppTheme = AppTheme.Dark;
}));
SamplesList.ItemsSource = SampleDatasource.Current.Samples;
CheckAPIKey();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:supportsRtl="true"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<queries>
<intent>
<action android:name="android.media.action.IMAGE_CAPTURE" />
</intent>
</queries>
</manifest>
2 changes: 2 additions & 0 deletions src/Samples/Toolkit.SampleApp.Maui/Platforms/iOS/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,7 @@
</array>
<key>XSAppIconAssets</key>
<string>Assets.xcassets/appicon.appiconset</string>
<key>NSCameraUsageDescription</key>
<string>Adding attachments</string>
</dict>
</plist>
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,21 @@
Map="https://www.arcgis.com/home/item.html?id=f72207ac170a40d8992b7a3507b44fad"
GeoViewTapped="mapView_GeoViewTapped" />

<Border HorizontalOptions="Center" VerticalOptions="Start" Background="#99ffffff" Padding="5" Margin="10" StrokeThickness="1" Stroke="Black">
<Border HorizontalOptions="Center" VerticalOptions="Start" Background="{AppThemeBinding Dark=#99000000, Light=#99ffffff}" Padding="5" Margin="10" StrokeThickness="1" Stroke="Black">
<Label Text="Click a feature to open its FeatureFormView" FontSize="18" />
</Border>

<Border x:Name="SidePanel" IsVisible="False" Grid.Column="1" WidthRequest="300">
<Border Background="{AppThemeBinding Dark=Black, Light=White}">
<Border Background="{AppThemeBinding Dark=#333333, Light=White}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<esri:FeatureFormView Background="Transparent" x:Name="formViewer" Padding="12" Grid.ColumnSpan="2" VerticalScrollBarVisibility="Default"/>
<Border Grid.Row="1" StrokeThickness="0" Padding="5" Background="#eeeeee">
<esri:FeatureFormView Background="Transparent" x:Name="formViewer" Padding="12" Grid.ColumnSpan="2" VerticalScrollBarVisibility="Default"
BarcodeButtonClicked="BarcodeButtonClicked" FormAttachmentClicked="FormAttachmentClicked"
/>
<Border Grid.Row="1" StrokeThickness="0" Padding="5" Background="{AppThemeBinding Dark=Black, Light=White}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Esri.ArcGISRuntime.Data;
using System.Diagnostics;
using Esri.ArcGISRuntime.Data;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Mapping.FeatureForms;
using Esri.ArcGISRuntime.Portal;
Expand Down Expand Up @@ -54,13 +55,45 @@ private async void mapView_GeoViewTapped(object sender, Esri.ArcGISRuntime.Maui.
return null;
}

private async void BarcodeButtonClicked(object sender, Esri.ArcGISRuntime.Toolkit.Maui.BarcodeButtonClickedEventArgs e)
{
// If user clicks the barcode button in a barcode input element, use ZXing library (https://github.com/Redth/ZXing.Net.Maui)
// to scan a barcode using the device camera
ZXing.Net.Maui.Controls.CameraBarcodeReaderView view = new ZXing.Net.Maui.Controls.CameraBarcodeReaderView();
TaskCompletionSource<string?> tcs = new TaskCompletionSource<string?>();
view.BarcodesDetected += (s, e) =>
{
if (tcs.TrySetResult(e.Results.FirstOrDefault()?.Value))
Dispatcher.Dispatch(() => _ = Navigation.PopModalAsync());
};
ContentPage p = new ContentPage() { Content = view };
await Navigation.PushModalAsync(p);
p.NavigatedFrom += (s, e) => tcs.TrySetResult(null);
var barcode = await tcs.Task;
if (!string.IsNullOrEmpty(barcode))
e.FormElement.UpdateValue(barcode);
}

private void FormAttachmentClicked(object sender, Esri.ArcGISRuntime.Toolkit.Maui.FormAttachmentClickedEventArgs e)
{
// User clicked an attachment,
// e.Handled = true; // Uncomment to override default open attachment action
Debug.WriteLine("Attachment clicked: " + e.Attachment.Name);
}

private async void DiscardButton_Click(object sender, EventArgs e)
{
var result = await DisplayAlert("Confirm", "Discard edits?", "Yes", "Cancel");
if (result)
{
formViewer.FeatureForm?.DiscardEdits();

((Button)sender).IsEnabled = false;
try
{
await formViewer.DiscardEditsAsync();
} catch { }

((Button)sender).IsEnabled = true;
}
}

Expand All @@ -84,7 +117,7 @@ private async void UpdateButton_Click(object sender, EventArgs e)
}
try
{
await formViewer.FeatureForm!.Feature.FeatureTable!.UpdateFeatureAsync(formViewer.FeatureForm.Feature);
await formViewer.FinishEditingAsync();
}
catch (Exception ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<Border Background="#99ffffff" x:Name="popupPanel" IsVisible="False">
<Border HorizontalOptions="Center" VerticalOptions="Center" Background="{AppThemeBinding Dark=Black, Light=White}" Margin="0,32" Padding="12">
<Grid>
<esriTK:PopupViewer x:Name="popupViewer" Padding="12" MaximumWidthRequest="400" MaximumHeightRequest="400" PopupAttachmentClicked="popupViewer_PopupAttachmentClicked" />
<esriTK:PopupViewer x:Name="popupViewer" Padding="12" MaximumWidthRequest="400" MaximumHeightRequest="400" PopupAttachmentClicked="popupViewer_PopupAttachmentClicked" HyperlinkClicked="popupViewer_HyperlinkClicked" />
<Button BorderWidth="0" Text="X" HorizontalOptions="End" VerticalOptions="Start" Clicked="CloseButton_Click" BackgroundColor="Transparent" TextColor="{AppThemeBinding Dark=White, Light=Black}" Margin="5" />
</Grid>
</Border>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
using Esri.ArcGISRuntime.Data;
using Esri.ArcGISRuntime.Mapping.Popups;
using Esri.ArcGISRuntime.Maui;
using Esri.ArcGISRuntime.Security;
using Esri.ArcGISRuntime.UI;
using Microsoft.Maui.Controls.Shapes;
using System.Diagnostics;

namespace Toolkit.SampleApp.Maui.Samples
{
Expand Down Expand Up @@ -117,5 +115,14 @@ private void popupViewer_PopupAttachmentClicked(object sender, Esri.ArcGISRuntim
_ = Microsoft.Maui.ApplicationModel.Launcher.Default.OpenAsync(
new Microsoft.Maui.ApplicationModel.OpenFileRequest(e.Attachment.Name, new ReadOnlyFile(e.Attachment.Filename!, e.Attachment.ContentType)));
}

private void popupViewer_HyperlinkClicked(object sender, Esri.ArcGISRuntime.Toolkit.Maui.HyperlinkClickedEventArgs e)
{
// Include below line if you want to prevent the default action
// e.Handled = true;

// Perform custom action when a link is clicked
Debug.WriteLine(e.Uri);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
<ItemGroup>
<PackageReference Include="CommunityToolkit.Maui" Version="7.0.0" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="ZXing.Net.Maui.Controls" Version="0.4.0" />
</ItemGroup>

<ItemGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible($(TargetFramework), 'net8.0'))">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,18 @@ private ArcGISFeature GetFeature(IEnumerable<IdentifyLayerResult> results, out F
return null;
}

private void DiscardButton_Click(object sender, RoutedEventArgs e)
private async void DiscardButton_Click(object sender, RoutedEventArgs e)
{
var result = MessageBox.Show("Discard edits?", "Confirm", MessageBoxButton.YesNo);
if (result == MessageBoxResult.Yes)
{
formViewer.FeatureForm.DiscardEdits();
((Button)sender).IsEnabled = false;
try
{
await formViewer.DiscardEditsAsync();
}
catch { }
((Button)sender).IsEnabled = true;
}
}

Expand All @@ -83,7 +89,7 @@ private async void UpdateButton_Click(object sender, RoutedEventArgs e)
}
try
{
await formViewer.FeatureForm.Feature.FeatureTable.UpdateFeatureAsync(formViewer.FeatureForm.Feature);
await formViewer.FinishEditingAsync();
}
catch (Exception ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

<Grid Background="#AA333333" Visibility="Collapsed" x:Name="PopupBackground" MouseDown="PopupBackground_MouseDown">
<Border BorderBrush="Black" BorderThickness="1" Background="White" HorizontalAlignment="Center" VerticalAlignment="Center" >
<esri:PopupViewer x:Name="popupViewer" Margin="5" Width="400" MaxHeight="400" PopupAttachmentClicked="popupViewer_PopupAttachmentClicked" />
<esri:PopupViewer x:Name="popupViewer" Margin="5" Width="400" MaxHeight="400" PopupAttachmentClicked="popupViewer_PopupAttachmentClicked" HyperlinkClicked="popupViewer_LinkClicked" />
</Border>
</Grid>
</Grid>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Esri.ArcGISRuntime.UI.Controls;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
Expand Down Expand Up @@ -154,5 +155,14 @@ private async void popupViewer_PopupAttachmentClicked(object sender, UI.Controls
}
}
}

private void popupViewer_LinkClicked(object sender, UI.Controls.HyperlinkClickedEventArgs e)
{
// Include below line if you want to prevent the default action
// e.Handled = true;

// Perform custom action when a link is clicked
Debug.WriteLine(e.Uri);
}
}
}
43 changes: 43 additions & 0 deletions src/Toolkit/Toolkit.Maui/Internal/CalciteImageButton.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// /*******************************************************************************
// * Copyright 2012-2018 Esri
// *
// * Licensed under the Apache License, Version 2.0 (the "License");
// * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at
// *
// * http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS,
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// * See the License for the specific language governing permissions and
// * limitations under the License.
// ******************************************************************************/

namespace Esri.ArcGISRuntime.Toolkit.Maui.Internal
{
internal sealed class CalciteImageButton : ImageButton
{
private readonly string _glyph;
public CalciteImageButton(string glyph)
{
_glyph = glyph;
Source = new FontImageSource() { Glyph = _glyph, FontFamily = "calcite-ui-icons-24", Color = Color };
this.SetAppThemeColor(ColorProperty, Colors.Black, Colors.White);
}

public Color Color
{
get { return (Color)GetValue(ColorProperty); }
set { SetValue(ColorProperty, value); }
}

public static readonly BindableProperty ColorProperty = BindableProperty.Create(nameof(Color), typeof(Color), typeof(CalciteImageButton), Colors.Black,
propertyChanged: (s, oldValue, newValue) => ((CalciteImageButton)s).SetColor());

private void SetColor()
{
((FontImageSource)Source).Color = Color;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ namespace Esri.ArcGISRuntime.Toolkit.UI.Controls
public partial class BasemapGallery : Control
{
private readonly BasemapGalleryController _controller;
private bool isAvailableBasemapCollectionInitialized;

/// <summary>
/// Initializes a new instance of the <see cref="BasemapGallery"/> class.
Expand All @@ -44,6 +45,7 @@ public BasemapGallery()
DefaultStyleKey = typeof(BasemapGallery);
SizeChanged += BasemapGallerySizeChanged;
AvailableBasemaps = new ObservableCollection<BasemapGalleryItem>();
isAvailableBasemapCollectionInitialized = true;
_controller.PropertyChanged += HandleControllerPropertyChanged;
Loaded += BasemapGallery_Loaded;
}
Expand All @@ -52,8 +54,8 @@ private async void BasemapGallery_Loaded(object? sender, RoutedEventArgs e)
{
// Unsubscribe from the Loaded event to ensure this only runs once.
Loaded -= BasemapGallery_Loaded;
if (AvailableBasemaps is null)

if ((AvailableBasemaps is null || !AvailableBasemaps.Any()) && isAvailableBasemapCollectionInitialized)
{
await _controller.LoadFromDefaultPortal();
}
Expand Down Expand Up @@ -141,6 +143,7 @@ private static void AvailableBasemapsChanged(DependencyObject d, DependencyPrope
{
if (d is BasemapGallery gallery)
{
gallery.isAvailableBasemapCollectionInitialized = false;
if (e.NewValue != gallery._controller.AvailableBasemaps)
{
gallery._controller.AvailableBasemaps = e.NewValue as IList<BasemapGalleryItem>;
Expand Down
Loading

0 comments on commit 94dbc05

Please sign in to comment.