Implemented mouse click selection.
This commit is contained in:
parent
516173916e
commit
cecfa82994
|
@ -1,71 +1,5 @@
|
||||||
// 4 december 2014
|
// 4 december 2014
|
||||||
|
|
||||||
struct rowcol {
|
|
||||||
intptr_t row;
|
|
||||||
intptr_t column;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct rowcol clientCoordToRowColumn(struct table *t, POINT pt)
|
|
||||||
{
|
|
||||||
RECT r;
|
|
||||||
struct rowcol rc;
|
|
||||||
intptr_t i;
|
|
||||||
RECT colrect;
|
|
||||||
|
|
||||||
// initial values for the PtInRect() check
|
|
||||||
rc.row = -1;
|
|
||||||
rc.column = -1;
|
|
||||||
|
|
||||||
if (GetClientRect(t->hwnd, &r) == 0)
|
|
||||||
panic("error getting Table client rect in clientCoordToRowColumn()");
|
|
||||||
r.top += t->headerHeight;
|
|
||||||
if (PtInRect(&r, p) == 0)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
// the row is easy
|
|
||||||
rc.row = (pt.y / rowht(t)) + t->yscrollpos;
|
|
||||||
|
|
||||||
// the column... not so much
|
|
||||||
// we scroll p.x, then subtract column widths until we cross the left edge of the control
|
|
||||||
p.x += t->hscrollpos;
|
|
||||||
rc.column = 0;
|
|
||||||
for (i = 0; i < t->nColumns; i++) {
|
|
||||||
// TODO error check
|
|
||||||
SendMessage(t->header, HDM_GETITEMRECT, (WPARAM) i, (LPARAM) (&colrect));
|
|
||||||
p.x -= colrect.right - colrect.left;
|
|
||||||
// use <, not <=, here:
|
|
||||||
// assume r.left and t->hscrollpos == 0;
|
|
||||||
// given the first column is 100 wide,
|
|
||||||
// p.x == 0 (first pixel of col 0) -> p.x - 100 == -100 < 0 -> break
|
|
||||||
// p.x == 99 (last pixel of col 0) -> p.x - 100 == -1 < 0 -> break
|
|
||||||
// p.x == 100 (first pixel of col 1) -> p.x - 100 == 0 >= 0 -> next column
|
|
||||||
if (p.x < r.left)
|
|
||||||
break;
|
|
||||||
rc.column++;
|
|
||||||
}
|
|
||||||
// TODO what happens if the break was never taken?
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
// same as client coordinates, but stored in a lParam (like the various mouse messages provide)
|
|
||||||
static struct rowcol lParamToRowColumn(struct table *t, LPARAM lParam)
|
|
||||||
{
|
|
||||||
POINT pt;
|
|
||||||
|
|
||||||
pt.x = GET_X_LPARAM(lParam);
|
|
||||||
pt.y = GET_Y_LPARAM(lParam);
|
|
||||||
return clientCoordToRowColumn(t, pt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns TRUE if the row is visible and thus has client coordinates; FALSE otherwise
|
|
||||||
static BOOL rowColumnToClientCoord(struct table *t, struct rowcol rc, struct POINT *pt)
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO idealCoordToRowColumn/rowColumnToIdealCoord?
|
|
||||||
|
|
||||||
// TODO find a better place for this
|
// TODO find a better place for this
|
||||||
static LONG rowHeight(struct table *t, HDC dc, BOOL select)
|
static LONG rowHeight(struct table *t, HDC dc, BOOL select)
|
||||||
{
|
{
|
||||||
|
@ -93,3 +27,70 @@ static LONG rowHeight(struct table *t, HDC dc, BOOL select)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define rowht(t) rowHeight(t, NULL, TRUE)
|
#define rowht(t) rowHeight(t, NULL, TRUE)
|
||||||
|
|
||||||
|
struct rowcol {
|
||||||
|
intptr_t row;
|
||||||
|
intptr_t column;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rowcol clientCoordToRowColumn(struct table *t, POINT pt)
|
||||||
|
{
|
||||||
|
RECT r;
|
||||||
|
struct rowcol rc;
|
||||||
|
intptr_t i;
|
||||||
|
RECT colrect;
|
||||||
|
|
||||||
|
// initial values for the PtInRect() check
|
||||||
|
rc.row = -1;
|
||||||
|
rc.column = -1;
|
||||||
|
|
||||||
|
if (GetClientRect(t->hwnd, &r) == 0)
|
||||||
|
panic("error getting Table client rect in clientCoordToRowColumn()");
|
||||||
|
r.top += t->headerHeight;
|
||||||
|
if (PtInRect(&r, pt) == 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
// the row is easy
|
||||||
|
pt.y -= t->headerHeight;
|
||||||
|
rc.row = (pt.y / rowht(t)) + t->vscrollpos;
|
||||||
|
|
||||||
|
// the column... not so much
|
||||||
|
// we scroll p.x, then subtract column widths until we cross the left edge of the control
|
||||||
|
pt.x += t->hscrollpos;
|
||||||
|
rc.column = 0;
|
||||||
|
for (i = 0; i < t->nColumns; i++) {
|
||||||
|
// TODO error check
|
||||||
|
SendMessage(t->header, HDM_GETITEMRECT, (WPARAM) i, (LPARAM) (&colrect));
|
||||||
|
pt.x -= colrect.right - colrect.left;
|
||||||
|
// use <, not <=, here:
|
||||||
|
// assume r.left and t->hscrollpos == 0;
|
||||||
|
// given the first column is 100 wide,
|
||||||
|
// pt.x == 0 (first pixel of col 0) -> p.x - 100 == -100 < 0 -> break
|
||||||
|
// pt.x == 99 (last pixel of col 0) -> p.x - 100 == -1 < 0 -> break
|
||||||
|
// pt.x == 100 (first pixel of col 1) -> p.x - 100 == 0 >= 0 -> next column
|
||||||
|
if (pt.x < r.left)
|
||||||
|
break;
|
||||||
|
rc.column++;
|
||||||
|
}
|
||||||
|
// TODO what happens if the break was never taken?
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// same as client coordinates, but stored in a lParam (like the various mouse messages provide)
|
||||||
|
static struct rowcol lParamToRowColumn(struct table *t, LPARAM lParam)
|
||||||
|
{
|
||||||
|
POINT pt;
|
||||||
|
|
||||||
|
pt.x = GET_X_LPARAM(lParam);
|
||||||
|
pt.y = GET_Y_LPARAM(lParam);
|
||||||
|
return clientCoordToRowColumn(t, pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns TRUE if the row is visible and thus has client coordinates; FALSE otherwise
|
||||||
|
static BOOL rowColumnToClientCoord(struct table *t, struct rowcol rc, POINT *pt)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO idealCoordToRowColumn/rowColumnToIdealCoord?
|
||||||
|
|
|
@ -21,6 +21,7 @@ static const handlerfunc mouseLeaveHandlers[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const handlerfunc lbuttonDownHandlers[] = {
|
static const handlerfunc lbuttonDownHandlers[] = {
|
||||||
|
mouseDownSelectHandler,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,6 +29,7 @@ static const handlerfunc lbuttonUpHandlers[] = {
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO remove or something? depends on if we implement combobox and how
|
||||||
static const handlerfunc mouseWheelHandlers[] = {
|
static const handlerfunc mouseWheelHandlers[] = {
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
|
@ -70,6 +70,7 @@ struct table {
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "coord.h"
|
#include "coord.h"
|
||||||
|
#include "select.h"
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
#include "scroll.h"
|
#include "scroll.h"
|
||||||
#include "hscroll.h"
|
#include "hscroll.h"
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
// 13 december 2014
|
||||||
|
|
||||||
|
// damn winsock
|
||||||
|
static void doselect(struct table *t, intptr_t row, intptr_t column)
|
||||||
|
{
|
||||||
|
t->selectedRow = row;
|
||||||
|
t->selectedColumn = column;
|
||||||
|
// TODO scroll to ensure the full cell is visible
|
||||||
|
// TODO redraw only the old and new columns /if there was no scrolling/
|
||||||
|
InvalidateRect(t->hwnd, NULL, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO which WM_xBUTTONDOWNs?
|
||||||
|
HANDLER(mouseDownSelectHandler)
|
||||||
|
{
|
||||||
|
struct rowcol rc;
|
||||||
|
|
||||||
|
rc = lParamToRowColumn(t, lParam);
|
||||||
|
// don't check if lParamToRowColumn() returned row -1 or column -1; we want deselection behavior
|
||||||
|
doselect(t, rc.row, rc.column);
|
||||||
|
*lResult = 0;
|
||||||
|
return TRUE;
|
||||||
|
}
|
Loading…
Reference in New Issue