Initial commit: PulseDock System Monitor
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using Brush = System.Windows.Media.Brush;
|
||||
using Brushes = System.Windows.Media.Brushes;
|
||||
using Color = System.Windows.Media.Color;
|
||||
using Pen = System.Windows.Media.Pen;
|
||||
using Point = System.Windows.Point;
|
||||
using Size = System.Windows.Size;
|
||||
|
||||
namespace PulseDock.App.Controls
|
||||
{
|
||||
public class ProgressRingControl : FrameworkElement
|
||||
{
|
||||
public static readonly DependencyProperty ValueProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(Value),
|
||||
typeof(double),
|
||||
typeof(ProgressRingControl),
|
||||
new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public static readonly DependencyProperty StrokeThicknessProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(StrokeThickness),
|
||||
typeof(double),
|
||||
typeof(ProgressRingControl),
|
||||
new FrameworkPropertyMetadata(4.0, FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public static readonly DependencyProperty ProgressBrushProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(ProgressBrush),
|
||||
typeof(Brush),
|
||||
typeof(ProgressRingControl),
|
||||
new FrameworkPropertyMetadata(Brushes.DarkViolet, FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public double Value
|
||||
{
|
||||
get => (double)GetValue(ValueProperty);
|
||||
set => SetValue(ValueProperty, value);
|
||||
}
|
||||
|
||||
public double StrokeThickness
|
||||
{
|
||||
get => (double)GetValue(StrokeThicknessProperty);
|
||||
set => SetValue(StrokeThicknessProperty, value);
|
||||
}
|
||||
|
||||
public Brush ProgressBrush
|
||||
{
|
||||
get => (Brush)GetValue(ProgressBrushProperty);
|
||||
set => SetValue(ProgressBrushProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnRender(DrawingContext drawingContext)
|
||||
{
|
||||
base.OnRender(drawingContext);
|
||||
|
||||
double width = ActualWidth;
|
||||
double height = ActualHeight;
|
||||
if (width <= 0 || height <= 0) return;
|
||||
|
||||
double radius = (Math.Min(width, height) - StrokeThickness) / 2.0;
|
||||
var center = new Point(width / 2.0, height / 2.0);
|
||||
|
||||
// Background circle
|
||||
var bgPen = new Pen(new SolidColorBrush(Color.FromArgb(40, 255, 255, 255)), StrokeThickness);
|
||||
bgPen.Freeze();
|
||||
drawingContext.DrawEllipse(null, bgPen, center, radius, radius);
|
||||
|
||||
double pct = Math.Clamp(Value, 0.0, 100.0) / 100.0;
|
||||
if (pct <= 0.001) return;
|
||||
|
||||
double angle = pct * 360.0;
|
||||
if (angle >= 360.0) angle = 359.99; // Avoid full circle arc overlap issues
|
||||
|
||||
Point startPoint = new Point(center.X, center.Y - radius);
|
||||
double radians = (angle - 90.0) * (Math.PI / 180.0);
|
||||
Point endPoint = new Point(center.X + radius * Math.Cos(radians), center.Y + radius * Math.Sin(radians));
|
||||
|
||||
bool isLargeArc = angle > 180.0;
|
||||
|
||||
var geometry = new StreamGeometry();
|
||||
using (var ctx = geometry.Open())
|
||||
{
|
||||
ctx.BeginFigure(startPoint, isFilled: false, isClosed: false);
|
||||
ctx.ArcTo(endPoint, new Size(radius, radius), 0, isLargeArc, SweepDirection.Clockwise, isStroked: true, isSmoothJoin: true);
|
||||
}
|
||||
geometry.Freeze();
|
||||
|
||||
var fgPen = new Pen(ProgressBrush, StrokeThickness)
|
||||
{
|
||||
StartLineCap = PenLineCap.Round,
|
||||
EndLineCap = PenLineCap.Round
|
||||
};
|
||||
fgPen.Freeze();
|
||||
|
||||
drawingContext.DrawGeometry(null, fgPen, geometry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using Brush = System.Windows.Media.Brush;
|
||||
using Brushes = System.Windows.Media.Brushes;
|
||||
using Pen = System.Windows.Media.Pen;
|
||||
using Point = System.Windows.Point;
|
||||
|
||||
namespace PulseDock.App.Controls
|
||||
{
|
||||
public class SparklineControl : FrameworkElement
|
||||
{
|
||||
public static readonly DependencyProperty ValuesProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(Values),
|
||||
typeof(IEnumerable<float>),
|
||||
typeof(SparklineControl),
|
||||
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public static readonly DependencyProperty LineColorProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(LineColor),
|
||||
typeof(Brush),
|
||||
typeof(SparklineControl),
|
||||
new FrameworkPropertyMetadata(Brushes.Cyan, FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public static readonly DependencyProperty LineThicknessProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(LineThickness),
|
||||
typeof(double),
|
||||
typeof(SparklineControl),
|
||||
new FrameworkPropertyMetadata(1.5, FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public IEnumerable<float>? Values
|
||||
{
|
||||
get => (IEnumerable<float>?)GetValue(ValuesProperty);
|
||||
set => SetValue(ValuesProperty, value);
|
||||
}
|
||||
|
||||
public Brush LineColor
|
||||
{
|
||||
get => (Brush)GetValue(LineColorProperty);
|
||||
set => SetValue(LineColorProperty, value);
|
||||
}
|
||||
|
||||
public double LineThickness
|
||||
{
|
||||
get => (double)GetValue(LineThicknessProperty);
|
||||
set => SetValue(LineThicknessProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnRender(DrawingContext drawingContext)
|
||||
{
|
||||
base.OnRender(drawingContext);
|
||||
|
||||
var values = Values?.ToArray();
|
||||
if (values == null || values.Length < 2 || ActualWidth <= 0 || ActualHeight <= 0)
|
||||
return;
|
||||
|
||||
double width = ActualWidth;
|
||||
double height = ActualHeight;
|
||||
|
||||
float min = 0f;
|
||||
float max = 100f; // Scale percentage or range dynamically
|
||||
float actualMax = values.Max();
|
||||
if (actualMax > 100f) max = actualMax;
|
||||
|
||||
var geometry = new StreamGeometry();
|
||||
using (var ctx = geometry.Open())
|
||||
{
|
||||
double stepX = width / (values.Length - 1);
|
||||
|
||||
for (int i = 0; i < values.Length; i++)
|
||||
{
|
||||
double x = i * stepX;
|
||||
float val = Math.Clamp(values[i], min, max);
|
||||
double normY = (val - min) / (max - min);
|
||||
double y = height - (normY * (height - 4)) - 2;
|
||||
|
||||
var point = new Point(x, y);
|
||||
|
||||
if (i == 0)
|
||||
ctx.BeginFigure(point, isFilled: false, isClosed: false);
|
||||
else
|
||||
ctx.LineTo(point, isStroked: true, isSmoothJoin: true);
|
||||
}
|
||||
}
|
||||
|
||||
geometry.Freeze();
|
||||
var pen = new Pen(LineColor, LineThickness);
|
||||
pen.Freeze();
|
||||
drawingContext.DrawGeometry(null, pen, geometry);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user