2014-03-01 12:29:24 -06:00
// 1 march 2014
2014-03-12 20:55:45 -05:00
2014-03-01 12:29:24 -06:00
package ui
import (
2014-03-01 12:53:29 -06:00
"fmt"
2014-03-01 16:06:06 -06:00
"sync"
2014-03-01 12:29:24 -06:00
)
// #cgo LDFLAGS: -lobjc -framework Foundation -framework AppKit
// #include "objc_darwin.h"
import "C"
type sysData struct {
cSysData
2014-05-10 13:59:11 -05:00
id C . id
trackingArea C . id // for Area
2014-03-01 12:29:24 -06:00
}
type classData struct {
2014-05-10 13:59:11 -05:00
make func ( parentWindow C . id , alternate bool , s * sysData ) C . id
2014-03-30 10:19:13 -05:00
getinside func ( scrollview C . id ) C . id
2014-03-01 12:53:29 -06:00
show func ( what C . id )
hide func ( what C . id )
2014-05-13 06:09:22 -05:00
settext func ( what C . id , text C . id )
text func ( what C . id , alternate bool ) C . id
2014-03-02 16:19:25 -06:00
append func ( id C . id , what string , alternate bool )
2014-03-02 16:44:13 -06:00
insertBefore func ( id C . id , what string , before int , alternate bool )
2014-03-02 17:38:45 -06:00
selIndex func ( id C . id ) int
2014-03-02 22:11:29 -06:00
selIndices func ( id C . id ) [ ] int
selTexts func ( id C . id ) [ ] string
2014-03-02 16:44:13 -06:00
delete func ( id C . id , index int )
2014-03-08 16:25:19 -06:00
len func ( id C . id ) int
2014-04-12 20:49:41 -05:00
selectIndex func ( id C . id , index int , alternate bool )
2014-04-12 21:05:34 -05:00
selectIndices func ( id C . id , indices [ ] int )
2014-03-01 12:29:24 -06:00
}
2014-03-03 14:52:39 -06:00
func addControl ( parentWindow C . id , control C . id ) {
2014-05-12 14:15:26 -05:00
C . addControl ( parentWindow , control )
2014-03-03 14:52:39 -06:00
}
2014-03-01 12:29:24 -06:00
func controlShow ( what C . id ) {
2014-05-12 14:15:26 -05:00
C . controlShow ( what )
2014-03-01 12:29:24 -06:00
}
func controlHide ( what C . id ) {
2014-05-12 14:15:26 -05:00
C . controlHide ( what )
2014-03-01 12:29:24 -06:00
}
2014-05-12 22:55:56 -05:00
// TODO move to objc_darwin.go unless the only thing that uses it is alternate
func toBOOL ( what bool ) C . BOOL {
if what {
return C . YES
}
return C . NO
}
2014-04-05 12:59:11 -05:00
2014-04-05 14:10:02 -05:00
// By default some controls do not use the correct font.
// These functions set the appropriate control font.
// Which one is used on each control was determined by comparing https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/AppleHIGuidelines/Characteristics/Characteristics.html#//apple_ref/doc/uid/TP40002721-SW10 to what Interface Builder says for each control.
// (not applicable to ProgressBar, Area)
// Button, Checkbox, Combobox, LineEdit, Label, Listbox
func applyStandardControlFont ( id C . id ) {
2014-05-12 14:15:26 -05:00
C . applyStandardControlFont ( id )
2014-04-05 14:10:02 -05:00
}
2014-03-01 12:29:24 -06:00
var classTypes = [ nctypes ] * classData {
c_window : & classData {
2014-05-10 13:59:11 -05:00
make : func ( parentWindow C . id , alternate bool , s * sysData ) C . id {
2014-05-12 22:55:56 -05:00
return C . makeWindow ( appDelegate )
2014-03-01 12:29:24 -06:00
} ,
show : func ( what C . id ) {
2014-05-12 14:15:26 -05:00
C . windowShow ( what )
2014-03-01 12:29:24 -06:00
} ,
hide : func ( what C . id ) {
2014-05-12 14:15:26 -05:00
C . windowHide ( what )
2014-03-01 12:29:24 -06:00
} ,
2014-05-13 06:09:22 -05:00
settext : func ( what C . id , text C . id ) {
C . windowSetTitle ( what , text )
} ,
text : func ( what C . id , alternate bool ) C . id {
return C . windowTitle ( what )
} ,
2014-03-01 12:29:24 -06:00
} ,
c_button : & classData {
2014-05-10 13:59:11 -05:00
make : func ( parentWindow C . id , alternate bool , s * sysData ) C . id {
2014-05-12 18:34:13 -05:00
button := C . makeButton ( )
C . buttonSetTargetAction ( button , appDelegate )
2014-04-05 14:10:02 -05:00
applyStandardControlFont ( button )
2014-03-03 14:52:39 -06:00
addControl ( parentWindow , button )
2014-03-01 20:34:37 -06:00
return button
} ,
show : controlShow ,
hide : controlHide ,
2014-05-13 06:09:22 -05:00
settext : func ( what C . id , text C . id ) {
C . buttonSetText ( what , text )
} ,
text : func ( what C . id , alternate bool ) C . id {
return C . buttonText ( what )
} ,
2014-03-01 12:29:24 -06:00
} ,
c_checkbox : & classData {
2014-05-10 13:59:11 -05:00
make : func ( parentWindow C . id , alternate bool , s * sysData ) C . id {
2014-05-12 18:34:13 -05:00
checkbox := C . makeCheckbox ( )
2014-04-05 14:10:02 -05:00
applyStandardControlFont ( checkbox )
2014-03-03 14:52:39 -06:00
addControl ( parentWindow , checkbox )
2014-03-02 08:17:42 -06:00
return checkbox
} ,
show : controlShow ,
hide : controlHide ,
2014-05-13 06:09:22 -05:00
settext : func ( what C . id , text C . id ) {
C . buttonSetText ( what , text )
} ,
text : func ( what C . id , alternate bool ) C . id {
return C . buttonText ( what )
} ,
2014-03-01 12:29:24 -06:00
} ,
c_combobox : & classData {
2014-05-10 13:59:11 -05:00
make : func ( parentWindow C . id , alternate bool , s * sysData ) C . id {
2014-05-12 22:55:56 -05:00
combobox := C . makeCombobox ( toBOOL ( alternate ) )
2014-04-05 14:10:02 -05:00
applyStandardControlFont ( combobox )
2014-03-03 14:52:39 -06:00
addControl ( parentWindow , combobox )
2014-03-02 16:19:25 -06:00
return combobox
} ,
show : controlShow ,
hide : controlHide ,
2014-05-13 06:09:22 -05:00
text : func ( what C . id , alternate bool ) C . id {
return C . comboboxText ( what , toBOOL ( alternate ) )
} ,
2014-03-02 16:19:25 -06:00
append : func ( id C . id , what string , alternate bool ) {
2014-05-12 22:55:56 -05:00
C . comboboxAppend ( id , toBOOL ( alternate ) , toNSString ( what ) )
2014-03-02 16:19:25 -06:00
} ,
2014-03-02 16:44:13 -06:00
insertBefore : func ( id C . id , what string , before int , alternate bool ) {
2014-05-12 22:55:56 -05:00
C . comboboxInsertBefore ( id , toBOOL ( alternate ) ,
toNSString ( what ) , C . intptr_t ( before ) )
2014-03-02 16:44:13 -06:00
} ,
2014-03-02 17:38:45 -06:00
selIndex : func ( id C . id ) int {
2014-05-12 18:34:13 -05:00
return int ( C . comboboxSelectedIndex ( id ) )
2014-03-02 17:38:45 -06:00
} ,
2014-03-02 16:44:13 -06:00
delete : func ( id C . id , index int ) {
2014-05-12 18:34:13 -05:00
C . comboboxDelete ( id , C . intptr_t ( index ) )
2014-03-02 16:44:13 -06:00
} ,
2014-03-08 16:25:19 -06:00
len : func ( id C . id ) int {
2014-05-12 18:34:13 -05:00
return int ( C . comboboxLen ( id ) )
2014-03-08 16:25:19 -06:00
} ,
2014-04-12 20:49:41 -05:00
selectIndex : func ( id C . id , index int , alternate bool ) {
2014-05-12 22:55:56 -05:00
C . comboboxSelectIndex ( id , toBOOL ( alternate ) , C . intptr_t ( index ) )
2014-04-12 20:49:41 -05:00
} ,
2014-03-01 12:29:24 -06:00
} ,
c_lineedit : & classData {
2014-05-10 13:59:11 -05:00
make : func ( parentWindow C . id , alternate bool , s * sysData ) C . id {
2014-05-12 22:55:56 -05:00
lineedit := C . makeLineEdit ( toBOOL ( alternate ) )
2014-04-05 14:10:02 -05:00
applyStandardControlFont ( lineedit )
2014-03-03 14:52:39 -06:00
addControl ( parentWindow , lineedit )
2014-03-02 18:01:34 -06:00
return lineedit
} ,
show : controlShow ,
hide : controlHide ,
2014-05-13 06:09:22 -05:00
settext : func ( what C . id , text C . id ) {
C . lineeditSetText ( what , text )
} ,
text : func ( what C . id , alternate bool ) C . id {
return C . lineeditText ( what )
} ,
2014-03-01 12:29:24 -06:00
} ,
c_label : & classData {
2014-05-10 13:59:11 -05:00
make : func ( parentWindow C . id , alternate bool , s * sysData ) C . id {
2014-05-12 18:34:13 -05:00
label := C . makeLabel ( )
2014-04-05 14:10:02 -05:00
applyStandardControlFont ( label )
2014-03-03 14:52:39 -06:00
addControl ( parentWindow , label )
2014-03-02 18:56:54 -06:00
return label
} ,
show : controlShow ,
hide : controlHide ,
2014-05-13 06:09:22 -05:00
settext : func ( what C . id , text C . id ) {
C . lineeditSetText ( what , text )
} ,
text : func ( what C . id , alternate bool ) C . id {
return C . lineeditText ( what )
} ,
2014-03-01 12:29:24 -06:00
} ,
c_listbox : & classData {
2014-03-02 22:11:29 -06:00
make : makeListbox ,
show : controlShow ,
hide : controlHide ,
append : appendListbox ,
insertBefore : insertListboxBefore ,
selIndices : selectedListboxIndices ,
selTexts : selectedListboxTexts ,
delete : deleteListbox ,
2014-03-08 16:25:19 -06:00
len : listboxLen ,
2014-04-12 21:05:34 -05:00
selectIndices : selectListboxIndices ,
2014-03-01 12:29:24 -06:00
} ,
c_progressbar : & classData {
2014-05-10 13:59:11 -05:00
make : func ( parentWindow C . id , alternate bool , s * sysData ) C . id {
2014-05-12 18:34:13 -05:00
pbar := C . makeProgressBar ( )
2014-03-03 14:52:39 -06:00
addControl ( parentWindow , pbar )
2014-03-03 14:32:54 -06:00
return pbar
} ,
show : controlShow ,
hide : controlHide ,
2014-03-01 12:29:24 -06:00
} ,
2014-03-30 10:19:13 -05:00
c_area : & classData {
make : makeArea ,
getinside : areaInScrollView ,
show : controlShow ,
hide : controlHide ,
} ,
2014-03-01 12:29:24 -06:00
}
2014-03-01 16:06:06 -06:00
// I need to access sysData from appDelegate, but appDelegate doesn't store any data. So, this.
var (
sysdatas = make ( map [ C . id ] * sysData )
sysdatalock sync . Mutex
)
func addSysData ( key C . id , value * sysData ) {
sysdatalock . Lock ( )
sysdatas [ key ] = value
sysdatalock . Unlock ( )
}
func getSysData ( key C . id ) * sysData {
sysdatalock . Lock ( )
defer sysdatalock . Unlock ( )
v , ok := sysdatas [ key ]
if ! ok {
panic ( fmt . Errorf ( "internal error: getSysData(%v) unknown" , key ) )
}
return v
}
2014-04-01 16:05:16 -05:00
func ( s * sysData ) make ( window * sysData ) error {
2014-03-01 12:29:24 -06:00
var parentWindow C . id
ct := classTypes [ s . ctype ]
if window != nil {
parentWindow = window . id
}
ret := make ( chan C . id )
defer close ( ret )
uitask <- func ( ) {
2014-05-10 13:59:11 -05:00
ret <- ct . make ( parentWindow , s . alternate , s )
2014-03-01 12:29:24 -06:00
}
s . id = <- ret
2014-03-30 10:19:13 -05:00
if ct . getinside != nil {
uitask <- func ( ) {
ret <- ct . getinside ( s . id )
}
addSysData ( <- ret , s )
} else {
addSysData ( s . id , s )
}
2014-03-01 12:29:24 -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-03-01 12:29:24 -06:00
ret := make ( chan struct { } )
defer close ( ret )
uitask <- func ( ) {
classTypes [ s . ctype ] . show ( s . id )
ret <- struct { } { }
}
<- ret
}
2014-03-09 20:56:17 -05:00
func ( s * sysData ) hide ( ) {
2014-03-01 12:29:24 -06:00
ret := make ( chan struct { } )
defer close ( ret )
uitask <- func ( ) {
classTypes [ s . ctype ] . hide ( s . id )
ret <- struct { } { }
}
<- ret
}
2014-03-10 09:39:08 -05:00
func ( s * sysData ) setText ( text string ) {
2014-03-01 12:29:24 -06:00
ret := make ( chan struct { } )
defer close ( ret )
uitask <- func ( ) {
2014-05-13 06:09:22 -05:00
classTypes [ s . ctype ] . settext ( s . id , toNSString ( text ) )
2014-03-01 12:29:24 -06:00
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 {
// winheight - y because (0,0) is the bottom-left corner of the window and not the top-left corner
// (winheight - y) - height because (x, y) is the bottom-left corner of the control and not the top-left
2014-05-12 18:34:13 -05:00
C . setRect ( s . id ,
C . intptr_t ( x ) , C . intptr_t ( ( winheight - y ) - height ) ,
C . intptr_t ( width ) , C . intptr_t ( height ) )
2014-03-01 12:29:24 -06:00
return nil
}
func ( s * sysData ) isChecked ( ) bool {
ret := make ( chan bool )
defer close ( ret )
uitask <- func ( ) {
2014-05-12 18:34:13 -05:00
ret <- C . isCheckboxChecked ( s . id ) != C . NO
2014-03-01 12:29:24 -06:00
}
return <- ret
}
func ( s * sysData ) text ( ) string {
ret := make ( chan string )
defer close ( ret )
uitask <- func ( ) {
2014-05-13 06:09:22 -05:00
str := classTypes [ s . ctype ] . text ( s . id , s . alternate )
2014-03-01 12:29:24 -06:00
ret <- fromNSString ( str )
}
return <- ret
}
2014-03-09 15:02:17 -05:00
func ( s * sysData ) append ( what string ) {
2014-03-02 16:19:25 -06:00
ret := make ( chan struct { } )
defer close ( ret )
uitask <- func ( ) {
classTypes [ s . ctype ] . append ( s . id , what , s . alternate )
ret <- struct { } { }
}
<- ret
2014-03-01 12:29:24 -06:00
}
2014-03-09 15:02:17 -05:00
func ( s * sysData ) insertBefore ( what string , before int ) {
2014-03-02 16:44:13 -06:00
ret := make ( chan struct { } )
defer close ( ret )
uitask <- func ( ) {
classTypes [ s . ctype ] . insertBefore ( s . id , what , before , s . alternate )
ret <- struct { } { }
}
<- ret
2014-03-01 12:29:24 -06:00
}
func ( s * sysData ) selectedIndex ( ) int {
2014-03-02 17:38:45 -06:00
ret := make ( chan int )
defer close ( ret )
uitask <- func ( ) {
ret <- classTypes [ s . ctype ] . selIndex ( s . id )
}
return <- ret
2014-03-01 12:29:24 -06:00
}
func ( s * sysData ) selectedIndices ( ) [ ] int {
2014-03-02 22:36:46 -06:00
ret := make ( chan [ ] int )
defer close ( ret )
uitask <- func ( ) {
ret <- classTypes [ s . ctype ] . selIndices ( s . id )
}
return <- ret
2014-03-01 12:29:24 -06:00
}
func ( s * sysData ) selectedTexts ( ) [ ] string {
2014-03-02 22:36:46 -06:00
ret := make ( chan [ ] string )
defer close ( ret )
uitask <- func ( ) {
ret <- classTypes [ s . ctype ] . selTexts ( s . id )
}
return <- ret
2014-03-01 12:29:24 -06:00
}
2014-03-01 12:53:29 -06:00
func ( s * sysData ) setWindowSize ( width int , height int ) error {
2014-03-01 12:29:24 -06:00
ret := make ( chan struct { } )
defer close ( ret )
uitask <- func ( ) {
2014-05-12 18:34:13 -05:00
C . windowSetContentSize ( s . id , C . intptr_t ( width ) , C . intptr_t ( height ) )
2014-03-01 12:29:24 -06:00
ret <- struct { } { }
}
<- ret
return nil
}
2014-03-11 12:50:02 -05:00
func ( s * sysData ) delete ( index int ) {
2014-03-02 16:44:13 -06:00
ret := make ( chan struct { } )
defer close ( ret )
uitask <- func ( ) {
classTypes [ s . ctype ] . delete ( s . id , index )
ret <- struct { } { }
}
<- ret
2014-03-01 12:29:24 -06:00
}
func ( s * sysData ) setProgress ( percent int ) {
2014-03-03 14:32:54 -06:00
ret := make ( chan struct { } )
defer close ( ret )
uitask <- func ( ) {
2014-05-12 18:34:13 -05:00
C . setProgress ( s . id , C . intptr_t ( percent ) )
2014-03-03 14:32:54 -06:00
ret <- struct { } { }
}
<- ret
2014-03-01 12:29:24 -06:00
}
2014-03-08 16:25:19 -06:00
func ( s * sysData ) len ( ) int {
ret := make ( chan int )
defer close ( ret )
uitask <- func ( ) {
ret <- classTypes [ s . ctype ] . len ( s . id )
}
return <- ret
}
2014-03-30 10:19:13 -05:00
func ( s * sysData ) setAreaSize ( width int , height int ) {
ret := make ( chan struct { } )
defer close ( ret )
uitask <- func ( ) {
2014-05-12 18:34:13 -05:00
C . setAreaSize ( s . id , C . intptr_t ( width ) , C . intptr_t ( height ) )
2014-03-30 10:19:13 -05:00
ret <- struct { } { }
}
<- ret
}
2014-04-12 20:49:41 -05:00
func ( s * sysData ) selectIndex ( index int ) {
ret := make ( chan struct { } )
defer close ( ret )
uitask <- func ( ) {
classTypes [ s . ctype ] . selectIndex ( s . id , index , s . alternate )
ret <- struct { } { }
}
<- ret
}
2014-04-12 21:05:34 -05:00
func ( s * sysData ) selectIndices ( indices [ ] int ) {
ret := make ( chan struct { } )
defer close ( ret )
uitask <- func ( ) {
classTypes [ s . ctype ] . selectIndices ( s . id , indices )
ret <- struct { } { }
}
<- ret
}