2018-05-29 19:26:48 -05:00
# include "uipriv_windows.hpp"
2018-06-09 23:49:44 -05:00
# include "table.hpp"
2018-05-29 19:26:48 -05:00
2018-06-08 20:44:55 -05:00
static uiTableTextColumnOptionalParams defaultTextColumnOptionalParams = {
2018-06-08 21:05:11 -05:00
/*TODO.ColorModelColumn = */ - 1 ,
2018-06-08 20:44:55 -05:00
} ;
2018-05-29 19:26:48 -05:00
uiTableModel * uiNewTableModel ( uiTableModelHandler * mh )
{
uiTableModel * m ;
2018-06-07 21:54:01 -05:00
m = uiprivNew ( uiTableModel ) ;
2018-05-29 19:26:48 -05:00
m - > mh = mh ;
2018-06-07 21:54:01 -05:00
m - > tables = new std : : vector < uiTable * > ;
2018-05-29 19:26:48 -05:00
return m ;
}
void uiFreeTableModel ( uiTableModel * m )
{
2018-06-07 21:54:01 -05:00
delete m - > tables ;
uiprivFree ( m ) ;
2018-05-29 19:26:48 -05:00
}
2018-06-08 00:35:23 -05:00
// TODO document that when this is called, the model must return the new row count when asked
2018-05-29 19:26:48 -05:00
void uiTableModelRowInserted ( uiTableModel * m , int newIndex )
{
LVITEMW item ;
2018-06-08 00:35:23 -05:00
int newCount ;
2018-05-29 19:26:48 -05:00
2018-06-08 00:35:23 -05:00
newCount = ( * ( m - > mh - > NumRows ) ) ( m - > mh , m ) ;
2018-05-29 19:26:48 -05:00
ZeroMemory ( & item , sizeof ( LVITEMW ) ) ;
item . mask = 0 ;
item . iItem = newIndex ;
item . iSubItem = 0 ;
2018-06-08 00:35:23 -05:00
for ( auto t : * ( m - > tables ) ) {
// actually insert the rows
if ( SendMessageW ( t - > hwnd , LVM_SETITEMCOUNT , ( WPARAM ) newCount , LVSICF_NOINVALIDATEALL ) = = 0 )
logLastError ( L " error calling LVM_SETITEMCOUNT in uiTableModelRowInserted() " ) ;
// and redraw every row from the new row down to simulate adding it
if ( SendMessageW ( t - > hwnd , LVM_REDRAWITEMS , ( WPARAM ) newIndex , ( LPARAM ) ( newCount - 1 ) ) = = FALSE )
logLastError ( L " error calling LVM_REDRAWITEMS in uiTableModelRowInserted() " ) ;
// update selection state
2018-05-29 19:26:48 -05:00
if ( SendMessageW ( t - > hwnd , LVM_INSERTITEM , 0 , ( LPARAM ) ( & item ) ) = = ( LRESULT ) ( - 1 ) )
2018-06-08 00:35:23 -05:00
logLastError ( L " error calling LVM_INSERTITEM in uiTableModelRowInserted() to update selection state " ) ;
}
2018-05-29 19:26:48 -05:00
}
2018-06-08 00:35:23 -05:00
// TODO compare LVM_UPDATE and LVM_REDRAWITEMS
2018-05-29 19:26:48 -05:00
void uiTableModelRowChanged ( uiTableModel * m , int index )
{
2018-06-07 21:54:01 -05:00
for ( auto t : * ( m - > tables ) )
2018-05-29 19:26:48 -05:00
if ( SendMessageW ( t - > hwnd , LVM_UPDATE , ( WPARAM ) index , 0 ) = = ( LRESULT ) ( - 1 ) )
logLastError ( L " error calling LVM_UPDATE in uiTableModelRowChanged() " ) ;
}
2018-06-08 00:35:23 -05:00
// TODO document that when this is called, the model must return the OLD row count when asked
// TODO for this and the above, see what GTK+ requires and adjust accordingly
2018-05-29 19:26:48 -05:00
void uiTableModelRowDeleted ( uiTableModel * m , int oldIndex )
{
2018-06-08 00:35:23 -05:00
int newCount ;
newCount = ( * ( m - > mh - > NumRows ) ) ( m - > mh , m ) ;
newCount - - ;
for ( auto t : * ( m - > tables ) ) {
// update selection state
2018-05-29 19:26:48 -05:00
if ( SendMessageW ( t - > hwnd , LVM_DELETEITEM , ( WPARAM ) oldIndex , 0 ) = = ( LRESULT ) ( - 1 ) )
2018-06-08 00:35:23 -05:00
logLastError ( L " error calling LVM_DELETEITEM in uiTableModelRowDeleted() to update selection state " ) ;
// actually delete the rows
if ( SendMessageW ( t - > hwnd , LVM_SETITEMCOUNT , ( WPARAM ) newCount , LVSICF_NOINVALIDATEALL ) = = 0 )
logLastError ( L " error calling LVM_SETITEMCOUNT in uiTableModelRowDeleted() " ) ;
// and redraw every row from the new nth row down to simulate removing the old nth row
if ( SendMessageW ( t - > hwnd , LVM_REDRAWITEMS , ( WPARAM ) oldIndex , ( LPARAM ) ( newCount - 1 ) ) = = FALSE )
logLastError ( L " error calling LVM_REDRAWITEMS in uiTableModelRowDeleted() " ) ;
}
2018-05-29 19:26:48 -05:00
}
2018-06-08 20:16:06 -05:00
static LRESULT onLVN_GETDISPINFO ( uiTable * t , NMLVDISPINFOW * nm )
2018-05-29 19:26:48 -05:00
{
2018-06-09 23:49:44 -05:00
static uiprivTableColumnParams * p ;
2018-06-08 20:16:06 -05:00
uiTableData * data ;
WCHAR * wstr ;
2018-06-09 19:35:05 -05:00
HDC dc ;
IWICBitmap * wb ;
HBITMAP b ;
2018-06-09 22:02:37 -05:00
int checked ;
2018-06-08 21:11:46 -05:00
bool queueUpdated = false ;
2018-06-10 09:43:29 -05:00
HRESULT hr ;
2018-06-08 20:16:06 -05:00
2018-06-08 21:05:11 -05:00
wstr = t - > dispinfoStrings - > front ( ) ;
2018-06-08 20:44:55 -05:00
if ( wstr ! = NULL )
uiprivFree ( wstr ) ;
2018-06-08 21:05:11 -05:00
t - > dispinfoStrings - > pop ( ) ;
2018-06-08 20:16:06 -05:00
p = ( * ( t - > columns ) ) [ nm - > item . iSubItem ] ;
2018-06-09 22:02:37 -05:00
nm - > item . pszText = L " abcdefg " ;
2018-06-08 20:16:06 -05:00
if ( ( nm - > item . mask & LVIF_TEXT ) ! = 0 )
if ( p - > textModelColumn ! = - 1 ) {
2018-06-08 21:05:11 -05:00
data = ( * ( t - > model - > mh - > CellValue ) ) ( t - > model - > mh , t - > model , nm - > item . iItem , p - > textModelColumn ) ;
2018-06-08 20:16:06 -05:00
wstr = toUTF16 ( uiTableDataString ( data ) ) ;
uiFreeTableData ( data ) ;
nm - > item . pszText = wstr ;
2018-06-08 21:05:11 -05:00
t - > dispinfoStrings - > push ( wstr ) ;
2018-06-08 21:11:46 -05:00
queueUpdated = true ;
2018-06-08 20:16:06 -05:00
}
2018-05-29 19:26:48 -05:00
2018-06-09 23:49:44 -05:00
hr = uiprivLVN_GETDISPINFOImagesCheckboxes ( t , nm , p ) ;
if ( hr ! = S_OK ) {
// TODO
2018-06-09 22:25:16 -05:00
}
2018-06-09 22:02:37 -05:00
2018-06-08 21:11:46 -05:00
// we don't want to pop from an empty queue, so if nothing updated the queue (no info was filled in above), just push NULL
if ( ! queueUpdated )
t - > dispinfoStrings - > push ( NULL ) ;
2018-06-08 20:16:06 -05:00
return 0 ;
2018-05-29 19:26:48 -05:00
}
2018-06-09 09:40:42 -05:00
static COLORREF blend ( COLORREF base , double r , double g , double b , double a )
{
double br , bg , bb ;
2018-06-09 11:15:50 -05:00
// TODO find a better fix than this
// TODO s listview already alphablending?
// TODO find the right color here
2018-06-09 12:57:43 -05:00
if ( base = = CLR_DEFAULT )
2018-06-09 11:15:50 -05:00
base = GetSysColor ( COLOR_WINDOW ) ;
br = ( ( double ) GetRValue ( base ) ) / 255.0 ;
bg = ( ( double ) GetGValue ( base ) ) / 255.0 ;
bb = ( ( double ) GetBValue ( base ) ) / 255.0 ;
2018-06-09 09:40:42 -05:00
br = ( r * a ) + ( br * ( 1.0 - a ) ) ;
bg = ( g * a ) + ( bg * ( 1.0 - a ) ) ;
bb = ( b * a ) + ( bb * ( 1.0 - a ) ) ;
return RGB ( ( BYTE ) ( br * 255 ) ,
( BYTE ) ( bg * 255 ) ,
( BYTE ) ( bb * 255 ) ) ;
}
2018-06-12 06:58:27 -05:00
static HRESULT fillSubitemDrawParams ( HWND hwnd , NMLVCUSTOMDRAW * nm , uiprivSubitemDrawParams * dp )
{
RECT r ;
HRESULT hr ;
// note that we can't just copy nm->nmcd.rc into p->bounds because that is only defined during prepaint stages
// TODO this corrupts memory
if ( nm - > iSubItem = = 0 ) { return S_OK ;
ZeroMemory ( & r , sizeof ( RECT ) ) ;
r . left = LVIR_BOUNDS ;
if ( SendMessageW ( hwnd , LVM_GETITEMRECT , nm - > nmcd . dwItemSpec , ( LPARAM ) ( & r ) ) = = FALSE ) {
logLastError ( L " LVM_GETITEMRECT LVIR_BOUNDS " ) ;
return E_FAIL ;
}
dp - > bounds = r ;
ZeroMemory ( & r , sizeof ( RECT ) ) ;
r . left = LVIR_ICON ;
if ( SendMessageW ( hwnd , LVM_GETITEMRECT , nm - > nmcd . dwItemSpec , ( LPARAM ) ( & r ) ) = = FALSE ) {
logLastError ( L " LVM_GETITEMRECT LVIR_ICON " ) ;
return E_FAIL ;
}
dp - > icon = r ;
ZeroMemory ( & r , sizeof ( RECT ) ) ;
r . left = LVIR_LABEL ;
if ( SendMessageW ( hwnd , LVM_GETITEMRECT , nm - > nmcd . dwItemSpec , ( LPARAM ) ( & r ) ) = = FALSE ) {
logLastError ( L " LVM_GETITEMRECT LVIR_LABEL " ) ;
return E_FAIL ;
}
dp - > label = r ;
return S_OK ;
}
ZeroMemory ( & r , sizeof ( RECT ) ) ;
r . left = LVIR_BOUNDS ;
r . top = nm - > iSubItem ;
if ( SendMessageW ( hwnd , LVM_GETSUBITEMRECT , nm - > nmcd . dwItemSpec , ( LPARAM ) ( & r ) ) = = 0 ) {
logLastError ( L " LVM_GETSUBITEMRECT LVIR_BOUNDS " ) ;
return E_FAIL ;
}
dp - > bounds = r ;
ZeroMemory ( & r , sizeof ( RECT ) ) ;
r . left = LVIR_ICON ;
r . top = nm - > iSubItem ;
if ( SendMessageW ( hwnd , LVM_GETSUBITEMRECT , nm - > nmcd . dwItemSpec , ( LPARAM ) ( & r ) ) = = 0 ) {
logLastError ( L " LVM_GETSUBITEMRECT LVIR_ICON " ) ;
return E_FAIL ;
}
dp - > icon = r ;
// LVIR_LABEL is treated as LVIR_BOUNDS for LVM_GETSUBITEMRECT, but it doesn't matter because the label rect is uses isn't what we want anyway
// there's a hardocded 2-logical unit gap between the icon and text for subitems, AND the text starts being drawn (in the background) one bitmap margin to the right of that
// with normal items, there's no gap, and only the 2-logical unit gap after the background starts (TODO confirm this part)
// let's copy that to look nicer, even if it's not "accurate"
// TODO check against accessibility
dp - > label = dp - > bounds ;
// because we want the 2 extra logical units to be included with the background, we don't include them here
dp - > label . left = dp - > icon . right ;
return S_OK ;
}
2018-06-09 09:40:42 -05:00
static LRESULT onNM_CUSTOMDRAW ( uiTable * t , NMLVCUSTOMDRAW * nm )
{
2018-06-09 23:49:44 -05:00
uiprivTableColumnParams * p ;
2018-06-09 09:40:42 -05:00
uiTableData * data ;
double r , g , b , a ;
2018-06-12 06:58:27 -05:00
uiprivSubitemDrawParams dp ;
2018-06-09 09:40:42 -05:00
LRESULT ret ;
2018-06-10 16:38:51 -05:00
HRESULT hr ;
2018-06-09 09:40:42 -05:00
switch ( nm - > nmcd . dwDrawStage ) {
case CDDS_PREPAINT :
2018-06-10 16:38:51 -05:00
ret = CDRF_NOTIFYITEMDRAW ;
break ;
2018-06-09 09:40:42 -05:00
case CDDS_ITEMPREPAINT :
if ( t - > backgroundColumn ! = - 1 ) {
data = ( * ( t - > model - > mh - > CellValue ) ) ( t - > model - > mh , t - > model , nm - > nmcd . dwItemSpec , t - > backgroundColumn ) ;
if ( data ! = NULL ) {
uiTableDataColor ( data , & r , & g , & b , & a ) ;
uiFreeTableData ( data ) ;
nm - > clrTextBk = blend ( nm - > clrTextBk , r , g , b , a ) ;
}
}
2018-06-09 11:15:50 -05:00
t - > clrItemText = nm - > clrText ;
2018-06-10 16:38:51 -05:00
ret = CDRF_NEWFONT | CDRF_NOTIFYSUBITEMDRAW ;
break ;
2018-06-09 09:40:42 -05:00
case CDDS_SUBITEM | CDDS_ITEMPREPAINT :
p = ( * ( t - > columns ) ) [ nm - > iSubItem ] ;
2018-06-10 18:07:34 -05:00
// TODO none of this runs on the first item
2018-06-09 11:15:50 -05:00
// we need this as previous subitems will persist their colors
nm - > clrText = t - > clrItemText ;
2018-06-09 09:40:42 -05:00
if ( p - > textParams . ColorModelColumn ! = - 1 ) {
data = ( * ( t - > model - > mh - > CellValue ) ) ( t - > model - > mh , t - > model , nm - > nmcd . dwItemSpec , p - > textParams . ColorModelColumn ) ;
if ( data ! = NULL ) {
uiTableDataColor ( data , & r , & g , & b , & a ) ;
uiFreeTableData ( data ) ;
2018-06-09 11:15:50 -05:00
nm - > clrText = blend ( nm - > clrTextBk , r , g , b , a ) ;
2018-06-09 09:40:42 -05:00
}
}
2018-06-09 12:57:43 -05:00
// TODO draw background on image columns if needed
2018-06-10 16:38:51 -05:00
ret = CDRF_NEWFONT ;
break ;
2018-06-10 22:03:54 -05:00
case CDDS_SUBITEM | CDDS_ITEMPOSTPAINT :
if ( nm - > iSubItem = = 1 ) {
RECT r , r2 ;
r . left = LVIR_LABEL ;
r . top = 1 ;
SendMessageW ( t - > hwnd , LVM_GETSUBITEMRECT , nm - > nmcd . dwItemSpec , ( LPARAM ) ( & r ) ) ;
r2 . left = LVIR_ICON ;
r2 . top = 1 ;
SendMessageW ( t - > hwnd , LVM_GETSUBITEMRECT , nm - > nmcd . dwItemSpec , ( LPARAM ) ( & r2 ) ) ;
r . left = r2 . right + 2 ;
DrawTextW ( nm - > nmcd . hdc , L " Part " , - 1 ,
& r , DT_LEFT | DT_VCENTER | DT_END_ELLIPSIS | DT_SINGLELINE | DT_NOPREFIX | DT_EDITCONTROL ) ; }
2018-06-10 16:38:51 -05:00
default :
ret = CDRF_DODEFAULT ;
}
2018-06-12 06:58:27 -05:00
if ( ( nm - > nmcd . dwDrawStage & CDDS_SUBITEM ) = = 0 ) return ret ;
ZeroMemory ( & dp , sizeof ( uiprivSubitemDrawParams ) ) ;
hr = fillSubitemDrawParams ( t - > hwnd , nm , & dp ) ;
if ( hr ! = S_OK ) {
// TODO
}
hr = uiprivNM_CUSTOMDRAWImagesCheckboxes ( t , nm , & dp , & ret ) ;
2018-06-10 16:38:51 -05:00
if ( hr ! = S_OK ) {
// TODO
2018-06-09 09:40:42 -05:00
}
2018-06-10 16:38:51 -05:00
return ret ;
2018-06-09 09:40:42 -05:00
}
2018-06-08 20:16:06 -05:00
static BOOL onWM_NOTIFY ( uiControl * c , HWND hwnd , NMHDR * nmhdr , LRESULT * lResult )
2018-05-29 19:26:48 -05:00
{
2018-06-08 20:16:06 -05:00
uiTable * t = uiTable ( c ) ;
2018-05-29 19:26:48 -05:00
2018-06-08 20:16:06 -05:00
switch ( nmhdr - > code ) {
case LVN_GETDISPINFO :
* lResult = onLVN_GETDISPINFO ( t , ( NMLVDISPINFOW * ) nmhdr ) ;
return TRUE ;
2018-06-09 09:40:42 -05:00
case NM_CUSTOMDRAW :
* lResult = onNM_CUSTOMDRAW ( t , ( NMLVCUSTOMDRAW * ) nmhdr ) ;
return TRUE ;
2018-06-08 20:16:06 -05:00
}
return FALSE ;
2018-05-29 19:26:48 -05:00
}
static void uiTableDestroy ( uiControl * c )
{
uiTable * t = uiTable ( c ) ;
uiTableModel * model = t - > model ;
std : : vector < uiTable * > : : iterator it ;
2018-06-08 20:44:55 -05:00
WCHAR * wstr ;
2018-05-29 19:26:48 -05:00
uiWindowsUnregisterWM_NOTIFYHandler ( t - > hwnd ) ;
uiWindowsEnsureDestroyWindow ( t - > hwnd ) ;
// detach table from model
2018-06-08 21:05:11 -05:00
for ( it = model - > tables - > begin ( ) ; it ! = model - > tables - > end ( ) ; it + + ) {
2018-05-29 19:26:48 -05:00
if ( * it = = t ) {
2018-06-08 20:44:55 -05:00
model - > tables - > erase ( it ) ;
2018-05-29 19:26:48 -05:00
break ;
}
}
2018-06-08 20:44:55 -05:00
// empty the string queue
while ( t - > dispinfoStrings - > size ( ) ! = 0 ) {
wstr = t - > dispinfoStrings - > front ( ) ;
if ( wstr ! = NULL )
uiprivFree ( wstr ) ;
t - > dispinfoStrings - > pop ( ) ;
}
delete t - > dispinfoStrings ;
2018-05-29 19:26:48 -05:00
// free the columns
2018-06-08 20:44:55 -05:00
for ( auto col : * ( t - > columns ) )
2018-05-29 19:26:48 -05:00
uiprivFree ( col ) ;
2018-06-07 21:54:01 -05:00
delete t - > columns ;
2018-06-09 19:35:05 -05:00
// t->smallImages will be automatically destroyed
2018-05-29 19:26:48 -05:00
uiFreeControl ( uiControl ( t ) ) ;
}
2018-06-08 20:16:06 -05:00
uiWindowsControlAllDefaultsExceptDestroy ( uiTable )
2018-05-29 19:26:48 -05:00
// suggested listview sizing from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing:
// "columns widths that avoid truncated data x an integral number of items"
// Don't think that'll cut it when some cells have overlong data (eg
// stupidly long URLs). So for now, just hardcode a minimum.
2018-06-11 07:01:18 -05:00
// TODO Investigate using LVM_GETHEADER/HDM_LAYOUT here
// TODO investigate using LVM_APPROXIMATEVIEWRECT here
2018-05-29 19:26:48 -05:00
# define tableMinWidth 107 /* in line with other controls */
2018-06-08 20:44:55 -05:00
# define tableMinHeight (14 * 3) /* header + 2 lines (roughly) */
2018-05-29 19:26:48 -05:00
static void uiTableMinimumSize ( uiWindowsControl * c , int * width , int * height )
{
uiTable * t = uiTable ( c ) ;
uiWindowsSizing sizing ;
int x , y ;
x = tableMinWidth ;
y = tableMinHeight ;
uiWindowsGetSizing ( t - > hwnd , & sizing ) ;
uiWindowsSizingDlgUnitsToPixels ( & sizing , & x , & y ) ;
* width = x ;
* height = y ;
2018-06-08 20:45:30 -05:00
}
2018-05-29 19:26:48 -05:00
2018-06-09 23:49:44 -05:00
static uiprivTableColumnParams * appendColumn ( uiTable * t , const char * name , int colfmt )
2018-05-29 19:26:48 -05:00
{
2018-06-08 20:44:55 -05:00
WCHAR * wstr ;
2018-06-08 20:16:06 -05:00
LVCOLUMNW lvc ;
2018-06-09 23:49:44 -05:00
uiprivTableColumnParams * p ;
2018-05-29 19:26:48 -05:00
2018-06-08 20:44:55 -05:00
ZeroMemory ( & lvc , sizeof ( LVCOLUMNW ) ) ;
lvc . mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT ;
lvc . fmt = colfmt ;
lvc . cx = 120 ; // TODO
wstr = toUTF16 ( name ) ;
lvc . pszText = wstr ;
if ( SendMessageW ( t - > hwnd , LVM_INSERTCOLUMNW , t - > nColumns , ( LPARAM ) ( & lvc ) ) = = ( LRESULT ) ( - 1 ) )
logLastError ( L " error calling LVM_INSERTCOLUMNW in appendColumn() " ) ;
uiprivFree ( wstr ) ;
t - > nColumns + + ;
2018-06-09 23:49:44 -05:00
p = uiprivNew ( uiprivTableColumnParams ) ;
2018-06-08 20:44:55 -05:00
p - > textModelColumn = - 1 ;
2018-06-09 22:02:37 -05:00
p - > textEditableColumn = - 1 ;
p - > textParams = defaultTextColumnOptionalParams ;
2018-06-08 20:44:55 -05:00
p - > imageModelColumn = - 1 ;
p - > checkboxModelColumn = - 1 ;
2018-06-09 22:02:37 -05:00
p - > checkboxEditableColumn = - 1 ;
2018-06-08 20:44:55 -05:00
p - > progressBarModelColumn = - 1 ;
p - > buttonModelColumn = - 1 ;
t - > columns - > push_back ( p ) ;
return p ;
}
2018-06-08 20:16:06 -05:00
2018-06-08 20:44:55 -05:00
void uiTableAppendTextColumn ( uiTable * t , const char * name , int textModelColumn , int textEditableModelColumn , uiTableTextColumnOptionalParams * params )
{
2018-06-09 23:49:44 -05:00
uiprivTableColumnParams * p ;
2018-06-08 20:16:06 -05:00
2018-06-08 20:44:55 -05:00
p = appendColumn ( t , name , LVCFMT_LEFT ) ;
p - > textModelColumn = textModelColumn ;
p - > textEditableColumn = textEditableModelColumn ;
if ( params ! = NULL )
p - > textParams = * params ;
}
void uiTableAppendImageColumn ( uiTable * t , const char * name , int imageModelColumn )
{
// TODO
}
void uiTableAppendImageTextColumn ( uiTable * t , const char * name , int imageModelColumn , int textModelColumn , int textEditableModelColumn , uiTableTextColumnOptionalParams * textParams )
{
2018-06-09 23:49:44 -05:00
uiprivTableColumnParams * p ;
2018-06-08 20:44:55 -05:00
2018-06-09 11:15:50 -05:00
p = appendColumn ( t , name , LVCFMT_LEFT ) ;
2018-06-08 20:44:55 -05:00
p - > textModelColumn = textModelColumn ;
p - > textEditableColumn = textEditableModelColumn ;
2018-06-08 21:05:11 -05:00
if ( textParams ! = NULL )
p - > textParams = * textParams ;
2018-06-08 20:44:55 -05:00
p - > imageModelColumn = imageModelColumn ;
2018-06-08 20:16:06 -05:00
}
2018-06-08 20:44:55 -05:00
void uiTableAppendCheckboxColumn ( uiTable * t , const char * name , int checkboxModelColumn , int checkboxEditableModelColumn )
2018-06-08 20:16:06 -05:00
{
2018-06-09 23:49:44 -05:00
uiprivTableColumnParams * p ;
2018-06-09 22:02:37 -05:00
p = appendColumn ( t , name , LVCFMT_LEFT ) ;
p - > checkboxModelColumn = checkboxModelColumn ;
p - > checkboxEditableColumn = checkboxEditableModelColumn ;
2018-06-08 20:16:06 -05:00
}
2018-06-08 20:44:55 -05:00
void uiTableAppendCheckboxTextColumn ( uiTable * t , const char * name , int checkboxModelColumn , int checkboxEditableModelColumn , int textModelColumn , int textEditableModelColumn , uiTableTextColumnOptionalParams * textParams )
2018-06-08 20:16:06 -05:00
{
2018-06-10 09:43:29 -05:00
uiprivTableColumnParams * p ;
2018-06-08 20:44:55 -05:00
p = appendColumn ( t , name , LVCFMT_LEFT ) ;
p - > textModelColumn = textModelColumn ;
p - > textEditableColumn = textEditableModelColumn ;
2018-06-08 21:05:11 -05:00
if ( textParams ! = NULL )
p - > textParams = * textParams ;
2018-06-08 20:44:55 -05:00
p - > checkboxModelColumn = checkboxModelColumn ;
p - > checkboxEditableColumn = checkboxEditableModelColumn ;
}
void uiTableAppendProgressBarColumn ( uiTable * t , const char * name , int progressModelColumn )
{
// TODO
}
void uiTableAppendButtonColumn ( uiTable * t , const char * name , int buttonTextModelColumn , int buttonClickableModelColumn )
{
// TODO
2018-06-08 20:16:06 -05:00
}
void uiTableSetRowBackgroundColorModelColumn ( uiTable * t , int modelColumn )
{
2018-06-09 09:40:42 -05:00
// TODO make the names consistent
t - > backgroundColumn = modelColumn ;
// TODO redraw?
2018-05-29 19:26:48 -05:00
}
uiTable * uiNewTable ( uiTableModel * model )
{
uiTable * t ;
int n ;
2018-06-09 22:25:16 -05:00
int i ;
2018-06-10 09:43:29 -05:00
HRESULT hr ;
2018-05-29 19:26:48 -05:00
uiWindowsNewControl ( uiTable , t ) ;
2018-06-07 21:54:01 -05:00
2018-06-09 23:49:44 -05:00
t - > columns = new std : : vector < uiprivTableColumnParams * > ;
2018-05-29 19:26:48 -05:00
t - > model = model ;
t - > hwnd = uiWindowsEnsureCreateControlHWND ( WS_EX_CLIENTEDGE ,
WC_LISTVIEW , L " " ,
LVS_REPORT | LVS_OWNERDATA | LVS_SINGLESEL | WS_TABSTOP | WS_HSCROLL | WS_VSCROLL ,
hInstance , NULL ,
TRUE ) ;
2018-06-08 21:05:11 -05:00
model - > tables - > push_back ( t ) ;
2018-05-29 19:26:48 -05:00
uiWindowsRegisterWM_NOTIFYHandler ( t - > hwnd , onWM_NOTIFY , uiControl ( t ) ) ;
// TODO: try LVS_EX_AUTOSIZECOLUMNS
2018-06-10 16:38:51 -05:00
// TODO check error
2018-05-29 19:26:48 -05:00
SendMessageW ( t - > hwnd , LVM_SETEXTENDEDLISTVIEWSTYLE ,
2018-06-09 11:15:50 -05:00
( WPARAM ) ( LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP | LVS_EX_SUBITEMIMAGES ) ,
( LPARAM ) ( LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP | LVS_EX_SUBITEMIMAGES ) ) ;
2018-05-29 19:26:48 -05:00
n = ( * ( model - > mh - > NumRows ) ) ( model - > mh , model ) ;
if ( SendMessageW ( t - > hwnd , LVM_SETITEMCOUNT , ( WPARAM ) n , 0 ) = = 0 )
logLastError ( L " error calling LVM_SETITEMCOUNT in uiNewTable() " ) ;
2018-06-08 21:05:11 -05:00
2018-06-09 19:35:05 -05:00
t - > backgroundColumn = - 1 ;
2018-06-08 21:05:11 -05:00
t - > dispinfoStrings = new std : : queue < WCHAR * > ;
// this encodes the idea that two LVN_GETDISPINFOs must complete before we can free a string: the first real one is for the fourth call to free
2018-06-09 23:49:44 -05:00
for ( i = 0 ; i < uiprivNumLVN_GETDISPINFOSkip ; i + + )
2018-06-09 22:25:16 -05:00
t - > dispinfoStrings - > push ( NULL ) ;
2018-06-08 21:05:11 -05:00
2018-06-10 09:43:29 -05:00
hr = uiprivTableSetupImagesCheckboxes ( t ) ;
if ( hr ! = S_OK ) {
// TODO
}
2018-06-09 22:02:37 -05:00
2018-05-29 19:26:48 -05:00
return t ;
}