Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CheckBox drawing update #269

Merged
merged 2 commits into from
Aug 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions sandbox/SandboxMAUI/Pages/CheckBoxPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@

<BoxView Color="Black" HeightRequest="1" HorizontalOptions="Fill" Margin="5,10" />

<input:CheckBox Text="Option 0 with Box Type" Type="Box" LabelPosition="After"/>
<input:CheckBox Text="Option 0 with Box Type" Type="Box"/>
<input:CheckBox Text="Option 1 with Check Type" Type="Check" />
<input:CheckBox Text="Option 2 wity Cross Type" Type="Cross" />
<input:CheckBox Text="Option 3 with Custom Type" Type="Custom" CustomIcon="ic_account_balance_black"/>
<input:CheckBox Text="Option 4 with Material Type" Type="Material" />
<input:CheckBox Text="Option 5 with Star Type" Type="Star"/>
<input:CheckBox Text="Option 2 with Line Type" Type="Line" />
<input:CheckBox Text="Option 3 with Material Type" Type="Material" />
<input:CheckBox Text="Option 4 with Custom Type (X)" Type="Custom" CustomIconGeometry="M17.705 7.705l-1.41-1.41L12 10.59 7.705 6.295l-1.41 1.41L10.59 12l-4.295 4.295 1.41 1.41L12 13.41l4.295 4.295 1.41-1.41L13.41 12l4.295-4.295z"/>
<input:CheckBox Text="Option 5 with Material Custom Type (X)" Type="Material" CustomIconGeometry="M17.705 7.705l-1.41-1.41L12 10.59 7.705 6.295l-1.41 1.41L10.59 12l-4.295 4.295 1.41 1.41L12 13.41l4.295 4.295 1.41-1.41L13.41 12l4.295-4.295z"/>
<input:CheckBox Text="Option 6 (Position)" Type="Check" LabelPosition="Before"/>

</StackLayout>
Expand Down
157 changes: 93 additions & 64 deletions src/InputKit.Maui/Shared/Controls/CheckBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
using InputKit.Shared.Configuration;
using InputKit.Shared.Helpers;
using InputKit.Shared.Layouts;
using Microsoft.Maui;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
using System;
using Microsoft.Maui.Controls.Shapes;
using System.ComponentModel;
using System.Windows.Input;
using Path = Microsoft.Maui.Controls.Shapes.Path;

namespace InputKit.Shared.Controls;

Expand All @@ -26,18 +25,36 @@ public partial class CheckBox : StatefulStackLayout, IValidatable
FontSize = 14,
LabelPosition = LabelPosition.After
};
protected static PathGeometryConverter PathGeometryConverter { get; } = new PathGeometryConverter();

#region Constants
public const string RESOURCE_CHECK = "InputKit.Shared.Resources.check.png";
public const string RESOURCE_CROSS = "InputKit.Shared.Resources.cross.png";
public const string RESOURCE_STAR = "InputKit.Shared.Resources.star.png";
public const string PATH_CHECK = "M 6.5212 16.4777 l -6.24 -6.24 c -0.3749 -0.3749 -0.3749 -0.9827 0 -1.3577 l 1.3576 -1.3577 c 0.3749 -0.3749 0.9828 -0.3749 1.3577 0 L 7.2 11.7259 L 16.2036 2.7224 c 0.3749 -0.3749 0.9828 -0.3749 1.3577 0 l 1.3576 1.3577 c 0.3749 0.3749 0.3749 0.9827 0 1.3577 l -11.04 11.04 c -0.3749 0.3749 -0.9828 0.3749 -1.3577 -0 z";
public const string PATH_SQUARE = "M12 12H0V0h12v12z";
public const string PATH_LINE = "M 17.2026 6.7911 H 0.9875 C 0.4422 6.7911 0 7.2332 0 7.7784 v 2.6331 c 0 0.5453 0.442 0.9873 0.9875 0.9873 h 16.2151 c 0.5453 0 0.9873 -0.442 0.9873 -0.9873 v -2.6331 C 18.1901 7.2332 17.7481 6.7911 17.2026 6.7911 z";
internal const double CHECK_SIZE_RATIO = .65;
#endregion

