ListWidget

This commit is contained in:
Vadim Lopatin 2014-03-26 11:40:34 +04:00
parent 6d705c51e2
commit 91764870d9
2 changed files with 89 additions and 32 deletions

View File

@ -324,6 +324,7 @@
<Folder name="widgets">
<File path="src\dlangui\widgets\controls.d" />
<File path="src\dlangui\widgets\layouts.d" />
<File path="src\dlangui\widgets\lists.d" />
<File path="src\dlangui\widgets\styles.d" />
<File path="src\dlangui\widgets\widget.d" />
</Folder>

View File

@ -16,7 +16,7 @@ class ListWidget : WidgetGroup {
/// returns linear layout orientation (Vertical, Horizontal)
@property Orientation orientation() { return _orientation; }
/// sets linear layout orientation
@property LinearLayout orientation(Orientation value) {
@property ListWidget orientation(Orientation value) {
_orientation = value;
_scrollbar.orientation = value;
requestLayout();
@ -24,7 +24,12 @@ class ListWidget : WidgetGroup {
}
protected Rect[] _itemRects;
protected Point[] _itemSizes;
protected bool _needScrollbar;
protected Point _sbsz; // scrollbar size
protected ScrollBar _scrollbar;
protected int _lastMeasureWidth;
protected int _lastMeasureHeight;
protected ListAdapter _adapter;
/// get adapter
@ -59,6 +64,7 @@ class ListWidget : WidgetGroup {
_orientation = orientation;
_scrollbar = new ScrollBar("listscroll", orientation);
_scrollbar.visibility = Visibility.Gone;
addChild(_scrollbar);
}
/// Measure widget according to desired width and height constraints. (Step 1 of two phase layout).
@ -67,6 +73,8 @@ class ListWidget : WidgetGroup {
_measuredWidth = _measuredHeight = 0;
return;
}
if (_itemSizes.length < itemCount)
_itemSizes.length = itemCount;
Rect m = margins;
Rect p = padding;
// calc size constraints for children
@ -76,16 +84,25 @@ class ListWidget : WidgetGroup {
pwidth -= m.left + m.right + p.left + p.right;
if (parentHeight != SIZE_UNSPECIFIED)
pheight -= m.top + m.bottom + p.top + p.bottom;
_scrollbar.visibility = Visibility.Visible;
_scrollbar.measure(pwidth, pheight);
_lastMeasureWidth = pwidth;
_lastMeasureHeight = pheight;
int sbsize = _orientation == Orientation.Vertical ? _scrollbar.measuredWidth : _scrollbar.measuredHeight;
// measure children
Point sz;
Point sbsz;
_sbsz.clear;
for (int i = 0; i < itemCount; i++) {
Widget w = itemWidget(i);
if (w is null || w.visibility == Visibility.Gone)
if (w is null || w.visibility == Visibility.Gone) {
_itemSizes[i].x = _itemSizes[i].y = 0;
continue;
}
w.measure(pwidth, pheight);
_itemSizes[i].x = w.measuredWidth;
_itemSizes[i].y = w.measuredHeight;
if (_orientation == Orientation.Vertical) {
// Vertical
if (sz.x < w.measuredWidth)
@ -99,14 +116,13 @@ class ListWidget : WidgetGroup {
sz.x += w.measuredWidth;
}
}
bool needScrollbar;
if (_orientation == Orientation.Vertical) {
if (pheight != SIZE_UNSPECIFIED && sz.y > pheight) {
// need scrollbar
if (pwidth != SIZE_UNSPECIFIED) {
pwidth -= sbsize;
sbsz.x = sbsize;
needScrollbar = true;
_sbsz.x = sbsize;
_needScrollbar = true;
}
}
} else {
@ -114,12 +130,12 @@ class ListWidget : WidgetGroup {
// need scrollbar
if (pheight != SIZE_UNSPECIFIED) {
pheight -= sbsize;
sbsz.y = sbsize;
needScrollbar = true;
_sbsz.y = sbsize;
_needScrollbar = true;
}
}
}
if (needScrollbar) {
if (_needScrollbar) {
// recalculate with scrollbar
sz.x = sz.y = 0;
for (int i = 0; i < itemCount; i++) {
@ -127,6 +143,8 @@ class ListWidget : WidgetGroup {
if (w is null || w.visibility == Visibility.Gone)
continue;
w.measure(pwidth, pheight);
_itemSizes[i].x = w.measuredWidth;
_itemSizes[i].y = w.measuredHeight;
if (_orientation == Orientation.Vertical) {
// Vertical
if (sz.x < w.measuredWidth)
@ -141,7 +159,7 @@ class ListWidget : WidgetGroup {
}
}
}
measuredContent(parentWidth, parentHeight, sz.x + sbsz.x, sz.y + sbsz.y);
measuredContent(parentWidth, parentHeight, sz.x + _sbsz.x, sz.y + _sbsz.y);
}
/// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout).
@ -150,40 +168,64 @@ class ListWidget : WidgetGroup {
return;
}
_pos = rc;
applyMargins(rc);
applyPadding(rc);
if (_itemRects.length < itemCount)
_itemRects.length = itemCount;
Rect r;
Point sz;
Point sbsz;
int sbsize = _orientation == Orientation.Vertical ? _scrollbar.measuredWidth : _scrollbar.measuredHeight;
r = rc;
for (int i = 0; i < itemCount; i++) {
// measure again if client size has been changed
if (_lastMeasureWidth != rc.width || _lastMeasureHeight != rc.height)
measure(rc.width, rc.height);
Widget w = itemWidget(i);
if (w is null || w.visibility == Visibility.Gone)
// layout scrollbar
if (_needScrollbar) {
_scrollbar.visibility = Visibility.Visible;
Rect sbrect = rc;
if (_orientation == Orientation.Vertical)
sbrect.left = sbrect.right - _sbsz.x;
else
sbrect.top = sbrect.bottom - _sbsz.y;
_scrollbar.layout(sbrect);
rc.right -= _sbsz.x;
rc.bottom -= _sbsz.y;
} else {
_scrollbar.visibility = Visibility.Gone;
}
// calc item rectangles
Rect r;
int p = 0;
for (int i = 0; i < itemCount; i++) {
if (_itemSizes[i].x == 0 && _itemSizes[i].y == 0)
continue;
if (_orientation == Orientation.Vertical) {
w.measure(rc.width, SIZE_UNSPECIFIED);
// Vertical
if (sz.x < w.measuredWidth)
sz.x = w.measuredWidth;
sz.y += w.measuredHeight;
r.bottom =
int w = rc.width;
int h = _itemSizes[i].y;
r.top = p;
r.bottom = p + h;
r.left = 0;
r.right = w;
_itemRects[i] = r;
p += h;
} else {
// Horizontal
w.measure(pwidth, pheight);
if (sz.y < w.measuredHeight)
sz.y = w.measuredHeight;
sz.x += w.measuredWidth;
int h = rc.height;
int w = _itemSizes[i].x;
r.top = 0;
r.bottom = h;
r.left = p;
r.right = p + w;
_itemRects[i] = r;
p += w;
}
}
_needLayout = false;
}
/// Draw widget at its position to buffer
override void onDraw(DrawBuf buf) {
if (visibility != Visibility.Visible)
@ -193,11 +235,25 @@ class ListWidget : WidgetGroup {
applyMargins(rc);
applyPadding(rc);
ClipRectSaver(buf, rc);
for (int i = 0; i < _children.count; i++) {
Widget item = _children.get(i);
if (item.visibility != Visibility.Visible)
continue;
item.onDraw(buf);
// draw scrollbar
if (_needScrollbar)
_scrollbar.onDraw(buf);
Point scrollOffset;
// todo: scrollOffset
// draw items
for (int i = 0; i < itemCount; i++) {
Widget w = itemWidget(i);
if (w is null || w.visibility != Visibility.Visible)
continue;
Rect itemrc = _itemRects[i];
itemrc.left += rc.left - scrollOffset.x;
itemrc.right += rc.left - scrollOffset.x;
itemrc.top += rc.top - scrollOffset.y;
itemrc.bottom += rc.top - scrollOffset.y;
w.measure(itemrc.width, itemrc.height);
w.layout(itemrc);
w.onDraw(buf);
}
}