using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; using System.ComponentModel.Design; namespace SDRSharp.CollapsiblePanel { /// <summary> /// Enumeration for defining the options for panel state /// </summary> public enum PanelStateOptions { Collapsed, Expanded } /// <summary> /// Main class for collapsible panel user control /// </summary> [DesignTimeVisible(true)] [Category("Containers")] [Description("Visual Studio like Collapsible Panel")] [Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))] public partial class CollapsiblePanel : UserControl { #region Class members #region Variables /// <summary> /// Variable for setting the user control height when control is expanded /// </summary> int _expandedHeight; /// <summary> /// Variable for setting the current user control state /// </summary> PanelStateOptions _panelState = PanelStateOptions.Expanded; /// <summary> /// Variable for determining if the user control is currently collapsed /// </summary> bool _isCollapsed = false; /// <summary> /// Determines if this user control is going to match its parent width /// </summary> bool _fitToParent = false; /// <summary> /// Panel to be located beneath this panel /// </summary> CollapsiblePanel _nextPanel; #endregion #region Delegates and events /// <summary> /// Delegate and event for informing the parent control that this user control state has changed /// </summary> public delegate void DelegateStateChanged(); [Category("Collapsible Panel")] public event DelegateStateChanged StateChanged; #endregion #region Properties /// <summary> /// Gets or sets the value for user control height when it is expanded /// </summary> [Description("Gets or sets the value for user control height when it is expanded")] [DisplayName("Expanded Height")] [Category("Collapsible Panel")] [DefaultValueAttribute(0)] public int ExpandedHeight { get { return _expandedHeight; } set { if (value > 0) { if (this.DesignMode) { if (_panelState == PanelStateOptions.Expanded) { //Setting Expanded Height is only allowed when user control is expanded this.SetBounds(this.Location.X, this.Location.Y, this.Size.Width, titlePanel.Height + value); } } else { _expandedHeight = value; } } } } /// <summary> /// Gets or sets panel title" /// </summary> [Description("Gets or sets panel title")] [DisplayName("Panel Title")] [Category("Collapsible Panel")] public string PanelTitle { get { return lblPanelTitle.Text; } set { lblPanelTitle.Text = value; } } /// <summary> /// Gets or sets current panel state /// </summary> [DefaultValue(typeof(PanelStateOptions),"Expanded")] [Description("Gets or sets current panel state")] [DisplayName("Panel State")] [Category("Collapsible Panel")] public PanelStateOptions PanelState { get { return _panelState; } set { _panelState = value; _isCollapsed = (_panelState != PanelStateOptions.Collapsed); ToggleState(null,null); } } /// <summary> /// If True, fits the panel to match the parent width /// </summary> [Category("Collapsible Panel")] [DesignOnly(true)] [DefaultValue(false)] [Description("If True, fits the panel to match the parent width")] public bool FitToParent { get { return _fitToParent; } set { _fitToParent = value; ////if (this.DesignMode) ////{ if (_fitToParent) { if (this.Parent != null) { this.Location = new Point(0, this.Location.Y); this.Size = new Size(this.Parent.Size.Width, this.Size.Height); this.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; } } else { this.Anchor = AnchorStyles.Top | AnchorStyles.Left; } ////} } } /// <summary> /// Gets or sets the panel to be located beneath this panel /// </summary> [Category("Collapsible Panel")] [Description("Gets or sets the panel to be located beneath this panel")] public CollapsiblePanel NextPanel { get { return _nextPanel; } set { _nextPanel = value; MoveNextPanel(); } } #endregion #endregion #region Class constructor public CollapsiblePanel() { InitializeComponent(); ////if (!this.DesignMode) ////{ //// _expandedHeight = contentPanel.Height; ////} ////else ////{ //// contentPanel.Height = this.Height - titlePanel.Height; ////} this.Load += new EventHandler(CollapsiblePanel_Load); this.SizeChanged += new EventHandler(CollapsiblePanel_SizeChanged); this.LocationChanged += new EventHandler(CollapsiblePanel_LocationChanged); } #endregion #region Methods for handling user control events void CollapsiblePanel_Load(object sender, EventArgs e) { ///Determining and setting the initial toggling image _isCollapsed = (_panelState == PanelStateOptions.Collapsed); if (_isCollapsed) { togglingImage.Image = global::SDRSharp.CollapsiblePanel.Properties.Resources.ExpandedIcon; } else { togglingImage.Image = global::SDRSharp.CollapsiblePanel.Properties.Resources.CollapsedIcon; } } /// <summary> /// We use this event to recalculate the Expanded Height when the user resizes the user control at Design mode /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void CollapsiblePanel_SizeChanged(object sender, EventArgs e) { if (this.DesignMode) { if (_panelState == PanelStateOptions.Expanded) { _expandedHeight = this.Height - titlePanel.Height; } else { ///Final user can only resize the user control when it is expanded this.SetBounds(this.Location.X, this.Location.Y, this.Size.Width, titlePanel.Height); } if (this.Parent != null) { if (this.Parent.Size.Width != this.Size.Width) { FitToParent = false; } } } MoveNextPanel(); } /// <summary> /// We use this event in order to move the next panel down when this panel located is changed /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void CollapsiblePanel_LocationChanged(object sender, EventArgs e) { if (this.DesignMode) { if (this.Location.X > 0) { FitToParent = false; } } MoveNextPanel(); } #endregion #region Class Methods /// <summary> /// Changes the current state from Collapsed to Expanded or viceversa /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ToggleState(object sender, EventArgs e) { if (_isCollapsed) { ///Current state is Collapsed. Expand the user control this.SetBounds(this.Location.X, this.Location.Y, this.Size.Width, titlePanel.Height + _expandedHeight); } else { ///Current state is Expanded. Collapse the user control this.SetBounds(this.Location.X, this.Location.Y, this.Size.Width, titlePanel.Height); } _isCollapsed = !_isCollapsed; ///Setting content control current state and toggling image if (_isCollapsed) { _panelState = PanelStateOptions.Collapsed; togglingImage.Image = global::SDRSharp.CollapsiblePanel.Properties.Resources.ExpandedIcon; } else { _panelState = PanelStateOptions.Expanded; togglingImage.Image = global::SDRSharp.CollapsiblePanel.Properties.Resources.CollapsedIcon; } if (!this.DesignMode) { if (StateChanged != null) { ///Fire the event to inform the parent control that the state for the user control has changed StateChanged(); } } } /// <summary> /// Moves the next panel down (when user control state is changed or the control is relocated) /// </summary> private void MoveNextPanel() { if (_nextPanel != null) { _nextPanel.Location = new Point(_nextPanel.Location.X, this.Location.Y + this.Size.Height); } } #endregion } }