mirror of https://github.com/buggins/dlangui.git
docks refactoring
This commit is contained in:
parent
7f27b57063
commit
b76b47833a
|
@ -24,17 +24,147 @@ module dlangui.widgets.docks;
|
|||
import dlangui.widgets.layouts;
|
||||
import dlangui.widgets.controls;
|
||||
|
||||
/// dock alignment types
|
||||
enum DockAlignment {
|
||||
/// at left of body
|
||||
Left,
|
||||
/// at right of body
|
||||
Right,
|
||||
/// above body
|
||||
Top,
|
||||
/// below body
|
||||
Bottom
|
||||
}
|
||||
|
||||
|
||||
struct DockSpace {
|
||||
protected Rect _rc;
|
||||
protected Rect _resizerRect;
|
||||
protected Rect _dockRect;
|
||||
protected DockWindow[] _docks;
|
||||
@property DockWindow[] docks() { return _docks; }
|
||||
protected DockHost _host;
|
||||
protected DockAlignment _alignment;
|
||||
@property DockAlignment alignment() { return _alignment; }
|
||||
protected ResizerWidget _resizer;
|
||||
@property ResizerWidget resizer() { return _resizer; }
|
||||
protected int _space;
|
||||
@property int space() { return _space; }
|
||||
protected int _minSpace;
|
||||
protected int _maxSpace;
|
||||
ResizerWidget init(DockHost host, DockAlignment a) {
|
||||
_host = host;
|
||||
_alignment = a;
|
||||
final switch (a) {
|
||||
case DockAlignment.Top:
|
||||
_resizer = new ResizerWidget("top_resizer", Orientation.Vertical);
|
||||
break;
|
||||
case DockAlignment.Bottom:
|
||||
_resizer = new ResizerWidget("bottom_resizer", Orientation.Vertical);
|
||||
break;
|
||||
case DockAlignment.Left:
|
||||
_resizer = new ResizerWidget("left_resizer", Orientation.Horizontal);
|
||||
break;
|
||||
case DockAlignment.Right:
|
||||
_resizer = new ResizerWidget("right_resizer", Orientation.Horizontal);
|
||||
break;
|
||||
}
|
||||
_resizer.visibility = Visibility.Gone;
|
||||
_resizer.resizeListener = &onResize;
|
||||
return _resizer;
|
||||
}
|
||||
/// host to be layed out
|
||||
void beforeLayout(Rect rc, DockWindow[] docks) {
|
||||
_docks = docks;
|
||||
int baseSize;
|
||||
if (_resizer.orientation == Orientation.Vertical)
|
||||
baseSize = rc.height;
|
||||
else
|
||||
baseSize = rc.width;
|
||||
_minSpace = baseSize * 1 / 10;
|
||||
_maxSpace = baseSize * 4 / 10;
|
||||
if (_docks.length) {
|
||||
if (_space < _minSpace) {
|
||||
if (_space == 0)
|
||||
_space = (_minSpace + _maxSpace) / 2;
|
||||
else
|
||||
_space = _minSpace;
|
||||
}
|
||||
if (_space > _maxSpace) {
|
||||
_space = _maxSpace;
|
||||
}
|
||||
_resizer.visibility = Visibility.Visible;
|
||||
} else {
|
||||
_space = 0;
|
||||
_resizer.visibility = Visibility.Gone;
|
||||
}
|
||||
}
|
||||
void layout(Rect rc) {
|
||||
int rsWidth = 3; // resizer width
|
||||
if (_space) {
|
||||
_rc = rc;
|
||||
final switch (_alignment) {
|
||||
case DockAlignment.Top:
|
||||
_resizerRect = Rect(rc.left, rc.bottom - rsWidth, rc.right, rc.bottom + rsWidth);
|
||||
_dockRect = Rect(rc.left, rc.top, rc.right, rc.bottom - rsWidth);
|
||||
break;
|
||||
case DockAlignment.Bottom:
|
||||
_resizerRect = Rect(rc.left, rc.top - rsWidth, rc.right, rc.top + rsWidth);
|
||||
_dockRect = Rect(rc.left, rc.top + rsWidth, rc.right, rc.bottom);
|
||||
break;
|
||||
case DockAlignment.Left:
|
||||
_resizerRect = Rect(rc.right - rsWidth, rc.top, rc.right + rsWidth, rc.bottom);
|
||||
_dockRect = Rect(rc.left, rc.top, rc.right - rsWidth, rc.bottom);
|
||||
break;
|
||||
case DockAlignment.Right:
|
||||
_resizerRect = Rect(rc.left - rsWidth, rc.top, rc.left + rsWidth, rc.bottom);
|
||||
_dockRect = Rect(rc.left + rsWidth, rc.top, rc.right, rc.bottom);
|
||||
break;
|
||||
}
|
||||
// layout resizer
|
||||
_resizer.layout(_resizerRect);
|
||||
// layout docked
|
||||
layoutDocked();
|
||||
} else {
|
||||
_rc = _resizerRect = _dockRect = Rect(0, 0, 0, 0); // empty rect
|
||||
}
|
||||
}
|
||||
protected void onResize(ResizerWidget source, ResizerEventType event, int newPosition) {
|
||||
_host.onResize(source, event, newPosition);
|
||||
}
|
||||
protected void layoutDocked() {
|
||||
Rect rc = _rc; //_dockRect;
|
||||
int len = cast(int)_docks.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
Rect itemRc = rc;
|
||||
if (len > 1) {
|
||||
if (_resizer.orientation == Orientation.Horizontal) {
|
||||
itemRc.top = rc.top + rc.height * i / len;
|
||||
if (i != len - 1)
|
||||
itemRc.bottom = rc.top + rc.height * (i + 1) / len;
|
||||
else
|
||||
itemRc.bottom = rc.bottom;
|
||||
} else {
|
||||
itemRc.left = rc.left + rc.width * i / len;
|
||||
if (i != len - 1)
|
||||
itemRc.right = rc.left + rc.width * (i + 1) / len;
|
||||
else
|
||||
itemRc.right = rc.right;
|
||||
}
|
||||
}
|
||||
_docks[i].layout(itemRc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Layout for docking support - contains body widget and optional docked windows
|
||||
class DockHost : WidgetGroupDefaultDrawing {
|
||||
|
||||
protected int _topSpace;
|
||||
protected int _bottomSpace;
|
||||
protected int _rightSpace;
|
||||
protected int _leftSpace;
|
||||
protected ResizerWidget _topResizer;
|
||||
protected ResizerWidget _bottomResizer;
|
||||
protected ResizerWidget _leftResizer;
|
||||
protected ResizerWidget _rightResizer;
|
||||
|
||||
protected DockSpace _topSpace;
|
||||
protected DockSpace _bottomSpace;
|
||||
protected DockSpace _rightSpace;
|
||||
protected DockSpace _leftSpace;
|
||||
protected Widget _bodyWidget;
|
||||
@property Widget bodyWidget() { return _bodyWidget; }
|
||||
@property void bodyWidget(Widget widget) {
|
||||
|
@ -59,22 +189,10 @@ class DockHost : WidgetGroupDefaultDrawing {
|
|||
this() {
|
||||
super("DOCK_HOST");
|
||||
styleId = STYLE_DOCK_HOST;
|
||||
_topResizer = new ResizerWidget("top_resizer", Orientation.Vertical);
|
||||
_topResizer.visibility = Visibility.Gone;
|
||||
_topResizer.resizeListener = &onResize;
|
||||
_leftResizer = new ResizerWidget("left_resizer", Orientation.Horizontal);
|
||||
_leftResizer.visibility = Visibility.Gone;
|
||||
_leftResizer.resizeListener = &onResize;
|
||||
_rightResizer = new ResizerWidget("right_resizer", Orientation.Horizontal);
|
||||
_rightResizer.visibility = Visibility.Gone;
|
||||
_rightResizer.resizeListener = &onResize;
|
||||
_bottomResizer = new ResizerWidget("bottom_resizer", Orientation.Vertical);
|
||||
_bottomResizer.visibility = Visibility.Gone;
|
||||
_bottomResizer.resizeListener = &onResize;
|
||||
addChild(_topResizer);
|
||||
addChild(_leftResizer);
|
||||
addChild(_rightResizer);
|
||||
addChild(_bottomResizer);
|
||||
addChild(_topSpace.init(this, DockAlignment.Top));
|
||||
addChild(_bottomSpace.init(this, DockAlignment.Bottom));
|
||||
addChild(_leftSpace.init(this, DockAlignment.Left));
|
||||
addChild(_rightSpace.init(this, DockAlignment.Right));
|
||||
}
|
||||
|
||||
protected DockWindow[] getDockedWindowList(DockAlignment alignType) {
|
||||
|
@ -90,29 +208,6 @@ class DockHost : WidgetGroupDefaultDrawing {
|
|||
return list;
|
||||
}
|
||||
|
||||
protected void layoutDocked(DockWindow[] list, Rect rc, Orientation orient) {
|
||||
int len = cast(int)list.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
Rect itemRc = rc;
|
||||
if (len > 1) {
|
||||
if (orient == Orientation.Vertical) {
|
||||
itemRc.top = rc.top + rc.height * i / len;
|
||||
if (i != len - 1)
|
||||
itemRc.bottom = rc.top + rc.height * (i + 1) / len;
|
||||
else
|
||||
itemRc.bottom = rc.bottom;
|
||||
} else {
|
||||
itemRc.left = rc.left + rc.width * i / len;
|
||||
if (i != len - 1)
|
||||
itemRc.right = rc.left + rc.width * (i + 1) / len;
|
||||
else
|
||||
itemRc.right = rc.right;
|
||||
}
|
||||
}
|
||||
list[i].layout(itemRc);
|
||||
}
|
||||
}
|
||||
|
||||
/// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout).
|
||||
override void layout(Rect rc) {
|
||||
_needLayout = false;
|
||||
|
@ -122,46 +217,18 @@ class DockHost : WidgetGroupDefaultDrawing {
|
|||
_pos = rc;
|
||||
applyMargins(rc);
|
||||
applyPadding(rc);
|
||||
DockWindow[] top = getDockedWindowList(DockAlignment.Top);
|
||||
DockWindow[] left = getDockedWindowList(DockAlignment.Left);
|
||||
DockWindow[] right = getDockedWindowList(DockAlignment.Right);
|
||||
DockWindow[] bottom = getDockedWindowList(DockAlignment.Bottom);
|
||||
_topSpace = top.length ? rc.height / 4 : 0;
|
||||
_bottomSpace = bottom.length ? rc.height / 4 : 0;
|
||||
_rightSpace = right.length ? rc.width / 4 : 0;
|
||||
_leftSpace = left.length ? rc.width / 4 : 0;
|
||||
int resizerWidth = 6;
|
||||
if (_topSpace) {
|
||||
_topResizer.visibility = Visibility.Visible;
|
||||
_topResizer.layout(Rect(rc.left + _leftSpace, rc.top + _topSpace - resizerWidth, rc.right - _rightSpace, rc.top + _topSpace));
|
||||
} else {
|
||||
_topResizer.visibility = Visibility.Gone;
|
||||
}
|
||||
if (_bottomSpace) {
|
||||
_bottomResizer.visibility = Visibility.Visible;
|
||||
_bottomResizer.layout(Rect(rc.left + _leftSpace, rc.bottom - _bottomSpace, rc.right - _rightSpace, rc.bottom - _bottomSpace + resizerWidth));
|
||||
} else {
|
||||
_bottomResizer.visibility = Visibility.Gone;
|
||||
}
|
||||
if (_leftSpace) {
|
||||
_leftResizer.visibility = Visibility.Visible;
|
||||
_leftResizer.layout(Rect(rc.left + _leftSpace - resizerWidth, rc.top, rc.left + _leftSpace, rc.bottom));
|
||||
} else {
|
||||
_leftResizer.visibility = Visibility.Gone;
|
||||
}
|
||||
if (_rightSpace) {
|
||||
_rightResizer.visibility = Visibility.Visible;
|
||||
_rightResizer.layout(Rect(rc.right - _rightSpace, rc.top, rc.right - _rightSpace + resizerWidth, rc.bottom));
|
||||
} else {
|
||||
_rightResizer.visibility = Visibility.Gone;
|
||||
}
|
||||
_topSpace.beforeLayout(rc, getDockedWindowList(DockAlignment.Top));
|
||||
_leftSpace.beforeLayout(rc, getDockedWindowList(DockAlignment.Left));
|
||||
_rightSpace.beforeLayout(rc, getDockedWindowList(DockAlignment.Right));
|
||||
_bottomSpace.beforeLayout(rc, getDockedWindowList(DockAlignment.Bottom));
|
||||
_topSpace.layout(Rect(rc.left + _leftSpace.space, rc.top, rc.right - _rightSpace.space, rc.top + _topSpace.space));
|
||||
_bottomSpace.layout(Rect(rc.left + _leftSpace.space, rc.bottom - _bottomSpace.space, rc.right - _rightSpace.space, rc.bottom));
|
||||
_leftSpace.layout(Rect(rc.left, rc.top, rc.left + _leftSpace.space, rc.bottom));
|
||||
_rightSpace.layout(Rect(rc.right - _rightSpace.space, rc.top, rc.right, rc.bottom));
|
||||
if (_bodyWidget)
|
||||
_bodyWidget.layout(Rect(rc.left + _leftSpace, rc.top + _topSpace, rc.right - _rightSpace, rc.bottom - _bottomSpace));
|
||||
layoutDocked(top, Rect(rc.left + _leftSpace, rc.top, rc.right - _rightSpace, rc.top + _topSpace), Orientation.Horizontal);
|
||||
layoutDocked(bottom, Rect(rc.left + _leftSpace, rc.bottom - _bottomSpace, rc.right - _rightSpace, rc.bottom), Orientation.Horizontal);
|
||||
layoutDocked(left, Rect(rc.left, rc.top, rc.left + _leftSpace, rc.bottom), Orientation.Vertical);
|
||||
layoutDocked(right, Rect(rc.right - _rightSpace, rc.top, rc.right, rc.bottom), Orientation.Vertical);
|
||||
_bodyWidget.layout(Rect(rc.left + _leftSpace.space, rc.top + _topSpace.space, rc.right - _rightSpace.space, rc.bottom - _bottomSpace.space));
|
||||
}
|
||||
|
||||
/// 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;
|
||||
|
@ -196,14 +263,6 @@ class DockHost : WidgetGroupDefaultDrawing {
|
|||
}
|
||||
}
|
||||
|
||||
/// dock alignment types
|
||||
enum DockAlignment {
|
||||
Left,
|
||||
Right,
|
||||
Top,
|
||||
Bottom
|
||||
}
|
||||
|
||||
/// docked window
|
||||
class DockWindow : VerticalLayout {
|
||||
|
||||
|
|
Loading…
Reference in New Issue