diff --git a/redo/container_windows.c b/redo/container_windows.c index 5db4548..927e03b 100644 --- a/redo/container_windows.c +++ b/redo/container_windows.c @@ -54,11 +54,8 @@ DWORD makeContainerWindowClass(char **errmsg) wc.hInstance = hInstance; wc.hIcon = hDefaultIcon; wc.hCursor = hArrowCursor; - wc.hbrBackground = (HBRUSH) GetStockObject(HOLLOW_BRUSH); - if (wc.hbrBackground == NULL) { - *errmsg = "error getting hollow brush for container window class"; - return GetLastError(); - } + /* TODO won't this override our visual styles? */ + wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); wc.lpszClassName = containerclass; if (RegisterClassW(&wc) == 0) { *errmsg = "error registering container window class"; diff --git a/redo/container_windows.go b/redo/container_windows.go new file mode 100644 index 0000000..88abd3e --- /dev/null +++ b/redo/container_windows.go @@ -0,0 +1,111 @@ +// 4 august 2014 + +package ui + +import ( + "fmt" + "syscall" + "unsafe" +) + +// #include "winapi_windows.h" +import "C" + +type container struct { + containerbase + hwnd C.HWND +} + +type sizing struct { + sizingbase + + // for size calculations + baseX C.int + baseY C.int + + // for the actual resizing + // possibly the HDWP +} + +func makeContainerWindowClass() error { + var errmsg *C.char + + err := C.makeContainerWindowClass(&errmsg) + if err != 0 || errmsg != nil { + return fmt.Errorf("%s: %v", C.GoString(errmsg), syscall.Errno(err)) + } + return nil +} + +func newContainer(control Control) *container { + c := new(container) + hwnd := C.newContainer(unsafe.Pointer(c)) + if hwnd != c.hwnd { + panic(fmt.Errorf("inconsistency: hwnd returned by CreateWindowEx() (%p) and hwnd stored in container (%p) differ", hwnd, c.hwnd)) + } + c.child = control + c.child.setParent(&controlParent{c.hwnd}) + return c +} + +func (c *container) setParent(p *controlParent) { + C.controlSetParent(c.hwnd, p.hwnd) +} + +//export storeContainerHWND +func storeContainerHWND(data unsafe.Pointer, hwnd C.HWND) { + c := (*container)(data) + c.hwnd = hwnd +} + +//export containerResize +func containerResize(data unsafe.Pointer, r *C.RECT) { + c := (*container)(data) + // the origin of any window's content area is always (0, 0), but let's use the values from the RECT just to be safe + c.resize(int(r.left), int(r.top), int(r.right - r.left), int(r.bottom - r.top)) +} + +// For Windows, Microsoft just hands you a list of preferred control sizes as part of the MSDN documentation and tells you to roll with it. +// These sizes are given in "dialog units", which are independent of the font in use. +// We need to convert these into standard pixels, which requires we get the device context of the OS window. +// References: +// - http://msdn.microsoft.com/en-us/library/ms645502%28VS.85%29.aspx - the calculation needed +// - http://support.microsoft.com/kb/125681 - to get the base X and Y +// (thanks to http://stackoverflow.com/questions/58620/default-button-size) + +// note on MulDiv(): +// div will not be 0 in the usages below +// we also ignore overflow; that isn't likely to happen for our use case anytime soon + +func fromdlgunitsX(du int, d *sizing) int { + return int(C.MulDiv(C.int(du), d.baseX, 4)) +} + +func fromdlgunitsY(du int, d *sizing) int { + return int(C.MulDiv(C.int(du), d.baseY, 8)) +} + +const ( + marginDialogUnits = 7 + paddingDialogUnits = 4 +) + +func (c *container) beginResize() (d *sizing) { + d = new(sizing) + + d.baseX = C.baseX + d.baseY = C.baseY + + if spaced { + d.xmargin = fromdlgunitsX(marginDialogUnits, d) + d.ymargin = fromdlgunitsY(marginDialogUnits, d) + d.xpadding = fromdlgunitsX(paddingDialogUnits, d) + d.ypadding = fromdlgunitsY(paddingDialogUnits, d) + } + + return d +} + +func (c *container) translateAllocationCoords(allocations []*allocation, winwidth, winheight int) { + // no translation needed on windows +} diff --git a/redo/layout_windows.go b/redo/layout_windows.go deleted file mode 100644 index 3010be9..0000000 --- a/redo/layout_windows.go +++ /dev/null @@ -1,61 +0,0 @@ -// 4 august 2014 - -package ui - -// TODO clean this up relative to window_windows.go - -import ( - "fmt" - "unsafe" -) - -// #include "winapi_windows.h" -import "C" - -type layout struct { - hwnd C.HWND - - closing *event - - *sizer -} - -func makeContainerWindowClass() error { - var errmsg *C.char - - err := C.makeContainerWindowClass(&errmsg) - if err != 0 || errmsg != nil { - return fmt.Errorf("%s: %v", C.GoString(errmsg), syscall.Errno(err)) - } - return nil -} - -func newLayout(title string, width int, height int, child C.BOOL, control Control) *layout { - l := &layout{ - sizer: new(sizer), - } - hwnd := C.newContainer(unsafe.Pointer(l)) - if hwnd != l.hwnd { - panic(fmt.Errorf("inconsistency: hwnd returned by CreateWindowEx() (%p) and hwnd stored in container (%p) differ", hwnd, l.hwnd)) - } - l.child = control - l.child.setParent(&controlParent{l.hwnd}) - return l -} - -func (l *layout) setParent(p *controlParent) { - C.controlSetParent(l.hwnd, p.hwnd) -} - -//export storeContainerHWND -func storeContainerHWND(data unsafe.Pointer, hwnd C.HWND) { - l := (*layout)(data) - l.hwnd = hwnd -} - -//export containerResize -func containerResize(data unsafe.Pointer, r *C.RECT) { - l := (*layout)(data) - // the origin of the window's content area is always (0, 0), but let's use the values from the RECT just to be safe - l.resize(int(r.left), int(r.top), int(r.right - r.left), int(r.bottom - r.top)) -} diff --git a/redo/sizer_windows.go b/redo/sizer_windows.go index 554b285..d20a95d 100644 --- a/redo/sizer_windows.go +++ b/redo/sizer_windows.go @@ -2,65 +2,6 @@ package ui -// #include "winapi_windows.h" -import "C" - -// For Windows, Microsoft just hands you a list of preferred control sizes as part of the MSDN documentation and tells you to roll with it. -// These sizes are given in "dialog units", which are independent of the font in use. -// We need to convert these into standard pixels, which requires we get the device context of the OS window. -// References: -// - http://msdn.microsoft.com/en-us/library/ms645502%28VS.85%29.aspx - the calculation needed -// - http://support.microsoft.com/kb/125681 - to get the base X and Y -// (thanks to http://stackoverflow.com/questions/58620/default-button-size) - -type sizing struct { - sizingbase - - // for size calculations - baseX C.int - baseY C.int - - // for the actual resizing - // possibly the HDWP -} - -// note on MulDiv(): -// div will not be 0 in the usages below -// we also ignore overflow; that isn't likely to happen for our use case anytime soon - -func fromdlgunitsX(du int, d *sizing) int { - return int(C.MulDiv(C.int(du), d.baseX, 4)) -} - -func fromdlgunitsY(du int, d *sizing) int { - return int(C.MulDiv(C.int(du), d.baseY, 8)) -} - -const ( - marginDialogUnits = 7 - paddingDialogUnits = 4 -) - -func (s *sizer) beginResize() (d *sizing) { - d = new(sizing) - - d.baseX = C.baseX - d.baseY = C.baseY - - if spaced { - d.xmargin = fromdlgunitsX(marginDialogUnits, d) - d.ymargin = fromdlgunitsY(marginDialogUnits, d) - d.xpadding = fromdlgunitsX(paddingDialogUnits, d) - d.ypadding = fromdlgunitsY(paddingDialogUnits, d) - } - - return d -} - -func (s *sizer) translateAllocationCoords(allocations []*allocation, winwidth, winheight int) { - // no translation needed on windows -} - //TODO /* func (w *widgetbase) preferredSize(d *sizing) (width int, height int) { diff --git a/redo/tab_windows.go b/redo/tab_windows.go index 8e96871..3456502 100644 --- a/redo/tab_windows.go +++ b/redo/tab_windows.go @@ -20,7 +20,7 @@ TODO type tab struct { _hwnd C.HWND - tabs []*layout + tabs []*container parent *controlParent } @@ -37,14 +37,14 @@ func newTab() Tab { } func (t *tab) Append(name string, control Control) { - l := newLayout("", 0, 0, C.TRUE, control) - t.tabs = append(t.tabs, l) + c := newContainer(control) + t.tabs = append(t.tabs, c) if t.parent != nil { - l.setParent(t.parent) + c.setParent(t.parent) } // initially hide tab 1..n controls; if we don't, they'll appear over other tabs, resulting in weird behavior if len(t.tabs) != 1 { - // TODO move these calls to layout itself + // TODO move these calls to container itself C.ShowWindow(t.tabs[len(t.tabs) - 1].hwnd, C.SW_HIDE) } C.tabAppend(t._hwnd, toUTF16(name)) @@ -68,8 +68,8 @@ func (t *tab) hwnd() C.HWND { func (t *tab) setParent(p *controlParent) { basesetParent(t, p) - for _, l := range t.tabs { - l.setParent(p) + for _, c := range t.tabs { + c.setParent(p) } t.parent = p } @@ -104,11 +104,11 @@ func (t *tab) commitResize(c *allocation, d *sizing) { C.tabGetContentRect(t._hwnd, &r) // and resize tabs // don't resize just the current tab; resize all tabs! - for _, l := range t.tabs { + for _, c := range t.tabs { // because each widget is actually a child of the Window, the origin is the one we calculated above // we use moveWindow() rather than calling resize() directly // TODO - C.moveWindow(l.hwnd, C.int(r.left), C.int(r.top), C.int(r.right - r.left), C.int(r.bottom - r.top)) + C.moveWindow(c.hwnd, C.int(r.left), C.int(r.top), C.int(r.right - r.left), C.int(r.bottom - r.top)) } // and now resize the tab control itself basecommitResize(t, c, d) diff --git a/redo/window_windows.go b/redo/window_windows.go index 9cf98d0..ae57e01 100644 --- a/redo/window_windows.go +++ b/redo/window_windows.go @@ -5,6 +5,7 @@ package ui import ( "fmt" "syscall" + "unsafe" ) // #include "winapi_windows.h" @@ -16,7 +17,7 @@ type window struct { closing *event - *layout + *container } func makeWindowWindowClass() error { @@ -33,10 +34,10 @@ func newWindow(title string, width int, height int, control Control) *window { w := &window{ // hwnd set in WM_CREATE handler closing: newEvent(), - layout: newLayout(control), + container: newContainer(control), } hwnd := C.newWindow(toUTF16(title), C.int(width), C.int(height), unsafe.Pointer(w)) - if hwnd != l.hwnd { + if hwnd != w.hwnd { panic(fmt.Errorf("inconsistency: hwnd returned by CreateWindowEx() (%p) and hwnd stored in Window (%p) differ", hwnd, w.hwnd)) } // TODO keep? @@ -44,7 +45,7 @@ func newWindow(title string, width int, height int, control Control) *window { if hresult != C.S_OK { panic(fmt.Errorf("error setting tab background texture on Window; HRESULT: 0x%X", hresult)) } - w.layout.setParent(&controlParent{w.hwnd}) + w.container.setParent(&controlParent{w.hwnd}) return w } @@ -80,7 +81,7 @@ func (w *window) OnClosing(e func() bool) { //export storeWindowHWND func storeWindowHWND(data unsafe.Pointer, hwnd C.HWND) { - w := (*wiindow)(data) + w := (*window)(data) w.hwnd = hwnd } @@ -89,14 +90,14 @@ func windowResize(data unsafe.Pointer, r *C.RECT) { w := (*window)(data) // the origin of the window's content area is always (0, 0), but let's use the values from the RECT just to be safe // TODO - C.moveWindow(w.layout.hwnd, int(r.left), int(r.top), int(r.right - r.left), int(r.bottom - r.top)) + C.moveWindow(w.container.hwnd, C.int(r.left), C.int(r.top), C.int(r.right - r.left), C.int(r.bottom - r.top)) } //export windowClosing func windowClosing(data unsafe.Pointer) { - l := (*layout)(data) - close := l.closing.fire() + w := (*window)(data) + close := w.closing.fire() if close { - C.windowClose(l.hwnd) + C.windowClose(w.hwnd) } }