void wxHeaderCtrl::DoUpdate(unsigned int idx) { // the native control does provide Header_SetItem() but it's inconvenient // to use it because it sends HDN_ITEMCHANGING messages and we'd have to // arrange not to block setting the width from there and the logic would be // more complicated as we'd have to reset the old values as well as setting // the new ones -- so instead just recreate the column const wxHeaderColumn& col = GetColumn(idx); if ( col.IsHidden() ) { // column is hidden now if ( !m_isHidden[idx] ) { // but it wasn't hidden before, so remove it if ( !Header_DeleteItem(GetHwnd(), MSWToNativeIdx(idx)) ) wxLogLastError(wxS("Header_DeleteItem()")); m_isHidden[idx] = true; } //else: nothing to do, updating hidden column doesn't have any effect } else // column is shown now { if ( m_isHidden[idx] ) { m_isHidden[idx] = false; } else // and it was shown before as well { // we need to remove the old column if ( !Header_DeleteItem(GetHwnd(), MSWToNativeIdx(idx)) ) wxLogLastError(wxS("Header_DeleteItem()")); } DoInsertItem(col, idx); } }
void wxHeaderCtrl::DoSetColumnsOrder(const wxArrayInt& order) { wxArrayInt orderShown; orderShown.reserve(m_numColumns); for ( unsigned n = 0; n < m_numColumns; n++ ) { const int idx = order[n]; if ( GetColumn(idx).IsShown() ) orderShown.push_back(MSWToNativeIdx(idx)); } if ( !Header_SetOrderArray(GetHwnd(), orderShown.size(), &orderShown[0]) ) { wxLogLastError(wxT("Header_GetOrderArray")); } m_colIndices = order; }
int wxHeaderCtrl::MSWFromNativeIdx(int item) { wxASSERT_MSG( item >= 0 && item < GetShownColumnsCount(), "column index out of range" ); // reverse the above function unsigned idx = item; for ( unsigned n = 0; n < m_numColumns; n++ ) { if ( n > idx ) break; if ( GetColumn(n).IsHidden() ) idx++; } wxASSERT_MSG( MSWToNativeIdx(idx) == item, "logic error" ); return idx; }
void wxHeaderCtrl::DoInsertItem(const wxHeaderColumn& col, unsigned int idx) { wxASSERT_MSG( !col.IsHidden(), "should only be called for shown columns" ); wxHDITEM hdi; // notice that we need to store the string we use the pointer to until we // pass it to the control hdi.mask |= HDI_TEXT; wxWxCharBuffer buf = col.GetTitle().t_str(); hdi.pszText = buf.data(); hdi.cchTextMax = wxStrlen(buf); const wxBitmap bmp = col.GetBitmap(); if ( bmp.IsOk() ) { hdi.mask |= HDI_IMAGE; if ( bmp.IsOk() ) { const int bmpWidth = bmp.GetWidth(), bmpHeight = bmp.GetHeight(); if ( !m_imageList ) { m_imageList = new wxImageList(bmpWidth, bmpHeight); (void) // suppress mingw32 warning about unused computed value Header_SetImageList(GetHwnd(), GetHimagelistOf(m_imageList)); } else // already have an image list { // check that all bitmaps we use have the same size int imageWidth, imageHeight; m_imageList->GetSize(0, imageWidth, imageHeight); wxASSERT_MSG( imageWidth == bmpWidth && imageHeight == bmpHeight, "all column bitmaps must have the same size" ); } m_imageList->Add(bmp); hdi.iImage = m_imageList->GetImageCount() - 1; } else // no bitmap but we still need to update the item { hdi.iImage = I_IMAGENONE; } } if ( col.GetAlignment() != wxALIGN_NOT ) { hdi.mask |= HDI_FORMAT | HDF_LEFT; switch ( col.GetAlignment() ) { case wxALIGN_LEFT: hdi.fmt |= HDF_LEFT; break; case wxALIGN_CENTER: case wxALIGN_CENTER_HORIZONTAL: hdi.fmt |= HDF_CENTER; break; case wxALIGN_RIGHT: hdi.fmt |= HDF_RIGHT; break; default: wxFAIL_MSG( "invalid column header alignment" ); } } if ( col.IsSortKey() ) { hdi.mask |= HDI_FORMAT; hdi.fmt |= col.IsSortOrderAscending() ? HDF_SORTUP : HDF_SORTDOWN; } if ( col.GetWidth() != wxCOL_WIDTH_DEFAULT ) { hdi.mask |= HDI_WIDTH; hdi.cxy = col.GetWidth(); } hdi.mask |= HDI_ORDER; hdi.iOrder = MSWToNativeOrder(m_colIndices.Index(idx)); if ( ::SendMessage(GetHwnd(), HDM_INSERTITEM, MSWToNativeIdx(idx), (LPARAM)&hdi) == -1 ) { wxLogLastError(wxT("Header_InsertItem()")); } }