+
+ wxRect update = GetUpdateRegion().GetBox();
+ m_owner->CalcUnscrolledPosition( update.x, update.y, &update.x, &update.y );
+
+ wxDataViewListModel *model = GetOwner()->GetModel();
+
+ unsigned int item_start = wxMax( 0, (update.y / m_lineHeight) );
+ unsigned int item_count = wxMin( (int)(((update.y + update.height) / m_lineHeight) - item_start + 1),
+ (int)(model->GetNumberOfRows()-item_start) );
+
+
+
+ unsigned int item;
+ for (item = item_start; item < item_start+item_count; item++)
+ {
+ if (m_selection.Index( item ) != wxNOT_FOUND)
+ {
+ int flags = wxCONTROL_SELECTED;
+ if (item == m_currentRow)
+ flags |= wxCONTROL_CURRENT;
+ if (m_hasFocus)
+ flags |= wxCONTROL_FOCUSED;
+ wxRect rect( 0, item*m_lineHeight+1, GetEndOfLastCol(), m_lineHeight-2 );
+ wxRendererNative::Get().DrawItemSelectionRect
+ (
+ this,
+ dc,
+ rect,
+ flags
+ );
+ }
+ else
+ {
+ if (item == m_currentRow)
+ {
+ int flags = wxCONTROL_CURRENT;
+ if (m_hasFocus)
+ flags |= wxCONTROL_FOCUSED; // should have no effect
+ wxRect rect( 0, item*m_lineHeight+1, GetEndOfLastCol(), m_lineHeight-2 );
+ wxRendererNative::Get().DrawItemSelectionRect
+ (
+ this,
+ dc,
+ rect,
+ flags
+ );
+
+ }
+ }
+ }
+
+ wxRect cell_rect;
+ cell_rect.x = 0;
+ cell_rect.height = m_lineHeight;
+ unsigned int cols = GetOwner()->GetNumberOfColumns();
+ unsigned int i;
+ for (i = 0; i < cols; i++)
+ {
+ wxDataViewColumn *col = GetOwner()->GetColumn( i );
+ wxDataViewRenderer *cell = col->GetRenderer();
+ cell_rect.width = col->GetWidth();
+
+ for (item = item_start; item < item_start+item_count; item++)
+ {
+ cell_rect.y = item*m_lineHeight;
+ wxVariant value;
+ model->GetValue( value, col->GetModelColumn(), item );
+ cell->SetValue( value );
+ wxSize size = cell->GetSize();
+ // cannot be bigger than allocated space
+ size.x = wxMin( size.x, cell_rect.width );
+ size.y = wxMin( size.y, cell_rect.height );
+ // TODO: check for left/right/centre alignment here
+ wxRect item_rect;
+ // for now: centre
+ item_rect.x = cell_rect.x + (cell_rect.width / 2) - (size.x / 2);
+ item_rect.y = cell_rect.y + (cell_rect.height / 2) - (size.y / 2);
+
+ item_rect.width = size.x;
+ item_rect.height= size.y;
+ cell->Render( item_rect, &dc, 0 );
+ }
+
+ cell_rect.x += cell_rect.width;
+ }
+}
+
+int wxDataViewMainWindow::GetCountPerPage()
+{
+ wxSize size = GetClientSize();
+ return size.y / m_lineHeight;
+}
+
+int wxDataViewMainWindow::GetEndOfLastCol()
+{
+ int width = 0;
+ unsigned int i;
+ for (i = 0; i < GetOwner()->GetNumberOfColumns(); i++)
+ {
+ wxDataViewColumn *c = GetOwner()->GetColumn( i );
+ width += c->GetWidth();
+ }
+ return width;
+}
+
+unsigned int wxDataViewMainWindow::GetFirstVisibleRow()
+{
+ int x = 0;
+ int y = 0;
+ m_owner->CalcUnscrolledPosition( x, y, &x, &y );
+
+ return y / m_lineHeight;
+}
+
+unsigned int wxDataViewMainWindow::GetLastVisibleRow()
+{
+ wxSize client_size = GetClientSize();
+ m_owner->CalcUnscrolledPosition( client_size.x, client_size.y, &client_size.x, &client_size.y );
+
+ return wxMin( GetRowCount()-1, ((unsigned)client_size.y/m_lineHeight)+1 );
+}
+
+unsigned int wxDataViewMainWindow::GetRowCount()
+{
+ return GetOwner()->GetModel()->GetNumberOfRows();
+}
+
+void wxDataViewMainWindow::ChangeCurrentRow( unsigned int row )
+{
+ m_currentRow = row;
+
+ // send event
+}
+
+void wxDataViewMainWindow::SelectAllRows( bool on )
+{
+ if (IsEmpty())
+ return;
+
+ if (on)
+ {
+ m_selection.Clear();
+ for (unsigned int i = 0; i < GetRowCount(); i++)
+ m_selection.Add( i );
+ Refresh();
+ }
+ else
+ {
+ unsigned int first_visible = GetFirstVisibleRow();
+ unsigned int last_visible = GetLastVisibleRow();
+ unsigned int i;
+ for (i = 0; i < m_selection.GetCount(); i++)
+ {
+ unsigned int row = m_selection[i];
+ if ((row >= first_visible) && (row <= last_visible))
+ RefreshRow( row );
+ }
+ m_selection.Clear();
+ }
+}
+
+void wxDataViewMainWindow::SelectRow( unsigned int row, bool on )
+{
+ if (m_selection.Index( row ) == wxNOT_FOUND)
+ {
+ if (on)
+ {
+ m_selection.Add( row );
+ RefreshRow( row );
+ }
+ }
+ else
+ {
+ if (!on)
+ {
+ m_selection.Remove( row );
+ RefreshRow( row );
+ }
+ }
+}
+
+void wxDataViewMainWindow::SelectRows( unsigned int from, unsigned int to, bool on )
+{
+ if (from > to)
+ {
+ unsigned int tmp = from;
+ from = to;
+ to = tmp;
+ }
+
+ unsigned int i;
+ for (i = from; i <= to; i++)
+ {
+ if (m_selection.Index( i ) == wxNOT_FOUND)
+ {
+ if (on)
+ m_selection.Add( i );
+ }
+ else
+ {
+ if (!on)
+ m_selection.Remove( i );
+ }
+ }
+ RefreshRows( from, to );
+}
+
+void wxDataViewMainWindow::ReverseRowSelection( unsigned int row )
+{
+ if (m_selection.Index( row ) == wxNOT_FOUND)
+ m_selection.Add( row );
+ else
+ m_selection.Remove( row );
+ RefreshRow( row );
+}
+
+bool wxDataViewMainWindow::IsRowSelected( unsigned int row )
+{
+ return (m_selection.Index( row ) != wxNOT_FOUND);
+}
+
+void wxDataViewMainWindow::RefreshRow( unsigned int row )
+{
+ wxRect rect( 0, row*m_lineHeight, GetEndOfLastCol(), m_lineHeight );
+ m_owner->CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
+
+ wxSize client_size = GetClientSize();
+ wxRect client_rect( 0, 0, client_size.x, client_size.y );
+ wxRect intersect_rect = client_rect.Intersect( rect );
+ if (intersect_rect.width > 0)
+ Refresh( true, &intersect_rect );
+}
+
+void wxDataViewMainWindow::RefreshRows( unsigned int from, unsigned int to )
+{
+ if (from > to)
+ {
+ unsigned int tmp = to;
+ to = from;
+ from = tmp;
+ }
+
+ wxRect rect( 0, from*m_lineHeight, GetEndOfLastCol(), (to-from+1) * m_lineHeight );
+ m_owner->CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
+
+ wxSize client_size = GetClientSize();
+ wxRect client_rect( 0, 0, client_size.x, client_size.y );
+ wxRect intersect_rect = client_rect.Intersect( rect );
+ if (intersect_rect.width > 0)
+ Refresh( true, &intersect_rect );
+}
+
+void wxDataViewMainWindow::RefreshRowsAfter( unsigned int firstRow )
+{
+ unsigned int count = GetRowCount();
+ if (firstRow > count)
+ return;
+
+ wxRect rect( 0, firstRow*m_lineHeight, GetEndOfLastCol(), count * m_lineHeight );
+ m_owner->CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
+
+ wxSize client_size = GetClientSize();
+ wxRect client_rect( 0, 0, client_size.x, client_size.y );
+ wxRect intersect_rect = client_rect.Intersect( rect );
+ if (intersect_rect.width > 0)
+ Refresh( true, &intersect_rect );
+}
+
+void wxDataViewMainWindow::OnArrowChar(unsigned int newCurrent, const wxKeyEvent& event)
+{
+ wxCHECK_RET( newCurrent < GetRowCount(),
+ _T("invalid item index in OnArrowChar()") );
+
+ // if there is no selection, we cannot move it anywhere
+ if (!HasCurrentRow())
+ return;
+
+ unsigned int oldCurrent = m_currentRow;
+
+ // in single selection we just ignore Shift as we can't select several
+ // items anyhow
+ if ( event.ShiftDown() && !IsSingleSel() )
+ {
+ RefreshRow( oldCurrent );
+
+ ChangeCurrentRow( newCurrent );
+
+ // select all the items between the old and the new one
+ if ( oldCurrent > newCurrent )
+ {
+ newCurrent = oldCurrent;
+ oldCurrent = m_currentRow;
+ }
+
+ SelectRows( oldCurrent, newCurrent, true );
+ }
+ else // !shift
+ {
+ RefreshRow( oldCurrent );
+
+ // all previously selected items are unselected unless ctrl is held
+ if ( !event.ControlDown() )
+ SelectAllRows(false);
+
+ ChangeCurrentRow( newCurrent );
+
+ if ( !event.ControlDown() )
+ SelectRow( m_currentRow, true );
+ else
+ RefreshRow( m_currentRow );
+ }
+
+ // MoveToFocus();
+}
+
+void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
+{
+ if (event.GetKeyCode() == WXK_TAB)
+ {
+ wxNavigationKeyEvent nevent;
+ nevent.SetWindowChange( event.ControlDown() );
+ nevent.SetDirection( !event.ShiftDown() );
+ nevent.SetEventObject( GetParent()->GetParent() );
+ nevent.SetCurrentFocus( m_parent );
+ if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent ))
+ return;
+ }
+
+ // no item -> nothing to do
+ if (!HasCurrentRow())
+ {
+ event.Skip();
+ return;
+ }
+
+ // don't use m_linesPerPage directly as it might not be computed yet
+ const int pageSize = GetCountPerPage();
+ wxCHECK_RET( pageSize, _T("should have non zero page size") );
+
+ switch ( event.GetKeyCode() )
+ {
+ case WXK_UP:
+ if ( m_currentRow > 0 )
+ OnArrowChar( m_currentRow - 1, event );
+ break;
+
+ case WXK_DOWN:
+ if ( m_currentRow < GetRowCount() - 1 )
+ OnArrowChar( m_currentRow + 1, event );
+ break;
+
+ case WXK_END:
+ if (!IsEmpty())
+ OnArrowChar( GetRowCount() - 1, event );
+ break;
+
+ case WXK_HOME:
+ if (!IsEmpty())
+ OnArrowChar( 0, event );
+ break;
+
+ case WXK_PAGEUP:
+ {
+ int steps = pageSize - 1;
+ int index = m_currentRow - steps;
+ if (index < 0)
+ index = 0;
+
+ OnArrowChar( index, event );
+ }
+ break;
+
+ case WXK_PAGEDOWN:
+ {
+ int steps = pageSize - 1;
+ unsigned int index = m_currentRow + steps;
+ unsigned int count = GetRowCount();
+ if ( index >= count )
+ index = count - 1;
+
+ OnArrowChar( index, event );
+ }
+ break;
+
+ default:
+ event.Skip();
+ }