This commit is contained in:
Javier Suárez Ruiz 2022-08-20 18:33:09 +02:00
Родитель fe09701807
Коммит 348d1e66fe
5 изменённых файлов: 459 добавлений и 1 удалений

Просмотреть файл

@ -18,8 +18,11 @@ namespace AlohaKit.Gallery.ViewModels
new SectionModel(typeof(CheckBoxView), "CheckBox",
"CheckBox is a type of button that can either be checked or empty."),
new SectionModel(typeof(LinearGaugeView), "LinearGauge",
"LinearGauge displays simple value within a specific range."),
new SectionModel(typeof(NumericUpDownView), "NumericUpDown",
new SectionModel(typeof(NumericUpDownView), "NumericUpDown",
" NumericUpDown control provides up and down repeat buttons to increase and decrease values."),
new SectionModel(typeof(PieChartView), "PieChart",

Просмотреть файл

@ -0,0 +1,121 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="AlohaKit.Gallery.LinearGaugeView"
xmlns:controls="clr-namespace:AlohaKit.Controls;assembly=AlohaKit"
Title="LinearGauge">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="SettingsSliderStyle" TargetType="Slider">
<Setter Property="VerticalOptions" Value="Center" />
<Setter Property="WidthRequest" Value="100" />
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource LightAccentColor}, Dark={StaticResource DarkAccentColor}}" />
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource LightAccentColor}, Dark={StaticResource DarkAccentColor}}" />
<Setter Property="Margin" Value="0, 0, 12, 0" />
</Style>
<Style x:Key="SettingsTextStyle" TargetType="Label">
<Setter Property="FontSize" Value="9" />
</Style>
<Style x:Key="SettingsEntryStyle" TargetType="Entry">
<Setter Property="VerticalOptions" Value="Center" />
<Setter Property="WidthRequest" Value="80" />
<Setter Property="Margin" Value="6, 0" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- DESCRIPTION -->
<StackLayout
Style="{StaticResource SectionContainerStyle}">
<Label
Text="LinearGauge displays simple value within a specific range."/>
</StackLayout>
<!-- FEATURES -->
<StackLayout
Grid.Row="1"
BackgroundColor="{AppThemeBinding Light={StaticResource LightBackgroundSecondaryColor}, Dark={StaticResource DarkBackgroundSecondaryColor}}"
Style="{StaticResource SectionContainerStyle}">
<Label
Text="Features"
Style="{StaticResource SectionTitleStyle}"/>
<Label
Text="- Allow to customize the background with a gradient."/>
<Label
Text="- Allow to customize the border with a color."/>
<Label
Text="- Define the range."/>
</StackLayout>
<!-- SETTINGS -->
<StackLayout
Grid.Row="2"
Style="{StaticResource SectionContainerStyle}">
<StackLayout
Orientation="Horizontal"
Margin="0, 6">
<Label
Text="Fill Start Color"
VerticalOptions="Center"
Style="{StaticResource SettingsTextStyle}"/>
<Entry
x:Name="FillStartColorEntry"
Placeholder="Background Color"
Text="#DD5E89"
TextChanged="OnFillStartColorEntryTextChanged"
Style="{StaticResource SettingsEntryStyle}"/>
<Label
Text="Fill End Color"
VerticalOptions="Center"
Style="{StaticResource SettingsTextStyle}"/>
<Entry
x:Name="FillEndColorEntry"
Placeholder="Color"
Text="#F7BB97"
TextChanged="OnFillEndColorEntryTextChanged"
Style="{StaticResource SettingsEntryStyle}"/>
</StackLayout>
<StackLayout
Orientation="Horizontal"
Margin="0, 6">
<Grid
RowDefinitions="Auto, *">
<Label
Text="Value"
Style="{StaticResource SettingsTextStyle}"/>
<Grid
ColumnDefinitions="*, Auto">
<Slider
x:Name="ValueSlider"
Grid.Row="1"
Minimum="0"
Value="50"
Maximum="100"
Style="{StaticResource SettingsSliderStyle}"/>
<Label
Grid.Column="1"
VerticalOptions="Center"
Text="{Binding Source={x:Reference ValueSlider}, Path=Value, StringFormat='{0:F2}'}"/>
</Grid>
</Grid>
</StackLayout>
</StackLayout>
<controls:LinearGauge
x:Name="LinearGauge"
Grid.Row="3"
RangeStart="0"
RangeEnd="100"
Value="{Binding Source={x:Reference ValueSlider}, Path=Value}"
HorizontalOptions="Center"
VerticalOptions="Center" />
</Grid>
</ContentPage>

