check point
This commit is contained in:
250
framework/MaterialSkin.Core/Controls/MaterialCheckBox.cs
Normal file
250
framework/MaterialSkin.Core/Controls/MaterialCheckBox.cs
Normal file
@@ -0,0 +1,250 @@
|
||||
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 MaterialCheckBox : CheckBox, IMaterialControl
|
||||
{
|
||||
[Browsable(false)]
|
||||
public int Depth { get; set; }
|
||||
[Browsable(false)]
|
||||
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
||||
[Browsable(false)]
|
||||
public MouseState MouseState { get; set; }
|
||||
[Browsable(false)]
|
||||
public Point MouseLocation { get; set; }
|
||||
|
||||
private bool _ripple;
|
||||
[Category("Behavior")]
|
||||
public bool Ripple
|
||||
{
|
||||
get { return _ripple; }
|
||||
set
|
||||
{
|
||||
_ripple = value;
|
||||
AutoSize = AutoSize; //Make AutoSize directly set the bounds.
|
||||
|
||||
if (value)
|
||||
{
|
||||
Margin = new Padding(0);
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly AnimationManager _animationManager;
|
||||
private readonly AnimationManager _rippleAnimationManager;
|
||||
|
||||
private const int CHECKBOX_SIZE = 18;
|
||||
private const int CHECKBOX_SIZE_HALF = CHECKBOX_SIZE / 2;
|
||||
private const int CHECKBOX_INNER_BOX_SIZE = CHECKBOX_SIZE - 4;
|
||||
|
||||
private int _boxOffset;
|
||||
private Rectangle _boxRectangle;
|
||||
|
||||
public MaterialCheckBox()
|
||||
{
|
||||
_animationManager = new AnimationManager
|
||||
{
|
||||
AnimationType = AnimationType.EaseInOut,
|
||||
Increment = 0.05
|
||||
};
|
||||
_rippleAnimationManager = new AnimationManager(false)
|
||||
{
|
||||
AnimationType = AnimationType.Linear,
|
||||
Increment = 0.10,
|
||||
SecondaryIncrement = 0.08
|
||||
};
|
||||
_animationManager.OnAnimationProgress += sender => Invalidate();
|
||||
_rippleAnimationManager.OnAnimationProgress += sender => Invalidate();
|
||||
|
||||
CheckedChanged += (sender, args) =>
|
||||
{
|
||||
_animationManager.StartNewAnimation(Checked ? AnimationDirection.In : AnimationDirection.Out);
|
||||
};
|
||||
|
||||
Ripple = true;
|
||||
MouseLocation = new Point(-1, -1);
|
||||
}
|
||||
|
||||
protected override void OnSizeChanged(EventArgs e)
|
||||
{
|
||||
base.OnSizeChanged(e);
|
||||
|
||||
_boxOffset = Height / 2 - 9;
|
||||
_boxRectangle = new Rectangle(_boxOffset, _boxOffset, CHECKBOX_SIZE - 1, CHECKBOX_SIZE - 1);
|
||||
}
|
||||
|
||||
public override Size GetPreferredSize(Size proposedSize)
|
||||
{
|
||||
var w = _boxOffset + CHECKBOX_SIZE + 2 + (int)CreateGraphics().MeasureString(Text, SkinManager.ROBOTO_MEDIUM_10).Width;
|
||||
return Ripple ? new Size(w, 30) : new Size(w, 20);
|
||||
}
|
||||
|
||||
private static readonly Point[] CheckmarkLine = { new Point(3, 8), new Point(7, 12), new Point(14, 5) };
|
||||
private const int TEXT_OFFSET = 22;
|
||||
protected override void OnPaint(PaintEventArgs pevent)
|
||||
{
|
||||
var g = pevent.Graphics;
|
||||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
g.TextRenderingHint = TextRenderingHint.AntiAlias;
|
||||
|
||||
// clear the control
|
||||
g.Clear(Parent.BackColor);
|
||||
|
||||
var CHECKBOX_CENTER = _boxOffset + CHECKBOX_SIZE_HALF - 1;
|
||||
|
||||
var animationProgress = _animationManager.GetProgress();
|
||||
|
||||
var colorAlpha = Enabled ? (int)(animationProgress * 255.0) : SkinManager.GetCheckBoxOffDisabledColor().A;
|
||||
var backgroundAlpha = Enabled ? (int)(SkinManager.GetCheckboxOffColor().A * (1.0 - animationProgress)) : SkinManager.GetCheckBoxOffDisabledColor().A;
|
||||
|
||||
var brush = new SolidBrush(Color.FromArgb(colorAlpha, Enabled ? SkinManager.ColorScheme.AccentColor : SkinManager.GetCheckBoxOffDisabledColor()));
|
||||
var brush3 = new SolidBrush(Enabled ? SkinManager.ColorScheme.AccentColor : SkinManager.GetCheckBoxOffDisabledColor());
|
||||
var pen = new Pen(brush.Color);
|
||||
|
||||
// draw ripple animation
|
||||
if (Ripple && _rippleAnimationManager.IsAnimating())
|
||||
{
|
||||
for (var i = 0; i < _rippleAnimationManager.GetAnimationCount(); i++)
|
||||
{
|
||||
var animationValue = _rippleAnimationManager.GetProgress(i);
|
||||
var animationSource = new Point(CHECKBOX_CENTER, CHECKBOX_CENTER);
|
||||
var rippleBrush = new SolidBrush(Color.FromArgb((int)((animationValue * 40)), ((bool)_rippleAnimationManager.GetData(i)[0]) ? Color.Black : brush.Color));
|
||||
var rippleHeight = (Height % 2 == 0) ? Height - 3 : Height - 2;
|
||||
var rippleSize = (_rippleAnimationManager.GetDirection(i) == AnimationDirection.InOutIn) ? (int)(rippleHeight * (0.8d + (0.2d * animationValue))) : rippleHeight;
|
||||
using (var path = DrawHelper.CreateRoundRect(animationSource.X - rippleSize / 2, animationSource.Y - rippleSize / 2, rippleSize, rippleSize, rippleSize / 2))
|
||||
{
|
||||
g.FillPath(rippleBrush, path);
|
||||
}
|
||||
|
||||
rippleBrush.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
brush3.Dispose();
|
||||
|
||||
var checkMarkLineFill = new Rectangle(_boxOffset, _boxOffset, (int)((int)(FontHeight * 1.1) * animationProgress), (int)(FontHeight * 1.1));
|
||||
using (var checkmarkPath = DrawHelper.CreateRoundRect(_boxOffset, _boxOffset, (int)(FontHeight*1.1), (int)(FontHeight * 1.1), 1f))
|
||||
{
|
||||
var brush2 = new SolidBrush(DrawHelper.BlendColor(Parent.BackColor, Enabled ? SkinManager.GetCheckboxOffColor() : SkinManager.GetCheckBoxOffDisabledColor(), backgroundAlpha));
|
||||
var pen2 = new Pen(brush2.Color);
|
||||
g.FillPath(brush2, checkmarkPath);
|
||||
g.DrawPath(pen2, checkmarkPath);
|
||||
|
||||
g.FillRectangle(new SolidBrush(Parent.BackColor), _boxOffset + 2, _boxOffset + 2, (int)(FontHeight * 1.1) -4, (int)(FontHeight * 1.1) -4);
|
||||
g.DrawRectangle(new Pen(Parent.BackColor), _boxOffset + 2, _boxOffset + 2, (int)(FontHeight * 1.1) -4, (int)(FontHeight * 1.1) - 4);
|
||||
|
||||
brush2.Dispose();
|
||||
pen2.Dispose();
|
||||
|
||||
if (Enabled)
|
||||
{
|
||||
g.FillPath(brush, checkmarkPath);
|
||||
g.DrawPath(pen, checkmarkPath);
|
||||
}
|
||||
else if (Checked)
|
||||
{
|
||||
g.SmoothingMode = SmoothingMode.None;
|
||||
g.FillRectangle(brush, _boxOffset + 2, _boxOffset + 2, CHECKBOX_INNER_BOX_SIZE, CHECKBOX_INNER_BOX_SIZE);
|
||||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
}
|
||||
|
||||
g.DrawImageUnscaledAndClipped(DrawCheckMarkBitmap(), checkMarkLineFill);
|
||||
}
|
||||
|
||||
// draw checkbox text
|
||||
SizeF stringSize = g.MeasureString(Text, Font);
|
||||
g.DrawString(
|
||||
Text,
|
||||
Font,
|
||||
Enabled ? SkinManager.GetPrimaryTextBrush() : SkinManager.GetDisabledOrHintBrush(),
|
||||
_boxOffset + TEXT_OFFSET, Height / 2 - stringSize.Height / 2);
|
||||
|
||||
// dispose used paint objects
|
||||
pen.Dispose();
|
||||
brush.Dispose();
|
||||
}
|
||||
|
||||
private Bitmap DrawCheckMarkBitmap()
|
||||
{
|
||||
var checkMark = new Bitmap(CHECKBOX_SIZE, CHECKBOX_SIZE);
|
||||
var g = Graphics.FromImage(checkMark);
|
||||
|
||||
// clear everything, transparent
|
||||
g.Clear(Color.Transparent);
|
||||
|
||||
// draw the checkmark lines
|
||||
using (var pen = new Pen(Parent.BackColor, 2))
|
||||
{
|
||||
g.DrawLines(pen, CheckmarkLine);
|
||||
}
|
||||
|
||||
return checkMark;
|
||||
}
|
||||
|
||||
public override bool AutoSize
|
||||
{
|
||||
get { return base.AutoSize; }
|
||||
set
|
||||
{
|
||||
base.AutoSize = value;
|
||||
if (value)
|
||||
{
|
||||
Size = new Size(10, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsMouseInCheckArea()
|
||||
{
|
||||
return _boxRectangle.Contains(MouseLocation);
|
||||
}
|
||||
|
||||
protected override void OnCreateControl()
|
||||
{
|
||||
base.OnCreateControl();
|
||||
Font = SkinManager.ROBOTO_MEDIUM_10;
|
||||
|
||||
if (DesignMode) return;
|
||||
|
||||
MouseState = MouseState.OUT;
|
||||
MouseEnter += (sender, args) =>
|
||||
{
|
||||
MouseState = MouseState.HOVER;
|
||||
};
|
||||
MouseLeave += (sender, args) =>
|
||||
{
|
||||
MouseLocation = new Point(-1, -1);
|
||||
MouseState = MouseState.OUT;
|
||||
};
|
||||
MouseDown += (sender, args) =>
|
||||
{
|
||||
MouseState = MouseState.DOWN;
|
||||
|
||||
if (Ripple && args.Button == MouseButtons.Left && IsMouseInCheckArea())
|
||||
{
|
||||
_rippleAnimationManager.SecondaryIncrement = 0;
|
||||
_rippleAnimationManager.StartNewAnimation(AnimationDirection.InOutIn, new object[] { Checked });
|
||||
}
|
||||
};
|
||||
MouseUp += (sender, args) =>
|
||||
{
|
||||
MouseState = MouseState.HOVER;
|
||||
_rippleAnimationManager.SecondaryIncrement = 0.08;
|
||||
};
|
||||
MouseMove += (sender, args) =>
|
||||
{
|
||||
MouseLocation = args.Location;
|
||||
Cursor = IsMouseInCheckArea() ? Cursors.Hand : Cursors.Default;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
44
framework/MaterialSkin.Core/Controls/MaterialComboBox.cs
Normal file
44
framework/MaterialSkin.Core/Controls/MaterialComboBox.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
public partial class MaterialComboBox : ComboBox
|
||||
{
|
||||
|
||||
[Browsable(false)]
|
||||
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
||||
public MaterialComboBox()
|
||||
{
|
||||
|
||||
DrawMode = DrawMode.OwnerDrawFixed;
|
||||
|
||||
DrawItem += AdvancedComboBox_DrawItem;
|
||||
|
||||
}
|
||||
|
||||
void AdvancedComboBox_DrawItem(object sender, DrawItemEventArgs e)
|
||||
{
|
||||
if (e.Index < 0)
|
||||
return;
|
||||
|
||||
ComboBox combo = sender as ComboBox;
|
||||
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
|
||||
e.Graphics.FillRectangle(new SolidBrush(SkinManager.ColorScheme.AccentColor),
|
||||
e.Bounds);
|
||||
else
|
||||
e.Graphics.FillRectangle(new SolidBrush(combo.BackColor),
|
||||
e.Bounds);
|
||||
|
||||
e.Graphics.DrawString(combo.Items[e.Index].ToString(), e.Font,
|
||||
SkinManager.GetRaisedButtonTextBrush((e.State & DrawItemState.Selected) == DrawItemState.Selected),
|
||||
new Point(e.Bounds.X, e.Bounds.Y));
|
||||
|
||||
e.DrawFocusRectangle();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
195
framework/MaterialSkin.Core/Controls/MaterialContextMenuStrip.cs
Normal file
195
framework/MaterialSkin.Core/Controls/MaterialContextMenuStrip.cs
Normal file
@@ -0,0 +1,195 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
framework/MaterialSkin.Core/Controls/MaterialDivider.cs
Normal file
27
framework/MaterialSkin.Core/Controls/MaterialDivider.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
public sealed class MaterialDivider : Control, IMaterialControl
|
||||
{
|
||||
[Browsable(false)]
|
||||
public int Depth { get; set; }
|
||||
[Browsable(false)]
|
||||
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
||||
[Browsable(false)]
|
||||
public MouseState MouseState { get; set; }
|
||||
|
||||
public MaterialDivider()
|
||||
{
|
||||
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
|
||||
|
||||
}
|
||||
|
||||
protected override void OnPaintBackground(PaintEventArgs pevent)
|
||||
{
|
||||
BackColor = SkinManager.ColorScheme.PrimaryColor;
|
||||
base.OnPaintBackground(pevent);
|
||||
}
|
||||
}
|
||||
}
|
||||
200
framework/MaterialSkin.Core/Controls/MaterialFlatButton.cs
Normal file
200
framework/MaterialSkin.Core/Controls/MaterialFlatButton.cs
Normal file
@@ -0,0 +1,200 @@
|
||||
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();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
619
framework/MaterialSkin.Core/Controls/MaterialForm.cs
Normal file
619
framework/MaterialSkin.Core/Controls/MaterialForm.cs
Normal file
@@ -0,0 +1,619 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Text;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
public class MaterialForm : Form, IMaterialControl
|
||||
{
|
||||
[Browsable(false)]
|
||||
public int Depth { get; set; }
|
||||
[Browsable(false)]
|
||||
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
||||
[Browsable(false)]
|
||||
public MouseState MouseState { get; set; }
|
||||
public new FormBorderStyle FormBorderStyle { get { return base.FormBorderStyle; } set { base.FormBorderStyle = value; } }
|
||||
public bool Sizable { get; set; }
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool ReleaseCapture();
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int TrackPopupMenuEx(IntPtr hmenu, uint fuFlags, int x, int y, IntPtr hwnd, IntPtr lptpm);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);
|
||||
|
||||
[DllImport("User32.dll", CharSet = CharSet.Auto)]
|
||||
public static extern bool GetMonitorInfo(HandleRef hmonitor, [In, Out] MONITORINFOEX info);
|
||||
|
||||
public const int WM_NCLBUTTONDOWN = 0xA1;
|
||||
public const int HT_CAPTION = 0x2;
|
||||
public const int WM_MOUSEMOVE = 0x0200;
|
||||
public const int WM_LBUTTONDOWN = 0x0201;
|
||||
public const int WM_LBUTTONUP = 0x0202;
|
||||
public const int WM_LBUTTONDBLCLK = 0x0203;
|
||||
public const int WM_RBUTTONDOWN = 0x0204;
|
||||
private const int HTBOTTOMLEFT = 16;
|
||||
private const int HTBOTTOMRIGHT = 17;
|
||||
private const int HTLEFT = 10;
|
||||
private const int HTRIGHT = 11;
|
||||
private const int HTBOTTOM = 15;
|
||||
private const int HTTOP = 12;
|
||||
private const int HTTOPLEFT = 13;
|
||||
private const int HTTOPRIGHT = 14;
|
||||
private const int BORDER_WIDTH = 7;
|
||||
private ResizeDirection _resizeDir;
|
||||
private ButtonState _buttonState = ButtonState.None;
|
||||
|
||||
private const int WMSZ_TOP = 3;
|
||||
private const int WMSZ_TOPLEFT = 4;
|
||||
private const int WMSZ_TOPRIGHT = 5;
|
||||
private const int WMSZ_LEFT = 1;
|
||||
private const int WMSZ_RIGHT = 2;
|
||||
private const int WMSZ_BOTTOM = 6;
|
||||
private const int WMSZ_BOTTOMLEFT = 7;
|
||||
private const int WMSZ_BOTTOMRIGHT = 8;
|
||||
|
||||
private readonly Dictionary<int, int> _resizingLocationsToCmd = new Dictionary<int, int>
|
||||
{
|
||||
{HTTOP, WMSZ_TOP},
|
||||
{HTTOPLEFT, WMSZ_TOPLEFT},
|
||||
{HTTOPRIGHT, WMSZ_TOPRIGHT},
|
||||
{HTLEFT, WMSZ_LEFT},
|
||||
{HTRIGHT, WMSZ_RIGHT},
|
||||
{HTBOTTOM, WMSZ_BOTTOM},
|
||||
{HTBOTTOMLEFT, WMSZ_BOTTOMLEFT},
|
||||
{HTBOTTOMRIGHT, WMSZ_BOTTOMRIGHT}
|
||||
};
|
||||
|
||||
private const int STATUS_BAR_BUTTON_WIDTH = STATUS_BAR_HEIGHT;
|
||||
private const int STATUS_BAR_HEIGHT = 24;
|
||||
private const int ACTION_BAR_HEIGHT = 40;
|
||||
|
||||
private const uint TPM_LEFTALIGN = 0x0000;
|
||||
private const uint TPM_RETURNCMD = 0x0100;
|
||||
|
||||
private const int WM_SYSCOMMAND = 0x0112;
|
||||
private const int WS_MINIMIZEBOX = 0x20000;
|
||||
private const int WS_SYSMENU = 0x00080000;
|
||||
|
||||
private const int MONITOR_DEFAULTTONEAREST = 2;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
|
||||
public class MONITORINFOEX
|
||||
{
|
||||
public int cbSize = Marshal.SizeOf(typeof(MONITORINFOEX));
|
||||
public RECT rcMonitor = new RECT();
|
||||
public RECT rcWork = new RECT();
|
||||
public int dwFlags = 0;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
|
||||
public char[] szDevice = new char[32];
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct RECT
|
||||
{
|
||||
public int left;
|
||||
public int top;
|
||||
public int right;
|
||||
public int bottom;
|
||||
|
||||
public int Width()
|
||||
{
|
||||
return right - left;
|
||||
}
|
||||
|
||||
public int Height()
|
||||
{
|
||||
return bottom - top;
|
||||
}
|
||||
}
|
||||
|
||||
private enum ResizeDirection
|
||||
{
|
||||
BottomLeft,
|
||||
Left,
|
||||
Right,
|
||||
BottomRight,
|
||||
Bottom,
|
||||
None
|
||||
}
|
||||
|
||||
private enum ButtonState
|
||||
{
|
||||
XOver,
|
||||
MaxOver,
|
||||
MinOver,
|
||||
XDown,
|
||||
MaxDown,
|
||||
MinDown,
|
||||
None
|
||||
}
|
||||
|
||||
private readonly Cursor[] _resizeCursors = { Cursors.SizeNESW, Cursors.SizeWE, Cursors.SizeNWSE, Cursors.SizeWE, Cursors.SizeNS };
|
||||
|
||||
private Rectangle _minButtonBounds;
|
||||
private Rectangle _maxButtonBounds;
|
||||
private Rectangle _xButtonBounds;
|
||||
private Rectangle _actionBarBounds;
|
||||
private Rectangle _statusBarBounds;
|
||||
|
||||
private bool _maximized;
|
||||
private Size _previousSize;
|
||||
private Point _previousLocation;
|
||||
private bool _headerMouseDown;
|
||||
private MouseMessageFilter _mouseMessageFilter;
|
||||
|
||||
|
||||
public MaterialForm()
|
||||
{
|
||||
FormBorderStyle = FormBorderStyle.None;
|
||||
AutoScaleMode = AutoScaleMode.None;
|
||||
DoubleBuffered = true;
|
||||
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true);
|
||||
|
||||
// This enables the form to trigger the MouseMove event even when mouse is over another control
|
||||
//_mouseMessageFilter = new MouseMessageFilter();
|
||||
//Application.AddMessageFilter(_mouseMessageFilter);
|
||||
//MouseMessageFilter.MouseMove += OnGlobalMouseMove;
|
||||
}
|
||||
|
||||
public void RemoveMessageFilter()
|
||||
{
|
||||
Application.RemoveMessageFilter(_mouseMessageFilter);
|
||||
MouseMessageFilter.MouseMove -= OnGlobalMouseMove;
|
||||
}
|
||||
|
||||
protected override void WndProc(ref Message m)
|
||||
{
|
||||
base.WndProc(ref m);
|
||||
if (DesignMode || IsDisposed) return;
|
||||
|
||||
if (m.Msg == WM_LBUTTONDBLCLK)
|
||||
{
|
||||
MaximizeWindow(!_maximized);
|
||||
}
|
||||
else if (m.Msg == WM_MOUSEMOVE && _maximized &&
|
||||
(_statusBarBounds.Contains(PointToClient(Cursor.Position)) || _actionBarBounds.Contains(PointToClient(Cursor.Position))) &&
|
||||
!(_minButtonBounds.Contains(PointToClient(Cursor.Position)) || _maxButtonBounds.Contains(PointToClient(Cursor.Position)) || _xButtonBounds.Contains(PointToClient(Cursor.Position))))
|
||||
{
|
||||
if (_headerMouseDown)
|
||||
{
|
||||
_maximized = false;
|
||||
_headerMouseDown = false;
|
||||
|
||||
var mousePoint = PointToClient(Cursor.Position);
|
||||
if (mousePoint.X < Width / 2)
|
||||
Location = mousePoint.X < _previousSize.Width / 2 ?
|
||||
new Point(Cursor.Position.X - mousePoint.X, Cursor.Position.Y - mousePoint.Y) :
|
||||
new Point(Cursor.Position.X - _previousSize.Width / 2, Cursor.Position.Y - mousePoint.Y);
|
||||
else
|
||||
Location = Width - mousePoint.X < _previousSize.Width / 2 ?
|
||||
new Point(Cursor.Position.X - _previousSize.Width + Width - mousePoint.X, Cursor.Position.Y - mousePoint.Y) :
|
||||
new Point(Cursor.Position.X - _previousSize.Width / 2, Cursor.Position.Y - mousePoint.Y);
|
||||
|
||||
Size = _previousSize;
|
||||
ReleaseCapture();
|
||||
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
|
||||
}
|
||||
}
|
||||
else if (m.Msg == WM_LBUTTONDOWN &&
|
||||
(_statusBarBounds.Contains(PointToClient(Cursor.Position)) || _actionBarBounds.Contains(PointToClient(Cursor.Position))) &&
|
||||
!(_minButtonBounds.Contains(PointToClient(Cursor.Position)) || _maxButtonBounds.Contains(PointToClient(Cursor.Position)) || _xButtonBounds.Contains(PointToClient(Cursor.Position))))
|
||||
{
|
||||
if (!_maximized)
|
||||
{
|
||||
ReleaseCapture();
|
||||
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
_headerMouseDown = true;
|
||||
}
|
||||
}
|
||||
else if (m.Msg == WM_RBUTTONDOWN)
|
||||
{
|
||||
Point cursorPos = PointToClient(Cursor.Position);
|
||||
|
||||
if (_statusBarBounds.Contains(cursorPos) && !_minButtonBounds.Contains(cursorPos) &&
|
||||
!_maxButtonBounds.Contains(cursorPos) && !_xButtonBounds.Contains(cursorPos))
|
||||
{
|
||||
// Show default system menu when right clicking titlebar
|
||||
var id = TrackPopupMenuEx(GetSystemMenu(Handle, false), TPM_LEFTALIGN | TPM_RETURNCMD, Cursor.Position.X, Cursor.Position.Y, Handle, IntPtr.Zero);
|
||||
|
||||
// Pass the command as a WM_SYSCOMMAND message
|
||||
SendMessage(Handle, WM_SYSCOMMAND, id, 0);
|
||||
}
|
||||
}
|
||||
else if (m.Msg == WM_NCLBUTTONDOWN)
|
||||
{
|
||||
// This re-enables resizing by letting the application know when the
|
||||
// user is trying to resize a side. This is disabled by default when using WS_SYSMENU.
|
||||
if (!Sizable) return;
|
||||
|
||||
byte bFlag = 0;
|
||||
|
||||
// Get which side to resize from
|
||||
if (_resizingLocationsToCmd.ContainsKey((int)m.WParam))
|
||||
bFlag = (byte)_resizingLocationsToCmd[(int)m.WParam];
|
||||
|
||||
if (bFlag != 0)
|
||||
SendMessage(Handle, WM_SYSCOMMAND, 0xF000 | bFlag, (int)m.LParam);
|
||||
}
|
||||
else if (m.Msg == WM_LBUTTONUP)
|
||||
{
|
||||
_headerMouseDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool DropShadow { get; set; } = true;
|
||||
protected override CreateParams CreateParams
|
||||
{
|
||||
get
|
||||
{
|
||||
const int CS_DROPSHADOW = 0x20000;
|
||||
var par = base.CreateParams;
|
||||
// WS_SYSMENU: Trigger the creation of the system menu
|
||||
// WS_MINIMIZEBOX: Allow minimizing from taskbar
|
||||
par.Style = par.Style | WS_MINIMIZEBOX | WS_SYSMENU; // Turn on the WS_MINIMIZEBOX style flag
|
||||
if(DropShadow)
|
||||
par.ClassStyle |= CS_DROPSHADOW;
|
||||
return par;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMouseDown(MouseEventArgs e)
|
||||
{
|
||||
if (DesignMode) return;
|
||||
UpdateButtons(e);
|
||||
|
||||
if (e.Button == MouseButtons.Left && !_maximized)
|
||||
ResizeForm(_resizeDir);
|
||||
base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override void OnMouseLeave(EventArgs e)
|
||||
{
|
||||
base.OnMouseLeave(e);
|
||||
if (DesignMode) return;
|
||||
_buttonState = ButtonState.None;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseMove(e);
|
||||
|
||||
if (DesignMode) return;
|
||||
|
||||
if (Sizable)
|
||||
{
|
||||
//True if the mouse is hovering over a child control
|
||||
var isChildUnderMouse = GetChildAtPoint(e.Location) != null;
|
||||
|
||||
if (e.Location.X < BORDER_WIDTH && e.Location.Y > Height - BORDER_WIDTH && !isChildUnderMouse && !_maximized)
|
||||
{
|
||||
_resizeDir = ResizeDirection.BottomLeft;
|
||||
Cursor = Cursors.SizeNESW;
|
||||
}
|
||||
else if (e.Location.X < BORDER_WIDTH && !isChildUnderMouse && !_maximized)
|
||||
{
|
||||
_resizeDir = ResizeDirection.Left;
|
||||
Cursor = Cursors.SizeWE;
|
||||
}
|
||||
else if (e.Location.X > Width - BORDER_WIDTH && e.Location.Y > Height - BORDER_WIDTH && !isChildUnderMouse && !_maximized)
|
||||
{
|
||||
_resizeDir = ResizeDirection.BottomRight;
|
||||
Cursor = Cursors.SizeNWSE;
|
||||
}
|
||||
else if (e.Location.X > Width - BORDER_WIDTH && !isChildUnderMouse && !_maximized)
|
||||
{
|
||||
_resizeDir = ResizeDirection.Right;
|
||||
Cursor = Cursors.SizeWE;
|
||||
}
|
||||
else if (e.Location.Y > Height - BORDER_WIDTH && !isChildUnderMouse && !_maximized)
|
||||
{
|
||||
_resizeDir = ResizeDirection.Bottom;
|
||||
Cursor = Cursors.SizeNS;
|
||||
}
|
||||
else
|
||||
{
|
||||
_resizeDir = ResizeDirection.None;
|
||||
|
||||
//Only reset the cursor when needed, this prevents it from flickering when a child control changes the cursor to its own needs
|
||||
if (_resizeCursors.Contains(Cursor))
|
||||
{
|
||||
Cursor = Cursors.Default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateButtons(e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected void OnGlobalMouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
|
||||
if (IsDisposed) return;
|
||||
// Convert to client position and pass to Form.MouseMove
|
||||
var clientCursorPos = PointToClient(e.Location);
|
||||
var newE = new MouseEventArgs(MouseButtons.None, 0, clientCursorPos.X, clientCursorPos.Y, 0);
|
||||
OnMouseMove(newE);
|
||||
|
||||
}
|
||||
|
||||
private void UpdateButtons(MouseEventArgs e, bool up = false)
|
||||
{
|
||||
if (DesignMode) return;
|
||||
var oldState = _buttonState;
|
||||
bool showMin = MinimizeBox && ControlBox;
|
||||
bool showMax = MaximizeBox && ControlBox;
|
||||
|
||||
if (e.Button == MouseButtons.Left && !up)
|
||||
{
|
||||
if (showMin && !showMax && _maxButtonBounds.Contains(e.Location))
|
||||
_buttonState = ButtonState.MinDown;
|
||||
else if (showMin && showMax && _minButtonBounds.Contains(e.Location))
|
||||
_buttonState = ButtonState.MinDown;
|
||||
else if (showMax && _maxButtonBounds.Contains(e.Location))
|
||||
_buttonState = ButtonState.MaxDown;
|
||||
else if (ControlBox && _xButtonBounds.Contains(e.Location))
|
||||
_buttonState = ButtonState.XDown;
|
||||
else
|
||||
_buttonState = ButtonState.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (showMin && !showMax && _maxButtonBounds.Contains(e.Location))
|
||||
{
|
||||
_buttonState = ButtonState.MinOver;
|
||||
|
||||
if (oldState == ButtonState.MinDown && up)
|
||||
WindowState = FormWindowState.Minimized;
|
||||
}
|
||||
else if (showMin && showMax && _minButtonBounds.Contains(e.Location))
|
||||
{
|
||||
_buttonState = ButtonState.MinOver;
|
||||
|
||||
if (oldState == ButtonState.MinDown && up)
|
||||
WindowState = FormWindowState.Minimized;
|
||||
}
|
||||
else if (MaximizeBox && ControlBox && _maxButtonBounds.Contains(e.Location))
|
||||
{
|
||||
_buttonState = ButtonState.MaxOver;
|
||||
|
||||
if (oldState == ButtonState.MaxDown && up)
|
||||
MaximizeWindow(!_maximized);
|
||||
|
||||
}
|
||||
else if (ControlBox && _xButtonBounds.Contains(e.Location))
|
||||
{
|
||||
_buttonState = ButtonState.XOver;
|
||||
|
||||
if (oldState == ButtonState.XDown && up)
|
||||
Close();
|
||||
}
|
||||
else _buttonState = ButtonState.None;
|
||||
}
|
||||
|
||||
if (oldState != _buttonState) Invalidate();
|
||||
}
|
||||
|
||||
public void MaximizeWindow(bool maximize)
|
||||
{
|
||||
if (!MaximizeBox || !ControlBox) return;
|
||||
|
||||
_maximized = maximize;
|
||||
|
||||
if (maximize)
|
||||
{
|
||||
var monitorHandle = MonitorFromWindow(Handle, MONITOR_DEFAULTTONEAREST);
|
||||
var monitorInfo = new MONITORINFOEX();
|
||||
GetMonitorInfo(new HandleRef(null, monitorHandle), monitorInfo);
|
||||
_previousSize = Size;
|
||||
_previousLocation = Location;
|
||||
|
||||
//var area=Screen.FromHandle(this.Handle).WorkingArea;
|
||||
|
||||
Size = new Size(monitorInfo.rcWork.Width(), monitorInfo.rcWork.Height());
|
||||
Location = new Point(monitorInfo.rcWork.left, monitorInfo.rcWork.top);
|
||||
//Size = new Size(area.Width, area.Height);
|
||||
//Location = new Point(area.Left, area.Top);
|
||||
}
|
||||
else
|
||||
{
|
||||
Size = _previousSize;
|
||||
Location = _previousLocation;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected override void OnMouseUp(MouseEventArgs e)
|
||||
{
|
||||
if (DesignMode) return;
|
||||
UpdateButtons(e, true);
|
||||
|
||||
base.OnMouseUp(e);
|
||||
ReleaseCapture();
|
||||
}
|
||||
|
||||
private void ResizeForm(ResizeDirection direction)
|
||||
{
|
||||
if (DesignMode) return;
|
||||
var dir = -1;
|
||||
switch (direction)
|
||||
{
|
||||
case ResizeDirection.BottomLeft:
|
||||
dir = HTBOTTOMLEFT;
|
||||
break;
|
||||
case ResizeDirection.Left:
|
||||
dir = HTLEFT;
|
||||
break;
|
||||
case ResizeDirection.Right:
|
||||
dir = HTRIGHT;
|
||||
break;
|
||||
case ResizeDirection.BottomRight:
|
||||
dir = HTBOTTOMRIGHT;
|
||||
break;
|
||||
case ResizeDirection.Bottom:
|
||||
dir = HTBOTTOM;
|
||||
break;
|
||||
}
|
||||
|
||||
ReleaseCapture();
|
||||
if (dir != -1)
|
||||
{
|
||||
SendMessage(Handle, WM_NCLBUTTONDOWN, dir, 0);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnResize(EventArgs e)
|
||||
{
|
||||
base.OnResize(e);
|
||||
|
||||
_minButtonBounds = new Rectangle((Width - SkinManager.FORM_PADDING / 2) - 3 * STATUS_BAR_BUTTON_WIDTH, 0, STATUS_BAR_BUTTON_WIDTH, STATUS_BAR_HEIGHT);
|
||||
_maxButtonBounds = new Rectangle((Width - SkinManager.FORM_PADDING / 2) - 2 * STATUS_BAR_BUTTON_WIDTH, 0, STATUS_BAR_BUTTON_WIDTH, STATUS_BAR_HEIGHT);
|
||||
_xButtonBounds = new Rectangle((Width - SkinManager.FORM_PADDING / 2) - STATUS_BAR_BUTTON_WIDTH, 0, STATUS_BAR_BUTTON_WIDTH, STATUS_BAR_HEIGHT);
|
||||
_statusBarBounds = new Rectangle(0, 0, Width, STATUS_BAR_HEIGHT);
|
||||
_actionBarBounds = new Rectangle(0, STATUS_BAR_HEIGHT, Width, ACTION_BAR_HEIGHT);
|
||||
}
|
||||
|
||||
public bool ShowSubHeader { get; set; }
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
var g = e.Graphics;
|
||||
g.TextRenderingHint = TextRenderingHint.AntiAlias;
|
||||
|
||||
g.Clear(SkinManager.GetApplicationBackgroundColor());
|
||||
g.FillRectangle(SkinManager.ColorScheme.DarkPrimaryBrush, _statusBarBounds);
|
||||
if(ShowSubHeader) g.FillRectangle(SkinManager.ColorScheme.PrimaryBrush, _actionBarBounds);
|
||||
|
||||
//Draw border
|
||||
using (var borderPen = new Pen(SkinManager.GetDividersColor(), 1))
|
||||
{
|
||||
g.DrawLine(borderPen, new Point(0, _statusBarBounds.Bottom), new Point(0, Height - 2));
|
||||
g.DrawLine(borderPen, new Point(Width - 1, _statusBarBounds.Bottom), new Point(Width - 1, Height - 2));
|
||||
g.DrawLine(borderPen, new Point(0, Height - 1), new Point(Width - 1, Height - 1));
|
||||
}
|
||||
|
||||
// Determine whether or not we even should be drawing the buttons.
|
||||
bool showMin = MinimizeBox && ControlBox;
|
||||
bool showMax = MaximizeBox && ControlBox;
|
||||
var hoverBrush = SkinManager.GetFlatButtonHoverBackgroundBrush();
|
||||
var downBrush = SkinManager.GetFlatButtonPressedBackgroundBrush();
|
||||
|
||||
// When MaximizeButton == false, the minimize button will be painted in its place
|
||||
if (_buttonState == ButtonState.MinOver && showMin)
|
||||
g.FillRectangle(hoverBrush, showMax ? _minButtonBounds : _maxButtonBounds);
|
||||
|
||||
if (_buttonState == ButtonState.MinDown && showMin)
|
||||
g.FillRectangle(downBrush, showMax ? _minButtonBounds : _maxButtonBounds);
|
||||
|
||||
if (_buttonState == ButtonState.MaxOver && showMax)
|
||||
g.FillRectangle(hoverBrush, _maxButtonBounds);
|
||||
|
||||
if (_buttonState == ButtonState.MaxDown && showMax)
|
||||
g.FillRectangle(downBrush, _maxButtonBounds);
|
||||
|
||||
if (_buttonState == ButtonState.XOver && ControlBox)
|
||||
g.FillRectangle(hoverBrush, _xButtonBounds);
|
||||
|
||||
if (_buttonState == ButtonState.XDown && ControlBox)
|
||||
g.FillRectangle(downBrush, _xButtonBounds);
|
||||
|
||||
using (var formButtonsPen = new Pen(SkinManager.ACTION_BAR_TEXT_SECONDARY, 2))
|
||||
{
|
||||
// Minimize button.
|
||||
if (showMin)
|
||||
{
|
||||
int x = showMax ? _minButtonBounds.X : _maxButtonBounds.X;
|
||||
int y = showMax ? _minButtonBounds.Y : _maxButtonBounds.Y;
|
||||
|
||||
g.DrawLine(
|
||||
formButtonsPen,
|
||||
x + (int)(_minButtonBounds.Width * 0.33),
|
||||
y + (int)(_minButtonBounds.Height * 0.66),
|
||||
x + (int)(_minButtonBounds.Width * 0.66),
|
||||
y + (int)(_minButtonBounds.Height * 0.66)
|
||||
);
|
||||
}
|
||||
|
||||
// Maximize button
|
||||
if (showMax)
|
||||
{
|
||||
g.DrawRectangle(
|
||||
formButtonsPen,
|
||||
_maxButtonBounds.X + (int)(_maxButtonBounds.Width * 0.33),
|
||||
_maxButtonBounds.Y + (int)(_maxButtonBounds.Height * 0.36),
|
||||
(int)(_maxButtonBounds.Width * 0.39),
|
||||
(int)(_maxButtonBounds.Height * 0.31)
|
||||
);
|
||||
}
|
||||
|
||||
// Close button
|
||||
if (ControlBox)
|
||||
{
|
||||
g.DrawLine(
|
||||
formButtonsPen,
|
||||
_xButtonBounds.X + (int)(_xButtonBounds.Width * 0.33),
|
||||
_xButtonBounds.Y + (int)(_xButtonBounds.Height * 0.33),
|
||||
_xButtonBounds.X + (int)(_xButtonBounds.Width * 0.66),
|
||||
_xButtonBounds.Y + (int)(_xButtonBounds.Height * 0.66)
|
||||
);
|
||||
|
||||
g.DrawLine(
|
||||
formButtonsPen,
|
||||
_xButtonBounds.X + (int)(_xButtonBounds.Width * 0.66),
|
||||
_xButtonBounds.Y + (int)(_xButtonBounds.Height * 0.33),
|
||||
_xButtonBounds.X + (int)(_xButtonBounds.Width * 0.33),
|
||||
_xButtonBounds.Y + (int)(_xButtonBounds.Height * 0.66));
|
||||
}
|
||||
}
|
||||
|
||||
//Form title
|
||||
g.DrawString(Text, SkinManager.ROBOTO_MEDIUM_12, SkinManager.ColorScheme.TextBrush, new Rectangle(SkinManager.FORM_PADDING, STATUS_BAR_HEIGHT, Width-20, ACTION_BAR_HEIGHT), new StringFormat { LineAlignment = StringAlignment.Center,Alignment = StringAlignment.Near });
|
||||
//Primary title
|
||||
g.DrawString(PrimaryText, new Font("Roboto",20,FontStyle.Bold),SkinManager.ColorScheme.TextBrush, new Rectangle(SkinManager.FORM_PADDING, STATUS_BAR_HEIGHT, Width, ACTION_BAR_HEIGHT), new StringFormat { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Center });
|
||||
g.DrawString(HeaderText, new Font("Roboto", 12, FontStyle.Bold), SkinManager.ColorScheme.TextBrush, new Rectangle(SkinManager.FORM_PADDING, 0, Width, STATUS_BAR_HEIGHT), new StringFormat { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Near });
|
||||
}
|
||||
public string PrimaryText { get; set; }
|
||||
public string HeaderText { get; set; }
|
||||
public Font TitleFont { get; set; }
|
||||
}
|
||||
|
||||
public class MouseMessageFilter : IMessageFilter
|
||||
{
|
||||
private const int WM_MOUSEMOVE = 0x0200;
|
||||
|
||||
public static event MouseEventHandler MouseMove;
|
||||
|
||||
public bool PreFilterMessage(ref Message m)
|
||||
{
|
||||
|
||||
if (m.Msg == WM_MOUSEMOVE)
|
||||
{
|
||||
if (MouseMove != null)
|
||||
{
|
||||
int x = Control.MousePosition.X, y = Control.MousePosition.Y;
|
||||
|
||||
MouseMove(null, new MouseEventArgs(MouseButtons.None, 0, x, y, 0));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
120
framework/MaterialSkin.Core/Controls/MaterialForm.resx
Normal file
120
framework/MaterialSkin.Core/Controls/MaterialForm.resx
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
171
framework/MaterialSkin.Core/Controls/MaterialIcon.cs
Normal file
171
framework/MaterialSkin.Core/Controls/MaterialIcon.cs
Normal file
@@ -0,0 +1,171 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using MaterialSkin.Animations;
|
||||
|
||||
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
public class MaterialIcon:Control
|
||||
{
|
||||
private Image _image;
|
||||
private Bitmap _bmp;
|
||||
private AnimationManager _animationManager;
|
||||
private Point _lastLocation;
|
||||
private Bitmap _backBuffer = null;
|
||||
private bool _primary;
|
||||
|
||||
public MaterialIcon()
|
||||
{
|
||||
Cursor = Cursors.Hand;
|
||||
Clickable = true;
|
||||
_animationManager = new AnimationManager(false)
|
||||
{
|
||||
Increment = 0.02,
|
||||
AnimationType = AnimationType.EaseOut
|
||||
};
|
||||
|
||||
_animationManager.OnAnimationProgress += sender => Invalidate();
|
||||
_animationManager.OnAnimationFinished += AnimationManagerOnOnAnimationFinished;
|
||||
}
|
||||
|
||||
private void AnimationManagerOnOnAnimationFinished(object sender)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
[Browsable(false)]
|
||||
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
||||
|
||||
public Image Image
|
||||
{
|
||||
get { return _image; }
|
||||
set
|
||||
{
|
||||
_image = value;
|
||||
RebuildIcon();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Primary
|
||||
{
|
||||
get { return _primary; }
|
||||
set
|
||||
{
|
||||
_primary = value;
|
||||
if (_image == null) return;
|
||||
RebuildIcon();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnEnabledChanged(EventArgs e)
|
||||
{
|
||||
base.OnEnabledChanged(e);
|
||||
RebuildIcon();
|
||||
}
|
||||
|
||||
protected override void OnResize(EventArgs e)
|
||||
{
|
||||
_backBuffer=new Bitmap(Width,Height);
|
||||
if (_image == null) return;
|
||||
RebuildIcon();
|
||||
base.OnResize(e);
|
||||
}
|
||||
|
||||
private void RebuildIcon()
|
||||
{
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
var tmp = new Bitmap(_image);
|
||||
ReplaceColor(tmp, Color.Black,
|
||||
Enabled
|
||||
? (_primary
|
||||
? SkinManager.GetApplicationBackgroundColor()
|
||||
: SkinManager.ColorScheme.PrimaryColor)
|
||||
: Color.FromArgb(0xAA, 0xAA, 0xAA));
|
||||
_bmp = tmp;
|
||||
Invalidate();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
protected override void OnPaintBackground(PaintEventArgs pevent)
|
||||
{
|
||||
//base.OnPaintBackground(pevent);
|
||||
}
|
||||
protected override void OnMouseDown(MouseEventArgs mevent)
|
||||
{
|
||||
base.OnMouseDown(mevent);
|
||||
if (!Enabled) return;
|
||||
_lastLocation = mevent.Location;
|
||||
_animationManager.StartNewAnimation(AnimationDirection.In, _lastLocation);
|
||||
}
|
||||
|
||||
public bool Clickable { get; set; }
|
||||
protected override void OnClick(EventArgs e)
|
||||
{
|
||||
if (!Clickable) return;
|
||||
|
||||
base.OnClick(e);
|
||||
}
|
||||
protected override void OnPaint(PaintEventArgs pe)
|
||||
{
|
||||
if (Image == null) return;
|
||||
if(_bmp == null)return;
|
||||
if(_backBuffer==null)return;
|
||||
using (Graphics g=Graphics.FromImage(_backBuffer))
|
||||
{
|
||||
g.InterpolationMode = InterpolationMode.Bicubic;
|
||||
g.SmoothingMode = SmoothingMode.HighQuality;
|
||||
g.Clear(_primary? SkinManager.ColorScheme.PrimaryColor : SkinManager.GetApplicationBackgroundColor());
|
||||
if (_animationManager.IsAnimating())
|
||||
{
|
||||
for (int i = 0; i < _animationManager.GetAnimationCount(); i++)
|
||||
{
|
||||
var animationValue = _animationManager.GetProgress(i);
|
||||
var animationSource = _animationManager.GetSource(i);
|
||||
var rippleBrush = new SolidBrush(Color.FromArgb((int)(51 - (animationValue * 50)), _primary ? SkinManager.GetApplicationBackgroundColor() : SkinManager.ColorScheme.PrimaryColor));
|
||||
var rippleSize = (int)(animationValue * Width * 2);
|
||||
g.FillEllipse(rippleBrush, new Rectangle(animationSource.X - rippleSize / 2, animationSource.Y - rippleSize / 2, rippleSize, rippleSize));
|
||||
}
|
||||
}
|
||||
g.DrawImage(_bmp,1,1,Width-2,Height-2);
|
||||
}
|
||||
|
||||
|
||||
pe.Graphics.DrawImage(_backBuffer, 0,0);
|
||||
|
||||
|
||||
}
|
||||
object _lockObject = new object();
|
||||
private void ReplaceColor(Bitmap bmp, Color oldColor, Color newColor)
|
||||
{
|
||||
|
||||
{
|
||||
var lockedBitmap = bmp;
|
||||
|
||||
for (int y = 0; y < lockedBitmap.Height; y++)
|
||||
{
|
||||
for (int x = 0; x < lockedBitmap.Width; x++)
|
||||
{
|
||||
if (lockedBitmap.GetPixel(x, y).A > 0)
|
||||
{
|
||||
lockedBitmap.SetPixel(x, y, newColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
44
framework/MaterialSkin.Core/Controls/MaterialIndicator.Designer.cs
generated
Normal file
44
framework/MaterialSkin.Core/Controls/MaterialIndicator.Designer.cs
generated
Normal file
@@ -0,0 +1,44 @@
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
partial class MaterialIndicator
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// MaterialIndicator
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Name = "MaterialIndicator";
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
51
framework/MaterialSkin.Core/Controls/MaterialIndicator.cs
Normal file
51
framework/MaterialSkin.Core/Controls/MaterialIndicator.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
public partial class MaterialIndicator : UserControl
|
||||
{
|
||||
private bool _checked;
|
||||
|
||||
[Browsable(false)]
|
||||
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
||||
|
||||
public Color CheckedColor { get; set; }
|
||||
public Color UncheckedColor { get; set; }
|
||||
public Color BorderColor { get; set; }
|
||||
public MaterialIndicator()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public bool Checked
|
||||
{
|
||||
get { return _checked; }
|
||||
set
|
||||
{
|
||||
_checked = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPaintBackground(PaintEventArgs e)
|
||||
{
|
||||
base.OnPaintBackground(e);
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
e.Graphics.FillEllipse(new SolidBrush(Checked?CheckedColor:UncheckedColor),1,1,Width-2,Height-2);
|
||||
e.Graphics.DrawEllipse(new Pen(BorderColor),1,1,Width-2,Height-2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
120
framework/MaterialSkin.Core/Controls/MaterialIndicator.resx
Normal file
120
framework/MaterialSkin.Core/Controls/MaterialIndicator.resx
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
115
framework/MaterialSkin.Core/Controls/MaterialInputBox.Designer.cs
generated
Normal file
115
framework/MaterialSkin.Core/Controls/MaterialInputBox.Designer.cs
generated
Normal file
@@ -0,0 +1,115 @@
|
||||
|
||||
namespace MaterialSkin.Core.Controls
|
||||
{
|
||||
partial class MaterialInputBox
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.materialRaisedButton1 = new MaterialSkin.Controls.MaterialRaisedButton();
|
||||
this.materialRaisedButton2 = new MaterialSkin.Controls.MaterialRaisedButton();
|
||||
this.textBox1 = new System.Windows.Forms.TextBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// materialRaisedButton1
|
||||
//
|
||||
this.materialRaisedButton1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.materialRaisedButton1.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.materialRaisedButton1.Depth = 0;
|
||||
this.materialRaisedButton1.DrawBorder = false;
|
||||
this.materialRaisedButton1.Icon = null;
|
||||
this.materialRaisedButton1.Location = new System.Drawing.Point(440, 88);
|
||||
this.materialRaisedButton1.MouseState = MaterialSkin.MouseState.HOVER;
|
||||
this.materialRaisedButton1.Name = "materialRaisedButton1";
|
||||
this.materialRaisedButton1.Primary = true;
|
||||
this.materialRaisedButton1.Size = new System.Drawing.Size(128, 48);
|
||||
this.materialRaisedButton1.TabIndex = 0;
|
||||
this.materialRaisedButton1.Text = "OK";
|
||||
this.materialRaisedButton1.UseVisualStyleBackColor = true;
|
||||
this.materialRaisedButton1.Click += new System.EventHandler(this.materialRaisedButton1_Click);
|
||||
//
|
||||
// materialRaisedButton2
|
||||
//
|
||||
this.materialRaisedButton2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.materialRaisedButton2.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.materialRaisedButton2.Depth = 0;
|
||||
this.materialRaisedButton2.DrawBorder = true;
|
||||
this.materialRaisedButton2.Icon = null;
|
||||
this.materialRaisedButton2.Location = new System.Drawing.Point(304, 88);
|
||||
this.materialRaisedButton2.MouseState = MaterialSkin.MouseState.HOVER;
|
||||
this.materialRaisedButton2.Name = "materialRaisedButton2";
|
||||
this.materialRaisedButton2.Primary = false;
|
||||
this.materialRaisedButton2.Size = new System.Drawing.Size(128, 48);
|
||||
this.materialRaisedButton2.TabIndex = 1;
|
||||
this.materialRaisedButton2.Text = "Cancel";
|
||||
this.materialRaisedButton2.UseVisualStyleBackColor = true;
|
||||
this.materialRaisedButton2.Click += new System.EventHandler(this.materialRaisedButton2_Click);
|
||||
//
|
||||
// textBox1
|
||||
//
|
||||
this.textBox1.Location = new System.Drawing.Point(16, 56);
|
||||
this.textBox1.Name = "textBox1";
|
||||
this.textBox1.Size = new System.Drawing.Size(552, 23);
|
||||
this.textBox1.TabIndex = 0;
|
||||
this.textBox1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBox1_KeyDown);
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.BackColor = System.Drawing.Color.White;
|
||||
this.label1.Location = new System.Drawing.Point(16, 32);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(38, 15);
|
||||
this.label1.TabIndex = 3;
|
||||
this.label1.Text = "label1";
|
||||
//
|
||||
// MaterialInputBox
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(579, 149);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.textBox1);
|
||||
this.Controls.Add(this.materialRaisedButton2);
|
||||
this.Controls.Add(this.materialRaisedButton1);
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "MaterialInputBox";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private MaterialSkin.Controls.MaterialRaisedButton materialRaisedButton1;
|
||||
private MaterialSkin.Controls.MaterialRaisedButton materialRaisedButton2;
|
||||
private System.Windows.Forms.TextBox textBox1;
|
||||
private System.Windows.Forms.Label label1;
|
||||
}
|
||||
}
|
||||
48
framework/MaterialSkin.Core/Controls/MaterialInputBox.cs
Normal file
48
framework/MaterialSkin.Core/Controls/MaterialInputBox.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using MaterialSkin.Controls;
|
||||
|
||||
namespace MaterialSkin.Core.Controls
|
||||
{
|
||||
public partial class MaterialInputBox : MaterialForm
|
||||
{
|
||||
private MaterialInputBox()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
public static DialogResult Prompt(string title, string defaultValue, out string result, bool masked = false)
|
||||
{
|
||||
MaterialInputBox box = new MaterialInputBox {label1 = {Text = title}, textBox1 = {Text = defaultValue}};
|
||||
if (masked) box.textBox1.PasswordChar = '*';
|
||||
var res= box.ShowDialog();
|
||||
result = box.textBox1.Text;
|
||||
return res;
|
||||
}
|
||||
|
||||
private void textBox1_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.KeyCode == Keys.Return)
|
||||
{
|
||||
DialogResult = DialogResult.OK;
|
||||
}
|
||||
}
|
||||
|
||||
private void materialRaisedButton2_Click(object sender, EventArgs e)
|
||||
{
|
||||
DialogResult = DialogResult.Cancel;
|
||||
}
|
||||
|
||||
private void materialRaisedButton1_Click(object sender, EventArgs e)
|
||||
{
|
||||
DialogResult = DialogResult.OK;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
60
framework/MaterialSkin.Core/Controls/MaterialInputBox.resx
Normal file
60
framework/MaterialSkin.Core/Controls/MaterialInputBox.resx
Normal file
@@ -0,0 +1,60 @@
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
24
framework/MaterialSkin.Core/Controls/MaterialLabel.cs
Normal file
24
framework/MaterialSkin.Core/Controls/MaterialLabel.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
public class MaterialLabel : Label, IMaterialControl
|
||||
{
|
||||
[Browsable(false)]
|
||||
public int Depth { get; set; }
|
||||
[Browsable(false)]
|
||||
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
||||
[Browsable(false)]
|
||||
public MouseState MouseState { get; set; }
|
||||
protected override void OnCreateControl()
|
||||
{
|
||||
base.OnCreateControl();
|
||||
|
||||
ForeColor = SkinManager.GetPrimaryTextColor();
|
||||
Font = SkinManager.ROBOTO_REGULAR_11;
|
||||
|
||||
BackColorChanged += (sender, args) => ForeColor = SkinManager.GetPrimaryTextColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
163
framework/MaterialSkin.Core/Controls/MaterialListView.cs
Normal file
163
framework/MaterialSkin.Core/Controls/MaterialListView.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
public class MaterialListView : ListView, IMaterialControl
|
||||
{
|
||||
[Browsable(false)]
|
||||
public int Depth { get; set; }
|
||||
[Browsable(false)]
|
||||
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
||||
[Browsable(false)]
|
||||
public MouseState MouseState { get; set; }
|
||||
[Browsable(false)]
|
||||
public Point MouseLocation { get; set; }
|
||||
[Browsable(false)]
|
||||
private ListViewItem HoveredItem { get; set; }
|
||||
|
||||
public MaterialListView()
|
||||
{
|
||||
GridLines = false;
|
||||
FullRowSelect = true;
|
||||
HeaderStyle = ColumnHeaderStyle.Nonclickable;
|
||||
View = View.Details;
|
||||
OwnerDraw = true;
|
||||
ResizeRedraw = true;
|
||||
BorderStyle = BorderStyle.None;
|
||||
SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer, true);
|
||||
|
||||
//Fix for hovers, by default it doesn't redraw
|
||||
//TODO: should only redraw when the hovered line changed, this to reduce unnecessary redraws
|
||||
MouseLocation = new Point(-1, -1);
|
||||
MouseState = MouseState.OUT;
|
||||
MouseEnter += delegate
|
||||
{
|
||||
MouseState = MouseState.HOVER;
|
||||
};
|
||||
MouseLeave += delegate
|
||||
{
|
||||
MouseState = MouseState.OUT;
|
||||
MouseLocation = new Point(-1, -1);
|
||||
HoveredItem = null;
|
||||
Invalidate();
|
||||
};
|
||||
MouseDown += delegate { MouseState = MouseState.DOWN; };
|
||||
MouseUp += delegate { MouseState = MouseState.HOVER; };
|
||||
MouseMove += delegate (object sender, MouseEventArgs args)
|
||||
{
|
||||
MouseLocation = args.Location;
|
||||
var currentHoveredItem = this.GetItemAt(MouseLocation.X, MouseLocation.Y);
|
||||
if (HoveredItem != currentHoveredItem)
|
||||
{
|
||||
HoveredItem = currentHoveredItem;
|
||||
Invalidate();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void OnDrawColumnHeader(DrawListViewColumnHeaderEventArgs e)
|
||||
{
|
||||
e.Graphics.FillRectangle(new SolidBrush(SkinManager.GetApplicationBackgroundColor()), new Rectangle(e.Bounds.X, e.Bounds.Y, Width, e.Bounds.Height));
|
||||
e.Graphics.DrawString(e.Header.Text,
|
||||
SkinManager.ROBOTO_MEDIUM_10,
|
||||
SkinManager.GetSecondaryTextBrush(),
|
||||
new Rectangle(e.Bounds.X + ITEM_PADDING, e.Bounds.Y + ITEM_PADDING, e.Bounds.Width - ITEM_PADDING * 2, e.Bounds.Height - ITEM_PADDING * 2),
|
||||
getStringFormat());
|
||||
}
|
||||
|
||||
private const int ITEM_PADDING = 12;
|
||||
protected override void OnDrawItem(DrawListViewItemEventArgs e)
|
||||
{
|
||||
//We draw the current line of items (= item with subitems) on a temp bitmap, then draw the bitmap at once. This is to reduce flickering.
|
||||
var b = new Bitmap(e.Item.Bounds.Width, e.Item.Bounds.Height);
|
||||
var g = Graphics.FromImage(b);
|
||||
|
||||
//always draw default background
|
||||
g.FillRectangle(new SolidBrush(SkinManager.GetApplicationBackgroundColor()), new Rectangle(new Point(e.Bounds.X, 0), e.Bounds.Size));
|
||||
|
||||
if (e.State.HasFlag(ListViewItemStates.Selected))
|
||||
{
|
||||
//selected background
|
||||
g.FillRectangle(SkinManager.GetFlatButtonPressedBackgroundBrush(), new Rectangle(new Point(e.Bounds.X, 0), e.Bounds.Size));
|
||||
}
|
||||
else if (e.Bounds.Contains(MouseLocation) && MouseState == MouseState.HOVER)
|
||||
{
|
||||
//hover background
|
||||
g.FillRectangle(SkinManager.GetFlatButtonHoverBackgroundBrush(), new Rectangle(new Point(e.Bounds.X, 0), e.Bounds.Size));
|
||||
}
|
||||
|
||||
|
||||
//Draw separator
|
||||
g.DrawLine(new Pen(SkinManager.GetDividersColor()), e.Bounds.Left, 0, e.Bounds.Right, 0);
|
||||
|
||||
foreach (ListViewItem.ListViewSubItem subItem in e.Item.SubItems)
|
||||
{
|
||||
//Draw text
|
||||
g.DrawString(subItem.Text, SkinManager.ROBOTO_MEDIUM_10, SkinManager.GetPrimaryTextBrush(),
|
||||
new Rectangle(subItem.Bounds.X + ITEM_PADDING, ITEM_PADDING, subItem.Bounds.Width - 2 * ITEM_PADDING, subItem.Bounds.Height - 2 * ITEM_PADDING),
|
||||
getStringFormat());
|
||||
}
|
||||
|
||||
e.Graphics.DrawImage((Image)b.Clone(), new Point(0, e.Item.Bounds.Location.Y));
|
||||
g.Dispose();
|
||||
b.Dispose();
|
||||
}
|
||||
|
||||
private StringFormat getStringFormat()
|
||||
{
|
||||
return new StringFormat
|
||||
{
|
||||
FormatFlags = StringFormatFlags.LineLimit,
|
||||
Trimming = StringTrimming.EllipsisCharacter,
|
||||
Alignment = StringAlignment.Near,
|
||||
LineAlignment = StringAlignment.Center
|
||||
};
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
public class LogFont
|
||||
{
|
||||
public int lfHeight = 0;
|
||||
public int lfWidth = 0;
|
||||
public int lfEscapement = 0;
|
||||
public int lfOrientation = 0;
|
||||
public int lfWeight = 0;
|
||||
public byte lfItalic = 0;
|
||||
public byte lfUnderline = 0;
|
||||
public byte lfStrikeOut = 0;
|
||||
public byte lfCharSet = 0;
|
||||
public byte lfOutPrecision = 0;
|
||||
public byte lfClipPrecision = 0;
|
||||
public byte lfQuality = 0;
|
||||
public byte lfPitchAndFamily = 0;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
|
||||
public string lfFaceName = string.Empty;
|
||||
}
|
||||
|
||||
protected override void OnCreateControl()
|
||||
{
|
||||
base.OnCreateControl();
|
||||
|
||||
// This hack tries to apply the Roboto (24) font to all ListViewItems in this ListView
|
||||
// It only succeeds if the font is installed on the system.
|
||||
// Otherwise, a default sans serif font is used.
|
||||
var roboto24 = new Font(SkinManager.ROBOTO_MEDIUM_12.FontFamily, 24);
|
||||
var roboto24Logfont = new LogFont();
|
||||
roboto24.ToLogFont(roboto24Logfont);
|
||||
|
||||
try
|
||||
{
|
||||
// Font.FromLogFont is the method used when drawing ListViewItems. I 'test' it in this safer context to avoid unhandled exceptions later.
|
||||
Font = Font.FromLogFont(roboto24Logfont);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
Font = new Font(FontFamily.GenericSansSerif, 24);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
framework/MaterialSkin.Core/Controls/MaterialLoader.Designer.cs
generated
Normal file
47
framework/MaterialSkin.Core/Controls/MaterialLoader.Designer.cs
generated
Normal file
@@ -0,0 +1,47 @@
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
partial class MaterialLoader
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
SuspendLayout();
|
||||
//
|
||||
// MaterialLoader
|
||||
//
|
||||
AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
ClientSize = new System.Drawing.Size(422, 189);
|
||||
ControlBox = false;
|
||||
Name = "MaterialLoader";
|
||||
StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
139
framework/MaterialSkin.Core/Controls/MaterialLoader.cs
Normal file
139
framework/MaterialSkin.Core/Controls/MaterialLoader.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
public partial class MaterialLoader : MaterialForm
|
||||
{
|
||||
private static MaterialLoader _instance;
|
||||
private static Thread _loaderThread;
|
||||
private static ManualResetEvent _instanceReadyEvent = new ManualResetEvent(false);
|
||||
private readonly Dictionary<string, (MaterialProgressBar ProgressBar, Label Label)> _loadingProcesses;
|
||||
|
||||
private MaterialLoader()
|
||||
{
|
||||
InitializeComponent();
|
||||
RemoveMessageFilter();
|
||||
_loadingProcesses = new Dictionary<string, (MaterialProgressBar, Label)>();
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.StartPosition = FormStartPosition.CenterScreen;
|
||||
}
|
||||
|
||||
public static MaterialLoader Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null || _instance.IsDisposed)
|
||||
{
|
||||
_instanceReadyEvent.Reset();
|
||||
_loaderThread = new Thread(() =>
|
||||
{
|
||||
_instance = new MaterialLoader();
|
||||
_instance.Shown += (_, _) =>
|
||||
{
|
||||
_instanceReadyEvent.Set();
|
||||
};
|
||||
Application.Run(_instance);
|
||||
});
|
||||
_loaderThread.SetApartmentState(ApartmentState.STA);
|
||||
_loaderThread.Start();
|
||||
_instanceReadyEvent.WaitOne();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public void StartLoading(string title)
|
||||
{
|
||||
if (_instance == null || !_instance.Visible)
|
||||
{
|
||||
Instance.Invoke(new Action(() =>
|
||||
{
|
||||
Instance.Show();
|
||||
Instance.Visible= true;
|
||||
}));
|
||||
}
|
||||
|
||||
Instance.Invoke(new Action(() =>
|
||||
{
|
||||
if (_loadingProcesses.ContainsKey(title))
|
||||
{
|
||||
return; // Prevent duplicate loading processes with the same title
|
||||
}
|
||||
|
||||
var progressBar = new MaterialProgressBar
|
||||
{
|
||||
Width = Instance.ClientSize.Width - 20,
|
||||
Height = 20,
|
||||
Top = 50 + (_loadingProcesses.Count * 30),
|
||||
Left = 10,
|
||||
Style = ProgressBarStyle.Marquee,
|
||||
MarqueeAnimationSpeed = 30,
|
||||
Value = 50,
|
||||
BackColor = Color.White
|
||||
};
|
||||
|
||||
var label = new Label
|
||||
{
|
||||
Text = title,
|
||||
AutoSize = true,
|
||||
Top = progressBar.Top - 20,
|
||||
Left = progressBar.Left,
|
||||
BackColor = Color.White
|
||||
};
|
||||
|
||||
_loadingProcesses[title] = (progressBar, label);
|
||||
Instance.Controls.Add(label);
|
||||
Instance.Controls.Add(progressBar);
|
||||
Instance.Height = 50 + (_loadingProcesses.Count * 30);
|
||||
Instance.Refresh();
|
||||
}));
|
||||
}
|
||||
|
||||
public void FinishLoading(string title)
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Instance.Invoke(new Action(() =>
|
||||
{
|
||||
if (_loadingProcesses.TryGetValue(title, out var components))
|
||||
{
|
||||
Instance.Controls.Remove(components.ProgressBar);
|
||||
Instance.Controls.Remove(components.Label);
|
||||
_loadingProcesses.Remove(title);
|
||||
RearrangeProgressBarsAndLabels();
|
||||
}
|
||||
|
||||
if (_loadingProcesses.Count == 0)
|
||||
{
|
||||
Instance.Visible= false;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private void RearrangeProgressBarsAndLabels()
|
||||
{
|
||||
int index = 0;
|
||||
foreach (var components in _loadingProcesses.Values)
|
||||
{
|
||||
components.ProgressBar.Top = 50 + (index * 30);
|
||||
components.Label.Top = components.ProgressBar.Top - 20;
|
||||
index++;
|
||||
}
|
||||
|
||||
this.Height = 50 + (_loadingProcesses.Count * 30);
|
||||
}
|
||||
}
|
||||
}
|
||||
120
framework/MaterialSkin.Core/Controls/MaterialLoader.resx
Normal file
120
framework/MaterialSkin.Core/Controls/MaterialLoader.resx
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
90
framework/MaterialSkin.Core/Controls/MaterialMessageBox.Designer.cs
generated
Normal file
90
framework/MaterialSkin.Core/Controls/MaterialMessageBox.Designer.cs
generated
Normal file
@@ -0,0 +1,90 @@
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
partial class MaterialMessageBox
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.pnlButtons = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.lblTitle = new System.Windows.Forms.Label();
|
||||
this.lblText = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// pnlButtons
|
||||
//
|
||||
this.pnlButtons.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.pnlButtons.AutoSize = true;
|
||||
this.pnlButtons.Location = new System.Drawing.Point(280, 204);
|
||||
this.pnlButtons.Name = "pnlButtons";
|
||||
this.pnlButtons.Padding = new System.Windows.Forms.Padding(0, 20, 0, 0);
|
||||
this.pnlButtons.Size = new System.Drawing.Size(140, 100);
|
||||
this.pnlButtons.TabIndex = 0;
|
||||
//
|
||||
// lblTitle
|
||||
//
|
||||
this.lblTitle.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.lblTitle.Location = new System.Drawing.Point(0, 20);
|
||||
this.lblTitle.Name = "lblTitle";
|
||||
this.lblTitle.Size = new System.Drawing.Size(1340, 40);
|
||||
this.lblTitle.TabIndex = 1;
|
||||
this.lblTitle.Text = "label1";
|
||||
this.lblTitle.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
//
|
||||
// lblText
|
||||
//
|
||||
this.lblText.Location = new System.Drawing.Point(280, 80);
|
||||
this.lblText.Name = "lblText";
|
||||
this.lblText.Size = new System.Drawing.Size(680, 100);
|
||||
this.lblText.TabIndex = 2;
|
||||
this.lblText.Text = "label1";
|
||||
this.lblText.TextAlign = System.Drawing.ContentAlignment.TopCenter;
|
||||
//
|
||||
// MaterialMessageBox
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 26F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.ClientSize = new System.Drawing.Size(1338, 312);
|
||||
this.ControlBox = false;
|
||||
this.Controls.Add(this.lblText);
|
||||
this.Controls.Add(this.lblTitle);
|
||||
this.Controls.Add(this.pnlButtons);
|
||||
this.Font = new System.Drawing.Font("Roboto", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
|
||||
this.Margin = new System.Windows.Forms.Padding(6);
|
||||
this.Name = "MaterialMessageBox";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
private System.Windows.Forms.FlowLayoutPanel pnlButtons;
|
||||
private System.Windows.Forms.Label lblTitle;
|
||||
private System.Windows.Forms.Label lblText;
|
||||
}
|
||||
}
|
||||
86
framework/MaterialSkin.Core/Controls/MaterialMessageBox.cs
Normal file
86
framework/MaterialSkin.Core/Controls/MaterialMessageBox.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
public partial class MaterialMessageBox : MaterialForm
|
||||
{
|
||||
[Browsable(false)]
|
||||
private MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
||||
private MaterialMessageBox()
|
||||
{
|
||||
InitializeComponent();
|
||||
BackColor = SkinManager.GetApplicationBackgroundColor();
|
||||
Left = 0;
|
||||
Width = Screen.PrimaryScreen.WorkingArea.Width;
|
||||
Top = (Screen.PrimaryScreen.WorkingArea.Height - Height) / 2;
|
||||
lblTitle.BackColor = SkinManager.ColorScheme.PrimaryColor;
|
||||
lblTitle.ForeColor= SkinManager.ColorScheme.TextColor;
|
||||
lblText.Left = (Width - lblText.Width) / 2;
|
||||
|
||||
}
|
||||
|
||||
private void AlignControls()
|
||||
{
|
||||
pnlButtons.Left = (Width - pnlButtons.Width) / 2;
|
||||
}
|
||||
|
||||
public static DialogResult Show(string text)
|
||||
{
|
||||
return Show(null, text, string.Empty, MessageBoxButtons.OK);
|
||||
}
|
||||
public static DialogResult Show(IWin32Window owner,string text, string caption, MessageBoxButtons buttons)
|
||||
{
|
||||
var mb = new MaterialMessageBox();
|
||||
mb.lblTitle.Text = caption;
|
||||
mb.lblText.Text = text;
|
||||
List<DialogResult> results;
|
||||
switch (buttons)
|
||||
{
|
||||
case MessageBoxButtons.OK:
|
||||
results=new List<DialogResult>(){DialogResult.OK};
|
||||
break;
|
||||
case MessageBoxButtons.OKCancel:
|
||||
results = new List<DialogResult>() { DialogResult.OK,DialogResult.Cancel };
|
||||
break;
|
||||
case MessageBoxButtons.AbortRetryIgnore:
|
||||
results = new List<DialogResult>() { DialogResult.Abort,DialogResult.Retry,DialogResult.Ignore };
|
||||
break;
|
||||
case MessageBoxButtons.YesNoCancel:
|
||||
results = new List<DialogResult>() { DialogResult.Yes,DialogResult.No,DialogResult.Cancel };
|
||||
break;
|
||||
case MessageBoxButtons.YesNo:
|
||||
results = new List<DialogResult>() { DialogResult.Yes,DialogResult.No };
|
||||
break;
|
||||
case MessageBoxButtons.RetryCancel:
|
||||
results = new List<DialogResult>() { DialogResult.Retry,DialogResult.Cancel };
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(buttons), buttons, null);
|
||||
}
|
||||
|
||||
var btns=Enum.GetNames(typeof(DialogResult));
|
||||
foreach (var btn in results)
|
||||
{
|
||||
MaterialRaisedButton opt = new MaterialRaisedButton();
|
||||
opt.Size = new Size(180, 60);
|
||||
opt.Margin = new Padding(10, 20, 10, 0);
|
||||
opt.Text = Enum.GetName(typeof(DialogResult),btn);
|
||||
opt.Click += (sender, args) =>
|
||||
mb.DialogResult = btn;
|
||||
mb.pnlButtons.Controls.Add(opt);
|
||||
mb.AlignControls();
|
||||
}
|
||||
|
||||
return mb.ShowDialog(owner);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
120
framework/MaterialSkin.Core/Controls/MaterialMessageBox.resx
Normal file
120
framework/MaterialSkin.Core/Controls/MaterialMessageBox.resx
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
16
framework/MaterialSkin.Core/Controls/MaterialPanel.cs
Normal file
16
framework/MaterialSkin.Core/Controls/MaterialPanel.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
public class MaterialPanel:Panel
|
||||
{
|
||||
[Browsable(false)]
|
||||
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
|
||||
e.Graphics.Clear(SkinManager.GetApplicationBackgroundColor());
|
||||
}
|
||||
}
|
||||
}
|
||||
134
framework/MaterialSkin.Core/Controls/MaterialProgressBar.cs
Normal file
134
framework/MaterialSkin.Core/Controls/MaterialProgressBar.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Material design-like progress bar
|
||||
/// </summary>
|
||||
public class MaterialProgressBar : ProgressBar, IMaterialControl
|
||||
{
|
||||
private int _animation;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MaterialProgressBar"/> class.
|
||||
/// </summary>
|
||||
public MaterialProgressBar()
|
||||
{
|
||||
SetStyle(ControlStyles.UserPaint, true);
|
||||
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
||||
Timer timer = new Timer();
|
||||
timer.Interval = 33;
|
||||
timer.Tick += Timer_Tick;
|
||||
timer.Enabled = true;
|
||||
}
|
||||
|
||||
private void Timer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the depth.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The depth.
|
||||
/// </value>
|
||||
[Browsable(false)]
|
||||
public int Depth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the skin manager.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The skin manager.
|
||||
/// </value>
|
||||
[Browsable(false)]
|
||||
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the state of the mouse.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The state of the mouse.
|
||||
/// </value>
|
||||
[Browsable(false)]
|
||||
public MouseState MouseState { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Performs the work of setting the specified bounds of this control.
|
||||
/// </summary>
|
||||
/// <param name="x">The new <see cref="P:System.Windows.Forms.Control.Left" /> property value of the control.</param>
|
||||
/// <param name="y">The new <see cref="P:System.Windows.Forms.Control.Top" /> property value of the control.</param>
|
||||
/// <param name="width">The new <see cref="P:System.Windows.Forms.Control.Width" /> property value of the control.</param>
|
||||
/// <param name="height">The new <see cref="P:System.Windows.Forms.Control.Height" /> property value of the control.</param>
|
||||
/// <param name="specified">A bitwise combination of the <see cref="T:System.Windows.Forms.BoundsSpecified" /> values.</param>
|
||||
protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
|
||||
{
|
||||
base.SetBoundsCore(x, y, width, 5, specified);
|
||||
}
|
||||
|
||||
protected override void CreateHandle()
|
||||
{
|
||||
base.CreateHandle();
|
||||
if (Style == ProgressBarStyle.Marquee)
|
||||
StartAnimation();
|
||||
}
|
||||
|
||||
private void StartAnimation()
|
||||
{
|
||||
_animation = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.Windows.Forms.Control.Paint" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs" /> that contains the event data.</param>
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
if (Style == ProgressBarStyle.Marquee)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
|
||||
|
||||
var animationProgress = (int)(e.ClipRectangle.Width * ((double)_animation / Maximum));
|
||||
var doneProgress = (int)(e.ClipRectangle.Width * ((double)Value / Maximum));
|
||||
if (doneProgress + animationProgress > e.ClipRectangle.Width)
|
||||
doneProgress = e.ClipRectangle.Width - animationProgress;
|
||||
|
||||
_animation+=Step;
|
||||
if (_animation >= 100) _animation = -Value;
|
||||
e.Graphics.FillRectangle(SkinManager.GetDisabledOrHintBrush(), 0, 0, e.ClipRectangle.Width, e.ClipRectangle.Height);
|
||||
e.Graphics.FillRectangle(SkinManager.ColorScheme.PrimaryBrush, animationProgress, 0, doneProgress, e.ClipRectangle.Height);
|
||||
//Task.Delay(33).ContinueWith((x) =>
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// System.Action a = () => { };
|
||||
// if (InvokeRequired)
|
||||
// Invoke(a);
|
||||
// else
|
||||
// a();
|
||||
// }catch{}
|
||||
|
||||
//});
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var doneProgress = (int)(e.ClipRectangle.Width * ((double)Value / Maximum));
|
||||
e.Graphics.FillRectangle(SkinManager.ColorScheme.PrimaryBrush, 0, 0, doneProgress, e.ClipRectangle.Height);
|
||||
e.Graphics.FillRectangle(SkinManager.GetDisabledOrHintBrush(), doneProgress, 0, e.ClipRectangle.Width, e.ClipRectangle.Height);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
211
framework/MaterialSkin.Core/Controls/MaterialRadioButton.cs
Normal file
211
framework/MaterialSkin.Core/Controls/MaterialRadioButton.cs
Normal file
@@ -0,0 +1,211 @@
|
||||
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 MaterialRadioButton : RadioButton, IMaterialControl
|
||||
{
|
||||
[Browsable(false)]
|
||||
public int Depth { get; set; }
|
||||
[Browsable(false)]
|
||||
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
||||
[Browsable(false)]
|
||||
public MouseState MouseState { get; set; }
|
||||
[Browsable(false)]
|
||||
public Point MouseLocation { get; set; }
|
||||
|
||||
private bool ripple;
|
||||
[Category("Behavior")]
|
||||
public bool Ripple
|
||||
{
|
||||
get { return ripple; }
|
||||
set
|
||||
{
|
||||
ripple = value;
|
||||
AutoSize = AutoSize; //Make AutoSize directly set the bounds.
|
||||
|
||||
if (value)
|
||||
{
|
||||
Margin = new Padding(0);
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
// animation managers
|
||||
private readonly AnimationManager _animationManager;
|
||||
private readonly AnimationManager _rippleAnimationManager;
|
||||
|
||||
// size related variables which should be recalculated onsizechanged
|
||||
private Rectangle _radioButtonBounds;
|
||||
private int _boxOffset;
|
||||
|
||||
// size constants
|
||||
private const int RADIOBUTTON_SIZE = 19;
|
||||
private const int RADIOBUTTON_SIZE_HALF = RADIOBUTTON_SIZE / 2;
|
||||
private const int RADIOBUTTON_OUTER_CIRCLE_WIDTH = 2;
|
||||
private const int RADIOBUTTON_INNER_CIRCLE_SIZE = RADIOBUTTON_SIZE - (2 * RADIOBUTTON_OUTER_CIRCLE_WIDTH);
|
||||
|
||||
public MaterialRadioButton()
|
||||
{
|
||||
SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer, true);
|
||||
|
||||
_animationManager = new AnimationManager
|
||||
{
|
||||
AnimationType = AnimationType.EaseInOut,
|
||||
Increment = 0.06
|
||||
};
|
||||
_rippleAnimationManager = new AnimationManager(false)
|
||||
{
|
||||
AnimationType = AnimationType.Linear,
|
||||
Increment = 0.10,
|
||||
SecondaryIncrement = 0.08
|
||||
};
|
||||
_animationManager.OnAnimationProgress += sender => Invalidate();
|
||||
_rippleAnimationManager.OnAnimationProgress += sender => Invalidate();
|
||||
|
||||
CheckedChanged += (sender, args) => _animationManager.StartNewAnimation(Checked ? AnimationDirection.In : AnimationDirection.Out);
|
||||
|
||||
SizeChanged += OnSizeChanged;
|
||||
|
||||
Ripple = true;
|
||||
MouseLocation = new Point(-1, -1);
|
||||
}
|
||||
private void OnSizeChanged(object sender, EventArgs eventArgs)
|
||||
{
|
||||
_boxOffset = Height / 2 - (int)Math.Ceiling(RADIOBUTTON_SIZE / 2d);
|
||||
_radioButtonBounds = new Rectangle(_boxOffset, _boxOffset, RADIOBUTTON_SIZE, RADIOBUTTON_SIZE);
|
||||
}
|
||||
|
||||
public override Size GetPreferredSize(Size proposedSize)
|
||||
{
|
||||
var width = _boxOffset + 20 + (int)CreateGraphics().MeasureString(Text, SkinManager.ROBOTO_MEDIUM_10).Width;
|
||||
return Ripple ? new Size(width, 30) : new Size(width, 20);
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs pevent)
|
||||
{
|
||||
var g = pevent.Graphics;
|
||||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
g.TextRenderingHint = TextRenderingHint.AntiAlias;
|
||||
|
||||
// clear the control
|
||||
g.Clear(Parent.BackColor);
|
||||
|
||||
var RADIOBUTTON_CENTER = _boxOffset + RADIOBUTTON_SIZE_HALF;
|
||||
|
||||
var animationProgress = _animationManager.GetProgress();
|
||||
|
||||
int colorAlpha = Enabled ? (int)(animationProgress * 255.0) : SkinManager.GetCheckBoxOffDisabledColor().A;
|
||||
int backgroundAlpha = Enabled ? (int)(SkinManager.GetCheckboxOffColor().A * (1.0 - animationProgress)) : SkinManager.GetCheckBoxOffDisabledColor().A;
|
||||
float animationSize = (float)(animationProgress * 8f);
|
||||
float animationSizeHalf = animationSize / 2;
|
||||
animationSize = (float)(animationProgress * 9f);
|
||||
|
||||
var brush = new SolidBrush(Color.FromArgb(colorAlpha, Enabled ? SkinManager.ColorScheme.AccentColor : SkinManager.GetCheckBoxOffDisabledColor()));
|
||||
var pen = new Pen(brush.Color);
|
||||
|
||||
// draw ripple animation
|
||||
if (Ripple && _rippleAnimationManager.IsAnimating())
|
||||
{
|
||||
for (var i = 0; i < _rippleAnimationManager.GetAnimationCount(); i++)
|
||||
{
|
||||
var animationValue = _rippleAnimationManager.GetProgress(i);
|
||||
var animationSource = new Point(RADIOBUTTON_CENTER, RADIOBUTTON_CENTER);
|
||||
var rippleBrush = new SolidBrush(Color.FromArgb((int)((animationValue * 40)), ((bool)_rippleAnimationManager.GetData(i)[0]) ? Color.Black : brush.Color));
|
||||
var rippleHeight = (Height % 2 == 0) ? Height - 3 : Height - 2;
|
||||
var rippleSize = (_rippleAnimationManager.GetDirection(i) == AnimationDirection.InOutIn) ? (int)(rippleHeight * (0.8d + (0.2d * animationValue))) : rippleHeight;
|
||||
using (var path = DrawHelper.CreateRoundRect(animationSource.X - rippleSize / 2, animationSource.Y - rippleSize / 2, rippleSize, rippleSize, rippleSize / 2))
|
||||
{
|
||||
g.FillPath(rippleBrush, path);
|
||||
}
|
||||
|
||||
rippleBrush.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// draw radiobutton circle
|
||||
Color uncheckedColor = DrawHelper.BlendColor(Parent.BackColor, Enabled ? SkinManager.GetCheckboxOffColor() : SkinManager.GetCheckBoxOffDisabledColor(), backgroundAlpha);
|
||||
|
||||
using (var path = DrawHelper.CreateRoundRect(_boxOffset, _boxOffset, RADIOBUTTON_SIZE, RADIOBUTTON_SIZE, 9f))
|
||||
{
|
||||
g.FillPath(new SolidBrush(uncheckedColor), path);
|
||||
|
||||
if (Enabled)
|
||||
{
|
||||
g.FillPath(brush, path);
|
||||
}
|
||||
}
|
||||
|
||||
g.FillEllipse(
|
||||
new SolidBrush(Parent.BackColor),
|
||||
RADIOBUTTON_OUTER_CIRCLE_WIDTH + _boxOffset,
|
||||
RADIOBUTTON_OUTER_CIRCLE_WIDTH + _boxOffset,
|
||||
RADIOBUTTON_INNER_CIRCLE_SIZE,
|
||||
RADIOBUTTON_INNER_CIRCLE_SIZE);
|
||||
|
||||
if (Checked)
|
||||
{
|
||||
using (var path = DrawHelper.CreateRoundRect(RADIOBUTTON_CENTER - animationSizeHalf, RADIOBUTTON_CENTER - animationSizeHalf, animationSize, animationSize, 4f))
|
||||
{
|
||||
g.FillPath(brush, path);
|
||||
}
|
||||
}
|
||||
SizeF stringSize = g.MeasureString(Text, SkinManager.ROBOTO_MEDIUM_10);
|
||||
g.DrawString(Text, SkinManager.ROBOTO_MEDIUM_10, Enabled ? SkinManager.GetPrimaryTextBrush() : SkinManager.GetDisabledOrHintBrush(), _boxOffset + 22, Height / 2 - stringSize.Height / 2);
|
||||
|
||||
brush.Dispose();
|
||||
pen.Dispose();
|
||||
}
|
||||
|
||||
private bool IsMouseInCheckArea()
|
||||
{
|
||||
return _radioButtonBounds.Contains(MouseLocation);
|
||||
}
|
||||
|
||||
protected override void OnCreateControl()
|
||||
{
|
||||
base.OnCreateControl();
|
||||
Font = SkinManager.ROBOTO_MEDIUM_10;
|
||||
|
||||
if (DesignMode) return;
|
||||
|
||||
MouseState = MouseState.OUT;
|
||||
MouseEnter += (sender, args) =>
|
||||
{
|
||||
MouseState = MouseState.HOVER;
|
||||
};
|
||||
MouseLeave += (sender, args) =>
|
||||
{
|
||||
MouseLocation = new Point(-1, -1);
|
||||
MouseState = MouseState.OUT;
|
||||
};
|
||||
MouseDown += (sender, args) =>
|
||||
{
|
||||
MouseState = MouseState.DOWN;
|
||||
|
||||
if (Ripple && args.Button == MouseButtons.Left && IsMouseInCheckArea())
|
||||
{
|
||||
_rippleAnimationManager.SecondaryIncrement = 0;
|
||||
_rippleAnimationManager.StartNewAnimation(AnimationDirection.InOutIn, new object[] { Checked });
|
||||
}
|
||||
};
|
||||
MouseUp += (sender, args) =>
|
||||
{
|
||||
MouseState = MouseState.HOVER;
|
||||
_rippleAnimationManager.SecondaryIncrement = 0.08;
|
||||
};
|
||||
MouseMove += (sender, args) =>
|
||||
{
|
||||
MouseLocation = args.Location;
|
||||
Cursor = IsMouseInCheckArea() ? Cursors.Hand : Cursors.Default;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
216
framework/MaterialSkin.Core/Controls/MaterialRaisedButton.cs
Normal file
216
framework/MaterialSkin.Core/Controls/MaterialRaisedButton.cs
Normal file
@@ -0,0 +1,216 @@
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Text;
|
||||
using System.Windows.Forms;
|
||||
using MaterialSkin.Animations;
|
||||
using System;
|
||||
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
public class MaterialRaisedButton : 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; }
|
||||
|
||||
|
||||
public bool DrawBorder
|
||||
{
|
||||
get { return _drawBorder; }
|
||||
set
|
||||
{
|
||||
_drawBorder = value;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly AnimationManager _animationManager;
|
||||
|
||||
private SizeF _textSize;
|
||||
|
||||
private Image _icon;
|
||||
private bool _drawBorder;
|
||||
private Point _lastLocation;
|
||||
private bool _wasClick;
|
||||
|
||||
public Image Icon
|
||||
{
|
||||
get { return _icon; }
|
||||
set
|
||||
{
|
||||
_icon = value;
|
||||
if (AutoSize)
|
||||
Size = GetPreferredSize();
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public MaterialRaisedButton()
|
||||
{
|
||||
Primary = true;
|
||||
Cursor = Cursors.Hand;
|
||||
_animationManager = new AnimationManager(false)
|
||||
{
|
||||
Increment = 0.02,
|
||||
AnimationType = AnimationType.EaseOut
|
||||
};
|
||||
_animationManager.OnAnimationProgress += sender => Invalidate();
|
||||
_animationManager.OnAnimationFinished +=AnimationManagerOnOnAnimationFinished;
|
||||
AutoSizeMode = AutoSizeMode.GrowAndShrink;
|
||||
|
||||
}
|
||||
|
||||
private void AnimationManagerOnOnAnimationFinished(object o)
|
||||
{
|
||||
if (_wasClick)
|
||||
{
|
||||
_wasClick = false;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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 OnMouseUp(MouseEventArgs mevent)
|
||||
{
|
||||
base.OnMouseUp(mevent);
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected override void OnMouseDown(MouseEventArgs mevent)
|
||||
{
|
||||
base.OnMouseDown(mevent);
|
||||
_lastLocation = mevent.Location;
|
||||
|
||||
}
|
||||
|
||||
protected override void OnClick(EventArgs e)
|
||||
{
|
||||
_animationManager.StartNewAnimation(AnimationDirection.In,_lastLocation);
|
||||
base.OnClick(e);
|
||||
}
|
||||
|
||||
|
||||
protected override void OnPaint(PaintEventArgs pevent)
|
||||
{
|
||||
try
|
||||
{
|
||||
var g = pevent.Graphics;
|
||||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
//g.TextRenderingHint = TextRenderingHint.AntiAlias;
|
||||
|
||||
g.Clear(Parent.BackColor);
|
||||
|
||||
using (var backgroundPath = DrawHelper.CreateRoundRect(ClientRectangle.X,
|
||||
ClientRectangle.Y,
|
||||
ClientRectangle.Width - 1,
|
||||
ClientRectangle.Height - 1,
|
||||
1f))
|
||||
{
|
||||
|
||||
g.FillPath(
|
||||
Enabled
|
||||
? (Primary
|
||||
? SkinManager.ColorScheme.PrimaryBrush
|
||||
: SkinManager.GetRaisedButtonBackgroundBrush())
|
||||
: Brushes.DarkGray, backgroundPath);
|
||||
if (!Primary && this.DrawBorder)
|
||||
{
|
||||
g.DrawPath(SkinManager.ColorScheme.PrimaryPen, backgroundPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (_animationManager.IsAnimating())
|
||||
{
|
||||
for (int i = 0; i < _animationManager.GetAnimationCount(); i++)
|
||||
{
|
||||
var animationValue = _animationManager.GetProgress(i);
|
||||
var animationSource = _animationManager.GetSource(i);
|
||||
var rippleBrush = new SolidBrush(Color.FromArgb((int) (51 - (animationValue * 50)),
|
||||
Primary ? Color.White : SkinManager.ColorScheme.PrimaryColor));
|
||||
var rippleSize = (int) (animationValue * Width * 2);
|
||||
g.FillEllipse(rippleBrush,
|
||||
new Rectangle(animationSource.X - rippleSize / 2, animationSource.Y - rippleSize / 2,
|
||||
rippleSize, rippleSize));
|
||||
}
|
||||
}
|
||||
|
||||
//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(),
|
||||
Font,
|
||||
Primary ? SkinManager.GetRaisedButtonTextBrush(Primary) : SkinManager.ColorScheme.PrimaryBrush,
|
||||
textRect,
|
||||
new StringFormat {Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center});
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
1169
framework/MaterialSkin.Core/Controls/MaterialSingleLineTextField.cs
Normal file
1169
framework/MaterialSkin.Core/Controls/MaterialSingleLineTextField.cs
Normal file
File diff suppressed because it is too large
Load Diff
22
framework/MaterialSkin.Core/Controls/MaterialTabControl.cs
Normal file
22
framework/MaterialSkin.Core/Controls/MaterialTabControl.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
public class MaterialTabControl : TabControl, IMaterialControl
|
||||
{
|
||||
[Browsable(false)]
|
||||
public int Depth { get; set; }
|
||||
[Browsable(false)]
|
||||
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
||||
[Browsable(false)]
|
||||
public MouseState MouseState { get; set; }
|
||||
|
||||
protected override void WndProc(ref Message m)
|
||||
{
|
||||
if (m.Msg == 0x1328 && !DesignMode) m.Result = (IntPtr)1;
|
||||
else base.WndProc(ref m);
|
||||
}
|
||||
}
|
||||
}
|
||||
175
framework/MaterialSkin.Core/Controls/MaterialTabSelector.cs
Normal file
175
framework/MaterialSkin.Core/Controls/MaterialTabSelector.cs
Normal file
@@ -0,0 +1,175 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Text;
|
||||
using System.Windows.Forms;
|
||||
using MaterialSkin.Animations;
|
||||
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
public class MaterialTabSelector : Control, IMaterialControl
|
||||
{
|
||||
[Browsable(false)]
|
||||
public int Depth { get; set; }
|
||||
[Browsable(false)]
|
||||
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
||||
[Browsable(false)]
|
||||
public MouseState MouseState { get; set; }
|
||||
|
||||
private MaterialTabControl _baseTabControl;
|
||||
public MaterialTabControl BaseTabControl
|
||||
{
|
||||
get { return _baseTabControl; }
|
||||
set
|
||||
{
|
||||
_baseTabControl = value;
|
||||
if (_baseTabControl == null) return;
|
||||
_previousSelectedTabIndex = _baseTabControl.SelectedIndex;
|
||||
_baseTabControl.Deselected += (sender, args) =>
|
||||
{
|
||||
_previousSelectedTabIndex = _baseTabControl.SelectedIndex;
|
||||
};
|
||||
_baseTabControl.SelectedIndexChanged += (sender, args) =>
|
||||
{
|
||||
_animationManager.SetProgress(0);
|
||||
_animationManager.StartNewAnimation(AnimationDirection.In);
|
||||
};
|
||||
_baseTabControl.ControlAdded += delegate
|
||||
{
|
||||
Invalidate();
|
||||
};
|
||||
_baseTabControl.ControlRemoved += delegate
|
||||
{
|
||||
Invalidate();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private int _previousSelectedTabIndex;
|
||||
private Point _animationSource;
|
||||
private readonly AnimationManager _animationManager;
|
||||
|
||||
private List<Rectangle> _tabRects;
|
||||
private const int TAB_HEADER_PADDING = 24;
|
||||
private const int TAB_INDICATOR_HEIGHT = 2;
|
||||
|
||||
public MaterialTabSelector()
|
||||
{
|
||||
SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer, true);
|
||||
Height = 48;
|
||||
|
||||
_animationManager = new AnimationManager
|
||||
{
|
||||
AnimationType = AnimationType.EaseOut,
|
||||
Increment = 0.04
|
||||
};
|
||||
_animationManager.OnAnimationProgress += sender => Invalidate();
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
var g = e.Graphics;
|
||||
g.TextRenderingHint = TextRenderingHint.AntiAlias;
|
||||
|
||||
g.Clear(SkinManager.ColorScheme.PrimaryColor);
|
||||
|
||||
if (_baseTabControl == null) return;
|
||||
|
||||
if (!_animationManager.IsAnimating() || _tabRects == null || _tabRects.Count != _baseTabControl.TabCount)
|
||||
UpdateTabRects();
|
||||
|
||||
var animationProgress = _animationManager.GetProgress();
|
||||
|
||||
//Click feedback
|
||||
if (_animationManager.IsAnimating())
|
||||
{
|
||||
var rippleBrush = new SolidBrush(Color.FromArgb((int)(51 - (animationProgress * 50)), Color.White));
|
||||
var rippleSize = (int)(animationProgress * _tabRects[_baseTabControl.SelectedIndex].Width * 1.75);
|
||||
|
||||
g.SetClip(_tabRects[_baseTabControl.SelectedIndex]);
|
||||
g.FillEllipse(rippleBrush, new Rectangle(_animationSource.X - rippleSize / 2, _animationSource.Y - rippleSize / 2, rippleSize, rippleSize));
|
||||
g.ResetClip();
|
||||
rippleBrush.Dispose();
|
||||
}
|
||||
|
||||
//Draw tab headers
|
||||
foreach (TabPage tabPage in _baseTabControl.TabPages)
|
||||
{
|
||||
var currentTabIndex = _baseTabControl.TabPages.IndexOf(tabPage);
|
||||
Brush textBrush = new SolidBrush(Color.FromArgb(CalculateTextAlpha(currentTabIndex, animationProgress), SkinManager.ColorScheme.TextColor));
|
||||
|
||||
g.DrawString(tabPage.Text.ToUpper(), SkinManager.ROBOTO_MEDIUM_10, textBrush, _tabRects[currentTabIndex], new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
|
||||
textBrush.Dispose();
|
||||
}
|
||||
|
||||
//Animate tab indicator
|
||||
var previousSelectedTabIndexIfHasOne = _previousSelectedTabIndex == -1 ? _baseTabControl.SelectedIndex : _previousSelectedTabIndex;
|
||||
var previousActiveTabRect = _tabRects[previousSelectedTabIndexIfHasOne];
|
||||
var activeTabPageRect = _tabRects[_baseTabControl.SelectedIndex];
|
||||
|
||||
var y = activeTabPageRect.Bottom - 2;
|
||||
var x = previousActiveTabRect.X + (int)((activeTabPageRect.X - previousActiveTabRect.X) * animationProgress);
|
||||
var width = previousActiveTabRect.Width + (int)((activeTabPageRect.Width - previousActiveTabRect.Width) * animationProgress);
|
||||
|
||||
g.FillRectangle(SkinManager.ColorScheme.AccentBrush, x, y, width, TAB_INDICATOR_HEIGHT);
|
||||
}
|
||||
|
||||
private int CalculateTextAlpha(int tabIndex, double animationProgress)
|
||||
{
|
||||
int primaryA = SkinManager.ACTION_BAR_TEXT.A;
|
||||
int secondaryA = SkinManager.ACTION_BAR_TEXT_SECONDARY.A;
|
||||
|
||||
if (tabIndex == _baseTabControl.SelectedIndex && !_animationManager.IsAnimating())
|
||||
{
|
||||
return primaryA;
|
||||
}
|
||||
if (tabIndex != _previousSelectedTabIndex && tabIndex != _baseTabControl.SelectedIndex)
|
||||
{
|
||||
return secondaryA;
|
||||
}
|
||||
if (tabIndex == _previousSelectedTabIndex)
|
||||
{
|
||||
return primaryA - (int)((primaryA - secondaryA) * animationProgress);
|
||||
}
|
||||
return secondaryA + (int)((primaryA - secondaryA) * animationProgress);
|
||||
}
|
||||
|
||||
protected override void OnMouseUp(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseUp(e);
|
||||
|
||||
if (_tabRects == null) UpdateTabRects();
|
||||
for (var i = 0; i < _tabRects.Count; i++)
|
||||
{
|
||||
if (_tabRects[i].Contains(e.Location))
|
||||
{
|
||||
_baseTabControl.SelectedIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
_animationSource = e.Location;
|
||||
}
|
||||
|
||||
private void UpdateTabRects()
|
||||
{
|
||||
_tabRects = new List<Rectangle>();
|
||||
|
||||
//If there isn't a base tab control, the rects shouldn't be calculated
|
||||
//If there aren't tab pages in the base tab control, the list should just be empty which has been set already; exit the void
|
||||
if (_baseTabControl == null || _baseTabControl.TabCount == 0) return;
|
||||
|
||||
//Calculate the bounds of each tab header specified in the base tab control
|
||||
using (var b = new Bitmap(1, 1))
|
||||
{
|
||||
using (var g = Graphics.FromImage(b))
|
||||
{
|
||||
_tabRects.Add(new Rectangle(SkinManager.FORM_PADDING, 0, TAB_HEADER_PADDING * 2 + (int)g.MeasureString(_baseTabControl.TabPages[0].Text, SkinManager.ROBOTO_MEDIUM_10).Width, Height));
|
||||
for (int i = 1; i < _baseTabControl.TabPages.Count; i++)
|
||||
{
|
||||
_tabRects.Add(new Rectangle(_tabRects[i - 1].Right, 0, TAB_HEADER_PADDING * 2 + (int)g.MeasureString(_baseTabControl.TabPages[i].Text, SkinManager.ROBOTO_MEDIUM_10).Width, Height));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
103
framework/MaterialSkin.Core/Controls/MaterialUpDown.Designer.cs
generated
Normal file
103
framework/MaterialSkin.Core/Controls/MaterialUpDown.Designer.cs
generated
Normal file
@@ -0,0 +1,103 @@
|
||||
using MaterialSkin.Core.Resources;
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
partial class MaterialUpDown
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.textBox1 = new System.Windows.Forms.TextBox();
|
||||
this.materialIcon2 = new MaterialSkin.Controls.MaterialIcon();
|
||||
this.materialIcon1 = new MaterialSkin.Controls.MaterialIcon();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// textBox1
|
||||
//
|
||||
this.textBox1.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
this.textBox1.Font = new System.Drawing.Font("Roboto", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
|
||||
this.textBox1.Location = new System.Drawing.Point(80, 20);
|
||||
this.textBox1.Name = "textBox1";
|
||||
this.textBox1.Size = new System.Drawing.Size(100, 28);
|
||||
this.textBox1.TabIndex = 13;
|
||||
this.textBox1.Text = "0000";
|
||||
this.textBox1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
this.textBox1.Click += new System.EventHandler(this.textBox1_Click);
|
||||
this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
|
||||
this.textBox1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBox1_KeyDown);
|
||||
this.textBox1.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.textBox1_KeyPress);
|
||||
this.textBox1.Leave += new System.EventHandler(this.textBox1_Leave);
|
||||
//
|
||||
// materialIcon2
|
||||
//
|
||||
this.materialIcon2.Clickable = true;
|
||||
this.materialIcon2.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.materialIcon2.Image = Resource1.rounded_add_button;
|
||||
this.materialIcon2.Location = new System.Drawing.Point(200, 0);
|
||||
this.materialIcon2.Name = "materialIcon2";
|
||||
this.materialIcon2.Primary = false;
|
||||
this.materialIcon2.Size = new System.Drawing.Size(64, 64);
|
||||
this.materialIcon2.TabIndex = 12;
|
||||
this.materialIcon2.Text = "materialIcon2";
|
||||
this.materialIcon2.Click += new System.EventHandler(this.materialIcon2_Click);
|
||||
this.materialIcon2.MouseDown += new System.Windows.Forms.MouseEventHandler(this.materialIcon2_MouseDown);
|
||||
this.materialIcon2.MouseLeave += new System.EventHandler(this.materialIcon2_MouseLeave);
|
||||
this.materialIcon2.MouseUp += new System.Windows.Forms.MouseEventHandler(this.materialIcon2_MouseUp);
|
||||
//
|
||||
// materialIcon1
|
||||
//
|
||||
this.materialIcon1.Clickable = true;
|
||||
this.materialIcon1.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.materialIcon1.Image = Resource1.round_delete_button;
|
||||
this.materialIcon1.Location = new System.Drawing.Point(0, 0);
|
||||
this.materialIcon1.Name = "materialIcon1";
|
||||
this.materialIcon1.Primary = false;
|
||||
this.materialIcon1.Size = new System.Drawing.Size(64, 64);
|
||||
this.materialIcon1.TabIndex = 11;
|
||||
this.materialIcon1.Text = "materialIcon1";
|
||||
this.materialIcon1.Click += new System.EventHandler(this.materialIcon1_Click);
|
||||
this.materialIcon1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.materialIcon1_MouseDown);
|
||||
this.materialIcon1.MouseLeave += new System.EventHandler(this.materialIcon1_MouseLeave);
|
||||
this.materialIcon1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.materialIcon1_MouseUp);
|
||||
//
|
||||
// MaterialUpDown
|
||||
//
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
|
||||
this.Controls.Add(this.textBox1);
|
||||
this.Controls.Add(this.materialIcon2);
|
||||
this.Controls.Add(this.materialIcon1);
|
||||
this.Name = "MaterialUpDown";
|
||||
this.Size = new System.Drawing.Size(266, 66);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
private MaterialIcon materialIcon2;
|
||||
private MaterialIcon materialIcon1;
|
||||
private System.Windows.Forms.TextBox textBox1;
|
||||
}
|
||||
}
|
||||
256
framework/MaterialSkin.Core/Controls/MaterialUpDown.cs
Normal file
256
framework/MaterialSkin.Core/Controls/MaterialUpDown.cs
Normal file
@@ -0,0 +1,256 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
|
||||
namespace MaterialSkin.Controls
|
||||
{
|
||||
public partial class MaterialUpDown : UserControl,INotifyPropertyChanged
|
||||
{
|
||||
private double _value;
|
||||
private bool _mouseDown;
|
||||
private int _direction;
|
||||
|
||||
public MaterialUpDown()
|
||||
{
|
||||
InitializeComponent();
|
||||
textBox1.BackColor = SkinManager.GetApplicationBackgroundColor();
|
||||
|
||||
AllowDecimal = false;
|
||||
AllowKeyboard=true;
|
||||
}
|
||||
[Browsable(false)]
|
||||
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
||||
|
||||
public bool AllowDecimal { get; set; }
|
||||
|
||||
public bool AllowKeyboard
|
||||
{
|
||||
get { return _allowKeyboard; }
|
||||
set
|
||||
{
|
||||
_allowKeyboard = value;
|
||||
textBox1.ReadOnly = !_allowKeyboard || _readOnly;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HideControls
|
||||
{
|
||||
get { return _hideControls; }
|
||||
set
|
||||
{
|
||||
_hideControls = value;
|
||||
materialIcon1.Visible = !value;
|
||||
materialIcon2.Visible = !value;
|
||||
}
|
||||
}
|
||||
|
||||
public double Value
|
||||
{
|
||||
get { return _value; }
|
||||
set
|
||||
{
|
||||
_value = value;
|
||||
if (_value>Max)
|
||||
{
|
||||
_value = Max;
|
||||
}
|
||||
|
||||
if (_value < Min)
|
||||
{
|
||||
_value = Min;
|
||||
}
|
||||
|
||||
if (!AllowDecimal)
|
||||
{
|
||||
_value = Math.Floor(_value);
|
||||
}
|
||||
|
||||
Action a = ()=> textBox1.Text = _value.ToString();
|
||||
if (textBox1.InvokeRequired)
|
||||
textBox1.Invoke(a);
|
||||
else
|
||||
a();
|
||||
}
|
||||
}
|
||||
|
||||
public bool ReadOnly
|
||||
{
|
||||
get { return _readOnly; }
|
||||
set
|
||||
{
|
||||
_readOnly = value;
|
||||
materialIcon1.Enabled = !value;
|
||||
materialIcon2.Enabled = !value;
|
||||
textBox1.ReadOnly = !_allowKeyboard || _readOnly;
|
||||
}
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged= delegate { };
|
||||
|
||||
public double Max { get; set; }
|
||||
public double Min { get; set; }
|
||||
public double Step { get; set; }
|
||||
protected override void OnPaintBackground(PaintEventArgs e)
|
||||
{
|
||||
e.Graphics.Clear(SkinManager.GetApplicationBackgroundColor());
|
||||
}
|
||||
|
||||
private void materialIcon2_Click(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void materialIcon1_Click(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private async void HoldCountDown(CancellationToken cancellationSourceToken)
|
||||
{
|
||||
await Task.Delay(500);
|
||||
|
||||
var startTime = DateTime.Now;
|
||||
while (_mouseDown&&!cancellationSourceToken.IsCancellationRequested)
|
||||
{
|
||||
Value += Step*_direction;
|
||||
await Task.Delay(100/(int)Math.Max(1,Math.Min(5,(DateTime.Now-startTime).TotalSeconds)));
|
||||
}
|
||||
}
|
||||
|
||||
private CancellationTokenSource _cancellationSource;
|
||||
private bool _readOnly;
|
||||
private bool _allowKeyboard;
|
||||
|
||||
private void materialIcon2_MouseDown(object sender, MouseEventArgs e)
|
||||
{
|
||||
|
||||
_cancellationSource =new CancellationTokenSource();
|
||||
Value += Step;
|
||||
|
||||
_mouseDown = true;
|
||||
_direction = 1;
|
||||
Task.Run(()=> HoldCountDown(_cancellationSource.Token));
|
||||
}
|
||||
|
||||
private void materialIcon2_MouseUp(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (_cancellationSource != null)
|
||||
{
|
||||
_cancellationSource.Cancel();
|
||||
_cancellationSource = null;
|
||||
}
|
||||
_mouseDown = false;
|
||||
PropertyChanged(this,new PropertyChangedEventArgs(nameof(Value)));
|
||||
}
|
||||
|
||||
private void materialIcon1_MouseDown(object sender, MouseEventArgs e)
|
||||
{
|
||||
_cancellationSource = new CancellationTokenSource();
|
||||
Value -= Step;
|
||||
|
||||
_mouseDown = true;
|
||||
_direction = -1;
|
||||
Task.Run(() => HoldCountDown(_cancellationSource.Token));
|
||||
}
|
||||
|
||||
private void materialIcon1_MouseUp(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (_cancellationSource != null)
|
||||
{
|
||||
_cancellationSource.Cancel();
|
||||
_cancellationSource = null;
|
||||
}
|
||||
_mouseDown = false;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Value)));
|
||||
}
|
||||
|
||||
private void materialIcon2_MouseLeave(object sender, EventArgs e)
|
||||
{
|
||||
materialIcon2_MouseUp(null,null);
|
||||
}
|
||||
|
||||
private void materialIcon1_MouseLeave(object sender, EventArgs e)
|
||||
{
|
||||
materialIcon1_MouseUp(null, null);
|
||||
}
|
||||
|
||||
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
|
||||
{
|
||||
|
||||
|
||||
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) &&
|
||||
(e.KeyChar != '.'))
|
||||
{
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// only allow one decimal point
|
||||
if ((e.KeyChar == '.') && ((sender as TextBox).Text.IndexOf('.') > -1))
|
||||
{
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_validate = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private CancellationTokenSource _cancellationTokenSource = null;
|
||||
private bool _validate;
|
||||
private bool _hideControls;
|
||||
|
||||
private void textBox1_Click(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
if (textBox1.ReadOnly) return;
|
||||
textBox1.SelectAll();
|
||||
|
||||
}
|
||||
|
||||
private void textBox1_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void textBox1_Leave(object sender, EventArgs e)
|
||||
{
|
||||
if (double.TryParse((sender as TextBox).Text, NumberStyles.AllowDecimalPoint, CultureInfo.GetCultureInfo("en-us"), out var value))
|
||||
{
|
||||
if (_cancellationTokenSource != null) _cancellationTokenSource.Cancel();
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var newValue = value;
|
||||
var token = _cancellationTokenSource.Token;
|
||||
if (token.IsCancellationRequested) throw new OperationCanceledException();
|
||||
Value = newValue;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Value)));
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void textBox1_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.KeyCode == Keys.Enter)
|
||||
{
|
||||
|
||||
textBox1_Leave(textBox1,null);
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
120
framework/MaterialSkin.Core/Controls/MaterialUpDown.resx
Normal file
120
framework/MaterialSkin.Core/Controls/MaterialUpDown.resx
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
Reference in New Issue
Block a user