100 lines
2.0 KiB
Go
100 lines
2.0 KiB
Go
// 6 july 2014
|
|
|
|
package ui
|
|
|
|
import (
|
|
"runtime"
|
|
"sync"
|
|
)
|
|
|
|
// Go initializes package ui.
|
|
// TODO write this bit
|
|
func Go() error {
|
|
runtime.LockOSThread()
|
|
if err := uiinit(); err != nil {
|
|
return err
|
|
}
|
|
uimsgloop()
|
|
return nil
|
|
}
|
|
|
|
// Do performs f on the main loop, as if it were an event handler.
|
|
// It waits for f to execute before returning.
|
|
// Do cannot be called within event handlers or within Do itself.
|
|
func Do(f func()) {
|
|
done := make(chan struct{})
|
|
defer close(done)
|
|
issue(func() {
|
|
f()
|
|
done <- struct{}{}
|
|
})
|
|
<-done
|
|
}
|
|
|
|
// Stop informs package ui that it should stop.
|
|
// Stop then returns immediately.
|
|
// Some time after this request is received, Go() will return without performing any final cleanup.
|
|
// Stop will not have an effect until any event handlers or dialog boxes presently active return.
|
|
// (TODO make sure this is the case for dialog boxes)
|
|
func Stop() {
|
|
issue(uistop)
|
|
}
|
|
|
|
type event struct {
|
|
// All events internally return bool; those that don't will be wrapped around to return a dummy value.
|
|
do func(c Doer) bool
|
|
lock sync.Mutex
|
|
}
|
|
|
|
// do should never be nil; TODO should we make setters panic instead?
|
|
|
|
func newEvent() *event {
|
|
return &event{
|
|
do: func(c Doer) bool {
|
|
return false
|
|
},
|
|
}
|
|
}
|
|
|
|
func (e *event) set(f func(Doer)) {
|
|
e.lock.Lock()
|
|
defer e.lock.Unlock()
|
|
|
|
if f == nil {
|
|
f = func(c Doer) {}
|
|
}
|
|
e.do = func(c Doer) bool {
|
|
f(c)
|
|
return false
|
|
}
|
|
}
|
|
|
|
func (e *event) setbool(f func(Doer) bool) {
|
|
e.lock.Lock()
|
|
defer e.lock.Unlock()
|
|
|
|
if f == nil {
|
|
f = func(c Doer) bool {
|
|
return false
|
|
}
|
|
}
|
|
e.do = f
|
|
}
|
|
|
|
// This is the common code for running an event.
|
|
// It runs on the main thread without a message pump; it provides its own.
|
|
func (e *event) fire() bool {
|
|
e.lock.Lock()
|
|
defer e.lock.Unlock()
|
|
|
|
return e.do(c)
|
|
}
|
|
|
|
// Common code for performing a requested action (ui.Do() or ui.Stop()).
|
|
// This should run on the main thread.
|
|
// Implementations of issue() should call this.
|
|
func perform(fp unsafe.Pointer) {
|
|
f := (*func())(fp)
|
|
(*f)()
|
|
}
|