mirror of https://github.com/buggins/dlangui.git
grids: row select support
This commit is contained in:
parent
0103bb8a3d
commit
e7b40dc6e0
|
|
@ -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++) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue