diff --git a/DemoApp/DemoApp/DemoApp.csproj b/DemoApp/DemoApp/DemoApp.csproj index b5aee1ac..fda3bc9e 100644 --- a/DemoApp/DemoApp/DemoApp.csproj +++ b/DemoApp/DemoApp/DemoApp.csproj @@ -155,6 +155,9 @@ + + MSBuild:Compile + MSBuild:Compile diff --git a/DemoApp/DemoApp/MainPage.xaml.cs b/DemoApp/DemoApp/MainPage.xaml.cs index 03124b30..e91e5e95 100644 --- a/DemoApp/DemoApp/MainPage.xaml.cs +++ b/DemoApp/DemoApp/MainPage.xaml.cs @@ -18,6 +18,7 @@ public MainPage() "CheckBox", "Chips", "DataGrid", + "Display Alert", "Input", "MultiLineInput", "NumberInput", @@ -30,8 +31,10 @@ public MainPage() "Spinner", "Switch", "TabbedPage", - "Toast" - + "Accordion", + "Chips", + "Switch", + "ProgressBar", }; BindingContext = this; } @@ -101,6 +104,9 @@ private void ItemTapped(object sender, ItemTappedEventArgs e) case "Switch": Navigation.PushAsync(new SwitchSamplePage()); break; + case "Display Alert": + Navigation.PushAsync(new DisplayAlertSamplePage()); + break; default: Console.WriteLine("Default Case"); break; diff --git a/DemoApp/DemoApp/Platforms/Android/Resources/values/colors.xml b/DemoApp/DemoApp/Platforms/Android/Resources/values/colors.xml index 86fc343d..14057841 100644 --- a/DemoApp/DemoApp/Platforms/Android/Resources/values/colors.xml +++ b/DemoApp/DemoApp/Platforms/Android/Resources/values/colors.xml @@ -1,6 +1,6 @@ - - - #0063a3 - #0063a3 - #0063a3 - + + + #0063a3 + #0063a3 + #0063a3 + diff --git a/DemoApp/DemoApp/Resources/AppIcon/appicon.svg b/DemoApp/DemoApp/Resources/AppIcon/appicon.svg index e2a12ca5..a9ce2284 100644 --- a/DemoApp/DemoApp/Resources/AppIcon/appicon.svg +++ b/DemoApp/DemoApp/Resources/AppIcon/appicon.svg @@ -1,9 +1,9 @@ - - appicon-svg - - - - - - + + appicon-svg + + + + + + diff --git a/DemoApp/DemoApp/Resources/AppIcon/appiconfg.svg b/DemoApp/DemoApp/Resources/AppIcon/appiconfg.svg index e6662e6a..74948864 100644 --- a/DemoApp/DemoApp/Resources/AppIcon/appiconfg.svg +++ b/DemoApp/DemoApp/Resources/AppIcon/appiconfg.svg @@ -1,11 +1,11 @@ - - appiconfg-svg - - - - - - - + + appiconfg-svg + + + + + + + diff --git a/DemoApp/DemoApp/Resources/Splash/splash.svg b/DemoApp/DemoApp/Resources/Splash/splash.svg index 89f8f7a1..18568357 100644 --- a/DemoApp/DemoApp/Resources/Splash/splash.svg +++ b/DemoApp/DemoApp/Resources/Splash/splash.svg @@ -1,9 +1,9 @@ - - - - - - - - - + + + + + + + + + diff --git a/DemoApp/DemoApp/ViewModels/DisplayAlertSampleViewModel.cs b/DemoApp/DemoApp/ViewModels/DisplayAlertSampleViewModel.cs new file mode 100644 index 00000000..ee478d33 --- /dev/null +++ b/DemoApp/DemoApp/ViewModels/DisplayAlertSampleViewModel.cs @@ -0,0 +1,35 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using Trimble.Modus.Components; + +namespace DemoApp.ViewModels +{ + public partial class DisplayAlertSampleViewModel : ObservableObject + { + [ObservableProperty] string _title; + [ObservableProperty] string _message; + [ObservableProperty] string _primaryButtonText; + [ObservableProperty] string _secondaryButtonText; + public DisplayAlertSampleViewModel() + { + Title = "Alert"; + Message = "Do you want to delete?"; + PrimaryButtonText = "Okay"; + SecondaryButtonText = ""; + } + + [RelayCommand] + async Task ShowAlert() + { + var confirmationDialog = new AlertDialogue(Title, Message, PrimaryButtonText, SecondaryButtonText); + try + { + var result = await confirmationDialog.Show(); + Console.WriteLine(result ? "Primary button tapped" : "Secondary button tapped"); + } catch (Exception ex) + { + Console.WriteLine("Invalid result " + ex.Message); + } + } + } +} diff --git a/DemoApp/DemoApp/Views/DisplayAlertSamplePage.xaml b/DemoApp/DemoApp/Views/DisplayAlertSamplePage.xaml new file mode 100644 index 00000000..0b66b1f6 --- /dev/null +++ b/DemoApp/DemoApp/Views/DisplayAlertSamplePage.xaml @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/DemoApp/DemoApp/Views/DisplayAlertSamplePage.xaml.cs b/DemoApp/DemoApp/Views/DisplayAlertSamplePage.xaml.cs new file mode 100644 index 00000000..64a89242 --- /dev/null +++ b/DemoApp/DemoApp/Views/DisplayAlertSamplePage.xaml.cs @@ -0,0 +1,13 @@ +using DemoApp.ViewModels; + +namespace DemoApp.Views; + +public partial class DisplayAlertSamplePage : ContentPage +{ + DisplayAlertSampleViewModel _viewModel = new DisplayAlertSampleViewModel(); + public DisplayAlertSamplePage() + { + InitializeComponent(); + BindingContext = _viewModel; + } +} diff --git a/DemoApp/DemoApp/Views/ListViewSamplePage.xaml b/DemoApp/DemoApp/Views/ListViewSamplePage.xaml index 2519b717..f9c5c2e8 100644 --- a/DemoApp/DemoApp/Views/ListViewSamplePage.xaml +++ b/DemoApp/DemoApp/Views/ListViewSamplePage.xaml @@ -1,92 +1,92 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Trimble.Modus.Components/Controls/Button/TMButton.xaml b/Trimble.Modus.Components/Controls/Button/TMButton.xaml index 44fbed4d..5a267d13 100644 --- a/Trimble.Modus.Components/Controls/Button/TMButton.xaml +++ b/Trimble.Modus.Components/Controls/Button/TMButton.xaml @@ -1,48 +1,48 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/Trimble.Modus.Components/Controls/ListView/TextCell.xaml b/Trimble.Modus.Components/Controls/ListView/TextCell.xaml index 45b22be7..eb366420 100644 --- a/Trimble.Modus.Components/Controls/ListView/TextCell.xaml +++ b/Trimble.Modus.Components/Controls/ListView/TextCell.xaml @@ -1,42 +1,42 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Trimble.Modus.Components/Controls/TMBadge/TMBadge.xaml b/Trimble.Modus.Components/Controls/TMBadge/TMBadge.xaml index 70ed0b1c..3946bda2 100644 --- a/Trimble.Modus.Components/Controls/TMBadge/TMBadge.xaml +++ b/Trimble.Modus.Components/Controls/TMBadge/TMBadge.xaml @@ -1,19 +1,19 @@ - - - - - + + + + + diff --git a/Trimble.Modus.Components/Controls/TMDataGrid/ColumnTypes/TextColumn.xaml b/Trimble.Modus.Components/Controls/TMDataGrid/ColumnTypes/TextColumn.xaml index e8069a57..d98af267 100644 --- a/Trimble.Modus.Components/Controls/TMDataGrid/ColumnTypes/TextColumn.xaml +++ b/Trimble.Modus.Components/Controls/TMDataGrid/ColumnTypes/TextColumn.xaml @@ -1,30 +1,30 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/Trimble.Modus.Components/Controls/TMDataGrid/DataGridColumn.cs b/Trimble.Modus.Components/Controls/TMDataGrid/DataGridColumn.cs index a5841ee5..79543f1b 100644 --- a/Trimble.Modus.Components/Controls/TMDataGrid/DataGridColumn.cs +++ b/Trimble.Modus.Components/Controls/TMDataGrid/DataGridColumn.cs @@ -1,244 +1,244 @@ -using System.ComponentModel; -using System.Globalization; -using Trimble.Modus.Components.Constant; -using Trimble.Modus.Components.Controls.DataGridControl; - -namespace Trimble.Modus.Components; -/// -/// Specifies each column of the DataGrid. -/// -public class DataGridColumn : BindableObject, IDefinition -{ - #region Fields - - private bool? _isSortable; - private ColumnDefinition? _columnDefinition; - private readonly ColumnDefinition _invisibleColumnDefinition = new(0); - private readonly WeakEventManager _sizeChangedEventManager = new(); - - #endregion Fields - internal DataGrid? DataGrid { get; set; } - - public DataGridColumn() - { - HeaderLabel = new Label { Margin = new Thickness(0,0,0,0), FontFamily = "OpenSansRegular" }; - SortingIcon = new Image {Source = ImageConstants.CaretDownImage}; - SortingIconContainer = new ContentView - { - IsVisible = false, - Content = SortingIcon, - HorizontalOptions = LayoutOptions.Center, - VerticalOptions = LayoutOptions.Center, - }; - } - - #region Events - - public event EventHandler SizeChanged - { - add => _sizeChangedEventManager.AddEventHandler(value); - remove => _sizeChangedEventManager.RemoveEventHandler(value); - } - - #endregion Events - - #region Bindable Properties - - public static readonly BindableProperty WidthProperty = BindableProperty.Create(nameof(Width), typeof(GridLength), typeof(DataGridColumn), GridLength.Star, propertyChanged: OnWidthPropertyChanged); - public static readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(DataGridColumn), string.Empty, propertyChanged: OnColumnTitleChanged); - public static readonly BindableProperty PropertyNameProperty = BindableProperty.Create(nameof(PropertyName), typeof(string), typeof(DataGridColumn)); - public static readonly BindableProperty IsVisibleProperty = BindableProperty.Create(nameof(IsVisible), typeof(bool), typeof(DataGridColumn), true, propertyChanged: OnIsVisiblePropertyChanged); - public static readonly BindableProperty CellTemplateProperty = BindableProperty.Create(nameof(CellTemplate), typeof(DataTemplate), typeof(DataGridColumn)); - public static readonly BindableProperty LineBreakModeProperty = BindableProperty.Create(nameof(LineBreakMode), typeof(LineBreakMode), typeof(DataGridColumn), LineBreakMode.WordWrap); - public static readonly BindableProperty HorizontalContentAlignmentProperty = BindableProperty.Create(nameof(HorizontalContentAlignment), typeof(LayoutOptions), typeof(DataGridColumn), LayoutOptions.Center); - public static readonly BindableProperty VerticalContentAlignmentProperty = BindableProperty.Create(nameof(VerticalContentAlignment), typeof(LayoutOptions), typeof(DataGridColumn), LayoutOptions.Center); - public static readonly BindableProperty SortingEnabledProperty = BindableProperty.Create(nameof(SortingEnabled), typeof(bool), typeof(DataGridColumn), true); - #endregion Bindable Properties - - #region Properties - - - internal ColumnDefinition? ColumnDefinition - { - get - { - if (!IsVisible) - { - return _invisibleColumnDefinition; - } - - return _columnDefinition; - } - set => _columnDefinition = value; - } - - internal View? HeaderView { get; set; } - - /// - /// Width of the column. Like Grid, you can use Absolute, star, Auto as unit. - /// - [TypeConverter(typeof(GridLengthTypeConverter))] - public GridLength Width - { - get => (GridLength)GetValue(WidthProperty); - set => SetValue(WidthProperty, value); - } - - /// - /// Column title - /// - public string Title - { - get => (string)GetValue(TitleProperty); - set => SetValue(TitleProperty, value); - } - /// - /// Property name to bind in the object - /// - public string PropertyName - { - get => (string)GetValue(PropertyNameProperty); - set => SetValue(PropertyNameProperty, value); - } - - /// - /// Is this column visible? - /// - public bool IsVisible - { - get => (bool)GetValue(IsVisibleProperty); - set => SetValue(IsVisibleProperty, value); - } - - /// - /// Cell template. Default value is Label with binding PropertyName - /// - public DataTemplate CellTemplate - { - get => (DataTemplate)GetValue(CellTemplateProperty); - set => SetValue(CellTemplateProperty, value); - } - - /// - /// LineBreakModeProperty for the text. WordWrap by default. - /// - public LineBreakMode LineBreakMode - { - get => (LineBreakMode)GetValue(LineBreakModeProperty); - set => SetValue(LineBreakModeProperty, value); - } - - /// - /// Horizontal alignment of the cell content - /// - public LayoutOptions HorizontalContentAlignment - { - get => (LayoutOptions)GetValue(HorizontalContentAlignmentProperty); - set => SetValue(HorizontalContentAlignmentProperty, value); - } - - /// - /// Vertical alignment of the cell content - /// - public LayoutOptions VerticalContentAlignment - { - get => (LayoutOptions)GetValue(VerticalContentAlignmentProperty); - set => SetValue(VerticalContentAlignmentProperty, value); - } - - /// - /// Defines if the column is sortable. Default is true - /// Sortable columns must implement - /// - public bool SortingEnabled - { - get => (bool)GetValue(SortingEnabledProperty); - set => SetValue(SortingEnabledProperty, value); - } - - internal Image SortingIcon { get; } - internal Label HeaderLabel { get; } - internal View SortingIconContainer { get; } - internal SortingOrder SortingOrder { get; set; } - - #endregion Properties - - #region Methods - private static void OnColumnTitleChanged(BindableObject bindable, object oldValue, object newValue) - { - var column = (DataGridColumn)bindable; - TextInfo textInfo = new CultureInfo("en-US", false).TextInfo; - column.HeaderLabel.Text = textInfo.ToTitleCase((string)newValue); - } - /// - /// On IsVisible property changed - /// - private static void OnIsVisiblePropertyChanged(BindableObject bindable, object oldValue, object newValue) - { - if (oldValue != newValue && bindable is DataGridColumn column) - { - try - { - Element parent = column.HeaderLabel.Parent; - int iterations = 0; - while (parent != null && !(parent is DataGrid) && iterations < 4) - { - parent = parent.Parent; - iterations++; - } - column.DataGrid ??= (DataGrid?)parent; - column.DataGrid?.Reload(); - } - catch { } - finally - { - column.OnSizeChanged(); - } - } - } - /// - /// Set Column width - /// - private static void OnWidthPropertyChanged(BindableObject bindable, object oldValue, object newValue) - { - if (oldValue != newValue && newValue is GridLength width && bindable is DataGridColumn self) - { - self.ColumnDefinition = new(width); - self.OnSizeChanged(); - } - } - - /// - /// Determines via reflection if the column's data type is sortable. - /// If you want to disable sorting for specific column please use SortingEnabled property - /// - /// - public bool IsSortable(DataGrid dataGrid) - { - if (_isSortable is not null) - { - return _isSortable.Value; - } - - try - { - var listItemType = dataGrid.ItemsSource.GetType().GetGenericArguments().Single(); - var columnDataType = listItemType.GetProperty(PropertyName)?.PropertyType; - - if (columnDataType is not null) - { - _isSortable = typeof(IComparable).IsAssignableFrom(columnDataType); - } - } - catch - { - _isSortable = false; - } - - return _isSortable ?? false; - } - - private void OnSizeChanged() => _sizeChangedEventManager.HandleEvent(this, EventArgs.Empty, nameof(SizeChanged)); - - #endregion Methods -} +using System.ComponentModel; +using System.Globalization; +using Trimble.Modus.Components.Constant; +using Trimble.Modus.Components.Controls.DataGridControl; + +namespace Trimble.Modus.Components; +/// +/// Specifies each column of the DataGrid. +/// +public class DataGridColumn : BindableObject, IDefinition +{ + #region Fields + + private bool? _isSortable; + private ColumnDefinition? _columnDefinition; + private readonly ColumnDefinition _invisibleColumnDefinition = new(0); + private readonly WeakEventManager _sizeChangedEventManager = new(); + + #endregion Fields + internal DataGrid? DataGrid { get; set; } + + public DataGridColumn() + { + HeaderLabel = new Label { Margin = new Thickness(0,0,0,0), FontFamily = "OpenSansRegular" }; + SortingIcon = new Image {Source = ImageConstants.CaretDownImage}; + SortingIconContainer = new ContentView + { + IsVisible = false, + Content = SortingIcon, + HorizontalOptions = LayoutOptions.Center, + VerticalOptions = LayoutOptions.Center, + }; + } + + #region Events + + public event EventHandler SizeChanged + { + add => _sizeChangedEventManager.AddEventHandler(value); + remove => _sizeChangedEventManager.RemoveEventHandler(value); + } + + #endregion Events + + #region Bindable Properties + + public static readonly BindableProperty WidthProperty = BindableProperty.Create(nameof(Width), typeof(GridLength), typeof(DataGridColumn), GridLength.Star, propertyChanged: OnWidthPropertyChanged); + public static readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(DataGridColumn), string.Empty, propertyChanged: OnColumnTitleChanged); + public static readonly BindableProperty PropertyNameProperty = BindableProperty.Create(nameof(PropertyName), typeof(string), typeof(DataGridColumn)); + public static readonly BindableProperty IsVisibleProperty = BindableProperty.Create(nameof(IsVisible), typeof(bool), typeof(DataGridColumn), true, propertyChanged: OnIsVisiblePropertyChanged); + public static readonly BindableProperty CellTemplateProperty = BindableProperty.Create(nameof(CellTemplate), typeof(DataTemplate), typeof(DataGridColumn)); + public static readonly BindableProperty LineBreakModeProperty = BindableProperty.Create(nameof(LineBreakMode), typeof(LineBreakMode), typeof(DataGridColumn), LineBreakMode.WordWrap); + public static readonly BindableProperty HorizontalContentAlignmentProperty = BindableProperty.Create(nameof(HorizontalContentAlignment), typeof(LayoutOptions), typeof(DataGridColumn), LayoutOptions.Center); + public static readonly BindableProperty VerticalContentAlignmentProperty = BindableProperty.Create(nameof(VerticalContentAlignment), typeof(LayoutOptions), typeof(DataGridColumn), LayoutOptions.Center); + public static readonly BindableProperty SortingEnabledProperty = BindableProperty.Create(nameof(SortingEnabled), typeof(bool), typeof(DataGridColumn), true); + #endregion Bindable Properties + + #region Properties + + + internal ColumnDefinition? ColumnDefinition + { + get + { + if (!IsVisible) + { + return _invisibleColumnDefinition; + } + + return _columnDefinition; + } + set => _columnDefinition = value; + } + + internal View? HeaderView { get; set; } + + /// + /// Width of the column. Like Grid, you can use Absolute, star, Auto as unit. + /// + [TypeConverter(typeof(GridLengthTypeConverter))] + public GridLength Width + { + get => (GridLength)GetValue(WidthProperty); + set => SetValue(WidthProperty, value); + } + + /// + /// Column title + /// + public string Title + { + get => (string)GetValue(TitleProperty); + set => SetValue(TitleProperty, value); + } + /// + /// Property name to bind in the object + /// + public string PropertyName + { + get => (string)GetValue(PropertyNameProperty); + set => SetValue(PropertyNameProperty, value); + } + + /// + /// Is this column visible? + /// + public bool IsVisible + { + get => (bool)GetValue(IsVisibleProperty); + set => SetValue(IsVisibleProperty, value); + } + + /// + /// Cell template. Default value is Label with binding PropertyName + /// + public DataTemplate CellTemplate + { + get => (DataTemplate)GetValue(CellTemplateProperty); + set => SetValue(CellTemplateProperty, value); + } + + /// + /// LineBreakModeProperty for the text. WordWrap by default. + /// + public LineBreakMode LineBreakMode + { + get => (LineBreakMode)GetValue(LineBreakModeProperty); + set => SetValue(LineBreakModeProperty, value); + } + + /// + /// Horizontal alignment of the cell content + /// + public LayoutOptions HorizontalContentAlignment + { + get => (LayoutOptions)GetValue(HorizontalContentAlignmentProperty); + set => SetValue(HorizontalContentAlignmentProperty, value); + } + + /// + /// Vertical alignment of the cell content + /// + public LayoutOptions VerticalContentAlignment + { + get => (LayoutOptions)GetValue(VerticalContentAlignmentProperty); + set => SetValue(VerticalContentAlignmentProperty, value); + } + + /// + /// Defines if the column is sortable. Default is true + /// Sortable columns must implement + /// + public bool SortingEnabled + { + get => (bool)GetValue(SortingEnabledProperty); + set => SetValue(SortingEnabledProperty, value); + } + + internal Image SortingIcon { get; } + internal Label HeaderLabel { get; } + internal View SortingIconContainer { get; } + internal SortingOrder SortingOrder { get; set; } + + #endregion Properties + + #region Methods + private static void OnColumnTitleChanged(BindableObject bindable, object oldValue, object newValue) + { + var column = (DataGridColumn)bindable; + TextInfo textInfo = new CultureInfo("en-US", false).TextInfo; + column.HeaderLabel.Text = textInfo.ToTitleCase((string)newValue); + } + /// + /// On IsVisible property changed + /// + private static void OnIsVisiblePropertyChanged(BindableObject bindable, object oldValue, object newValue) + { + if (oldValue != newValue && bindable is DataGridColumn column) + { + try + { + Element parent = column.HeaderLabel.Parent; + int iterations = 0; + while (parent != null && !(parent is DataGrid) && iterations < 4) + { + parent = parent.Parent; + iterations++; + } + column.DataGrid ??= (DataGrid?)parent; + column.DataGrid?.Reload(); + } + catch { } + finally + { + column.OnSizeChanged(); + } + } + } + /// + /// Set Column width + /// + private static void OnWidthPropertyChanged(BindableObject bindable, object oldValue, object newValue) + { + if (oldValue != newValue && newValue is GridLength width && bindable is DataGridColumn self) + { + self.ColumnDefinition = new(width); + self.OnSizeChanged(); + } + } + + /// + /// Determines via reflection if the column's data type is sortable. + /// If you want to disable sorting for specific column please use SortingEnabled property + /// + /// + public bool IsSortable(DataGrid dataGrid) + { + if (_isSortable is not null) + { + return _isSortable.Value; + } + + try + { + var listItemType = dataGrid.ItemsSource.GetType().GetGenericArguments().Single(); + var columnDataType = listItemType.GetProperty(PropertyName)?.PropertyType; + + if (columnDataType is not null) + { + _isSortable = typeof(IComparable).IsAssignableFrom(columnDataType); + } + } + catch + { + _isSortable = false; + } + + return _isSortable ?? false; + } + + private void OnSizeChanged() => _sizeChangedEventManager.HandleEvent(this, EventArgs.Empty, nameof(SizeChanged)); + + #endregion Methods +} diff --git a/Trimble.Modus.Components/Controls/TMModal/AlertDialogue.cs b/Trimble.Modus.Components/Controls/TMModal/AlertDialogue.cs new file mode 100644 index 00000000..48af434e --- /dev/null +++ b/Trimble.Modus.Components/Controls/TMModal/AlertDialogue.cs @@ -0,0 +1,60 @@ +using System; + +namespace Trimble.Modus.Components +{ + public class AlertDialogue + { + private string Title; + private string Message; + private string PrimaryButtonText; + private string SecondaryText; + + TaskCompletionSource alertClosedTask = new TaskCompletionSource(); + + private AlertDialogue() + { + + } + + public AlertDialogue(string title, string message = "", string primaryButtonText = "Ok", string secondaryText = "") + { + Title = title; + Message = message; + PrimaryButtonText = primaryButtonText; + SecondaryText = secondaryText; + } + + public Task Show() + { + if (string.IsNullOrWhiteSpace(Title) && string.IsNullOrWhiteSpace(Message)) + { + throw new ArgumentNullException("Title cannot be empty"); + } + + if (string.IsNullOrWhiteSpace(PrimaryButtonText) && string.IsNullOrWhiteSpace(SecondaryText)) + { + throw new ArgumentNullException("Alert should atleast have one button"); + } + + + TMModal modal = new TMModal(Title, Message); + if (!string.IsNullOrEmpty(PrimaryButtonText)) + { + modal.AddPrimaryAction(PrimaryButtonText, () => + { + alertClosedTask.SetResult(true); + }); + } + if (!string.IsNullOrEmpty(SecondaryText)) + { + modal.AddSecondaryAction(SecondaryText, () => + { + alertClosedTask.SetResult(false); + }); + } + modal.Show(); + return alertClosedTask.Task; + } + } +} + diff --git a/Trimble.Modus.Components/Controls/TMSegmentedControl/TMSegmentedItem.xaml b/Trimble.Modus.Components/Controls/TMSegmentedControl/TMSegmentedItem.xaml index 33b25f2b..117928cd 100644 --- a/Trimble.Modus.Components/Controls/TMSegmentedControl/TMSegmentedItem.xaml +++ b/Trimble.Modus.Components/Controls/TMSegmentedControl/TMSegmentedItem.xaml @@ -1,78 +1,78 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Trimble.Modus.Components/Controls/TMSwitch/TMSwitch.xaml b/Trimble.Modus.Components/Controls/TMSwitch/TMSwitch.xaml index e20b6c11..8c2e43c5 100644 --- a/Trimble.Modus.Components/Controls/TMSwitch/TMSwitch.xaml +++ b/Trimble.Modus.Components/Controls/TMSwitch/TMSwitch.xaml @@ -1,25 +1,25 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/Trimble.Modus.Components/Controls/TabBar/TMTabbedPage.cs b/Trimble.Modus.Components/Controls/TabBar/TMTabbedPage.cs index e2771e06..26ccab29 100644 --- a/Trimble.Modus.Components/Controls/TabBar/TMTabbedPage.cs +++ b/Trimble.Modus.Components/Controls/TabBar/TMTabbedPage.cs @@ -1,335 +1,335 @@ -using System.Collections; -using System.Collections.ObjectModel; -using System.ComponentModel; -using Trimble.Modus.Components.Constant; -using Trimble.Modus.Components.Helpers; - -namespace Trimble.Modus.Components; - -[ContentProperty(nameof(TabItems))] -public partial class TMTabbedPage : ContentPage -{ - #region Private Fields - private Grid mainContainer; - private Grid tabStripContainer; - private CarouselView contentContainer; - private ObservableCollection? contentTabItems; - #endregion - #region Public Fields - public ObservableCollection TabItems { get; set; } = new(); - public delegate void TabSelectionChangedEventHandler(object? sender, TabSelectionChangedEventArgs e); - public event TabSelectionChangedEventHandler? SelectionChanged; - #endregion - #region Bindable Properties - public static readonly BindableProperty SelectedIndexProperty = - BindableProperty.Create(nameof(SelectedIndex), typeof(int), typeof(TMTabbedPage), -1, BindingMode.TwoWay, propertyChanged: OnSelectedIndexChanged); - - public static readonly BindableProperty OrientationProperty = - BindableProperty.Create(nameof(Orientation), typeof(StackOrientation), typeof(TMTabbedPage), StackOrientation.Vertical); - - public static readonly BindableProperty TabItemsSourceProperty = - BindableProperty.Create(nameof(TabItemsSource), typeof(IList), typeof(TMTabbedPage), null); - - public static readonly BindableProperty TabColorProperty = - BindableProperty.Create(nameof(TabColor), typeof(TabColor), typeof(TabViewItem), defaultValue: TabColor.Primary, propertyChanged: OnTabColorPropertyChanged); - - #endregion - #region Public Fields - public StackOrientation Orientation - { - get => (StackOrientation)GetValue(OrientationProperty); - set => SetValue(OrientationProperty, value); - } - - public TabColor TabColor - { - get => (TabColor)GetValue(TabColorProperty); - set => SetValue(TabColorProperty, value); - } - public int SelectedIndex - { - get => (int)GetValue(SelectedIndexProperty); - set => SetValue(SelectedIndexProperty, value); - } - public IList? TabItemsSource - { - get => (IList?)GetValue(TabItemsSourceProperty); - set => SetValue(TabItemsSourceProperty, value); - } - #endregion - - #region Constructor - public TMTabbedPage() - { - InitializeComponent(); - - contentContainer = new CarouselView - { - BackgroundColor = Colors.LightGray, - ItemsSource = TabItems, - ItemTemplate = new DataTemplate(() => - { - var contentView = new ContentView(); - contentView.SetBinding(ContentView.ContentProperty, "ContentView"); - return contentView; - }), - IsSwipeEnabled = true, - IsScrollAnimated = true, - Loop = false, - HorizontalScrollBarVisibility = ScrollBarVisibility.Never, - VerticalScrollBarVisibility = ScrollBarVisibility.Never, - - }; - - tabStripContainer = new Grid - { - BackgroundColor = ResourcesDictionary.ColorsDictionary(ColorsConstants.TrimbleBlue), - HeightRequest = 70, - VerticalOptions = LayoutOptions.Fill - }; - - mainContainer = new Grid - { - BackgroundColor = Colors.Red, - HorizontalOptions = LayoutOptions.FillAndExpand, - VerticalOptions = LayoutOptions.FillAndExpand, - Children = { contentContainer, tabStripContainer }, - RowSpacing = 0 - }; - - mainContainer.RowDefinitions.Add(new RowDefinition { Height = GridLength.Star }); - mainContainer.RowDefinitions.Add(new RowDefinition { Height = 70 }); - - Grid.SetRow(contentContainer, 0); - Grid.SetRow(tabStripContainer, 1); - - Content = mainContainer; - - TabItems.CollectionChanged += TabItems_CollectionChanged; - contentContainer.PropertyChanged += OnContentContainerPropertyChanged; - contentContainer.Scrolled += OnContentContainerScrolled; - - } - #endregion - #region Private Methods - private static void OnSelectedIndexChanged(BindableObject bindable, object oldValue, object newValue) - { - if (bindable is TMTabbedPage tabView && tabView.TabItems != null) - { - var selectedIndex = (int)newValue; - - if (selectedIndex < 0) - { - return; - } - if ((int)oldValue != selectedIndex) - tabView.UpdateSelectedIndex(selectedIndex); - } - } - private static void OnTabColorPropertyChanged(BindableObject bindable, object oldValue, object newValue) - { - if (bindable is TMTabbedPage tabbedPage) - { - if ((TabColor)newValue == TabColor.Primary) - { - tabbedPage.tabStripContainer.BackgroundColor = ResourcesDictionary.ColorsDictionary(ColorsConstants.TrimbleBlue); - } - else - { - tabbedPage.tabStripContainer.BackgroundColor = ResourcesDictionary.ColorsDictionary(ColorsConstants.White); - } - } - } - private void OnContentContainerScrolled(object? sender, ItemsViewScrolledEventArgs args) - { - for (var i = 0; i < TabItems.Count; i++) - TabItems[i].UpdateCurrentContent(); - } - - private void OnContentContainerPropertyChanged(object? sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(CarouselView.ItemsSource) - || e.PropertyName == nameof(CarouselView.VisibleViews)) - { - var items = contentContainer.ItemsSource; - - UpdateItemsSource(items); - } - else if (e.PropertyName == nameof(CarouselView.Position)) - { - var selectedIndex = contentContainer.Position; - if (SelectedIndex != selectedIndex) - { - UpdateSelectedIndex(selectedIndex, true); - } - } - } - private void UpdateItemsSource(IEnumerable items) - { - - if (contentContainer.VisibleViews.Count == 0) - return; - - var contentWidth = contentContainer.VisibleViews.FirstOrDefault().Width; - var tabItemsCount = items.Cast().Count(); - - } - private void TabItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) - { - TabItemsSource = TabItems; - - if (e.NewItems != null) - { - foreach (var tabViewItem in e.NewItems.OfType()) - { - AddTabViewItem(tabViewItem, TabItems.IndexOf(tabViewItem)); - } - } - } - - private void AddTabViewItem(TabViewItem item, int index = -1) - { - var tabItem = new Grid() - { - HorizontalOptions = LayoutOptions.FillAndExpand, - VerticalOptions = LayoutOptions.FillAndExpand - }; - tabItem.RowDefinitions.Add(new RowDefinition { Height = GridLength.Star }); - tabItem.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); - - var text = new Label - { - FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label)), - HorizontalOptions = LayoutOptions.Center, - VerticalOptions = LayoutOptions.Center, - Margin = new Thickness(0, 6) - }; - tabItem.Add(text); - tabItem.SetRow(text, 1); - - tabStripContainer.ColumnDefinitions.Add(new ColumnDefinition() - { - Width = GridLength.Star - }); - item.TabColor = TabColor; - item.Orientation = Orientation; - tabStripContainer.Add(item, index, 0); - AddSelectionTapRecognizer(item); - if (SelectedIndex != 0) - UpdateSelectedIndex(0); - } - private void AddSelectionTapRecognizer(View view) - { - TapGestureRecognizer tapGestureRecognizer = new TapGestureRecognizer(); - tapGestureRecognizer.Tapped += (sender, args) => - { - if (sender is not View view) - return; - - var capturedIndex = tabStripContainer.Children.IndexOf(view); - - if (view is TabViewItem tabViewItem) - { - var tabTappedEventArgs = new TabTappedEventArgs(capturedIndex); - tabViewItem.OnTabTapped(tabTappedEventArgs); - } - - if (CanUpdateSelectedIndex(capturedIndex)) - { - if (SelectedIndex != capturedIndex) - UpdateSelectedIndex(capturedIndex); - } - - }; - - view.GestureRecognizers.Add(tapGestureRecognizer); - } - private bool CanUpdateSelectedIndex(int selectedIndex) - { - if (TabItems == null || TabItems.Count == 0) - return true; - - var tabItem = TabItems[selectedIndex]; - - if (tabItem != null && tabItem.Content == null) - { - var itemsCount = TabItems.Count; - var contentItemsCount = TabItems.Count(t => t.Content == null); - - return itemsCount == contentItemsCount; - } - - return true; - } - - private void UpdateSelectedIndex(int position, bool hasCurrentItem = false) - { - if (position < 0) - return; - var oldposition = SelectedIndex; - - var newPosition = position; - - MainThread.BeginInvokeOnMainThread(() => - { - if (contentTabItems == null || contentTabItems.Count != TabItems.Count) - contentTabItems = new ObservableCollection(TabItems.Where(t => t.Content != null)); - - var contentIndex = position; - var tabStripIndex = position; - - if (TabItems.Count > 0) - { - TabViewItem? currentItem = null; - - if (hasCurrentItem) - currentItem = (TabViewItem)contentContainer.CurrentItem; - - var tabViewItem = TabItems[position]; - - contentIndex = contentTabItems.IndexOf(tabViewItem); - tabStripIndex = TabItems.IndexOf(tabViewItem); - - position = tabStripIndex; - - for (var index = 0; index < TabItems.Count; index++) - { - if (index == position) - { - TabItems[position].IsSelected = true; - } - else - { - TabItems[index].IsSelected = false; - } - } - } - - if (contentIndex >= 0) - contentContainer.Position = contentIndex; - - if (tabStripContainer.Children.Count > 0) - contentContainer.ScrollTo(tabStripIndex, 1, ScrollToPosition.MakeVisible, false); - - SelectedIndex = position; - if (oldposition != SelectedIndex) - { - var selectionChangedArgs = new TabSelectionChangedEventArgs() - { - NewPosition = newPosition, - OldPosition = oldposition - }; - - OnTabSelectionChanged(selectionChangedArgs); - } - }); - } - #endregion - #region Internal Methods - internal virtual void OnTabSelectionChanged(TabSelectionChangedEventArgs e) - { - var handler = SelectionChanged; - handler?.Invoke(this, e); - } - #endregion -} +using System.Collections; +using System.Collections.ObjectModel; +using System.ComponentModel; +using Trimble.Modus.Components.Constant; +using Trimble.Modus.Components.Helpers; + +namespace Trimble.Modus.Components; + +[ContentProperty(nameof(TabItems))] +public partial class TMTabbedPage : ContentPage +{ + #region Private Fields + private Grid mainContainer; + private Grid tabStripContainer; + private CarouselView contentContainer; + private ObservableCollection? contentTabItems; + #endregion + #region Public Fields + public ObservableCollection TabItems { get; set; } = new(); + public delegate void TabSelectionChangedEventHandler(object? sender, TabSelectionChangedEventArgs e); + public event TabSelectionChangedEventHandler? SelectionChanged; + #endregion + #region Bindable Properties + public static readonly BindableProperty SelectedIndexProperty = + BindableProperty.Create(nameof(SelectedIndex), typeof(int), typeof(TMTabbedPage), -1, BindingMode.TwoWay, propertyChanged: OnSelectedIndexChanged); + + public static readonly BindableProperty OrientationProperty = + BindableProperty.Create(nameof(Orientation), typeof(StackOrientation), typeof(TMTabbedPage), StackOrientation.Vertical); + + public static readonly BindableProperty TabItemsSourceProperty = + BindableProperty.Create(nameof(TabItemsSource), typeof(IList), typeof(TMTabbedPage), null); + + public static readonly BindableProperty TabColorProperty = + BindableProperty.Create(nameof(TabColor), typeof(TabColor), typeof(TabViewItem), defaultValue: TabColor.Primary, propertyChanged: OnTabColorPropertyChanged); + + #endregion + #region Public Fields + public StackOrientation Orientation + { + get => (StackOrientation)GetValue(OrientationProperty); + set => SetValue(OrientationProperty, value); + } + + public TabColor TabColor + { + get => (TabColor)GetValue(TabColorProperty); + set => SetValue(TabColorProperty, value); + } + public int SelectedIndex + { + get => (int)GetValue(SelectedIndexProperty); + set => SetValue(SelectedIndexProperty, value); + } + public IList? TabItemsSource + { + get => (IList?)GetValue(TabItemsSourceProperty); + set => SetValue(TabItemsSourceProperty, value); + } + #endregion + + #region Constructor + public TMTabbedPage() + { + InitializeComponent(); + + contentContainer = new CarouselView + { + BackgroundColor = Colors.LightGray, + ItemsSource = TabItems, + ItemTemplate = new DataTemplate(() => + { + var contentView = new ContentView(); + contentView.SetBinding(ContentView.ContentProperty, "ContentView"); + return contentView; + }), + IsSwipeEnabled = true, + IsScrollAnimated = true, + Loop = false, + HorizontalScrollBarVisibility = ScrollBarVisibility.Never, + VerticalScrollBarVisibility = ScrollBarVisibility.Never, + + }; + + tabStripContainer = new Grid + { + BackgroundColor = ResourcesDictionary.ColorsDictionary(ColorsConstants.TrimbleBlue), + HeightRequest = 70, + VerticalOptions = LayoutOptions.Fill + }; + + mainContainer = new Grid + { + BackgroundColor = Colors.Red, + HorizontalOptions = LayoutOptions.FillAndExpand, + VerticalOptions = LayoutOptions.FillAndExpand, + Children = { contentContainer, tabStripContainer }, + RowSpacing = 0 + }; + + mainContainer.RowDefinitions.Add(new RowDefinition { Height = GridLength.Star }); + mainContainer.RowDefinitions.Add(new RowDefinition { Height = 70 }); + + Grid.SetRow(contentContainer, 0); + Grid.SetRow(tabStripContainer, 1); + + Content = mainContainer; + + TabItems.CollectionChanged += TabItems_CollectionChanged; + contentContainer.PropertyChanged += OnContentContainerPropertyChanged; + contentContainer.Scrolled += OnContentContainerScrolled; + + } + #endregion + #region Private Methods + private static void OnSelectedIndexChanged(BindableObject bindable, object oldValue, object newValue) + { + if (bindable is TMTabbedPage tabView && tabView.TabItems != null) + { + var selectedIndex = (int)newValue; + + if (selectedIndex < 0) + { + return; + } + if ((int)oldValue != selectedIndex) + tabView.UpdateSelectedIndex(selectedIndex); + } + } + private static void OnTabColorPropertyChanged(BindableObject bindable, object oldValue, object newValue) + { + if (bindable is TMTabbedPage tabbedPage) + { + if ((TabColor)newValue == TabColor.Primary) + { + tabbedPage.tabStripContainer.BackgroundColor = ResourcesDictionary.ColorsDictionary(ColorsConstants.TrimbleBlue); + } + else + { + tabbedPage.tabStripContainer.BackgroundColor = ResourcesDictionary.ColorsDictionary(ColorsConstants.White); + } + } + } + private void OnContentContainerScrolled(object? sender, ItemsViewScrolledEventArgs args) + { + for (var i = 0; i < TabItems.Count; i++) + TabItems[i].UpdateCurrentContent(); + } + + private void OnContentContainerPropertyChanged(object? sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(CarouselView.ItemsSource) + || e.PropertyName == nameof(CarouselView.VisibleViews)) + { + var items = contentContainer.ItemsSource; + + UpdateItemsSource(items); + } + else if (e.PropertyName == nameof(CarouselView.Position)) + { + var selectedIndex = contentContainer.Position; + if (SelectedIndex != selectedIndex) + { + UpdateSelectedIndex(selectedIndex, true); + } + } + } + private void UpdateItemsSource(IEnumerable items) + { + + if (contentContainer.VisibleViews.Count == 0) + return; + + var contentWidth = contentContainer.VisibleViews.FirstOrDefault().Width; + var tabItemsCount = items.Cast().Count(); + + } + private void TabItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + TabItemsSource = TabItems; + + if (e.NewItems != null) + { + foreach (var tabViewItem in e.NewItems.OfType()) + { + AddTabViewItem(tabViewItem, TabItems.IndexOf(tabViewItem)); + } + } + } + + private void AddTabViewItem(TabViewItem item, int index = -1) + { + var tabItem = new Grid() + { + HorizontalOptions = LayoutOptions.FillAndExpand, + VerticalOptions = LayoutOptions.FillAndExpand + }; + tabItem.RowDefinitions.Add(new RowDefinition { Height = GridLength.Star }); + tabItem.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + + var text = new Label + { + FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label)), + HorizontalOptions = LayoutOptions.Center, + VerticalOptions = LayoutOptions.Center, + Margin = new Thickness(0, 6) + }; + tabItem.Add(text); + tabItem.SetRow(text, 1); + + tabStripContainer.ColumnDefinitions.Add(new ColumnDefinition() + { + Width = GridLength.Star + }); + item.TabColor = TabColor; + item.Orientation = Orientation; + tabStripContainer.Add(item, index, 0); + AddSelectionTapRecognizer(item); + if (SelectedIndex != 0) + UpdateSelectedIndex(0); + } + private void AddSelectionTapRecognizer(View view) + { + TapGestureRecognizer tapGestureRecognizer = new TapGestureRecognizer(); + tapGestureRecognizer.Tapped += (sender, args) => + { + if (sender is not View view) + return; + + var capturedIndex = tabStripContainer.Children.IndexOf(view); + + if (view is TabViewItem tabViewItem) + { + var tabTappedEventArgs = new TabTappedEventArgs(capturedIndex); + tabViewItem.OnTabTapped(tabTappedEventArgs); + } + + if (CanUpdateSelectedIndex(capturedIndex)) + { + if (SelectedIndex != capturedIndex) + UpdateSelectedIndex(capturedIndex); + } + + }; + + view.GestureRecognizers.Add(tapGestureRecognizer); + } + private bool CanUpdateSelectedIndex(int selectedIndex) + { + if (TabItems == null || TabItems.Count == 0) + return true; + + var tabItem = TabItems[selectedIndex]; + + if (tabItem != null && tabItem.Content == null) + { + var itemsCount = TabItems.Count; + var contentItemsCount = TabItems.Count(t => t.Content == null); + + return itemsCount == contentItemsCount; + } + + return true; + } + + private void UpdateSelectedIndex(int position, bool hasCurrentItem = false) + { + if (position < 0) + return; + var oldposition = SelectedIndex; + + var newPosition = position; + + MainThread.BeginInvokeOnMainThread(() => + { + if (contentTabItems == null || contentTabItems.Count != TabItems.Count) + contentTabItems = new ObservableCollection(TabItems.Where(t => t.Content != null)); + + var contentIndex = position; + var tabStripIndex = position; + + if (TabItems.Count > 0) + { + TabViewItem? currentItem = null; + + if (hasCurrentItem) + currentItem = (TabViewItem)contentContainer.CurrentItem; + + var tabViewItem = TabItems[position]; + + contentIndex = contentTabItems.IndexOf(tabViewItem); + tabStripIndex = TabItems.IndexOf(tabViewItem); + + position = tabStripIndex; + + for (var index = 0; index < TabItems.Count; index++) + { + if (index == position) + { + TabItems[position].IsSelected = true; + } + else + { + TabItems[index].IsSelected = false; + } + } + } + + if (contentIndex >= 0) + contentContainer.Position = contentIndex; + + if (tabStripContainer.Children.Count > 0) + contentContainer.ScrollTo(tabStripIndex, 1, ScrollToPosition.MakeVisible, false); + + SelectedIndex = position; + if (oldposition != SelectedIndex) + { + var selectionChangedArgs = new TabSelectionChangedEventArgs() + { + NewPosition = newPosition, + OldPosition = oldposition + }; + + OnTabSelectionChanged(selectionChangedArgs); + } + }); + } + #endregion + #region Internal Methods + internal virtual void OnTabSelectionChanged(TabSelectionChangedEventArgs e) + { + var handler = SelectionChanged; + handler?.Invoke(this, e); + } + #endregion +} diff --git a/Trimble.Modus.Components/Controls/TabBar/TabViewItem.xaml b/Trimble.Modus.Components/Controls/TabBar/TabViewItem.xaml index 116fd94e..4f63c725 100644 --- a/Trimble.Modus.Components/Controls/TabBar/TabViewItem.xaml +++ b/Trimble.Modus.Components/Controls/TabBar/TabViewItem.xaml @@ -1,29 +1,29 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/Trimble.Modus.Components/Trimble.Modus.Components.csproj b/Trimble.Modus.Components/Trimble.Modus.Components.csproj index 7f3380a4..d08a9abf 100644 --- a/Trimble.Modus.Components/Trimble.Modus.Components.csproj +++ b/Trimble.Modus.Components/Trimble.Modus.Components.csproj @@ -158,7 +158,7 @@ MSBuild:Compile - + MSBuild:Compile