Add wxDataViewValueAdjuster

Add wxDataViewRenderer:: SetValueAdjuster() and a
wxDataViewValueAdjuster class. This can be used to customize rendering
of values depending on whether they are highlighted (selection) or not,
without having to implement an entire new custom renderer.
This commit is contained in:
Václav Slavík 2016-11-21 18:07:32 +01:00 committed by Václav Slavík
parent 13862ad8e6
commit ff1dba498e
9 changed files with 152 additions and 6 deletions

View File

@ -96,6 +96,16 @@ enum wxDataViewCellRenderState
wxDATAVIEW_CELL_FOCUSED = 8
};
// helper for fine-tuning rendering of values depending on row's state
class WXDLLIMPEXP_ADV wxDataViewValueAdjuster
{
public:
virtual ~wxDataViewValueAdjuster() {}
// changes the value to have appearance suitable for highlighted rows
virtual wxVariant MakeHighlighted(const wxVariant& value) const { return value; }
};
class WXDLLIMPEXP_ADV wxDataViewRendererBase: public wxObject
{
public:
@ -190,6 +200,10 @@ public:
// Send wxEVT_DATAVIEW_ITEM_EDITING_STARTED event.
void NotifyEditingStarted(const wxDataViewItem& item);
// Sets the transformer for fine-tuning rendering of values depending on row's state
void SetValueAdjuster(wxDataViewValueAdjuster *transformer)
{ delete m_valueAdjuster; m_valueAdjuster = transformer; }
protected:
// These methods are called from PrepareForItem() and should do whatever is
// needed for the current platform to ensure that the item is rendered
@ -197,6 +211,10 @@ protected:
virtual void SetAttr(const wxDataViewItemAttr& attr) = 0;
virtual void SetEnabled(bool enabled) = 0;
// Return whether the currently rendered item is on a highlighted row
// (typically selection with dark background). For internal use only.
virtual bool IsHighlighted() const = 0;
// Called from {Cancel,Finish}Editing() to cleanup m_editorCtrl
void DestroyEditControl();
@ -211,6 +229,8 @@ protected:
wxWeakRef<wxWindow> m_editorCtrl;
wxDataViewItem m_item; // Item being currently edited, if valid.
wxDataViewValueAdjuster *m_valueAdjuster;
// internal utility, may be used anywhere the window associated with the
// renderer is required
wxDataViewCtrl* GetView() const;

View File

@ -52,6 +52,12 @@ public:
const wxMouseEvent* WXUNUSED(mouseEvent))
{ return false; }
void SetState(int state) { m_state = state; }
protected:
virtual bool IsHighlighted() const wxOVERRIDE
{ return m_state & wxDATAVIEW_CELL_SELECTED; }
private:
int m_align;
wxDataViewCellMode m_mode;
@ -60,6 +66,8 @@ private:
wxDC *m_dc;
int m_state;
wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewRenderer);
};

View File

@ -64,6 +64,8 @@ public:
// different from the editor control widget for the custom renderers
virtual GtkWidget* GtkGetEditorWidget() const;
void GtkSetCurrentItem(const wxDataViewItem& item) { m_itemBeingRendered = item; }
private:
// Change the mode at GTK level without touching m_mode, this is useful for
// temporarily making the renderer insensitive but does mean that GetMode()
@ -74,6 +76,8 @@ protected:
virtual void SetAttr(const wxDataViewItemAttr& attr) wxOVERRIDE;
virtual void SetEnabled(bool enabled) wxOVERRIDE;
virtual bool IsHighlighted() const wxOVERRIDE;
virtual void GtkOnCellChanged(const wxVariant& value,
const wxDataViewItem& item,
unsigned col);
@ -93,6 +97,9 @@ protected:
// doing this
bool m_usingDefaultAttrs;
// the item currently being rendered
wxDataViewItem m_itemBeingRendered;
protected:
wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewRenderer);
};

View File

@ -93,6 +93,8 @@ protected:
void SetEnabled(bool WXUNUSED(enabled)) wxOVERRIDE { };
#endif
virtual bool IsHighlighted() const wxOVERRIDE;
private:
// contains the alignment flags
int m_alignment;

View File

