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:
Pietro Gagliardi 2014-07-25 17:34:45 -04:00
parent d03b8f4b7c
commit 4680e35300
6 changed files with 26 additions and 53 deletions

View File

@ -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))
}

View File

@ -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

View File

@ -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() {

View File

@ -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)
}

View File

@ -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
}

View File

@ -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