From b60f2a4f475695bbc5495408c46434af378838e6 Mon Sep 17 00:00:00 2001 From: watsonb8 Date: Sun, 1 Dec 2019 15:26:13 -0800 Subject: [PATCH] Serious styling. Added data grid src for future modifications in performance --- Aurora.gtk/Aurora.gtk.csproj | 3 - Aurora.gtk/packages.config | 1 - Aurora/Aurora.csproj | 8 +- .../Components/DataGrid/ColumnCollection.cs | 8 + .../Design/Components/DataGrid/DataGrid.xaml | 93 +++ .../Components/DataGrid/DataGrid.xaml.cs | 650 ++++++++++++++++++ .../Components/DataGrid/DataGridColumn.cs | 129 ++++ .../Components/DataGrid/DataGridComponent.cs | 12 + .../DataGrid/DataGridRowTemplateSelector.cs | 28 + .../Components/DataGrid/DataGridViewCell.cs | 152 ++++ .../Components/DataGrid/IColorProvider.cs | 8 + .../Components/DataGrid/PaletteCollection.cs | 17 + Aurora/Design/Components/DataGrid/SortData.cs | 51 ++ .../DataGrid/SortDataTypeConverter.cs | 24 + .../Components/DataGrid/SortingOrder.cs | 9 + Aurora/Design/Components/DataGrid/down.png | Bin 0 -> 7104 bytes Aurora/Design/Components/DataGrid/up.png | Bin 0 -> 7104 bytes Aurora/Design/Components/Library/Library.css | 4 +- Aurora/Design/Components/Library/Library.xaml | 85 ++- .../Design/Components/Library/Library.xaml.cs | 1 - .../NavigationMenu/NavigationMenu.css | 2 - .../NavigationMenu/NavigationMenu.xaml | 1 - .../NavigationMenu/NavigationMenu.xaml.cs | 1 - Aurora/Design/Resources/unselected.png | Bin 0 -> 49079 bytes Aurora/Design/Views/MainView/MainView.xaml | 2 +- Aurora/Utils/ReflectionUtils.cs | 77 +++ 26 files changed, 1332 insertions(+), 34 deletions(-) create mode 100644 Aurora/Design/Components/DataGrid/ColumnCollection.cs create mode 100644 Aurora/Design/Components/DataGrid/DataGrid.xaml create mode 100644 Aurora/Design/Components/DataGrid/DataGrid.xaml.cs create mode 100644 Aurora/Design/Components/DataGrid/DataGridColumn.cs create mode 100644 Aurora/Design/Components/DataGrid/DataGridComponent.cs create mode 100644 Aurora/Design/Components/DataGrid/DataGridRowTemplateSelector.cs create mode 100644 Aurora/Design/Components/DataGrid/DataGridViewCell.cs create mode 100644 Aurora/Design/Components/DataGrid/IColorProvider.cs create mode 100644 Aurora/Design/Components/DataGrid/PaletteCollection.cs create mode 100644 Aurora/Design/Components/DataGrid/SortData.cs create mode 100644 Aurora/Design/Components/DataGrid/SortDataTypeConverter.cs create mode 100644 Aurora/Design/Components/DataGrid/SortingOrder.cs create mode 100644 Aurora/Design/Components/DataGrid/down.png create mode 100644 Aurora/Design/Components/DataGrid/up.png create mode 100644 Aurora/Design/Resources/unselected.png create mode 100644 Aurora/Utils/ReflectionUtils.cs diff --git a/Aurora.gtk/Aurora.gtk.csproj b/Aurora.gtk/Aurora.gtk.csproj index f5ecc4a..08f7eb5 100644 --- a/Aurora.gtk/Aurora.gtk.csproj +++ b/Aurora.gtk/Aurora.gtk.csproj @@ -79,9 +79,6 @@ ..\packages\taglib-sharp-netstandard2.0.2.1.0\lib\netstandard2.0\taglib-sharp.dll - - ..\packages\Xamarin.Forms.DataGrid.3.1.0\lib\netstandard2.0\Xamarin.Forms.DataGrid.dll - ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll diff --git a/Aurora.gtk/packages.config b/Aurora.gtk/packages.config index bae457d..ec8433b 100644 --- a/Aurora.gtk/packages.config +++ b/Aurora.gtk/packages.config @@ -31,6 +31,5 @@ - \ No newline at end of file diff --git a/Aurora/Aurora.csproj b/Aurora/Aurora.csproj index 9533cee..9a68ccd 100644 --- a/Aurora/Aurora.csproj +++ b/Aurora/Aurora.csproj @@ -10,7 +10,6 @@ - @@ -42,6 +41,7 @@ + @@ -55,9 +55,15 @@ + + + PreserveNewest + + + \ No newline at end of file diff --git a/Aurora/Design/Components/DataGrid/ColumnCollection.cs b/Aurora/Design/Components/DataGrid/ColumnCollection.cs new file mode 100644 index 0000000..1906bcb --- /dev/null +++ b/Aurora/Design/Components/DataGrid/ColumnCollection.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic; + +namespace Aurora.Design.Components.DataGrid +{ + public sealed class ColumnCollection : List + { + } +} diff --git a/Aurora/Design/Components/DataGrid/DataGrid.xaml b/Aurora/Design/Components/DataGrid/DataGrid.xaml new file mode 100644 index 0000000..dc825b6 --- /dev/null +++ b/Aurora/Design/Components/DataGrid/DataGrid.xaml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Aurora/Design/Components/DataGrid/DataGrid.xaml.cs b/Aurora/Design/Components/DataGrid/DataGrid.xaml.cs new file mode 100644 index 0000000..aba83ea --- /dev/null +++ b/Aurora/Design/Components/DataGrid/DataGrid.xaml.cs @@ -0,0 +1,650 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Reflection; +using System.Windows.Input; +using Xamarin.Forms; +using Aurora.Utils; + +namespace Aurora.Design.Components.DataGrid +{ + public partial class DataGrid : Grid + { + + public event EventHandler Refreshing; + public event EventHandler ItemSelected; + + #region Bindable properties + public static readonly BindableProperty ActiveRowColorProperty = + BindableProperty.Create(nameof(ActiveRowColor), typeof(Color), typeof(DataGrid), Color.FromRgb(128, 144, 160), + coerceValue: (b, v) => + { + if (!(b as DataGrid).SelectionEnabled) + throw new InvalidOperationException("Datagrid must be SelectionEnabled=true to set ActiveRowColor"); + return v; + }); + + public static readonly BindableProperty HeaderBackgroundProperty = + BindableProperty.Create(nameof(HeaderBackground), typeof(Color), typeof(DataGrid), Color.White, + propertyChanged: (b, o, n) => + { + var self = b as DataGrid; + if (self._headerView != null && !self.HeaderBordersVisible) + self._headerView.BackgroundColor = (Color)n; + }); + + public static readonly BindableProperty BorderColorProperty = + BindableProperty.Create(nameof(BorderColor), typeof(Color), typeof(DataGrid), Color.Black, + propertyChanged: (b, o, n) => + { + var self = b as DataGrid; + if (self.HeaderBordersVisible) + self._headerView.BackgroundColor = (Color)n; + + if (self.Columns != null && self.ItemsSource != null) + self.Reload(); + }); + + public static readonly BindableProperty RowsBackgroundColorPaletteProperty = + BindableProperty.Create(nameof(RowsBackgroundColorPalette), typeof(IColorProvider), typeof(DataGrid), new PaletteCollection { default(Color) }, + propertyChanged: (b, o, n) => + { + var self = b as DataGrid; + if (self.Columns != null && self.ItemsSource != null) + self.Reload(); + }); + + public static readonly BindableProperty RowsTextColorPaletteProperty = + BindableProperty.Create(nameof(RowsTextColorPalette), typeof(IColorProvider), typeof(DataGrid), new PaletteCollection { Color.Black }, + propertyChanged: (b, o, n) => + { + var self = b as DataGrid; + if (self.Columns != null && self.ItemsSource != null) + self.Reload(); + }); + + public static readonly BindableProperty ColumnsProperty = + BindableProperty.Create(nameof(Columns), typeof(ColumnCollection), typeof(DataGrid), + propertyChanged: (b, o, n) => (b as DataGrid).InitHeaderView(), + defaultValueCreator: b => { return new ColumnCollection(); } + ); + + public static readonly BindableProperty ItemsSourceProperty = + BindableProperty.Create(nameof(ItemsSource), typeof(IEnumerable), typeof(DataGrid), null, + propertyChanged: (b, o, n) => + { + DataGrid self = b as DataGrid; + //ObservableCollection Tracking + if (o != null && o is INotifyCollectionChanged) + (o as INotifyCollectionChanged).CollectionChanged -= self.HandleItemsSourceCollectionChanged; + + if (n != null) + { + if (n is INotifyCollectionChanged) + (n as INotifyCollectionChanged).CollectionChanged += self.HandleItemsSourceCollectionChanged; + + self.InternalItems = new List(((IEnumerable)n).Cast()); + } + + if (self.SelectedItem != null && !self.InternalItems.Contains(self.SelectedItem)) + self.SelectedItem = null; + + if (self.NoDataView != null) + { + if (self.ItemsSource == null || self.InternalItems.Count() == 0) + self._noDataView.IsVisible = true; + else if (self._noDataView.IsVisible) + self._noDataView.IsVisible = false; + } + }); + + void HandleItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + InternalItems = new List(((IEnumerable)sender).Cast()); + if (SelectedItem != null && !InternalItems.Contains(SelectedItem)) + SelectedItem = null; + } + + public static readonly BindableProperty RowHeightProperty = + BindableProperty.Create(nameof(RowHeight), typeof(int), typeof(DataGrid), 40, + propertyChanged: (b, o, n) => + { + var self = b as DataGrid; + self._listView.RowHeight = (int)n; + }); + + + public static readonly BindableProperty HeaderHeightProperty = + BindableProperty.Create(nameof(HeaderHeight), typeof(int), typeof(DataGrid), 40, + propertyChanged: (b, o, n) => + { + var self = b as DataGrid; + self._headerView.HeightRequest = (int)n; + }); + + public static readonly BindableProperty IsSortableProperty = + BindableProperty.Create(nameof(IsSortable), typeof(bool), typeof(DataGrid), true); + + public static readonly BindableProperty FontSizeProperty = + BindableProperty.Create(nameof(FontSize), typeof(double), typeof(DataGrid), 13.0); + + public static readonly BindableProperty FontFamilyProperty = + BindableProperty.Create(nameof(FontFamily), typeof(string), typeof(DataGrid), Font.Default.FontFamily); + + public static readonly BindableProperty SelectedItemProperty = + BindableProperty.Create(nameof(SelectedItem), typeof(object), typeof(DataGrid), null, BindingMode.TwoWay, + coerceValue: (b, v) => + { + var self = b as DataGrid; + if (!self.SelectionEnabled && v != null) + throw new InvalidOperationException("Datagrid must be SelectionEnabled=true to set SelectedItem"); + if (self.InternalItems != null && self.InternalItems.Contains(v)) + return v; + else + return null; + }, + propertyChanged: (b, o, n) => + { + var self = b as DataGrid; + if (self._listView.SelectedItem != n) + self._listView.SelectedItem = n; + } + ); + + public static readonly BindableProperty SelectionEnabledProperty = + BindableProperty.Create(nameof(SelectionEnabled), typeof(bool), typeof(DataGrid), true, + propertyChanged: (b, o, n) => + { + var self = b as DataGrid; + if (!self.SelectionEnabled && self.SelectedItem != null) + self.SelectedItem = null; + }); + + public static readonly BindableProperty PullToRefreshCommandProperty = + BindableProperty.Create(nameof(PullToRefreshCommand), typeof(ICommand), typeof(DataGrid), null, + propertyChanged: (b, o, n) => + { + var self = b as DataGrid; + if (n == null) + { + self._listView.IsPullToRefreshEnabled = false; + self._listView.RefreshCommand = null; + } + else + { + self._listView.IsPullToRefreshEnabled = true; + self._listView.RefreshCommand = n as ICommand; + } + }); + + public static readonly BindableProperty IsRefreshingProperty = + BindableProperty.Create(nameof(IsRefreshing), typeof(bool), typeof(DataGrid), false, BindingMode.TwoWay, + propertyChanged: (b, o, n) => (b as DataGrid)._listView.IsRefreshing = (bool)n); + + public static readonly BindableProperty BorderThicknessProperty = + BindableProperty.Create(nameof(BorderThickness), typeof(Thickness), typeof(DataGrid), new Thickness(1), + propertyChanged: (b, o, n) => + { + (b as DataGrid)._headerView.ColumnSpacing = ((Thickness)n).HorizontalThickness / 2; + (b as DataGrid)._headerView.Padding = ((Thickness)n).HorizontalThickness / 2; + }); + + public static readonly BindableProperty HeaderBordersVisibleProperty = + BindableProperty.Create(nameof(HeaderBordersVisible), typeof(bool), typeof(DataGrid), true, + propertyChanged: (b, o, n) => (b as DataGrid)._headerView.BackgroundColor = (bool)n ? (b as DataGrid).BorderColor : (b as DataGrid).HeaderBackground); + + public static readonly BindableProperty SortedColumnIndexProperty = + BindableProperty.Create(nameof(SortedColumnIndex), typeof(SortData), typeof(DataGrid), null, BindingMode.TwoWay, + validateValue: (b, v) => + { + var self = b as DataGrid; + var sData = (SortData)v; + + return + sData == null || //setted to null + self.Columns == null || // Columns binded but not setted + self.Columns.Count == 0 || //columns not setted yet + (sData.Index < self.Columns.Count && self.Columns.ElementAt(sData.Index).SortingEnabled); + }, + propertyChanged: (b, o, n) => + { + var self = b as DataGrid; + if (o != n) + self.SortItems((SortData)n); + }); + + + public static readonly BindableProperty HeaderLabelStyleProperty = + BindableProperty.Create(nameof(HeaderLabelStyle), typeof(Style), typeof(DataGrid)); + + public static readonly BindableProperty AscendingIconProperty = + BindableProperty.Create(nameof(AscendingIcon), typeof(ImageSource), typeof(DataGrid), ImageSource.FromResource("Xamarin.Forms.DataGrid.up.png", typeof(DataGrid).GetTypeInfo().Assembly)); + + public static readonly BindableProperty DescendingIconProperty = + BindableProperty.Create(nameof(DescendingIcon), typeof(ImageSource), typeof(DataGrid), ImageSource.FromResource("Xamarin.Forms.DataGrid.down.png", typeof(DataGrid).GetTypeInfo().Assembly)); + + public static readonly BindableProperty DescendingIconStyleProperty = + BindableProperty.Create(nameof(DescendingIconStyle), typeof(Style), typeof(DataGrid), null, + + propertyChanged: (b, o, n) => + { + var self = b as DataGrid; + var style = (n as Style).Setters.FirstOrDefault(x => x.Property == Image.SourceProperty); + if (style != null) + { + if (style.Value is string vs) + self.DescendingIcon = ImageSource.FromFile(vs); + else + self.DescendingIcon = (ImageSource)style.Value; + } + }); + + public static readonly BindableProperty AscendingIconStyleProperty = + BindableProperty.Create(nameof(AscendingIconStyle), typeof(Style), typeof(DataGrid), null, + coerceValue: (b, v) => + { + var self = b as DataGrid; + + return v; + }, + + propertyChanged: (b, o, n) => + { + var self = b as DataGrid; + if ((n as Style).Setters.Any(x => x.Property == Image.SourceProperty)) + { + var style = (n as Style).Setters.FirstOrDefault(x => x.Property == Image.SourceProperty); + if (style != null) + { + if (style.Value is string vs) + self.AscendingIcon = ImageSource.FromFile(vs); + else + self.AscendingIcon = (ImageSource)style.Value; + } + } + }); + + public static readonly BindableProperty NoDataViewProperty = + BindableProperty.Create(nameof(NoDataView), typeof(View), typeof(DataGrid), + propertyChanged: (b, o, n) => + { + if (o != n) + (b as DataGrid)._noDataView.Content = n as View; + }); + #endregion + + #region Properties + public Color ActiveRowColor + { + get { return (Color)GetValue(ActiveRowColorProperty); } + set { SetValue(ActiveRowColorProperty, value); } + } + + public Color HeaderBackground + { + get { return (Color)GetValue(HeaderBackgroundProperty); } + set { SetValue(HeaderBackgroundProperty, value); } + } + + [Obsolete("Please use HeaderLabelStyle", true)] + public Color HeaderTextColor + { + get; set; + } + + public Color BorderColor + { + get { return (Color)GetValue(BorderColorProperty); } + set { SetValue(BorderColorProperty, value); } + } + + public IColorProvider RowsBackgroundColorPalette + { + get { return (IColorProvider)GetValue(RowsBackgroundColorPaletteProperty); } + set { SetValue(RowsBackgroundColorPaletteProperty, value); } + } + + public IColorProvider RowsTextColorPalette + { + get { return (IColorProvider)GetValue(RowsTextColorPaletteProperty); } + set { SetValue(RowsTextColorPaletteProperty, value); } + } + + public IEnumerable ItemsSource + { + get { return (IEnumerable)GetValue(ItemsSourceProperty); } + set { SetValue(ItemsSourceProperty, value); } + } + + IList _internalItems; + + internal IList InternalItems + { + get { return _internalItems; } + set + { + _internalItems = value; + + if (IsSortable && SortedColumnIndex != null) + SortItems(SortedColumnIndex); + else + _listView.ItemsSource = _internalItems; + } + } + + public ColumnCollection Columns + { + get { return (ColumnCollection)GetValue(ColumnsProperty); } + set { SetValue(ColumnsProperty, value); } + } + + public double FontSize + { + get { return (double)GetValue(FontSizeProperty); } + set { SetValue(FontSizeProperty, value); } + } + + [Obsolete("Please use HeaderLabelStyle", true)] + public double HeaderFontSize + { + get; set; + } + + public string FontFamily + { + get { return (string)GetValue(FontFamilyProperty); } + set { SetValue(FontFamilyProperty, value); } + } + + public int RowHeight + { + get { return (int)GetValue(RowHeightProperty); } + set { SetValue(RowHeightProperty, value); } + } + + public int HeaderHeight + { + get { return (int)GetValue(HeaderHeightProperty); } + set { SetValue(HeaderHeightProperty, value); } + } + + public bool IsSortable + { + get { return (bool)GetValue(IsSortableProperty); } + set { SetValue(IsSortableProperty, value); } + } + + public bool SelectionEnabled + { + get { return (bool)GetValue(SelectionEnabledProperty); } + set { SetValue(SelectionEnabledProperty, value); } + } + + public object SelectedItem + { + get { return GetValue(SelectedItemProperty); } + set { SetValue(SelectedItemProperty, value); } + } + + public ICommand PullToRefreshCommand + { + get { return (ICommand)GetValue(PullToRefreshCommandProperty); } + set { SetValue(PullToRefreshCommandProperty, value); } + } + + public bool IsRefreshing + { + get { return (bool)GetValue(IsRefreshingProperty); } + set { SetValue(IsRefreshingProperty, value); } + } + + public Thickness BorderThickness + { + get { return (Thickness)GetValue(BorderThicknessProperty); } + set { SetValue(BorderThicknessProperty, value); } + } + + public bool HeaderBordersVisible + { + get { return (bool)GetValue(HeaderBordersVisibleProperty); } + set { SetValue(HeaderBordersVisibleProperty, value); } + } + + public SortData SortedColumnIndex + { + get { return (SortData)GetValue(SortedColumnIndexProperty); } + set { SetValue(SortedColumnIndexProperty, value); } + } + + public Style HeaderLabelStyle + { + get { return (Style)GetValue(HeaderLabelStyleProperty); } + set { SetValue(HeaderLabelStyleProperty, value); } + } + + public ImageSource AscendingIcon + { + get { return (ImageSource)GetValue(AscendingIconProperty); } + set { SetValue(AscendingIconProperty, value); } + } + + public ImageSource DescendingIcon + { + get { return (ImageSource)GetValue(DescendingIconProperty); } + set { SetValue(DescendingIconProperty, value); } + } + + public Style AscendingIconStyle + { + get { return (Style)GetValue(AscendingIconStyleProperty); } + set { SetValue(AscendingIconStyleProperty, value); } + } + + public Style DescendingIconStyle + { + get { return (Style)GetValue(DescendingIconStyleProperty); } + set { SetValue(DescendingIconStyleProperty, value); } + } + + public View NoDataView + { + get { return (View)GetValue(NoDataViewProperty); } + set { SetValue(NoDataViewProperty, value); } + } + #endregion + + #region Fields + Dictionary _sortingOrders; + ListView _listView; + #endregion + + #region ctor + + public DataGrid() : this(ListViewCachingStrategy.RecycleElement) + { + } + + public DataGrid(ListViewCachingStrategy cachingStrategy) + { + InitializeComponent(); + BackgroundColor = Color.Transparent; + + _sortingOrders = new Dictionary(); + + _listView = new ListView(cachingStrategy) + { + BackgroundColor = Color.FromHex("#222222"), + ItemTemplate = new DataGridRowTemplateSelector(), + SeparatorVisibility = SeparatorVisibility.Default, + }; + + _listView.ItemSelected += (s, e) => + { + if (SelectionEnabled) + SelectedItem = _listView.SelectedItem; + else + _listView.SelectedItem = null; + + ItemSelected?.Invoke(this, e); + }; + + _listView.Refreshing += (s, e) => + { + Refreshing?.Invoke(this, e); + }; + + _listView.SetBinding(ListView.RowHeightProperty, new Binding("RowHeight", source: this)); + Grid.SetRow(_listView, 1); + Children.Add(_listView); + } + #endregion + + #region UI Methods + protected override void OnParentSet() + { + base.OnParentSet(); + InitHeaderView(); + } + + protected override void OnBindingContextChanged() + { + base.OnBindingContextChanged(); + SetColumnsBindingContext(); + } + + private void Reload() + { + InternalItems = new List(_internalItems); + } + #endregion + + #region Header Creation Methods + + private View GetHeaderViewForColumn(DataGridColumn column) + { + column.HeaderLabel.Style = column.HeaderLabelStyle ?? this.HeaderLabelStyle ?? (Style)_headerView.Resources["HeaderDefaultStyle"]; + + Grid grid = new Grid + { + ColumnSpacing = 0, + }; + + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) }); + + if (IsSortable) + { + column.SortingIcon.Style = (Style)_headerView.Resources["ImageStyleBase"]; + + grid.Children.Add(column.SortingIcon); + Grid.SetColumn(column.SortingIcon, 1); + + TapGestureRecognizer tgr = new TapGestureRecognizer(); + tgr.Tapped += (s, e) => + { + int index = Columns.IndexOf(column); + SortingOrder order = _sortingOrders[index] == SortingOrder.Ascendant ? SortingOrder.Descendant : SortingOrder.Ascendant; + + if (Columns.ElementAt(index).SortingEnabled) + SortedColumnIndex = new SortData(index, order); + }; + grid.GestureRecognizers.Add(tgr); + } + + grid.Children.Add(column.HeaderLabel); + + return grid; + } + + private void InitHeaderView() + { + SetColumnsBindingContext(); + _headerView.Children.Clear(); + _headerView.ColumnDefinitions.Clear(); + _sortingOrders.Clear(); + + _headerView.Padding = new Thickness(BorderThickness.Left, BorderThickness.Top, BorderThickness.Right, 0); + _headerView.ColumnSpacing = BorderThickness.HorizontalThickness / 2; + + if (Columns != null) + { + foreach (var col in Columns) + { + _headerView.ColumnDefinitions.Add(new ColumnDefinition { Width = col.Width }); + + var cell = GetHeaderViewForColumn(col); + + _headerView.Children.Add(cell); + Grid.SetColumn(cell, Columns.IndexOf(col)); + + _sortingOrders.Add(Columns.IndexOf(col), SortingOrder.None); + } + } + } + + private void SetColumnsBindingContext() + { + if (Columns != null) + foreach (var c in Columns) + c.BindingContext = BindingContext; + } + #endregion + + #region Sorting methods + internal void SortItems(SortData sData) + { + if (InternalItems == null || sData.Index >= Columns.Count || !Columns[sData.Index].SortingEnabled) + return; + + var items = InternalItems; + var column = Columns[sData.Index]; + SortingOrder order = sData.Order; + + if (!IsSortable) + throw new InvalidOperationException("This DataGrid is not sortable"); + else if (column.PropertyName == null) + throw new InvalidOperationException("Please set the PropertyName property of Column"); + + //Sort + if (order == SortingOrder.Descendant) + items = items.OrderByDescending(x => ReflectionUtils.GetValueByPath(x, column.PropertyName)).ToList(); + else + items = items.OrderBy(x => ReflectionUtils.GetValueByPath(x, column.PropertyName)).ToList(); + + column.SortingIcon.Style = (order == SortingOrder.Descendant) ? + AscendingIconStyle ?? (Style)_headerView.Resources["DescendingIconStyle"] : + DescendingIconStyle ?? (Style)_headerView.Resources["AscendingIconStyle"]; + + //Support DescendingIcon property (if setted) + if (!column.SortingIcon.Style.Setters.Any(x => x.Property == Image.SourceProperty)) + { + if (order == SortingOrder.Descendant && DescendingIconProperty.DefaultValue != DescendingIcon) + column.SortingIcon.Source = DescendingIcon; + if (order == SortingOrder.Ascendant && AscendingIconProperty.DefaultValue != AscendingIcon) + column.SortingIcon.Source = AscendingIcon; + } + + for (int i = 0; i < Columns.Count; i++) + { + if (i != sData.Index) + { + if (Columns[i].SortingIcon.Style != null) + Columns[i].SortingIcon.Style = null; + if (Columns[i].SortingIcon.Source != null) + Columns[i].SortingIcon.Source = null; + _sortingOrders[i] = SortingOrder.None; + } + } + + _internalItems = items; + + _sortingOrders[sData.Index] = order; + SortedColumnIndex = sData; + + _listView.ItemsSource = _internalItems; + } + #endregion + } +} diff --git a/Aurora/Design/Components/DataGrid/DataGridColumn.cs b/Aurora/Design/Components/DataGrid/DataGridColumn.cs new file mode 100644 index 0000000..31b0826 --- /dev/null +++ b/Aurora/Design/Components/DataGrid/DataGridColumn.cs @@ -0,0 +1,129 @@ +using System; +using Xamarin.Forms; + +namespace Aurora.Design.Components.DataGrid +{ + public class DataGridColumn : BindableObject, IDefinition + { + #region bindable properties + public static readonly BindableProperty WidthProperty = + BindableProperty.Create(nameof(Width), typeof(GridLength), typeof(DataGridColumn), new GridLength(1, GridUnitType.Star), + propertyChanged: (b, o, n) => { if (o != n) (b as DataGridColumn).OnSizeChanged(); }); + + public static readonly BindableProperty TitleProperty = + BindableProperty.Create(nameof(Title), typeof(string), typeof(DataGridColumn), string.Empty, + propertyChanged: (b, o, n) => (b as DataGridColumn).HeaderLabel.Text = (string)n); + + public static readonly BindableProperty FormattedTitleProperty = + BindableProperty.Create(nameof(FormattedTitle), typeof(FormattedString), typeof(DataGridColumn), + propertyChanged: (b, o, n) => (b as DataGridColumn).HeaderLabel.FormattedText = (FormattedString)n); + + public static readonly BindableProperty PropertyNameProperty = + BindableProperty.Create(nameof(PropertyName), typeof(string), typeof(DataGridColumn), null); + + public static readonly BindableProperty StringFormatProperty = + BindableProperty.Create(nameof(StringFormat), typeof(string), typeof(DataGridColumn), null); + + public static readonly BindableProperty CellTemplateProperty = + BindableProperty.Create(nameof(CellTemplate), typeof(DataTemplate), typeof(DataGridColumn), null); + + 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); + + public static readonly BindableProperty HeaderLabelStyleProperty = + BindableProperty.Create(nameof(HeaderLabelStyle), typeof(Style), typeof(DataGridColumn), + propertyChanged: (b, o, n) => + { + if ((b as DataGridColumn).HeaderLabel != null && (o != n)) + (b as DataGridColumn).HeaderLabel.Style = n as Style; + }); + + #endregion + + #region properties + + public GridLength Width + { + get { return (GridLength)GetValue(WidthProperty); } + set { SetValue(WidthProperty, value); } + } + + public string Title + { + get { return (string)GetValue(TitleProperty); } + set { SetValue(TitleProperty, value); } + } + + public FormattedString FormattedTitle + { + get { return (string)GetValue(FormattedTitleProperty); } + set { SetValue(FormattedTitleProperty, value); } + } + public string PropertyName + { + get { return (string)GetValue(PropertyNameProperty); } + set { SetValue(PropertyNameProperty, value); } + } + + public string StringFormat + { + get { return (string)GetValue(StringFormatProperty); } + set { SetValue(StringFormatProperty, value); } + } + + public DataTemplate CellTemplate + { + get { return (DataTemplate)GetValue(CellTemplateProperty); } + set { SetValue(CellTemplateProperty, value); } + } + + internal Image SortingIcon { get; set; } + internal Label HeaderLabel { get; set; } + + public LayoutOptions HorizontalContentAlignment + { + get { return (LayoutOptions)GetValue(HorizontalContentAlignmentProperty); } + set { SetValue(HorizontalContentAlignmentProperty, value); } + } + + public LayoutOptions VerticalContentAlignment + { + get { return (LayoutOptions)GetValue(VerticalContentAlignmentProperty); } + set { SetValue(VerticalContentAlignmentProperty, value); } + } + + public bool SortingEnabled + { + get { return (bool)GetValue(SortingEnabledProperty); } + set { SetValue(SortingEnabledProperty, value); } + } + + public Style HeaderLabelStyle + { + get { return (Style)GetValue(HeaderLabelStyleProperty); } + set { SetValue(HeaderLabelStyleProperty, value); } + } + + #endregion + + public event EventHandler SizeChanged; + + public DataGridColumn() + { + HeaderLabel = new Label(); + SortingIcon = new Image(); + } + + void OnSizeChanged() + { + SizeChanged?.Invoke(this, EventArgs.Empty); + } + } + +} diff --git a/Aurora/Design/Components/DataGrid/DataGridComponent.cs b/Aurora/Design/Components/DataGrid/DataGridComponent.cs new file mode 100644 index 0000000..fc54ac5 --- /dev/null +++ b/Aurora/Design/Components/DataGrid/DataGridComponent.cs @@ -0,0 +1,12 @@ +namespace Aurora.Design.Components.DataGrid +{ + public static class DataGridComponent + { + /// + /// You should call this method for loding the assembly + /// + public static void Init() + { + } + } +} diff --git a/Aurora/Design/Components/DataGrid/DataGridRowTemplateSelector.cs b/Aurora/Design/Components/DataGrid/DataGridRowTemplateSelector.cs new file mode 100644 index 0000000..f83e06c --- /dev/null +++ b/Aurora/Design/Components/DataGrid/DataGridRowTemplateSelector.cs @@ -0,0 +1,28 @@ +using Xamarin.Forms; +namespace Aurora.Design.Components.DataGrid +{ + internal class DataGridRowTemplateSelector : DataTemplateSelector + { + private static DataTemplate _dataGridRowTemplate; + + public DataGridRowTemplateSelector() + { + _dataGridRowTemplate = new DataTemplate(typeof(DataGridViewCell)); + } + + protected override DataTemplate OnSelectTemplate(object item, BindableObject container) + { + var listView = container as ListView; + var dataGrid = listView.Parent as DataGrid; + var items = dataGrid.InternalItems; + + _dataGridRowTemplate.SetValue(DataGridViewCell.DataGridProperty, dataGrid); + _dataGridRowTemplate.SetValue(DataGridViewCell.RowContextProperty, item); + + if (items != null) + _dataGridRowTemplate.SetValue(DataGridViewCell.IndexProperty, items.IndexOf(item)); + + return _dataGridRowTemplate; + } + } +} diff --git a/Aurora/Design/Components/DataGrid/DataGridViewCell.cs b/Aurora/Design/Components/DataGrid/DataGridViewCell.cs new file mode 100644 index 0000000..f8208f5 --- /dev/null +++ b/Aurora/Design/Components/DataGrid/DataGridViewCell.cs @@ -0,0 +1,152 @@ +using Xamarin.Forms; +namespace Aurora.Design.Components.DataGrid +{ + internal sealed class DataGridViewCell : ViewCell + { + #region Fields + Grid _mainLayout; + Color _bgColor; + Color _textColor; + bool _hasSelected; + #endregion + + #region properties + public DataGrid DataGrid + { + get { return (DataGrid)GetValue(DataGridProperty); } + set { SetValue(DataGridProperty, value); } + } + + public int Index + { + get { return (int)GetValue(IndexProperty); } + set { SetValue(IndexProperty, value); } + } + + public object RowContext + { + get { return GetValue(RowContextProperty); } + set { SetValue(RowContextProperty, value); } + } + #endregion + + #region Bindable Properties + public static readonly BindableProperty DataGridProperty = + BindableProperty.Create(nameof(DataGrid), typeof(DataGrid), typeof(DataGridViewCell), null, + propertyChanged: (b, o, n) => (b as DataGridViewCell).CreateView()); + + public static readonly BindableProperty IndexProperty = + BindableProperty.Create(nameof(Index), typeof(int), typeof(DataGridViewCell), 0, + propertyChanged: (b, o, n) => (b as DataGridViewCell).UpdateBackgroundColor()); + + public static readonly BindableProperty RowContextProperty = + BindableProperty.Create(nameof(RowContext), typeof(object), typeof(DataGridViewCell), + propertyChanged: (b, o, n) => (b as DataGridViewCell).UpdateBackgroundColor()); + #endregion + + #region Methods + private void CreateView() + { + UpdateBackgroundColor(); + + _mainLayout = new Grid() + { + BackgroundColor = DataGrid.BorderColor, + RowSpacing = 0, + ColumnSpacing = DataGrid.BorderThickness.HorizontalThickness / 2, + Padding = new Thickness(DataGrid.BorderThickness.HorizontalThickness / 2, + DataGrid.BorderThickness.VerticalThickness / 2), + }; + + foreach (var col in DataGrid.Columns) + { + _mainLayout.ColumnDefinitions.Add(new ColumnDefinition() { Width = col.Width }); + View cell; + + if (col.CellTemplate != null) + { + cell = new ContentView() { Content = col.CellTemplate.CreateContent() as View }; + if (col.PropertyName != null) + { + cell.SetBinding(BindingContextProperty, + new Binding(col.PropertyName, source: RowContext)); + } + } + else + { + var text = new Label + { + TextColor = _textColor, + HorizontalOptions = col.HorizontalContentAlignment, + VerticalOptions = col.VerticalContentAlignment, + LineBreakMode = LineBreakMode.WordWrap, + }; + text.SetBinding(Label.TextProperty, new Binding(col.PropertyName, BindingMode.Default, stringFormat: col.StringFormat)); + text.SetBinding(Label.FontSizeProperty, new Binding(DataGrid.FontSizeProperty.PropertyName, BindingMode.Default, source: DataGrid)); + text.SetBinding(Label.FontFamilyProperty, new Binding(DataGrid.FontFamilyProperty.PropertyName, BindingMode.Default, source: DataGrid)); + + cell = new ContentView + { + Padding = 0, + BackgroundColor = _bgColor, + Content = text, + }; + } + + _mainLayout.Children.Add(cell); + Grid.SetColumn(cell, DataGrid.Columns.IndexOf(col)); + } + + View = _mainLayout; + } + + private void UpdateBackgroundColor() + { + _hasSelected = DataGrid.SelectedItem == RowContext; + int actualIndex = DataGrid?.InternalItems?.IndexOf(BindingContext) ?? -1; + if (actualIndex > -1) + { + _bgColor = (DataGrid.SelectionEnabled && DataGrid.SelectedItem != null && DataGrid.SelectedItem == RowContext) ? + DataGrid.ActiveRowColor : DataGrid.RowsBackgroundColorPalette.GetColor(Index, BindingContext); + _textColor = DataGrid.RowsTextColorPalette.GetColor(actualIndex, BindingContext); + + ChangeColor(_bgColor); + } + } + + private void ChangeColor(Color color) + { + foreach (var v in _mainLayout.Children) + { + v.BackgroundColor = color; + var contentView = v as ContentView; + if (contentView?.Content is Label) + ((Label)contentView.Content).TextColor = _textColor; + } + } + + protected override void OnBindingContextChanged() + { + base.OnBindingContextChanged(); + UpdateBackgroundColor(); + } + + protected override void OnParentSet() + { + base.OnParentSet(); + if (Parent != null) + DataGrid.ItemSelected += DataGrid_ItemSelected; + else + DataGrid.ItemSelected -= DataGrid_ItemSelected; + } + + private void DataGrid_ItemSelected(object sender, SelectedItemChangedEventArgs e) + { + if (DataGrid.SelectionEnabled && (e.SelectedItem == RowContext || _hasSelected)) + { + UpdateBackgroundColor(); + } + } + #endregion + } +} diff --git a/Aurora/Design/Components/DataGrid/IColorProvider.cs b/Aurora/Design/Components/DataGrid/IColorProvider.cs new file mode 100644 index 0000000..3cc9825 --- /dev/null +++ b/Aurora/Design/Components/DataGrid/IColorProvider.cs @@ -0,0 +1,8 @@ +using Xamarin.Forms; +namespace Aurora.Design.Components.DataGrid +{ + public interface IColorProvider + { + Color GetColor(int rowIndex, object item); + } +} diff --git a/Aurora/Design/Components/DataGrid/PaletteCollection.cs b/Aurora/Design/Components/DataGrid/PaletteCollection.cs new file mode 100644 index 0000000..770c8d9 --- /dev/null +++ b/Aurora/Design/Components/DataGrid/PaletteCollection.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using System.Linq; +using Xamarin.Forms; + +namespace Aurora.Design.Components.DataGrid +{ + public sealed class PaletteCollection : List, IColorProvider + { + public Color GetColor(int rowIndex, object item) + { + if (Count > 0) + return this.ElementAt(rowIndex % Count); + else + return default(Color); + } + } +} diff --git a/Aurora/Design/Components/DataGrid/SortData.cs b/Aurora/Design/Components/DataGrid/SortData.cs new file mode 100644 index 0000000..1552d09 --- /dev/null +++ b/Aurora/Design/Components/DataGrid/SortData.cs @@ -0,0 +1,51 @@ +using System; +using Xamarin.Forms; + +namespace Aurora.Design.Components.DataGrid +{ + + [TypeConverter(typeof(SortDataTypeConverter))] + public class SortData + { + + #region ctor + public SortData() + { + } + + public SortData(int index, SortingOrder order) + { + Index = index; + Order = order; + } + + #endregion + + #region Properties + public SortingOrder Order { get; set; } + + public int Index { get; set; } + #endregion + + public static implicit operator SortData(int index) + { + return new SortData + { + Index = Math.Abs(index), + Order = index < 0 ? SortingOrder.Descendant : SortingOrder.Ascendant + }; + } + + public override bool Equals(object obj) + { + if (obj is SortData) + { + SortData other = obj as SortData; + return other.Index == Index && other.Order == Order; + } + else + return false; + } + + } +} diff --git a/Aurora/Design/Components/DataGrid/SortDataTypeConverter.cs b/Aurora/Design/Components/DataGrid/SortDataTypeConverter.cs new file mode 100644 index 0000000..baf0d0d --- /dev/null +++ b/Aurora/Design/Components/DataGrid/SortDataTypeConverter.cs @@ -0,0 +1,24 @@ +using System; +using Xamarin.Forms; + +namespace Aurora.Design.Components.DataGrid +{ + public class SortDataTypeConverter : TypeConverter + { + + public override bool CanConvertFrom(Type sourceType) + { + return base.CanConvertFrom(sourceType); + } + + public override object ConvertFromInvariantString(string value) + { + int index = 0; + + if (int.TryParse(value, out index)) + return (SortData)index; + else + return null; + } + } +} diff --git a/Aurora/Design/Components/DataGrid/SortingOrder.cs b/Aurora/Design/Components/DataGrid/SortingOrder.cs new file mode 100644 index 0000000..78c9520 --- /dev/null +++ b/Aurora/Design/Components/DataGrid/SortingOrder.cs @@ -0,0 +1,9 @@ +namespace Aurora.Design.Components.DataGrid +{ + public enum SortingOrder + { + None = 0, + Ascendant = 1, + Descendant = 2, + } +} diff --git a/Aurora/Design/Components/DataGrid/down.png b/Aurora/Design/Components/DataGrid/down.png new file mode 100644 index 0000000000000000000000000000000000000000..3a359e82cce9634fc8738fadbf6269fe780ba10b GIT binary patch literal 7104 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 + + + + RowHeight="30" + BorderColor="#3a3a3a" + BorderThickness="0" + HeaderFontSize="14" + HeaderHeight="45" + HeaderTextColor="White" + HeaderBackground="#222222"> - - - 15 - 13 - 20 - - + + + + + + + + + Width="2*"> + + + + + + + Width="0.95*"> + + + + + - + Width="1*"> + + + + + + + + White + + - #F2F2F2 - #FFFFFF + Transparent diff --git a/Aurora/Design/Components/Library/Library.xaml.cs b/Aurora/Design/Components/Library/Library.xaml.cs index f093141..dde5a28 100644 --- a/Aurora/Design/Components/Library/Library.xaml.cs +++ b/Aurora/Design/Components/Library/Library.xaml.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using Xamarin.Forms; -using Xamarin.Forms.DataGrid; using Aurora.Models.Media; namespace Aurora.Design.Components.Library diff --git a/Aurora/Design/Components/NavigationMenu/NavigationMenu.css b/Aurora/Design/Components/NavigationMenu/NavigationMenu.css index c75df32..a320db9 100644 --- a/Aurora/Design/Components/NavigationMenu/NavigationMenu.css +++ b/Aurora/Design/Components/NavigationMenu/NavigationMenu.css @@ -14,7 +14,6 @@ ListView { #GroupCell Label { color: lightgray; - background-color: #232323; font-size: 12; font-family: Courier New, Courier, monospace; font-style: italic; @@ -23,7 +22,6 @@ ListView { #ItemCell label { color: white; - background-color: #232323; font-size: 15; font-family: Courier New, Courier, monospace; font-style: normal; diff --git a/Aurora/Design/Components/NavigationMenu/NavigationMenu.xaml b/Aurora/Design/Components/NavigationMenu/NavigationMenu.xaml index c401b23..de69dae 100644 --- a/Aurora/Design/Components/NavigationMenu/NavigationMenu.xaml +++ b/Aurora/Design/Components/NavigationMenu/NavigationMenu.xaml @@ -11,7 +11,6 @@ Pl=Z+$ zEymxdHaQ34zZP05s3}m?!yBwK#~0zx46fQrG%CA}ryqadJ9$`JjiS7_P*eaep2A-R z^ih=iE{Ym3rzq(NidyXyQ=+vG|FHOkiqb*qANl|I@|4^78)m1&hOYSU!}R|szOt3Y zB^6?DB?e{@)S={C>(89l4Py^x8y{6HV`W!gsk_9m_JQDo;2bL`3(Nt7?VJ7S1;^HMzSIXs}(v9`aqdhfuA|umgW@b3zTHH-6PMw zSL+`<82IJO7u~#5N2*`E*tTPb`oo70$(8tfeu{EZUKYenu`B20<+XQ|dfK*Ro3uW% zyfHU9{<-|@Kdp#=le4$@l~ilQ?;AWk;lK5xzt8jP>NLAgdFciZ@4vnyoZ|BBb?l`3 zyZeW>c2fa26%rOx2Hhjw&xSr^85Ot>>e;sysuMF)H0x#^6T>UVd|{)Qyg6+s`KsDiubhkQ z+mgq|-0VN)9qRAzpZYya{$jzBWf37)9D$Qfh#u#nlmzR`*iIj z7L_^%is1$g_hQ0^I(U1Rh}*Z0-M#Vk>!~cGBK6|p;$;4(_1p9^Qx~&wr=ETr<^MO; ztg<4QOIY#KVrq>N-fB|K)bw6-cz81TjajAXI&nM6(OdWK&D~`y4bU0&+Lx}E6=l<$ zp43`ko8j@ZHQlHvdnE@4*MHL9J9FlY}AM}ix?HJ`M$BS!=g5PtCZB=gJ;y$)S4fj ztWi~3pe}SQKXv8Gm0>q;#$RMxm#%POu}%Bqhgga7tHo5z9`f5Nj~^eqcNpd!^!M3r zT4qq{IV{f0DrpHLuxW@t7bRxv@r8fmMuqh^F5z*K{P;=N2H0mufo+QoEKD%mwmweI zZ2Hg7J-loq#VZArQ?(Km1;ejO*nUtIIhL=ftIH{{jv85wGpaJ%Qvdt=TODof(2(`} zZKPMR@7lC!Q&XxIe}R45pXZxPu|7^aipd$*GKu0KhG0Nqo%i@Y0?)sjy#D5RXI z4i3=i7o70a9!)}y+wiW4rdwpl?N6K6jFJo}JCWLpW?9A`6XUpZRhT4mjj~o%@Wo9yj z&*+lJBpg_R)rDJpq0HCf`h~@6(c;Cfy>-p_&0g2;uo|1pnGW7s9N?uwyH8*ICOSN){3t(?~aD>Ce z^{rUR_b6N4Nr#UB}NSt42Px$f6cz!n)yx4g(#fMes_c;>7{9 z`x8WCUg z*;}PHTx1XL5-KwkK`7d>!my~_NYGr6tLWiTC}aJ8bNS!z(NTLWLvWG-ol+r*S9g>g_Uv%K>pj+&fT#-V z5XOctEQg7f#`*lZqIhF{7P3-g$O208I=m{w|KA+^|>vH8*|dSX?~(1Y4COc46kk@aOWO!JNwM z7Spq8(-XrI*aq{2h=?`Bov`VtNZE%UF79%L{mK@c`F(oA|KD`n=d;86dG~uax$#i) zOp_-UJo29%G=sS(z{4-C-H$s|UxktZ|^^<(+txOiDePIW+bq=w%(#%4G0j!zSo&77!@@H#bo^ zK0DDF9l|)NdS#^m=el)gzwpmvF5*e|6BCbS8i>OBw*kl@b8XYQ9~jKJ_5S@sSJMw( zS;?||xxTS+`<41$$&eE#PyQQqCm8AS<;#^kW4&L$KEAYk!(2`0+m|mVYoqlEz{KL0 z@k&3)%-jyoRYm^LhTXs-!(wBz_?1HX`rakJe)C2b@nac}Wc;;j*ElxdqTRmw3uIjp zd~84F9)~}f0=8)iA$7a{n;rJI{r)C0Igzpy*u7gDnN;WRuWv^aXp8QM80m3s)72z@ zEVMJcBdkAk@c3L0|Gs_uHZQAk1!Rz0{R3Fcs{Y>o)>6+LkKxZ**e7coA%gE+^2hyW z|Io9SU00^tP`lx?i)=dZ_5)vfxdR+=E-@Uzdl?P;-zObSQsz3Ep{It}se}K}|Cn{` zC=k$5^7M4wt;_D0Tm74x9YUTd@EkTJC=-CNwa`8qS>`?c$HzKjA!=ru>U_JxtWm*{X$H~$(#OcEjU{0VP9QSlX0xTMv%o7 zA)bqu_w6}nO4@rYwG<2B2s(=;x0aoG1V_qYTPIFlH<^D^p!-165xh{M!2(HPSmUDI zo=q)WjQKW=^OoQT9R za`y&KGa}>?`#Zn~VvsnaMetsyW3_j8dd7KuVMZi)>&9vDvS&0^@j5p_a=@AzGev&0 zQ*enjOCCvf6QF^OzeC5GUpfA%si^4q`Bn6Ljj4?bYkoE;>3o|FrTY>|38FO>0`Mzo7(_ z)4ZpCUm_CiFXKgB8{o5Zbf2x=S(%BtVPJB!C%K1@DJUo?&9vNGP}%j->9+*g-PvIh zbwO+LZNh;|?LcBNLLXJax4+A&oO}J7yY2`|6Nln&tFXJOceWk?}2pz*FS~n)E#;&-DVyhiM!kR!=S!C?wM5P;1As6{p@bYE> zep>f6Bm`f*+H+uW@5aHn0oOBk||ZfshzV_{1fz)oq0uC59W z4*n9qQbBm<&UzC-hVbo%_s{(PZcV_Xnwmwiq`ELX{J^DU&G8BsycVn=_?GYBw{PEy zH~5U4yXQA$?NMKSr26^uzVoa*G&A(Fn({1E2vh}F>aJSx0p(F#sreH|5#z_21lS@L zghfVLORr+oOj5oxMvRo?)Td9MdigD+v18o|1lUbC99V7*??_JM3(!r|K7{<%a%i>5 z0~B7uqM}*=^a~CKmd(ugNQj9Y{oPyN5+mh0hQk%!zrVw6`@);BoBpJ`rrN;AXX+Nx z5XhM}+J4A%j`JSa3ZU`CjdNjuT)3lWUxNbN>*$5WY?AB?S*-rQaGD_=ukZcsj=tOH zGrgleEP+fcV(g4?`Jc;hh9uRHOj>hpBaWt-Eb{8k3IhULQL4OV*w7_Fz`bSty)58c zt3N+J9V_+7>OZ_|^S*t?p6$+;<`9)KP$llGXADo&T(GLPuFj*==eHURy~*r@1N|t;63(E=_rci zd;Sb6i1Mt(*@Fa(aZ9_UzJLE-wdP!0;H680Gr#Ng|HI@3j-966-Q7IT85rm=bGJpX z-(>fa*ta#9DUll@B=nfGF*zxP@HmsVC&fhRaD|SIO?v;~kqbCU+p)fPHm&(v>l*_O2{i=> z{2A^Xo}2Fc_kkqEva)@R&RzV+j~_?fd8fp4IGcc2W@cud2nK~6A|h{NrCgIMX8#zy zjgh+DUr-IWNN`{I%&*!QGd6?sG`5Asu#bt`8nW*$ESF6Mn1AcWGbx{@o#gh(;%*wC za|tp!*SdAJ3Tw>M;7KLO@`-@g_Z=%|^<+GU_VO~zlDhl&vy1)6y5FXnb*F7>ewry9 zvcS6WVy_q9VXf42e1tcE6(&r5y{+-QK6gJNU300Y<9L6g(v>S$c#Ih)ujc3PC1{sm zX%sJBb47tYk|_W0nx6T_bu>*osMnA0r6z6_8XY}YF*h~nJ&=|{f-bgik$+fUh3|Aa z!V}M72BDka14;n>xW2V+!tpd7Sib*3%?5vC&?{x@DFw1;SIqqWR`W_a#RKoFDk*IA z+PA*Iq2pMKvFmkG79eq5zp#Z03cYu4NIh!r5e`B1Ce)H)adD2)D_If{guDl{ib%m@ zx*>oMFpIH$Zg#puY5kdlh!+eTm-#**KA8B=BKc(8MUD1cVI^n-q|oVacg;}WJ0Ht6 zXUJKn@Y5}vFz&A1Q+1bcwELwnz61lp;g(qUDl zCx+WhO7h9ukvhPptx#l%JjF zW$Dhck@NS?4oM-Yy>a8=)KpcyMnE)7*z~Tc_tv|Q8QF7x{r=q%=RapiY9~@qzImhC zcuP|r(YLvBZhYtdv4#V|moIm@FJ@xLZROv@%Cz7J_*&MoZ9=8gh{Aw=KM-EMU5n*4 zrTk_dlZuHfElSq6n zx1M7mLQ*=ZV`ir(^s|l?NJcQ22fdA!C_VY&+PetRlld04s~Vl179;zS&}8b>y$GRw z9#VE<7X7ysV7g^nRXt)y9Kj5{D0Jwc zn?-#SN}3OEa-HA+$0>o18--8gp!=trGel?PNm~aZ|uOQM}l`t83P{eA{eS! z->kXC%s&gXYNPXrAaGhE34ZX`(UQfJF!_-L;L68{vN>B+Bg~~)<{r?3SV~aAy5k_y z5gK{yDEW=p>u0FOJjY?sHlVYTd%85H#`+WAB`Q7o#WJ!Hug4FF@99|jQ~YOpaibgO zOty2+3wTbcThDcgbgOswd5o!m)!zWa5!MS7LwM3q&|yiXc^0(;*tB<8>D$5eT?;sE zs%nACzskaBV}yD6@M?r^d2(UNqgQLFNk9{oc0e!dnaR=DZ{LdXE(s-Rqa1Mw<-o$6 zpn%m#NjszD{435js!3P_7$zqMmJ#aBv9p4E_o>SREjjg17Eo()!8noQdS{zco(y}9 z4&nGkxD1reeP6Eb{O-PDWF_8f5uw`P%PFLc0hg5A6PQ0a>BY8YmpmzG5j-T#!I3+G zr1nI3;g)iFpsk~$R>N!!BPaVxjQr4{L!;8noFGMn9w5XO!!#20G7XMPD<8J~TvmK> z8E-l`-q$^&P66Qah2-QqWA~lOySRKqb`b08s1T0#+!79%pe@spE6PqY26c(@QcQZ; zgC(e&U5xUr6e7h_fit4;qg5iu9^iPT!mKGKnTysG>Pk=xnjGUSh^AWrPEVv=@hHN@$7T3*-DFq-2 zi=oRa_{R`WU0TC7-Zgf)B0JT`ze9jIW&w+sQ#ewD?F78+q$}5gP5k`sKMPt09@eba zq0tz3PEqE!NV-8??hSLgbLWnQwED}fDDFP{P1~EC{aH{}!DxAo#>T0srx!k5wP1N4 zBJXZqfv=ok=}{jw-Q0LUx7fwPw2z_c1Q5k z=7L2xqoM}>{A|1HnlzgU9=_yfVcS?=;*E4*)w0|L@=TuqA*WkybF8r{)O&k*1s`nQ zvSr{=y=)`=sm6Av(_&7WuBEc5(I;U49|)zd#Jtv@v%hBjSyfbZUDZ4k?c;`OZ?Ltm zU%uSMD|m`?tM`* z0Nc=)mU2&R_OAChr2qK^lzCjlmn1j{ZZ8E=W6ENFL0el zN*ff01aFNuDeRH%GZ9)xr`Rsj*baw=?=Tto1FFy3+B!MW;H@(c;r$5K11a*1Rg|i- zC3LGS2pn&)7kBR7wUiENCP{>uV@oP3#f+ zSDQ(~%ma$xQg6>p|163{U7hYZ{Q1Puyx|8aDT8q14~<1h zM2)R1ZJA2N3Ktx=a1o$Ojo{UvEf598T^ru*Qbj zyt^MH`)|f|i#wB)YU+yJd5<1-EZN|r2}~)@Tdl06rByOqF+KL2LnHOnt59MjRZ?z! zH)VV#oq+xS>A;oxCH1)XdF7h=j2^;iI&BZQDW9Nt_#>ExwiJyGv%u=u5Q15`#caaB z;JmsjNbz+cq`aN2_n%8d9Mkyw_b=9yg1?&rZYQKh2&?&i7O~7CyHC4|Pz<)_SzN`Q zSYx%OurL#^?w~SrM(TVW3E4~5d&#?ge%3y*)YjI-{38id1@Z@_9I_niG>*Nd`P7jQ+b=HY9&b9067S>Io;1XYL4 z#juF5yLWpLh7uh>Y(N4KZFJ6Dv370R^iZh=^5}~hJL2wHeFLiQtaS{5EyHcg%cq|;RxW&XXmXs>6hW8K`%Kx<5;>=|QxGD22 z!if@Vc@e^ED;<1vM@io%!Z9Pq_DC}7C1^g|CajC;1`1Q!(w9Wq=UtX-Q#j)ykt)V;|KFs5}Bj0@yGKUbHvRpA39Ysj9m-HvavT* zWrs5<(h-lgZQ1g|jYk+Zp8+T2mhsrmvESeV?RtD~N%nM(|7>mfP|2VhK}yb<4LI;D z!$*o5aBWTxhX2;=Iz@(6)2y)r}|ThLoct+ zxBH|`fCF$<)##G*NTdp+e0P`_>L{+rU!8B?riZGkkbAFH73*4xT9kkM+2V=p(xETu zn@ly4FVybsGek7|X0TAobEWlCIgUQ!dw$y#lI837@(QF9{e>7B0zU7J8v31h z#)mrE3{i{|kSH!99EgOFfl3ugcVQB@LXbcw6AJ+sBt`>D)VPJk>peQHMkskiM~<9H zit_rDY51s}0KM6%@#MsX1*JnJDln1sr_Y{AnJQEzYVvmh$yfaZ#qT#Ws??};KD?&q z9qw40e3GIj4M-M6oogT*LYweU%I$+aO|E7J+S$53q%}{2Sog2DC8?D=W?-^=ohM;JGF1 z8(=gY;1ZUtS-~Em`HYk!r2wQYK%A$gl^fDD6V4M^$-V!5&?emJX5{|^ZWqP^Iu3w_ z&_W-9)Z+76oHlFFAkl5=-h7lU?FcFKUR>wU05+SD5v({+g#kQq2vmE{a=DoXoMh_KZ3rx%a-=LPLF}t`nyMm1@I7zJ(61*xK}<|)*(HWW z5B>l7p$t?2AHIO&z$6=o&17}hR-JZP-zgzs;aco4I|oN15&V!;zHxCvF`0NP(fPQj z!y_8G%u-re^Kx+Tdl0@v?hHvJn#?4si5|jk2n!05*x-bGX$9L0<@p9MZ~ zN_)o$Yic|@T%Lk!UH2`DJMl`whwRo6=-$JTJ1EF+goJ@Yk*K-=Av#q%DR__VhwX$R z2K|NjRt7$)!=ugK8?{=*`ll%{LQ7L%yNT{g8^n3}g>*9wv`*H9G+W#?QM`rIOA)iI zo3c)GMT?5Bv0f!Sa1oqN{w)GmH6r30iF$ue!PcK{OL(HGwzs=ZxXbb?_s1 zAoS>vl_SP2&4fDpH`6Ppx}uwd)5fa+3z2EL{^1XjbnQ7N7@p#CN<|A8H1J#s~Q5PWVC3pT2hoKue4A3d9q( z%NrPZYqO-~_P;NroK0HFd+(hUYP57BTGl+;qPq0KvU-vlG9#y=75Du^5&_r-eLp{0 z9mN<97O}dh!4d*m#y%K1A`&+cCs0H4gR`?U@EXu*1Z%`w*kB-I)Z!q0Id< z$z~ZuyZ-3c$CEdTkx3|?g>NXPT_ESH)4K{*-Xs_A2XN)->CP8wlFR~{D>-m+sVIJn zO3?agAalu&yjrjO==4+Ax^?TTpYIYcAugSSRdCDtJO*{}`r&%@E41r6-21)rWvm+b z8bukk5!eVZ+?=6*L(qVt*qfk?bwN^yefwJdsWZ=YXxN^ez7jP)l3Q8C)CZ7!-ATds zt+y9`=|tok0z{E(zgW)@q}H{ets@*gY9dVxLFh62>jiBgoC02!%(`En3TA^L(E1#5h4vc5Qfk}RyDd& zsOcu@G$ZC^RA@(B?s-j(?Tc$`(M7XEBOI-nn^6Z8>l-@mSGr_r0UNtRL55}*uX|}1i~Hr* zkc4u;Pm7q8G~oi5-)|*s0YM3&M!clU6P+&3FK%qefxbe&gUdH%6GR)Zvul#14{D_z z(1bYJmSZM2i!vQf8wL*_K$Dj4!GrU6aD)IC10u3xEuc2frDsWUZzA_7kwOBz#n$GH zmubA`*L!s_(6zH`0V~$8&jut`!by4ZnDU|S zcnPv~$P{wH>-u^i9X>)c!8ElI4!qtYic2mbv{_sESx<}8r=vnvvcvKT#R1cE_F210 zsA=OD+`$9D(S=veuN|956rD7klynpX`#vF4b3T2aq|zar{g`(4&ktAy-$6x18*J`C zL&AcZ$c+IsUdGVdw+Xeem7o6^ZlH^}CyMjFk zM2C^^)~!bfet+C};>R!hhoIIT$I5sntNzOdxr&~d`y_`=%0okqF?@774FWOwA?hH~ z&<2+5)Ol-BmVzXr7!#0#?k6lA>MJXX2NiH)@$}yx23Z&jsFwlChWsA2D`}O1rzhze z1=H-)09*9wO$2Kgy5FnpY(~6&fc?^e-BLc8UZY>?P;xb+2LZ?a6pb%AAkm^j7&atm z8j;xU+u>A;$R(<@8)r}U<1Z}eFFQgSy2!fM+>DL=2_M&oDeUI0evFPKl3Ss|$9ulFEpU*912*==dh)WmQOPDvLbnWXyw z>YHT9Z^E8-Rh=V01uZ-Ppe4?`An1AWDFwUt4~{tCO*sc{bZ@9Fd-n7x0q~SUmAeU@ zOf_;Ww~!8oc-9BLRVPl?S2Bc6n{$A#03oIbFihIz>*anSMHsFM$|6g0xa_BZxCrz? z25WKSOe9@C5EDSP7Chkj!S=9dm&96!flk?11do+A-3O2_b`iM&}K1Mth+AjsI*T&lPw4 zoC!=v8lY8WE-Vd_ez|X?Y5`sItJ#$f92m9NI`sbi`|~fn19@vL(h+2nlXzhQCf56o zX*G&Eg&X|hJqQwM@UvSZ`gqq6ft#eA|FK4c&1hQv2|1IbSRC!ttak^`;9_PL_nQVN ztJ{zhz{*61oKOWJz8C$9#0v!1V3%2eF-n1do0`&eV5iBzTBIU8mT&b$)R8@2bICcd zMa5`Dp2zW`$p~6eQm$J_(64eqz#PJ9W}~ej0yjsr7{{)V(u-$$v1DDsGAIA-zRcft zcc7e7iOCgbp*PJkamo~bEwKK;0cnh+K)X#YP;9J=0#KbQ5Ec` zrm-;(c_QDzujqe%S$$tg%0A}(I#8jv2?_2p!Psg%7A?UF@im3}PM>p9Rn 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