summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--redo/basicctrls_windows.go96
-rw-r--r--redo/containerctrls_windows.go26
-rw-r--r--redo/control.go45
-rw-r--r--redo/control_windows.go63
-rw-r--r--redo/sizing_windows.go37
-rw-r--r--redo/table_windows.go4
6 files changed, 166 insertions, 105 deletions
diff --git a/redo/basicctrls_windows.go b/redo/basicctrls_windows.go
index ecc1494..138c6a8 100644
--- a/redo/basicctrls_windows.go
+++ b/redo/basicctrls_windows.go
@@ -9,61 +9,21 @@ import (
// #include "winapi_windows.h"
import "C"
-type widgetbase struct {
- hwnd C.HWND
- parent C.HWND
-}
-
-func newWidget(class C.LPCWSTR, style C.DWORD, extstyle C.DWORD) *widgetbase {
- return &widgetbase{
- hwnd: C.newWidget(class, style, extstyle),
- }
-}
-
-// these few methods are embedded by all the various Controls since they all will do the same thing
-
-type controlParent struct {
- hwnd C.HWND
-}
-
-func (w *widgetbase) setParent(win *controlParent) {
- C.controlSetParent(w.hwnd, win.hwnd)
- w.parent = win.hwnd
-}
-
-func (w *widgetbase) containerShow() {
- C.ShowWindow(w.hwnd, C.SW_SHOW)
-}
-
-func (w *widgetbase) containerHide() {
- C.ShowWindow(w.hwnd, C.SW_HIDE)
-}
-
-// don't embed these as exported; let each Control decide if it should
-
-func (w *widgetbase) text() string {
- return getWindowText(w.hwnd)
-}
-
-func (w *widgetbase) settext(text string) {
- C.setWindowText(w.hwnd, toUTF16(text))
-}
-
type button struct {
- *widgetbase
+ *controlbase
clicked *event
}
var buttonclass = toUTF16("BUTTON")
func startNewButton(text string, style C.DWORD) *button {
- w := newWidget(buttonclass,
+ c := newControl(buttonclass,
style | C.WS_TABSTOP,
0)
- C.setWindowText(w.hwnd, toUTF16(text))
- C.controlSetControlFont(w.hwnd)
+ C.setWindowText(c.hwnd, toUTF16(text))
+ C.controlSetControlFont(c.hwnd)
b := &button{
- widgetbase: w,
+ controlbase: c,
clicked: newEvent(),
}
return b
@@ -84,7 +44,7 @@ func (b *button) Text() string {
}
func (b *button) SetText(text string) {
- b.settext(text)
+ b.setText(text)
}
//export buttonClicked
@@ -94,6 +54,8 @@ func buttonClicked(data unsafe.Pointer) {
println("button clicked")
}
+// TODO button preferredSize
+
type checkbox struct {
*button
}
@@ -131,18 +93,18 @@ func checkboxToggled(data unsafe.Pointer) {
}
type textField struct {
- *widgetbase
+ *controlbase
}
var editclass = toUTF16("EDIT")
func startNewTextField(style C.DWORD) *textField {
- w := newWidget(editclass,
+ c := newControl(editclass,
style | C.ES_AUTOHSCROLL | C.ES_LEFT | C.ES_NOHIDESEL | C.WS_TABSTOP,
C.WS_EX_CLIENTEDGE) // WS_EX_CLIENTEDGE without WS_BORDER will show the canonical visual styles border (thanks to MindChild in irc.efnet.net/#winprog)
- C.controlSetControlFont(w.hwnd)
+ C.controlSetControlFont(c.hwnd)
return &textField{
- widgetbase: w,
+ controlbase: c,
}
}
@@ -159,28 +121,31 @@ func (t *textField) Text() string {
}
func (t *textField) SetText(text string) {
- t.settext(text)
+ t.setText(text)
}
type label struct {
- *widgetbase
- standalone bool
+ *controlbase
+ standalone bool
+ supercommitResize func(c *allocation, d *sizing)
}
var labelclass = toUTF16("STATIC")
func finishNewLabel(text string, standalone bool) *label {
- w := newWidget(labelclass,
+ c := newControl(labelclass,
// SS_NOPREFIX avoids accelerator translation; SS_LEFTNOWORDWRAP clips text past the end
// controls are vertically aligned to the top by default (thanks Xeek in irc.freenode.net/#winapi)
C.SS_NOPREFIX | C.SS_LEFTNOWORDWRAP,
0)
- C.setWindowText(w.hwnd, toUTF16(text))
- C.controlSetControlFont(w.hwnd)
+ C.setWindowText(c.hwnd, toUTF16(text))
+ C.controlSetControlFont(c.hwnd)
l := &label{
- widgetbase: w,
+ controlbase: c,
standalone: standalone,
}
+ l.supercommitResize = l.fcommitResize
+ l.fcommitResize = l.labelcommitResize
return l
}
@@ -197,7 +162,20 @@ func (l *label) Text() string {
}
func (l *label) SetText(text string) {
- l.settext(text)
+ l.setText(text)
}
-// TODO label commitResize
+func (l *label) labelcommitResize(c *allocation, d *sizing) {
+// TODO
+/*
+ yoff := stdDlgSizes[s.ctype].yoff
+ if s.standalone {
+ yoff = stdDlgSizes[s.ctype].yoffalt
+ }
+ if yoff != 0 {
+ yoff = int(C.MulDiv(C.int(yoff), C.int(d.baseY), 8))
+ }
+ c.y += yoff
+*/
+ l.supercommitResize(c, d)
+}
diff --git a/redo/containerctrls_windows.go b/redo/containerctrls_windows.go
index cc881e7..e81c340 100644
--- a/redo/containerctrls_windows.go
+++ b/redo/containerctrls_windows.go
@@ -18,24 +18,30 @@ TODO
*/
type tab struct {
- *widgetbase
- tabs []*container
+ *controlbase
+ tabs []*container
+ supersetParent func(p *controlParent)
+ superallocate func(x int, y int, width int, height int, d *sizing) []*allocation
}
func newTab() Tab {
- w := newWidget(C.xWC_TABCONTROL,
+ c := newControl(C.xWC_TABCONTROL,
C.TCS_TOOLTIPS | C.WS_TABSTOP,
0)
t := &tab{
- widgetbase: w,
+ controlbase: c,
}
- C.controlSetControlFont(w.hwnd)
- C.setTabSubclass(w.hwnd, unsafe.Pointer(t))
+ t.supersetParent = t.fsetParent
+ t.fsetParent = t.tabsetParent
+ t.superallocate = t.fallocate
+ t.fallocate = t.taballocate
+ C.controlSetControlFont(t.hwnd)
+ C.setTabSubclass(t.hwnd, unsafe.Pointer(t))
return t
}
-func (t *tab) setParent(p *controlParent) {
- t.widgetbase.setParent(p)
+func (t *tab) tabsetParent(p *controlParent) {
+ t.supersetParent(p)
for _, c := range t.tabs {
c.child.setParent(p)
}
@@ -68,7 +74,7 @@ func tabChanged(data unsafe.Pointer, new C.LRESULT) {
}
// a tab control contains other controls; size appropriately
-func (t *tab) allocate(x int, y int, width int, height int, d *sizing) []*allocation {
+func (t *tab) taballocate(x int, y int, width int, height int, d *sizing) []*allocation {
var r C.RECT
// figure out what the rect for each child is...
@@ -84,5 +90,5 @@ func (t *tab) allocate(x int, y int, width int, height int, d *sizing) []*alloca
c.resize(int(r.left), int(r.top), int(r.right - r.left), int(r.bottom - r.top))
}
// and now allocate the tab control itself
- return t.widgetbase.allocate(x, y, width, height, d)
+ return t.superallocate(x, y, width, height, d)
}
diff --git a/redo/control.go b/redo/control.go
new file mode 100644
index 0000000..bd4ef00
--- /dev/null
+++ b/redo/control.go
@@ -0,0 +1,45 @@
+// 30 july 2014
+
+package ui
+
+// All Controls embed this structure, which provides the Control interface methods.
+// If a Control needs to override one of these functions, it assigns to the function variables.
+type controldefs struct {
+ fsetParent func(p *controlParent)
+ fcontainerShow func()
+ fcontainerHide func()
+ fallocate func(x int, y int, width int, height int, d *sizing) []*allocation
+ fpreferredSize func(*sizing) (int, int)
+ fcommitResize func(*allocation, *sizing)
+ fgetAuxResizeInfo func(*sizing)
+}
+
+// There's no newcontroldefs() function; all defaults are set by controlbase.
+
+func (w *controldefs) setParent(p *controlParent) {
+ w.fsetParent(p)
+}
+
+func (w *controldefs) containerShow() {
+ w.fcontainerShow()
+}
+
+func (w *controldefs) containerHide() {
+ w.fcontainerHide()
+}
+
+func (w *controldefs) allocate(x int, y int, width int, height int, d *sizing) []*allocation {
+ return w.fallocate(x, y, width, height, d)
+}
+
+func (w *controldefs) preferredSize(d *sizing) (int, int) {
+ return w.fpreferredSize(d)
+}
+
+func (w *controldefs) commitResize(c *allocation, d *sizing) {
+ w.fcommitResize(c, d)
+}
+
+func (w *controldefs) getAuxResizeInfo(d *sizing) {
+ w.fgetAuxResizeInfo(d)
+}
diff --git a/redo/control_windows.go b/redo/control_windows.go
new file mode 100644
index 0000000..36f3d4a
--- /dev/null
+++ b/redo/control_windows.go
@@ -0,0 +1,63 @@
+// 30 july 2014
+
+package ui
+
+// #include "winapi_windows.h"
+import "C"
+
+type controlbase struct {
+ *controldefs
+ hwnd C.HWND
+ parent C.HWND // for Tab and Group
+}
+
+type controlParent struct {
+ hwnd C.HWND
+}
+
+func newControl(class C.LPCWSTR, style C.DWORD, extstyle C.DWORD) *controlbase {
+ c := new(controlbase)
+ c.hwnd = C.newWidget(class, style, extstyle)
+ c.controldefs = new(controldefs)
+ c.fsetParent = func(p *controlParent) {
+ C.controlSetParent(c.hwnd, p.hwnd)
+ c.parent = p.hwnd
+ }
+ c.fcontainerShow = func() {
+ C.ShowWindow(c.hwnd, C.SW_SHOW)
+ }
+ c.fcontainerHide = func() {
+ C.ShowWindow(c.hwnd, C.SW_HIDE)
+ }
+ c.fallocate = func(x int, y int, width int, height int, d *sizing) []*allocation {
+ // TODO split into its own function
+ return []*allocation{&allocation{
+ x: x,
+ y: y,
+ width: width,
+ height: height,
+ this: c,
+ }}
+ }
+ c.fpreferredSize = func(d *sizing) (int, int) {
+ // TODO
+ return 75, 23
+ }
+ c.fcommitResize = func(a *allocation, d *sizing) {
+ C.moveWindow(c.hwnd, C.int(a.x), C.int(a.y), C.int(a.width), C.int(a.height))
+ }
+ c.fgetAuxResizeInfo = func(d *sizing) {
+ // do nothing
+ }
+ return c
+}
+
+// these are provided for convenience
+
+func (c *controlbase) text() string {
+ return getWindowText(c.hwnd)
+}
+
+func (c *controlbase) setText(text string) {
+ C.setWindowText(c.hwnd, toUTF16(text))
+}
diff --git a/redo/sizing_windows.go b/redo/sizing_windows.go
index d8f3246..2404aea 100644
--- a/redo/sizing_windows.go
+++ b/redo/sizing_windows.go
@@ -41,37 +41,6 @@ func (c *container) translateAllocationCoords(allocations []*allocation, winwidt
// no translation needed on windows
}
-// TODO move this to sizing.go
-// TODO when doing so, account for margins
-func (w *widgetbase) allocate(x int, y int, width int, height int, d *sizing) []*allocation {
- return []*allocation{&allocation{
- x: x,
- y: y,
- width: width,
- height: height,
- this: w,
- }}
-}
-
-func (w *widgetbase) commitResize(c *allocation, d *sizing) {
-// TODO
-/*
- yoff := stdDlgSizes[s.ctype].yoff
- if s.alternate {
- yoff = stdDlgSizes[s.ctype].yoffalt
- }
- if yoff != 0 {
- yoff = int(C.MulDiv(C.int(yoff), C.int(d.baseY), 8))
- }
- c.y += yoff
-*/
- C.moveWindow(w.hwnd, C.int(c.x), C.int(c.y), C.int(c.width), C.int(c.height))
-}
-
-func (w *widgetbase) getAuxResizeInfo(d *sizing) {
- // do nothing
-}
-
// 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.
@@ -143,7 +112,7 @@ var stdDlgSizes = [nctypes]dlgunits{
}
*/
-func (w *widgetbase) preferredSize(d *sizing) (width int, height int) {
+//func (w *widgetbase) preferredSize(d *sizing) (width int, height int) {
// TODO
/*
// the preferred size of an Area is its size
@@ -174,8 +143,8 @@ func (w *widgetbase) preferredSize(d *sizing) (width int, height int) {
width = int(C.MulDiv(C.int(width), C.int(d.baseX), 4)) // equivalent to right of rect
height = int(C.MulDiv(C.int(height), C.int(d.baseY), 8)) // equivalent to bottom of rect
*/
- return width, height
-}
+// return width, height
+//}
// note on MulDiv():
// div will not be 0 in the usages above
diff --git a/redo/table_windows.go b/redo/table_windows.go
index c3e0453..1453407 100644
--- a/redo/table_windows.go
+++ b/redo/table_windows.go
@@ -12,13 +12,13 @@ import (
import "C"
type table struct {
- *widgetbase
+ *controlbase
*tablebase
}
func finishNewTable(b *tablebase, ty reflect.Type) Table {
t := &table{
- widgetbase: newWidget(C.xWC_LISTVIEW,
+ controlbase: newControl(C.xWC_LISTVIEW,
C.LVS_REPORT | C.LVS_OWNERDATA | C.LVS_NOSORTHEADER | C.LVS_SHOWSELALWAYS | C.WS_HSCROLL | C.WS_VSCROLL,
C.WS_EX_CLIENTEDGE), // WS_EX_CLIENTEDGE without WS_BORDER will show the canonical visual styles border (thanks to MindChild in irc.efnet.net/#winprog)
tablebase: b,