Billing/Billing.Shared/UI/OptionsCells.cs
2022-03-07 21:31:27 +08:00

405 lines
16 KiB
C#

using Billing.Themes;
using System;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace Billing.UI
{
public class OptionEntry : Entry { }
public class OptionEditor : Editor { }
public class OptionDatePicker : DatePicker { }
public class OptionTimePicker : TimePicker { }
public abstract class OptionCell : ViewCell
{
public static readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(OptionCell));
public static readonly BindableProperty BackgroundColorProperty = BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(OptionCell));
public static readonly BindableProperty IconProperty = BindableProperty.Create(nameof(Icon), typeof(ImageSource), typeof(OptionCell));
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(.3, GridUnitType.Star) },
new ColumnDefinition { Width = new GridLength(.7, 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 = BindableProperty.Create(nameof(Detail), typeof(string), typeof(OptionTextCell));
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 = BindableProperty.Create(nameof(Command), typeof(Command), typeof(OptionSelectCell));
public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create(nameof(CommandParameter), typeof(object), typeof(OptionSelectCell));
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 = BindableProperty.Create(nameof(ImageSource), typeof(ImageSource), typeof(OptionImageCell));
public static readonly BindableProperty TintColorProperty = BindableProperty.Create(nameof(TintColor), typeof(Color?), typeof(OptionImageCell));
[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(TintImage.PrimaryColorProperty, nameof(TintColor)),
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 = BindableProperty.Create(nameof(IsToggled), typeof(bool), typeof(OptionSwitchCell));
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 = BindableProperty.Create(nameof(Date), typeof(DateTime), typeof(OptionDatePickerCell));
public DateTime Date
{
get => (DateTime)GetValue(DateProperty);
set => SetValue(DateProperty, value);
}
protected override View Content => new OptionDatePicker
{
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.Center
}
.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 = BindableProperty.Create(nameof(Time), typeof(TimeSpan), typeof(OptionTimePickerCell));
public TimeSpan Time
{
get => (TimeSpan)GetValue(TimeProperty);
set => SetValue(TimeProperty, value);
}
protected override View Content => new OptionTimePicker
{
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.Center
}
.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 = BindableProperty.Create(nameof(Text), typeof(string), typeof(OptionEntryCell));
public static readonly BindableProperty KeyboardProperty = BindableProperty.Create(nameof(Keyboard), typeof(Keyboard), typeof(OptionEntryCell));
public static readonly BindableProperty PlaceholderProperty = BindableProperty.Create(nameof(Placeholder), typeof(string), typeof(OptionEntryCell));
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<FocusEventArgs> Unfocused;
protected override View Content
{
get
{
var content = new OptionEntry
{
HorizontalOptions = LayoutOptions.Fill,
HorizontalTextAlignment = TextAlignment.End,
VerticalOptions = LayoutOptions.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 = BindableProperty.Create(nameof(Text), typeof(string), typeof(OptionEditorCell));
public static readonly BindableProperty FontSizeProperty = BindableProperty.Create(nameof(FontSize), typeof(double), typeof(OptionEditorCell), defaultValue: Device.GetNamedSize(NamedSize.Default, typeof(Editor)));
public static readonly BindableProperty KeyboardProperty = BindableProperty.Create(nameof(Keyboard), typeof(Keyboard), typeof(OptionEditorCell), defaultValue: Keyboard.Default);
public static readonly BindableProperty PlaceholderProperty = BindableProperty.Create(nameof(Placeholder), typeof(string), typeof(OptionEditorCell));
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);
}
}