@ -1925,6 +1925,28 @@ public:
*/
virtual bool SetValue(const wxVariant& value) = 0;
/**
Set the transformer object to be used to customize values before they
are rendered.
Can be used to change the value if it is shown on a highlighted row
(i.e. in selection) which typically has dark background. It is useful
in combination with wxDataViewTextRenderer with markup and can be used
e.g. to remove background color attributes inside selection, as a
lightweight alternative to implementing an entire
wxDataViewCustomRenderer specialization.
@a transformer can be @NULL to reset any transformer currently being
used.
Takes ownership of @a transformer.
@see wxDataViewValueAdjuster
@since 3.1.1
*/
void SetValueAdjuster(wxDataViewValueAdjuster *transformer);
/**
Before data is committed to the data model, it is passed to this
method where it can be checked for validity. This can also be
@ -3662,3 +3684,66 @@ public:
};
/**
@class wxDataViewValueAdjuster
This class can be used with wxDataViewRenderer::SetValueAdjuster() to
customize rendering of model values with standard renderers.
Can be used to change the value if it is shown on a highlighted row (i.e.
in selection) which typically has dark background. It is useful in
combination with wxDataViewTextRenderer with markup and can be used e.g. to
remove background color attributes inside selection, as a lightweight
alternative to implementing an entire wxDataViewCustomRenderer
specialization.
@example
// Markup renderer that removes bgcolor attributes when in selection
class DataViewMarkupRenderer : public wxDataViewTextRenderer
{
public:
DataViewMarkupRenderer()
{
EnableMarkup();
SetValueAdjuster(new Adjuster());
}
private:
class Adjuster : public wxDataViewValueAdjuster
{
public:
wxVariant MakeHighlighted(const wxVariant& value) const override
{
wxString s = value.GetString();
size_t pos = s.find(" bgcolor=\"");
if (pos != wxString::npos)
{
size_t pos2 = s.find('"', pos + 10);
s.erase(pos, pos2 - pos + 1);
return s;
}
return value;
}
};
};
@endexample
@since 3.1.1
@library{wxadv}
@category{dvc}
*/
class wxDataViewValueAdjuster
{
public:
/**
Change value for rendering when highlighted.
Override to customize the value when it is shown in a highlighted
(selected) row, typically on a dark background.
Default implementation returns @a value unmodified.
*/
virtual wxVariant MakeHighlighted(const wxVariant& value) const;
};

View File

@ -658,12 +658,14 @@ wxDataViewRendererBase::wxDataViewRendererBase( const wxString &varianttype,
{
m_variantType = varianttype;
m_owner = NULL;
m_valueAdjuster = NULL;
}
wxDataViewRendererBase::~wxDataViewRendererBase()
{
if ( m_editorCtrl )
DestroyEditControl();
delete m_valueAdjuster;
}
wxDataViewCtrl* wxDataViewRendererBase::GetView() const
@ -830,7 +832,14 @@ wxDataViewRendererBase::PrepareForItem(const wxDataViewModel *model,
// Now check if we have a value and remember it for rendering it later.
// Notice that we do it even if it's null, as the cell should be empty then
// and not show the last used value.
const wxVariant& value = CheckedGetValue(model, item, column);
wxVariant value = CheckedGetValue(model, item, column);
if ( m_valueAdjuster )
{
if ( IsHighlighted() )
value = m_valueAdjuster->MakeHighlighted(value);
}
SetValue(value);
if ( !value.IsNull() )

View File

@ -969,6 +969,7 @@ wxDataViewRenderer::wxDataViewRenderer( const wxString &varianttype,
m_mode = mode;
m_ellipsizeMode = wxELLIPSIZE_MIDDLE;
m_dc = NULL;
m_state = 0;
}
wxDataViewRenderer::~wxDataViewRenderer()
@ -2264,10 +2265,16 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
cell_rect.y = GetLineStart( item );
cell_rect.height = GetLineHeight( item );
bool selected = m_selection.IsSelected(item);
int state = 0;
if (m_hasFocus && selected)
state |= wxDATAVIEW_CELL_SELECTED;
cell->SetState(state);
cell->PrepareForItem(model, dataitem, col->GetModelColumn());
// draw the background
bool selected = m_selection.IsSelected(item);
if ( !selected )
DrawCellBackground( cell, dc, cell_rect );
@ -2323,10 +2330,6 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
if ( item_rect.width <= 0 )
continue;
int state = 0;
if (m_hasFocus && selected)
state |= wxDATAVIEW_CELL_SELECTED;
// TODO: it would be much more efficient to create a clipping
// region for the entire column being rendered (in the OnPaint
// of wxDataViewMainWindow) instead of a single clip region for

View File

@ -2128,6 +2128,12 @@ wxEllipsizeMode wxDataViewRenderer::GetEllipsizeMode() const
return mode;
}
bool wxDataViewRenderer::IsHighlighted() const
{
return m_itemBeingRendered.IsOk() &&
GetOwner()->GetOwner()->IsSelected(m_itemBeingRendered);
}
void
wxDataViewRenderer::GtkOnTextEdited(const char *itempath, const wxString& str)
{
@ -3078,6 +3084,7 @@ static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *WXUNUSED(column),
return;
}
cell->GtkSetCurrentItem(item);
cell->PrepareForItem(wx_model, item, column);
}

View File

@ -2767,6 +2767,11 @@ wxEllipsizeMode wxDataViewRenderer::GetEllipsizeMode() const
return GetNativeData()->GetEllipsizeMode();
}
bool wxDataViewRenderer::IsHighlighted() const
{
return [GetNativeData()->GetColumnCell() backgroundStyle] == NSBackgroundStyleDark;
}
void
wxDataViewRenderer::OSXOnCellChanged(NSObject *object,
const wxDataViewItem& item,