X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7bade612f0f138a06f6a53d84220bb9d8ece7662..7f08aa6ce9c7d079b247963a3cb66193780603a3:/src/generic/datavgen.cpp diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index bdeadffd36..9ae974c053 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -607,65 +607,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(); - - // take alignment into account only if there is enough space, otherwise - // show as much contents as possible - // - // notice that many existing renderers (e.g. wxDataViewSpinRenderer) - // return hard-coded size which can be more than they need and if we - // trusted their GetSize() we'd draw the text out of cell bounds - // entirely - - if ( size.x < cell_rect.width ) - { - if (align & wxALIGN_CENTER_HORIZONTAL) - item_rect.x += (cell_rect.width - size.x)/2; - else if (align & wxALIGN_RIGHT) - item_rect.x += cell_rect.width - size.x; - // else: wxALIGN_LEFT is the default - - item_rect.width = size.x; - } - - if ( size.y < cell_rect.height ) - { - if (align & wxALIGN_CENTER_VERTICAL) - item_rect.y += (cell_rect.height - size.y)/2; - else if (align & wxALIGN_BOTTOM) - item_rect.y += cell_rect.height - size.y; - // else: wxALIGN_TOP is the default - - item_rect.height = size.y; - } - } - - return Render(item_rect, &dc, state); + delete m_dc; } wxDC *wxDataViewRenderer::GetDC() @@ -692,19 +644,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 // --------------------------------------------------------- @@ -717,53 +656,15 @@ wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString &varianttype, { } -void -wxDataViewCustomRenderer::RenderText(wxDC& dc, - const wxRect& rect, - int align, - const wxString& text, - const wxDataViewItemAttr *attr, - int state, - int xoffset) -{ - wxColour col; - if ( attr && attr->HasColour() ) - col = attr->GetColour(); - else if ( state & wxDATAVIEW_CELL_SELECTED ) - col = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT); - else // use default foreground - col = GetOwner()->GetOwner()->GetForegroundColour(); - - wxDCTextColourChanger changeFg(dc, col); - - 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 ) { } @@ -805,14 +706,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; } @@ -828,11 +724,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 ) { } @@ -875,11 +771,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; } @@ -904,6 +800,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, @@ -917,10 +819,7 @@ bool wxDataViewToggleRenderer::Activate( wxRect WXUNUSED(cell), wxDataViewModel *model, const wxDataViewItem & item, unsigned int col) { - bool value = !m_toggle; - wxVariant variant = value; - model->SetValue( variant, item, col); - model->ValueChanged( item, col ); + model->ChangeValue(!m_toggle, item, col); return true; } @@ -935,11 +834,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; @@ -961,24 +860,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; } @@ -1035,20 +933,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 ) { } @@ -1105,11 +1000,11 @@ bool wxDataViewDateRenderer::Activate( wxRect WXUNUSED(cell), wxDataViewModel *m // 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); @@ -1126,23 +1021,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; } @@ -1628,15 +1518,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; @@ -1681,6 +1571,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++) @@ -1759,7 +1656,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, @@ -1774,7 +1672,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 ); @@ -1798,7 +1696,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++) @@ -1828,44 +1726,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)) { - indent = node->GetIndentLevel(); - // Calculate the indent first - indent = cell_rect.x + GetOwner()->GetIndent() * indent; - - int expander_width = m_lineHeight - 2*EXPANDER_MARGIN; + indent = GetOwner()->GetIndent() * node->GetIndentLevel(); - // 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; + // 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; - indent = indent + m_lineHeight; - // try to use the m_lineHeight as the expander space + indent += m_lineHeight; - 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 @@ -1885,6 +1789,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; @@ -1898,11 +1805,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; @@ -2170,6 +2073,7 @@ bool wxDataViewMainWindow::Cleared() void wxDataViewMainWindow::UpdateDisplay() { m_dirty = true; + m_underMouse = NULL; } void wxDataViewMainWindow::OnInternalIdle() @@ -3652,12 +3556,15 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) { if ((!ignore_other_columns) && (cell->GetMode() == wxDATAVIEW_CELL_ACTIVATABLE)) { - 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() ); + if ( wxDataViewCustomRenderer *custom = cell->WXGetAsCustom() ) + { + wxVariant value; + model->GetValue( value, item, col->GetModelColumn() ); + custom->SetValue( value ); + wxRect cell_rect( xpos, GetLineStart( current ), + col->GetWidth(), GetLineHeight( current ) ); + custom->Activate( cell_rect, model, item, col->GetModelColumn() ); + } } else { @@ -3787,7 +3694,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) { ChangeCurrentRow(current); ReverseRowSelection(m_currentRow); - SendSelectionChangedEvent(GetItemByRow(m_selection[0]) ); + SendSelectionChangedEvent(GetItemByRow(m_currentRow)); } else if (event.ShiftDown()) { @@ -3826,14 +3733,17 @@ 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 ) ); + /* ignore ret */ custom->LeftClick( event.GetPosition(), cell_rect, + model, item, col->GetModelColumn()); + } } } } @@ -4215,7 +4125,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 ); } }