119 lines
3.8 KiB
C
119 lines
3.8 KiB
C
// 13 december 2014
|
|
|
|
// damn winsock
|
|
static void doselect(struct table *t, intptr_t row, intptr_t column)
|
|
{
|
|
RECT r, client;
|
|
intptr_t oldrow;
|
|
LONG width, height;
|
|
struct rowcol rc;
|
|
BOOL dovscroll;
|
|
intptr_t i;
|
|
intptr_t xpos;
|
|
LONG clientWidth;
|
|
|
|
oldrow = t->selectedRow;
|
|
t->selectedRow = row;
|
|
t->selectedColumn = column;
|
|
|
|
if (GetClientRect(t->hwnd, &client) == 0)
|
|
panic("error getting Table client rect in doselect()");
|
|
client.top += t->headerHeight;
|
|
height = rowht(t);
|
|
|
|
// first vertically scroll to the new row to make it fully visible (or as visible as possible)
|
|
if (t->selectedRow < t->vscrollpos)
|
|
vscrollto(t, t->selectedRow);
|
|
else {
|
|
rc.row = t->selectedRow;
|
|
rc.column = t->selectedColumn;
|
|
// first assume entirely outside the client area
|
|
dovscroll = TRUE;
|
|
if (rowColumnToClientRect(t, rc, &r))
|
|
// partially outside the client area?
|
|
if (r.bottom <= client.bottom) // <= here since we are comparing bottoms (which are the first pixels outside the rectangle)
|
|
dovscroll = FALSE;
|
|
if (dovscroll)
|
|
vscrollto(t, t->selectedRow - t->vpagesize + 1); // + 1 because apparently just t->selectedRow - t->vpagesize results in no scrolling (t->selectedRow - t->vpagesize == t->vscrollpos)...
|
|
}
|
|
|
|
// now see if the cell we want is to the left of offscreen, in which case scroll to its x-position
|
|
xpos = 0;
|
|
for (i = 0; i < t->selectedColumn; i++)
|
|
xpos += columnWidth(t, i);
|
|
if (xpos < t->hscrollpos)
|
|
hscrollto(t, xpos);
|
|
else {
|
|
// if the full cell is not visible, scroll to the right just enough to make it fully visible (or as visible as possible)
|
|
width = columnWidth(t, t->selectedColumn);
|
|
clientWidth = client.right - client.left;
|
|
if (xpos + width > t->hscrollpos + clientWidth) // > because both sides deal with the first pixel outside
|
|
// if the column is too wide, then just make it occupy the whole visible area (left-aligned)
|
|
if (width > clientWidth) // TODO >= ?
|
|
hscrollto(t, xpos);
|
|
else
|
|
// TODO don't use t->hpagesize here? depends if other code uses it
|
|
hscrollto(t, (xpos + width) - t->hpagesize);
|
|
}
|
|
|
|
// now redraw the old and new /rows/
|
|
// we do this after scrolling so the rectangles to be invalidated make sense
|
|
r.left = client.left;
|
|
r.right = client.right;
|
|
if (oldrow != -1 && oldrow >= t->vscrollpos) {
|
|
r.top = client.top + ((oldrow - t->vscrollpos) * height);
|
|
r.bottom = r.top + height;
|
|
if (InvalidateRect(t->hwnd, &r, TRUE) == 0)
|
|
panic("error queueing previously selected row for redraw in doselect()");
|
|
}
|
|
// t->selectedRow must be visible by this point; we scrolled to it
|
|
if (t->selectedRow != -1 && t->selectedRow != oldrow) {
|
|
r.top = client.top + ((t->selectedRow - t->vscrollpos) * height);
|
|
r.bottom = r.top + height;
|
|
if (InvalidateRect(t->hwnd, &r, TRUE) == 0)
|
|
panic("error queueing newly selected row for redraw in doselect()");
|
|
}
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
/*
|
|
keyboard selection behaviors of the windows 7 listview:
|
|
with 100 items (0-99), the window currently shows items 30 through 47 as well as having item 48 partially visible
|
|
- item 30:
|
|
- page up -> item 13
|
|
- page down -> item 47
|
|
- item 31:
|
|
TODO
|
|
- item 42:
|
|
- page up -> item 30
|
|
- page down -> item 47
|
|
- item 46:
|
|
TODO
|
|
- item 47:
|
|
- page up: -> item 30
|
|
- page down: -> item 64
|
|
|
|
when nothing is selected:
|
|
- down selects item 0 regardless of scroll
|
|
- up selects nothing regardless of scroll
|
|
- page down selects the last fully visible item depending on scroll
|
|
- so with the above configuration:
|
|
- item 0 -> item 17
|
|
- item 30 -> item 47
|
|
- item 80 -> item 97
|
|
- page up selects item 0 regardless of scroll
|
|
- home selects item xxxx
|
|
- end selects item xxx
|
|
*/
|