Просмотреть файл

@ -0,0 +1,59 @@
namespace AlohaKit.Gallery;
public partial class LinearGaugeView : ContentPage
{
public LinearGaugeView()
{
InitializeComponent();
UpdateBrushes();
}
void OnFillStartColorEntryTextChanged(object sender, TextChangedEventArgs e)
{
UpdateBrushes();
}
void OnFillEndColorEntryTextChanged(object sender, TextChangedEventArgs e)
{
UpdateBrushes();
}
void UpdateBrushes()
{
var fillStartColor = GetColorFromString(FillStartColorEntry.Text);
var fillEndColor = GetColorFromString(FillEndColorEntry.Text);
if (fillStartColor != null && fillEndColor != null)
{
FillStartColorEntry.BackgroundColor = fillStartColor;
FillEndColorEntry.BackgroundColor = fillEndColor;
LinearGauge.Background = new LinearGradientBrush
{
StartPoint = new Point(0, 1),
EndPoint = new Point(0, 0),
GradientStops = new GradientStopCollection
{
new GradientStop { Color = fillStartColor, Offset = 0 },
new GradientStop { Color = fillEndColor, Offset = 1 }
}
};
}
}
Color GetColorFromString(string value)
{
if (string.IsNullOrEmpty(value))
return null;
try
{
return Color.FromArgb(value[0].Equals('#') ? value : $"#{value}");
}
catch (Exception)
{
return null;
}
}
}

Просмотреть файл

@ -0,0 +1,165 @@
using Microsoft.Maui.Platform;
namespace AlohaKit.Controls
{
// TODO: Include the Orientation property
public class LinearGauge : GraphicsView
{
public LinearGauge()
{
HeightRequest = 200;
WidthRequest = 60;
Drawable = LinearGaugeDrawable = new LinearGaugeDrawable();
}
public LinearGaugeDrawable LinearGaugeDrawable { get; set; }
public static readonly new BindableProperty BackgroundProperty =
BindableProperty.Create(nameof(Background), typeof(Brush), typeof(Button), null,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is LinearGauge linearGauge)
{
linearGauge.UpdateBackground();
}
});
public new Brush Background
{
get => (Brush)GetValue(BackgroundProperty);
set => SetValue(BackgroundProperty, value);
}
public static readonly BindableProperty RangeStartProperty =
BindableProperty.Create(nameof(RangeStart), typeof(int), typeof(LinearGauge), 0,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is LinearGauge linearGauge)
{
linearGauge.UpdateBackground();
}
});
public int RangeStart
{
get => (int)GetValue(RangeStartProperty);
set => SetValue(RangeStartProperty, value);
}
public static readonly BindableProperty RangeEndProperty =
BindableProperty.Create(nameof(RangeEnd), typeof(int), typeof(LinearGauge), 100,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is LinearGauge linearGauge)
{
linearGauge.UpdateRangeEnd();
}
});
public int RangeEnd
{
get => (int)GetValue(RangeEndProperty);
set => SetValue(RangeEndProperty, value);
}
public static readonly BindableProperty ValueProperty =
BindableProperty.Create(nameof(Value), typeof(int), typeof(LinearGauge), 0,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is LinearGauge linearGauge)
{
linearGauge.UpdateValue();
linearGauge.ValueChanged?.Invoke(linearGauge, new ValueChangedEventArgs((double)oldValue, (double)newValue));
}
});
public int Value
{
get => (int)GetValue(ValueProperty);
set => SetValue(ValueProperty, value);
}
public static readonly BindableProperty CornerRadiusProperty =
BindableProperty.Create(nameof(CornerRadius), typeof(CornerRadius), typeof(Button), new CornerRadius(),
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (newValue != null && bindableObject is LinearGauge linearGauge)
{
linearGauge.UpdateCornerRadius();
}
});
public CornerRadius CornerRadius
{
get => (CornerRadius)GetValue(CornerRadiusProperty);
set => SetValue(CornerRadiusProperty, value);
}
public event EventHandler<ValueChangedEventArgs> ValueChanged;
protected override void OnParentSet()
{
base.OnParentSet();
if (Parent != null)
{
UpdateBackground();
UpdateRangeStart();
UpdateRangeEnd();
UpdateValue();
UpdateCornerRadius();
}
}
void UpdateBackground()
{
if (LinearGaugeDrawable == null)
return;
LinearGaugeDrawable.BackgroundPaint = Background;
Invalidate();
}
void UpdateRangeStart()
{
if (LinearGaugeDrawable == null)
return;
LinearGaugeDrawable.RangeStart = RangeStart;
Invalidate();
}
void UpdateRangeEnd()
{
if (LinearGaugeDrawable == null)
return;
LinearGaugeDrawable.RangeEnd = RangeEnd;
Invalidate();
}
void UpdateValue()
{
if (LinearGaugeDrawable == null)
return;
LinearGaugeDrawable.Value = Value;
Invalidate();
}
void UpdateCornerRadius()
{
if (LinearGaugeDrawable == null)
return;
LinearGaugeDrawable.CornerRadius = CornerRadius;
Invalidate();
}
}
}

