summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2014-07-28 20:52:32 -0400
committerPietro Gagliardi <[email protected]>2014-07-28 20:52:32 -0400
commit7cb6ca1243fd12fe942964c3ffbfa6a9bb80caeb (patch)
tree1230d24c4c692feed9125e3e34664ebaeb5ad302
parente2ef204b706b308090d1a1b6f3161458dcb99b0e (diff)
Began the implementation of Table on Windows.
-rw-r--r--redo/comctl32_windows.c8
-rw-r--r--redo/table.go14
-rw-r--r--redo/table_windows.c51
-rw-r--r--redo/table_windows.go39
-rw-r--r--redo/winapi_windows.h6
-rw-r--r--redo/zz_test.go1
6 files changed, 113 insertions, 6 deletions
diff --git a/redo/comctl32_windows.c b/redo/comctl32_windows.c
index 68d58cb..e3e02cf 100644
--- a/redo/comctl32_windows.c
+++ b/redo/comctl32_windows.c
@@ -10,6 +10,12 @@ BOOL (*WINAPI fv_SetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
BOOL (*WINAPI fv_RemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
LRESULT (*WINAPI fv_DefSubclassProc)(HWND, UINT, WPARAM, LPARAM);
+#define wantedICCClasses ( \
+ ICC_PROGRESS_CLASS | /* progress bars */ \
+ ICC_TAB_CLASSES | /* tabs */ \
+ ICC_LISTVIEW_CLASSES | /* list views */ \
+ 0)
+
DWORD initCommonControls(LPCWSTR manifest, char **errmsg)
{
ACTCTX actctx;
@@ -35,7 +41,7 @@ DWORD initCommonControls(LPCWSTR manifest, char **errmsg)
ZeroMemory(&icc, sizeof (INITCOMMONCONTROLSEX));
icc.dwSize = sizeof (INITCOMMONCONTROLSEX);
- icc.dwICC = ICC_PROGRESS_CLASS | ICC_TAB_CLASSES;
+ icc.dwICC = wantedICCClasses;
comctl32 = LoadLibraryW(L"comctl32.dll");
if (comctl32 == NULL) {
diff --git a/redo/table.go b/redo/table.go
index 52024da..7a0e174 100644
--- a/redo/table.go
+++ b/redo/table.go
@@ -13,6 +13,8 @@ import (
// Tables maintain their own storage behind a sync.RWMutex-compatible sync.Locker; use Table.Lock()/Table.Unlock() to make changes and Table.RLock()/Table.RUnlock() to merely read values.
// TODO headers
type Table interface {
+ Control
+
// Lock and Unlock lock and unlock Data for reading or writing.
// RLock and RUnlock lock and unlock Data for reading only.
// These methods have identical semantics to the analogous methods of sync.RWMutex.
@@ -41,16 +43,18 @@ func NewTable(ty reflect.Type) Table {
panic(fmt.Errorf("unknown or unsupported type %v given to NewTable()", ty))
}
b := new(tablebase)
- // arbitrary starting capacity
- b.data = reflect.NewSlice(ty, 0, 512).Addr().Interface()
- return finishNewTable(b)
+ // we want a pointer to a slice
+ b.data = reflect.New(reflect.SliceOf(ty)).Interface()
+ return finishNewTable(b, ty)
}
func (b *tablebase) Lock() {
b.lock.Lock()
}
-func (b *tablebase) Unlock() {
+// Unlock() is defined on each backend implementation of Table
+// they should all call this, however
+func (b *tablebase) unlock() {
b.lock.Unlock()
}
@@ -62,6 +66,6 @@ func (b *tablebase) RUnlock() {
b.lock.RUnlock()
}
-func (b *tablebase) Data() {
+func (b *tablebase) Data() interface{} {
return b.data
}
diff --git a/redo/table_windows.c b/redo/table_windows.c
new file mode 100644
index 0000000..a9039f0
--- /dev/null
+++ b/redo/table_windows.c
@@ -0,0 +1,51 @@
+/* 28 july 2014 */
+
+#include "winapi_windows.h"
+
+/* provided for cgo's benefit */
+LPCWSTR xWC_LISTVIEW = WC_LISTVIEW;
+
+static LRESULT CALLBACK tableSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR id, DWORD_PTR data)
+{
+ switch (uMsg) {
+ case msgCOMMAND:
+ /* TODO */
+ return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam);
+ case msgNOTIFY:
+ /* TODO */
+ return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam);
+ case WM_NCDESTROY:
+ if ((*fv_RemoveWindowSubclass)(hwnd, tableSubProc, id) == FALSE)
+ xpanic("error removing Table subclass (which was for its own event handler)", GetLastError());
+ return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam);
+ default:
+ return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam);
+ }
+ xmissedmsg("Button", "tableSubProc()", uMsg);
+ return 0; /* unreached */
+}
+
+void setTableSubclass(HWND hwnd, void *data)
+{
+ if ((*fv_SetWindowSubclass)(hwnd, tableSubProc, 0, (DWORD_PTR) data) == FALSE)
+ xpanic("error subclassing Table to give it its own event handler", GetLastError());
+}
+
+void tableAppendColumn(HWND hwnd, int index, LPCWSTR name)
+{
+ LVCOLUMNW col;
+
+ ZeroMemory(&col, sizeof (LVCOLUMNW));
+ col.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_ORDER;
+ col.fmt = LVCFMT_LEFT;
+ col.pszText = name;
+ col.iSubItem = index;
+ col.iOrder = index;
+ if (SendMessageW(hwnd, LVM_INSERTCOLUMN, (WPARAM) index, (LPARAM) (&col)) == (LRESULT) -1)
+ xpanic("error adding column to Table", GetLastError());
+}
+
+void tableUpdate(HWND table, int nItems)
+{
+ /* TODO */
+}
diff --git a/redo/table_windows.go b/redo/table_windows.go
new file mode 100644
index 0000000..4711e37
--- /dev/null
+++ b/redo/table_windows.go
@@ -0,0 +1,39 @@
+// 28 july 2014
+
+package ui
+
+import (
+ "unsafe"
+ "reflect"
+)
+
+// #include "winapi_windows.h"
+import "C"
+
+type table struct {
+ *widgetbase
+ *tablebase
+}
+
+func finishNewTable(b *tablebase, ty reflect.Type) Table {
+ t := &table{
+ widgetbase: newWidget(C.xWC_LISTVIEW,
+ C.LVS_REPORT | C.LVS_OWNERDATA | C.LVS_NOSORTHEADER | C.LVS_SHOWSELALWAYS | C.WS_HSCROLL | C.WS_VSCROLL,
+ 0), // TODO WS_EX_CLIENTEDGE?
+ tablebase: b,
+ }
+ C.setTableSubclass(t.hwnd, unsafe.Pointer(&t))
+ for i := 0; i < ty.NumField(); i++ {
+ C.tableAppendColumn(t.hwnd, C.int(i), toUTF16(ty.Field(i).Name))
+ }
+ return t
+}
+
+func (t *table) Unlock() {
+ t.unlock()
+ // TODO RACE CONDITION HERE
+ // I think there's a way to set the item count without causing a refetch of data that works around this...
+ t.RLock()
+ defer t.RUnlock()
+ C.tableUpdate(t.hwnd, C.int(reflect.Indirect(reflect.ValueOf(t.data)).Len()))
+}
diff --git a/redo/winapi_windows.h b/redo/winapi_windows.h
index 0129d37..c8726e7 100644
--- a/redo/winapi_windows.h
+++ b/redo/winapi_windows.h
@@ -87,4 +87,10 @@ extern void setTabSubclass(HWND, void *);
extern void tabAppend(HWND, LPCWSTR);
extern void tabGetContentRect(HWND, RECT *);
+/* table_windows.go */
+extern LPCWSTR xWC_LISTVIEW;
+extern void setTableSubclass(HWND, void *);
+extern void tableAppendColumn(HWND, int, LPCWSTR);
+extern void tableUpdate(HWND, int);
+
#endif
diff --git a/redo/zz_test.go b/redo/zz_test.go
index 327aec2..1d23f35 100644
--- a/redo/zz_test.go
+++ b/redo/zz_test.go
@@ -7,6 +7,7 @@ package ui
import (
"fmt"
"flag"
+ "reflect"
"testing"
)