#region Fields
protected internal Frame frmBackground = new Frame { Padding = 0, CornerRadius = GlobalSetting.CornerRadius, InputTransparent = true, HeightRequest = GlobalSetting.Size, WidthRequest = GlobalSetting.Size, BackgroundColor = GlobalSetting.BackgroundColor, BorderColor = GlobalSetting.BorderColor, VerticalOptions = LayoutOptions.CenterAndExpand, HasShadow = false };
protected internal BoxView boxSelected = new BoxView { IsVisible = false, HeightRequest = GlobalSetting.Size * .60, WidthRequest = GlobalSetting.Size * .60, Color = GlobalSetting.Color, VerticalOptions = LayoutOptions.CenterAndExpand, HorizontalOptions = LayoutOptions.Center };
protected internal IconView imgSelected = new IconView { Source = ImageSource.FromResource(RESOURCE_CHECK), FillColor = GlobalSetting.Color, VerticalOptions = LayoutOptions.CenterAndExpand, HorizontalOptions = LayoutOptions.Center, IsVisible = false };
internal Label lblOption = new Label { VerticalOptions = LayoutOptions.CenterAndExpand, FontSize = GlobalSetting.FontSize, TextColor = GlobalSetting.TextColor, FontFamily = GlobalSetting.FontFamily, IsVisible = false };
protected internal Grid IconLayout;
protected Rectangle outlineBox = new Rectangle
{
Fill = GlobalSetting.BackgroundColor,
Stroke = GlobalSetting.BorderColor,
StrokeThickness = 2,
WidthRequest = GlobalSetting.Size,
HeightRequest = GlobalSetting.Size,
};
protected Path selectedIcon = new Path
{
Fill = GlobalSetting.Color,
Aspect = Stretch.Uniform,
HeightRequest = GlobalSetting.Size,
WidthRequest = GlobalSetting.Size,
MaximumHeightRequest = GlobalSetting.Size,
MaximumWidthRequest = GlobalSetting.Size,
Scale = 0,
};
internal Label lblOption = new Label { VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Start, FontSize = GlobalSetting.FontSize, TextColor = GlobalSetting.TextColor, FontFamily = GlobalSetting.FontFamily, IsVisible = false };
private CheckType _type = CheckType.Box;
private bool _isEnabled;
#endregion
Expand All @@ -50,20 +67,26 @@ public CheckBox()
{
InitVisualStates();
Orientation = StackOrientation.Horizontal;
Padding = new Thickness(0, 10);
Spacing = 10;
frmBackground.Content = boxSelected;
ApplyLabelPosition(LabelPosition);
Padding = new Thickness(0, 10);
ApplyIsCheckedAction = ApplyIsChecked;
ApplyIsPressedAction = ApplyIsPressed;

IconLayout = new Grid
{
Children =
{
outlineBox,
selectedIcon
}
};

ApplyLabelPosition(LabelPosition);
UpdateType();
GestureRecognizers.Add(new TapGestureRecognizer
{
Command = new Command(() => { if (IsDisabled) return; IsChecked = !IsChecked; ExecuteCommand(); CheckChanged?.Invoke(this, new EventArgs()); ValidationChanged?.Invoke(this, new EventArgs()); }),
});

imgSelected.BackgroundColor = Colors.Cyan;

imgSelected.WidthRequest = 15;
}

/// <summary>
Expand Down Expand Up @@ -163,12 +186,12 @@ public Color Color
/// <summary>
/// Size of Checkbox
/// </summary>
public double BoxSize { get => frmBackground.Width; }
public double BoxSize { get => outlineBox.Width; }

/// <summary>
/// SizeRequest of CheckBox
/// </summary>
public double BoxSizeRequest { get => frmBackground.WidthRequest; set => SetBoxSize(value); }
public double BoxSizeRequest { get => outlineBox.WidthRequest; set => SetBoxSize(value); }

/// <summary>
/// Fontsize of Checkbox text
Expand Down Expand Up @@ -199,7 +222,11 @@ public Color Color
/// </summary>
public string FontFamily { get => (string)GetValue(FontFamilyProperty); set => SetValue(FontFamilyProperty, value); }

public ImageSource CustomIcon { get => (ImageSource)GetValue(CustomIconProperty); set => SetValue(CustomIconProperty, value); }
[Obsolete("This option is removed. Use CustomIconGeometry")]
public ImageSource CustomIcon { get => default; set { } }

[TypeConverter(typeof(PathGeometryConverter))]
public Geometry CustomIconGeometry { get => (Geometry)GetValue(CustomIconGeometryProperty); set => SetValue(CustomIconGeometryProperty, value); }

