using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using System.ComponentModel; using System.Drawing; namespace DevComponents.DotNetBar.Controls { /// /// Represents the panel which can slide out and into the view. /// [ToolboxBitmap(typeof(CircularProgress), "Controls.SlidePanel.ico"), ToolboxItem(true), Designer("DevComponents.DotNetBar.Design.SlidePanelDesigner, DevComponents.DotNetBar.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf")] public class SlidePanel : UserControl { internal const int DefaultAnimationTime = 500; #region Events /// /// Occurs when IsOpen property value has changed, i.e. slide-panel is shown or hidden. /// [Description("Occurs when IsOpen property value has changed, i.e. slide-panel is shown or hidden.")] public event EventHandler IsOpenChanged; /// /// Raises IsOpenChanged event. /// /// Provides event arguments. protected virtual void OnIsOpenChanged(EventArgs e) { EventHandler handler = IsOpenChanged; if (handler != null) handler(this, e); } #endregion #region Constructor protected override void Dispose(bool disposing) { DisposeSlideOutButton(); base.Dispose(disposing); } #endregion #region Implementation private eSlideSide _SlideSide = eSlideSide.Left; /// /// Gets or sets side panel slides into. /// [DefaultValue(eSlideSide.Left), Category("Behavior"), Description("Indicates side panel slides into.")] public eSlideSide SlideSide { get { return _SlideSide; } set { if (value != _SlideSide) { eSlideSide oldValue = _SlideSide; _SlideSide = value; OnSlideSideChanged(oldValue, value); } } } /// /// Called when SlideSide property has changed. /// /// Old property value /// New property value protected virtual void OnSlideSideChanged(eSlideSide oldValue, eSlideSide newValue) { //OnPropertyChanged(new PropertyChangedEventArgs("SlideSide")); if (!this.IsOpen) { WaitForCurrentAnimationFinish(); this.Bounds = GetSlideOutBounds(this.Parent, _OpenBounds); if (_SlideOutButtonVisible) CreateSlideOutButton(); } } private bool _IsOpen = true; /// /// Gets or sets whether panel is open. When this property is changed panel will slide in or out of the view. /// [Browsable(false), DefaultValue(true), Description("Indicates whether panel is open. When this property is changed panel will slide in or out of the view.")] public bool IsOpen { get { return _IsOpen; } set { if (_UsesBlockingAnimation && _CurrentAnimation != null || _IsWaiting) return; if (value != _IsOpen) { bool oldValue = _IsOpen; _IsOpen = value; OnIsOpenChanged(oldValue, value); } } } /// /// Called when IsOpen property has changed. /// /// Old property value /// New property value protected virtual void OnIsOpenChanged(bool oldValue, bool newValue) { //OnPropertyChanged(new PropertyChangedEventArgs("IsOpen")); if (!newValue) SlideOutOfView(); else SlideIntoView(); OnIsOpenChanged(EventArgs.Empty); } private bool _UsesBlockingAnimation = false; /// /// Gets or sets whether panel uses modal animation, meaning when IsOpen property is set the call is not returned until animation is complete. /// [Browsable(false)] public bool UsesBlockingAnimation { get { return _UsesBlockingAnimation; } set { _UsesBlockingAnimation = value; } } private Rectangle _OpenBounds = Rectangle.Empty; /// /// Gets or sets the open panel bounds. When control IsOpen=false and panel is collapsed its original bounds are stored in OpenBounds property and restored once panel is open. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Rectangle OpenBounds { get { return _OpenBounds; } set { _OpenBounds = value; if (!this.Visible && this.Bounds.Size != _OpenBounds.Size) this.Bounds = GetSlideOutBounds(this.Parent, _OpenBounds); } } /// /// Slides panel into the view. /// private void SlideIntoView() { Animation.Animation current = _CurrentAnimation; if (current != null) { current.Stop(); WaitForCurrentAnimationFinish(); } Rectangle bounds = this.Bounds; Rectangle targetBounds = _OpenBounds; if (_SlideOutButton != null) _SlideOutButton.Visible = false; if (_AnimationTime > 0) { _IsAnimating = true; //BarFunctions.AnimateControl(this, true, _AnimationTime, bounds, targetBounds); this.Visible = true; Animation.AnimationRectangle anim = new DevComponents.DotNetBar.Animation.AnimationRectangle( new Animation.AnimationRequest(this, "Bounds", bounds, targetBounds), Animation.AnimationEasing.EaseOutExpo, _AnimationTime); anim.AnimationCompleted += new EventHandler(AnimationCompleted); anim.Start(); _CurrentAnimation = anim; } else this.Bounds = targetBounds; if (_SlideOutButtonVisible && _SlideOutButton != null) { DisposeSlideOutButton(); } } internal void AbortAnimation() { Animation.Animation anim = _CurrentAnimation; _CurrentAnimation = null; if (anim != null) { anim.Stop(); anim.Dispose(); //Console.WriteLine("{0} Animation Forcefully Stopped", DateTime.Now); } } private bool _IsWaiting = false; /// /// Waits for current slide animation to finish and then returns control. /// public void WaitForCurrentAnimationFinish() { if (_IsWaiting) return; _IsWaiting = true; try { if (_CurrentAnimation == null) return; DateTime start = DateTime.Now; while (_CurrentAnimation != null) { Application.DoEvents(); if (DateTime.Now.Subtract(start).TotalMilliseconds > _AnimationTime * 1.5f) { AbortAnimation(); break; } } } finally { _IsWaiting = false; } } private void DisposeSlideOutButton() { if (_SlideOutButton == null) return; Control parent = _SlideOutButton.Parent; if (parent != null) { parent.Resize -= ParentResize; parent.Controls.Remove(_SlideOutButton); } _SlideOutButton.Dispose(); _SlideOutButton = null; } private Animation.Animation _CurrentAnimation = null; /// /// Slides panel out of the view. /// private void SlideOutOfView() { Animation.Animation current = _CurrentAnimation; if (current != null) { current.Stop(); WaitForCurrentAnimationFinish(); } Rectangle bounds = this.Bounds; Rectangle targetBounds = GetSlideOutBounds(); if (_AnimationTime > 0 && this.Visible) { _IsAnimating = true; //BarFunctions.AnimateControl(this, true, _AnimationTime, bounds, targetBounds); Animation.AnimationRectangle anim = new DevComponents.DotNetBar.Animation.AnimationRectangle( new Animation.AnimationRequest(this, "Bounds", bounds, targetBounds), Animation.AnimationEasing.EaseOutExpo, _AnimationTime); anim.AnimationCompleted += new EventHandler(AnimationCompleted); anim.Start(); _CurrentAnimation = anim; //this.Visible = false; } else this.Bounds = targetBounds; _OpenBounds = bounds; if (_SlideOutButtonVisible) CreateSlideOutButton(); } private bool _IsAnimating = false; internal bool IsAnimating { get { return _IsAnimating; } } private void AnimationCompleted(object sender, EventArgs e) { //Console.WriteLine("{0} Animation Completed", DateTime.Now); Animation.Animation anim = _CurrentAnimation; _CurrentAnimation = null; if (anim != null) anim.Dispose(); if (!_IsOpen) { this.Visible = false; } _IsAnimating = false; } public void SlideOutOfViewSilent(Control parent) { _OpenBounds = this.Bounds; this.Bounds = GetSlideOutBounds(parent); _IsOpen = false; } private SliderButton _SlideOutButton = null; private void CreateSlideOutButton() { DisposeSlideOutButton(); Control parent = this.Parent; if (parent == null) return; _SlideOutButton = new SliderButton(this); if (_SlideOutButtonStyle != null) _SlideOutButton.Style = _SlideOutButtonStyle; else _SlideOutButton.Style = new ElementStyle(DevComponents.DotNetBar.Rendering.ElementStyleClassKeys.SlideOutButtonKey); Size activeSlideOutSize = Dpi.Size(_SlideOutActiveButtonSize); Size slideOutSize = Dpi.Size(_SlideOutButtonSize); if (_SlideSide == eSlideSide.Top || _SlideSide == eSlideSide.Bottom) // Flip width/height { activeSlideOutSize = new Size(activeSlideOutSize.Height, activeSlideOutSize.Width); slideOutSize = new Size(slideOutSize.Height, slideOutSize.Width); } _SlideOutButton.ActiveSliderSize = activeSlideOutSize; _SlideOutButton.SliderSize = slideOutSize; _SlideOutButton.Symbol = _Symbol; _SlideOutButton.SymbolColor = _SymbolColor; _SlideOutButton.SymbolSet = _SymbolSet; _SlideOutButton.SymbolSize = _SymbolSize; parent.Controls.Add(_SlideOutButton); parent.Controls.SetChildIndex(_SlideOutButton, 0); parent.Resize += ParentResize; } private void ParentResize(object sender, EventArgs e) { if (_SlideOutButton != null) _SlideOutButton.UpdatePosition(); } private Rectangle GetSlideOutBounds() { return GetSlideOutBounds(this.Parent); } private Rectangle GetSlideOutBounds(Control parent) { return GetSlideOutBounds(parent, this.Bounds); } private Rectangle GetSlideOutBounds(Control parent, Rectangle panelBounds) { if (parent == null) return panelBounds; Rectangle r = panelBounds; if (_SlideSide == eSlideSide.Left) { r.X = -r.Width; } else if (_SlideSide == eSlideSide.Right) { r.X = parent.Width; } else if (_SlideSide == eSlideSide.Top) { r.Y = -r.Height; } else if (_SlideSide == eSlideSide.Bottom) { r.Y = parent.Height; } return r; } private int _AnimationTime = DefaultAnimationTime; /// /// Gets or sets the animation duration time in milliseconds. Setting this property to 0 will disable slide animation. /// [DefaultValue(DefaultAnimationTime), Category("Behavior"), Description("Indicates animation duration time in milliseconds. Setting this property to 0 will disable slide animation.")] public int AnimationTime { get { return _AnimationTime; } set { if (value != _AnimationTime) { int oldValue = _AnimationTime; _AnimationTime = value; OnAnimationTimeChanged(oldValue, value); } } } /// /// Called when AnimationTime property has changed. /// /// Old property value /// New property value protected virtual void OnAnimationTimeChanged(int oldValue, int newValue) { //OnPropertyChanged(new PropertyChangedEventArgs("AnimationTime")); } private bool _SlideOutButtonVisible = true; /// /// Gets or sets whether slide out button is shown when panel is out of the view and which allows panel to be shown. /// [DefaultValue(true), Category("Behavior"), Description("Indicates whether slide out button is shown when panel is out of the view and which allows panel to be shown.")] public bool SlideOutButtonVisible { get { return _SlideOutButtonVisible; } set { if (value != _SlideOutButtonVisible) { bool oldValue = _SlideOutButtonVisible; _SlideOutButtonVisible = value; OnSlideOutButtonVisibleChanged(oldValue, value); } } } /// /// Called when SlideOutButtonVisible property has changed. /// /// Old property value /// New property value protected virtual void OnSlideOutButtonVisibleChanged(bool oldValue, bool newValue) { //OnPropertyChanged(new PropertyChangedEventArgs("SlideOutButtonVisible")); if (_IsOpen) return; if (newValue) CreateSlideOutButton(); else DisposeSlideOutButton(); } private Size _SlideOutButtonSize = SliderButton.DefaultSliderSize; /// /// Gets or sets the slide-out buttton size in default state. /// [Category("Appearance"), Description("Indicates slide-out buttton size in default state.")] public Size SlideOutButtonSize { get { return _SlideOutButtonSize; } set { if (value != _SlideOutButtonSize) { Size oldValue = _SlideOutButtonSize; _SlideOutButtonSize = value; OnSlideOutButtonSizeChanged(oldValue, value); } } } /// /// Called when SlideOutButtonSize property has changed. /// /// Old property value /// New property value protected virtual void OnSlideOutButtonSizeChanged(Size oldValue, Size newValue) { //OnPropertyChanged(new PropertyChangedEventArgs("SlideOutButtonSize")); if (_SlideOutButton != null) { _SlideOutButton.SliderSize = newValue; _SlideOutButton.UpdatePosition(); } } /// /// Returns whether property should be serialized. /// public bool ShouldSerializeSlideOutButtonSize() { return _SlideOutButtonSize != SliderButton.DefaultSliderSize; } /// /// Resets property to default value. /// [EditorBrowsable(EditorBrowsableState.Never)] public void ResetSlideOutButtonSize() { SlideOutButtonSize = SliderButton.DefaultSliderSize; } private Size _SlideOutActiveButtonSize = SliderButton.DefaultActiveSliderSize; /// /// Gets or sets active (mouse over) slide out button size. /// [Category("Appearance"), Description("Indicates active (mouse over) slide out button size.")] public Size SlideOutActiveButtonSize { get { return _SlideOutActiveButtonSize; } set { if (value != _SlideOutActiveButtonSize) { Size oldValue = _SlideOutActiveButtonSize; _SlideOutActiveButtonSize = value; OnSlideOutActiveButtonSizeChanged(oldValue, value); } } } /// /// Called when SlideOutActiveButtonSize property has changed. /// /// Old property value /// New property value protected virtual void OnSlideOutActiveButtonSizeChanged(Size oldValue, Size newValue) { //OnPropertyChanged(new PropertyChangedEventArgs("SlideOutActiveButtonSize")); if (_SlideOutButton != null) { _SlideOutButton.ActiveSliderSize = newValue; _SlideOutButton.UpdatePosition(); } } /// /// Returns whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeSlideOutActiveButtonSize() { return _SlideOutActiveButtonSize != SliderButton.DefaultActiveSliderSize; } /// /// Resets property to default value. /// [EditorBrowsable(EditorBrowsableState.Never)] public void ResetSlideOutActiveButtonSize() { SlideOutActiveButtonSize = SliderButton.DefaultActiveSliderSize; } private ElementStyle _SlideOutButtonStyle = null; /// /// Gets or sets slide-out button style. /// [DefaultValue(null), Category("Appearance"), Description("Indicates slide-out button style.")] public ElementStyle SlideOutButtonStyle { get { return _SlideOutButtonStyle; } set { if (value != _SlideOutButtonStyle) { ElementStyle oldValue = _SlideOutButtonStyle; _SlideOutButtonStyle = value; OnSlideOutButtonStyleChanged(oldValue, value); } } } /// /// Called when SlideOutButtonStyle property has changed. /// /// Old property value /// New property value protected virtual void OnSlideOutButtonStyleChanged(ElementStyle oldValue, ElementStyle newValue) { if (newValue != null) { if (_SlideOutButton != null) _SlideOutButton.Style = newValue; } //OnPropertyChanged(new PropertyChangedEventArgs("SlideOutButtonStyle")); } private bool _CenterContent = false; /// /// Gets or sets whether panel centers the Controls inside of it. Default value is false. /// internal bool CenterContent { get { return _CenterContent; } set { if (value != _CenterContent) { bool oldValue = _CenterContent; _CenterContent = value; OnCenterContentChanged(oldValue, value); } } } /// /// Called when CenterContent property has changed. /// /// Old property value /// New property value protected virtual void OnCenterContentChanged(bool oldValue, bool newValue) { //OnPropertyChanged(new PropertyChangedEventArgs("CenterContent")); if (newValue) CenterControls(); } protected override void OnResize(EventArgs e) { if (_CenterContent) CenterControls(); base.OnResize(e); } protected override void OnControlAdded(ControlEventArgs e) { if (_CenterContent) CenterControl(e.Control); base.OnControlAdded(e); } private void CenterControl(Control item) { Point loc = new Point(Math.Max(0, (this.Width - item.Width) / 2), Math.Max(0, (this.Height - item.Height) / 2)); if (item.Location != loc) item.Location = loc; } private void CenterControls() { foreach (Control item in this.Controls) { CenterControl(item); } } [Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), EditorBrowsable(EditorBrowsableState.Always), Bindable(true)] public override string Text { get { return base.Text; } set { base.Text = value; } } private Color _SymbolColor = Color.Empty; /// /// Gets or sets the color of the Symbol displayed on slideout button. /// [Category("Appearance"), Description("Indicates color of the Symbol displayed on slideout button.")] public Color SymbolColor { get { return _SymbolColor; } set { _SymbolColor = value; this.Invalidate(); } } /// /// Gets whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeSymbolColor() { return !_SymbolColor.IsEmpty; } /// /// Resets property to its default value. /// [EditorBrowsable(EditorBrowsableState.Never)] public void ResetSymbolColor() { this.SymbolColor = Color.Empty; } /// /// Gets the realized symbol string. /// [Browsable(false)] public string SymbolRealized { get { return _SymbolRealized; } } private string _Symbol = "", _SymbolRealized = ""; /// /// Indicates the symbol displayed on face of the slideout button. /// [DefaultValue(""), Category("Appearance"), Description("Indicates the symbol displayed on face of the slideout button.")] [Editor("DevComponents.DotNetBar.Design.SymbolTypeEditor, DevComponents.DotNetBar.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(System.Drawing.Design.UITypeEditor))] public string Symbol { get { return _Symbol; } set { if (value != _Symbol) { string oldValue = _Symbol; _Symbol = value; OnSymbolChanged(oldValue, value); } } } /// /// Called when Symbol property has changed. /// /// Old property value /// New property value protected virtual void OnSymbolChanged(string oldValue, string newValue) { if (string.IsNullOrEmpty(newValue)) _SymbolRealized = ""; else _SymbolRealized = Symbols.GetSymbol(newValue); this.Invalidate(); } private eSymbolSet _SymbolSet = eSymbolSet.Awesome; /// /// Gets or sets the symbol set used to represent the Symbol. /// [Browsable(false), DefaultValue(eSymbolSet.Awesome)] public eSymbolSet SymbolSet { get { return _SymbolSet; } set { if (_SymbolSet != value) { eSymbolSet oldValue = _SymbolSet; _SymbolSet = value; OnSymbolSetChanged(oldValue, value); } } } /// /// Called when SymbolSet property value changes. /// /// Indciates old value /// Indicates new value protected virtual void OnSymbolSetChanged(eSymbolSet oldValue, eSymbolSet newValue) { this.Invalidate(); this.Refresh(); } private float _SymbolSize = 10f; /// /// Indicates the size of the symbol in points. /// [DefaultValue(10f), Category("Appearance"), Description("Indicates the size of the symbol in points.")] public float SymbolSize { get { return _SymbolSize; } set { if (value != _SymbolSize) { float oldValue = _SymbolSize; _SymbolSize = value; OnSymbolSizeChanged(oldValue, value); } } } /// /// Called when SymbolSize property has changed. /// /// Old property value /// New property value protected virtual void OnSymbolSizeChanged(float oldValue, float newValue) { this.Invalidate(); } #endregion } /// /// Defines the side SlidePanel slides into. /// public enum eSlideSide { Left, Right, Top, Bottom } }