2014-02-16 14:55:51 -06:00
// +build !windows,!darwin,!plan9
// 16 february 2014
2014-02-19 10:41:10 -06:00
package ui
2014-02-16 14:55:51 -06:00
import (
2014-03-10 10:06:07 -05:00
// ...
2014-02-16 14:55:51 -06:00
)
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
2014-02-16 22:50:54 -06:00
selMulti func ( widget * gtkWidget ) [ ] int
smtexts func ( widget * gtkWidget ) [ ] string
2014-02-16 18:50:52 -06:00
delete func ( widget * gtkWidget , index int )
2014-03-08 15:42:57 -06:00
len func ( widget * gtkWidget ) 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 {
2014-02-24 23:48:23 -06:00
c_window : & classData {
make : gtk_window_new ,
setText : gtk_window_set_title ,
text : gtk_window_get_title ,
signals : map [ string ] func ( * sysData ) func ( ) bool {
2014-02-18 08:57:19 -06:00
"delete-event" : func ( s * sysData ) func ( ) bool {
2014-02-16 15:43:48 -06:00
return func ( ) bool {
2014-02-18 08:57:19 -06:00
s . signal ( )
2014-02-16 15:23:49 -06:00
return true // do not close the window
}
} ,
2014-02-18 08:57:19 -06:00
"configure-event" : func ( s * sysData ) func ( ) bool {
2014-02-16 17:04:57 -06:00
return func ( ) bool {
2014-02-18 08:57:19 -06:00
if s . container != nil && s . resize != nil { // wait for init
width , height := gtk_window_get_size ( s . widget )
2014-03-03 16:44:03 -06:00
// top-left is (0,0) so no need for winheight
err := s . resize ( 0 , 0 , width , height , 0 )
2014-02-17 00:40:53 -06:00
if err != nil {
panic ( "child resize failed: " + err . Error ( ) )
}
2014-02-16 17:04:57 -06:00
}
2014-02-16 20:50:55 -06:00
// returning false indicates that we continue processing events related to configure-event; if we choose not to, then after some controls have been added, the layout fails completely and everything stays in the starting position/size
2014-02-17 00:40:53 -06:00
// TODO make sure this is the case
2014-02-16 20:50:55 -06:00
return false
2014-02-16 17:04:57 -06:00
}
} ,
2014-02-16 15:23:49 -06:00
} ,
2014-02-16 14:55:51 -06:00
} ,
2014-02-24 23:48:23 -06:00
c_button : & classData {
make : gtk_button_new ,
setText : gtk_button_set_label ,
text : gtk_button_get_label ,
signals : map [ string ] func ( * sysData ) func ( ) bool {
2014-02-18 08:57:19 -06:00
"clicked" : func ( s * sysData ) func ( ) bool {
2014-02-16 16:30:58 -06:00
return func ( ) bool {
2014-02-18 08:57:19 -06:00
s . signal ( )
2014-02-16 16:30:58 -06:00
return true // do not close the window
}
} ,
} ,
2014-02-16 14:55:51 -06:00
} ,
2014-02-24 23:48:23 -06:00
c_checkbox : & classData {
make : gtk_check_button_new ,
setText : gtk_button_set_label ,
2014-03-10 00:19:01 -05:00
text : gtk_button_get_label ,
2014-02-16 14:55:51 -06:00
} ,
2014-02-24 23:48:23 -06:00
c_combobox : & classData {
make : gtk_combo_box_text_new ,
makeAlt : gtk_combo_box_text_new_with_entry ,
2014-02-16 18:50:52 -06:00
// TODO setText
2014-02-24 23:48:23 -06:00
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-03-08 15:42:57 -06:00
len : gtkComboBoxLen ,
2014-02-16 14:55:51 -06:00
} ,
2014-02-24 23:48:23 -06:00
c_lineedit : & classData {
make : gtk_entry_new ,
2014-02-25 14:06:51 -06:00
makeAlt : gtkPasswordEntryNew ,
2014-02-24 23:48:23 -06:00
setText : gtk_entry_set_text ,
text : gtk_entry_get_text ,
2014-02-16 14:55:51 -06:00
} ,
2014-02-24 23:48:23 -06:00
c_label : & classData {
make : gtk_label_new ,
setText : gtk_label_set_text ,
text : gtk_label_get_text ,
2014-02-16 14:55:51 -06:00
} ,
2014-02-24 23:48:23 -06:00
c_listbox : & classData {
make : gListboxNewSingle ,
makeAlt : gListboxNewMulti ,
2014-02-16 22:50:54 -06:00
// TODO setText
2014-02-24 23:48:23 -06:00
text : gListboxText ,
append : gListboxAppend ,
insert : gListboxInsert ,
selMulti : gListboxSelectedMulti ,
smtexts : gListboxSelMultiTexts ,
delete : gListboxDelete ,
2014-03-08 15:42:57 -06:00
len : gListboxLen ,
2014-02-24 23:48:23 -06:00
} ,
c_progressbar : & classData {
make : gtk_progress_bar_new ,
2014-02-16 14:55:51 -06:00
} ,
}
func ( s * sysData ) make ( initText string , window * sysData ) error {
ct := classTypes [ s . ctype ]
ret := make ( chan * gtkWidget )
defer close ( ret )
uitask <- func ( ) {
2014-02-16 19:27:16 -06:00
if s . alternate {
ret <- ct . makeAlt ( )
return
}
2014-02-16 14:55:51 -06:00
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
}
2014-03-10 10:06:07 -05:00
s . setText ( initText )
2014-02-16 14:55:51 -06:00
return nil
}
2014-03-09 20:40:14 -05:00
// used for Windows; nothing special needed elsewhere
func ( s * sysData ) firstShow ( ) error {
s . show ( )
return nil
}
2014-03-09 20:56:17 -05:00
func ( s * sysData ) show ( ) {
2014-02-16 14:55:51 -06:00
ret := make ( chan struct { } )
defer close ( ret )
uitask <- func ( ) {
gtk_widget_show ( s . widget )
ret <- struct { } { }
}
<- ret
}
2014-03-09 20:56:17 -05:00
func ( s * sysData ) hide ( ) {
2014-02-16 14:55:51 -06:00
ret := make ( chan struct { } )
defer close ( ret )
uitask <- func ( ) {
gtk_widget_hide ( s . widget )
ret <- struct { } { }
}
<- ret
}
2014-03-10 09:39:08 -05:00
func ( s * sysData ) setText ( text string ) {
2014-02-16 22:50:54 -06:00
if classTypes [ s . ctype ] . setText == nil { // does not have concept of text
2014-03-10 10:06:07 -05:00
return
2014-02-16 22:50:54 -06:00
}
2014-02-16 14:55:51 -06:00
ret := make ( chan struct { } )
defer close ( ret )
uitask <- func ( ) {
classTypes [ s . ctype ] . setText ( s . widget , text )
ret <- struct { } { }
}
<- ret
}
2014-03-03 16:44:03 -06:00
func ( s * sysData ) setRect ( x int , y int , width int , height int , winheight int ) error {
2014-02-17 00:40:53 -06:00
gtk_fixed_move ( s . container , s . widget , x , y )
gtk_widget_set_size_request ( s . widget , width , height )
2014-02-16 14:55:51 -06:00
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 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
}
2014-03-09 15:02:17 -05:00
func ( s * sysData ) append ( what string ) {
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
}
2014-03-09 15:02:17 -05:00
func ( s * sysData ) insertBefore ( what string , before int ) {
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
}
func ( s * sysData ) selectedIndex ( ) int {
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 {
2014-02-16 22:50:54 -06:00
ret := make ( chan [ ] int )
defer close ( ret )
uitask <- func ( ) {
ret <- classTypes [ s . ctype ] . selMulti ( s . widget )
}
return <- ret
2014-02-16 14:55:51 -06:00
}
func ( s * sysData ) selectedTexts ( ) [ ] string {
2014-02-16 22:50:54 -06:00
ret := make ( chan [ ] string )
defer close ( ret )
uitask <- func ( ) {
ret <- classTypes [ s . ctype ] . smtexts ( s . widget )
}
return <- ret
2014-02-16 14:55:51 -06:00
}
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 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
}
2014-02-24 23:48:23 -06:00
func ( s * sysData ) setProgress ( percent int ) {
ret := make ( chan struct { } )
defer close ( ret )
uitask <- func ( ) {
gtk_progress_bar_set_fraction ( s . widget , percent )
ret <- struct { } { }
}
<- ret
}
2014-03-08 15:42:57 -06:00
func ( s * sysData ) len ( ) int {
ret := make ( chan int )
defer close ( ret )
uitask <- func ( ) {
ret <- classTypes [ s . ctype ] . len ( s . widget )
}
return <- ret
}