X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/38c349189a580ed624e89fb9cc1065f46860092f..2d55af1dfa7fd1cc2df13a6593fd51591cfcfcb1:/src/generic/datavgen.cpp diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index 06a43cfd93..2f24a4a993 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -53,8 +53,14 @@ // classes //----------------------------------------------------------------------------- +class wxDataViewColumn; +class wxDataViewHeaderWindow; class wxDataViewCtrl; +//----------------------------------------------------------------------------- +// classes +//----------------------------------------------------------------------------- + static const int SCROLL_UNIT_X = 15; // the cell padding on the left/right @@ -76,6 +82,29 @@ static wxDataViewModel* g_model; static int g_column = -2; static bool g_asending = true; +//----------------------------------------------------------------------------- +// wxDataViewColumn +//----------------------------------------------------------------------------- + +void wxDataViewColumn::Init(int width, wxAlignment align, int flags) +{ + m_width = width == wxCOL_WIDTH_DEFAULT ? wxDVC_DEFAULT_WIDTH : width; + m_minWidth = 0; + m_align = align; + m_flags = flags; + m_sort = false; + m_sortAscending = true; +} + +void wxDataViewColumn::UpdateDisplay() +{ + if (m_owner) + { + int idx = m_owner->GetColumnIndex( this ); + m_owner->OnColumnChange( idx ); + } +} + //----------------------------------------------------------------------------- // wxDataViewHeaderWindow //----------------------------------------------------------------------------- @@ -382,6 +411,7 @@ public: const wxString &name = wxT("wxdataviewctrlmainwindow") ); virtual ~wxDataViewMainWindow(); + bool IsList() const { return GetOwner()->GetModel()->IsListModel(); } bool IsVirtualList() const { return m_root == NULL; } // notifications from wxDataViewModel @@ -441,6 +471,7 @@ public: void ScrollWindow( int dx, int dy, const wxRect *rect = NULL ); void ScrollTo( int rows, int column ); + unsigned GetCurrentRow() const { return m_currentRow; } bool HasCurrentRow() { return m_currentRow != (unsigned int)-1; } void ChangeCurrentRow( unsigned int row ); @@ -607,52 +638,17 @@ IMPLEMENT_ABSTRACT_CLASS(wxDataViewRenderer, wxDataViewRendererBase) wxDataViewRenderer::wxDataViewRenderer( const wxString &varianttype, wxDataViewCellMode mode, int align) : - wxDataViewRendererBase( varianttype, mode, align ) + wxDataViewCustomRendererBase( varianttype, mode, align ) { - m_dc = NULL; m_align = align; m_mode = mode; + m_ellipsizeMode = wxELLIPSIZE_MIDDLE; + m_dc = NULL; } wxDataViewRenderer::~wxDataViewRenderer() { - if (m_dc) - delete m_dc; -} - -bool -wxDataViewRenderer::RenderWithAttr(wxDC& dc, - const wxRect& cell_rect, - int align, - const wxDataViewItemAttr *WXUNUSED(attr), - int state) -{ - // adjust the rectangle ourselves to account for the alignment - - wxRect item_rect = cell_rect; - if ( align ) - { - const wxSize size = GetSize(); - - // horizontal alignment: - if (align & wxALIGN_CENTER_HORIZONTAL) - item_rect.x = cell_rect.x + (cell_rect.width / 2) - (size.x / 2); - else if (align & wxALIGN_RIGHT) - item_rect.x = cell_rect.x + cell_rect.width - size.x; - // else: wxALIGN_LEFT is the default - - // vertical alignment: - item_rect.y = cell_rect.y; - if (align & wxALIGN_CENTER_VERTICAL) - item_rect.y = cell_rect.y + (cell_rect.height / 2) - (size.y / 2); - else if (align & wxALIGN_BOTTOM) - item_rect.y = cell_rect.y + cell_rect.height - size.y; - // else: wxALIGN_TOP is the default - - item_rect.SetSize(size); - } - - return Render(item_rect, &dc, state); + delete m_dc; } wxDC *wxDataViewRenderer::GetDC() @@ -679,19 +675,6 @@ int wxDataViewRenderer::GetAlignment() const return m_align; } -int wxDataViewRenderer::CalculateAlignment() const -{ - if (m_align == wxDVR_DEFAULT_ALIGNMENT) - { - if (GetOwner() == NULL) - return wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL; - - return GetOwner()->GetAlignment() | wxALIGN_CENTRE_VERTICAL; - } - - return m_align; -} - // --------------------------------------------------------- // wxDataViewCustomRenderer // --------------------------------------------------------- @@ -704,59 +687,15 @@ wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString &varianttype, { } -void wxDataViewCustomRenderer::RenderText( const wxString &text, int xoffset, - wxRect cell, wxDC *dc, int state ) -{ - wxColour col = state & wxDATAVIEW_CELL_SELECTED - ? wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) - : GetOwner()->GetOwner()->GetForegroundColour(); - - wxDataViewItemAttr attr; - attr.SetColour(col); - RenderText(*dc, cell, wxALIGN_NOT, text, &attr, state, xoffset); -} - -void -wxDataViewCustomRenderer::RenderText(wxDC& dc, - const wxRect& rect, - int align, - const wxString& text, - const wxDataViewItemAttr *attr, - int WXUNUSED(state), - int xoffset) -{ - wxDCTextColourChanger changeFg(dc); - if ( attr && attr->HasColour() ) - changeFg.Set(attr->GetColour()); - - wxDCFontChanger changeFont(dc); - if ( attr && attr->HasFont() ) - { - wxFont font(dc.GetFont()); - if ( attr->GetBold() ) - font.MakeBold(); - if ( attr->GetItalic() ) - font.MakeItalic(); - - changeFont.Set(font); - } - - wxRect rectText = rect; - rectText.x += xoffset; - rectText.width -= xoffset; - - dc.DrawLabel(text, rectText, align); -} - // --------------------------------------------------------- // wxDataViewTextRenderer // --------------------------------------------------------- -IMPLEMENT_CLASS(wxDataViewTextRenderer, wxDataViewCustomRenderer) +IMPLEMENT_CLASS(wxDataViewTextRenderer, wxDataViewRenderer) wxDataViewTextRenderer::wxDataViewTextRenderer( const wxString &varianttype, wxDataViewCellMode mode, int align ) : - wxDataViewCustomRenderer( varianttype, mode, align ) + wxDataViewRenderer( varianttype, mode, align ) { } @@ -798,14 +737,9 @@ bool wxDataViewTextRenderer::GetValueFromEditorCtrl( wxControl *editor, wxVarian return true; } -bool -wxDataViewTextRenderer::RenderWithAttr(wxDC& dc, - const wxRect& rect, - int align, - const wxDataViewItemAttr *attr, - int state) +bool wxDataViewTextRenderer::Render(wxRect rect, wxDC *dc, int state) { - RenderText(dc, rect, align, m_text, attr, state); + RenderText(m_text, 0, rect, dc, state); return true; } @@ -821,11 +755,11 @@ wxSize wxDataViewTextRenderer::GetSize() const // wxDataViewBitmapRenderer // --------------------------------------------------------- -IMPLEMENT_CLASS(wxDataViewBitmapRenderer, wxDataViewCustomRenderer) +IMPLEMENT_CLASS(wxDataViewBitmapRenderer, wxDataViewRenderer) wxDataViewBitmapRenderer::wxDataViewBitmapRenderer( const wxString &varianttype, wxDataViewCellMode mode, int align ) : - wxDataViewCustomRenderer( varianttype, mode, align ) + wxDataViewRenderer( varianttype, mode, align ) { } @@ -868,11 +802,11 @@ wxSize wxDataViewBitmapRenderer::GetSize() const // wxDataViewToggleRenderer // --------------------------------------------------------- -IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleRenderer, wxDataViewCustomRenderer) +IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleRenderer, wxDataViewRenderer) wxDataViewToggleRenderer::wxDataViewToggleRenderer( const wxString &varianttype, wxDataViewCellMode mode, int align ) : - wxDataViewCustomRenderer( varianttype, mode, align ) + wxDataViewRenderer( varianttype, mode, align ) { m_toggle = false; } @@ -897,6 +831,12 @@ bool wxDataViewToggleRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state if (GetMode() != wxDATAVIEW_CELL_ACTIVATABLE) flags |= wxCONTROL_DISABLED; + // check boxes we draw must always have the same, standard size (if it's + // bigger than the cell size the checkbox will be truncated because the + // caller had set the clipping rectangle to prevent us from drawing outside + // the cell) + cell.SetSize(GetSize()); + wxRendererNative::Get().DrawCheckBox( GetOwner()->GetOwner(), *dc, @@ -906,15 +846,12 @@ bool wxDataViewToggleRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state return true; } -bool wxDataViewToggleRenderer::Activate( wxRect WXUNUSED(cell), - wxDataViewModel *model, - const wxDataViewItem & item, unsigned int col) +void wxDataViewToggleRenderer::WXOnActivate(wxDataViewModel *model, + const wxVariant& valueOld, + const wxDataViewItem & item, + unsigned int col) { - bool value = !m_toggle; - wxVariant variant = value; - model->SetValue( variant, item, col); - model->ValueChanged( item, col ); - return true; + model->ChangeValue(!valueOld.GetBool(), item, col); } wxSize wxDataViewToggleRenderer::GetSize() const @@ -928,11 +865,11 @@ wxSize wxDataViewToggleRenderer::GetSize() const // wxDataViewProgressRenderer // --------------------------------------------------------- -IMPLEMENT_ABSTRACT_CLASS(wxDataViewProgressRenderer, wxDataViewCustomRenderer) +IMPLEMENT_ABSTRACT_CLASS(wxDataViewProgressRenderer, wxDataViewRenderer) wxDataViewProgressRenderer::wxDataViewProgressRenderer( const wxString &label, const wxString &varianttype, wxDataViewCellMode mode, int align ) : - wxDataViewCustomRenderer( varianttype, mode, align ) + wxDataViewRenderer( varianttype, mode, align ) { m_label = label; m_value = 0; @@ -954,24 +891,23 @@ bool wxDataViewProgressRenderer::GetValue( wxVariant &value ) const return true; } -bool wxDataViewProgressRenderer::RenderWithAttr(wxDC& dc, - const wxRect& rect, - int WXUNUSED(align), - const wxDataViewItemAttr *attr, - int WXUNUSED(state)) +bool +wxDataViewProgressRenderer::Render(wxRect rect, wxDC *dc, int WXUNUSED(state)) { - // deflat the rect to leave a small border between bars in adjacent rows + // deflate the rect to leave a small border between bars in adjacent rows wxRect bar = rect.Deflate(0, 1); - dc.SetBrush( *wxTRANSPARENT_BRUSH ); - dc.SetPen( *wxBLACK_PEN ); - dc.DrawRectangle( bar ); + dc->SetBrush( *wxTRANSPARENT_BRUSH ); + dc->SetPen( *wxBLACK_PEN ); + dc->DrawRectangle( bar ); bar.width = (int)(bar.width * m_value / 100.); - dc.SetPen( *wxTRANSPARENT_PEN ); - dc.SetBrush( attr && attr->HasColour() ? wxBrush(attr->GetColour()) - : *wxBLUE_BRUSH ); - dc.DrawRectangle( bar ); + dc->SetPen( *wxTRANSPARENT_PEN ); + + const wxDataViewItemAttr& attr = GetAttr(); + dc->SetBrush( attr.HasColour() ? wxBrush(attr.GetColour()) + : *wxBLUE_BRUSH ); + dc->DrawRectangle( bar ); return true; } @@ -1028,20 +964,17 @@ END_EVENT_TABLE() void wxDataViewDateRendererPopupTransient::OnCalendar( wxCalendarEvent &event ) { - wxDateTime date = event.GetDate(); - wxVariant value = date; - m_model->SetValue( value, m_item, m_col ); - m_model->ValueChanged( m_item, m_col ); + m_model->ChangeValue( event.GetDate(), m_item, m_col ); DismissAndNotify(); } #endif // wxUSE_DATE_RENDERER_POPUP -IMPLEMENT_ABSTRACT_CLASS(wxDataViewDateRenderer, wxDataViewCustomRenderer) +IMPLEMENT_ABSTRACT_CLASS(wxDataViewDateRenderer, wxDataViewRenderer) wxDataViewDateRenderer::wxDataViewDateRenderer( const wxString &varianttype, wxDataViewCellMode mode, int align ) : - wxDataViewCustomRenderer( varianttype, mode, align ) + wxDataViewRenderer( varianttype, mode, align ) { } @@ -1074,35 +1007,34 @@ wxSize wxDataViewDateRenderer::GetSize() const return wxSize(x,y+d); } -bool wxDataViewDateRenderer::Activate( wxRect WXUNUSED(cell), wxDataViewModel *model, - const wxDataViewItem & item, unsigned int col ) +void wxDataViewDateRenderer::WXOnActivate(wxDataViewModel *model, + const wxVariant& valueOld, + const wxDataViewItem & item, + unsigned int col ) { - wxVariant variant; - model->GetValue( variant, item, col ); - wxDateTime value = variant.GetDateTime(); + wxDateTime dtOld = valueOld.GetDateTime(); #if wxUSE_DATE_RENDERER_POPUP wxDataViewDateRendererPopupTransient *popup = new wxDataViewDateRendererPopupTransient( - GetOwner()->GetOwner()->GetParent(), &value, model, item, col); + GetOwner()->GetOwner()->GetParent(), &dtOld, model, item, col); wxPoint pos = wxGetMousePosition(); popup->Move( pos ); popup->Layout(); popup->Popup( popup->m_cal ); #else // !wxUSE_DATE_RENDERER_POPUP - wxMessageBox(value.Format()); + wxMessageBox(dtOld.Format()); #endif // wxUSE_DATE_RENDERER_POPUP/!wxUSE_DATE_RENDERER_POPUP - return true; } // --------------------------------------------------------- // wxDataViewIconTextRenderer // --------------------------------------------------------- -IMPLEMENT_CLASS(wxDataViewIconTextRenderer, wxDataViewCustomRenderer) +IMPLEMENT_CLASS(wxDataViewIconTextRenderer, wxDataViewRenderer) wxDataViewIconTextRenderer::wxDataViewIconTextRenderer( const wxString &varianttype, wxDataViewCellMode mode, int align ) : - wxDataViewCustomRenderer( varianttype, mode, align ) + wxDataViewRenderer( varianttype, mode, align ) { SetMode(mode); SetAlignment(align); @@ -1119,23 +1051,18 @@ bool wxDataViewIconTextRenderer::GetValue( wxVariant& WXUNUSED(value) ) const return false; } -bool -wxDataViewIconTextRenderer::RenderWithAttr(wxDC& dc, - const wxRect& rect, - int align, - const wxDataViewItemAttr *attr, - int state) +bool wxDataViewIconTextRenderer::Render(wxRect rect, wxDC *dc, int state) { int xoffset = 0; const wxIcon& icon = m_value.GetIcon(); if ( icon.IsOk() ) { - dc.DrawIcon(icon, rect.x, rect.y + (rect.height - icon.GetHeight())/2); + dc->DrawIcon(icon, rect.x, rect.y + (rect.height - icon.GetHeight())/2); xoffset = icon.GetWidth()+4; } - RenderText(dc, rect, align, m_value.GetText(), attr, state, xoffset); + RenderText(m_value.GetText(), xoffset, rect, dc, state); return true; } @@ -1452,7 +1379,7 @@ wxDragResult wxDataViewMainWindow::OnDragOver( wxDataFormat format, wxCoord x, m_owner->CalcUnscrolledPosition( xx, yy, &xx, &yy ); unsigned int row = GetLineAt( yy ); - if ((row >= GetRowCount()) || (yy > GetEndOfLastCol())) + if ((row >= GetRowCount()) || (xx > GetEndOfLastCol())) { RemoveDropHint(); return wxDragNone; @@ -1498,7 +1425,7 @@ bool wxDataViewMainWindow::OnDrop( wxDataFormat format, wxCoord x, wxCoord y ) m_owner->CalcUnscrolledPosition( xx, yy, &xx, &yy ); unsigned int row = GetLineAt( yy ); - if ((row >= GetRowCount()) || (yy > GetEndOfLastCol())) + if ((row >= GetRowCount()) || (xx > GetEndOfLastCol())) return false; wxDataViewItem item = GetItemByRow( row ); @@ -1527,7 +1454,7 @@ wxDragResult wxDataViewMainWindow::OnData( wxDataFormat format, wxCoord x, wxCoo m_owner->CalcUnscrolledPosition( xx, yy, &xx, &yy ); unsigned int row = GetLineAt( yy ); - if ((row >= GetRowCount()) || (yy > GetEndOfLastCol())) + if ((row >= GetRowCount()) || (xx > GetEndOfLastCol())) return wxDragNone; wxDataViewItem item = GetItemByRow( row ); @@ -1572,7 +1499,7 @@ wxBitmap wxDataViewMainWindow::CreateItemBitmap( unsigned int row, int &indent ) } indent = 0; - if (!IsVirtualList()) + if (!IsList()) { wxDataViewTreeNode *node = GetTreeNodeByRow(row); indent = GetOwner()->GetIndent() * node->GetIndentLevel(); @@ -1621,15 +1548,15 @@ wxBitmap wxDataViewMainWindow::CreateItemBitmap( unsigned int row, int &indent ) model->GetValue( value, item, column->GetModelColumn()); cell->SetValue( value ); + wxDataViewItemAttr attr; + model->GetAttr(item, column->GetModelColumn(), attr); + cell->SetAttr(attr); + wxRect item_rect(x, 0, width, height); item_rect.Deflate(PADDING_RIGHTLEFT, 0); // dc.SetClippingRegion( item_rect ); - wxDataViewItemAttr attr; - const bool - hasAttr = model->GetAttr(item, column->GetModelColumn(), attr); - cell->RenderWithAttr(dc, item_rect, cell->CalculateAlignment(), - hasAttr ? &attr : NULL, 0); + cell->WXCallRender(item_rect, &dc, 0); // dc.DestroyClippingRegion(); x += width; @@ -1674,6 +1601,13 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) // compute which columns needs to be redrawn unsigned int cols = GetOwner()->GetColumnCount(); + if ( !cols ) + { + // we assume that we have at least one column below and painting an + // empty control is unnecessary anyhow + return; + } + unsigned int col_start = 0; unsigned int x_start; for (x_start = 0; col_start < cols; col_start++) @@ -1752,7 +1686,8 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) if (m_hasFocus) flags |= wxCONTROL_FOCUSED; - wxRect rect( x_start, GetLineStart( item ), x_last, GetLineHeight( item ) ); + wxRect rect( x_start, GetLineStart( item ), + x_last - x_start, GetLineHeight( item ) ); wxRendererNative::Get().DrawItemSelectionRect ( this, @@ -1767,7 +1702,7 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) if (m_dropHint) { wxRect rect( x_start, GetLineStart( m_dropHintLine ), - x_last, GetLineHeight( m_dropHintLine ) ); + x_last - x_start, GetLineHeight( m_dropHintLine ) ); dc.SetPen( *wxBLACK_PEN ); dc.SetBrush( *wxTRANSPARENT_BRUSH ); dc.DrawRectangle( rect ); @@ -1791,7 +1726,7 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) wxDataViewRenderer *cell = col->GetRenderer(); cell_rect.width = col->GetWidth(); - if (col->IsHidden()) + if ( col->IsHidden() || cell_rect.width <= 0 ) continue; // skip it! for (unsigned int item = item_start; item < item_last; item++) @@ -1821,44 +1756,50 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) model->GetValue( value, dataitem, col->GetModelColumn()); cell->SetValue( value ); + wxDataViewItemAttr attr; + model->GetAttr(dataitem, col->GetModelColumn(), attr); + cell->SetAttr(attr); + // update cell_rect cell_rect.y = GetLineStart( item ); cell_rect.height = GetLineHeight( item ); - // Draw the expander here. + // deal with the expander int indent = 0; - if ((!IsVirtualList()) && (col == expander)) + if ((!IsList()) && (col == expander)) { - indent = node->GetIndentLevel(); - // Calculate the indent first - indent = cell_rect.x + GetOwner()->GetIndent() * indent; + indent = GetOwner()->GetIndent() * node->GetIndentLevel(); - int expander_width = m_lineHeight - 2*EXPANDER_MARGIN; + // we reserve m_lineHeight of horizontal space for the expander + // but leave EXPANDER_MARGIN around the expander itself + int exp_x = cell_rect.x + indent + EXPANDER_MARGIN; - // change the cell_rect.x to the appropriate pos - int expander_x = indent + EXPANDER_MARGIN; - int expander_y = cell_rect.y + EXPANDER_MARGIN + (GetLineHeight(item) / 2) - - (expander_width/2) - EXPANDER_OFFSET; + indent += m_lineHeight; - indent = indent + m_lineHeight; - // try to use the m_lineHeight as the expander space - - dc.SetPen( m_penExpander ); - dc.SetBrush( wxNullBrush ); - if( node->HasChildren() ) + // draw expander if needed and visible + if ( node->HasChildren() && exp_x < cell_rect.GetRight() ) { - wxRect rect( expander_x , expander_y, expander_width, expander_width); + dc.SetPen( m_penExpander ); + dc.SetBrush( wxNullBrush ); + + int exp_size = m_lineHeight - 2*EXPANDER_MARGIN; + int exp_y = cell_rect.y + (cell_rect.height - exp_size)/2 + + EXPANDER_MARGIN - EXPANDER_OFFSET; + + const wxRect rect(exp_x, exp_y, exp_size, exp_size); + int flag = 0; - if (m_underMouse == node) - { + if ( m_underMouse == node ) flag |= wxCONTROL_CURRENT; - } - if( node->IsOpen() ) - wxRendererNative::Get().DrawTreeItemButton( this, dc, rect, - flag|wxCONTROL_EXPANDED ); - else - wxRendererNative::Get().DrawTreeItemButton( this, dc, rect, flag); + if ( node->IsOpen() ) + flag |= wxCONTROL_EXPANDED; + + // ensure that we don't overflow the cell (which might + // happen if the column is very narrow) + wxDCClipper clip(dc, cell_rect); + + wxRendererNative::Get().DrawTreeItemButton( this, dc, rect, flag); } // force the expander column to left-center align @@ -1878,6 +1819,9 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) item_rect.x += indent; item_rect.width -= indent; + if ( item_rect.width <= 0 ) + continue; + int state = 0; if (m_hasFocus && (m_selection.Index(item) != wxNOT_FOUND)) state |= wxDATAVIEW_CELL_SELECTED; @@ -1891,11 +1835,7 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) // make its own renderer and thus we cannot be sure of that. wxDCClipper clip(dc, item_rect); - wxDataViewItemAttr attr; - const bool - hasAttr = model->GetAttr(dataitem, col->GetModelColumn(), attr); - cell->RenderWithAttr(dc, item_rect, cell->CalculateAlignment(), - hasAttr ? &attr : NULL, state); + cell->WXCallRender(item_rect, &dc, state); } cell_rect.x += cell_rect.width; @@ -2051,9 +1991,12 @@ bool wxDataViewMainWindow::ItemDeleted(const wxDataViewItem& parent, wxDataViewTreeNode * node = FindNode(parent); - wxCHECK_MSG( node != NULL, false, "item not found" ); - wxCHECK_MSG( node->GetChildren().Index( item.GetID() ) != wxNOT_FOUND, - false, "item not found" ); + // Notice that it is possible that the item being deleted is not in the + // tree at all, for example we could be deleting a never shown (because + // collapsed) item in a tree model. So it's not an error if we don't know + // about this item, just return without doing anything then. + if ( !node || node->GetChildren().Index(item.GetID()) == wxNOT_FOUND ) + return false; int sub = -1; node->GetChildren().Remove( item.GetID() ); @@ -2163,6 +2106,7 @@ bool wxDataViewMainWindow::Cleared() void wxDataViewMainWindow::UpdateDisplay() { m_dirty = true; + m_underMouse = NULL; } void wxDataViewMainWindow::OnInternalIdle() @@ -2853,7 +2797,7 @@ wxDataViewEvent wxDataViewMainWindow::SendExpanderEvent( wxEventType type, bool wxDataViewMainWindow::IsExpanded( unsigned int row ) const { - if (IsVirtualList()) + if (IsList()) return false; wxDataViewTreeNode * node = GetTreeNodeByRow(row); @@ -2871,7 +2815,7 @@ bool wxDataViewMainWindow::IsExpanded( unsigned int row ) const bool wxDataViewMainWindow::HasChildren( unsigned int row ) const { - if (IsVirtualList()) + if (IsList()) return false; wxDataViewTreeNode * node = GetTreeNodeByRow(row); @@ -2889,7 +2833,7 @@ bool wxDataViewMainWindow::HasChildren( unsigned int row ) const void wxDataViewMainWindow::Expand( unsigned int row ) { - if (IsVirtualList()) + if (IsList()) return; wxDataViewTreeNode * node = GetTreeNodeByRow(row); @@ -2945,7 +2889,7 @@ void wxDataViewMainWindow::Expand( unsigned int row ) void wxDataViewMainWindow::Collapse(unsigned int row) { - if (IsVirtualList()) + if (IsList()) return; wxDataViewTreeNode *node = GetTreeNodeByRow(row); @@ -3144,7 +3088,7 @@ wxRect wxDataViewMainWindow::GetItemRect( const wxDataViewItem & item, // to get the correct x position where the actual text is int indent = 0; int row = GetRowByItem(item); - if (!IsVirtualList() && (column == 0 || GetOwner()->GetExpanderColumn() == column) ) + if (!IsList() && (column == 0 || GetOwner()->GetExpanderColumn() == column) ) { wxDataViewTreeNode* node = GetTreeNodeByRow(row); indent = GetOwner()->GetIndent() * node->GetIndentLevel(); @@ -3342,7 +3286,15 @@ void wxDataViewMainWindow::DestroyTree() void wxDataViewMainWindow::OnChar( wxKeyEvent &event ) { - if ( GetParent()->HandleAsNavigationKey(event) ) + wxWindow * const parent = GetParent(); + + // propagate the char event upwards + wxKeyEvent eventForParent(event); + eventForParent.SetEventObject(parent); + if ( parent->ProcessWindowEvent(eventForParent) ) + return; + + if ( parent->HandleAsNavigationKey(event) ) return; // no item -> nothing to do @@ -3360,7 +3312,6 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event ) { case WXK_RETURN: { - wxWindow *parent = GetParent(); wxDataViewEvent le(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, parent->GetId()); le.SetItem( GetItemByRow(m_currentRow) ); @@ -3383,7 +3334,7 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event ) // Add the process for tree expanding/collapsing case WXK_LEFT: { - if (IsVirtualList()) + if (IsList()) break; wxDataViewTreeNode* node = GetTreeNodeByRow(m_currentRow); @@ -3524,7 +3475,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) // Test whether the mouse is hovered on the tree item button bool hoverOverExpander = false; - if ((!IsVirtualList()) && (GetOwner()->GetExpanderColumn() == col)) + if ((!IsList()) && (GetOwner()->GetExpanderColumn() == col)) { wxDataViewTreeNode * node = GetTreeNodeByRow(current); if( node!=NULL && node->HasChildren() ) @@ -3645,12 +3596,21 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) { if ((!ignore_other_columns) && (cell->GetMode() == wxDATAVIEW_CELL_ACTIVATABLE)) { + const unsigned colIdx = col->GetModelColumn(); + wxVariant value; - model->GetValue( value, item, col->GetModelColumn() ); - cell->SetValue( value ); - wxRect cell_rect( xpos, GetLineStart( current ), - col->GetWidth(), GetLineHeight( current ) ); - cell->Activate( cell_rect, model, item, col->GetModelColumn() ); + model->GetValue( value, item, colIdx ); + + cell->WXOnActivate(model, value, item, colIdx); + + if ( wxDataViewCustomRenderer *custom = cell->WXGetAsCustom() ) + { + cell->SetValue( value ); + + wxRect cell_rect( xpos, GetLineStart( current ), + col->GetWidth(), GetLineHeight( current ) ); + custom->Activate( cell_rect, model, item, colIdx ); + } } else { @@ -3780,7 +3740,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) { ChangeCurrentRow(current); ReverseRowSelection(m_currentRow); - SendSelectionChangedEvent(GetItemByRow(m_selection[0]) ); + SendSelectionChangedEvent(GetItemByRow(m_currentRow)); } else if (event.ShiftDown()) { @@ -3819,14 +3779,54 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) // Call LeftClick after everything else as under GTK+ if (cell->GetMode() & wxDATAVIEW_CELL_ACTIVATABLE) { - // notify cell about right click - wxVariant value; - model->GetValue( value, item, col->GetModelColumn() ); - cell->SetValue( value ); - wxRect cell_rect( xpos, GetLineStart( current ), - col->GetWidth(), GetLineHeight( current ) ); - /* ignore ret */ cell->LeftClick( event.GetPosition(), cell_rect, - model, item, col->GetModelColumn()); + if ( wxDataViewCustomRenderer *custom = cell->WXGetAsCustom() ) + { + // notify cell about click + wxVariant value; + model->GetValue( value, item, col->GetModelColumn() ); + custom->SetValue( value ); + wxRect cell_rect( xpos, GetLineStart( current ), + col->GetWidth(), GetLineHeight( current ) ); + + // Report position relative to the cell's custom area, i.e. + // no the entire space as given by the control but the one + // used by the renderer after calculation of alignment etc. + + // adjust the rectangle ourselves to account for the alignment + wxRect rectItem = cell_rect; + const int align = custom->GetAlignment(); + if ( align != wxDVR_DEFAULT_ALIGNMENT ) + { + const wxSize size = custom->GetSize(); + + if ( size.x >= 0 && size.x < cell_rect.width ) + { + if ( align & wxALIGN_CENTER_HORIZONTAL ) + rectItem.x += (cell_rect.width - size.x)/2; + else if ( align & wxALIGN_RIGHT ) + rectItem.x += cell_rect.width - size.x; + // else: wxALIGN_LEFT is the default + } + + if ( size.y >= 0 && size.y < cell_rect.height ) + { + if ( align & wxALIGN_CENTER_VERTICAL ) + rectItem.y += (cell_rect.height - size.y)/2; + else if ( align & wxALIGN_BOTTOM ) + rectItem.y += cell_rect.height - size.y; + // else: wxALIGN_TOP is the default + } + } + + wxPoint pos( event.GetPosition() ); + pos.x -= rectItem.x; + pos.y -= rectItem.y; + + m_owner->CalcUnscrolledPosition( pos.x, pos.y, &pos.x, &pos.y ); + + /* ignore ret */ custom->LeftClick( pos, cell_rect, + model, item, col->GetModelColumn()); + } } } } @@ -3889,9 +3889,13 @@ void wxDataViewCtrl::Init() m_headerArea = NULL; } -bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id, - const wxPoint& pos, const wxSize& size, - long style, const wxValidator& validator ) +bool wxDataViewCtrl::Create(wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxValidator& validator, + const wxString& name) { // if ( (style & wxBORDER_MASK) == 0) // style |= wxBORDER_SUNKEN; @@ -3899,7 +3903,7 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id, Init(); if (!wxControl::Create( parent, id, pos, size, - style | wxScrolledWindowStyle, validator)) + style | wxScrolledWindowStyle, validator, name)) return false; SetInitialSize(size); @@ -3910,6 +3914,11 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id, m_clientArea = new wxDataViewMainWindow( this, wxID_ANY ); + // We use the cursor keys for moving the selection, not scrolling, so call + // this method to ensure wxScrollHelperEvtHandler doesn't catch all + // keyboard events forwarded to us from wxListMainWindow. + DisableKeyboardScrolling(); + if (HasFlag(wxDV_NO_HEADER)) m_headerArea = NULL; else @@ -4129,6 +4138,18 @@ bool wxDataViewCtrl::ClearColumns() int wxDataViewCtrl::GetColumnPosition( const wxDataViewColumn *column ) const { +#if 1 + unsigned int len = GetColumnCount(); + for ( unsigned int i = 0; i < len; i++ ) + { + wxDataViewColumn * col = GetColumnAt(i); + if (column==col) + return i; + } + + return wxNOT_FOUND; +#else + // This returns the position in pixels which is not what we want. int ret = 0, dummy = 0; unsigned int len = GetColumnCount(); @@ -4145,6 +4166,7 @@ int wxDataViewCtrl::GetColumnPosition( const wxDataViewColumn *column ) const } } return ret; +#endif } wxDataViewColumn *wxDataViewCtrl::GetSortingColumn() const @@ -4153,6 +4175,24 @@ wxDataViewColumn *wxDataViewCtrl::GetSortingColumn() const : GetColumn(m_sortingColumnIdx); } +wxDataViewItem wxDataViewCtrl::DoGetCurrentItem() const +{ + return GetItemByRow(m_clientArea->GetCurrentRow()); +} + +void wxDataViewCtrl::DoSetCurrentItem(const wxDataViewItem& item) +{ + const int row = m_clientArea->GetRowByItem(item); + + const unsigned oldCurrent = m_clientArea->GetCurrentRow(); + if ( static_cast(row) != oldCurrent ) + { + m_clientArea->ChangeCurrentRow(row); + m_clientArea->RefreshRow(oldCurrent); + m_clientArea->RefreshRow(row); + } +} + // Selection code with wxDataViewItem as parameters wxDataViewItem wxDataViewCtrl::GetSelection() const { @@ -4208,7 +4248,11 @@ void wxDataViewCtrl::Select( const wxDataViewItem & item ) // Unselect all rows before select another in the single select mode if (m_clientArea->IsSingleSel()) m_clientArea->SelectAllRows(false); + m_clientArea->SelectRow(row, true); + + // Also set focus to the selected item + m_clientArea->ChangeCurrentRow( row ); } }