2014-07-28 19:52:32 -05:00
// 28 july 2014
package ui
import (
2014-07-28 22:29:06 -05:00
"fmt"
2014-07-28 19:52:32 -05:00
"unsafe"
"reflect"
)
// #include "winapi_windows.h"
import "C"
type table struct {
* tablebase
2014-08-03 20:52:21 -05:00
_hwnd C . HWND
2014-08-06 09:42:26 -05:00
noautosize bool
colcount C . int
2014-07-28 19:52:32 -05:00
}
func finishNewTable ( b * tablebase , ty reflect . Type ) Table {
t := & table {
2014-08-03 20:52:21 -05:00
_hwnd : C . newControl ( C . xWC_LISTVIEW ,
2014-08-13 21:38:39 -05:00
C . LVS_REPORT | C . LVS_OWNERDATA | C . LVS_NOSORTHEADER | C . LVS_SHOWSELALWAYS | C . WS_HSCROLL | C . WS_VSCROLL | C . WS_TABSTOP ,
2014-07-28 21:16:45 -05:00
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-28 19:52:32 -05:00
tablebase : b ,
}
2014-08-03 20:52:21 -05:00
C . setTableSubclass ( t . _hwnd , unsafe . Pointer ( t ) )
2014-07-28 22:47:45 -05:00
// LVS_EX_FULLROWSELECT gives us selection across the whole row, not just the leftmost column; this makes the list view work like on other platforms
// LVS_EX_SUBITEMIMAGES gives us images in subitems, which will be important when both images and checkboxes are added
2014-08-03 20:52:21 -05:00
C . tableAddExtendedStyles ( t . _hwnd , C . LVS_EX_FULLROWSELECT | C . LVS_EX_SUBITEMIMAGES )
2014-07-28 19:52:32 -05:00
for i := 0 ; i < ty . NumField ( ) ; i ++ {
2014-08-03 20:52:21 -05:00
C . tableAppendColumn ( t . _hwnd , C . int ( i ) , toUTF16 ( ty . Field ( i ) . Name ) )
2014-07-28 19:52:32 -05:00
}
2014-08-06 09:42:26 -05:00
t . colcount = C . int ( ty . NumField ( ) )
2014-07-28 19:52:32 -05:00
return t
}
func ( t * table ) Unlock ( ) {
t . unlock ( )
2014-08-11 18:38:21 -05:00
// there's a possibility that user actions can happen at this point, before the view is updated
// alas, this is something we have to deal with, because Unlock() can be called from any thread
go func ( ) {
Do ( func ( ) {
t . RLock ( )
defer t . RUnlock ( )
C . tableUpdate ( t . _hwnd , C . int ( reflect . Indirect ( reflect . ValueOf ( t . data ) ) . Len ( ) ) )
} )
} ( )
2014-07-28 19:52:32 -05:00
}
2014-07-28 22:29:06 -05:00
2014-08-16 16:37:21 -05:00
func ( t * table ) LoadImageList ( il ImageList ) {
il . apply ( t . _hwnd , C . LVM_SETIMAGELIST , C . LVSIL_SMALL )
}
//export tableGetCell
func tableGetCell ( data unsafe . Pointer , item * C . LVITEMW ) {
2014-07-28 22:29:06 -05:00
t := ( * table ) ( data )
t . RLock ( )
defer t . RUnlock ( )
d := reflect . Indirect ( reflect . ValueOf ( t . data ) )
2014-08-16 16:37:21 -05:00
datum := d . Index ( int ( item . iItem ) ) . Field ( int ( item . iSubItem ) )
2014-08-16 17:33:51 -05:00
// TODO figure out why changing item.mask causes crashes or why "it just works"
2014-08-16 16:37:21 -05:00
switch d := datum . Interface ( ) . ( type ) {
case ImageIndex :
item . iImage = C . int ( d )
default :
s := fmt . Sprintf ( "%v" , datum )
item . pszText = toUTF16 ( s )
}
2014-07-28 22:29:06 -05:00
}
2014-08-03 08:18:35 -05:00
2014-08-14 08:20:20 -05:00
// the column autoresize policy is simple:
// on every table.commitResize() call, if the columns have not been resized by the user, autoresize
func ( t * table ) autoresize ( ) {
t . RLock ( )
defer t . RUnlock ( )
if ! t . noautosize {
C . tableAutosizeColumns ( t . _hwnd , t . colcount )
}
}
2014-08-06 09:42:26 -05:00
//export tableStopColumnAutosize
func tableStopColumnAutosize ( data unsafe . Pointer ) {
t := ( * table ) ( data )
t . noautosize = true
}
//export tableColumnCount
func tableColumnCount ( data unsafe . Pointer ) C . int {
t := ( * table ) ( data )
return t . colcount
}
2014-08-03 20:52:21 -05:00
func ( t * table ) hwnd ( ) C . HWND {
return t . _hwnd
}
2014-08-03 08:18:35 -05:00
func ( t * table ) setParent ( p * controlParent ) {
2014-08-03 20:52:21 -05:00
basesetParent ( t , p )
2014-08-03 08:18:35 -05:00
}
func ( t * table ) allocate ( x int , y int , width int , height int , d * sizing ) [ ] * allocation {
return baseallocate ( t , x , y , width , height , d )
}
const (
2014-08-13 15:49:30 -05:00
// from C++ Template 05 in http://msdn.microsoft.com/en-us/library/windows/desktop/bb226818%28v=vs.85%29.aspx as this is the best I can do for now
// there IS a message LVM_APPROXIMATEVIEWRECT that can do calculations, but it doesn't seem to work right when asked to base its calculations on the current width/height on Windows and wine...
2014-08-03 08:18:35 -05:00
tableWidth = 183
tableHeight = 50
)
func ( t * table ) preferredSize ( d * sizing ) ( width , height int ) {
return fromdlgunitsX ( tableWidth , d ) , fromdlgunitsY ( tableHeight , d )
}
func ( t * table ) commitResize ( a * allocation , d * sizing ) {
2014-08-03 20:52:21 -05:00
basecommitResize ( t , a , d )
2014-08-14 08:20:20 -05:00
t . RLock ( )
defer t . RUnlock ( )
t . autoresize ( )
2014-08-03 08:18:35 -05:00
}
func ( t * table ) getAuxResizeInfo ( d * sizing ) {
2014-08-03 19:42:45 -05:00
basegetAuxResizeInfo ( t , d )
2014-08-03 08:18:35 -05:00
}