m_dc = NULL;
m_align = align;
m_mode = mode;
+ m_ellipsizeMode = wxELLIPSIZE_MIDDLE;
}
wxDataViewRenderer::~wxDataViewRenderer()
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);
+}
+
wxDC *wxDataViewRenderer::GetDC()
{
if (m_dc == NULL)
{
}
-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, text, &attr, state, xoffset);
-}
-
void
wxDataViewCustomRenderer::RenderText(wxDC& dc,
const wxRect& rect,
+ int align,
const wxString& text,
const wxDataViewItemAttr *attr,
- int WXUNUSED(state),
+ int state,
int xoffset)
{
- wxDCTextColourChanger changeFg(dc);
- if ( attr && attr->HasColour() )
- changeFg.Set(attr->GetColour());
+ // override custom foreground with the standard one for the selected items
+ // because we currently don't allow changing the selection background and
+ // custom colours may be unreadable on it
+ wxColour col;
+ if ( state & wxDATAVIEW_CELL_SELECTED )
+ col = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
+ else if ( attr && attr->HasColour() )
+ col = attr->GetColour();
+ else // use default foreground
+ col = GetOwner()->GetOwner()->GetForegroundColour();
+
+ wxDCTextColourChanger changeFg(dc, col);
wxDCFontChanger changeFont(dc);
if ( attr && attr->HasFont() )
changeFont.Set(font);
}
- dc.DrawText(text,
- rect.x + xoffset,
- rect.y + ((rect.height - dc.GetCharHeight()) / 2));
+ wxRect rectText = rect;
+ rectText.x += xoffset;
+ rectText.width -= xoffset;
+
+ // check if we want to ellipsize the text if it doesn't fit
+ wxString ellipsizedText;
+ if ( GetEllipsizeMode() != wxELLIPSIZE_NONE )
+ {
+ ellipsizedText = wxControl::Ellipsize
+ (
+ text,
+ dc,
+ GetEllipsizeMode(),
+ rect.width,
+ wxELLIPSIZE_FLAGS_NONE
+ );
+ }
+
+ dc.DrawLabel(ellipsizedText.empty() ? text : ellipsizedText,
+ rectText, align);
}
// ---------------------------------------------------------
bool
wxDataViewTextRenderer::RenderWithAttr(wxDC& dc,
const wxRect& rect,
+ int align,
const wxDataViewItemAttr *attr,
int state)
{
- RenderText(dc, rect, m_text, attr, state);
+ RenderText(dc, rect, align, m_text, attr, state);
return true;
}
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;
}
m_value = 0;
}
-wxDataViewProgressRenderer::~wxDataViewProgressRenderer()
-{
-}
-
bool wxDataViewProgressRenderer::SetValue( const wxVariant &value )
{
m_value = (long) value;
return true;
}
-bool wxDataViewProgressRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state) )
+bool wxDataViewProgressRenderer::RenderWithAttr(wxDC& dc,
+ const wxRect& rect,
+ int WXUNUSED(align),
+ const wxDataViewItemAttr *attr,
+ int WXUNUSED(state))
{
- double pct = (double)m_value / 100.0;
- wxRect bar = cell;
- bar.width = (int)(cell.width * pct);
- dc->SetPen( *wxTRANSPARENT_PEN );
- dc->SetBrush( *wxBLUE_BRUSH );
- dc->DrawRectangle( bar );
+ // deflat 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( cell );
+ 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 );
return true;
}
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();
}
SetAlignment(align);
}
-wxDataViewIconTextRenderer::~wxDataViewIconTextRenderer()
-{
-}
-
bool wxDataViewIconTextRenderer::SetValue( const wxVariant &value )
{
m_value << value;
return false;
}
-bool wxDataViewIconTextRenderer::Render( wxRect cell, wxDC *dc, int state )
+bool
+wxDataViewIconTextRenderer::RenderWithAttr(wxDC& dc,
+ const wxRect& rect,
+ int align,
+ const wxDataViewItemAttr *attr,
+ int state)
{
int xoffset = 0;
- const wxIcon &icon = m_value.GetIcon();
- if (icon.IsOk())
+
+ const wxIcon& icon = m_value.GetIcon();
+ if ( icon.IsOk() )
{
- dc->DrawIcon( icon, cell.x, cell.y + ((cell.height - icon.GetHeight()) / 2));
- xoffset = icon.GetWidth()+4;
+ dc.DrawIcon(icon, rect.x, rect.y + (rect.height - icon.GetHeight())/2);
+ xoffset = icon.GetWidth()+4;
}
- RenderText( m_value.GetText(), xoffset, cell, dc, state );
+ RenderText(dc, rect, align, m_value.GetText(), attr, state, xoffset);
return true;
}
model->GetValue( value, item, column->GetModelColumn());
cell->SetValue( value );
- wxSize size = cell->GetSize();
- size.x = wxMin( 2*PADDING_RIGHTLEFT + size.x, width );
- size.y = height;
- wxRect item_rect(x, 0, size.x, size.y);
-
- int align = cell->CalculateAlignment();
- // horizontal alignment:
- item_rect.x = x;
- if (align & wxALIGN_CENTER_HORIZONTAL)
- item_rect.x = x + (width / 2) - (size.x / 2);
- else if (align & wxALIGN_RIGHT)
- item_rect.x = x + width - size.x;
- // else: wxALIGN_LEFT is the default
-
- // vertical alignment:
- item_rect.y = 0;
- if (align & wxALIGN_CENTER_VERTICAL)
- item_rect.y = (height / 2) - (size.y / 2);
- else if (align & wxALIGN_BOTTOM)
- item_rect.y = height - size.y;
- // else: wxALIGN_TOP is the default
-
- // add padding
- item_rect.x += PADDING_RIGHTLEFT;
- item_rect.width = size.x - 2 * PADDING_RIGHTLEFT;
+ 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, hasAttr ? &attr : NULL, 0);
+ cell->RenderWithAttr(dc, item_rect, cell->CalculateAlignment(),
+ hasAttr ? &attr : NULL, 0);
// dc.DestroyClippingRegion();
x += width;
wxDELETE(node);
}
- // cannot be bigger than allocated space
- wxSize size = cell->GetSize();
-
- // Because of the tree structure indent, here we should minus the width
- // of the cell for drawing
- size.x = wxMin( size.x + 2*PADDING_RIGHTLEFT, cell_rect.width - indent );
- // size.y = wxMin( size.y, cell_rect.height );
- size.y = cell_rect.height;
-
- wxRect item_rect(cell_rect.GetTopLeft(), size);
- int align = cell->CalculateAlignment();
-
- // horizontal alignment:
- item_rect.x = cell_rect.x;
- 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
+ wxRect item_rect = cell_rect;
+ item_rect.Deflate(PADDING_RIGHTLEFT, 0);
- // 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
-
- // add padding
- item_rect.x += PADDING_RIGHTLEFT;
- item_rect.width = size.x - 2 * PADDING_RIGHTLEFT;
-
- // Here we add the tree indent
+ // account for the tree indent (harmless if we're not indented)
item_rect.x += indent;
+ item_rect.width -= indent;
int state = 0;
if (m_hasFocus && (m_selection.Index(item) != wxNOT_FOUND))
// respect the given wxRect's top & bottom coords, eventually
// violating only the left & right coords - however the user can
// make its own renderer and thus we cannot be sure of that.
- dc.SetClippingRegion( item_rect );
+ wxDCClipper clip(dc, item_rect);
wxDataViewItemAttr attr;
const bool
hasAttr = model->GetAttr(dataitem, col->GetModelColumn(), attr);
- cell->RenderWithAttr(dc, item_rect, hasAttr ? &attr : NULL, state);
-
- dc.DestroyClippingRegion();
+ cell->RenderWithAttr(dc, item_rect, cell->CalculateAlignment(),
+ hasAttr ? &attr : NULL, state);
}
cell_rect.x += cell_rect.width;