#region Imports
|
|
using DPumpHydr.WinFrmUI.RLT.Helper;
|
using DPumpHydr.WinFrmUI.RLT.Manager;
|
using System;
|
using System.ComponentModel;
|
using System.Drawing;
|
using System.Drawing.Drawing2D;
|
using System.Windows.Forms;
|
using static DPumpHydr.WinFrmUI.RLT.Helper.MaterialDrawHelper;
|
using static DPumpHydr.WinFrmUI.RLT.Util.MaterialAnimations;
|
|
#endregion
|
|
namespace DPumpHydr.WinFrmUI.RLT.Controls
|
{
|
#region MaterialFloatingActionButton
|
|
public class MaterialFloatingActionButton : System.Windows.Forms.Button, MaterialControlI
|
{
|
[Browsable(false)]
|
public int Depth { get; set; }
|
|
[Browsable(false)]
|
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
|
[Browsable(false)]
|
public MaterialMouseState MouseState { get; set; }
|
|
private const int FAB_SIZE = 56;
|
private const int FAB_MINI_SIZE = 40;
|
private const int FAB_ICON_MARGIN = 16;
|
private const int FAB_MINI_ICON_MARGIN = 8;
|
private const int FAB_ICON_SIZE = 24;
|
|
private bool _mouseHover = false;
|
|
[DefaultValue(true)]
|
[Category("Material"), DisplayName("Draw Shadows")]
|
[Description("Draw Shadows around control")]
|
public bool DrawShadows { get; set; }
|
|
[DefaultValue(false)]
|
[Category("Material"), DisplayName("Size Mini")]
|
[Description("Set control size to default or mini")]
|
public bool Mini
|
{
|
get => _mini;
|
set
|
{
|
if (Parent != null)
|
{
|
Parent.Invalidate();
|
}
|
|
setSize(value);
|
}
|
}
|
|
private bool _mini;
|
|
[DefaultValue(false)]
|
[Category("Material"), DisplayName("Animate Show HideButton")]
|
public bool AnimateShowHideButton
|
{
|
get => _animateShowButton;
|
set { _animateShowButton = value; Refresh(); }
|
}
|
|
private bool _animateShowButton;
|
|
[DefaultValue(false)]
|
[Category("Material")]
|
[Description("Define icon to display")]
|
public Image Icon
|
{
|
get => _icon;
|
set { _icon = value; Refresh(); }
|
}
|
|
private Image _icon;
|
|
private bool _isHiding = false;
|
|
private readonly AnimationManager _animationManager;
|
|
private readonly AnimationManager _showAnimationManager;
|
|
public MaterialFloatingActionButton()
|
{
|
AnimateShowHideButton = false;
|
Mini = false;
|
DrawShadows = true;
|
SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
|
|
Size = new Size(FAB_SIZE, FAB_SIZE);
|
_animationManager = new AnimationManager(false)
|
{
|
Increment = 0.03,
|
AnimationType = AnimationType.EaseOut
|
};
|
_animationManager.OnAnimationProgress += sender => Invalidate();
|
|
_showAnimationManager = new AnimationManager(true)
|
{
|
Increment = 0.1,
|
AnimationType = AnimationType.EaseOut
|
};
|
_showAnimationManager.OnAnimationProgress += sender => Invalidate();
|
_showAnimationManager.OnAnimationFinished += _showAnimationManager_OnAnimationFinished;
|
}
|
|
protected override void InitLayout()
|
{
|
LocationChanged += (sender, e) => { if (DrawShadows) { Parent?.Invalidate(); } };
|
}
|
|
protected override void OnParentChanged(EventArgs e)
|
{
|
base.OnParentChanged(e);
|
if (DrawShadows && Parent != null)
|
{
|
AddShadowPaintEvent(Parent, drawShadowOnParent);
|
}
|
|
if (_oldParent != null)
|
{
|
RemoveShadowPaintEvent(_oldParent, drawShadowOnParent);
|
}
|
|
_oldParent = Parent;
|
}
|
|
private Control _oldParent;
|
|
protected override void OnVisibleChanged(EventArgs e)
|
{
|
base.OnVisibleChanged(e);
|
if (Parent == null)
|
{
|
return;
|
}
|
|
if (Visible)
|
{
|
AddShadowPaintEvent(Parent, drawShadowOnParent);
|
}
|
else
|
{
|
RemoveShadowPaintEvent(Parent, drawShadowOnParent);
|
}
|
}
|
|
private bool _shadowDrawEventSubscribed = false;
|
|
private void AddShadowPaintEvent(Control control, PaintEventHandler shadowPaintEvent)
|
{
|
if (_shadowDrawEventSubscribed)
|
{
|
return;
|
}
|
|
control.Paint += shadowPaintEvent;
|
control.Invalidate();
|
_shadowDrawEventSubscribed = true;
|
}
|
|
private void RemoveShadowPaintEvent(Control control, PaintEventHandler shadowPaintEvent)
|
{
|
if (!_shadowDrawEventSubscribed)
|
{
|
return;
|
}
|
|
control.Paint -= shadowPaintEvent;
|
control.Invalidate();
|
_shadowDrawEventSubscribed = false;
|
}
|
|
private void setSize(bool mini)
|
{
|
_mini = mini;
|
Size = _mini ? new Size(FAB_MINI_SIZE, FAB_MINI_SIZE) : new Size(FAB_SIZE, FAB_SIZE);
|
fabBounds = _mini ? new Rectangle(0, 0, FAB_MINI_SIZE, FAB_MINI_SIZE) : new Rectangle(0, 0, FAB_SIZE, FAB_SIZE);
|
fabBounds.Width -= 1;
|
fabBounds.Height -= 1;
|
}
|
|
private void _showAnimationManager_OnAnimationFinished(object sender)
|
{
|
if (_isHiding)
|
{
|
Visible = false;
|
_isHiding = false;
|
}
|
}
|
|
private void drawShadowOnParent(object sender, PaintEventArgs e)
|
{
|
if (Parent == null)
|
{
|
RemoveShadowPaintEvent((Control)sender, drawShadowOnParent);
|
return;
|
}
|
|
// paint shadow on parent
|
Graphics gp = e.Graphics;
|
Rectangle rect = new(Location, fabBounds.Size);
|
gp.SmoothingMode = SmoothingMode.AntiAlias;
|
DrawRoundShadow(gp, rect);
|
}
|
|
private Rectangle fabBounds;
|
|
protected override void OnPaint(PaintEventArgs pevent)
|
{
|
Graphics g = pevent.Graphics;
|
|
g.Clear(Parent.BackColor == Color.Transparent ? ((Parent.Parent == null || (Parent.Parent != null && Parent.Parent.BackColor == Color.Transparent)) ? SkinManager.BackgroundColor : Parent.Parent.BackColor) : Parent.BackColor);
|
g.SmoothingMode = SmoothingMode.AntiAlias;
|
|
// Paint shadow on element to blend with the parent shadow
|
DrawRoundShadow(g, fabBounds);
|
|
// draw fab
|
g.FillEllipse(Enabled ? _mouseHover ?
|
new SolidBrush(SkinManager.ColorScheme.AccentColor.Lighten(0.25f)) :
|
SkinManager.ColorScheme.AccentBrush :
|
new SolidBrush(BlendColor(SkinManager.ColorScheme.AccentColor, SkinManager.SwitchOffDisabledThumbColor, 197)),
|
fabBounds);
|
|
if (_animationManager.IsAnimating())
|
{
|
GraphicsPath regionPath = new();
|
regionPath.AddEllipse(new Rectangle(fabBounds.X - 1, fabBounds.Y - 1, fabBounds.Width + 3, fabBounds.Height + 2));
|
Region fabRegion = new(regionPath);
|
|
GraphicsContainer gcont = g.BeginContainer();
|
g.SetClip(fabRegion, CombineMode.Replace);
|
|
for (int i = 0; i < _animationManager.GetAnimationCount(); i++)
|
{
|
double animationValue = _animationManager.GetProgress(i);
|
Point animationSource = _animationManager.GetSource(i);
|
SolidBrush rippleBrush = new(Color.FromArgb((int)(51 - (animationValue * 50)), Color.White));
|
int rippleSize = (int)(animationValue * Width * 2);
|
g.FillEllipse(rippleBrush, new Rectangle(animationSource.X - (rippleSize / 2), animationSource.Y - (rippleSize / 2), rippleSize, rippleSize));
|
}
|
|
g.EndContainer(gcont);
|
}
|
|
if (Icon != null)
|
{
|
g.DrawImage(Icon, new Rectangle((fabBounds.Width / 2) - 11, (fabBounds.Height / 2) - 11, 24, 24));
|
}
|
|
if (_showAnimationManager.IsAnimating())
|
{
|
int target = Convert.ToInt32((_mini ? FAB_MINI_SIZE : FAB_SIZE) * _showAnimationManager.GetProgress());
|
fabBounds.Width = target == 0 ? 1 : target;
|
fabBounds.Height = target == 0 ? 1 : target;
|
fabBounds.X = Convert.ToInt32(((_mini ? FAB_MINI_SIZE : FAB_SIZE) / 2) - ((_mini ? FAB_MINI_SIZE : FAB_SIZE) / 2 * _showAnimationManager.GetProgress()));
|
fabBounds.Y = Convert.ToInt32(((_mini ? FAB_MINI_SIZE : FAB_SIZE) / 2) - ((_mini ? FAB_MINI_SIZE : FAB_SIZE) / 2 * _showAnimationManager.GetProgress()));
|
}
|
|
// Clip to a round shape with a 1px padding
|
GraphicsPath clipPath = new();
|
clipPath.AddEllipse(new Rectangle(fabBounds.X - 1, fabBounds.Y - 1, fabBounds.Width + 3, fabBounds.Height + 3));
|
Region = new Region(clipPath);
|
}
|
|
protected override void OnMouseClick(MouseEventArgs mevent)
|
{
|
base.OnMouseClick(mevent);
|
_animationManager.StartNewAnimation(AnimationDirection.In, mevent.Location);
|
}
|
|
protected override void OnMouseMove(MouseEventArgs e)
|
{
|
base.OnMouseMove(e);
|
|
if (DesignMode)
|
{
|
return;
|
}
|
|
_mouseHover = ClientRectangle.Contains(e.Location);
|
Invalidate();
|
}
|
|
protected override void OnMouseLeave(EventArgs e)
|
{
|
base.OnMouseLeave(e);
|
if (DesignMode)
|
{
|
return;
|
}
|
|
_mouseHover = false;
|
Invalidate();
|
}
|
|
protected override void OnResize(EventArgs e)
|
{
|
base.OnResize(e);
|
|
if (DrawShadows && Parent != null)
|
{
|
RemoveShadowPaintEvent(Parent, drawShadowOnParent);
|
AddShadowPaintEvent(Parent, drawShadowOnParent);
|
}
|
}
|
|
private Point origin;
|
|
public new void Hide()
|
{
|
if (Visible)
|
{
|
_isHiding = true;
|
_showAnimationManager.StartNewAnimation(AnimationDirection.Out);
|
}
|
}
|
|
public new void Show()
|
{
|
if (!Visible)
|
{
|
origin = Location;
|
_showAnimationManager.StartNewAnimation(AnimationDirection.In);
|
Visible = true;
|
}
|
}
|
}
|
|
#endregion
|
}
|