andlabs-ui/sysdata.go

104 lines
2.4 KiB
Go

// 11 february 2014
package ui
const eventbufsiz = 100 // suggested by skelterjohn
// newEvent returns a new channel suitable for listening for events.
func newEvent() chan struct{} {
return make(chan struct{}, eventbufsiz)
}
// The sysData type contains all system data. It provides the system-specific underlying implementation. It is guaranteed to have the following by embedding:
type cSysData struct {
ctype int
event chan struct{}
resize func(x int, y int, width int, height int, rr *[]resizerequest)
resizes []resizerequest
alternate bool // editable for Combobox, multi-select for listbox, password for lineedit
handler AreaHandler // for Areas
}
// this interface is used to make sure all sysDatas are synced
var _xSysData interface {
make(window *sysData) error
firstShow() error
show()
hide()
setText(text string)
setRect(x int, y int, width int, height int, winheight int) error
isChecked() bool
text() string
append(string)
insertBefore(string, int)
selectedIndex() int
selectedIndices() []int
selectedTexts() []string
setWindowSize(int, int) error
delete(int)
preferredSize() (int, int)
setProgress(int)
len() int
setAreaSize(int, int)
selectIndex(int)
} = &sysData{} // this line will error if there's an inconsistency
// signal sends the event signal. This raise is done asynchronously to avoid deadlocking the UI task.
// Thanks skelterjohn for this techinque: if we can't queue any more events, drop them
func (s *cSysData) signal() {
if s.event != nil {
go func() {
select {
case s.event <- struct{}{}:
default:
}
}()
}
}
const (
c_window = iota
c_button
c_checkbox
c_combobox
c_lineedit
c_label
c_listbox
c_progressbar
c_area
nctypes
)
func mksysdata(ctype int) *sysData {
s := &sysData{
cSysData: cSysData{
ctype: ctype,
},
}
if ctype == c_window { // make resizes non-nil so it can be passed in
s.resizes = make([]resizerequest, 0, 0)
}
return s
}
type resizerequest struct {
sysData *sysData
x int
y int
width int
height int
}
func (s *sysData) doResize(x int, y int, width int, height int, winheight int) {
if s.resize != nil {
s.resizes = s.resizes[0:0] // set len to 0 without changing cap
s.resize(x, y, width, height, &s.resizes)
for _, s := range s.resizes {
err := s.sysData.setRect(s.x, s.y, s.width, s.height, winheight)
if err != nil {
panic("child resize failed: " + err.Error())
}
}
}
}