using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Text; using System.Windows.Forms; using MaterialSkin.Animations; namespace MaterialSkin.Controls { public class MaterialFlatButton : Button, IMaterialControl { [Browsable(false)] public int Depth { get; set; } [Browsable(false)] public MaterialSkinManager SkinManager => MaterialSkinManager.Instance; [Browsable(false)] public MouseState MouseState { get; set; } public bool Primary { get; set; } private readonly AnimationManager _animationManager; private readonly AnimationManager _hoverAnimationManager; private SizeF _textSize; private Image _icon; public Image Icon { get { return _icon; } set { _icon = value; if (AutoSize) Size = GetPreferredSize(); Invalidate(); } } public MaterialFlatButton() { Primary = false; _animationManager = new AnimationManager(false) { Increment = 0.03, AnimationType = AnimationType.EaseOut }; _hoverAnimationManager = new AnimationManager { Increment = 0.07, AnimationType = AnimationType.Linear }; _hoverAnimationManager.OnAnimationProgress += sender => Invalidate(); _animationManager.OnAnimationProgress += sender => Invalidate(); AutoSizeMode = AutoSizeMode.GrowAndShrink; Margin = new Padding(4, 6, 4, 6); Padding = new Padding(0); } public override string Text { get { return base.Text; } set { base.Text = value; _textSize = CreateGraphics().MeasureString(value.ToUpper(), SkinManager.ROBOTO_MEDIUM_10); if (AutoSize) Size = GetPreferredSize(); Invalidate(); } } protected override void OnPaint(PaintEventArgs pevent) { var g = pevent.Graphics; g.TextRenderingHint = TextRenderingHint.AntiAlias; g.Clear(Parent.BackColor); //Hover Color c = SkinManager.GetFlatButtonHoverBackgroundColor(); using (Brush b = new SolidBrush(Color.FromArgb((int)(_hoverAnimationManager.GetProgress() * c.A), c.RemoveAlpha()))) g.FillRectangle(b, ClientRectangle); //Ripple if (_animationManager.IsAnimating()) { g.SmoothingMode = SmoothingMode.AntiAlias; for (var i = 0; i < _animationManager.GetAnimationCount(); i++) { var animationValue = _animationManager.GetProgress(i); var animationSource = _animationManager.GetSource(i); using (Brush rippleBrush = new SolidBrush(Color.FromArgb((int)(101 - (animationValue * 100)), Color.Black))) { var rippleSize = (int)(animationValue * Width * 2); g.FillEllipse(rippleBrush, new Rectangle(animationSource.X - rippleSize / 2, animationSource.Y - rippleSize / 2, rippleSize, rippleSize)); } } g.SmoothingMode = SmoothingMode.None; } //Icon var iconRect = new Rectangle(8, 6, 24, 24); if (string.IsNullOrEmpty(Text)) // Center Icon iconRect.X += 2; if (Icon != null) g.DrawImage(Icon, iconRect); //Text var textRect = ClientRectangle; if (Icon != null) { // // Resize and move Text container // // First 8: left padding // 24: icon width // Second 4: space between Icon and Text // Third 8: right padding textRect.Width -= 8 + 24 + 4 + 8; // First 8: left padding // 24: icon width // Second 4: space between Icon and Text textRect.X += 8 + 24 + 4; } g.DrawString( Text.ToUpper(), SkinManager.ROBOTO_MEDIUM_10, Enabled ? (Primary ? SkinManager.ColorScheme.PrimaryBrush : SkinManager.GetPrimaryTextBrush()) : SkinManager.GetFlatButtonDisabledTextBrush(), textRect, new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center } ); } private Size GetPreferredSize() { return GetPreferredSize(new Size(0, 0)); } public override Size GetPreferredSize(Size proposedSize) { // Provides extra space for proper padding for content var extra = 16; if (Icon != null) // 24 is for icon size // 4 is for the space between icon & text extra += 24 + 4; return new Size((int)Math.Ceiling(_textSize.Width) + extra, 36); } protected override void OnCreateControl() { base.OnCreateControl(); if (DesignMode) return; MouseState = MouseState.OUT; MouseEnter += (sender, args) => { MouseState = MouseState.HOVER; _hoverAnimationManager.StartNewAnimation(AnimationDirection.In); Invalidate(); }; MouseLeave += (sender, args) => { MouseState = MouseState.OUT; _hoverAnimationManager.StartNewAnimation(AnimationDirection.Out); Invalidate(); }; MouseDown += (sender, args) => { if (args.Button == MouseButtons.Left) { MouseState = MouseState.DOWN; _animationManager.StartNewAnimation(AnimationDirection.In, args.Location); Invalidate(); } }; MouseUp += (sender, args) => { MouseState = MouseState.HOVER; Invalidate(); }; } } }