- return false;
-}
-
-// ---------------------------------------------------------
-// wxDataViewColumn
-// ---------------------------------------------------------
-
-IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumn, wxDataViewColumnBase)
-
-wxDataViewColumn::wxDataViewColumn( const wxString &title, wxDataViewRenderer *cell,
- unsigned int model_column,
- int width, wxAlignment align, int flags ) :
- wxDataViewColumnBase( title, cell, model_column, width, align, flags )
-{
- wxDataViewColumnBase::SetWidth(width == wxCOL_WIDTH_DEFAULT
- ? wxDVC_DEFAULT_WIDTH
- : width);
- SetTitle(title);
- SetAlignment(align);
- SetFlags(flags);
-}
-
-wxDataViewColumn::wxDataViewColumn( const wxBitmap &bitmap, wxDataViewRenderer *cell,
- unsigned int model_column,
- int width, wxAlignment align, int flags ) :
- wxDataViewColumnBase( bitmap, cell, model_column, width, align, flags )
-{
- wxDataViewColumnBase::SetWidth(width == wxCOL_WIDTH_DEFAULT
- ? wxDVC_DEFAULT_WIDTH
- : width);
- SetBitmap(bitmap);
- SetAlignment(align);
- SetFlags(flags);
-}
-
-void wxDataViewColumn::SetFlags(int flags)
-{
- if ( flags != GetFlags() )
- {
- wxDataViewColumnBase::SetFlags(flags);
-
- // tell our owner to e.g. update its scrollbars:
- if ( GetOwner() )
- GetOwner()->OnColumnChange();
- }
-}
-
-void wxDataViewColumn::SetSortOrder( bool ascending )
-{
- if ( ascending == IsSortOrderAscending() )
- return;
-
- wxDataViewColumnBase::SetSortOrder(ascending);
-
- // Update header button
- if (GetOwner())
- GetOwner()->OnColumnChange();
-}
-
-void wxDataViewColumn::SetInternalWidth( int width )
-{
- if ( width == GetWidth() )
- return;
-
- wxDataViewColumnBase::SetWidth(width);
-
- // the scrollbars of the wxDataViewCtrl needs to be recalculated!
- if (m_owner && m_owner->m_clientArea)
- m_owner->m_clientArea->RecalculateDisplay();
-}
-
-void wxDataViewColumn::SetWidth( int width )
-{
- if ( width == wxCOL_WIDTH_DEFAULT )
- width = wxDVC_DEFAULT_WIDTH;
-
- if ( width == GetWidth() )
- return;
-
- if (m_owner->m_headerArea)
- m_owner->m_headerArea->UpdateDisplay();
-
- SetInternalWidth(width);
-}
-
-int wxDataViewColumn::GetWidth() const
-{
- int width = wxDataViewColumnBase::GetWidth();
- return width == wxCOL_WIDTH_DEFAULT ? wxDVC_DEFAULT_WIDTH : width;
-}
-
-//-----------------------------------------------------------------------------
-// wxDataViewHeaderWindowBase
-//-----------------------------------------------------------------------------
-
-void wxDataViewHeaderWindowBase::SendEvent(wxEventType type, unsigned int n)
-{
- wxWindow *parent = GetParent();
- wxDataViewEvent le(type, parent->GetId());
-
- le.SetEventObject(parent);
- le.SetColumn(n);
- le.SetDataViewColumn(GetColumn(n));
- le.SetModel(GetOwner()->GetModel());
-
- // for events created by wxDataViewHeaderWindow the
- // row / value fields are not valid
-
- parent->GetEventHandler()->ProcessEvent(le);
-}
-
-#ifdef USE_NATIVE_HEADER_WINDOW
-
-// implemented in msw/listctrl.cpp:
-int WXDLLIMPEXP_CORE wxMSWGetColumnClicked(NMHDR *nmhdr, POINT *ptClick);
-
-IMPLEMENT_ABSTRACT_CLASS(wxDataViewHeaderWindowMSW, wxWindow)
-
-bool wxDataViewHeaderWindowMSW::Create(wxDataViewCtrl *parent)
-{
- m_owner = parent;
-
- m_scrollOffsetX = 0;
- m_delayedUpdate = false;
- m_vetoColumnDrag = false;
- m_buttonHeight = wxRendererNative::Get().GetHeaderButtonHeight( this );
-
- return wxHeaderCtrl::Create(parent, wxID_ANY);
-}
-
-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
- DeleteAllColumns();
-
- // add the updated array of columns to the header control
- const unsigned int cols = GetOwner()->GetColumnCount();
- for (unsigned int i = 0; i < cols; i++)
- {
- wxDataViewColumn * const col = GetColumn( i );
- if (col->IsHidden())
- continue; // don't add it!
-
- // we store the column index to use later as client data (we need to do
- // it since column indices in the control and the model may not be the
- // same if any columns have been hidden)
- col->SetClientData(i);
-
- AppendColumn(*col);
-
- if ( col->IsSortable() && GetOwner()->GetSortingColumn() == col )
- {
- ShowSortIndicator(GetColumnCount() - 1, col->IsSortOrderAscending());
- }
-
-#if 0
- // 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;
-#endif
- }
-}
-
-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++)
- {
- wxDataViewColumn *col = GetColumn( i );
- if (col->IsHidden())
- continue; // skip it!
-
- int cw = col->GetWidth();
- int ch = h;
-
- wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE;
- if (col->IsSortable() && GetOwner()->GetSortingColumn() == col)
- {
- if (col->IsSortOrderAscending())
- sortArrow = wxHDR_SORT_ICON_UP;
- else
- sortArrow = wxHDR_SORT_ICON_DOWN;
- }
-
- int state = 0;
- if (m_parent->IsEnabled())
- {
- if ((int) i == m_hover)
- state = wxCONTROL_CURRENT;
- }
- else
- {
- state = (int) wxCONTROL_DISABLED;
- }
-
- wxRendererNative::Get().DrawHeaderButton
- (
- this,
- dc,
- wxRect(xpos, 0, cw, ch-1),
- state,
- sortArrow
- );