diff --git a/wintable/new/coord.h b/wintable/new/coord.h index 5716db4..16f93a3 100644 --- a/wintable/new/coord.h +++ b/wintable/new/coord.h @@ -1,71 +1,5 @@ // 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 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) + +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? diff --git a/wintable/new/events.h b/wintable/new/events.h index 2e270a9..a631178 100644 --- a/wintable/new/events.h +++ b/wintable/new/events.h @@ -21,6 +21,7 @@ static const handlerfunc mouseLeaveHandlers[] = { }; static const handlerfunc lbuttonDownHandlers[] = { + mouseDownSelectHandler, NULL, }; @@ -28,6 +29,7 @@ static const handlerfunc lbuttonUpHandlers[] = { NULL, }; +// TODO remove or something? depends on if we implement combobox and how static const handlerfunc mouseWheelHandlers[] = { NULL, }; diff --git a/wintable/new/main.c b/wintable/new/main.c index 9a806b6..4635c16 100644 --- a/wintable/new/main.c +++ b/wintable/new/main.c @@ -70,6 +70,7 @@ struct table { #include "util.h" #include "coord.h" +#include "select.h" #include "events.h" #include "scroll.h" #include "hscroll.h" diff --git a/wintable/new/select.h b/wintable/new/select.h new file mode 100644 index 0000000..c849802 --- /dev/null +++ b/wintable/new/select.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; +}