mirror of https://github.com/buggins/dlangui.git
rework scrollbars auto mode - implement #440
This commit is contained in:
parent
e6f62a0a15
commit
46a8f1029a
|
|
@ -2335,9 +2335,73 @@ class EditBox : EditWidgetBase {
|
||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected bool _extendRightScrollBound = true;
|
||||||
|
/// override to determine if scrollbars are needed or not
|
||||||
|
override protected void checkIfScrollbarsNeeded(ref bool needHScroll, ref bool needVScroll) {
|
||||||
|
needHScroll = _hscrollbar && (_hscrollbarMode == ScrollBarMode.Visible || _hscrollbarMode == ScrollBarMode.Auto);
|
||||||
|
needVScroll = _vscrollbar && (_vscrollbarMode == ScrollBarMode.Visible || _vscrollbarMode == ScrollBarMode.Auto);
|
||||||
|
if (!needHScroll && !needVScroll)
|
||||||
|
return; // not needed
|
||||||
|
if (_hscrollbarMode != ScrollBarMode.Auto && _vscrollbarMode != ScrollBarMode.Auto)
|
||||||
|
return; // no auto scrollbars
|
||||||
|
// either h or v scrollbar is in auto mode
|
||||||
|
|
||||||
|
int hsbHeight = _hscrollbar.measuredHeight;
|
||||||
|
int vsbWidth = _hscrollbar.measuredWidth;
|
||||||
|
|
||||||
|
int visibleLines = _lineHeight > 0 ? (_clientRect.height / _lineHeight) : 1; // fully visible lines
|
||||||
|
if (visibleLines < 1)
|
||||||
|
visibleLines = 1;
|
||||||
|
int visibleLinesWithScrollbar = _lineHeight > 0 ? ((_clientRect.height - hsbHeight) / _lineHeight) : 1; // fully visible lines
|
||||||
|
if (visibleLinesWithScrollbar < 1)
|
||||||
|
visibleLinesWithScrollbar = 1;
|
||||||
|
|
||||||
|
// either h or v scrollbar is in auto mode
|
||||||
|
//Point contentSize = fullContentSize();
|
||||||
|
int contentWidth = _maxLineWidth + (_extendRightScrollBound ? _clientRect.width / 16 : 0);
|
||||||
|
int contentHeight = _content.length;
|
||||||
|
|
||||||
|
int clientWidth = _clientRect.width;
|
||||||
|
int clientHeight = visibleLines;
|
||||||
|
|
||||||
|
int clientWidthWithScrollbar = clientWidth - vsbWidth;
|
||||||
|
int clientHeightWithScrollbar = visibleLinesWithScrollbar;
|
||||||
|
|
||||||
|
if (_hscrollbarMode == ScrollBarMode.Auto && _vscrollbarMode == ScrollBarMode.Auto) {
|
||||||
|
// both scrollbars in auto mode
|
||||||
|
bool xFits = contentWidth <= clientWidth;
|
||||||
|
bool yFits = contentHeight <= clientHeight;
|
||||||
|
if (!xFits && !yFits) {
|
||||||
|
// none fits, need both scrollbars
|
||||||
|
} else if (xFits && yFits) {
|
||||||
|
// everything fits!
|
||||||
|
needHScroll = false;
|
||||||
|
needVScroll = false;
|
||||||
|
} else if (xFits) {
|
||||||
|
// only X fits
|
||||||
|
if (contentWidth <= clientWidthWithScrollbar)
|
||||||
|
needHScroll = false; // disable hscroll
|
||||||
|
} else { // yFits
|
||||||
|
// only Y fits
|
||||||
|
if (contentHeight <= clientHeightWithScrollbar)
|
||||||
|
needVScroll = false; // disable vscroll
|
||||||
|
}
|
||||||
|
} else if (_hscrollbarMode == ScrollBarMode.Auto) {
|
||||||
|
// only hscroll is in auto mode
|
||||||
|
if (needVScroll)
|
||||||
|
clientWidth = clientWidthWithScrollbar;
|
||||||
|
needHScroll = contentWidth > clientWidth;
|
||||||
|
} else {
|
||||||
|
// only vscroll is in auto mode
|
||||||
|
if (needHScroll)
|
||||||
|
clientHeight = clientHeightWithScrollbar;
|
||||||
|
needVScroll = contentHeight > clientHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// update horizontal scrollbar widget position
|
/// update horizontal scrollbar widget position
|
||||||
override protected void updateHScrollBar() {
|
override protected void updateHScrollBar() {
|
||||||
_hscrollbar.setRange(0, _maxLineWidth + _clientRect.width / 4);
|
_hscrollbar.setRange(0, _maxLineWidth + (_extendRightScrollBound ? _clientRect.width / 16 : 0));
|
||||||
_hscrollbar.pageSize = _clientRect.width;
|
_hscrollbar.pageSize = _clientRect.width;
|
||||||
_hscrollbar.position = _scrollPos.x;
|
_hscrollbar.position = _scrollPos.x;
|
||||||
}
|
}
|
||||||
|
|
@ -2347,7 +2411,7 @@ class EditBox : EditWidgetBase {
|
||||||
int visibleLines = _lineHeight ? _clientRect.height / _lineHeight : 1; // fully visible lines
|
int visibleLines = _lineHeight ? _clientRect.height / _lineHeight : 1; // fully visible lines
|
||||||
if (visibleLines < 1)
|
if (visibleLines < 1)
|
||||||
visibleLines = 1;
|
visibleLines = 1;
|
||||||
_vscrollbar.setRange(0, _content.length - 1);
|
_vscrollbar.setRange(0, _content.length);
|
||||||
_vscrollbar.pageSize = visibleLines;
|
_vscrollbar.pageSize = visibleLines;
|
||||||
_vscrollbar.position = _firstVisibleLine;
|
_vscrollbar.position = _firstVisibleLine;
|
||||||
}
|
}
|
||||||
|
|
@ -2743,9 +2807,9 @@ class EditBox : EditWidgetBase {
|
||||||
/// calculate full content size in pixels
|
/// calculate full content size in pixels
|
||||||
override Point fullContentSize() {
|
override Point fullContentSize() {
|
||||||
Point textSz = measureVisibleText();
|
Point textSz = measureVisibleText();
|
||||||
int maxy = _lineHeight * 5; // limit measured height
|
//int maxy = _lineHeight * 5; // limit measured height
|
||||||
if (textSz.y > maxy)
|
//if (textSz.y > maxy)
|
||||||
textSz.y = maxy;
|
// textSz.y = maxy;
|
||||||
return textSz;
|
return textSz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,27 @@ class ScrollWidgetBase : WidgetGroup, OnScrollHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected bool _insideChangeScrollbarVisibility;
|
||||||
|
protected void checkIfNeededToChangeScrollbarVisibility() {
|
||||||
|
if (_insideChangeScrollbarVisibility)
|
||||||
|
return;
|
||||||
|
bool needHScroll = false;
|
||||||
|
bool needVScroll = false;
|
||||||
|
checkIfScrollbarsNeeded(needHScroll, needVScroll);
|
||||||
|
bool hscrollVisible = _hscrollbar && _hscrollbar.visibility == Visibility.Visible;
|
||||||
|
bool vscrollVisible = _vscrollbar && _vscrollbar.visibility == Visibility.Visible;
|
||||||
|
bool needChange = false;
|
||||||
|
if (_hscrollbar && hscrollVisible != needHScroll)
|
||||||
|
needChange = true;
|
||||||
|
if (_vscrollbar && vscrollVisible != needVScroll)
|
||||||
|
needChange = true;
|
||||||
|
if (needChange) {
|
||||||
|
_insideChangeScrollbarVisibility = true;
|
||||||
|
layout(_pos);
|
||||||
|
_insideChangeScrollbarVisibility = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// update scrollbar positions
|
/// update scrollbar positions
|
||||||
protected void updateScrollBars() {
|
protected void updateScrollBars() {
|
||||||
if (_hscrollbar) {
|
if (_hscrollbar) {
|
||||||
|
|
@ -177,6 +198,7 @@ class ScrollWidgetBase : WidgetGroup, OnScrollHandler {
|
||||||
if (_vscrollbar) {
|
if (_vscrollbar) {
|
||||||
updateVScrollBar();
|
updateVScrollBar();
|
||||||
}
|
}
|
||||||
|
checkIfNeededToChangeScrollbarVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @property ScrollBar hscrollbar() { return _hscrollbar; }
|
public @property ScrollBar hscrollbar() { return _hscrollbar; }
|
||||||
|
|
@ -306,12 +328,18 @@ class ScrollWidgetBase : WidgetGroup, OnScrollHandler {
|
||||||
int vsbw = 0;
|
int vsbw = 0;
|
||||||
int hsbh = 0;
|
int hsbh = 0;
|
||||||
if (_hscrollbar && (_hscrollbarMode == ScrollBarMode.Visible || _hscrollbarMode == ScrollBarMode.Auto)) {
|
if (_hscrollbar && (_hscrollbarMode == ScrollBarMode.Visible || _hscrollbarMode == ScrollBarMode.Auto)) {
|
||||||
|
Visibility oldVisibility = _hscrollbar.visibility;
|
||||||
|
_hscrollbar.visibility = Visibility.Visible;
|
||||||
_hscrollbar.measure(pwidth, pheight);
|
_hscrollbar.measure(pwidth, pheight);
|
||||||
hsbh = _hscrollbar.measuredHeight;
|
hsbh = _hscrollbar.measuredHeight;
|
||||||
|
_hscrollbar.visibility = oldVisibility;
|
||||||
}
|
}
|
||||||
if (_vscrollbar && (_vscrollbarMode == ScrollBarMode.Visible || _vscrollbarMode == ScrollBarMode.Auto)) {
|
if (_vscrollbar && (_vscrollbarMode == ScrollBarMode.Visible || _vscrollbarMode == ScrollBarMode.Auto)) {
|
||||||
|
Visibility oldVisibility = _vscrollbar.visibility;
|
||||||
|
_vscrollbar.visibility = Visibility.Visible;
|
||||||
_vscrollbar.measure(pwidth, pheight);
|
_vscrollbar.measure(pwidth, pheight);
|
||||||
vsbw = _vscrollbar.measuredWidth;
|
vsbw = _vscrollbar.measuredWidth;
|
||||||
|
_vscrollbar.visibility = oldVisibility;
|
||||||
}
|
}
|
||||||
Point sz = minimumVisibleContentSize();
|
Point sz = minimumVisibleContentSize();
|
||||||
|
|
||||||
|
|
@ -329,6 +357,59 @@ class ScrollWidgetBase : WidgetGroup, OnScrollHandler {
|
||||||
protected void handleClientRectLayout(ref Rect rc) {
|
protected void handleClientRectLayout(ref Rect rc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// override to determine if scrollbars are needed or not
|
||||||
|
protected void checkIfScrollbarsNeeded(ref bool needHScroll, ref bool needVScroll) {
|
||||||
|
needHScroll = _hscrollbar && (_hscrollbarMode == ScrollBarMode.Visible || _hscrollbarMode == ScrollBarMode.Auto);
|
||||||
|
needVScroll = _vscrollbar && (_vscrollbarMode == ScrollBarMode.Visible || _vscrollbarMode == ScrollBarMode.Auto);
|
||||||
|
if (!needHScroll && !needVScroll)
|
||||||
|
return; // not needed
|
||||||
|
if (_hscrollbarMode != ScrollBarMode.Auto && _vscrollbarMode != ScrollBarMode.Auto)
|
||||||
|
return; // no auto scrollbars
|
||||||
|
// either h or v scrollbar is in auto mode
|
||||||
|
Point contentSize = fullContentSize();
|
||||||
|
int contentWidth = contentSize.x;
|
||||||
|
int contentHeight = contentSize.y;
|
||||||
|
int clientWidth = _clientRect.width;
|
||||||
|
int clientHeight = _clientRect.height;
|
||||||
|
|
||||||
|
int hsbHeight = _hscrollbar.measuredHeight;
|
||||||
|
int vsbWidth = _hscrollbar.measuredWidth;
|
||||||
|
|
||||||
|
int clientWidthWithScrollbar = clientWidth - vsbWidth;
|
||||||
|
int clientHeightWithScrollbar = clientHeight - hsbHeight;
|
||||||
|
|
||||||
|
if (_hscrollbarMode == ScrollBarMode.Auto && _vscrollbarMode == ScrollBarMode.Auto) {
|
||||||
|
// both scrollbars in auto mode
|
||||||
|
bool xFits = contentWidth <= clientWidth;
|
||||||
|
bool yFits = contentHeight <= clientHeight;
|
||||||
|
if (!xFits && !yFits) {
|
||||||
|
// none fits, need both scrollbars
|
||||||
|
} else if (xFits && yFits) {
|
||||||
|
// everything fits!
|
||||||
|
needHScroll = false;
|
||||||
|
needVScroll = false;
|
||||||
|
} else if (xFits) {
|
||||||
|
// only X fits
|
||||||
|
if (contentWidth <= clientWidthWithScrollbar)
|
||||||
|
needHScroll = false; // disable hscroll
|
||||||
|
} else { // yFits
|
||||||
|
// only Y fits
|
||||||
|
if (contentHeight <= clientHeightWithScrollbar)
|
||||||
|
needVScroll = false; // disable vscroll
|
||||||
|
}
|
||||||
|
} else if (_hscrollbarMode == ScrollBarMode.Auto) {
|
||||||
|
// only hscroll is in auto mode
|
||||||
|
if (needVScroll)
|
||||||
|
clientWidth = clientWidthWithScrollbar;
|
||||||
|
needHScroll = contentWidth > clientWidth;
|
||||||
|
} else {
|
||||||
|
// only vscroll is in auto mode
|
||||||
|
if (needHScroll)
|
||||||
|
clientHeight = clientHeightWithScrollbar;
|
||||||
|
needVScroll = contentHeight > clientHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout).
|
/// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout).
|
||||||
override void layout(Rect rc) {
|
override void layout(Rect rc) {
|
||||||
if (visibility == Visibility.Gone) {
|
if (visibility == Visibility.Gone) {
|
||||||
|
|
@ -338,17 +419,16 @@ class ScrollWidgetBase : WidgetGroup, OnScrollHandler {
|
||||||
_needLayout = false;
|
_needLayout = false;
|
||||||
applyMargins(rc);
|
applyMargins(rc);
|
||||||
applyPadding(rc);
|
applyPadding(rc);
|
||||||
Point sz = fullContentSize();
|
|
||||||
bool needHscroll = _hscrollbarMode != ScrollBarMode.External && _hscrollbarMode != ScrollBarMode.Invisible && sz.x > rc.width;
|
// client area - initial setup w/o scrollbars
|
||||||
bool needVscroll = _vscrollbarMode != ScrollBarMode.External && _vscrollbarMode != ScrollBarMode.Invisible && sz.y > rc.height;
|
_clientRect = rc;
|
||||||
if (needVscroll && _vscrollbarMode != ScrollBarMode.Invisible)
|
handleClientRectLayout(_clientRect);
|
||||||
needHscroll = sz.x > rc.width - _vscrollbar.measuredWidth;
|
|
||||||
if (needHscroll && _hscrollbarMode != ScrollBarMode.Invisible)
|
bool needHscroll;
|
||||||
needVscroll = sz.y > rc.height - _hscrollbar.measuredHeight;
|
bool needVscroll;
|
||||||
if (needVscroll && _vscrollbarMode != ScrollBarMode.Invisible)
|
|
||||||
needHscroll = sz.x > rc.width - _vscrollbar.measuredWidth;
|
checkIfScrollbarsNeeded(needHscroll, needVscroll);
|
||||||
needVscroll = needVscroll || (_vscrollbarMode == ScrollBarMode.Visible);
|
|
||||||
needHscroll = needHscroll || (_hscrollbarMode == ScrollBarMode.Visible);
|
|
||||||
// scrollbars
|
// scrollbars
|
||||||
Rect vsbrc = rc;
|
Rect vsbrc = rc;
|
||||||
vsbrc.left = vsbrc.right - (needVscroll ? _vscrollbar.measuredWidth : 0);
|
vsbrc.left = vsbrc.right - (needVscroll ? _vscrollbar.measuredWidth : 0);
|
||||||
|
|
@ -364,13 +444,13 @@ class ScrollWidgetBase : WidgetGroup, OnScrollHandler {
|
||||||
_hscrollbar.visibility = needHscroll ? Visibility.Visible : Visibility.Gone;
|
_hscrollbar.visibility = needHscroll ? Visibility.Visible : Visibility.Gone;
|
||||||
_hscrollbar.layout(hsbrc);
|
_hscrollbar.layout(hsbrc);
|
||||||
}
|
}
|
||||||
// client area
|
|
||||||
_clientRect = rc;
|
_clientRect = rc;
|
||||||
handleClientRectLayout(_clientRect);
|
|
||||||
if (needVscroll)
|
if (needVscroll)
|
||||||
_clientRect.right = vsbrc.left;
|
_clientRect.right = vsbrc.left;
|
||||||
if (needHscroll)
|
if (needHscroll)
|
||||||
_clientRect.bottom = hsbrc.top;
|
_clientRect.bottom = hsbrc.top;
|
||||||
|
handleClientRectLayout(_clientRect);
|
||||||
updateScrollBars();
|
updateScrollBars();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -282,6 +282,11 @@ class ScrollBar : AbstractSlider, OnClickHandler {
|
||||||
return sendScrollEvent(ScrollAction.SliderMoved, currentPosition);
|
return sendScrollEvent(ScrollAction.SliderMoved, currentPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// true if full scroll range is visible, and no need of scrolling at all
|
||||||
|
@property bool fullRangeVisible() {
|
||||||
|
return _pageSize >= _maxValue - _minValue;
|
||||||
|
}
|
||||||
|
|
||||||
private bool calcButtonSizes(int availableSize, ref int spaceBackSize, ref int spaceForwardSize, ref int indicatorSize) {
|
private bool calcButtonSizes(int availableSize, ref int spaceBackSize, ref int spaceForwardSize, ref int indicatorSize) {
|
||||||
int dv = _maxValue - _minValue;
|
int dv = _maxValue - _minValue;
|
||||||
if (_pageSize >= dv) {
|
if (_pageSize >= dv) {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ enum DEFAULT_SOURCE_EDIT_FONT_FACES = "Menlo,Consolas,DejaVuSansMono,DejaVu Sans
|
||||||
class SourceEdit : EditBox {
|
class SourceEdit : EditBox {
|
||||||
this(string ID) {
|
this(string ID) {
|
||||||
super(ID);
|
super(ID);
|
||||||
|
_extendRightScrollBound = true;
|
||||||
fontFace = DEFAULT_SOURCE_EDIT_FONT_FACES;
|
fontFace = DEFAULT_SOURCE_EDIT_FONT_FACES;
|
||||||
//fontFace = "Consolas,Lucida Console,Courier New";
|
//fontFace = "Consolas,Lucida Console,Courier New";
|
||||||
fontFamily = FontFamily.MonoSpace;
|
fontFamily = FontFamily.MonoSpace;
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
v0.9.134
|
v0.9.136
|
||||||
Loading…
Reference in New Issue