mirror of https://github.com/buggins/dlangui.git
Linear layout - in progress
This commit is contained in:
parent
f13757042e
commit
03eb2c7b65
|
@ -272,6 +272,7 @@
|
||||||
</Folder>
|
</Folder>
|
||||||
<Folder name="widgets">
|
<Folder name="widgets">
|
||||||
<File path="src\dlangui\widgets\controls.d" />
|
<File path="src\dlangui\widgets\controls.d" />
|
||||||
|
<File path="src\dlangui\widgets\layouts.d" />
|
||||||
<File path="src\dlangui\widgets\styles.d" />
|
<File path="src\dlangui\widgets\styles.d" />
|
||||||
<File path="src\dlangui\widgets\widget.d" />
|
<File path="src\dlangui\widgets\widget.d" />
|
||||||
</Folder>
|
</Folder>
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
module dlangui.all;
|
||||||
|
|
||||||
|
public import dlangui.platforms.common.platform;
|
||||||
|
public import dlangui.graphics.images;
|
||||||
|
public import dlangui.widgets.widget;
|
||||||
|
public import dlangui.widgets.controls;
|
||||||
|
public import dlangui.core.logger;
|
||||||
|
public import dlangui.graphics.fonts;
|
|
@ -0,0 +1,164 @@
|
||||||
|
module dlangui.widgets.layouts;
|
||||||
|
|
||||||
|
import dlangui.widgets.widget;
|
||||||
|
|
||||||
|
enum Orientation : ubyte {
|
||||||
|
Vertical,
|
||||||
|
Horizontal
|
||||||
|
}
|
||||||
|
|
||||||
|
class LinearLayout : WidgetGroup {
|
||||||
|
protected Orientation _orientation = Orientation.Vertical;
|
||||||
|
/// returns linear layout orientation (Vertical, Horizontal)
|
||||||
|
@property Orientation orientation() { return _orientation; }
|
||||||
|
/// sets linear layout orientation
|
||||||
|
@property LinearLayout orientation(Orientation value) { _orientation = value; requestLayout(); return this; }
|
||||||
|
|
||||||
|
/// Measure widget according to desired width and height constraints. (Step 1 of two phase layout).
|
||||||
|
override void measure(int parentWidth, int parentHeight) {
|
||||||
|
Rect m = margins;
|
||||||
|
Rect p = padding;
|
||||||
|
// calc size constraints for children
|
||||||
|
int pwidth = parentWidth;
|
||||||
|
int pheight = parentHeight;
|
||||||
|
if (parentWidth != SIZE_UNSPECIFIED)
|
||||||
|
pwidth -= m.left + m.right + p.left + p.right;
|
||||||
|
if (parentHeight != SIZE_UNSPECIFIED)
|
||||||
|
pheight -= m.top + m.bottom + p.top + p.bottom;
|
||||||
|
// measure children
|
||||||
|
int contentWidth = 0;
|
||||||
|
int contentHeight = 0;
|
||||||
|
if (orientation == Orientation.Vertical) {
|
||||||
|
// Vertical
|
||||||
|
int max = 0;
|
||||||
|
int total = 0;
|
||||||
|
for (int i = 0; i < _children.count; i++) {
|
||||||
|
Widget item = _children.get(i);
|
||||||
|
if (item.visibility == Visibility.Gone)
|
||||||
|
continue;
|
||||||
|
item.measure(pwidth, pheight);
|
||||||
|
if (max < item.measuredWidth)
|
||||||
|
max = item.measuredWidth;
|
||||||
|
total += item.measuredHeight;
|
||||||
|
}
|
||||||
|
contentWidth = max;
|
||||||
|
contentHeight = total;
|
||||||
|
} else {
|
||||||
|
// Horizontal
|
||||||
|
int max = 0;
|
||||||
|
int total = 0;
|
||||||
|
for (int i = 0; i < _children.count; i++) {
|
||||||
|
Widget item = _children.get(i);
|
||||||
|
if (item.visibility == Visibility.Gone)
|
||||||
|
continue;
|
||||||
|
item.measure(pwidth, pheight);
|
||||||
|
if (max < item.measuredHeight)
|
||||||
|
max = item.measuredHeight;
|
||||||
|
total += item.measuredWidth;
|
||||||
|
}
|
||||||
|
contentWidth = total;
|
||||||
|
contentHeight = max;
|
||||||
|
}
|
||||||
|
measuredContent(parentWidth, parentHeight, contentWidth, contentHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout).
|
||||||
|
override void layout(Rect rc) {
|
||||||
|
if (visibility == Visibility.Gone) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_pos = rc;
|
||||||
|
applyMargins(rc);
|
||||||
|
applyPadding(rc);
|
||||||
|
int contentWidth = 0;
|
||||||
|
int contentHeight = 0;
|
||||||
|
if (orientation == Orientation.Vertical) {
|
||||||
|
// Vertical
|
||||||
|
int position = 0;
|
||||||
|
int totalSize = 0;
|
||||||
|
int delta = 0;
|
||||||
|
int resizableSize = 0;
|
||||||
|
int resizableWeight = 0;
|
||||||
|
int nonresizableSize = 0;
|
||||||
|
int nonresizableWeight = 0;
|
||||||
|
int maxItem = 0; // max item dimention
|
||||||
|
// calc total size
|
||||||
|
int visibleCount = 0;
|
||||||
|
for (int i = 0; i < _children.count; i++) {
|
||||||
|
Widget item = _children.get(i);
|
||||||
|
if (item.visibility == Visibility.Gone)
|
||||||
|
continue;
|
||||||
|
visibleCount++;
|
||||||
|
totalSize += item.measuredHeight;
|
||||||
|
if (maxItem < item.measuredWidth)
|
||||||
|
maxItem = item.measuredWidth;
|
||||||
|
int weight = item.layoutWeight;
|
||||||
|
if (item.layoutHeight == FILL_PARENT) {
|
||||||
|
resizableWeight += weight;
|
||||||
|
resizableSize += item.measuredHeight;
|
||||||
|
} else {
|
||||||
|
nonresizableWeight += weight;
|
||||||
|
nonresizableSize += item.measuredHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (layoutWidth == WRAP_CONTENT && maxItem < rc.width)
|
||||||
|
contentWidth = maxItem;
|
||||||
|
else
|
||||||
|
contentWidth = rc.width;
|
||||||
|
if (layoutHeight == FILL_PARENT || totalSize > rc.height)
|
||||||
|
delta = rc.height - totalSize; // total space to add to fit
|
||||||
|
bool needForceResize = false;
|
||||||
|
bool needResize = false;
|
||||||
|
int scaleFactor = 10000; // per weight unit
|
||||||
|
if (delta != 0 && visibleCount > 0) {
|
||||||
|
// need resize of some children
|
||||||
|
needResize = true;
|
||||||
|
needForceResize = delta < 0 || resizableSize < delta; // do we need resize non-FILL_PARENT items?
|
||||||
|
if (needForceResize)
|
||||||
|
scaleFactor = 10000 * rc.height / (resizableSize + nonresizableSize) / (nonresizableWeight + resizableWeight);
|
||||||
|
else
|
||||||
|
scaleFactor = 10000 * rc.height / (rc.height - delta) / resizableWeight;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < _children.count; i++) {
|
||||||
|
Widget item = _children.get(i);
|
||||||
|
if (item.visibility == Visibility.Gone)
|
||||||
|
continue;
|
||||||
|
int weight = item.layoutWeight;
|
||||||
|
if (item.layoutHeight == FILL_PARENT) {
|
||||||
|
resizableWeight += weight;
|
||||||
|
resizableSize += item.measuredHeight;
|
||||||
|
} else {
|
||||||
|
nonresizableWeight += weight;
|
||||||
|
nonresizableSize += item.measuredHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < _children.count; i++) {
|
||||||
|
Widget item = _children.get(i);
|
||||||
|
if (item.visibility == Visibility.Gone)
|
||||||
|
continue;
|
||||||
|
int layoutSize = item.layoutHeight;
|
||||||
|
totalWeight += item.measuredHeight;
|
||||||
|
int weight = item.layoutWeight;
|
||||||
|
if (layoutSize) {
|
||||||
|
resizableWeight += weight;
|
||||||
|
resizableSize += item.measuredHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Horizontal
|
||||||
|
}
|
||||||
|
_needLayout = false;
|
||||||
|
}
|
||||||
|
/// Draw widget at its position to buffer
|
||||||
|
override void onDraw(DrawBuf buf) {
|
||||||
|
if (visibility != Visibility.Visible)
|
||||||
|
return;
|
||||||
|
super.onDraw(buf);
|
||||||
|
Rect rc = _pos;
|
||||||
|
applyMargins(rc);
|
||||||
|
applyPadding(rc);
|
||||||
|
// TODO
|
||||||
|
_needDraw = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -194,11 +194,6 @@ class Widget {
|
||||||
_needDraw = true;
|
_needDraw = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Measure widget according to desired width and height constraints. (Step 1 of two phase layout).
|
|
||||||
void measure(int parentWidth, int parentHeight) {
|
|
||||||
measuredContent(parentWidth, parentHeight, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// helper function for implement measure() when widget's content dimensions are known
|
/// helper function for implement measure() when widget's content dimensions are known
|
||||||
protected void measuredContent(int parentWidth, int parentHeight, int contentWidth, int contentHeight) {
|
protected void measuredContent(int parentWidth, int parentHeight, int contentWidth, int contentHeight) {
|
||||||
if (visibility == Visibility.Gone) {
|
if (visibility == Visibility.Gone) {
|
||||||
|
@ -232,6 +227,11 @@ class Widget {
|
||||||
_measuredHeight = dy;
|
_measuredHeight = dy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Measure widget according to desired width and height constraints. (Step 1 of two phase layout).
|
||||||
|
void measure(int parentWidth, int parentHeight) {
|
||||||
|
measuredContent(parentWidth, parentHeight, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/// 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).
|
||||||
void layout(Rect rc) {
|
void layout(Rect rc) {
|
||||||
if (visibility == Visibility.Gone) {
|
if (visibility == Visibility.Gone) {
|
||||||
|
@ -240,7 +240,19 @@ class Widget {
|
||||||
_pos = rc;
|
_pos = rc;
|
||||||
_needLayout = false;
|
_needLayout = false;
|
||||||
}
|
}
|
||||||
/// applies margins to rectangle
|
/// Draw widget at its position to buffer
|
||||||
|
void onDraw(DrawBuf buf) {
|
||||||
|
if (visibility != Visibility.Visible)
|
||||||
|
return;
|
||||||
|
Rect rc = _pos;
|
||||||
|
applyMargins(rc);
|
||||||
|
DrawableRef bg = style.backgroundDrawable;
|
||||||
|
bg.drawTo(buf, rc);
|
||||||
|
applyPadding(rc);
|
||||||
|
_needDraw = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper function: applies margins to rectangle
|
||||||
void applyMargins(ref Rect rc) {
|
void applyMargins(ref Rect rc) {
|
||||||
Rect m = margins;
|
Rect m = margins;
|
||||||
rc.left += m.left;
|
rc.left += m.left;
|
||||||
|
@ -248,7 +260,7 @@ class Widget {
|
||||||
rc.bottom -= m.bottom;
|
rc.bottom -= m.bottom;
|
||||||
rc.right -= m.right;
|
rc.right -= m.right;
|
||||||
}
|
}
|
||||||
/// applies padding to rectangle
|
/// Helper function: applies padding to rectangle
|
||||||
void applyPadding(ref Rect rc) {
|
void applyPadding(ref Rect rc) {
|
||||||
Rect m = padding;
|
Rect m = padding;
|
||||||
rc.left += m.left;
|
rc.left += m.left;
|
||||||
|
@ -256,18 +268,6 @@ class Widget {
|
||||||
rc.bottom -= m.bottom;
|
rc.bottom -= m.bottom;
|
||||||
rc.right -= m.right;
|
rc.right -= m.right;
|
||||||
}
|
}
|
||||||
/// Draw widget at its position to buffer
|
|
||||||
void onDraw(DrawBuf buf) {
|
|
||||||
if (visibility != Visibility.Visible)
|
|
||||||
return;
|
|
||||||
Rect rc = _pos;
|
|
||||||
applyMargins(rc);
|
|
||||||
buf.fillRect(_pos, backgroundColor);
|
|
||||||
DrawableRef bg = style.backgroundDrawable;
|
|
||||||
bg.drawTo(buf, rc);
|
|
||||||
applyPadding(rc);
|
|
||||||
_needDraw = false;
|
|
||||||
}
|
|
||||||
/// Applies alignment for content of size sz - set rectangle rc to aligned value of content inside of initial value of rc.
|
/// Applies alignment for content of size sz - set rectangle rc to aligned value of content inside of initial value of rc.
|
||||||
void applyAlign(ref Rect rc, Point sz) {
|
void applyAlign(ref Rect rc, Point sz) {
|
||||||
Align va = valign;
|
Align va = valign;
|
||||||
|
|
Loading…
Reference in New Issue