public bool IsPressed { get; set; }
/// <summary>
Expand Down Expand Up @@ -231,9 +258,9 @@ public LabelPosition LabelPosition
public static readonly BindableProperty TextFontSizeProperty = BindableProperty.Create(nameof(TextFontSize), typeof(double), typeof(CheckBox), GlobalSetting.FontSize, propertyChanged: (bo, ov, nv) => (bo as CheckBox).TextFontSize = (double)nv);
public static readonly BindableProperty BorderColorProperty = BindableProperty.Create(nameof(BorderColor), typeof(Color), typeof(CheckBox), GlobalSetting.BorderColor, propertyChanged: (bo, ov, nv) => (bo as CheckBox).UpdateBorderColor());
public static readonly BindableProperty FontFamilyProperty = BindableProperty.Create(nameof(FontFamily), typeof(string), typeof(CheckBox), Label.FontFamilyProperty.DefaultValue, propertyChanged: (bo, ov, nv) => (bo as CheckBox).UpdateFontFamily(nv?.ToString()));
public static readonly BindableProperty CustomIconProperty = BindableProperty.Create(nameof(CustomIcon), typeof(ImageSource), typeof(CheckBox), default(ImageSource), propertyChanged: (bo, ov, nv) => (bo as CheckBox).UpdateType((bo as CheckBox).Type));
public static readonly BindableProperty CustomIconGeometryProperty = BindableProperty.Create(nameof(CustomIconGeometry), typeof(Geometry), typeof(CheckBox), defaultValue: GetGeometryFromString(PATH_CHECK), propertyChanged: (bo, ov, nv) => (bo as CheckBox).UpdateType(CheckType.Custom));
public static readonly BindableProperty IsPressedProperty = BindableProperty.Create(nameof(IsPressed), typeof(bool), typeof(CheckBox), propertyChanged: (bo, ov, nv) => (bo as CheckBox).ApplyIsPressedAction(bo as CheckBox, (bool)nv));
public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(nameof(CornerRadius), typeof(float), typeof(CheckBox), GlobalSetting.CornerRadius, propertyChanged: (bo, ov, nv) => (bo as CheckBox).frmBackground.CornerRadius = (float)nv);
public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(nameof(CornerRadius), typeof(float), typeof(CheckBox), GlobalSetting.CornerRadius, propertyChanged: (bo, ov, nv) => (bo as CheckBox).outlineBox.RadiusX = (float)nv);
public static readonly BindableProperty LabelPositionProperty = BindableProperty.Create(
propertyName: nameof(LabelPosition), declaringType: typeof(CheckBox),
returnType: typeof(LabelPosition), defaultBindingMode: BindingMode.TwoWay,
Expand All @@ -249,14 +276,14 @@ void ApplyLabelPosition(LabelPosition position)
if (position == LabelPosition.After)
{
lblOption.HorizontalOptions = LayoutOptions.Start;
Children.Add(frmBackground);
Children.Add(IconLayout);
Children.Add(lblOption);
}
else
{
lblOption.HorizontalOptions = LayoutOptions.StartAndExpand;
lblOption.HorizontalOptions = LayoutOptions.FillAndExpand;
Children.Add(lblOption);
Children.Add(frmBackground);
Children.Add(IconLayout);
}
}

Expand All @@ -271,24 +298,24 @@ void UpdateBoxBackground()
if (Type == CheckType.Material)
return;

frmBackground.BackgroundColor = BoxBackgroundColor;
outlineBox.Fill = BoxBackgroundColor;
}

void UpdateColors()
{
boxSelected.Color = Color;
//selectedIcon.Fill = Color;

if (Type == CheckType.Material)
{
frmBackground.BorderColor = Color;
frmBackground.BackgroundColor = IsChecked ? Color : Colors.Transparent;
imgSelected.FillColor = Color.ToSurfaceColor();
outlineBox.Stroke = Color;
outlineBox.Fill = IsChecked ? Color : Colors.Transparent;
selectedIcon.Fill = Color.ToSurfaceColor();
}
else
{
frmBackground.BorderColor = IsChecked ? Color : BorderColor;
frmBackground.BackgroundColor = BoxBackgroundColor;
imgSelected.FillColor = IconColor == Colors.Transparent ? Color : IconColor;
outlineBox.Stroke = IsChecked ? Color : BorderColor;
outlineBox.Fill = BoxBackgroundColor;
selectedIcon.Fill = IconColor == Colors.Transparent ? Color : IconColor;
}
}

