Added LinearGauge
This commit is contained in:
Родитель
fe09701807
Коммит
348d1e66fe
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче