public override void Layout(ViewLayoutContext context)
{
bool relayout;
bool canScrollV;
bool canScrollH;
// Update the enabled state of the scrollbars and contained control
ViewControl.Enabled = this.Enabled;
ScrollbarV.Enabled = this.Enabled;
ScrollbarH.Enabled = this.Enabled;
BorderEdgeV.Enabled = this.Enabled;
BorderEdgeH.Enabled = this.Enabled;
// Cache the starting viewport offsets
Point originalOffset = Viewport.Offset;
// Hide both scrollbars, in case having them both hidden
// always enough content to be seen that none or only one
// of them is required.
BorderEdgeV.Visible = ScrollbarV.Visible = false;
BorderEdgeH.Visible = ScrollbarH.Visible = false;
// Do not actually change the layout of any child controls
context.ViewManager.DoNotLayoutControls = true;
do
{
// Do we need to layout again?
relayout = false;
// Always reinstate the cached offset, so that if one of the cycles
// around limits the offset to a different value then subsequent cycles
// will not remember that artificial limitation
Viewport.Offset = originalOffset;
// Make sure the viewport has extents calculated
Viewport.GetPreferredSize(context);
// Let base class perform a layout calculation
base.Layout(context);
// Find the latest scrolling requirement
canScrollV = Viewport.CanScrollV;
canScrollH = Viewport.CanScrollH;
// Is there a change in vertical scrolling?
if (canScrollV != ScrollbarV.Visible)
{
// Update the view elements
ScrollbarV.Visible = canScrollV;
BorderEdgeV.Visible = canScrollV;
relayout = true;
}
// Is there a change in horizontally scrolling?
if (canScrollH != ScrollbarH.Visible)
{
// Update the view elements
ScrollbarH.Visible = canScrollH;
BorderEdgeH.Visible = canScrollH;
relayout = true;
}
// We short size the horizontal scrollbar if both bars are showing
bool needShortSize = (ScrollbarV.Visible && ScrollbarH.Visible);
if (ScrollbarH.ShortSize != needShortSize)
{
// Update the scrollbar view and need layout to reflect resizing
ScrollbarH.ShortSize = needShortSize;
relayout = true;
}
} while (relayout);
// Now all layouts have occured we can actually move child controls
context.ViewManager.DoNotLayoutControls = false;
// Perform actual layout of child controls
foreach (ViewBase child in this)
{
context.DisplayRectangle = child.ClientRectangle;
child.Layout(context);
}
// Do we need to update the vertical scrolling values?
if (canScrollV)
ScrollbarV.SetScrollValues(0, Viewport.ScrollExtent.Height - 1,
1, Viewport.ClientSize.Height,
Viewport.ScrollOffset.Y);
// Do we need to update the horizontal scrolling values?
if (canScrollH)
ScrollbarH.SetScrollValues(0, Viewport.ScrollExtent.Width - 1,
1, Viewport.ClientSize.Width,
Viewport.ScrollOffset.X);
}