Collected all of the metric updating stuff into a single update() function. Far from optimal, but much better.

This commit is contained in:
Pietro Gagliardi 2015-01-08 01:45:06 -05:00
parent 224bdb4087
commit 1dcdcd522c
6 changed files with 65 additions and 63 deletions

View File

@ -9,7 +9,7 @@ static void addColumn(struct table *t, WPARAM wParam, LPARAM lParam)
if (t->columnTypes[t->nColumns - 1] >= nTableColumnTypes) if (t->columnTypes[t->nColumns - 1] >= nTableColumnTypes)
panic("invalid column type passed to tableAddColumn"); panic("invalid column type passed to tableAddColumn");
headerAddColumn(t, (WCHAR *) lParam); headerAddColumn(t, (WCHAR *) lParam);
updateTableWidth(t); update(t, TRUE);
} }
HANDLER(apiHandlers) HANDLER(apiHandlers)
@ -21,8 +21,11 @@ HANDLER(apiHandlers)
// don't free the old font; see http://blogs.msdn.com/b/oldnewthing/archive/2008/09/12/8945692.aspx // don't free the old font; see http://blogs.msdn.com/b/oldnewthing/archive/2008/09/12/8945692.aspx
t->font = (HFONT) wParam; t->font = (HFONT) wParam;
SendMessageW(t->header, WM_SETFONT, wParam, lParam); SendMessageW(t->header, WM_SETFONT, wParam, lParam);
// TODO how to properly handle LOWORD(lParam) != FALSE? update(t, LOWORD(lParam) != FALSE);
// TODO depending on the result of the above, update table width to refresh t->headerHeight? // TODO is this needed?
if (LOWORD(lParam) != FALSE)
// TODO check error
InvalidateRect(t->hwnd, NULL, TRUE);
*lResult = 0; *lResult = 0;
return TRUE; return TRUE;
case WM_GETFONT: case WM_GETFONT:
@ -35,8 +38,8 @@ HANDLER(apiHandlers)
case tableSetRowCount: case tableSetRowCount:
rcp = (intptr_t *) lParam; rcp = (intptr_t *) lParam;
t->count = *rcp; t->count = *rcp;
// TODO refresh table in this way? // TODO shouldn't we just redraw everything?
updateTableWidth(t); update(t, TRUE);
*lResult = 0; *lResult = 0;
return TRUE; return TRUE;
} }

View File

@ -22,6 +22,9 @@ static void destroyHeader(struct table *t)
panic("error destroying Table header"); panic("error destroying Table header");
} }
// to avoid weird bugs, the only functions allowed to call this one are the horizontal scroll functions
// when we need to reposition the header in a situation other than a user-initiated scroll, we use a dummy scroll (hscrollby(t, 0))
// see update() in update.h
static void repositionHeader(struct table *t) static void repositionHeader(struct table *t)
{ {
RECT r; RECT r;
@ -58,40 +61,6 @@ static void headerAddColumn(struct table *t, WCHAR *name)
panic("error adding column to Table header"); panic("error adding column to Table header");
} }
// TODO make a better name for this?
// TODO move to hscroll.h?
// TODO organize this in general...
// TODO because of this function's new extended functionality only hscrollto() is allowed to call repositionHeader()
static void updateTableWidth(struct table *t)
{
HDITEMW item;
intptr_t i;
RECT client;
t->width = 0;
// TODO count dividers?
// TODO use columnWidth()
for (i = 0; i < t->nColumns; i++) {
ZeroMemory(&item, sizeof (HDITEMW));
item.mask = HDI_WIDTH;
if (SendMessageW(t->header, HDM_GETITEM, (WPARAM) i, (LPARAM) (&item)) == FALSE)
panic("error getting Table column width for updateTableWidth()");
t->width += item.cxy;
}
if (GetClientRect(t->hwnd, &client) == 0)
panic("error getting Table client rect in updateTableWidth()");
t->hpagesize = client.right - client.left;
// this part is critical: if we resize the columns to less than the client area width, then the following hscrollby() will make t->hscrollpos negative, which does very bad things
// note to self: do this regardless of whether the table width or the client area width was changed
if (t->hpagesize > t->width)
t->hpagesize = t->width;
// do a dummy scroll to update the horizontal scrollbar to use the new width
hscrollby(t, 0);
}
HANDLER(headerNotifyHandler) HANDLER(headerNotifyHandler)
{ {
NMHDR *nmhdr = (NMHDR *) lParam; NMHDR *nmhdr = (NMHDR *) lParam;
@ -100,10 +69,10 @@ HANDLER(headerNotifyHandler)
return FALSE; return FALSE;
if (nmhdr->code != HDN_ITEMCHANGED) if (nmhdr->code != HDN_ITEMCHANGED)
return FALSE; return FALSE;
updateTableWidth(t); update(t, TRUE);
// TODO make more intelligent // TODO make more intelligent
// (TODO is it actually needed?)
InvalidateRect(t->hwnd, NULL, TRUE); InvalidateRect(t->hwnd, NULL, TRUE);
// TODO UpdateWindow()?
*lResult = 0; *lResult = 0;
return TRUE; return TRUE;
} }

