using Billing.Themes; using System; using Xamarin.Forms; namespace Billing.UI { public enum BorderStyle { None = 0, RoundedRect } public class OptionEntry : Entry { } public class OptionEditor : Editor { } public class OptionPicker : Picker { public static readonly BindableProperty BorderStyleProperty = Helper.Create(nameof(BorderStyle)); public BorderStyle BorderStyle { get => (BorderStyle)GetValue(BorderStyleProperty); set => SetValue(BorderStyleProperty, value); } } public class OptionDatePicker : DatePicker { } public class OptionTimePicker : TimePicker { } public abstract class OptionCell : ViewCell { public static readonly BindableProperty TitleProperty = Helper.Create(nameof(Title)); public static readonly BindableProperty BackgroundColorProperty = Helper.Create(nameof(BackgroundColor)); public static readonly BindableProperty IconProperty = Helper.Create(nameof(Icon)); public string Title { get => (string)GetValue(TitleProperty); set => SetValue(TitleProperty, value); } public Color BackgroundColor { get => (Color)GetValue(BackgroundColorProperty); set => SetValue(BackgroundColorProperty, value); } [TypeConverter(typeof(ImageSourceConverter))] public ImageSource Icon { get => (ImageSource)GetValue(IconProperty); set => SetValue(IconProperty, value); } protected abstract View Content { get; } public OptionCell() { View = new Grid { BindingContext = this, Padding = new Thickness(20, 0), ColumnDefinitions = { new ColumnDefinition { Width = GridLength.Auto }, new ColumnDefinition { Width = new GridLength(.35, GridUnitType.Star) }, new ColumnDefinition { Width = new GridLength(.65, GridUnitType.Star) } }, Children = { new TintImage { WidthRequest = 20, HeightRequest = 20, Aspect = Aspect.AspectFit, VerticalOptions = LayoutOptions.Center, Margin = new Thickness(6, 0) } .Binding(VisualElement.IsVisibleProperty, nameof(Icon), converter: new NotNullConverter()) .Binding(Image.SourceProperty, nameof(Icon)), new Label { LineBreakMode = LineBreakMode.TailTruncation, VerticalOptions = LayoutOptions.Center } .GridColumn(1) .Binding(Label.TextProperty, nameof(Title)) .DynamicResource(Label.TextColorProperty, BaseTheme.TextColor), Content.GridColumn(2) } } .DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor); } } public abstract class OptionVerticalCell : OptionCell { public OptionVerticalCell() { View = new Grid { BindingContext = this, Padding = new Thickness(20, 0), ColumnDefinitions = { new ColumnDefinition { Width = GridLength.Auto }, new ColumnDefinition { Width = GridLength.Star } }, RowDefinitions = { new RowDefinition { Height = new GridLength(40) }, new RowDefinition { Height = GridLength.Star } }, Children = { new TintImage { WidthRequest = 20, HeightRequest = 20, Aspect = Aspect.AspectFit, VerticalOptions = LayoutOptions.Center, Margin = new Thickness(6, 0) } .Binding(VisualElement.IsVisibleProperty, nameof(Icon), converter: new NotNullConverter()) .Binding(Image.SourceProperty, nameof(Icon)), new Label { LineBreakMode = LineBreakMode.TailTruncation, VerticalOptions = LayoutOptions.Center } .GridColumn(1) .Binding(Label.TextProperty, nameof(Title)) .DynamicResource(Label.TextColorProperty, BaseTheme.TextColor), Content.GridRow(1).GridColumnSpan(2) } } .DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor); } } public class OptionTextCell : OptionCell { public static readonly BindableProperty DetailProperty = Helper.Create(nameof(Detail)); public string Detail { get => (string)GetValue(DetailProperty); set => SetValue(DetailProperty, value); } protected override View Content => new Label { HorizontalOptions = LayoutOptions.End, VerticalOptions = LayoutOptions.Center } .Binding(Label.TextProperty, nameof(Detail)) .DynamicResource(Label.TextColorProperty, BaseTheme.SecondaryTextColor); } public class OptionSelectCell : OptionTextCell { public static readonly BindableProperty CommandProperty = Helper.Create(nameof(Command)); public static readonly BindableProperty CommandParameterProperty = Helper.Create(nameof(CommandParameter)); public Command Command { get => (Command)GetValue(CommandProperty); set => SetValue(CommandProperty, value); } public object CommandParameter { get => GetValue(CommandParameterProperty); set => SetValue(CommandParameterProperty, value); } protected override View Content => new StackLayout { Orientation = StackOrientation.Horizontal, HorizontalOptions = LayoutOptions.End, Children = { new Label { VerticalOptions = LayoutOptions.Center } .Binding(Label.TextProperty, nameof(Detail)) .DynamicResource(Label.TextColorProperty, BaseTheme.SecondaryTextColor), new TintImage { HeightRequest = 20, VerticalOptions = LayoutOptions.Center, Margin = new Thickness(6, 0), Source = "right.png" } }, GestureRecognizers = { new TapGestureRecognizer() .Binding(TapGestureRecognizer.CommandProperty, nameof(Command)) .Binding(TapGestureRecognizer.CommandParameterProperty, nameof(CommandParameter)) } }; } public class OptionImageCell : OptionSelectCell { public static readonly BindableProperty ImageSourceProperty = Helper.Create(nameof(ImageSource)); public static readonly BindableProperty TintColorProperty = Helper.Create(nameof(TintColor)); [TypeConverter(typeof(ImageSourceConverter))] public ImageSource ImageSource { get => (ImageSource)GetValue(ImageSourceProperty); set => SetValue(ImageSourceProperty, value); } [TypeConverter(typeof(ColorTypeConverter))] public Color? TintColor { get => (Color?)GetValue(TintColorProperty); set => SetValue(TintColorProperty, value); } protected override View Content => new StackLayout { Orientation = StackOrientation.Horizontal, HorizontalOptions = LayoutOptions.End, Children = { new TintImage { WidthRequest = 26, HeightRequest = 20, VerticalOptions = LayoutOptions.Center, Margin = new Thickness(6, 0) } .Binding(Image.SourceProperty, nameof(ImageSource)) .Binding(TintHelper.TintColorProperty, nameof(TintColor)), new Label { VerticalOptions = LayoutOptions.Center } .Binding(Label.TextProperty, nameof(Detail)) .DynamicResource(Label.TextColorProperty, BaseTheme.SecondaryTextColor), new TintImage { HeightRequest = 20, VerticalOptions = LayoutOptions.Center, Margin = new Thickness(6, 0), Source = "right.png" } }, GestureRecognizers = { new TapGestureRecognizer() .Binding(TapGestureRecognizer.CommandProperty, nameof(Command)) .Binding(TapGestureRecognizer.CommandParameterProperty, nameof(CommandParameter)) } }; } public class OptionSwitchCell : OptionCell { public static readonly BindableProperty IsToggledProperty = Helper.Create(nameof(IsToggled)); public bool IsToggled { get => (bool)GetValue(IsToggledProperty); set => SetValue(IsToggledProperty, value); } protected override View Content => new Switch { HorizontalOptions = LayoutOptions.End, VerticalOptions = LayoutOptions.Center } .Binding(Switch.IsToggledProperty, nameof(IsToggled), mode: BindingMode.TwoWay); } public class OptionDatePickerCell : OptionCell { public static readonly BindableProperty DateProperty = Helper.Create(nameof(Date)); public DateTime Date { get => (DateTime)GetValue(DateProperty); set => SetValue(DateProperty, value); } protected override View Content => new OptionDatePicker { HorizontalOptions = LayoutOptions.End, VerticalOptions = LayoutOptions.Fill } .Binding(DatePicker.DateProperty, nameof(Date), mode: BindingMode.TwoWay) .DynamicResource(DatePicker.TextColorProperty, BaseTheme.TextColor) .DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor); } public class OptionTimePickerCell : OptionCell { public static readonly BindableProperty TimeProperty = Helper.Create(nameof(Time)); public TimeSpan Time { get => (TimeSpan)GetValue(TimeProperty); set => SetValue(TimeProperty, value); } protected override View Content => new OptionTimePicker { HorizontalOptions = LayoutOptions.End, VerticalOptions = LayoutOptions.Fill } .Binding(TimePicker.TimeProperty, nameof(Time), mode: BindingMode.TwoWay) .DynamicResource(TimePicker.TextColorProperty, BaseTheme.TextColor) .DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor); } public class OptionEntryCell : OptionCell { public static readonly BindableProperty TextProperty = Helper.Create(nameof(Text)); public static readonly BindableProperty KeyboardProperty = Helper.Create(nameof(Keyboard), defaultValue: Keyboard.Default); public static readonly BindableProperty PlaceholderProperty = Helper.Create(nameof(Placeholder)); public string Text { get => (string)GetValue(TextProperty); set => SetValue(TextProperty, value); } public Keyboard Keyboard { get => (Keyboard)GetValue(KeyboardProperty); set => SetValue(KeyboardProperty, value); } public string Placeholder { get => (string)GetValue(PlaceholderProperty); set => SetValue(PlaceholderProperty, value); } public event EventHandler Unfocused; protected override View Content { get { var content = new OptionEntry { HorizontalOptions = LayoutOptions.Fill, HorizontalTextAlignment = TextAlignment.End, VerticalOptions = LayoutOptions.Fill, VerticalTextAlignment = TextAlignment.Center, ReturnType = ReturnType.Next } .Binding(Entry.TextProperty, nameof(Text), mode: BindingMode.TwoWay) .Binding(InputView.KeyboardProperty, nameof(Keyboard)) .Binding(Entry.PlaceholderProperty, nameof(Placeholder)) .DynamicResource(Entry.TextColorProperty, BaseTheme.TextColor) .DynamicResource(Entry.PlaceholderColorProperty, BaseTheme.SecondaryTextColor) .DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor); content.Unfocused += Content_Unfocused; return content; } } private void Content_Unfocused(object sender, FocusEventArgs e) { Unfocused?.Invoke(sender, e); } } public class OptionEditorCell : OptionVerticalCell { public static readonly BindableProperty TextProperty = Helper.Create(nameof(Text)); public static readonly BindableProperty FontSizeProperty = Helper.Create(nameof(FontSize), defaultValue: Device.GetNamedSize(NamedSize.Default, typeof(Editor))); public static readonly BindableProperty KeyboardProperty = Helper.Create(nameof(Keyboard), defaultValue: Keyboard.Default); public static readonly BindableProperty PlaceholderProperty = Helper.Create(nameof(Placeholder)); public string Text { get => (string)GetValue(TextProperty); set => SetValue(TextProperty, value); } [TypeConverter(typeof(FontSizeConverter))] public double FontSize { get => (double)GetValue(FontSizeProperty); set => SetValue(FontSizeProperty, value); } public Keyboard Keyboard { get => (Keyboard)GetValue(KeyboardProperty); set => SetValue(KeyboardProperty, value); } public string Placeholder { get => (string)GetValue(PlaceholderProperty); set => SetValue(PlaceholderProperty, value); } OptionEditor editor; public void SetFocus() { if (editor != null) { editor.Focus(); } } protected override View Content => editor = new OptionEditor { HorizontalOptions = LayoutOptions.Fill, VerticalOptions = LayoutOptions.Fill } .Binding(Editor.TextProperty, nameof(Text), mode: BindingMode.TwoWay) .Binding(Editor.FontSizeProperty, nameof(FontSize)) .Binding(InputView.KeyboardProperty, nameof(Keyboard)) .Binding(Editor.PlaceholderProperty, nameof(Placeholder)) .DynamicResource(Editor.TextColorProperty, BaseTheme.TextColor) .DynamicResource(Editor.PlaceholderColorProperty, BaseTheme.SecondaryTextColor) .DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor); } }