- m_owner = parent;
-
- m_scrollOffsetX = 0;
- m_delayedUpdate = false;
- m_vetoColumnDrag = false;
- m_buttonHeight = wxRendererNative::Get().GetHeaderButtonHeight( this );
-
- int x = pos.x == wxDefaultCoord ? 0 : pos.x,
- y = pos.y == wxDefaultCoord ? 0 : pos.y,
- w = size.x == wxDefaultCoord ? 1 : size.x,
- h = m_buttonHeight;
-
- wxSize new_size(w,h);
-
- if ( !CreateControl(parent, id, pos, new_size, 0, wxDefaultValidator, name) )
- return false;
-
- // create the native WC_HEADER window:
- WXHWND hwndParent = (HWND)parent->GetHandle();
- WXDWORD msStyle = WS_CHILD | HDS_DRAGDROP | HDS_BUTTONS | HDS_HORZ | HDS_HOTTRACK | HDS_FULLDRAG;
-
- if ( m_isShown )
- msStyle |= WS_VISIBLE;
-
- m_hWnd = CreateWindowEx(0,
- WC_HEADER,
- (LPCTSTR) NULL,
- msStyle,
- x, y, w, h,
- (HWND)hwndParent,
- (HMENU)-1,
- wxGetInstance(),
- (LPVOID) NULL);
- if (m_hWnd == NULL)
- {
- wxLogLastError(_T("CreateWindowEx"));
- return false;
- }
-
- m_imageList = new wxImageList( 16, 16 );
- Header_SetImageList( (HWND) m_hWnd, m_imageList->GetHIMAGELIST() );
-
- // we need to subclass the m_hWnd to force wxWindow::HandleNotify
- // to call wxDataViewHeaderWindow::MSWOnNotify
- SubclassWin(m_hWnd);
-
- // the following is required to get the default win's font for
- // header windows and must be done befor sending the HDM_LAYOUT msg
- SetFont(GetFont());
-
- return true;
-}
-
-wxDataViewHeaderWindowMSW::~wxDataViewHeaderWindow()
-{
- delete m_imageList;
- UnsubclassWin();
-}
-
-wxSize wxDataViewHeaderWindowMSW::DoGetBestSize() const
-{
- return wxSize( 80, m_buttonHeight+2 );
-}
-
-void wxDataViewHeaderWindowMSW::OnInternalIdle()
-{
- if (m_delayedUpdate)
- {
- m_delayedUpdate = false;
- UpdateDisplay();
- }
-}
-
-void wxDataViewHeaderWindowMSW::UpdateDisplay()
-{
- // remove old columns
- for (int j=0, max=Header_GetItemCount((HWND)m_hWnd); j < max; j++)
- Header_DeleteItem((HWND)m_hWnd, 0);
-
- m_imageList->RemoveAll();
-
- // add the updated array of columns to the header control
- unsigned int cols = GetOwner()->GetColumnCount();
- unsigned int added = 0;
- for (unsigned int i = 0; i < cols; i++)
- {
- wxDataViewColumn *col = GetColumn( i );
- if (col->IsHidden())
- continue; // don't add it!
-
- wxString title( col->GetTitle() );
- HDITEM hdi;
- hdi.mask = HDI_TEXT | HDI_FORMAT | HDI_WIDTH;
- if (col->GetBitmap().IsOk())
- {
- m_imageList->Add( col->GetBitmap() );
- hdi.mask |= HDI_IMAGE;
- hdi.iImage = m_imageList->GetImageCount()-1;
- }
- hdi.pszText = (wxChar *) title.wx_str();
- hdi.cxy = col->GetWidth();
- hdi.cchTextMax = sizeof(hdi.pszText)/sizeof(hdi.pszText[0]);
- hdi.fmt = HDF_LEFT | HDF_STRING;
- if (col->GetBitmap().IsOk())
- hdi.fmt |= HDF_IMAGE;
-
- //hdi.fmt &= ~(HDF_SORTDOWN|HDF_SORTUP);
-
- if (col->IsSortable() && GetOwner()->GetSortingColumn() == col)
- {
- //The Microsoft Comctrl32.dll 6.0 support SORTUP/SORTDOWN, but they are not default
- //see http://msdn2.microsoft.com/en-us/library/ms649534.aspx for more detail
- // VZ: works with 5.81
- hdi.fmt |= col->IsSortOrderAscending() ? HDF_SORTUP : HDF_SORTDOWN;
- }
-
- // lParam is reserved for application's use:
- // we store there the column index to use it later in MSWOnNotify
- // (since columns may have been hidden)
- hdi.lParam = (LPARAM)i;
-
- // the native wxMSW implementation of the header window
- // draws the column separator COLUMN_WIDTH_OFFSET pixels
- // on the right: to correct this effect we make the column
- // exactly COLUMN_WIDTH_OFFSET wider (for the first column):
- if (i == 0)
- hdi.cxy += COLUMN_WIDTH_OFFSET;
-
- 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:
- // such alignment is not allowed for the column header!
- break; // wxFAIL;
- }
-
- SendMessage((HWND)m_hWnd, HDM_INSERTITEM,
- (WPARAM)added, (LPARAM)&hdi);
- added++;
- }
-}
-
-unsigned int wxDataViewHeaderWindowMSW::GetColumnIdxFromHeader(NMHEADER *nmHDR)
-{
- unsigned int idx;
-
- // NOTE: we don't just return nmHDR->iItem because when there are
- // hidden columns, nmHDR->iItem may be different from
- // nmHDR->pitem->lParam
-
- if (nmHDR->pitem && nmHDR->pitem->mask & HDI_LPARAM)
- {
- idx = (unsigned int)nmHDR->pitem->lParam;
- return idx;
- }
-
- HDITEM item;
- item.mask = HDI_LPARAM;
- Header_GetItem((HWND)m_hWnd, nmHDR->iItem, &item);
-
- return (unsigned int)item.lParam;
-}
-
-bool wxDataViewHeaderWindowMSW::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
-{
- NMHDR *nmhdr = (NMHDR *)lParam;
-
- // is it a message from the header?
- if ( nmhdr->hwndFrom != (HWND)m_hWnd )
- return wxWindow::MSWOnNotify(idCtrl, lParam, result);
-
- NMHEADER *nmHDR = (NMHEADER *)nmhdr;
- switch ( nmhdr->code )
- {
- case NM_RELEASEDCAPTURE:
- {
- // user has released the mouse
- m_vetoColumnDrag = false;
- }
- break;
-
- case HDN_BEGINTRACK:
- // user has started to resize a column:
- // do we need to veto it?
- if (!GetColumn(nmHDR->iItem)->IsResizeable())
- {
- // veto it!
- *result = TRUE;
- }
- break;
-
- case HDN_BEGINDRAG:
- // valid column
- if (nmHDR->iItem != -1)
- {
- // user has started to reorder a valid column
- if ((m_vetoColumnDrag == true) || (!GetColumn(nmHDR->iItem)->IsReorderable()))
- {
- // veto it!
- *result = TRUE;
- m_vetoColumnDrag = true;
- }
- }
- else
- {
- // veto it!
- m_vetoColumnDrag = true;
- }
- break;
-
- case HDN_ENDDRAG: // user has finished reordering a column
- {
- wxDataViewColumn *col = GetColumn(nmHDR->iItem);
- unsigned int new_pos = nmHDR->pitem->iOrder;
- m_owner->ColumnMoved( col, new_pos );
- m_delayedUpdate = true;
- }
- break;
-
- case HDN_ITEMCHANGING:
- if (nmHDR->pitem != NULL &&
- (nmHDR->pitem->mask & HDI_WIDTH) != 0)
- {
- int minWidth = GetColumnFromHeader(nmHDR)->GetMinWidth();
- if (nmHDR->pitem->cxy < minWidth)
- {
- // do not allow the user to resize this column under
- // its minimal width:
- *result = TRUE;
- }
- }
- break;
-
- case HDN_ITEMCHANGED: // user is resizing a column
- case HDN_ENDTRACK: // user has finished resizing a column
-
- // update the width of the modified column:
- if (nmHDR->pitem != NULL &&
- (nmHDR->pitem->mask & HDI_WIDTH) != 0)
- {
- unsigned int idx = GetColumnIdxFromHeader(nmHDR);
- unsigned int w = nmHDR->pitem->cxy;
- wxDataViewColumn *col = GetColumn(idx);
-
- // see UpdateDisplay() for more info about COLUMN_WIDTH_OFFSET
- if (idx == 0 && w > COLUMN_WIDTH_OFFSET)
- w -= COLUMN_WIDTH_OFFSET;
-
- if (w >= (unsigned)col->GetMinWidth())
- col->SetInternalWidth(w);
- }
- break;
-
- case HDN_ITEMCLICK:
- {
- unsigned int idx = GetColumnIdxFromHeader(nmHDR);
- wxDataViewModel * model = GetOwner()->GetModel();
-
- if(nmHDR->iButton == 0)
- {
- wxDataViewColumn *col = GetColumn(idx);
- if(col->IsSortable())
- {
- if(model && m_owner->GetSortingColumn() == col)
- {
- bool order = col->IsSortOrderAscending();
- col->SetSortOrder(!order);
- }
- else if(model)
- {
- m_owner->SetSortingColumn(col);
- }
- }
- UpdateDisplay();
- if(model)
- model->Resort();
- }
-
- wxEventType evt = nmHDR->iButton == 0 ?
- wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK :
- wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK;
- SendEvent(evt, idx);
- }
- break;
-
- case NM_RCLICK:
- {
- // NOTE: for some reason (i.e. for a bug in Windows)
- // the HDN_ITEMCLICK notification is not sent on
- // right clicks, so we need to handle NM_RCLICK
-
- POINT ptClick;
- int column = wxMSWGetColumnClicked(nmhdr, &ptClick);
- if (column != wxNOT_FOUND)
- {
- HDITEM item;
- item.mask = HDI_LPARAM;
- Header_GetItem((HWND)m_hWnd, column, &item);
-
- // 'idx' may be different from 'column' if there are
- // hidden columns...
- unsigned int idx = (unsigned int)item.lParam;
- SendEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK,
- idx);
- }
- }
- break;
-
- case HDN_GETDISPINFOW:
- // see wxListCtrl::MSWOnNotify for more info!
- break;
-
- case HDN_ITEMDBLCLICK:
- {
- unsigned int idx = GetColumnIdxFromHeader(nmHDR);
- int w = GetOwner()->GetBestColumnWidth(idx);
-
- // update the native control:
- HDITEM hd;
- ZeroMemory(&hd, sizeof(hd));
- hd.mask = HDI_WIDTH;
- hd.cxy = w;
- Header_SetItem(GetHwnd(),
- nmHDR->iItem, // NOTE: we don't want 'idx' here!
- &hd);
-
- // update the wxDataViewColumn class:
- GetColumn(idx)->SetInternalWidth(w);
- }
- break;
-
- default:
- return wxWindow::MSWOnNotify(idCtrl, lParam, result);
- }
-
- return true;
-}
-
-void wxDataViewHeaderWindowMSW::ScrollWindow(int dx, int WXUNUSED(dy),
- const wxRect * WXUNUSED(rect))
-{
- m_scrollOffsetX += dx;
-
- GetParent()->Layout();
-}
-
-void wxDataViewHeaderWindowMSW::DoSetSize(int x, int y,
- int w, int h,
- int f)
-{
- // TODO: why is there a border + 2px around it?
- wxControl::DoSetSize( x+m_scrollOffsetX+1, y+1, w-m_scrollOffsetX-2, h-2, f );
-}
-
-#else // !defined(__WXMSW__)
-
-IMPLEMENT_ABSTRACT_CLASS(wxGenericDataViewHeaderWindow, wxWindow)
-BEGIN_EVENT_TABLE(wxGenericDataViewHeaderWindow, wxWindow)
- EVT_PAINT (wxGenericDataViewHeaderWindow::OnPaint)
- EVT_MOUSE_EVENTS (wxGenericDataViewHeaderWindow::OnMouse)
- EVT_SET_FOCUS (wxGenericDataViewHeaderWindow::OnSetFocus)
-END_EVENT_TABLE()
-
-bool wxGenericDataViewHeaderWindow::Create(wxDataViewCtrl *parent, wxWindowID id,
- const wxPoint &pos, const wxSize &size,
- const wxString &name )
-{
- m_owner = parent;
-
- if (!wxDataViewHeaderWindowBase::Create(parent, id, pos, size, name))
- return false;
-
- wxVisualAttributes attr = wxPanel::GetClassDefaultAttributes();
- SetBackgroundStyle( wxBG_STYLE_CUSTOM );
- SetOwnForegroundColour( attr.colFg );
- SetOwnBackgroundColour( attr.colBg );
- if (!m_hasFont)
- SetOwnFont( attr.font );
-
- // set our size hints: wxDataViewCtrl will put this wxWindow inside
- // a wxBoxSizer and in order to avoid super-big header windows,
- // we need to set our height as fixed
- SetMinSize(wxSize(-1, HEADER_WINDOW_HEIGHT));
- SetMaxSize(wxSize(-1, HEADER_WINDOW_HEIGHT));
-
- return true;
-}
-
-void wxGenericDataViewHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
-{
- int w, h;
- GetClientSize( &w, &h );
-
- wxAutoBufferedPaintDC dc( this );
-
- dc.SetBackground(GetBackgroundColour());
- dc.Clear();
-
- int xpix;
- m_owner->GetScrollPixelsPerUnit( &xpix, NULL );
-
- int x;
- m_owner->GetViewStart( &x, NULL );
-
- // account for the horz scrollbar offset
- dc.SetDeviceOrigin( -x * xpix, 0 );
-
- dc.SetFont( GetFont() );
-
- unsigned int cols = GetOwner()->GetColumnCount();
- unsigned int i;
- int xpos = 0;
- for (i = 0; i < cols; i++)