summaryrefslogtreecommitdiff
path: root/wintable/main.h
diff options
context:
space:
mode:
Diffstat (limited to 'wintable/main.h')
-rw-r--r--wintable/main.h172
1 files changed, 172 insertions, 0 deletions
diff --git a/wintable/main.h b/wintable/main.h
new file mode 100644
index 0000000..7199676
--- /dev/null
+++ b/wintable/main.h
@@ -0,0 +1,172 @@
+// 7 january 2015
+
+// TODO
+// - should tablePanic be CALLBACK or some other equivalent macro? and definitely export initTable somehow, but which alias macro to use?
+// - make panic messages grammatically correct ("Table error: adding...")
+// - make access to column widths consistent; see whether HDITEMW.cxy == (ITEMRECT.right - ITEMRECT.left)
+// - make sure all uses of t->headerHeight are ADDED to RECT.top
+// - WM_THEMECHANGED, etc.
+// - see if vertical centering is really what we want or if we just want to offset by a few pixels or so
+// - going right from column 0 to column 2 with the right arrow key deselects
+// - make sure all error messages involving InvalidateRect() are consistent with regards to "redrawing" and "queueing for redraw"
+// - collect all resize-related tasks in a single function (so things like adding columns will refresh everything, not just horizontal scrolls; also would fix initial coordinates)
+// - checkbox columns don't clip to the column width
+
+#define tableWindowClass L"gouitable"
+
+// start at WM_USER + 20 just in case for whatever reason we ever get the various dialog manager messages (see also http://blogs.msdn.com/b/oldnewthing/archive/2003/10/21/55384.aspx)
+enum {
+ // wParam - one of the type constants
+ // lParam - column name as a Unicode string
+ tableAddColumn = WM_USER + 20,
+};
+
+enum {
+ tableColumnText,
+ tableColumnImage,
+ tableColumnCheckbox,
+ nTableColumnTypes,
+};
+
+static void (*tablePanic)(const char *, DWORD) = NULL;
+#define panic(...) (*tablePanic)(__VA_ARGS__, GetLastError())
+#define abort $$$$ // prevent accidental use of abort()
+
+static BOOL (*WINAPI tableTrackMouseEvent)(LPTRACKMOUSEEVENT);
+
+// forward declaration
+struct tableAcc;
+
+struct table {
+ HWND hwnd;
+ HWND header;
+ HFONT font;
+ intptr_t nColumns;
+ int *columnTypes;
+ intptr_t width;
+ intptr_t headerHeight;
+ intptr_t hscrollpos; // in logical units
+ intptr_t hpagesize; // in logical units
+ intptr_t count;
+ intptr_t vscrollpos; // in rows
+ intptr_t vpagesize; // in rows
+ int hwheelCarry;
+ int vwheelCarry;
+ intptr_t selectedRow;
+ intptr_t selectedColumn;
+ HTHEME theme;
+ int checkboxWidth;
+ int checkboxHeight;
+ BOOL checkboxMouseOverLast;
+ LPARAM checkboxMouseOverLastPoint;
+ BOOL checkboxMouseDown;
+ intptr_t checkboxMouseDownRow;
+ intptr_t checkboxMouseDownColumn;
+ struct tableAcc *ta;
+};
+
+#include "util.h"
+#include "coord.h"
+#include "scroll.h"
+#include "hscroll.h"
+#include "vscroll.h"
+#include "select.h"
+#include "checkboxes.h"
+#include "events.h"
+#include "header.h"
+#include "children.h"
+#include "resize.h"
+#include "draw.h"
+#include "api.h"
+#include "accessibility.h"
+
+static const handlerfunc handlers[] = {
+ eventHandlers,
+ childrenHandlers,
+ resizeHandler,
+ drawHandlers,
+ apiHandlers,
+ hscrollHandler,
+ vscrollHandler,
+ accessibilityHandler,
+ NULL,
+};
+
+static void initDummyTableStuff(struct table *t)
+{
+ t->count = 100;
+ t->selectedRow = 2;
+ t->selectedColumn = 1;
+}
+
+static LRESULT CALLBACK tableWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ struct table *t;
+ LRESULT lResult;
+
+ t = (struct table *) GetWindowLongPtrW(hwnd, GWLP_USERDATA);
+ if (t == NULL) {
+ // we have to do things this way because creating the header control will fail mysteriously if we create it first thing
+ // (which is fine; we can get the parent hInstance this way too)
+ // we use WM_CREATE because we have to use WM_DESTROY to destroy the header; we can't do it in WM_NCDESTROY because Windows will have destroyed it for us by then, and let's match message pairs to be safe
+ if (uMsg == WM_CREATE) {
+ CREATESTRUCTW *cs = (CREATESTRUCTW *) lParam;
+
+ t = (struct table *) tableAlloc(sizeof (struct table), "error allocating internal Table data structure");
+ t->hwnd = hwnd;
+ makeHeader(t, cs->hInstance);
+ t->selectedRow = -1;
+ t->selectedColumn = -1;
+ loadCheckboxThemeData(t);
+ t->ta = newTableAcc(t);
+initDummyTableStuff(t);
+ SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) t);
+ }
+ // even if we did the above, fall through
+ return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+ }
+ if (uMsg == WM_DESTROY) {
+printf("destroy\n");
+ // TODO free appropriate (after figuring this part out) components of t
+ // TODO send EVENT_OBJECT_DESTROY events to accessibility listeners (when appropriate); see the note on proxy objects as well
+ freeTableAcc(t->ta);
+ t->ta = NULL;
+ freeCheckboxThemeData(t);
+ destroyHeader(t);
+ tableFree(t, "error allocating internal Table data structure");
+ return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+ }
+ if (runHandlers(handlers, t, uMsg, wParam, lParam, &lResult))
+ return lResult;
+ return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+}
+
+static void deftablePanic(const char *msg, DWORD lastError)
+{
+ fprintf(stderr, "Table error: %s (last error %d)\n", msg, lastError);
+ fprintf(stderr, "This is the default Table error handler function; programs that use Table should provide their own instead.\nThe program will now break into the debugger.\n");
+ DebugBreak();
+}
+
+void initTable(void (*panicfunc)(const char *msg, DWORD lastError), BOOL (*WINAPI tme)(LPTRACKMOUSEEVENT))
+{
+ WNDCLASSW wc;
+
+ tablePanic = panicfunc;
+ if (tablePanic == NULL)
+ tablePanic = deftablePanic;
+ if (tme == NULL)
+ // TODO errorless version
+ panic("must provide a TrackMouseEvent() to initTable()");
+ tableTrackMouseEvent = tme;
+ ZeroMemory(&wc, sizeof (WNDCLASSW));
+ wc.lpszClassName = tableWindowClass;
+ wc.lpfnWndProc = tableWndProc;
+ wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
+ wc.hIcon = LoadIconW(NULL, IDI_APPLICATION);
+ wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); // TODO correct?
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.hInstance = GetModuleHandle(NULL);
+ if (RegisterClassW(&wc) == 0)
+ panic("error registering Table window class");
+}