grid mouse handling - select cell

This commit is contained in:
Vadim Lopatin 2014-06-03 16:57:29 +04:00
parent 1a849c1970
commit 305e020de7
3 changed files with 149 additions and 27 deletions

View File

@ -240,24 +240,44 @@ enum MouseAction : ubyte {
/// mouse flag bits
enum MouseFlag : ushort {
/// Ctrl key is down
Control = 0x0008,
// mouse buttons
/// Left mouse button is down
LButton = 0x0001,
/// Middle mouse button is down
MButton = 0x0010,
/// Right mouse button is down
RButton = 0x0002,
/// Shift key is down
Shift = 0x0004,
/// X1 mouse button is down
XButton1= 0x0020,
/// X2 mouse button is down
XButton2= 0x0040,
// keyboard modifiers
/// Ctrl key is down
Control = 0x0008,
/// Shift key is down
Shift = 0x0004,
/// Alt key is down
Alt = 0x0080
Alt = 0x0080,
}
/// mouse button
enum MouseButton : ubyte {
/// no button
None,
/// left mouse button
Left = MouseFlag.LButton,
/// right mouse button
Right = MouseFlag.RButton,
/// right mouse button
Middle = MouseFlag.MButton,
/// additional mouse button 1
XButton1 = MouseFlag.XButton1, // additional button 1
/// additional mouse button 2
XButton2 = MouseFlag.XButton2, // additional button 2
}
/// mouse button state details
struct ButtonDetails {
/// Clock.currStdTime() for down event of this button (0 if button is up).
@ -297,22 +317,6 @@ struct ButtonDetails {
@property ushort downFlags() { return _downFlags; }
}
/// mouse button
enum MouseButton : ubyte {
/// no button
None,
/// left mouse button
Left,
/// right mouse button
Right,
/// right mouse button
Middle,
/// additional mouse button 1
XButton1, // additional button
/// additional mouse button 2
XButton2, // additional button
}
/// mouse event
class MouseEvent {
protected long _eventTimestamp;

View File

@ -41,8 +41,11 @@ module dlangui.core.types;
import std.algorithm;
/// 2D point
struct Point {
/// x coordinate
int x;
/// y coordinate
int y;
this(int x0, int y0) {
x = x0;
@ -50,25 +53,35 @@ struct Point {
}
}
/// 2D rectangle
struct Rect {
/// x coordinate of top left corner
int left;
/// y coordinate of top left corner
int top;
/// x coordinate of bottom right corner
int right;
/// y coordinate of bottom right corner
int bottom;
/// returns average of left, right
@property int middlex() { return (left + right) / 2; }
/// returns average of top, bottom
@property int middley() { return (top + bottom) / 2; }
/// add offset to horizontal and vertical coordinates
void offset(int dx, int dy) {
left += dx;
right += dx;
top += dy;
bottom += dy;
}
/// expand rectangle dimensions
void expand(int dx, int dy) {
left -= dx;
right += dx;
top -= dy;
bottom += dy;
}
/// shrink rectangle dimensions
void shrink(int dx, int dy) {
left += dx;
right -= dx;
@ -97,6 +110,7 @@ struct Rect {
@property bool empty() {
return right <= left || bottom <= top;
}
/// translate rectangle coordinates by (x,y) - add deltax to x coordinates, and deltay to y coordinates
void moveBy(int deltax, int deltay) {
left += deltax;
right += deltax;
@ -187,10 +201,13 @@ class RefCountedObject {
~this() {}
}
/// reference counting
struct Ref(T) { // if (T is RefCountedObject)
private T _data;
alias get this;
/// returns true if object is not assigned
@property bool isNull() const { return _data is null; }
/// returns counter of references
@property int refCount() const { return _data !is null ? _data.refCount : 0; }
this(T data) {
_data = data;
@ -231,15 +248,18 @@ struct Ref(T) { // if (T is RefCountedObject)
_data.addRef();
return this;
}
/// clears reference
void clear() {
if (_data !is null) {
_data.releaseRef();
_data = null;
}
}
/// returns object reference (null if not assigned)
@property T get() {
return _data;
}
/// returns const reference from const object
@property const(T) get() const {
return _data;
}
@ -249,8 +269,10 @@ struct Ref(T) { // if (T is RefCountedObject)
}
}
//================================================================================
// some utility functions
string fromStringz(const(char[]) s) {
if (s is null)
return null;

View File

@ -125,6 +125,11 @@ class StringGridWidget : GridWidgetBase {
protected int _scrollCol;
/// row scroll offset, relative to last fixed row; 0 = not scrolled
protected int _scrollRow;
/// selected cell column
protected int _col;
/// selected cell row
protected int _row;
this(string ID = null) {
super(ID);
_headerCols = 1;
@ -135,6 +140,13 @@ class StringGridWidget : GridWidgetBase {
addChild(_hscrollbar);
styleId = "EDIT_BOX";
resize(20, 30);
_col = 3;
_row = 4;
for (int y = 1; y < _rows; y++) {
for (int x = 1; x < _cols; x++) {
_data[y][x] = "cell("d ~ to!dstring(x) ~ ","d ~ to!dstring(y) ~ ")"d;
}
}
}
@property override int cols() {
return _cols;
@ -202,7 +214,7 @@ class StringGridWidget : GridWidgetBase {
for (int i = _cols; i < cols; i++) {
if (i >= _headerCols)
_data[0][i] = genColHeader(i - _headerCols);
_colWidths[i] = i == 0 ? 20 : 80;
_colWidths[i] = i == 0 ? 20 : 100;
}
_rowHeights.length = rows;
int fontHeight = font.height;
@ -254,6 +266,82 @@ class StringGridWidget : GridWidgetBase {
}
return rc;
}
/// converts client rect relative coordinates to cell coordinates
bool pointToCell(int x, int y, ref int col, ref int row, ref Rect cellRect) {
col = row = -1;
cellRect = Rect();
Rect rc;
int xx = 0;
for (int i = 0; i < _cols; i++) {
rc.left = xx;
xx += colWidth(i);
rc.right = xx;
if (rc.left < rc.right && x >= rc.left && x < rc.right) {
col = i;
break;
}
if (xx > x)
break;
}
int yy = 0;
for (int i = 0; i < _rows; i++) {
rc.top = yy;
yy += rowHeight(i);
rc.bottom = yy;
if (rc.top < rc.bottom && y >= rc.top && y < rc.bottom) {
row = i;
break;
}
if (yy > y)
break;
}
if (col >= 0 && row >= 0) {
cellRect = rc;
return true;
}
return false;
}
/// handle mouse wheel events
override bool onMouseEvent(MouseEvent event) {
if (visibility != Visibility.Visible)
return false;
int c, r; // col, row
Rect rc;
bool cellFound = false;
bool normalCell = false;
// convert coordinates
if (event.action == MouseAction.ButtonUp || event.action == MouseAction.ButtonDown || event.action == MouseAction.Move) {
int x = event.x;
int y = event.y;
x -= _clientRect.left;
y -= _clientRect.top;
cellFound = pointToCell(x, y, c, r, rc);
normalCell = c >= _fixedCols && r >= _fixedRows;
}
if (event.action == MouseAction.ButtonDown && event.button == MouseButton.Left) {
if (cellFound && normalCell) {
_col = c;
_row = r;
invalidate();
}
return true;
}
if (event.action == MouseAction.Move && (event.flags & MouseFlag.LButton)) {
// TODO: selection
if (cellFound && normalCell) {
_col = c;
_row = r;
invalidate();
}
return true;
}
return super.onMouseEvent(event);
}
/// returns row header title
dstring rowTitle(int row) {
return _rowTitles[row];
@ -331,7 +419,7 @@ class StringGridWidget : GridWidgetBase {
/// draw cell content
void drawCell(DrawBuf buf, Rect rc, int col, int row) {
rc.shrink(1, 1);
rc.shrink(2, 1);
FontRef fnt = font;
dstring txt = cellText(col, row);
Point sz = fnt.textSize(txt);
@ -351,15 +439,23 @@ class StringGridWidget : GridWidgetBase {
vborder.left = vborder.right - 1;
hborder.top = hborder.bottom - 1;
hborder.right--;
bool selectedCol = _col == col;
bool selectedRow = _row == row;
bool selectedCell = selectedCol && selectedRow;
if (col < _headerCols || row < _headerRows) {
// draw header cell background
buf.fillRect(rc, 0x80808080);
buf.fillRect(vborder, 0x80FFFFFF);
buf.fillRect(hborder, 0x80FFFFFF);
uint cl = 0x80909090;
if (selectedCol || selectedRow)
cl = 0x80FFC040;
buf.fillRect(rc, cl);
buf.fillRect(vborder, 0x80202020);
buf.fillRect(hborder, 0x80202020);
} else {
// normal cell background
buf.fillRect(vborder, 0x80C0C0C0);
buf.fillRect(hborder, 0x80C0C0C0);
if (selectedCell)
buf.drawFrame(rc, 0x404040FF, Rect(1,1,1,1), 0xC0FFFF00);
}
}