Simplified the control nesting model by removing Control.unparent() and requiring all Windows to have a Control at construct time; implemented such on Windows.
This commit is contained in:
parent
d03b8f4b7c
commit
4680e35300
|
@ -20,7 +20,6 @@ TODO
|
||||||
type tab struct {
|
type tab struct {
|
||||||
*widgetbase
|
*widgetbase
|
||||||
tabs []Control
|
tabs []Control
|
||||||
curparent *window
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTab() Tab {
|
func newTab() Tab {
|
||||||
|
@ -35,28 +34,17 @@ func newTab() Tab {
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tab) unparent() {
|
func (t *tab) setParent(win C.HWND) {
|
||||||
t.widgetbase.unparent()
|
t.widgetbase.setParent(win)
|
||||||
for _, c := range t.tabs {
|
for _, c := range t.tabs {
|
||||||
c.unparent()
|
c.setParent(win)
|
||||||
}
|
}
|
||||||
t.curparent = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *tab) parent(win *window) {
|
|
||||||
t.widgetbase.parent(win)
|
|
||||||
for _, c := range t.tabs {
|
|
||||||
c.parent(win)
|
|
||||||
}
|
|
||||||
t.curparent = win
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tab) Append(name string, control Control) {
|
func (t *tab) Append(name string, control Control) {
|
||||||
t.tabs = append(t.tabs, control)
|
t.tabs = append(t.tabs, control)
|
||||||
if t.curparent == nil {
|
if t.parent != nil {
|
||||||
control.unparent()
|
control.setParent(t.parent)
|
||||||
} else {
|
|
||||||
control.parent(t.curparent)
|
|
||||||
}
|
}
|
||||||
C.tabAppend(t.hwnd, toUTF16(name))
|
C.tabAppend(t.hwnd, toUTF16(name))
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,7 @@ package ui
|
||||||
// Control represents a control.
|
// Control represents a control.
|
||||||
// All Controls have event handlers that take a single argument (the Doer active during the event) and return nothing.
|
// All Controls have event handlers that take a single argument (the Doer active during the event) and return nothing.
|
||||||
type Control interface {
|
type Control interface {
|
||||||
unparent()
|
controlParent // platform-specific
|
||||||
parent(*window)
|
|
||||||
// TODO enable/disable (public)
|
// TODO enable/disable (public)
|
||||||
// TODO show/hide (public)
|
// TODO show/hide (public)
|
||||||
containerShow() // for Windows, where all controls need ot belong to an overlapped window, not to a container control; these respect programmer settings
|
containerShow() // for Windows, where all controls need ot belong to an overlapped window, not to a container control; these respect programmer settings
|
||||||
|
|
|
@ -11,6 +11,7 @@ import "C"
|
||||||
|
|
||||||
type widgetbase struct {
|
type widgetbase struct {
|
||||||
hwnd C.HWND
|
hwnd C.HWND
|
||||||
|
parent C.HWND
|
||||||
}
|
}
|
||||||
|
|
||||||
func newWidget(class C.LPCWSTR, style C.DWORD, extstyle C.DWORD) *widgetbase {
|
func newWidget(class C.LPCWSTR, style C.DWORD, extstyle C.DWORD) *widgetbase {
|
||||||
|
@ -21,13 +22,9 @@ func newWidget(class C.LPCWSTR, style C.DWORD, extstyle C.DWORD) *widgetbase {
|
||||||
|
|
||||||
// these few methods are embedded by all the various Controls since they all will do the same thing
|
// these few methods are embedded by all the various Controls since they all will do the same thing
|
||||||
|
|
||||||
func (w *widgetbase) unparent() {
|
func (w *widgetbase) setParent(win C.HWND) {
|
||||||
C.controlSetParent(w.hwnd, C.msgwin)
|
C.controlSetParent(w.hwnd, win)
|
||||||
}
|
w.parent = win
|
||||||
|
|
||||||
func (w *widgetbase) parent(win *window) {
|
|
||||||
C.controlSetParent(w.hwnd, win.hwnd)
|
|
||||||
// TODO new control does not show up until window is resized
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *widgetbase) containerShow() {
|
func (w *widgetbase) containerShow() {
|
||||||
|
|
|
@ -6,9 +6,6 @@ package ui
|
||||||
// Windows in package ui can only contain one control; the Stack and Grid layout Controls allow you to pack multiple Controls in a Window.
|
// Windows in package ui can only contain one control; the Stack and Grid layout Controls allow you to pack multiple Controls in a Window.
|
||||||
// Note that a Window is not itself a Control.
|
// Note that a Window is not itself a Control.
|
||||||
type Window interface {
|
type Window interface {
|
||||||
// SetControl sets the Window's child Control.
|
|
||||||
SetControl(c Control)
|
|
||||||
|
|
||||||
// Title and SetTitle get and set the Window's title, respectively.
|
// Title and SetTitle get and set the Window's title, respectively.
|
||||||
Title() string
|
Title() string
|
||||||
SetTitle(title string)
|
SetTitle(title string)
|
||||||
|
@ -30,20 +27,7 @@ type Window interface {
|
||||||
OnClosing(func() bool)
|
OnClosing(func() bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWindow creates a new Window with the given title text and size.
|
// NewWindow creates a new Window with the given title text, size, and control.
|
||||||
func NewWindow(title string, width int, height int) Window {
|
func NewWindow(title string, width int, height int, control Control) Window {
|
||||||
return newWindow(title, width, height)
|
return newWindow(title, width, height, control)
|
||||||
}
|
|
||||||
|
|
||||||
// everything below is kept here because they're the same on all platforms
|
|
||||||
// TODO move event stuff here and make windowbase
|
|
||||||
|
|
||||||
func (w *window) SetControl(control Control) {
|
|
||||||
if w.child != nil { // unparent existing control
|
|
||||||
w.child.unparent()
|
|
||||||
}
|
|
||||||
control.unparent()
|
|
||||||
control.parent(w)
|
|
||||||
w.child = control
|
|
||||||
// each call to unparent() and parent() will cause the old/new parents to be redrawn; we don't have to worry about that here
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,11 @@ func makeWindowWindowClass() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newWindow(title string, width int, height int) *window {
|
type controlParent interface {
|
||||||
|
setParent(C.HWND)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newWindow(title string, width int, height int, control Control) *window {
|
||||||
w := &window{
|
w := &window{
|
||||||
// hwnd set in WM_CREATE handler
|
// hwnd set in WM_CREATE handler
|
||||||
closing: newEvent(),
|
closing: newEvent(),
|
||||||
|
@ -49,6 +53,8 @@ func newWindow(title string, width int, height int) *window {
|
||||||
if hresult != C.S_OK {
|
if hresult != C.S_OK {
|
||||||
panic(fmt.Errorf("error setting tab background texture on Window; HRESULT: 0x%X", hresult))
|
panic(fmt.Errorf("error setting tab background texture on Window; HRESULT: 0x%X", hresult))
|
||||||
}
|
}
|
||||||
|
w.child = control
|
||||||
|
w.child.setParent(w.hwnd)
|
||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,13 +18,8 @@ func init() {
|
||||||
go func() {
|
go func() {
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
Do(func() {
|
Do(func() {
|
||||||
w := NewWindow("Hello", 320, 240)
|
|
||||||
b := NewButton("There")
|
|
||||||
t := NewTab()
|
t := NewTab()
|
||||||
w.SetControl(t)
|
w := NewWindow("Hello", 320, 240, t)
|
||||||
if *closeOnClick {
|
|
||||||
b.SetText("Click to Close")
|
|
||||||
}
|
|
||||||
w.OnClosing(func() bool {
|
w.OnClosing(func() bool {
|
||||||
if *closeOnClick {
|
if *closeOnClick {
|
||||||
panic("window closed normally in close on click mode (should not happen)")
|
panic("window closed normally in close on click mode (should not happen)")
|
||||||
|
@ -34,6 +29,10 @@ func init() {
|
||||||
done <- struct{}{}
|
done <- struct{}{}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
b := NewButton("There")
|
||||||
|
if *closeOnClick {
|
||||||
|
b.SetText("Click to Close")
|
||||||
|
}
|
||||||
// GTK+ TODO: this is causing a resize event to happen afterward?!
|
// GTK+ TODO: this is causing a resize event to happen afterward?!
|
||||||
b.OnClicked(func() {
|
b.OnClicked(func() {
|
||||||
println("in OnClicked()")
|
println("in OnClicked()")
|
||||||
|
@ -45,10 +44,10 @@ func init() {
|
||||||
})
|
})
|
||||||
t.Append("Button", b)
|
t.Append("Button", b)
|
||||||
c := NewCheckbox("You Should Now See Me Instead")
|
c := NewCheckbox("You Should Now See Me Instead")
|
||||||
t.Append("Checkbox", c)
|
|
||||||
c.OnClicked(func() {
|
c.OnClicked(func() {
|
||||||
w.SetTitle(fmt.Sprint(c.Checked()))
|
w.SetTitle(fmt.Sprint(c.Checked()))
|
||||||
})
|
})
|
||||||
|
t.Append("Checkbox", c)
|
||||||
w.Show()
|
w.Show()
|
||||||
})
|
})
|
||||||
<-done
|
<-done
|
||||||
|
|
Loading…
Reference in New Issue