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 {
|
||||
*widgetbase
|
||||
tabs []Control
|
||||
curparent *window
|
||||
}
|
||||
|
||||
func newTab() Tab {
|
||||
|
@ -35,28 +34,17 @@ func newTab() Tab {
|
|||
return t
|
||||
}
|
||||
|
||||
func (t *tab) unparent() {
|
||||
t.widgetbase.unparent()
|
||||
func (t *tab) setParent(win C.HWND) {
|
||||
t.widgetbase.setParent(win)
|
||||
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) {
|
||||
t.tabs = append(t.tabs, control)
|
||||
if t.curparent == nil {
|
||||
control.unparent()
|
||||
} else {
|
||||
control.parent(t.curparent)
|
||||
if t.parent != nil {
|
||||
control.setParent(t.parent)
|
||||
}
|
||||
C.tabAppend(t.hwnd, toUTF16(name))
|
||||
}
|
||||
|
|
|
@ -5,8 +5,7 @@ package ui
|
|||
// Control represents a control.
|
||||
// All Controls have event handlers that take a single argument (the Doer active during the event) and return nothing.
|
||||
type Control interface {
|
||||
unparent()
|
||||
parent(*window)
|
||||
controlParent // platform-specific
|
||||
// TODO enable/disable (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
|
||||
|
|
|
@ -11,6 +11,7 @@ import "C"
|
|||
|
||||
type widgetbase struct {
|
||||
hwnd C.HWND
|
||||
parent C.HWND
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
func (w *widgetbase) unparent() {
|
||||
C.controlSetParent(w.hwnd, C.msgwin)
|
||||
}
|
||||
|
||||
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) setParent(win C.HWND) {
|
||||
C.controlSetParent(w.hwnd, win)
|
||||
w.parent = win
|
||||
}
|
||||
|
||||
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.
|
||||
// Note that a Window is not itself a Control.
|
||||
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() string
|
||||
SetTitle(title string)
|
||||
|
@ -30,20 +27,7 @@ type Window interface {
|
|||
OnClosing(func() bool)
|
||||
}
|
||||
|
||||
// NewWindow creates a new Window with the given title text and size.
|
||||
func NewWindow(title string, width int, height int) Window {
|
||||
return newWindow(title, width, height)
|
||||
}
|
||||
|
||||
// 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
|
||||
// NewWindow creates a new Window with the given title text, size, and control.
|
||||
func NewWindow(title string, width int, height int, control Control) Window {
|
||||
return newWindow(title, width, height, control)
|
||||
}
|
||||
|
|
|
@ -35,7 +35,11 @@ func makeWindowWindowClass() error {
|
|||
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{
|
||||
// hwnd set in WM_CREATE handler
|
||||
closing: newEvent(),
|
||||
|
@ -49,6 +53,8 @@ func newWindow(title string, width int, height int) *window {
|
|||
if hresult != C.S_OK {
|
||||
panic(fmt.Errorf("error setting tab background texture on Window; HRESULT: 0x%X", hresult))
|
||||
}
|
||||
w.child = control
|
||||
w.child.setParent(w.hwnd)
|
||||
return w
|
||||
}
|
||||
|
||||
|
|
|
@ -18,13 +18,8 @@ func init() {
|
|||
go func() {
|
||||
done := make(chan struct{})
|
||||
Do(func() {
|
||||
w := NewWindow("Hello", 320, 240)
|
||||
b := NewButton("There")
|
||||
t := NewTab()
|
||||
w.SetControl(t)
|
||||
if *closeOnClick {
|
||||
b.SetText("Click to Close")
|
||||
}
|
||||
w := NewWindow("Hello", 320, 240, t)
|
||||
w.OnClosing(func() bool {
|
||||
if *closeOnClick {
|
||||
panic("window closed normally in close on click mode (should not happen)")
|
||||
|
@ -34,6 +29,10 @@ func init() {
|
|||
done <- struct{}{}
|
||||
return true
|
||||
})
|
||||
b := NewButton("There")
|
||||
if *closeOnClick {
|
||||
b.SetText("Click to Close")
|
||||
}
|
||||
// GTK+ TODO: this is causing a resize event to happen afterward?!
|
||||
b.OnClicked(func() {
|
||||
println("in OnClicked()")
|
||||
|
@ -45,10 +44,10 @@ func init() {
|
|||
})
|
||||
t.Append("Button", b)
|
||||
c := NewCheckbox("You Should Now See Me Instead")
|
||||
t.Append("Checkbox", c)
|
||||
c.OnClicked(func() {
|
||||
w.SetTitle(fmt.Sprint(c.Checked()))
|
||||
})
|
||||
t.Append("Checkbox", c)
|
||||
w.Show()
|
||||
})
|
||||
<-done
|
||||
|
|
Loading…
Reference in New Issue