View File

@ -103,6 +103,9 @@ struct table {
// forward declaration (TODO needed?) // forward declaration (TODO needed?)
static LRESULT notify(struct table *, UINT, intptr_t, intptr_t, uintptr_t); static LRESULT notify(struct table *, UINT, intptr_t, intptr_t, uintptr_t);
// necessary forward declaration
static void update(struct table *, BOOL);
#include "util.h" #include "util.h"
#include "coord.h" #include "coord.h"
#include "scroll.h" #include "scroll.h"
@ -117,6 +120,7 @@ static LRESULT notify(struct table *, UINT, intptr_t, intptr_t, uintptr_t);
#include "draw.h" #include "draw.h"
#include "api.h" #include "api.h"
#include "accessibility.h" #include "accessibility.h"
#include "update.h"
static const handlerfunc handlers[] = { static const handlerfunc handlers[] = {
eventHandlers, eventHandlers,

View File

@ -3,37 +3,18 @@
// TODO why doesn't this trigger on first show? // TODO why doesn't this trigger on first show?
// TODO see if there's anything not metaphor related in the last bits of the scrollbar series // TODO see if there's anything not metaphor related in the last bits of the scrollbar series
// TODO rename this to boot // TODO rename this to boot
// TODO merge with update.h?
HANDLER(resizeHandler) HANDLER(resizeHandler)
{ {
WINDOWPOS *wp; WINDOWPOS *wp;
RECT client;
intptr_t height;
if (uMsg != WM_WINDOWPOSCHANGED) if (uMsg != WM_WINDOWPOSCHANGED)
return FALSE; return FALSE;
wp = (WINDOWPOS *) lParam; wp = (WINDOWPOS *) lParam;
if ((wp->flags & SWP_NOSIZE) != 0) if ((wp->flags & SWP_NOSIZE) != 0)
return FALSE; return FALSE;
update(t, TRUE);
// TODO does wp store the window rect or the client rect?
if (GetClientRect(t->hwnd, &client) == 0)
panic("error getting Table client rect in resizeHandler()");
// TODO do this after calling updateTableWidth() (which calls repositionHeader()?)?
client.top += t->headerHeight;
// update the width...
// this will call repositionHeader(); there's a good reason... (see comments)
// TODO when I clean that mess up, remove this comment
updateTableWidth(t);
// ...and the height
// TODO find out if order matters
height = client.bottom - client.top;
t->vpagesize = height / rowht(t);
// do a dummy scroll to reflect those changes
vscrollby(t, 0);
*lResult = 0; *lResult = 0;
return TRUE; return TRUE;
} }

View File

@ -117,7 +117,8 @@ int main(int argc, char *argv[])
INITCOMMONCONTROLSEX icc; INITCOMMONCONTROLSEX icc;
WNDCLASSW wc; WNDCLASSW wc;
mkbitmap(); if (argc != 1)
msgfont = TRUE;
ZeroMemory(&icc, sizeof (INITCOMMONCONTROLSEX)); ZeroMemory(&icc, sizeof (INITCOMMONCONTROLSEX));
icc.dwSize = sizeof (INITCOMMONCONTROLSEX); icc.dwSize = sizeof (INITCOMMONCONTROLSEX);
icc.dwICC = ICC_LISTVIEW_CLASSES; icc.dwICC = ICC_LISTVIEW_CLASSES;

44
wintable/update.h Normal file
View File

@ -0,0 +1,44 @@
// 8 january 2015
// Whenever a number of things in the Table changes, the update() function needs to be called to update any metrics and scrolling positions.
// The control font changing is the big one, as that comes with a flag that decides whether or not to redraw everything. We'll need to respect that here.
// TODO actually use redraw here
static void update(struct table *t, int redraw)
{
RECT client;
intptr_t i;
intptr_t height;
// before we do anything we need the client rect
if (GetClientRect(t->hwnd, &client) == 0)
panic("error getting Table client rect in update()");
// the first step is to figure out how wide the whole table is
// TODO count dividers?
t->width = 0;
for (i = 0; i < t->nColumns; i++)
t->width += columnWidth(t, i);
// now we need to figure out how much of the width of the table can be seen at once
t->hpagesize = client.right - client.left;
// this part is critical: if we resize the columns to less than the client area width, then the following hscrollby() will make t->hscrollpos negative, which does very bad things
// we do this regardless of which of the two has changed, just to be safe
if (t->hpagesize > t->width)
t->hpagesize = t->width;
// now we do a dummy horizontal scroll to apply the new width and horizontal page size
// this will also reposition and resize the header (the latter in case the font changed), which will be important for the next step
hscrollby(t, 0);
// now that we have the new height of the header, we can fix up vertical scrolling
// so let's take the header height away from the client area
client.top += t->headerHeight;
// and update our page size appropriately
height = client.bottom - client.top;
t->vpagesize = height / rowht(t);
// and do a dummy vertical scroll to apply that
vscrollby(t, 0);
// TODO invalidate /everything/?
}