#region Imports
|
|
using DPumpHydr.WinFrmUI.RLT.Manager;
|
using DPumpHydr.WinFrmUI.RLT.Util;
|
using System;
|
using System.ComponentModel;
|
using System.Drawing;
|
using System.Drawing.Drawing2D;
|
using System.Drawing.Text;
|
using System.Windows.Forms;
|
using static DPumpHydr.WinFrmUI.RLT.Helper.MaterialDrawHelper;
|
|
#endregion
|
|
namespace DPumpHydr.WinFrmUI.RLT.Controls
|
{
|
#region MaterialExpansionPanel
|
|
public class MaterialExpansionPanel : System.Windows.Forms.Panel, MaterialControlI
|
{
|
#region "Private members"
|
|
private MaterialButton _validationButton;
|
private MaterialButton _cancelButton;
|
|
private const int _expansionPanelDefaultPadding = 16;
|
private const int _leftrightPadding = 24;
|
private const int _buttonPadding = 8;
|
private const int _expandcollapsbuttonsize = 24;
|
private const int _textHeaderHeight = 24;
|
private const int _headerHeightCollapse = 48;
|
private const int _headerHeightExpand = 64;
|
private const int _footerHeight = 68;
|
private const int _footerButtonHeight = 36;
|
private const int _minHeight = 200;
|
private int _headerHeight;
|
|
private bool _collapse;
|
private bool _useAccentColor;
|
private int _expandHeight;
|
|
|
private string _titleHeader;
|
private string _descriptionHeader;
|
private string _validationButtonText;
|
private string _cancelButtonText;
|
|
|
|
private bool _showValidationButtons;
|
private bool _showCollapseExpand;
|
private bool _drawShadows;
|
private bool _shadowDrawEventSubscribed = false;
|
private Rectangle _headerBounds;
|
private Rectangle _expandcollapseBounds;
|
private Rectangle _savebuttonBounds;
|
private Rectangle _cancelbuttonBounds;
|
private bool _savebuttonEnable;
|
|
private enum ButtonState
|
{
|
SaveOver,
|
CancelOver,
|
ColapseExpandOver,
|
HeaderOver,
|
None
|
}
|
|
private ButtonState _buttonState = ButtonState.None;
|
|
#endregion
|
|
#region "Public Properties"
|
|
[Browsable(false)]
|
public int Depth { get; set; }
|
|
[Browsable(false)]
|
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
|
|
[Browsable(false)]
|
public MaterialMouseState MouseState { get; set; }
|
|
[Category("Material"), DefaultValue(false), DisplayName("Use Accent Color")]
|
public bool UseAccentColor
|
{
|
get => _useAccentColor;
|
set { _useAccentColor = value; UpdateRects(); Invalidate(); }
|
}
|
|
[DefaultValue(false)]
|
[Description("Collapses the control when set to true")]
|
[Category("Material")]
|
public bool Collapse
|
{
|
get => _collapse;
|
set
|
{
|
_collapse = value;
|
CollapseOrExpand();
|
Invalidate();
|
}
|
}
|
|
[DefaultValue("Title")]
|
[Category("Material"), DisplayName("Title")]
|
[Description("Title to show in expansion panel's header")]
|
public string Title
|
{
|
get => _titleHeader;
|
set
|
{
|
_titleHeader = value;
|
Invalidate();
|
}
|
}
|
|
[DefaultValue("Description")]
|
[Category("Material"), DisplayName("Description")]
|
[Description("Description to show in expansion panel's header")]
|
public string Description
|
{
|
get => _descriptionHeader;
|
set
|
{
|
_descriptionHeader = value;
|
Invalidate();
|
}
|
}
|
|
[DefaultValue(true)]
|
[Category("Material"), DisplayName("Draw Shadows")]
|
[Description("Draw Shadows around control")]
|
public bool DrawShadows
|
{
|
get => _drawShadows;
|
set { _drawShadows = value; Invalidate(); }
|
}
|
|
[DefaultValue(240)]
|
[Category("Material"), DisplayName("Expand Height")]
|
[Description("Define control height when expanded")]
|
public int ExpandHeight
|
{
|
get => _expandHeight;
|
set { if (value < _minHeight) { value = _minHeight; } _expandHeight = value; Invalidate(); }
|
}
|
|
[DefaultValue(true)]
|
[Category("Material"), DisplayName("Show Collapse/Expand")]
|
[Description("Show collapse/expand indicator")]
|
public bool ShowCollapseExpand
|
{
|
get => _showCollapseExpand;
|
set { _showCollapseExpand = value; Invalidate(); }
|
}
|
|
[DefaultValue(true)]
|
[Category("Material"), DisplayName("Show Validation Buttons")]
|
[Description("Show save/cancel button")]
|
public bool ShowValidationButtons
|
{
|
get => _showValidationButtons;
|
set { _showValidationButtons = value; UpdateRects(); Invalidate(); }
|
}
|
|
[DefaultValue("SAVE")]
|
[Category("Material"), DisplayName("Validation Button Text")]
|
[Description("Set Validation button text")]
|
public string ValidationButtonText
|
{
|
get => _validationButtonText;
|
set { _validationButtonText = value; UpdateRects(); Invalidate(); }
|
}
|
|
[DefaultValue("CANCEL")]
|
[Category("Material"), DisplayName("Cancel Button Text")]
|
[Description("Set Cancel button text")]
|
public string CancelButtonText
|
{
|
get => _cancelButtonText;
|
set { _cancelButtonText = value; UpdateRects(); Invalidate(); }
|
}
|
|
[DefaultValue(false)]
|
[Category("Material"), DisplayName("Validation Button Enable")]
|
[Description("Enable validation button")]
|
public bool ValidationButtonEnable
|
{
|
get => _savebuttonEnable;
|
set { _savebuttonEnable = value; UpdateRects(); Invalidate(); }
|
}
|
|
#endregion
|
|
#region "Events"
|
|
[Category("Action")]
|
[Description("Fires when Save button is clicked")]
|
public event EventHandler SaveClick;
|
|
[Category("Action")]
|
[Description("Fires when Cancel button is clicked")]
|
public event EventHandler CancelClick;
|
|
[Category("Disposition")]
|
[Description("Fires when Panel Collapse")]
|
public event EventHandler PanelCollapse;
|
|
[Category("Disposition")]
|
[Description("Fires when Panel Expand")]
|
public event EventHandler PanelExpand;
|
|
#endregion
|
|
public MaterialExpansionPanel()
|
{
|
ShowValidationButtons = true;
|
ValidationButtonEnable = false;
|
ValidationButtonText = "SAVE";
|
CancelButtonText = "CANCEL";
|
ShowCollapseExpand = true;
|
Collapse = false;
|
Title = "Title";
|
Description = "Description";
|
DrawShadows = true;
|
ExpandHeight = 240;
|
AutoScroll = false;
|
|
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true);
|
BackColor = SkinManager.BackgroundColor;
|
ForeColor = SkinManager.TextHighEmphasisColor;
|
|
Padding = new Padding(24, 64, 24, 16);
|
Margin = new Padding(3, 16, 3, 16);
|
Size = new Size(480, ExpandHeight);
|
|
//CollapseOrExpand();
|
|
_validationButton = new MaterialButton
|
{
|
DrawShadows = false,
|
Type = MaterialButton.MaterialButtonType.Text,
|
UseAccentColor = _useAccentColor,
|
Enabled = ValidationButtonEnable,
|
Visible = _showValidationButtons,
|
Text = "SAVE"
|
};
|
_cancelButton = new MaterialButton
|
{
|
DrawShadows = false,
|
Type = MaterialButton.MaterialButtonType.Text,
|
UseAccentColor = _useAccentColor,
|
Visible = _showValidationButtons,
|
Text = "CANCEL"
|
};
|
|
if (!Controls.Contains(_validationButton))
|
{
|
Controls.Add(_validationButton);
|
}
|
if (!Controls.Contains(_cancelButton))
|
{
|
Controls.Add(_cancelButton);
|
}
|
|
_validationButton.Click += _validationButton_Click;
|
_cancelButton.Click += _cancelButton_Click;
|
|
UpdateRects();
|
}
|
|
private void _cancelButton_Click(object sender, EventArgs e)
|
{
|
//throw new NotImplementedException();
|
CancelClick?.Invoke(this, new EventArgs());
|
Collapse = true;
|
CollapseOrExpand();
|
}
|
|
private void _validationButton_Click(object sender, EventArgs e)
|
{
|
//throw new NotImplementedException();
|
SaveClick?.Invoke(this, new EventArgs());
|
Collapse = true;
|
CollapseOrExpand();
|
}
|
|
protected override void OnCreateControl()
|
{
|
base.OnCreateControl();
|
Font = SkinManager.GetFontByType(MaterialSkinManager.FontType.Body1);
|
}
|
|
protected override void InitLayout()
|
{
|
LocationChanged += (sender, e) => { Parent?.Invalidate(); };
|
ForeColor = SkinManager.TextHighEmphasisColor;
|
}
|
|
protected override void OnParentChanged(EventArgs e)
|
{
|
base.OnParentChanged(e);
|
if (Parent != null)
|
{
|
AddShadowPaintEvent(Parent, drawShadowOnParent);
|
}
|
|
if (_oldParent != null)
|
{
|
RemoveShadowPaintEvent(_oldParent, drawShadowOnParent);
|
}
|
|
_oldParent = Parent;
|
}
|
|
private Control _oldParent;
|
|
protected override void OnVisibleChanged(EventArgs e)
|
{
|
base.OnVisibleChanged(e);
|
if (Parent == null)
|
{
|
return;
|
}
|
|
if (Visible)
|
{
|
AddShadowPaintEvent(Parent, drawShadowOnParent);
|
}
|
else
|
{
|
RemoveShadowPaintEvent(Parent, drawShadowOnParent);
|
}
|
}
|
|
private void drawShadowOnParent(object sender, PaintEventArgs e)
|
{
|
if (Parent == null)
|
{
|
RemoveShadowPaintEvent((Control)sender, drawShadowOnParent);
|
return;
|
}
|
|
if (!_drawShadows || Parent == null)
|
{
|
return;
|
}
|
|
// paint shadow on parent
|
Graphics gp = e.Graphics;
|
Rectangle rect = new(Location, ClientRectangle.Size);
|
gp.SmoothingMode = SmoothingMode.AntiAlias;
|
DrawSquareShadow(gp, rect);
|
}
|
|
|
private void AddShadowPaintEvent(Control control, PaintEventHandler shadowPaintEvent)
|
{
|
if (_shadowDrawEventSubscribed)
|
{
|
return;
|
}
|
|
control.Paint += shadowPaintEvent;
|
control.Invalidate();
|
_shadowDrawEventSubscribed = true;
|
}
|
|
private void RemoveShadowPaintEvent(Control control, PaintEventHandler shadowPaintEvent)
|
{
|
if (!_shadowDrawEventSubscribed)
|
{
|
return;
|
}
|
|
control.Paint -= shadowPaintEvent;
|
control.Invalidate();
|
_shadowDrawEventSubscribed = false;
|
}
|
|
protected override void OnBackColorChanged(EventArgs e)
|
{
|
base.OnBackColorChanged(e);
|
BackColor = SkinManager.BackgroundColor;
|
}
|
|
protected override void OnResize(EventArgs e)
|
{
|
if (!_collapse)
|
{
|
if (DesignMode)
|
{
|
_expandHeight = Height;
|
}
|
if (Height < _minHeight)
|
{
|
Height = _minHeight;
|
}
|
}
|
else
|
{
|
Height = _headerHeightCollapse;
|
}
|
|
base.OnResize(e);
|
|
_headerBounds = new Rectangle(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, _headerHeight);
|
_expandcollapseBounds = new Rectangle(Width - _leftrightPadding - _expandcollapsbuttonsize, (int)((_headerHeight - _expandcollapsbuttonsize) / 2), _expandcollapsbuttonsize, _expandcollapsbuttonsize);
|
|
UpdateRects();
|
|
if (Parent != null)
|
{
|
RemoveShadowPaintEvent(Parent, drawShadowOnParent);
|
AddShadowPaintEvent(Parent, drawShadowOnParent);
|
}
|
}
|
|
protected override void OnMouseMove(MouseEventArgs e)
|
{
|
base.OnMouseMove(e);
|
|
if (DesignMode)
|
{
|
return;
|
}
|
|
ButtonState oldState = _buttonState;
|
|
if (_savebuttonBounds.Contains(e.Location))
|
{
|
_buttonState = ButtonState.SaveOver;
|
}
|
else if (_cancelbuttonBounds.Contains(e.Location))
|
{
|
_buttonState = ButtonState.CancelOver;
|
}
|
else if (_expandcollapseBounds.Contains(e.Location))
|
{
|
Cursor = Cursors.Hand;
|
_buttonState = ButtonState.ColapseExpandOver;
|
}
|
else if (_headerBounds.Contains(e.Location))
|
{
|
Cursor = Cursors.Hand;
|
_buttonState = ButtonState.HeaderOver;
|
}
|
else
|
{
|
Cursor = Cursors.Default;
|
_buttonState = ButtonState.None;
|
}
|
|
if (oldState != _buttonState)
|
{
|
Invalidate();
|
}
|
}
|
|
protected override void OnMouseDown(MouseEventArgs e)
|
{
|
if (Enabled && (_buttonState == ButtonState.HeaderOver | _buttonState == ButtonState.ColapseExpandOver))
|
{
|
Collapse = !Collapse;
|
CollapseOrExpand();
|
}
|
else
|
{
|
if (DesignMode)
|
{
|
return;
|
}
|
}
|
|
base.OnMouseDown(e);
|
}
|
|
protected override void OnMouseLeave(EventArgs e)
|
{
|
base.OnMouseLeave(e);
|
if (DesignMode)
|
{
|
return;
|
}
|
|
Cursor = Cursors.Arrow;
|
_buttonState = ButtonState.None;
|
Invalidate();
|
}
|
|
|
protected override void OnPaint(PaintEventArgs e)
|
{
|
Graphics g = e.Graphics;
|
g.TextRenderingHint = TextRenderingHint.AntiAlias;
|
|
g.Clear(Parent.BackColor == Color.Transparent ? ((Parent.Parent == null || (Parent.Parent != null && Parent.Parent.BackColor == Color.Transparent)) ? SkinManager.BackgroundColor : Parent.Parent.BackColor) : Parent.BackColor);
|
|
// card rectangle path
|
RectangleF expansionPanelRectF = new(ClientRectangle.Location, ClientRectangle.Size);
|
expansionPanelRectF.X -= 0.5f;
|
expansionPanelRectF.Y -= 0.5f;
|
GraphicsPath expansionPanelPath = CreateRoundRect(expansionPanelRectF, 2);
|
|
// button shadow (blend with form shadow)
|
DrawSquareShadow(g, ClientRectangle);
|
|
// Draw expansion panel
|
// Disabled
|
if (!Enabled)
|
{
|
using SolidBrush disabledBrush = new(BlendColor(Parent.BackColor, SkinManager.BackgroundDisabledColor, SkinManager.BackgroundDisabledColor.A));
|
g.FillPath(disabledBrush, expansionPanelPath);
|
}
|
// Mormal
|
else
|
{
|
if ((_buttonState == ButtonState.HeaderOver | _buttonState == ButtonState.ColapseExpandOver) && _collapse)
|
{
|
RectangleF expansionPanelBorderRectF = new(ClientRectangle.X + 1, ClientRectangle.Y + 1, ClientRectangle.Width - 2, ClientRectangle.Height - 2);
|
expansionPanelBorderRectF.X -= 0.5f;
|
expansionPanelBorderRectF.Y -= 0.5f;
|
GraphicsPath expansionPanelBoarderPath = CreateRoundRect(expansionPanelBorderRectF, 2);
|
|
g.FillPath(SkinManager.ExpansionPanelFocusBrush, expansionPanelBoarderPath);
|
}
|
else
|
{
|
using SolidBrush normalBrush = new(SkinManager.BackgroundColor);
|
g.FillPath(normalBrush, expansionPanelPath);
|
}
|
}
|
|
// Calc text Rect
|
Rectangle headerRect = new(
|
_leftrightPadding,
|
(_headerHeight - _textHeaderHeight) / 2,
|
TextRenderer.MeasureText(_titleHeader, Font).Width + _expansionPanelDefaultPadding,
|
_textHeaderHeight);
|
|
//Draw headers
|
using (MaterialNativeTextRenderer NativeText = new(g))
|
{
|
// Draw header text
|
NativeText.DrawTransparentText(
|
_titleHeader,
|
SkinManager.GetLogFontByType(MaterialSkinManager.FontType.Body1),
|
Enabled ? SkinManager.TextHighEmphasisColor : SkinManager.TextDisabledOrHintColor,
|
headerRect.Location,
|
headerRect.Size,
|
MaterialNativeTextRenderer.TextAlignFlags.Left | MaterialNativeTextRenderer.TextAlignFlags.Middle);
|
}
|
|
if (!string.IsNullOrEmpty(_descriptionHeader))
|
{
|
//Draw description header text
|
|
Rectangle headerDescriptionRect = new(
|
headerRect.Right + _expansionPanelDefaultPadding,
|
(_headerHeight - _textHeaderHeight) / 2,
|
_expandcollapseBounds.Left - (headerRect.Right + _expansionPanelDefaultPadding) - _expansionPanelDefaultPadding,
|
_textHeaderHeight);
|
|
using MaterialNativeTextRenderer NativeText = new(g);
|
// Draw description header text
|
NativeText.DrawTransparentText(
|
_descriptionHeader,
|
SkinManager.GetLogFontByType(MaterialSkinManager.FontType.Body1),
|
SkinManager.TextDisabledOrHintColor,
|
headerDescriptionRect.Location,
|
headerDescriptionRect.Size,
|
MaterialNativeTextRenderer.TextAlignFlags.Left | MaterialNativeTextRenderer.TextAlignFlags.Middle);
|
}
|
|
if (_showCollapseExpand == true)
|
{
|
using Pen formButtonsPen = new(_useAccentColor && Enabled ? SkinManager.ColorScheme.AccentColor : SkinManager.TextDisabledOrHintColor, 2);
|
if (_collapse)
|
{
|
//Draw Expand button
|
System.Drawing.Drawing2D.GraphicsPath pth = new();
|
PointF TopLeft = new(_expandcollapseBounds.X + 6, _expandcollapseBounds.Y + 9);
|
PointF MidBottom = new(_expandcollapseBounds.X + 12, _expandcollapseBounds.Y + 15);
|
PointF TopRight = new(_expandcollapseBounds.X + 18, _expandcollapseBounds.Y + 9);
|
pth.AddLine(TopLeft, MidBottom);
|
pth.AddLine(TopRight, MidBottom);
|
g.DrawPath(formButtonsPen, pth);
|
}
|
else
|
{
|
// Draw Collapse button
|
System.Drawing.Drawing2D.GraphicsPath pth = new();
|
PointF BottomLeft = new(_expandcollapseBounds.X + 6, _expandcollapseBounds.Y + 15);
|
PointF MidTop = new(_expandcollapseBounds.X + 12, _expandcollapseBounds.Y + 9);
|
PointF BottomRight = new(_expandcollapseBounds.X + 18, _expandcollapseBounds.Y + 15);
|
pth.AddLine(BottomLeft, MidTop);
|
pth.AddLine(BottomRight, MidTop);
|
g.DrawPath(formButtonsPen, pth);
|
}
|
}
|
|
if (!_collapse && _showValidationButtons)
|
{
|
//Draw divider
|
g.DrawLine(new Pen(SkinManager.DividersColor, 1), new Point(0, Height - _footerHeight), new Point(Width, Height - _footerHeight));
|
}
|
}
|
|
private void CollapseOrExpand()
|
{
|
//if (!useAnimation)
|
//{
|
if (_collapse)
|
{
|
_headerHeight = _headerHeightCollapse;
|
this.Height = _headerHeightCollapse;
|
Margin = new Padding(16, 1, 16, 0);
|
|
// Is the event registered?
|
if (PanelCollapse != null)
|
{
|
// Raise the event
|
this.PanelCollapse(this, new EventArgs());
|
}
|
}
|
else
|
{
|
_headerHeight = _headerHeightExpand;
|
this.Height = _expandHeight;
|
Margin = new Padding(16, 16, 16, 16);
|
|
// Is the event registered?
|
if (PanelExpand != null)
|
{
|
// Raise the event
|
this.PanelExpand(this, new EventArgs());
|
}
|
}
|
|
Refresh();
|
}
|
|
private void UpdateRects()
|
{
|
if (!_collapse && _showValidationButtons)
|
{
|
int _buttonWidth = TextRenderer.MeasureText(ValidationButtonText, SkinManager.GetFontByType(MaterialSkinManager.FontType.Button)).Width + 32;
|
_savebuttonBounds = new Rectangle(Width - _buttonPadding - _buttonWidth, Height - _expansionPanelDefaultPadding - _footerButtonHeight, _buttonWidth, _footerButtonHeight);
|
_buttonWidth = TextRenderer.MeasureText(CancelButtonText, SkinManager.GetFontByType(MaterialSkinManager.FontType.Button)).Width + 32;
|
_cancelbuttonBounds = new Rectangle(_savebuttonBounds.Left - _buttonPadding - _buttonWidth, Height - _expansionPanelDefaultPadding - _footerButtonHeight, _buttonWidth, _footerButtonHeight);
|
|
if (_validationButton != null)
|
{
|
_validationButton.Width = _savebuttonBounds.Width;
|
_validationButton.Left = Width - _buttonPadding - _validationButton.Width; //Button minimum width management
|
_validationButton.Top = _savebuttonBounds.Top;
|
_validationButton.Height = _savebuttonBounds.Height;
|
_validationButton.Text = _validationButtonText;
|
_validationButton.Enabled = _savebuttonEnable;
|
_validationButton.UseAccentColor = _useAccentColor;
|
}
|
if (_cancelButton != null)
|
{
|
_cancelButton.Width = _cancelbuttonBounds.Width;
|
_cancelButton.Left = _validationButton.Left - _buttonPadding - _cancelbuttonBounds.Width; //Button minimum width management
|
_cancelButton.Top = _cancelbuttonBounds.Top;
|
_cancelButton.Height = _cancelbuttonBounds.Height;
|
_cancelButton.Text = _cancelButtonText;
|
_cancelButton.UseAccentColor = _useAccentColor;
|
}
|
}
|
if (_validationButton != null)
|
{
|
_validationButton.Visible = _showValidationButtons;
|
}
|
if (_cancelButton != null)
|
{
|
_cancelButton.Visible = _showValidationButtons;
|
}
|
}
|
|
}
|
|
#endregion
|
}
|