mirror of
https://github.com/jkocon/g-helper.git
synced 2026-02-23 13:00:52 +01:00
168 lines
4.7 KiB
C#
168 lines
4.7 KiB
C#
using System.Drawing.Drawing2D;
|
|
|
|
namespace GHelper.UI
|
|
{
|
|
public static class GraphicsExtensions
|
|
{
|
|
public static void DrawCircle(this Graphics g, Pen pen,
|
|
float centerX, float centerY, float radius)
|
|
{
|
|
g.DrawEllipse(pen, centerX - radius, centerY - radius,
|
|
radius + radius, radius + radius);
|
|
}
|
|
|
|
public static void FillCircle(this Graphics g, Brush brush,
|
|
float centerX, float centerY, float radius)
|
|
{
|
|
g.FillEllipse(brush, centerX - radius, centerY - radius,
|
|
radius + radius, radius + radius);
|
|
}
|
|
}
|
|
|
|
public class Slider : Control
|
|
{
|
|
private float _radius;
|
|
private PointF _thumbPos;
|
|
private SizeF _barSize;
|
|
private PointF _barPos;
|
|
|
|
public int Step = 1;
|
|
|
|
public Color accentColor = Color.FromArgb(255, 58, 174, 239);
|
|
public Color borderColor = Color.White;
|
|
|
|
public event EventHandler ValueChanged;
|
|
|
|
public Slider()
|
|
{
|
|
// This reduces flicker
|
|
DoubleBuffered = true;
|
|
}
|
|
|
|
private int _min = 0;
|
|
public int Min
|
|
{
|
|
get => _min;
|
|
set
|
|
{
|
|
_min = value;
|
|
RecalculateParameters();
|
|
}
|
|
}
|
|
|
|
private int _max = 100;
|
|
public int Max
|
|
{
|
|
get => _max;
|
|
set
|
|
{
|
|
_max = value;
|
|
RecalculateParameters();
|
|
}
|
|
}
|
|
|
|
private int _value = 50;
|
|
public int Value
|
|
{
|
|
get => _value;
|
|
set
|
|
{
|
|
|
|
value = (int)Math.Round(value / (float)Step) * Step;
|
|
|
|
if (_value != value)
|
|
{
|
|
_value = value;
|
|
ValueChanged?.Invoke(this, EventArgs.Empty);
|
|
RecalculateParameters();
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void OnPaint(PaintEventArgs e)
|
|
{
|
|
base.OnPaint(e);
|
|
|
|
Brush brushAccent = new SolidBrush(accentColor);
|
|
Brush brushEmpty = new SolidBrush(Color.Gray);
|
|
Brush brushBorder = new SolidBrush(borderColor);
|
|
|
|
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
|
e.Graphics.FillRectangle(brushEmpty,
|
|
_barPos.X, _barPos.Y, _barSize.Width, _barSize.Height);
|
|
e.Graphics.FillRectangle(brushAccent,
|
|
_barPos.X, _barPos.Y, _thumbPos.X - _barPos.X, _barSize.Height);
|
|
|
|
e.Graphics.FillCircle(brushBorder, _thumbPos.X, _thumbPos.Y, _radius);
|
|
e.Graphics.FillCircle(brushAccent, _thumbPos.X, _thumbPos.Y, 0.7f * _radius);
|
|
}
|
|
|
|
protected override void OnResize(EventArgs e)
|
|
{
|
|
base.OnResize(e);
|
|
RecalculateParameters();
|
|
}
|
|
|
|
private void RecalculateParameters()
|
|
{
|
|
_radius = 0.4F * ClientSize.Height;
|
|
_barSize = new SizeF(ClientSize.Width - 2 * _radius, ClientSize.Height * 0.15F);
|
|
_barPos = new PointF(_radius, (ClientSize.Height - _barSize.Height) / 2);
|
|
_thumbPos = new PointF(
|
|
_barSize.Width / (Max - Min) * (Value - Min) + _barPos.X,
|
|
_barPos.Y + 0.5f * _barSize.Height);
|
|
Invalidate();
|
|
}
|
|
|
|
bool _moving = false;
|
|
SizeF _delta;
|
|
|
|
protected override void OnMouseDown(MouseEventArgs e)
|
|
{
|
|
base.OnMouseDown(e);
|
|
|
|
// Difference between tumb and mouse position.
|
|
_delta = new SizeF(e.Location.X - _thumbPos.X, e.Location.Y - _thumbPos.Y);
|
|
if (_delta.Width * _delta.Width + _delta.Height * _delta.Height <= _radius * _radius)
|
|
{
|
|
// Clicking inside thumb.
|
|
_moving = true;
|
|
}
|
|
|
|
_calculateValue(e);
|
|
|
|
}
|
|
|
|
private void _calculateValue(MouseEventArgs e)
|
|
{
|
|
float thumbX = e.Location.X; // - _delta.Width;
|
|
if (thumbX < _barPos.X)
|
|
{
|
|
thumbX = _barPos.X;
|
|
}
|
|
else if (thumbX > _barPos.X + _barSize.Width)
|
|
{
|
|
thumbX = _barPos.X + _barSize.Width;
|
|
}
|
|
Value = (int)Math.Round(Min + (thumbX - _barPos.X) * (Max - Min) / _barSize.Width);
|
|
|
|
}
|
|
|
|
protected override void OnMouseMove(MouseEventArgs e)
|
|
{
|
|
base.OnMouseMove(e);
|
|
if (_moving)
|
|
{
|
|
_calculateValue(e);
|
|
}
|
|
}
|
|
|
|
protected override void OnMouseUp(MouseEventArgs e)
|
|
{
|
|
base.OnMouseUp(e);
|
|
_moving = false;
|
|
}
|
|
|
|
}
|
|
|
|
} |