Expand All @@ -297,48 +324,39 @@ void UpdateBorderColor()
if (Type == CheckType.Material)
return;

frmBackground.BorderColor = BorderColor;
outlineBox.Stroke = BorderColor;
}

void SetBoxSize(double value)
void SetBoxSize(double size)
{
frmBackground.WidthRequest = value;
frmBackground.HeightRequest = value;
boxSelected.WidthRequest = value * .6; //old value 0.72
boxSelected.HeightRequest = value * 0.6;
//lblSelected.FontSize = value * 0.72; //old value 0.76 //TODO: Do something to resizing

// TODO: Refactor after MAUI update
(this.Children[0] as View).MinimumWidthRequest = value * 1.4;
outlineBox.HeightRequest = size;
outlineBox.WidthRequest = size;
//selectedIcon.MaximumHeightRequest = size * CHECK_SIZE_RATIO;
//selectedIcon.MaximumWidthRequest = size * CHECK_SIZE_RATIO;
}

void UpdateType(CheckType _Type)
void UpdateType(CheckType _Type = CheckType.Custom)
{
switch (_Type)
{
case CheckType.Box:
frmBackground.Content = boxSelected;
break;
case CheckType.Check:
imgSelected.Source = ImageSource.FromResource(RESOURCE_CHECK);
frmBackground.Content = imgSelected;
selectedIcon.Data = GetGeometryFromString(PATH_SQUARE);
break;
case CheckType.Cross:
imgSelected.Source = ImageSource.FromResource(RESOURCE_CROSS);
frmBackground.Content = imgSelected;
case CheckType.Line:
selectedIcon.Data = GetGeometryFromString(PATH_LINE);
break;

case CheckType.Check:
case CheckType.Star:
imgSelected.Source = ImageSource.FromResource(RESOURCE_STAR);
frmBackground.Content = imgSelected;
case CheckType.Cross:
selectedIcon.Data = GetGeometryFromString(PATH_CHECK);
break;
case CheckType.Material:
imgSelected.Source = ImageSource.FromResource(RESOURCE_CHECK);
frmBackground.CornerRadius = 5;
frmBackground.Content = imgSelected;
outlineBox.RadiusX = 5;
selectedIcon.Data = GetGeometryFromString(PATH_CHECK);
break;
case CheckType.Custom:
imgSelected.Source = CustomIcon;
frmBackground.Content = imgSelected;
selectedIcon.Data = CustomIconGeometry;
break;
}

Expand Down Expand Up @@ -389,26 +407,37 @@ public void DisplayValidation()
{

}

public static void ApplyIsChecked(CheckBox checkBox, bool isChecked)
{
checkBox.frmBackground.Content.IsVisible = isChecked;
checkBox.selectedIcon.ScaleTo(isChecked ? CHECK_SIZE_RATIO : 0, 160);

checkBox.UpdateColors();
}

public static async void ApplyIsPressed(CheckBox checkBox, bool isPressed)
{
await checkBox.frmBackground.ScaleTo(isPressed ? .8 : 1, 50, Easing.BounceIn);
var radiusVal = isPressed ? checkBox.frmBackground.CornerRadius * 2f : checkBox.CornerRadius;
checkBox.frmBackground.CornerRadius = radiusVal;
await checkBox.outlineBox.ScaleTo(isPressed ? .8 : 1, 50, Easing.BounceIn);
var radiusVal = isPressed ? checkBox.outlineBox.RadiusX * 2f : checkBox.CornerRadius;
checkBox.outlineBox.RadiusX = radiusVal;
}

internal static Geometry GetGeometryFromString(string path)
{
return (Geometry)PathGeometryConverter.ConvertFromInvariantString(path);
}
#endregion

public enum CheckType
{
Box,
Check,
[Obsolete("This option is removed. Use another one.")]
Cross,
[Obsolete("This option is removed. Use another one.")]
Star,
Material,
Line,
Custom = 90
}
}
Binary file removed src/InputKit.Maui/Shared/Resources/check.png
Binary file not shown.
Binary file removed src/InputKit.Maui/Shared/Resources/cross.png
Binary file not shown.
Binary file removed src/InputKit.Maui/Shared/Resources/star.png
Binary file not shown.