2014-02-16 14:55:51 -06:00
|
|
|
// +build !windows,!darwin,!plan9
|
|
|
|
|
|
|
|
// 16 february 2014
|
|
|
|
//package ui
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
)
|
|
|
|
|
|
|
|
type sysData struct {
|
|
|
|
cSysData
|
|
|
|
|
|
|
|
widget *gtkWidget
|
|
|
|
container *gtkWidget // for moving
|
|
|
|
}
|
|
|
|
|
|
|
|
type classData struct {
|
|
|
|
make func() *gtkWidget
|
2014-02-16 18:50:52 -06:00
|
|
|
makeAlt func() *gtkWidget
|
2014-02-16 14:55:51 -06:00
|
|
|
setText func(widget *gtkWidget, text string)
|
2014-02-16 17:57:50 -06:00
|
|
|
text func(widget *gtkWidget) string
|
2014-02-16 18:50:52 -06:00
|
|
|
append func(widget *gtkWidget, text string)
|
|
|
|
insert func(widget *gtkWidget, index int, text string)
|
|
|
|
selected func(widget *gtkWidget) int
|
|
|
|
// ...
|
|
|
|
delete func(widget *gtkWidget, index int)
|
2014-02-16 15:23:49 -06:00
|
|
|
// ...
|
2014-02-16 15:43:48 -06:00
|
|
|
signals map[string]func(*sysData) func() bool
|
2014-02-16 14:55:51 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
var classTypes = [nctypes]*classData{
|
|
|
|
c_window: &classData{
|
|
|
|
make: gtk_window_new,
|
|
|
|
setText: gtk_window_set_title,
|
2014-02-16 17:57:50 -06:00
|
|
|
text: gtk_window_get_title,
|
2014-02-16 15:43:48 -06:00
|
|
|
signals: map[string]func(*sysData) func() bool{
|
|
|
|
"delete-event": func(w *sysData) func() bool {
|
|
|
|
return func() bool {
|
2014-02-16 15:23:49 -06:00
|
|
|
if w.event != nil {
|
|
|
|
w.event <- struct{}{}
|
|
|
|
}
|
|
|
|
return true // do not close the window
|
|
|
|
}
|
|
|
|
},
|
2014-02-16 17:04:57 -06:00
|
|
|
"configure-event": func(w *sysData) func() bool {
|
|
|
|
return func() bool {
|
|
|
|
if w.container != nil && w.resize != nil { // wait for init
|
|
|
|
width, height := gtk_window_get_size(w.widget)
|
|
|
|
// run in another goroutine since this will be called in uitask
|
|
|
|
go func() {
|
|
|
|
w.resize(0, 0, width, height)
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
// TODO really return true?
|
|
|
|
return true // do not continue events; we just did so
|
|
|
|
}
|
|
|
|
},
|
2014-02-16 15:23:49 -06:00
|
|
|
},
|
2014-02-16 14:55:51 -06:00
|
|
|
},
|
|
|
|
c_button: &classData{
|
2014-02-16 16:30:58 -06:00
|
|
|
make: gtk_button_new,
|
|
|
|
setText: gtk_button_set_label,
|
2014-02-16 17:57:50 -06:00
|
|
|
text: gtk_button_get_label,
|
2014-02-16 16:30:58 -06:00
|
|
|
signals: map[string]func(*sysData) func() bool{
|
|
|
|
"clicked": func(w *sysData) func() bool {
|
|
|
|
return func() bool {
|
|
|
|
if w.event != nil {
|
|
|
|
w.event <- struct{}{}
|
|
|
|
}
|
|
|
|
return true // do not close the window
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
2014-02-16 14:55:51 -06:00
|
|
|
},
|
|
|
|
c_checkbox: &classData{
|
2014-02-16 17:41:29 -06:00
|
|
|
make: gtk_check_button_new,
|
|
|
|
setText: gtk_button_set_label,
|
2014-02-16 14:55:51 -06:00
|
|
|
},
|
|
|
|
c_combobox: &classData{
|
2014-02-16 18:50:52 -06:00
|
|
|
make: gtk_combo_box_text_new,
|
|
|
|
makeAlt: gtk_combo_box_text_new_with_entry,
|
|
|
|
// TODO setText
|
|
|
|
text: gtk_combo_box_text_get_active_text,
|
|
|
|
append: gtk_combo_box_text_append_text,
|
|
|
|
insert: gtk_combo_box_text_insert_text,
|
|
|
|
selected: gtk_combo_box_get_active,
|
|
|
|
delete: gtk_combo_box_text_remove,
|
2014-02-16 14:55:51 -06:00
|
|
|
},
|
|
|
|
c_lineedit: &classData{
|
|
|
|
},
|
|
|
|
c_label: &classData{
|
|
|
|
},
|
|
|
|
c_listbox: &classData{
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *sysData) make(initText string, window *sysData) error {
|
|
|
|
ct := classTypes[s.ctype]
|
|
|
|
if ct.make == nil { // not yet implemented
|
|
|
|
println(s.ctype, "not implemented")
|
|
|
|
return nil
|
|
|
|
}
|
2014-02-16 19:09:51 -06:00
|
|
|
if s.alternate && ct.makeAlt == nil { // not yet implemented
|
|
|
|
println(s.ctype, "alt not implemented")
|
|
|
|
return nil
|
|
|
|
}
|
2014-02-16 14:55:51 -06:00
|
|
|
ret := make(chan *gtkWidget)
|
|
|
|
defer close(ret)
|
|
|
|
uitask <- func() {
|
|
|
|
ret <- ct.make()
|
|
|
|
}
|
|
|
|
s.widget = <-ret
|
|
|
|
if window == nil {
|
|
|
|
uitask <- func() {
|
|
|
|
fixed := gtk_fixed_new()
|
|
|
|
gtk_container_add(s.widget, fixed)
|
2014-02-16 17:04:57 -06:00
|
|
|
// TODO return the container before assigning the signals?
|
2014-02-16 15:23:49 -06:00
|
|
|
for signal, generator := range ct.signals {
|
|
|
|
g_signal_connect(s.widget, signal, generator(s))
|
|
|
|
}
|
2014-02-16 14:55:51 -06:00
|
|
|
ret <- fixed
|
|
|
|
}
|
|
|
|
s.container = <-ret
|
|
|
|
} else {
|
|
|
|
s.container = window.container
|
2014-02-16 16:30:58 -06:00
|
|
|
uitask <- func() {
|
|
|
|
gtk_container_add(s.container, s.widget)
|
|
|
|
for signal, generator := range ct.signals {
|
|
|
|
g_signal_connect(s.widget, signal, generator(s))
|
|
|
|
}
|
|
|
|
ret <- nil
|
|
|
|
}
|
|
|
|
<-ret
|
2014-02-16 14:55:51 -06:00
|
|
|
}
|
|
|
|
err := s.setText(initText)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("error setting initial text of new window/control: %v", err)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *sysData) show() error {
|
|
|
|
ret := make(chan struct{})
|
|
|
|
defer close(ret)
|
|
|
|
uitask <- func() {
|
|
|
|
gtk_widget_show(s.widget)
|
|
|
|
ret <- struct{}{}
|
|
|
|
}
|
|
|
|
<-ret
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *sysData) hide() error {
|
|
|
|
ret := make(chan struct{})
|
|
|
|
defer close(ret)
|
|
|
|
uitask <- func() {
|
|
|
|
gtk_widget_hide(s.widget)
|
|
|
|
ret <- struct{}{}
|
|
|
|
}
|
|
|
|
<-ret
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *sysData) setText(text string) error {
|
|
|
|
if classTypes[s.ctype] == nil || classTypes[s.ctype].setText == nil { return nil }
|
|
|
|
ret := make(chan struct{})
|
|
|
|
defer close(ret)
|
|
|
|
uitask <- func() {
|
|
|
|
classTypes[s.ctype].setText(s.widget, text)
|
|
|
|
ret <- struct{}{}
|
|
|
|
}
|
|
|
|
<-ret
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *sysData) setRect(x int, y int, width int, height int) error {
|
2014-02-16 19:07:10 -06:00
|
|
|
if classTypes[s.ctype] == nil || classTypes[s.ctype].make == nil { return nil }
|
2014-02-16 14:55:51 -06:00
|
|
|
ret := make(chan struct{})
|
|
|
|
defer close(ret)
|
|
|
|
uitask <- func() {
|
2014-02-16 16:30:58 -06:00
|
|
|
gtk_fixed_move(s.container, s.widget, x, y)
|
2014-02-16 14:55:51 -06:00
|
|
|
gtk_widget_set_size_request(s.widget, width, height)
|
|
|
|
ret <- struct{}{}
|
|
|
|
}
|
|
|
|
<-ret
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *sysData) isChecked() bool {
|
2014-02-16 17:41:29 -06:00
|
|
|
ret := make(chan bool)
|
|
|
|
defer close(ret)
|
|
|
|
uitask <- func() {
|
|
|
|
ret <- gtk_toggle_button_get_active(s.widget)
|
|
|
|
}
|
|
|
|
return <-ret
|
2014-02-16 14:55:51 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *sysData) text() string {
|
2014-02-16 19:07:10 -06:00
|
|
|
if classTypes[s.ctype] == nil || classTypes[s.ctype].make == nil { println(s.ctype,"unsupported text()"); return "" }
|
2014-02-16 17:57:50 -06:00
|
|
|
ret := make(chan string)
|
|
|
|
defer close(ret)
|
|
|
|
uitask <- func() {
|
|
|
|
ret <- classTypes[s.ctype].text(s.widget)
|
|
|
|
}
|
|
|
|
return <-ret
|
2014-02-16 14:55:51 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *sysData) append(what string) error {
|
2014-02-16 19:07:10 -06:00
|
|
|
if classTypes[s.ctype] == nil || classTypes[s.ctype].make == nil { return nil }
|
2014-02-16 18:50:52 -06:00
|
|
|
ret := make(chan struct{})
|
|
|
|
defer close(ret)
|
|
|
|
uitask <- func() {
|
|
|
|
classTypes[s.ctype].append(s.widget, what)
|
|
|
|
ret <- struct{}{}
|
|
|
|
}
|
|
|
|
<-ret
|
2014-02-16 14:55:51 -06:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *sysData) insertBefore(what string, before int) error {
|
2014-02-16 19:07:10 -06:00
|
|
|
if classTypes[s.ctype] == nil || classTypes[s.ctype].make == nil { return nil }
|
2014-02-16 18:50:52 -06:00
|
|
|
ret := make(chan struct{})
|
|
|
|
defer close(ret)
|
|
|
|
uitask <- func() {
|
|
|
|
classTypes[s.ctype].insert(s.widget, before, what)
|
|
|
|
ret <- struct{}{}
|
|
|
|
}
|
|
|
|
<-ret
|
2014-02-16 14:55:51 -06:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *sysData) selectedIndex() int {
|
2014-02-16 19:07:10 -06:00
|
|
|
if classTypes[s.ctype] == nil || classTypes[s.ctype].make == nil { return -1 }
|
2014-02-16 18:50:52 -06:00
|
|
|
ret := make(chan int)
|
|
|
|
defer close(ret)
|
|
|
|
uitask <- func() {
|
|
|
|
ret <- classTypes[s.ctype].selected(s.widget)
|
|
|
|
}
|
|
|
|
return <-ret
|
2014-02-16 14:55:51 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *sysData) selectedIndices() []int {
|
|
|
|
// TODO
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *sysData) selectedTexts() []string {
|
|
|
|
// TODO
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *sysData) setWindowSize(width int, height int) error {
|
|
|
|
ret := make(chan struct{})
|
|
|
|
defer close(ret)
|
|
|
|
uitask <- func() {
|
|
|
|
gtk_window_resize(s.widget, width, height)
|
|
|
|
ret <- struct{}{}
|
|
|
|
}
|
|
|
|
<-ret
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *sysData) delete(index int) error {
|
2014-02-16 19:07:10 -06:00
|
|
|
if classTypes[s.ctype] == nil || classTypes[s.ctype].make == nil { return nil }
|
2014-02-16 18:50:52 -06:00
|
|
|
ret := make(chan struct{})
|
|
|
|
defer close(ret)
|
|
|
|
uitask <- func() {
|
|
|
|
classTypes[s.ctype].delete(s.widget, index)
|
|
|
|
ret <- struct{}{}
|
|
|
|
}
|
|
|
|
<-ret
|
2014-02-16 14:55:51 -06:00
|
|
|
return nil
|
|
|
|
}
|