grids: row select support

This commit is contained in:
Vadim Lopatin 2014-06-09 13:26:19 +04:00
parent 0103bb8a3d
commit e7b40dc6e0
2 changed files with 135 additions and 31 deletions

View File

@ -520,6 +520,7 @@ extern (C) int UIAppMain(string[] args) {
grid.resize(30, 50); grid.resize(30, 50);
grid.fixedCols = 3; grid.fixedCols = 3;
grid.fixedRows = 2; grid.fixedRows = 2;
grid.rowSelect = true;
grid.selectCell(4, 6, false); grid.selectCell(4, 6, false);
// create sample grid content // create sample grid content
for (int y = 1; y < grid.rows; y++) { for (int y = 1; y < grid.rows; y++) {

View File

@ -158,6 +158,10 @@ class GridWidgetBase : WidgetGroup, OnScrollHandler {
protected int[] _colWidths; protected int[] _colWidths;
/// row heights /// row heights
protected int[] _rowHeights; protected int[] _rowHeights;
/// when true, shows col headers row
protected bool _showColHeaders;
/// when true, shows row headers column
protected bool _showRowHeaders;
/// number of header rows (e.g. like col name A, B, C... in excel; 0 for no header row) /// number of header rows (e.g. like col name A, B, C... in excel; 0 for no header row)
protected int _headerRows; protected int _headerRows;
/// number of header columns (e.g. like row number in excel; 0 for no header column) /// number of header columns (e.g. like row number in excel; 0 for no header column)
@ -180,7 +184,8 @@ class GridWidgetBase : WidgetGroup, OnScrollHandler {
protected ScrollBar _hscrollbar; protected ScrollBar _hscrollbar;
/// inner area, excluding additional controls like scrollbars /// inner area, excluding additional controls like scrollbars
protected Rect _clientRect; protected Rect _clientRect;
/// when true, allows to select only whole row
protected bool _rowSelect;
// properties // properties
@ -196,6 +201,7 @@ class GridWidgetBase : WidgetGroup, OnScrollHandler {
@property int rows() { return _rows; } @property int rows() { return _rows; }
/// set row count /// set row count
@property GridWidgetBase rows(int r) { resize(_cols, r); return this; } @property GridWidgetBase rows(int r) { resize(_cols, r); return this; }
/// fixed (non-scrollable) data column count /// fixed (non-scrollable) data column count
@property int fixedCols() { return _fixedCols; } @property int fixedCols() { return _fixedCols; }
@property GridWidgetBase fixedCols(int c) { _fixedCols = c; invalidate(); return this; } @property GridWidgetBase fixedCols(int c) { _fixedCols = c; invalidate(); return this; }
@ -203,23 +209,58 @@ class GridWidgetBase : WidgetGroup, OnScrollHandler {
@property int fixedRows() { return _fixedRows; } @property int fixedRows() { return _fixedRows; }
@property GridWidgetBase fixedRows(int r) { _fixedRows = r; invalidate(); return this; } @property GridWidgetBase fixedRows(int r) { _fixedRows = r; invalidate(); return this; }
/// row header column count
@property int headerCols() { return _headerCols; }
@property GridWidgetBase headerCols(int c) {
_headerCols = c;
invalidate();
return this;
}
/// col header row count
@property int headerRows() { return _headerRows; }
@property GridWidgetBase headerRows(int r) {
_headerRows = r;
invalidate();
return this;
}
/// flag to enable column headers
@property bool showColHeaders() { /// when true, allows only select the whole row
return _headerRows > 0; @property bool rowSelect() {
return _rowSelect;
} }
@property GridWidgetBase showColHeaders(bool show) { @property GridWidgetBase rowSelect(bool flg) {
_headerRows = show ? 1 : 0; _rowSelect = flg;
invalidate(); invalidate();
return this; return this;
} }
/// flag to enable column headers
@property bool showColHeaders() {
return _showColHeaders;
}
@property GridWidgetBase showColHeaders(bool show) {
if (_showColHeaders != show) {
_showColHeaders = show;
for (int i = 0; i < _headerRows; i++)
autoFitRowHeight(i);
invalidate();
}
return this;
}
/// flag to enable row headers /// flag to enable row headers
@property bool showRowHeaders() { @property bool showRowHeaders() {
return _headerCols > 0; return _showRowHeaders;
} }
@property GridWidgetBase showRowHeaders(bool show) { @property GridWidgetBase showRowHeaders(bool show) {
_headerCols = show ? 1 : 0; if (_showRowHeaders != show) {
invalidate(); _showRowHeaders = show;
for (int i = 0; i < _headerCols; i++)
autoFitColumnWidth(i);
invalidate();
}
return this; return this;
} }
@ -391,6 +432,7 @@ class GridWidgetBase : WidgetGroup, OnScrollHandler {
} }
//if (changed) //if (changed)
updateScrollBars(); updateScrollBars();
invalidate();
return oldx != _scrollCol || oldy != _scrollRow; return oldx != _scrollCol || oldy != _scrollRow;
} }
@ -505,6 +547,13 @@ class GridWidgetBase : WidgetGroup, OnScrollHandler {
} }
return true; return true;
} }
if (event.action == MouseAction.Wheel) {
if (event.flags & MouseFlag.Shift)
scrollBy(-event.wheelDelta, 0);
else
scrollBy(0, -event.wheelDelta);
return true;
}
return super.onMouseEvent(event); return super.onMouseEvent(event);
} }
@ -618,24 +667,41 @@ class GridWidgetBase : WidgetGroup, OnScrollHandler {
override protected bool handleAction(const Action a) { override protected bool handleAction(const Action a) {
calcScrollableAreaPos(); calcScrollableAreaPos();
switch (a.id) { int actionId = a.id;
if (_rowSelect) {
switch(actionId) {
case GridActions.Left:
actionId = GridActions.ScrollLeft;
break;
case GridActions.Right:
actionId = GridActions.ScrollRight;
break;
//case GridActions.LineBegin:
// actionId = GridActions.ScrollPageLeft;
// break;
//case GridActions.LineEnd:
// actionId = GridActions.ScrollPageRight;
// break;
default:
break;
}
}
switch (actionId) {
case GridActions.ScrollLeft: case GridActions.ScrollLeft:
if (_scrollCol > 0) scrollBy(-1, 0);
scrollBy(-1, 0);
return true; return true;
case GridActions.Left: case GridActions.Left:
selectCell(_col - 1, _row); selectCell(_col - 1, _row);
return true; return true;
case GridActions.ScrollRight: case GridActions.ScrollRight:
if (_fullyVisibleCells.right < _cols - 1) scrollBy(1, 0);
scrollBy(1, 0);
return true; return true;
case GridActions.Right: case GridActions.Right:
selectCell(_col + 1, _row); selectCell(_col + 1, _row);
return true; return true;
case GridActions.ScrollUp: case GridActions.ScrollUp:
if (_scrollRow > 0) scrollBy(0, -1);
scrollBy(0, -1);
return true; return true;
case GridActions.Up: case GridActions.Up:
selectCell(_col, _row - 1); selectCell(_col, _row - 1);
@ -680,7 +746,7 @@ class GridWidgetBase : WidgetGroup, OnScrollHandler {
} }
return true; return true;
case GridActions.LineBegin: case GridActions.LineBegin:
if (_scrollCol > 0 && _col > _headerCols + _fixedCols + _scrollCol) if (_scrollCol > 0 && _col > _headerCols + _fixedCols + _scrollCol && !_rowSelect)
selectCell(_headerCols + _fixedCols + _scrollCol, _row); selectCell(_headerCols + _fixedCols + _scrollCol, _row);
else { else {
if (_scrollCol > 0) { if (_scrollCol > 0) {
@ -791,7 +857,6 @@ class GridWidgetBase : WidgetGroup, OnScrollHandler {
measuredContent(parentWidth, parentHeight, sz.x, sz.y); measuredContent(parentWidth, parentHeight, sz.x, sz.y);
} }
/// 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) {
@ -924,14 +989,22 @@ class GridWidgetBase : WidgetGroup, OnScrollHandler {
return m; return m;
} }
void autoFitColumnWidth(int i) {
_colWidths[i] = (i < _headerCols && !_showRowHeaders) ? 0 : measureColWidth(i) + 5;
}
void autoFitColumnWidths() { void autoFitColumnWidths() {
for (int i = 0; i < _cols; i++) for (int i = 0; i < _cols; i++)
_colWidths[i] = measureColWidth(i) + 5; autoFitColumnWidth(i);
}
void autoFitRowHeight(int i) {
_rowHeights[i] = (i < _headerRows && !_showColHeaders) ? 0 : measureRowHeight(i) + 2;
} }
void autoFitRowHeights() { void autoFitRowHeights() {
for (int i = 0; i < _rows; i++) for (int i = 0; i < _rows; i++)
_rowHeights[i] = measureRowHeight(i) + 2; autoFitRowHeight(i);
} }
void autoFit() { void autoFit() {
@ -947,6 +1020,10 @@ class GridWidgetBase : WidgetGroup, OnScrollHandler {
_vscrollbar.onScrollEventListener = this; _vscrollbar.onScrollEventListener = this;
addChild(_vscrollbar); addChild(_vscrollbar);
addChild(_hscrollbar); addChild(_hscrollbar);
_headerCols = 1;
_headerRows = 1;
_showColHeaders = true;
_showRowHeaders = true;
acceleratorMap.add( [ acceleratorMap.add( [
new Action(GridActions.Up, KeyCode.UP, 0), new Action(GridActions.Up, KeyCode.UP, 0),
new Action(GridActions.Down, KeyCode.DOWN, 0), new Action(GridActions.Down, KeyCode.DOWN, 0),
@ -965,11 +1042,29 @@ class GridWidgetBase : WidgetGroup, OnScrollHandler {
} }
} }
class StringGridWidgetBase : GridWidgetBase {
this(string ID = null) {
super(ID);
}
/// get cell text
abstract dstring cellText(int col, int row);
/// set cell text
abstract StringGridWidgetBase setCellText(int col, int row, dstring text);
/// returns row header title
abstract dstring rowTitle(int row);
/// set row header title
abstract StringGridWidgetBase setRowTitle(int row, dstring title);
/// returns row header title
abstract dstring colTitle(int col);
/// set col header title
abstract StringGridWidgetBase setColTitle(int col, dstring title);
}
/** /**
* Grid view with string data shown. All rows are of the same height. * Grid view with string data shown. All rows are of the same height.
*/ */
class StringGridWidget : GridWidgetBase { class StringGridWidget : StringGridWidgetBase {
protected dstring[][] _data; protected dstring[][] _data;
protected dstring[] _rowTitles; protected dstring[] _rowTitles;
@ -980,11 +1075,11 @@ class StringGridWidget : GridWidgetBase {
styleId = "EDIT_BOX"; styleId = "EDIT_BOX";
} }
/// get cell text /// get cell text
dstring cellText(int col, int row) { override dstring cellText(int col, int row) {
return _data[row][col]; return _data[row][col];
} }
/// set cell text /// set cell text
GridWidgetBase setCellText(int col, int row, dstring text) { override StringGridWidgetBase setCellText(int col, int row, dstring text) {
_data[row][col] = text; _data[row][col] = text;
return this; return this;
} }
@ -1038,22 +1133,22 @@ class StringGridWidget : GridWidgetBase {
} }
/// returns row header title /// returns row header title
dstring rowTitle(int row) { override dstring rowTitle(int row) {
return _rowTitles[row]; return _rowTitles[row];
} }
/// set row header title /// set row header title
GridWidgetBase setRowTitle(int row, dstring title) { override StringGridWidgetBase setRowTitle(int row, dstring title) {
_rowTitles[row] = title; _rowTitles[row] = title;
return this; return this;
} }
/// returns row header title /// returns row header title
dstring colTitle(int col) { override dstring colTitle(int col) {
return _colTitles[col]; return _colTitles[col];
} }
/// set col header title /// set col header title
GridWidgetBase setColTitle(int col, dstring title) { override StringGridWidgetBase setColTitle(int col, dstring title) {
_colTitles[col] = title; _colTitles[col] = title;
return this; return this;
} }
@ -1093,11 +1188,15 @@ class StringGridWidget : GridWidgetBase {
bool selectedCol = _col == col; bool selectedCol = _col == col;
bool selectedRow = _row == row; bool selectedRow = _row == row;
bool selectedCell = selectedCol && selectedRow; bool selectedCell = selectedCol && selectedRow;
if (_rowSelect && selectedRow)
selectedCell = true;
if (col < _headerCols || row < _headerRows) { if (col < _headerCols || row < _headerRows) {
// draw header cell background // draw header cell background
uint cl = 0x80909090; uint cl = 0x80909090;
if (selectedCol || selectedRow) if (!_rowSelect || col < _headerCols) {
cl = 0x80FFC040; if (selectedCol || selectedRow)
cl = 0x80FFC040;
}
buf.fillRect(rc, cl); buf.fillRect(rc, cl);
buf.fillRect(vborder, 0x80202020); buf.fillRect(vborder, 0x80202020);
buf.fillRect(hborder, 0x80202020); buf.fillRect(hborder, 0x80202020);
@ -1109,8 +1208,12 @@ class StringGridWidget : GridWidgetBase {
} }
buf.fillRect(vborder, 0x80C0C0C0); buf.fillRect(vborder, 0x80C0C0C0);
buf.fillRect(hborder, 0x80C0C0C0); buf.fillRect(hborder, 0x80C0C0C0);
if (selectedCell) if (selectedCell) {
buf.drawFrame(rc, 0x404040FF, Rect(1,1,1,1), 0xC0FFFF00); if (_rowSelect)
buf.drawFrame(rc, 0x80A0B0FF, Rect(0,1,0,1), 0xC0FFFF00);
else
buf.drawFrame(rc, 0x404040FF, Rect(1,1,1,1), 0xC0FFFF00);
}
} }
} }