public override void Layout()
{
ISceneDrawable bg = _style.Background;
ISceneDrawable hScrollKnob = _style.HScrollKnob;
ISceneDrawable vScrollKnob = _style.VScrollKnob;
float bgLeftWidth = 0;
float bgRightWidth = 0;
float bgTopHeight = 0;
float bgBottomHeight = 0;
if (bg != null) {
bgLeftWidth = bg.LeftWidth;
bgRightWidth = bg.RightWidth;
bgTopHeight = bg.TopHeight;
bgBottomHeight = bg.BottomHeight;
}
float width = Width;
float height = Height;
float scrollbarHeight = 0;
if (hScrollKnob != null)
scrollbarHeight = hScrollKnob.MinHeight;
if (_style.HScroll != null)
scrollbarHeight = Math.Max(scrollbarHeight, _style.HScroll.MinHeight);
float scrollbarWidth = 0;
if (vScrollKnob != null)
scrollbarWidth = vScrollKnob.MinWidth;
if (_style.VScroll != null)
scrollbarWidth = Math.Max(scrollbarWidth, _style.VScroll.MinWidth);
// Get available space size by subtracting background's padded area.
_areaWidth = width - bgLeftWidth - bgRightWidth;
_areaHeight = height - bgTopHeight - bgBottomHeight;
if (_widget == null)
return;
// Get widget's desired width.
float widgetWidth = 0;
float widgetHeight = 0;
if (_widget is ILayout) {
ILayout layout = _widget as ILayout;
widgetWidth = layout.PrefWidth;
widgetHeight = layout.PrefHeight;
}
else {
widgetWidth = _widget.Width;
widgetHeight = _widget.Height;
}
// Determine if horizontal/vertical scrollbars are needed.
IsScrollX = ForceScrollX || (widgetWidth > _areaWidth && !IsDisabledX);
IsScrollY = ForceScrollY || (widgetHeight > _areaHeight && !IsDisabledY);
bool fade = _fadeScrollBars;
if (!fade) {
// Check again, now taking into account the area that's taken up by any enabled scrollbars.
if (IsScrollY) {
_areaWidth -= scrollbarWidth;
if (!IsScrollX && widgetWidth > _areaWidth && !IsDisabledX)
IsScrollX = true;
}
if (IsScrollX) {
_areaHeight -= scrollbarHeight;
if (!IsScrollY && widgetHeight > _areaHeight && !IsDisabledY) {
IsScrollY = true;
_areaWidth -= scrollbarWidth;
}
}
}
// Set the widget area bounds
_widgetAreaBounds = new RectangleF(bgLeftWidth, bgBottomHeight, _areaWidth, _areaHeight);
if (fade) {
// Make sure widget is drawn under fading scrollbars.
if (IsScrollX)
_areaHeight -= scrollbarHeight;
if (IsScrollY)
_areaWidth -= scrollbarWidth;
}
else {
if (ScrollBarsOnTop) {
// Make sure widget is drawn under non-fading scrollbars.
if (IsScrollX)
_widgetAreaBounds.Height += scrollbarHeight;
if (IsScrollY)
_widgetAreaBounds.Width += scrollbarWidth;
}
else {
// Offset widget area y for horizontal scrollbar.
if (IsScrollX)
_widgetAreaBounds.Y += scrollbarHeight;
}
}
// If the widget is smaller than the available space, make it take up the available space.
widgetWidth = IsDisabledX ? width : Math.Max(_areaWidth, widgetWidth);
widgetHeight = IsDisabledY ? height : Math.Max(_areaHeight, widgetHeight);
MaxX = widgetWidth - _areaWidth;
MaxY = widgetHeight - _areaHeight;
if (fade) {
// Make sure widget is drawn under fading scrollbars.
if (IsScrollX)
MaxY -= scrollbarHeight;
if (IsScrollY)
MaxX -= scrollbarWidth;
}
ScrollX = MathHelper.Clamp(ScrollX, 0, MaxX);
ScrollY = MathHelper.Clamp(ScrollY, 0, MaxY);
// Set the bounds and scroll knob sizes if scrollbars are needed.
if (IsScrollX) {
if (hScrollKnob != null) {
float hScrollHeight = _style.HScroll != null ? _style.HScroll.MinHeight : hScrollKnob.MinHeight;
_hScrollBounds = new RectangleF(bgLeftWidth, bgBottomHeight, _areaWidth, hScrollHeight);
_hKnobBounds.Width = Math.Max(hScrollKnob.MinWidth, (int)(_hScrollBounds.Width * _areaWidth / widgetWidth));
_hKnobBounds.Height = hScrollKnob.MinHeight;
_hKnobBounds.X = _hScrollBounds.X + (int)((_hScrollBounds.Width - _hKnobBounds.Width) * ScrollPercentX);
_hKnobBounds.Y = _hScrollBounds.Y;
}
else {
_hScrollBounds = RectangleF.Empty;
_hKnobBounds = RectangleF.Empty;
}
}
if (IsScrollY) {
if (vScrollKnob != null) {
float vScrollWidth = _style.VScroll != null ? _style.VScroll.MinWidth : vScrollKnob.MinWidth;
_vScrollBounds = new RectangleF(width - bgRightWidth - vScrollWidth, height - bgTopHeight - _areaHeight, vScrollWidth, _areaHeight);
_vKnobBounds.Width = vScrollKnob.MinWidth;
_vKnobBounds.Height = Math.Max(vScrollKnob.MinHeight, (int)(_vScrollBounds.Height * _areaHeight / widgetHeight));
_vKnobBounds.X = width - bgRightWidth - vScrollKnob.MinWidth;
_vKnobBounds.Y = _vScrollBounds.Y + (int)((_vScrollBounds.Height - _vKnobBounds.Height) * (1 - ScrollPercentY));
}
else {
_vScrollBounds = RectangleF.Empty;
_vKnobBounds = RectangleF.Empty;
}
}
if (_widget.Width != widgetWidth || _widget.Height != widgetHeight) {
_widget.Width = widgetWidth;
_widget.Height = widgetHeight;
if (_widget is ILayout) {
ILayout layout = _widget as ILayout;
layout.Invalidate();
layout.Validate();
}
}
else {
if (_widget is ILayout)
(_widget as ILayout).Validate();
}
}