Make wxDataViewCheckIconTextRenderer class public

Export this class, which was only used internally by wxTreeListCtrl
before, so that user code can use it for its own columns with custom
wxDataViewCtrl models.
This commit is contained in:
Vadim Zeitlin
2017-10-02 22:28:28 +02:00
parent 9662be097d
commit f0de65fb98
5 changed files with 357 additions and 250 deletions

View File

@@ -364,7 +364,6 @@ public:
void SetItemData(Node* item, wxClientData* data);
void CheckItem(Node* item, wxCheckBoxState checkedState);
void ToggleItem(wxDataViewItem item);
// Implement the base class pure virtual methods.
@@ -403,214 +402,6 @@ private:
bool m_isFlat;
};
// ============================================================================
// wxDataViewCheckIconText[Renderer]: special renderer for our first column.
// ============================================================================
// Currently this class is private but it could be extracted and made part of
// public API later as could be used directly with wxDataViewCtrl as well.
namespace
{
const char* CHECK_ICON_TEXT_TYPE = "wxDataViewCheckIconText";
// The value used by wxDataViewCheckIconTextRenderer
class wxDataViewCheckIconText : public wxDataViewIconText
{
public:
wxDataViewCheckIconText(const wxString& text = wxString(),
const wxIcon& icon = wxNullIcon,
wxCheckBoxState checkedState = wxCHK_UNDETERMINED)
: wxDataViewIconText(text, icon),
m_checkedState(checkedState)
{
}
wxDataViewCheckIconText(const wxDataViewCheckIconText& other)
: wxDataViewIconText(other),
m_checkedState(other.m_checkedState)
{
}
// There is no encapsulation anyhow, so just expose this field directly.
wxCheckBoxState m_checkedState;
private:
wxDECLARE_DYNAMIC_CLASS(wxDataViewCheckIconText);
};
wxIMPLEMENT_DYNAMIC_CLASS(wxDataViewCheckIconText, wxDataViewIconText);
DECLARE_VARIANT_OBJECT(wxDataViewCheckIconText)
IMPLEMENT_VARIANT_OBJECT(wxDataViewCheckIconText)
class wxDataViewCheckIconTextRenderer : public wxDataViewCustomRenderer
{
public:
wxDataViewCheckIconTextRenderer()
: wxDataViewCustomRenderer(CHECK_ICON_TEXT_TYPE,
wxDATAVIEW_CELL_ACTIVATABLE)
{
}
virtual bool SetValue(const wxVariant& value) wxOVERRIDE
{
m_value << value;
return true;
}
virtual bool GetValue(wxVariant& WXUNUSED(value)) const wxOVERRIDE
{
return false;
}
#if wxUSE_ACCESSIBILITY
virtual wxString GetAccessibleDescription() const wxOVERRIDE
{
wxString text = m_value.GetText();
if ( !text.empty() )
{
text += wxS(" ");
}
switch ( m_value.m_checkedState )
{
case wxCHK_CHECKED:
/* TRANSLATORS: Checkbox state name */
text += _("checked");
break;
case wxCHK_UNCHECKED:
/* TRANSLATORS: Checkbox state name */
text += _("unchecked");
break;
case wxCHK_UNDETERMINED:
/* TRANSLATORS: Checkbox state name */
text += _("undetermined");
break;
}
return text;
}
#endif // wxUSE_ACCESSIBILITY
wxSize GetSize() const wxOVERRIDE
{
wxSize size = GetCheckSize();
size.x += MARGIN_CHECK_ICON;
if ( m_value.GetIcon().IsOk() )
{
const wxSize sizeIcon = m_value.GetIcon().GetSize();
if ( sizeIcon.y > size.y )
size.y = sizeIcon.y;
size.x += sizeIcon.x + MARGIN_ICON_TEXT;
}
wxString text = m_value.GetText();
if ( text.empty() )
text = "Dummy";
const wxSize sizeText = GetTextExtent(text);
if ( sizeText.y > size.y )
size.y = sizeText.y;
size.x += sizeText.x;
return size;
}
virtual bool Render(wxRect cell, wxDC* dc, int state) wxOVERRIDE
{
// Draw the checkbox first.
int renderFlags = 0;
switch ( m_value.m_checkedState )
{
case wxCHK_UNCHECKED:
break;
case wxCHK_CHECKED:
renderFlags |= wxCONTROL_CHECKED;
break;
case wxCHK_UNDETERMINED:
renderFlags |= wxCONTROL_UNDETERMINED;
break;
}
if ( state & wxDATAVIEW_CELL_PRELIT )
renderFlags |= wxCONTROL_CURRENT;
const wxSize sizeCheck = GetCheckSize();
wxRect rectCheck(cell.GetPosition(), sizeCheck);
rectCheck = rectCheck.CentreIn(cell, wxVERTICAL);
wxRendererNative::Get().DrawCheckBox
(
GetView(), *dc, rectCheck, renderFlags
);
// Then the icon, if any.
int xoffset = sizeCheck.x + MARGIN_CHECK_ICON;
const wxIcon& icon = m_value.GetIcon();
if ( icon.IsOk() )
{
const wxSize sizeIcon = icon.GetSize();
wxRect rectIcon(cell.GetPosition(), sizeIcon);
rectIcon.x += xoffset;
rectIcon = rectIcon.CentreIn(cell, wxVERTICAL);
dc->DrawIcon(icon, rectIcon.GetPosition());
xoffset += sizeIcon.x + MARGIN_ICON_TEXT;
}
// Finally the text.
RenderText(m_value.GetText(), xoffset, cell, dc, state);
return true;
}
// Event handlers toggling the items checkbox if it was clicked.
virtual bool ActivateCell(const wxRect& WXUNUSED(cell),
wxDataViewModel *model,
const wxDataViewItem & item,
unsigned int WXUNUSED(col),
const wxMouseEvent *mouseEvent) wxOVERRIDE
{
if ( mouseEvent )
{
if ( !wxRect(GetCheckSize()).Contains(mouseEvent->GetPosition()) )
return false;
}
static_cast<wxTreeListModel*>(model)->ToggleItem(item);
return true;
}
protected:
wxSize GetCheckSize() const
{
return wxRendererNative::Get().GetCheckBoxSize(GetView());
}
private:
// Just some arbitrary constants defining margins, in pixels.
enum
{
MARGIN_CHECK_ICON = 3,
MARGIN_ICON_TEXT = 4
};
wxDataViewCheckIconText m_value;
};
} // anonymous namespace
// ============================================================================
// wxTreeListModel implementation
// ============================================================================
@@ -837,40 +628,6 @@ void wxTreeListModel::CheckItem(Node* item, wxCheckBoxState checkedState)
ItemChanged(ToDVI(item));
}
void wxTreeListModel::ToggleItem(wxDataViewItem dvi)
{
Node* const item = FromDVI(dvi);
wxCHECK_RET( item, "Invalid item" );
const wxCheckBoxState stateOld = item->m_checkedState;
// If the 3rd state is user-settable then the cycle is
// unchecked->checked->undetermined.
switch ( stateOld )
{
case wxCHK_CHECKED:
item->m_checkedState = m_treelist->HasFlag(wxTL_USER_3STATE)
? wxCHK_UNDETERMINED
: wxCHK_UNCHECKED;
break;
case wxCHK_UNDETERMINED:
// Whether 3rd state is user-settable or not, the next state is
// unchecked.
item->m_checkedState = wxCHK_UNCHECKED;
break;
case wxCHK_UNCHECKED:
item->m_checkedState = wxCHK_CHECKED;
break;
}
ItemChanged(ToDVI(item));
m_treelist->OnItemToggled(item, stateOld);
}
unsigned wxTreeListModel::GetColumnCount() const
{
return m_numColumns;
@@ -881,8 +638,8 @@ wxString wxTreeListModel::GetColumnType(unsigned col) const
if ( col == 0 )
{
return m_treelist->HasFlag(wxTL_CHECKBOX)
? wxS("wxDataViewCheckIconText")
: wxS("wxDataViewIconText");
? wxDataViewCheckIconTextRenderer::GetDefaultType()
: wxDataViewIconTextRenderer::GetDefaultType();
}
else // All the other columns contain just text.
{
@@ -928,12 +685,26 @@ wxTreeListModel::GetValue(wxVariant& variant,
}
bool
wxTreeListModel::SetValue(const wxVariant& WXUNUSED(variant),
const wxDataViewItem& WXUNUSED(item),
wxTreeListModel::SetValue(const wxVariant& variant,
const wxDataViewItem& item,
unsigned WXUNUSED(col))
{
// We are not editable currently.
return false;
Node* const node = FromDVI(item);
wxCHECK_MSG( item, false, "Invalid item" );
const wxCheckBoxState stateOld = node->m_checkedState;
// We don't allow changing anything but the checked state currently, yet we
// still get the full wxVariant containing the text and the icon as well,
// so we need to extract just the part we're interested in from it first.
wxDataViewCheckIconText value;
value << variant;
node->m_checkedState = value.GetCheckedState();
m_treelist->OnItemToggled(node, stateOld);
return true;
}
wxDataViewItem wxTreeListModel::GetParent(const wxDataViewItem& item) const
@@ -1122,7 +893,12 @@ wxTreeListCtrl::DoInsertColumn(const wxString& title,
if ( HasFlag(wxTL_CHECKBOX) )
{
// Use our custom renderer to show the checkbox.
renderer = new wxDataViewCheckIconTextRenderer;
wxDataViewCheckIconTextRenderer* const
rendererCheckIconText = new wxDataViewCheckIconTextRenderer;
if ( HasFlag(wxTL_USER_3STATE) )
rendererCheckIconText->Allow3rdStateForUser();
renderer = rendererCheckIconText;
}
else // We still need a special renderer to show the icons.
{