spreadsheet example

This commit is contained in:
Vadim Lopatin 2015-11-30 13:40:58 +03:00
parent 768d418eec
commit a7decf99ea
5 changed files with 185 additions and 27 deletions
examples/spreadsheet
src/dlangui/widgets
views/res
src/dlangui/widgets

View File

@ -9,6 +9,8 @@ import dlangui.widgets.tabs;
import dlangui.widgets.editors;
import dlangui.widgets.grid;
import std.algorithm : min;
/// standard style id for Tab with Up alignment
immutable string STYLE_TAB_SHEET_DOWN = "TAB_SHEET_DOWN";
/// standard style id for button of Tab with Up alignment
@ -21,6 +23,7 @@ class SheetTabs : TabControl {
this(string ID = null) {
super(ID, Align.Bottom);
setStyles(STYLE_TAB_SHEET_DOWN, STYLE_TAB_SHEET_DOWN_BUTTON, STYLE_TAB_SHEET_DOWN_BUTTON_TEXT);
_moreButton.visibility = Visibility.Gone;
}
}
@ -38,19 +41,36 @@ class SheetEditControl : HorizontalLayout {
}
}
class SpreadSheetWidget : VerticalLayout {
class SpreadSheetView : StringGridWidget {
this(string ID = null) {
super(ID);
layoutWidth = FILL_PARENT;
layoutHeight = FILL_PARENT;
resize(50, 50);
}
}
class SpreadSheetWidget : WidgetGroupDefaultDrawing {
SheetEditControl _editControl;
StringGridWidget _grid;
SheetTabs _tabs;
ScrollBar _hScroll1;
ScrollBar _hScroll2;
ScrollBar _vScroll1;
ScrollBar _vScroll2;
SpreadSheetView _viewTopLeft;
SpreadSheetView _viewTopRight;
SpreadSheetView _viewBottomLeft;
SpreadSheetView _viewBottomRight;
SpreadSheetView[4] _views;
ScrollBar[4] _scrollbars;
this(string ID = "spreadsheet") {
_editControl = new SheetEditControl();
_editControl.layoutWidth = FILL_PARENT;
_grid = new StringGridWidget("grid");
_grid.layoutWidth = FILL_PARENT;
_grid.layoutHeight = FILL_PARENT;
_grid.resize(50, 50);
_tabs = new SheetTabs();
_tabs.layoutWidth = FILL_PARENT;
_tabs.addTab("Sheet1", "Sheet1"d);
@ -58,10 +78,93 @@ class SpreadSheetWidget : VerticalLayout {
_tabs.addTab("Sheet3", "Sheet3"d);
layoutWidth = FILL_PARENT;
layoutHeight = FILL_PARENT;
backgroundColor = 0xFFE0E0E0;
backgroundColor = 0xdce2e8;
minHeight = 100;
addChild(_editControl);
addChild(_grid);
addChild(_tabs);
_hScroll1 = new ScrollBar("hscroll1", Orientation.Horizontal);
_hScroll2 = new ScrollBar("hscroll2", Orientation.Horizontal);
_vScroll1 = new ScrollBar("vscroll1", Orientation.Vertical);
_vScroll2 = new ScrollBar("vscroll2", Orientation.Vertical);
_scrollbars[0] = _hScroll1;
_scrollbars[1] = _vScroll1;
_scrollbars[2] = _hScroll2;
_scrollbars[3] = _vScroll2;
_viewTopLeft = new SpreadSheetView("sheetViewTopLeft");
_viewTopRight = new SpreadSheetView("sheetViewTopRight");
_viewBottomLeft = new SpreadSheetView("sheetViewBottomLeft");
_viewBottomRight = new SpreadSheetView("sheetViewBottomRight");
_viewTopRight.headerCols = 0;
_viewBottomLeft.headerRows = 0;
_viewBottomRight.headerCols = 0;
_viewBottomRight.headerRows = 0;
_views[0] = _viewTopLeft;
_views[1] = _viewTopRight;
_views[2] = _viewBottomLeft;
_views[3] = _viewBottomRight;
_viewTopLeft.hscrollbar = _hScroll1;
_viewTopLeft.vscrollbar = _vScroll1;
_viewTopRight.hscrollbar = _hScroll2;
_viewTopRight.vscrollbar = _vScroll1;
_viewBottomLeft.hscrollbar = _hScroll1;
_viewBottomLeft.vscrollbar = _vScroll2;
_viewBottomRight.hscrollbar = _hScroll2;
_viewBottomRight.vscrollbar = _vScroll2;
addChildren([_hScroll1, _vScroll1, _hScroll2, _vScroll2,
_viewTopLeft, _viewTopRight, _viewBottomLeft, _viewBottomRight,
_editControl, _tabs
]);
}
/// Measure widget according to desired width and height constraints. (Step 1 of two phase layout).
override void measure(int parentWidth, int parentHeight) {
if (visibility == Visibility.Gone) {
return;
}
_measuredWidth = parentWidth;
_measuredHeight = parentHeight;
foreach(view; _views)
view.measure(parentWidth, parentHeight);
foreach(sb; _scrollbars)
sb.measure(parentWidth, parentHeight);
_editControl.measure(parentWidth, parentHeight);
_tabs.measure(parentWidth, parentHeight);
}
/// 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;
_needLayout = false;
applyMargins(rc);
applyPadding(rc);
int editHeight = _editControl.measuredHeight;
_editControl.layout(Rect(rc.left, rc.top, rc.right, rc.top + editHeight));
rc.top += editHeight;
int splitWidth = 4;
int splitHeight = 4;
int hscrollHeight = _hScroll1.measuredHeight;
int vscrollWidth = _vScroll1.measuredWidth;
int tabsHeight = _tabs.measuredHeight;
int bottomSize = min(hscrollHeight, tabsHeight);
int splitx = (rc.width - vscrollWidth - splitWidth) / 2;
int splity = (rc.height - hscrollHeight - splitHeight) / 2;
_viewTopLeft.layout(Rect(rc.left, rc.top, rc.left + splitx, rc.top + splity));
_viewTopRight.layout(Rect(rc.left + splitx + splitWidth, rc.top, rc.right - vscrollWidth, rc.top + splity));
_viewBottomLeft.layout(Rect(rc.left, rc.top + splity + splitHeight, rc.left + splitx, rc.bottom - bottomSize));
_viewBottomRight.layout(Rect(rc.left + splitx + splitWidth, rc.top + splity + splitHeight, rc.right - vscrollWidth, rc.bottom - bottomSize));
int tabsWidth = splitx / 2;
_tabs.layout(Rect(rc.left, rc.bottom - bottomSize, rc.left + tabsWidth, rc.bottom - bottomSize + tabsHeight));
_hScroll1.layout(Rect(rc.left + tabsWidth + splitWidth, rc.bottom - hscrollHeight, rc.left + splitx, rc.bottom));
_hScroll2.layout(Rect(rc.left + splitx + splitWidth, rc.bottom - hscrollHeight, rc.right - vscrollWidth, rc.bottom));
_vScroll1.layout(Rect(rc.right - vscrollWidth, rc.top, rc.right, rc.top + splity));
_vScroll2.layout(Rect(rc.right - vscrollWidth, rc.top + splity + splitHeight, rc.right, rc.bottom - bottomSize));
}
}

View File

@ -2,9 +2,9 @@
<theme
id="theme_custom"
parent="theme_default"
fontSize="16"
fontSize="12px"
>
<style id="TAB_SHEET_DOWN_BUTTON"
<style id="TAB_SHEET_DOWN"
backgroundImageId="tab_sheet_down_background"
layoutWidth="FILL_PARENT"
>
@ -13,12 +13,12 @@
<style id="TAB_SHEET_DOWN_BUTTON_TEXT"
textColor="#000000"
align="Center"
fontSize="12px"
fontSize="10px"
>
<state state_selected="true" state_focused="true" textColor="#000000"/>
<state state_selected="true" textColor="#000000"/>
<state state_focused="true" textColor="#000000"/>
<state state_hovered="true" textColor="#808000"/>
<state state_hovered="true" textColor="#800000"/>
</style>
<style id="TAB_SHEET_DOWN_BUTTON"
backgroundImageId="tab_sheet_down"

View File

@ -81,7 +81,9 @@ enum ScrollBarMode {
/** always visible */
Visible,
/** automatically show/hide scrollbar depending on content size */
Auto
Auto,
/** Scrollbar is provided by external control outside this widget */
External,
}
/**
@ -149,6 +151,35 @@ class ScrollWidgetBase : WidgetGroup, OnScrollHandler {
}
}
public @property ScrollBar hscrollbar() { return _hscrollbar; }
public @property ScrollBar vscrollbar() { return _vscrollbar; }
public @property void hscrollbar(ScrollBar hscroll) {
if (_hscrollbar) {
removeChild(_hscrollbar);
destroy(_hscrollbar);
_hscrollbar = null;
_hscrollbarMode = ScrollBarMode.Invisible;
}
if (_hscrollbar) {
_hscrollbar = hscroll;
_hscrollbarMode = ScrollBarMode.External;
}
}
public @property void vscrollbar(ScrollBar vscroll) {
if (_vscrollbar) {
removeChild(_vscrollbar);
destroy(_vscrollbar);
_vscrollbar = null;
_vscrollbarMode = ScrollBarMode.Invisible;
}
if (_vscrollbar) {
_vscrollbar = vscroll;
_vscrollbarMode = ScrollBarMode.External;
}
}
/// update horizontal scrollbar widget position
protected void updateHScrollBar() {
// default implementation: use _fullScrollableArea, _visibleScrollableArea: override it if necessary
@ -228,17 +259,17 @@ class ScrollWidgetBase : WidgetGroup, OnScrollHandler {
pwidth -= m.left + m.right + p.left + p.right;
if (parentHeight != SIZE_UNSPECIFIED)
pheight -= m.top + m.bottom + p.top + p.bottom;
if (_hscrollbar) {
if (_hscrollbar && _hscrollbarMode == ScrollBarMode.Visible) {
_hscrollbar.measure(pwidth, pheight);
}
if (_vscrollbar) {
if (_vscrollbar && _vscrollbarMode == ScrollBarMode.Visible) {
_vscrollbar.measure(pwidth, pheight);
}
Point sz = fullContentSize();
if (_hscrollbar) {
if (_hscrollbar && _hscrollbarMode == ScrollBarMode.Visible) {
sz.y += _hscrollbar.measuredHeight;
}
if (_vscrollbar) {
if (_vscrollbar && _vscrollbarMode == ScrollBarMode.Visible) {
sz.x += _vscrollbar.measuredWidth;
}
measuredContent(parentWidth, parentHeight, sz.x, sz.y);
@ -258,8 +289,8 @@ class ScrollWidgetBase : WidgetGroup, OnScrollHandler {
applyMargins(rc);
applyPadding(rc);
Point sz = fullContentSize();
bool needHscroll = _hscrollbarMode != ScrollBarMode.Invisible && sz.x > rc.width;
bool needVscroll = _vscrollbarMode != ScrollBarMode.Invisible && sz.y > rc.height;
bool needHscroll = _hscrollbarMode != ScrollBarMode.External && _hscrollbarMode != ScrollBarMode.Invisible && sz.x > rc.width;
bool needVscroll = _vscrollbarMode != ScrollBarMode.External && _vscrollbarMode != ScrollBarMode.Invisible && sz.y > rc.height;
if (needVscroll && _vscrollbarMode != ScrollBarMode.Invisible)
needHscroll = sz.x > rc.width - _vscrollbar.measuredWidth;
if (needHscroll && _hscrollbarMode != ScrollBarMode.Invisible)

View File

@ -429,9 +429,11 @@ class TabControl : WidgetGroupDefaultDrawing {
pheight -= m.top + m.bottom + p.top + p.bottom;
// measure children
Point sz;
_moreButton.measure(pwidth, pheight);
sz.x = _moreButton.measuredWidth;
sz.y = _moreButton.measuredHeight;
if (_moreButton.visibility == Visibility.Visible) {
_moreButton.measure(pwidth, pheight);
sz.x = _moreButton.measuredWidth;
sz.y = _moreButton.measuredHeight;
}
pwidth -= sz.x;
for (int i = 1; i < _children.count; i++) {
Widget tab = _children.get(i);
@ -458,9 +460,11 @@ class TabControl : WidgetGroupDefaultDrawing {
applyPadding(rc);
// more button
Rect moreRc = rc;
moreRc.left = rc.right - _moreButton.measuredWidth;
_moreButton.layout(moreRc);
rc.right -= _moreButton.measuredWidth;
if (_moreButton.visibility == Visibility.Visible) {
moreRc.left = rc.right - _moreButton.measuredWidth;
_moreButton.layout(moreRc);
rc.right -= _moreButton.measuredWidth;
}
// tabs
int maxw = rc.width;
// measure and update visibility

View File

@ -1419,10 +1419,19 @@ class Widget {
Widget child(int index) { return null; }
/// adds child, returns added item
Widget addChild(Widget item) { assert(false, "addChild: children not suported for this widget type"); }
/// adds child, returns added item
Widget addChildren(Widget[] items) {
foreach(item; items) {
addChild(item);
}
return this;
}
/// removes child, returns removed item
Widget removeChild(int index) { assert(false, "removeChild: children not suported for this widget type"); }
/// removes child by ID, returns removed item
Widget removeChild(string id) { assert(false, "removeChild: children not suported for this widget type"); }
/// removes child, returns removed item
Widget removeChild(Widget child) { assert(false, "removeChild: children not suported for this widget type"); }
/// returns index of widget in child list, -1 if passed widget is not a child of this widget
int childIndex(Widget item) { return -1; }
@ -1639,6 +1648,17 @@ class WidgetGroup : Widget {
res.parent = null;
return res;
}
/// removes child, returns removed item
override Widget removeChild(Widget child) {
Widget res = null;
int index = _children.indexOf(child);
if (index < 0)
return null;
res = _children.remove(index);
if (res !is null)
res.parent = null;
return res;
}
/// returns index of widget in child list, -1 if passed widget is not a child of this widget
override int childIndex(Widget item) { return _children.indexOf(item); }