Started dropping the whole request/response system because it fell apart... time to make a ui.Do(func(){ ... })

This commit is contained in:
Pietro Gagliardi 2014-07-19 09:44:32 -04:00
parent 47c0f573a9
commit 48c5055eb9
8 changed files with 202 additions and 460 deletions

View File

@ -16,24 +16,15 @@ type Control interface {
type Button interface {
Control
// OnClicked creates a Request to set the event handler for when the Button is clicked.
OnClicked(func(d Doer)) *Request
// OnClicked sets the event handler for when the Button is clicked.
OnClicked(func())
// Text and SetText creates a Request that get and set the Button's label text.
Text() *Request
SetText(text string) *Request
// Text and SetText get and set the Button's label text.
Text() string
SetText(text string)
}
// NewButton creates a Request to create a new Button with the given label text.
func NewButton(text string) *Request {
// NewButton creates a new Button with the given label text.
func NewButton(text string) {
return newButton(text)
}
// GetNewButton is like NewButton but sends the Request along the given Doer and returns the resultant Button.
// Example:
// b := ui.GetNewButton(ui.Do, "OK")
func GetNewButton(c Doer, text string) Button {
req := newButton(text)
c <- req
return (<-req.resp).(Button)
}

View File

@ -50,32 +50,19 @@ type button struct {
clicked *event
}
func newButton(text string) *Request {
c := make(chan interface{})
return &Request{
op: func() {
ctext := C.CString(text)
defer C.free(unsafe.Pointer(ctext))
b := &button{
widgetbase: newWidget(C.newButton(ctext)),
clicked: newEvent(),
}
C.buttonSetDelegate(b.id, unsafe.Pointer(b))
c <- b
},
resp: c,
func newButton(text string) *button {
ctext := C.CString(text)
defer C.free(unsafe.Pointer(ctext))
b := &button{
widgetbase: newWidget(C.newButton(ctext)),
clicked: newEvent(),
}
C.buttonSetDelegate(b.id, unsafe.Pointer(b))
return b
}
func (b *button) OnClicked(e func(c Doer)) *Request {
c := make(chan interface{})
return &Request{
op: func() {
b.clicked.set(e)
c <- struct{}{}
},
resp: c,
}
func (b *button) OnClicked(e func()) {
b.clicked.set(e)
}
//export buttonClicked
@ -85,25 +72,12 @@ func buttonClicked(xb unsafe.Pointer) {
println("button clicked")
}
func (b *button) Text() *Request {
c := make(chan interface{})
return &Request{
op: func() {
c <- C.GoString(C.buttonText(b.id))
},
resp: c,
}
func (b *button) Text() string {
return C.GoString(C.buttonText(b.id))
}
func (b *button) SetText(text string) *Request {
c := make(chan interface{})
return &Request{
op: func() {
ctext := C.CString(text)
defer C.free(unsafe.Pointer(ctext))
C.buttonSetText(b.id, ctext)
c <- struct{}{}
},
resp: c,
}
func (b *button) SetText(text string) {
ctext := C.CString(text)
defer C.free(unsafe.Pointer(ctext))
C.buttonSetText(b.id, ctext)
}

View File

@ -53,38 +53,25 @@ type button struct {
clicked *event
}
func newButton(text string) *Request {
c := make(chan interface{})
return &Request{
op: func() {
ctext := togstr(text)
defer freegstr(ctext)
widget := C.gtk_button_new_with_label(ctext)
b := &button{
widgetbase: newWidget(widget),
button: (*C.GtkButton)(unsafe.Pointer(widget)),
clicked: newEvent(),
}
g_signal_connect(
C.gpointer(unsafe.Pointer(b.button)),
"clicked",
C.GCallback(C.buttonClicked),
C.gpointer(unsafe.Pointer(b)))
c <- b
},
resp: c,
func newButton(text string) *button {
ctext := togstr(text)
defer freegstr(ctext)
widget := C.gtk_button_new_with_label(ctext)
b := &button{
widgetbase: newWidget(widget),
button: (*C.GtkButton)(unsafe.Pointer(widget)),
clicked: newEvent(),
}
g_signal_connect(
C.gpointer(unsafe.Pointer(b.button)),
"clicked",
C.GCallback(C.buttonClicked),
C.gpointer(unsafe.Pointer(b)))
return b
}
func (b *button) OnClicked(e func(c Doer)) *Request {
c := make(chan interface{})
return &Request{
op: func() {
b.clicked.set(e)
c <- struct{}{}
},
resp: c,
}
func (b *button) OnClicked(e func()) {
b.clicked.set(e)
}
//export buttonClicked
@ -94,25 +81,12 @@ func buttonClicked(bwid *C.GtkButton, data C.gpointer) {
println("button clicked")
}
func (b *button) Text() *Request {
c := make(chan interface{})
return &Request{
op: func() {
c <- fromgstr(C.gtk_button_get_label(b.button))
},
resp: c,
}
func (b *button) Text() string {
return fromgstr(C.gtk_button_get_label(b.button))
}
func (b *button) SetText(text string) *Request {
c := make(chan interface{})
return &Request{
op: func() {
ctext := togstr(text)
defer freegstr(ctext)
C.gtk_button_set_label(b.button, ctext)
c <- struct{}{}
},
resp: c,
}
func (b *button) SetText(text string) {
ctext := togstr(text)
defer freegstr(ctext)
C.gtk_button_set_label(b.button, ctext)
}

View File

@ -31,25 +31,12 @@ func (w *widgetbase) parent(win *window) {
// don't embed these as exported; let each Control decide if it should
func (w *widgetbase) text() *Request {
c := make(chan interface{})
return &Request{
op: func() {
c <- getWindowText(w.hwnd)
},
resp: c,
}
func (w *widgetbase) text() string {
return getWindowText(w.hwnd)
}
func (w *widgetbase) settext(text string) *Request {
c := make(chan interface{})
return &Request{
op: func() {
C.setWindowText(w.hwnd, toUTF16(text))
c <- struct{}{}
},
resp: c,
}
func (w *widgetbase) settext(text string) {
C.setWindowText(w.hwnd, toUTF16(text))
}
type button struct {
@ -59,42 +46,30 @@ type button struct {
var buttonclass = toUTF16("BUTTON")
func newButton(text string) *Request {
c := make(chan interface{})
return &Request{
op: func() {
w := newWidget(buttonclass,
C.BS_PUSHBUTTON | C.WS_TABSTOP,
0)
C.setWindowText(w.hwnd, toUTF16(text))
C.controlSetControlFont(w.hwnd)
b := &button{
widgetbase: w,
clicked: newEvent(),
}
C.setButtonSubclass(w.hwnd, unsafe.Pointer(b))
c <- b
},
resp: c,
func newButton(text string) *button {
op: func() {
w := newWidget(buttonclass,
C.BS_PUSHBUTTON | C.WS_TABSTOP,
0)
C.setWindowText(w.hwnd, toUTF16(text))
C.controlSetControlFont(w.hwnd)
b := &button{
widgetbase: w,
clicked: newEvent(),
}
C.setButtonSubclass(w.hwnd, unsafe.Pointer(b))
return b
}
func (b *button) OnClicked(e func(c Doer)) *Request {
c := make(chan interface{})
return &Request{
op: func() {
b.clicked.set(e)
c <- struct{}{}
},
resp: c,
}
func (b *button) OnClicked(e func()) {
b.clicked.set(e)
}
func (b *button) Text() *Request {
func (b *button) Text() string {
return b.text()
}
func (b *button) SetText(text string) *Request {
func (b *button) SetText(text string) {
return b.settext(text)
}

View File

@ -6,41 +6,32 @@ 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 creates a Request to the Window's child Control.
SetControl(c Control) *Request
// SetControl sets the Window's child Control.
SetControl(c Control)
// Title and SetTitle create Requests to get and set the Window's title, respectively.
Title() *Request
SetTitle(title string) *Request
// Title and SetTitle get and set the Window's title, respectively.
Title() string
SetTitle(title string)
// Show and Hide create Requests to bring the Window on-screen and off-screen, respectively.
Show() *Request
Hide() *Request
// Show and Hide bring the Window on-screen and off-screen, respectively.
Show()
Hide()
// Close creates a Request to close the Window.
// Close closes the Window.
// Any Controls within the Window are destroyed, and the Window itself is also destroyed.
// Attempting to use a Window after it has been closed results in undefined behavior.
// Close unconditionally closes the Window; it neither raises OnClosing nor checks for a return from OnClosing.
// TODO make sure the above happens on GTK+ and Mac OS X; it does on Windows
Close() *Request
Close()
// OnClosing creates a Request to register an event handler that is triggered when the user clicks the Window's close button.
// OnClosing registers an event handler that is triggered when the user clicks the Window's close button.
// On systems where whole applications own windows, OnClosing is also triggered when the user asks to close the application.
// If this handler returns true, the Window is closed as defined by Close above.
// If this handler returns false, the Window is not closed.
OnClosing(func(c Doer) bool) *Request
OnClosing(func() bool)
}
// NewWindow returns a Request to create a new Window with the given title text and size.
func NewWindow(title string, width int, height int) *Request {
// 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)
}
// GetNewWindow is like NewWindow but sends the Request along the given Doer and returns the resultant Window.
// Example:
// w := ui.GetNewWindow(ui.Do, "Main Window")
func GetNewWindow(c Doer, title string, width int, height int) Window {
req := newWindow(title, width, height)
c <- req
return (<-req.resp).(Window)
}

View File

@ -20,106 +20,52 @@ type window struct {
spaced bool
}
func newWindow(title string, width int, height int) *Request {
c := make(chan interface{})
return &Request{
op: func() {
id := C.newWindow(C.intptr_t(width), C.intptr_t(height))
ctitle := C.CString(title)
defer C.free(unsafe.Pointer(ctitle))
C.windowSetTitle(id, ctitle)
w := &window{
id: id,
closing: newEvent(),
}
C.windowSetDelegate(id, unsafe.Pointer(w))
c <- w
},
resp: c,
func newWindow(title string, width int, height int) *window {
id := C.newWindow(C.intptr_t(width), C.intptr_t(height))
ctitle := C.CString(title)
defer C.free(unsafe.Pointer(ctitle))
C.windowSetTitle(id, ctitle)
w := &window{
id: id,
closing: newEvent(),
}
C.windowSetDelegate(id, unsafe.Pointer(w))
return w
}
func (w *window) SetControl(control Control) *Request {
c := make(chan interface{})
return &Request{
op: func() {
if w.child != nil { // unparent existing control
w.child.unparent()
}
control.unparent()
control.parent(w)
w.child = control
c <- struct{}{}
},
resp: c,
func (w *window) SetControl(control Control) {
if w.child != nil { // unparent existing control
w.child.unparent()
}
control.unparent()
control.parent(w)
w.child = control
}
func (w *window) Title() *Request {
c := make(chan interface{})
return &Request{
op: func() {
c <- C.GoString(C.windowTitle(w.id))
},
resp: c,
}
func (w *window) Title() string {
return C.GoString(C.windowTitle(w.id))
}
func (w *window) SetTitle(title string) *Request {
c := make(chan interface{})
return &Request{
op: func() {
ctitle := C.CString(title)
defer C.free(unsafe.Pointer(ctitle))
C.windowSetTitle(w.id, ctitle)
c <- struct{}{}
},
resp: c,
}
func (w *window) SetTitle(title string) {
ctitle := C.CString(title)
defer C.free(unsafe.Pointer(ctitle))
C.windowSetTitle(w.id, ctitle)
}
func (w *window) Show() *Request {
c := make(chan interface{})
return &Request{
op: func() {
C.windowShow(w.id)
c <- struct{}{}
},
resp: c,
}
func (w *window) Show() {
C.windowShow(w.id)
}
func (w *window) Hide() *Request {
c := make(chan interface{})
return &Request{
op: func() {
C.windowHide(w.id)
c <- struct{}{}
},
resp: c,
}
func (w *window) Hide() {
C.windowHide(w.id)
}
func (w *window) Close() *Request {
c := make(chan interface{})
return &Request{
op: func() {
C.windowClose(w.id)
c <- struct{}{}
},
resp: c,
}
func (w *window) Close() {
C.windowClose(w.id)
}
func (w *window) OnClosing(e func(c Doer) bool) *Request {
c := make(chan interface{})
return &Request{
op: func() {
w.closing.setbool(e)
c <- struct{}{}
},
resp: c,
}
func (w *window) OnClosing(e func() bool) {
w.closing.setbool(e)
}
//export windowClosing

View File

@ -30,128 +30,73 @@ type window struct {
spaced bool
}
func newWindow(title string, width int, height int) *Request {
c := make(chan interface{})
return &Request{
op: func() {
widget := C.gtk_window_new(C.GTK_WINDOW_TOPLEVEL)
ctitle := togstr(title)
defer freegstr(ctitle)
layoutw := C.gtk_layout_new(nil, nil)
w := &window{
widget: widget,
container: (*C.GtkContainer)(unsafe.Pointer(widget)),
bin: (*C.GtkBin)(unsafe.Pointer(widget)),
window: (*C.GtkWindow)(unsafe.Pointer(widget)),
layoutc: (*C.GtkContainer)(unsafe.Pointer(layoutw)),
layout: (*C.GtkLayout)(unsafe.Pointer(layoutw)),
closing: newEvent(),
}
C.gtk_window_set_title(w.window, ctitle)
g_signal_connect(
C.gpointer(unsafe.Pointer(w.window)),
"delete-event",
C.GCallback(C.windowClosing),
C.gpointer(unsafe.Pointer(w)))
// we connect to the layout's size-allocate, not to the window's configure-event
// this allows us to handle client-side decoration-based configurations (such as GTK+ on Wayland) properly
// also see commitResize() in sizing_unix.go for additional notes
// thanks to many people in irc.gimp.net/#gtk+ for help (including tristan for suggesting g_signal_connect_after())
g_signal_connect_after(
C.gpointer(unsafe.Pointer(layoutw)),
"size-allocate",
C.GCallback(C.windowResizing),
C.gpointer(unsafe.Pointer(w)))
// TODO size
C.gtk_container_add(w.container, layoutw)
c <- w
},
resp: c,
func newWindow(title string, width int, height int) *window {
widget := C.gtk_window_new(C.GTK_WINDOW_TOPLEVEL)
ctitle := togstr(title)
defer freegstr(ctitle)
layoutw := C.gtk_layout_new(nil, nil)
w := &window{
widget: widget,
container: (*C.GtkContainer)(unsafe.Pointer(widget)),
bin: (*C.GtkBin)(unsafe.Pointer(widget)),
window: (*C.GtkWindow)(unsafe.Pointer(widget)),
layoutc: (*C.GtkContainer)(unsafe.Pointer(layoutw)),
layout: (*C.GtkLayout)(unsafe.Pointer(layoutw)),
closing: newEvent(),
}
C.gtk_window_set_title(w.window, ctitle)
g_signal_connect(
C.gpointer(unsafe.Pointer(w.window)),
"delete-event",
C.GCallback(C.windowClosing),
C.gpointer(unsafe.Pointer(w)))
// we connect to the layout's size-allocate, not to the window's configure-event
// this allows us to handle client-side decoration-based configurations (such as GTK+ on Wayland) properly
// also see commitResize() in sizing_unix.go for additional notes
// thanks to many people in irc.gimp.net/#gtk+ for help (including tristan for suggesting g_signal_connect_after())
g_signal_connect_after(
C.gpointer(unsafe.Pointer(layoutw)),
"size-allocate",
C.GCallback(C.windowResizing),
C.gpointer(unsafe.Pointer(w)))
// TODO size
C.gtk_container_add(w.container, layoutw)
return w
}
func (w *window) SetControl(control Control) *Request {
c := make(chan interface{})
return &Request{
op: func() {
if w.child != nil { // unparent existing control
w.child.unparent()
}
control.unparent()
control.parent(w)
w.child = control
c <- struct{}{}
},
resp: c,
func (w *window) SetControl(control Control) {
if w.child != nil { // unparent existing control
w.child.unparent()
}
control.unparent()
control.parent(w)
w.child = control
}
func (w *window) Title() *Request {
c := make(chan interface{})
return &Request{
op: func() {
c <- fromgstr(C.gtk_window_get_title(w.window))
},
resp: c,
}
func (w *window) Title() string {
return fromgstr(C.gtk_window_get_title(w.window))
}
func (w *window) SetTitle(title string) *Request {
c := make(chan interface{})
return &Request{
op: func() {
ctitle := togstr(title)
defer freegstr(ctitle)
C.gtk_window_set_title(w.window, ctitle)
c <- struct{}{}
},
resp: c,
}
func (w *window) SetTitle(title string) {
ctitle := togstr(title)
defer freegstr(ctitle)
C.gtk_window_set_title(w.window, ctitle)
}
func (w *window) Show() *Request {
c := make(chan interface{})
return &Request{
op: func() {
C.gtk_widget_show_all(w.widget)
c <- struct{}{}
},
resp: c,
}
func (w *window) Show() {
C.gtk_widget_show_all(w.widget)
}
func (w *window) Hide() *Request {
c := make(chan interface{})
return &Request{
op: func() {
C.gtk_widget_hide(w.widget)
c <- struct{}{}
},
resp: c,
}
func (w *window) Hide() {
C.gtk_widget_hide(w.widget)
}
func (w *window) Close() *Request {
c := make(chan interface{})
return &Request{
op: func() {
C.gtk_widget_destroy(w.widget)
c <- struct{}{}
},
resp: c,
}
func (w *window) Close() {
C.gtk_widget_destroy(w.widget)
}
func (w *window) OnClosing(e func(c Doer) bool) *Request {
c := make(chan interface{})
return &Request{
op: func() {
w.closing.setbool(e)
c <- struct{}{}
},
resp: c,
}
func (w *window) OnClosing(e func() bool) {
w.closing.setbool(e)
}
//export windowClosing

View File

@ -35,109 +35,55 @@ func makeWindowWindowClass() error {
return nil
}
func newWindow(title string, width int, height int) *Request {
c := make(chan interface{})
return &Request{
op: func() {
w := &window{
// hwnd set in WM_CREATE handler
closing: newEvent(),
}
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))
}
c <- w
},
resp: c,
func newWindow(title string, width int, height int) *window {
w := &window{
// hwnd set in WM_CREATE handler
closing: newEvent(),
}
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))
}
return w
}
func (w *window) SetControl(control Control) {
if w.child != nil { // unparent existing control
w.child.unparent()
}
control.unparent()
control.parent(w)
w.child = control
}
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) SetControl(control Control) *Request {
c := make(chan interface{})
return &Request{
op: func() {
if w.child != nil { // unparent existing control
w.child.unparent()
}
control.unparent()
control.parent(w)
w.child = control
c <- struct{}{}
},
resp: c,
}
func (w *window) Hide() {
C.ShowWindow(w.hwnd, C.SW_HIDE)
}
func (w *window) Title() *Request {
c := make(chan interface{})
return &Request{
op: func() {
c <- getWindowText(w.hwnd)
},
resp: c,
}
func (w *window) Close() {
C.windowClose(w.hwnd)
}
func (w *window) SetTitle(title string) *Request {
c := make(chan interface{})
return &Request{
op: func() {
C.setWindowText(w.hwnd, toUTF16(title))
c <- struct{}{}
},
resp: c,
}
}
func (w *window) Show() *Request {
c := make(chan interface{})
return &Request{
op: func() {
if !w.shownbefore {
C.ShowWindow(w.hwnd, C.nCmdShow)
C.updateWindow(w.hwnd)
w.shownbefore = true
} else {
C.ShowWindow(w.hwnd, C.SW_SHOW)
}
c <- struct{}{}
},
resp: c,
}
}
func (w *window) Hide() *Request {
c := make(chan interface{})
return &Request{
op: func() {
C.ShowWindow(w.hwnd, C.SW_HIDE)
c <- struct{}{}
},
resp: c,
}
}
func (w *window) Close() *Request {
c := make(chan interface{})
return &Request{
op: func() {
C.windowClose(w.hwnd)
c <- struct{}{}
},
resp: c,
}
}
func (w *window) OnClosing(e func(Doer) bool) *Request {
c := make(chan interface{})
return &Request{
op: func() {
w.closing.setbool(e)
c <- struct{}{}
},
resp: c,
}
func (w *window) OnClosing(e func() bool) {
w.closing.setbool(e)
}
//export storeWindowHWND