Download Source Code: DockingPanel.zip - 9.94KB
Implementation
DockingPanel is implemented as a typical ASP.NET web user control, derived from Panel. Here is the main CreateControls private function, that builds the controls when Render is called:
private void CreateControls()
{
if (base.Width.IsEmpty)
base.Width = Unit.Percentage(100);
if (base.Height.IsEmpty && !IsVertical())
base.Height = Unit.Percentage(100);
if (_altStyles)
base.CssClass = "dock-control";
// if grouping, add a hidden input element
if (_group != null && _group.Length > 0)
{
HtmlInputHidden hidden = new HtmlInputHidden();
hidden.Value = "docking_group_" + _group;
base.Controls.Add(hidden);
}
// inner container
Panel panelContentArea = new Panel();
if (!IsVertical())
{
panelContentArea.Height = Unit.Percentage(100);
panelContentArea.Style.Add("float",
_docking == DockingStyle.Left ? "left" : "none");
}
// title bar (with title text and chevron)
Panel panelTitleBar = new Panel();
if (_altStyles)
panelTitleBar.CssClass = "dock-titlebar";
else
{
panelTitleBar.BackColor = Color.Lavender;
panelTitleBar.BorderStyle = BorderStyle.Solid;
panelTitleBar.BorderWidth = Unit.Pixel(1);
panelTitleBar.BorderColor = Color.Gray;
}
if (!IsVertical())
{
panelTitleBar.Height = Unit.Percentage(100);
panelTitleBar.Width = Unit.Pixel(19);
panelTitleBar.Style.Add("text-align", "center");
panelTitleBar.Style.Add("float",
_docking == DockingStyle.Left ? "left" : "right");
panelTitleBar.Style.Add("background-image",
"url(DynamicImage.aspx?"
+ (_docking == DockingStyle.Left
? "rotate=true&" : "")
+ "italic=true&vtext="
+ HttpUtility.UrlEncode(_text) + ")");
panelTitleBar.Style.Add("background-repeat", "no-repeat");
panelTitleBar.Style.Add("background-position", "bottom "
+ (_docking == DockingStyle.Left ? "right" : "left"));
}
else
{
panelTitleBar.Height = Unit.Pixel(19);
panelTitleBar.Style.Add("text-align", "left");
}
// panel to align chevron right (but only for Top/Bottom)
Panel panelChevron = new Panel();
panelChevron.Style.Add("float", "right");
// chevron image
System.Web.UI.WebControls.Image chevron
= new System.Web.UI.WebControls.Image();
chevron.ID = ID + "_chevron";
chevron.Style.Add("cursor", "hand");
chevron.Style.Add("cursor", "pointer");
chevron.BorderWidth = 0;
chevron.AlternateText = "Expand/Collapse";
chevron.ImageUrl
= "images/" + GetChevronImageName() + ".png";
chevron.Attributes.Add("onclick", _animation
? "ToggleDockingPanel2(this.id.substring(0,"
+ "this.id.lastIndexOf('_')),'" + _group + "',"
+ _interval + "," + _step + ")"
: "ToggleDockingPanel4(this.id.substring(0,"
+ "this.id.lastIndexOf('_')),'" + _group + "')");
// title (but only for Top/Bottom)
Literal text = new Literal();
text.Text = " <i>" + _text + "</i>";
// collapsible content panel
Panel panelContent = new Panel();
panelContent.ID = ID + "_content";
panelContent.Height = Unit.Percentage(100);
if (_docking == DockingStyle.Right)
panelContent.Style.Add("float", "right");
panelContent.Style.Add("display", _collapsed ? "none" : "block");
panelContent.Style.Add("overflow", "hidden");
panelContent.Style.Add("border-"
+ _docking.ToString().ToLower() + "-style", "none");
if (_altStyles)
panelContent.CssClass = "dock-content";
else
{
panelContent.BackColor = Color.WhiteSmoke;
panelContent.BorderStyle = BorderStyle.Solid;
panelContent.BorderWidth = Unit.Pixel(1);
panelContent.BorderColor = Color.Gray;
}
// fixed content panel
Panel panelFixedContent = new Panel();
panelFixedContent.Height = Unit.Percentage(100);
panelFixedContent.Style.Add("overflow", "hidden");
if (_altStyles)
panelFixedContent.CssClass = "dock-fixed-content";
// structure
panelContent.Controls.Add(_content);
if (_fixedContent.Controls.Count > 0)
panelFixedContent.Controls.Add(_fixedContent);
switch (_docking)
{
case DockingStyle.Top:
base.Controls.Add(panelContentArea);
if (_fixedContent.Controls.Count > 0)
base.Controls.Add(panelFixedContent);
panelContentArea.Controls.Add(panelTitleBar);
panelContentArea.Controls.Add(panelContent);
panelTitleBar.Controls.Add(panelChevron);
panelTitleBar.Controls.Add(text);
panelChevron.Controls.Add(chevron);
break;
case DockingStyle.Bottom:
if (_fixedContent.Controls.Count > 0)
base.Controls.Add(panelFixedContent);
base.Controls.Add(panelContentArea);
panelContentArea.Controls.Add(panelContent);
panelContentArea.Controls.Add(panelTitleBar);
panelTitleBar.Controls.Add(panelChevron);
panelTitleBar.Controls.Add(text);
panelChevron.Controls.Add(chevron);
break;
case DockingStyle.Left:
base.Controls.Add(panelContentArea);
if (_fixedContent.Controls.Count > 0)
base.Controls.Add(panelFixedContent);
panelContentArea.Controls.Add(panelTitleBar);
panelContentArea.Controls.Add(panelContent);
panelTitleBar.Controls.Add(chevron);
break;
case DockingStyle.Right:
base.Controls.Add(panelContentArea);
panelContentArea.Controls.Add(panelTitleBar);
panelContentArea.Controls.Add(panelContent);
if (_fixedContent.Controls.Count > 0)
panelContentArea.Controls.Add(panelFixedContent);
panelTitleBar.Controls.Add(chevron);
break;
}
}It is important to have Width (and Height, for horizontal orientation) set. If they are not, they will be set to 100%.
For vertical orientation (Left or Right docking), the title must appear vertical: bottom-up for Left docking and top-down for Right docking. To get vertical text in HTML, we use the technique already described at Vertical HTML Text as Dynamic Image. Images are created on-the-fly from the required text by the DynamicImage.aspx page, included with the demo project. The title bar will show these images as background at the bottom of the vertical edge.
Each control has a Group property, by default empty. You can group several panels together for an "accordion" effect: one single panel from the group can be expanded at one time, the others are automatically collapsed. We implemented this with an INPUT type HIDDEN placeholder element, which value has the group name. Before a panel with group expands, a client-side JavaScript function will collapse all other panels with the same group name:
function CollapseAllBut(ctrlID, group)
{
if (group==null || group.length==0)
return;
var groups = document.getElementsByTagName("input");
for (var i=0; i<groups.length; i++)
if (groups[i].type=="hidden"
&& groups[i].value=="docking_group_" + group
&& groups[i].parentNode.id!=ctrlID)
ToggleDockingPanel3(groups[i].parentNode.id, false);
}When UseAnimation is False, the ToggleDockingPanel4 JavaScript function provides an instantaneous collapse/expand effect. ToggleDockingPanel was its previous implementation, with no group name. ToggleDockingPanel3 provides a specific expand or collapse action. ToggleDockingPanelChevron will change the chevron's image name accordingly:
function ToggleDockingPanel(ctrlID)
{
var content = document.getElementById(ctrlID + "_content");
var chevron = document.getElementById(ctrlID + "_chevron");
if (typeof(content) != "undefined"
&& typeof(chevron) != "undefined")
{
var expand = (content.style.display=="none");
content.style.display = (expand ? "block" : "none");
ToggleDockingPanelChevron(chevron);
}
}
function ToggleDockingPanelChevron(chevron)
{
var src = chevron.src.toString();
if (src.indexOf("to-top")>0)
chevron.src = src.split("to-top").join("to-bottom");
else if (src.indexOf("to-bottom")>0)
chevron.src = src.split("to-bottom").join("to-top");
else if (src.indexOf("to-left")>0)
chevron.src = src.split("to-left").join("to-right");
else if (src.indexOf("to-right")>0)
chevron.src = src.split("to-right").join("to-left");
return (src.indexOf("to-top")>0 || src.indexOf("to-bottom")>0);
}
function ToggleDockingPanel4(ctrlID, group)
{
var content = document.getElementById(ctrlID + "_content");
var chevron = document.getElementById(ctrlID + "_chevron");
if (typeof(content) != "undefined"
&& typeof(chevron) != "undefined")
{
var expand = (content.style.display=="none");
if (expand)
CollapseAllBut(ctrlID, group);
content.style.display = (expand ? "block" : "none");
ToggleDockingPanelChevron(chevron);
}
}
function ToggleDockingPanel3(ctrlID, expand)
{
var content = document.getElementById(ctrlID + "_content");
var chevron = document.getElementById(ctrlID + "_chevron");
if (typeof(content) != "undefined"
&& typeof(chevron) != "undefined"
&& (expand && content.style.display=="none"
|| !expand && content.style.display!="none"))
{
content.style.display = (expand ? "block" : "none");
ToggleDockingPanelChevron(chevron);
}
}Animation has been already described in the page 3 of the Animated Collapsible Panel. When Animation is True, ToggleDockingPanel2 JavaScript function will be called instead, which starts the initial animation iteration, each iteration being executed by ToggleDockingPanelAnimation.