196 lines
7.5 KiB
C#
196 lines
7.5 KiB
C#
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 MaterialContextMenuStrip : ContextMenuStrip, IMaterialControl
|
|
{
|
|
//Properties for managing the material design properties
|
|
[Browsable(false)]
|
|
public int Depth { get; set; }
|
|
[Browsable(false)]
|
|
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
|
[Browsable(false)]
|
|
public MouseState MouseState { get; set; }
|
|
|
|
|
|
internal AnimationManager AnimationManager;
|
|
internal Point AnimationSource;
|
|
|
|
public delegate void ItemClickStart(object sender, ToolStripItemClickedEventArgs e);
|
|
public event ItemClickStart OnItemClickStart;
|
|
|
|
public MaterialContextMenuStrip()
|
|
{
|
|
Renderer = new MaterialToolStripRender();
|
|
|
|
AnimationManager = new AnimationManager(false)
|
|
{
|
|
Increment = 0.07,
|
|
AnimationType = AnimationType.Linear
|
|
};
|
|
AnimationManager.OnAnimationProgress += sender => Invalidate();
|
|
AnimationManager.OnAnimationFinished += sender => OnItemClicked(_delayesArgs);
|
|
|
|
BackColor = SkinManager.GetApplicationBackgroundColor();
|
|
}
|
|
|
|
protected override void OnMouseUp(MouseEventArgs mea)
|
|
{
|
|
base.OnMouseUp(mea);
|
|
|
|
AnimationSource = mea.Location;
|
|
}
|
|
|
|
private ToolStripItemClickedEventArgs _delayesArgs;
|
|
protected override void OnItemClicked(ToolStripItemClickedEventArgs e)
|
|
{
|
|
if (e.ClickedItem != null && !(e.ClickedItem is ToolStripSeparator))
|
|
{
|
|
if (e == _delayesArgs)
|
|
{
|
|
//The event has been fired manualy because the args are the ones we saved for delay
|
|
base.OnItemClicked(e);
|
|
}
|
|
else
|
|
{
|
|
//Interrupt the default on click, saving the args for the delay which is needed to display the animaton
|
|
_delayesArgs = e;
|
|
|
|
//Fire custom event to trigger actions directly but keep cms open
|
|
OnItemClickStart?.Invoke(this, e);
|
|
|
|
//Start animation
|
|
AnimationManager.StartNewAnimation(AnimationDirection.In);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public class MaterialToolStripMenuItem : ToolStripMenuItem
|
|
{
|
|
public MaterialToolStripMenuItem()
|
|
{
|
|
AutoSize = false;
|
|
Size = new Size(120, 30);
|
|
}
|
|
|
|
protected override ToolStripDropDown CreateDefaultDropDown()
|
|
{
|
|
var baseDropDown = base.CreateDefaultDropDown();
|
|
if (DesignMode) return baseDropDown;
|
|
|
|
var defaultDropDown = new MaterialContextMenuStrip();
|
|
defaultDropDown.Items.AddRange(baseDropDown.Items);
|
|
|
|
return defaultDropDown;
|
|
}
|
|
}
|
|
|
|
internal class MaterialToolStripRender : ToolStripProfessionalRenderer, IMaterialControl
|
|
{
|
|
//Properties for managing the material design properties
|
|
public int Depth { get; set; }
|
|
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
|
public MouseState MouseState { get; set; }
|
|
|
|
|
|
protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
|
|
{
|
|
var g = e.Graphics;
|
|
g.TextRenderingHint = TextRenderingHint.AntiAlias;
|
|
|
|
var itemRect = GetItemRect(e.Item);
|
|
var textRect = new Rectangle(24, itemRect.Y, itemRect.Width - (24 + 16), itemRect.Height);
|
|
g.DrawString(
|
|
e.Text,
|
|
SkinManager.ROBOTO_MEDIUM_10,
|
|
e.Item.Enabled ? SkinManager.GetPrimaryTextBrush() : SkinManager.GetDisabledOrHintBrush(),
|
|
textRect,
|
|
new StringFormat { LineAlignment = StringAlignment.Center });
|
|
}
|
|
|
|
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
|
|
{
|
|
var g = e.Graphics;
|
|
g.Clear(SkinManager.GetApplicationBackgroundColor());
|
|
|
|
//Draw background
|
|
var itemRect = GetItemRect(e.Item);
|
|
g.FillRectangle(e.Item.Selected && e.Item.Enabled ? SkinManager.GetCmsSelectedItemBrush() : new SolidBrush(SkinManager.GetApplicationBackgroundColor()), itemRect);
|
|
|
|
//Ripple animation
|
|
var toolStrip = e.ToolStrip as MaterialContextMenuStrip;
|
|
if (toolStrip != null)
|
|
{
|
|
var animationManager = toolStrip.AnimationManager;
|
|
var animationSource = toolStrip.AnimationSource;
|
|
if (toolStrip.AnimationManager.IsAnimating() && e.Item.Bounds.Contains(animationSource))
|
|
{
|
|
for (int i = 0; i < animationManager.GetAnimationCount(); i++)
|
|
{
|
|
var animationValue = animationManager.GetProgress(i);
|
|
var rippleBrush = new SolidBrush(Color.FromArgb((int)(51 - (animationValue * 50)), Color.Black));
|
|
var rippleSize = (int)(animationValue * itemRect.Width * 2.5);
|
|
g.FillEllipse(rippleBrush, new Rectangle(animationSource.X - rippleSize / 2, itemRect.Y - itemRect.Height, rippleSize, itemRect.Height * 3));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void OnRenderImageMargin(ToolStripRenderEventArgs e)
|
|
{
|
|
//base.OnRenderImageMargin(e);
|
|
}
|
|
|
|
protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
|
|
{
|
|
var g = e.Graphics;
|
|
|
|
g.FillRectangle(new SolidBrush(SkinManager.GetApplicationBackgroundColor()), e.Item.Bounds);
|
|
g.DrawLine(
|
|
new Pen(SkinManager.GetDividersColor()),
|
|
new Point(e.Item.Bounds.Left, e.Item.Bounds.Height / 2),
|
|
new Point(e.Item.Bounds.Right, e.Item.Bounds.Height / 2));
|
|
}
|
|
|
|
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
|
|
{
|
|
var g = e.Graphics;
|
|
|
|
g.DrawRectangle(
|
|
new Pen(SkinManager.GetDividersColor()),
|
|
new Rectangle(e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1));
|
|
}
|
|
|
|
protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
|
|
{
|
|
var g = e.Graphics;
|
|
const int ARROW_SIZE = 4;
|
|
|
|
var arrowMiddle = new Point(e.ArrowRectangle.X + e.ArrowRectangle.Width / 2, e.ArrowRectangle.Y + e.ArrowRectangle.Height / 2);
|
|
var arrowBrush = e.Item.Enabled ? SkinManager.GetPrimaryTextBrush() : SkinManager.GetDisabledOrHintBrush();
|
|
using (var arrowPath = new GraphicsPath())
|
|
{
|
|
arrowPath.AddLines(
|
|
new[] {
|
|
new Point(arrowMiddle.X - ARROW_SIZE, arrowMiddle.Y - ARROW_SIZE),
|
|
new Point(arrowMiddle.X, arrowMiddle.Y),
|
|
new Point(arrowMiddle.X - ARROW_SIZE, arrowMiddle.Y + ARROW_SIZE) });
|
|
arrowPath.CloseFigure();
|
|
|
|
g.FillPath(arrowBrush, arrowPath);
|
|
}
|
|
}
|
|
|
|
private Rectangle GetItemRect(ToolStripItem item)
|
|
{
|
|
return new Rectangle(0, item.ContentRectangle.Y, item.ContentRectangle.Width + 4, item.ContentRectangle.Height);
|
|
}
|
|
}
|
|
}
|