Просмотреть файл

@ -0,0 +1,110 @@
using Microsoft.Maui.Graphics;
namespace AlohaKit.Controls
{
public class LinearGaugeDrawable : IDrawable
{
// TODO: Expose these properties
Color Stroke = Colors.Black;
const float StrokeThickness = 2.0f;
const float TicksWidth = 20.0f;
public Paint BackgroundPaint { get; set; }
public int RangeStart { get; set; }
public int RangeEnd { get; set; }
public int Value { get; set; }
public CornerRadius CornerRadius { get; set; }
public void Draw(ICanvas canvas, RectF dirtyRect)
{
DrawBackground(canvas, dirtyRect);
DrawProgress(canvas, dirtyRect);
DrawTicks(canvas, dirtyRect);
}
void DrawBackground(ICanvas canvas, RectF dirtyRect)
{
canvas.SaveState();
canvas.StrokeColor = Stroke;
canvas.StrokeSize = StrokeThickness;
canvas.DrawRoundedRectangle(
dirtyRect.X + TicksWidth,
dirtyRect.Y,
dirtyRect.Width - TicksWidth,
dirtyRect.Height,
(float)CornerRadius.TopLeft,
(float)CornerRadius.TopRight,
(float)CornerRadius.BottomLeft,
(float)CornerRadius.BottomRight);
canvas.RestoreState();
}
void DrawProgress(ICanvas canvas, RectF dirtyRect)
{
if (BackgroundPaint != null)
{
canvas.SaveState();
int value = Value;
if (value > RangeEnd)
value = RangeEnd;
if (value < RangeStart)
value = RangeStart;
var percentage = (double)value / RangeEnd;
var progressHeight = dirtyRect.Height * percentage;
var progressY = dirtyRect.Y + dirtyRect.Height - progressHeight;
var rect = new Rect(
dirtyRect.X + TicksWidth + StrokeThickness / 2,
progressY + StrokeThickness / 2,
dirtyRect.Width - TicksWidth - StrokeThickness,
progressHeight - StrokeThickness);
canvas.SetFillPaint(BackgroundPaint, rect);
canvas.FillRoundedRectangle(
rect,
CornerRadius.TopLeft,
CornerRadius.TopRight,
CornerRadius.BottomLeft,
CornerRadius.BottomRight);
canvas.RestoreState();
}
}
void DrawTicks(ICanvas canvas, RectF dirtyRect)
{
int steps = 10;
for (int i = 0; i < steps; i++)
{
var stepScale = (double)i / steps;
Point nextLine = new Point(dirtyRect.X + TicksWidth, dirtyRect.Y + dirtyRect.Height * stepScale);
double defaultTickWidthh = 10.0d;
double tickWidth = defaultTickWidthh;
if (i != 0)
{
if (i == (steps / 2))
tickWidth = defaultTickWidthh * 2;
canvas.DrawLine(nextLine, nextLine.Offset(tickWidth, 0));
canvas.Font = Microsoft.Maui.Graphics.Font.Default;
var strValue = (int)(((double)RangeEnd / steps) * (steps - i));
PointF stringPosition = nextLine.Offset(-10, 0);
canvas.DrawString(strValue.ToString(), stringPosition.X, stringPosition.Y, HorizontalAlignment.Center);
}
}
}
}
}