2014-07-15 21:29:45 -05:00
// 15 july 2014
package ui
import (
2014-07-17 14:10:26 -05:00
"unsafe"
2014-07-15 21:29:45 -05:00
)
2014-07-17 21:16:32 -05:00
// #include "winapi_windows.h"
import "C"
2014-07-15 21:29:45 -05:00
type button struct {
2014-07-30 01:06:01 -05:00
* controlbase
2014-07-17 14:10:26 -05:00
clicked * event
2014-07-15 21:29:45 -05:00
}
2014-07-17 21:16:32 -05:00
var buttonclass = toUTF16 ( "BUTTON" )
2014-07-15 21:29:45 -05:00
2014-07-21 20:34:52 -05:00
func startNewButton ( text string , style C . DWORD ) * button {
2014-07-30 01:06:01 -05:00
c := newControl ( buttonclass ,
2014-07-21 20:34:52 -05:00
style | C . WS_TABSTOP ,
2014-07-19 08:44:32 -05:00
0 )
2014-08-01 18:27:12 -05:00
c . setText ( text )
2014-07-30 01:06:01 -05:00
C . controlSetControlFont ( c . hwnd )
2014-07-19 08:44:32 -05:00
b := & button {
2014-07-30 01:06:01 -05:00
controlbase : c ,
2014-07-19 08:44:32 -05:00
clicked : newEvent ( ) ,
2014-07-15 21:29:45 -05:00
}
2014-07-21 20:34:52 -05:00
return b
}
func newButton ( text string ) * button {
b := startNewButton ( text , C . BS_PUSHBUTTON )
C . setButtonSubclass ( b . hwnd , unsafe . Pointer ( b ) )
2014-08-01 20:30:41 -05:00
b . fpreferredSize = b . buttonpreferredSize
2014-07-19 08:44:32 -05:00
return b
2014-07-15 21:29:45 -05:00
}
2014-07-19 08:44:32 -05:00
func ( b * button ) OnClicked ( e func ( ) ) {
b . clicked . set ( e )
2014-07-15 21:29:45 -05:00
}
2014-07-19 08:44:32 -05:00
func ( b * button ) Text ( ) string {
2014-07-15 21:29:45 -05:00
return b . text ( )
}
2014-07-19 08:44:32 -05:00
func ( b * button ) SetText ( text string ) {
2014-07-30 01:06:01 -05:00
b . setText ( text )
2014-07-15 21:29:45 -05:00
}
2014-07-17 14:10:26 -05:00
2014-07-17 21:16:32 -05:00
//export buttonClicked
func buttonClicked ( data unsafe . Pointer ) {
b := ( * button ) ( data )
b . clicked . fire ( )
println ( "button clicked" )
2014-07-17 14:10:26 -05:00
}
2014-07-21 20:34:52 -05:00
2014-08-01 20:30:41 -05:00
const (
// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
buttonHeight = 14
)
func ( b * button ) buttonpreferredSize ( d * sizing ) ( width , height int ) {
// common controls 6 thankfully provides a method to grab this...
var size C . SIZE
size . cx = 0 // explicitly ask for ideal size
size . cy = 0
if C . SendMessageW ( b . hwnd , C . BCM_GETIDEALSIZE , 0 , C . LPARAM ( uintptr ( unsafe . Pointer ( & size ) ) ) ) != C . FALSE {
return int ( size . cx ) , int ( size . cy )
}
// that failed, fall back
2014-08-01 20:35:56 -05:00
println ( "message failed; falling back" )
2014-08-01 20:30:41 -05:00
// don't worry about the error return from GetSystemMetrics(); there's no way to tell (explicitly documented as such)
xmargins := 2 * int ( C . GetSystemMetrics ( C . SM_CXEDGE ) )
return xmargins + int ( b . textlen ) , fromdlgunitsY ( buttonHeight , d )
}
2014-07-30 01:06:01 -05:00
2014-07-21 20:34:52 -05:00
type checkbox struct {
* button
}
func newCheckbox ( text string ) * checkbox {
c := & checkbox {
// don't use BS_AUTOCHECKBOX here because it creates problems when refocusing (see http://blogs.msdn.com/b/oldnewthing/archive/2014/05/22/10527522.aspx)
// we'll handle actually toggling the check state ourselves (see controls_windows.c)
button : startNewButton ( text , C . BS_CHECKBOX ) ,
}
2014-08-01 19:56:11 -05:00
c . fpreferredSize = c . checkboxpreferredSize
2014-07-21 20:34:52 -05:00
C . setCheckboxSubclass ( c . hwnd , unsafe . Pointer ( c ) )
return c
}
func ( c * checkbox ) Checked ( ) bool {
if C . checkboxChecked ( c . hwnd ) == C . FALSE {
return false
}
return true
}
func ( c * checkbox ) SetChecked ( checked bool ) {
if checked {
C . checkboxSetChecked ( c . hwnd , C . TRUE )
return
}
C . checkboxSetChecked ( c . hwnd , C . FALSE )
}
//export checkboxToggled
func checkboxToggled ( data unsafe . Pointer ) {
c := ( * checkbox ) ( data )
c . clicked . fire ( )
println ( "checkbox toggled" )
}
2014-07-26 05:57:11 -05:00
2014-08-01 19:56:11 -05:00
const (
// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
checkboxHeight = 10
// from http://msdn.microsoft.com/en-us/library/windows/desktop/bb226818%28v=vs.85%29.aspx
checkboxXFromLeftOfBoxToLeftOfLabel = 12
)
func ( c * checkbox ) checkboxpreferredSize ( d * sizing ) ( width , height int ) {
return fromdlgunitsX ( checkboxXFromLeftOfBoxToLeftOfLabel , d ) + int ( c . textlen ) ,
fromdlgunitsY ( checkboxHeight , d )
}
2014-08-01 20:07:49 -05:00
type textField struct {
* controlbase
}
2014-07-26 05:57:11 -05:00
var editclass = toUTF16 ( "EDIT" )
func startNewTextField ( style C . DWORD ) * textField {
2014-07-30 01:06:01 -05:00
c := newControl ( editclass ,
2014-07-28 21:16:45 -05:00
style | C . ES_AUTOHSCROLL | C . ES_LEFT | C . ES_NOHIDESEL | C . WS_TABSTOP ,
C . WS_EX_CLIENTEDGE ) // WS_EX_CLIENTEDGE without WS_BORDER will show the canonical visual styles border (thanks to MindChild in irc.efnet.net/#winprog)
2014-07-30 01:06:01 -05:00
C . controlSetControlFont ( c . hwnd )
2014-08-01 20:07:49 -05:00
t := & textField {
2014-07-30 01:06:01 -05:00
controlbase : c ,
2014-07-26 05:57:11 -05:00
}
2014-08-01 20:07:49 -05:00
t . fpreferredSize = t . textfieldpreferredSize
return t
2014-07-26 05:57:11 -05:00
}
func newTextField ( ) * textField {
return startNewTextField ( 0 )
}
func newPasswordField ( ) * textField {
return startNewTextField ( C . ES_PASSWORD )
}
func ( t * textField ) Text ( ) string {
return t . text ( )
}
func ( t * textField ) SetText ( text string ) {
2014-07-30 01:06:01 -05:00
t . setText ( text )
2014-07-26 05:57:11 -05:00
}
2014-07-29 12:48:31 -05:00
2014-08-01 20:07:49 -05:00
const (
// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
textfieldWidth = 107 // this is actually the shorter progress bar width, but Microsoft only indicates as wide as necessary
textfieldHeight = 14
)
func ( t * textField ) textfieldpreferredSize ( d * sizing ) ( width , height int ) {
return fromdlgunitsX ( textfieldWidth , d ) , fromdlgunitsY ( textfieldHeight , d )
}
2014-07-29 12:48:31 -05:00
type label struct {
2014-07-30 01:06:01 -05:00
* controlbase
standalone bool
supercommitResize func ( c * allocation , d * sizing )
2014-07-29 12:48:31 -05:00
}
var labelclass = toUTF16 ( "STATIC" )
func finishNewLabel ( text string , standalone bool ) * label {
2014-07-30 01:06:01 -05:00
c := newControl ( labelclass ,
2014-07-29 12:48:31 -05:00
// SS_NOPREFIX avoids accelerator translation; SS_LEFTNOWORDWRAP clips text past the end
// controls are vertically aligned to the top by default (thanks Xeek in irc.freenode.net/#winapi)
C . SS_NOPREFIX | C . SS_LEFTNOWORDWRAP ,
0 )
2014-08-01 18:27:12 -05:00
c . setText ( text )
2014-07-30 01:06:01 -05:00
C . controlSetControlFont ( c . hwnd )
2014-07-29 12:48:31 -05:00
l := & label {
2014-07-30 01:06:01 -05:00
controlbase : c ,
2014-07-29 12:48:31 -05:00
standalone : standalone ,
}
2014-08-01 18:32:19 -05:00
l . fpreferredSize = l . labelpreferredSize
2014-07-30 01:06:01 -05:00
l . supercommitResize = l . fcommitResize
l . fcommitResize = l . labelcommitResize
2014-07-29 12:48:31 -05:00
return l
}
func newLabel ( text string ) Label {
return finishNewLabel ( text , false )
}
func newStandaloneLabel ( text string ) Label {
return finishNewLabel ( text , true )
}
func ( l * label ) Text ( ) string {
return l . text ( )
}
func ( l * label ) SetText ( text string ) {
2014-07-30 01:06:01 -05:00
l . setText ( text )
2014-07-29 12:48:31 -05:00
}
2014-08-01 14:11:09 -05:00
const (
// via http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
2014-08-01 18:32:19 -05:00
labelHeight = 8
2014-08-01 14:11:09 -05:00
labelYOffset = 3
// TODO the label is offset slightly by default...
)
2014-08-01 18:32:19 -05:00
func ( l * label ) labelpreferredSize ( d * sizing ) ( width , height int ) {
return int ( l . textlen ) , fromdlgunitsY ( labelHeight , d )
}
2014-07-30 01:06:01 -05:00
func ( l * label ) labelcommitResize ( c * allocation , d * sizing ) {
2014-08-01 14:11:09 -05:00
if ! l . standalone {
2014-08-01 18:24:57 -05:00
yoff := fromdlgunitsY ( labelYOffset , d )
2014-08-01 14:11:09 -05:00
c . y += yoff
c . height -= yoff
2014-07-30 01:06:01 -05:00
}
l . supercommitResize ( c , d )
}