Started the new recontainerization..
This commit is contained in:
parent
aad6e4c699
commit
eef3e1136b
|
@ -0,0 +1,73 @@
|
||||||
|
// 15 july 2014
|
||||||
|
|
||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// #include "winapi_windows.h"
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
type button struct {
|
||||||
|
*controlSingleHWNDWithText
|
||||||
|
clicked *event
|
||||||
|
}
|
||||||
|
|
||||||
|
var buttonclass = toUTF16("BUTTON")
|
||||||
|
|
||||||
|
func newButton(text string) *button {
|
||||||
|
hwnd := C.newControl(buttonclass,
|
||||||
|
C.BS_PUSHBUTTON|C.WS_TABSTOP,
|
||||||
|
0)
|
||||||
|
b := &button{
|
||||||
|
controlSingleHWNDWithText: newControlSingleHWNDWithText(hwnd),
|
||||||
|
clicked: newEvent(),
|
||||||
|
}
|
||||||
|
b.fpreferredSize = b.preferredSize
|
||||||
|
b.SetText(text)
|
||||||
|
C.controlSetControlFont(b.hwnd)
|
||||||
|
C.setButtonSubclass(b.hwnd, unsafe.Pointer(b))
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *button) OnClicked(e func()) {
|
||||||
|
b.clicked.set(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *button) Text() string {
|
||||||
|
return b.text()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *button) SetText(text string) {
|
||||||
|
b.setText(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export buttonClicked
|
||||||
|
func buttonClicked(data unsafe.Pointer) {
|
||||||
|
b := (*button)(data)
|
||||||
|
b.clicked.fire()
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
|
||||||
|
buttonHeight = 14
|
||||||
|
)
|
||||||
|
|
||||||
|
func (b *button) preferredSize(d *sizing) (width, height int) {
|
||||||
|
return 0,0/*TODO/*
|
||||||
|
// comctl32.dll version 6 thankfully provides a method to grab this...
|
||||||
|
var size C.SIZE
|
||||||
|
|
||||||
|
size.cx = 0 // explicitly ask for ideal size
|
||||||
|
size.cy = 0
|
||||||
|
if C.SendMessageW(b.hwnd, C.BCM_GETIDEALSIZE, 0, C.LPARAM(uintptr(unsafe.Pointer(&size)))) != C.FALSE {
|
||||||
|
return int(size.cx), int(size.cy)
|
||||||
|
}
|
||||||
|
// that failed, fall back
|
||||||
|
println("message failed; falling back")
|
||||||
|
// don't worry about the error return from GetSystemMetrics(); there's no way to tell (explicitly documented as such)
|
||||||
|
xmargins := 2 * int(C.GetSystemMetrics(C.SM_CXEDGE))
|
||||||
|
return xmargins + int(b.textlen), fromdlgunitsY(buttonHeight, d)
|
||||||
|
*/
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
// 30 july 2014
|
||||||
|
|
||||||
|
package ui
|
||||||
|
|
||||||
|
// Control represents a control.
|
||||||
|
type Control interface {
|
||||||
|
setParent(p *controlParent) // controlParent defined per-platform
|
||||||
|
// nChildren() int // TODO
|
||||||
|
preferredSize(d *sizing) (width, height int)
|
||||||
|
resize(x int, y int, width int, height int, d *sizing)
|
||||||
|
}
|
||||||
|
|
||||||
|
type controlbase struct {
|
||||||
|
fsetParent func(p *controlParent)
|
||||||
|
fpreferredSize func(d *sizing) (width, height int)
|
||||||
|
fresize func(x int, y int, width int, height int, d *sizing)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controlbase) setParent(p *controlParent) {
|
||||||
|
c.fsetParent(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controlbase) preferredSize(d *sizing) (width, height int) {
|
||||||
|
return c.fpreferredSize(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controlbase) resize(x int, y int, width int, height int, d *sizing) {
|
||||||
|
c.fresize(x, y, width, height, d)
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
// 30 july 2014
|
||||||
|
|
||||||
|
package ui
|
||||||
|
|
||||||
|
// #include "winapi_windows.h"
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
type controlParent struct {
|
||||||
|
hwnd C.HWND
|
||||||
|
}
|
||||||
|
type sizing struct {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't specify preferredSize in any of these; they're per-control
|
||||||
|
|
||||||
|
type controlSingleHWND struct {
|
||||||
|
*controlbase
|
||||||
|
hwnd C.HWND
|
||||||
|
}
|
||||||
|
|
||||||
|
func newControlSingleHWND(hwnd C.HWND) *controlSingleHWND {
|
||||||
|
c := new(controlSingleHWND)
|
||||||
|
c.controlbase = &controlbase{
|
||||||
|
fsetParent: c.setParent,
|
||||||
|
fresize: c.resize,
|
||||||
|
}
|
||||||
|
c.hwnd = hwnd
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controlSingleHWND) setParent(p *controlParent) {
|
||||||
|
C.controlSetParent(c.hwnd, p.hwnd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controlSingleHWND) resize(x int, y int, width int, height int, d *sizing) {
|
||||||
|
C.moveWindow(c.hwnd, C.int(x), C.int(y), C.int(width), C.int(height))
|
||||||
|
}
|
||||||
|
|
||||||
|
// these are provided for convenience
|
||||||
|
|
||||||
|
type controlSingleHWNDWithText struct {
|
||||||
|
*controlSingleHWND
|
||||||
|
textlen C.LONG
|
||||||
|
}
|
||||||
|
|
||||||
|
func newControlSingleHWNDWithText(h C.HWND) *controlSingleHWNDWithText {
|
||||||
|
return &controlSingleHWNDWithText{
|
||||||
|
controlSingleHWND: newControlSingleHWND(h),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controlSingleHWNDWithText) text() string {
|
||||||
|
return getWindowText(c.hwnd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controlSingleHWNDWithText) setText(text string) {
|
||||||
|
t := toUTF16(text)
|
||||||
|
C.setWindowText(c.hwnd, t)
|
||||||
|
c.textlen = C.controlTextLength(c.hwnd, t)
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
// 12 july 2014
|
||||||
|
|
||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// #include "winapi_windows.h"
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
type window struct {
|
||||||
|
hwnd C.HWND
|
||||||
|
shownbefore bool
|
||||||
|
|
||||||
|
closing *event
|
||||||
|
|
||||||
|
child Control
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeWindowWindowClass() error {
|
||||||
|
var errmsg *C.char
|
||||||
|
|
||||||
|
err := C.makeWindowWindowClass(&errmsg)
|
||||||
|
if err != 0 || errmsg != nil {
|
||||||
|
return fmt.Errorf("%s: %v", C.GoString(errmsg), syscall.Errno(err))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newWindow(title string, width int, height int, control Control) *window {
|
||||||
|
w := &window{
|
||||||
|
// hwnd set in WM_CREATE handler
|
||||||
|
closing: newEvent(),
|
||||||
|
child: control,
|
||||||
|
}
|
||||||
|
hwnd := C.newWindow(toUTF16(title), C.int(width), C.int(height), unsafe.Pointer(w))
|
||||||
|
if hwnd != w.hwnd {
|
||||||
|
panic(fmt.Errorf("inconsistency: hwnd returned by CreateWindowEx() (%p) and hwnd stored in Window (%p) differ", hwnd, w.hwnd))
|
||||||
|
}
|
||||||
|
hresult := C.EnableThemeDialogTexture(w.hwnd, C.ETDT_ENABLE|C.ETDT_USETABTEXTURE)
|
||||||
|
if hresult != C.S_OK {
|
||||||
|
panic(fmt.Errorf("error setting tab background texture on Window; HRESULT: 0x%X", hresult))
|
||||||
|
}
|
||||||
|
w.child.setParent(&controlParent{w.hwnd})
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *window) Title() string {
|
||||||
|
return getWindowText(w.hwnd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *window) SetTitle(title string) {
|
||||||
|
C.setWindowText(w.hwnd, toUTF16(title))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *window) Show() {
|
||||||
|
if !w.shownbefore {
|
||||||
|
C.ShowWindow(w.hwnd, C.nCmdShow)
|
||||||
|
C.updateWindow(w.hwnd)
|
||||||
|
w.shownbefore = true
|
||||||
|
} else {
|
||||||
|
C.ShowWindow(w.hwnd, C.SW_SHOW)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *window) Hide() {
|
||||||
|
C.ShowWindow(w.hwnd, C.SW_HIDE)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *window) Close() {
|
||||||
|
C.windowClose(w.hwnd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *window) OnClosing(e func() bool) {
|
||||||
|
w.closing.setbool(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export storeWindowHWND
|
||||||
|
func storeWindowHWND(data unsafe.Pointer, hwnd C.HWND) {
|
||||||
|
w := (*window)(data)
|
||||||
|
w.hwnd = hwnd
|
||||||
|
}
|
||||||
|
|
||||||
|
//export windowResize
|
||||||
|
func windowResize(data unsafe.Pointer, r *C.RECT) {
|
||||||
|
w := (*window)(data)
|
||||||
|
TODO := &sizing{}
|
||||||
|
w.child.resize(int(r.left), int (r.top), int(r.right - r.left), int(r.bottom - r.top), TODO)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export windowClosing
|
||||||
|
func windowClosing(data unsafe.Pointer) {
|
||||||
|
w := (*window)(data)
|
||||||
|
close := w.closing.fire()
|
||||||
|
if close {
|
||||||
|
C.windowClose(w.hwnd)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
// 14 october 2014
|
||||||
|
|
||||||
|
package ui
|
||||||
|
|
||||||
|
import "flag"
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
var twindow *window
|
||||||
|
|
||||||
|
func maketw(done chan struct{}) {
|
||||||
|
button := newButton("Greet")
|
||||||
|
twindow = newWindow("Hello", 200, 100, button)
|
||||||
|
twindow.OnClosing(func() bool {
|
||||||
|
Stop()
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
twindow.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
// because Cocoa hates being run off the main thread, even if it's run exclusively off the main thread
|
||||||
|
func init() {
|
||||||
|
flag.Parse()
|
||||||
|
go func() {
|
||||||
|
done := make(chan struct{})
|
||||||
|
Do(func() { maketw(done) })
|
||||||
|
<-done
|
||||||
|
}()
|
||||||
|
err := Go()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDummy(t *testing.T) {
|
||||||
|
// do nothing
|
||||||
|
}
|
Loading…
Reference in New Issue