andlabs-ui/wintable/new/select.h

128 lines
4.6 KiB
C
Raw Normal View History

2014-12-13 12:56:31 -06:00
// 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;
2014-12-13 12:56:31 -06:00
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)
2014-12-14 16:29:32 -06:00
if (width > clientWidth) // TODO >= ?
hscrollto(t, xpos);
else
2014-12-14 17:06:08 -06:00
// 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()");
}
2014-12-13 12:56:31 -06:00
}
// 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;
}
/*
the routine below is intended to simulate the comctl32.dll listview keyboard navigation rules, at least as far as vertical navigation is concerned.
horizontal scrolling is different because (unlike the comctl32) listview, we say that a single column in each row has the keyboard focus, so left and right navigate between columns here, instead of scrolling left/right by pixels.
TODO provide an override for scrolling by pixels?
TODO any other keyboard shortcuts?
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:
- page up -> item 30
- page down -> item 47
- item 42:
- page up -> item 30
- page down -> item 47
- item 46:
- page up -> item 30
- page down -> item 47
- item 47:
- page up: -> item 30
- page down: -> item 64
2014-12-15 19:03:46 -06:00
when nothing is selected:
- down selects item 0 regardless of scroll
- up selects nothing regardless of scroll
2014-12-15 22:48:09 -06:00
- 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 0 regardless of scroll
- end selects the last item regardless of scroll
for left and right we will simulate up and down, respectively (so right selects row 0 column 0); remember that you can't have either row or column be -1 but not both
*/