diff --git a/docs/changes.txt b/docs/changes.txt
index 81c64a89c6..290420065b 100644
--- a/docs/changes.txt
+++ b/docs/changes.txt
@@ -85,8 +85,10 @@ All (GUI):
- Fix vertical scrollbar visibility in wxStyledTextCtrl (yenwu, NewPagodi).
- Fix bug with not being able to select AUI tab after dragging.
- Make wxDataViewCtrl::Expand() expand ancestors in native ports too.
+- Add wxDataViewTextRenderer::EnableMarkup().
- Add wxDataViewCtrl::SetHeaderAttr().
- Add wxListCtrl::SetHeaderAttr().
+- Add support for using markup in wxDataViewCtrl text items.
- Implement auto complete in generic wxSearchCtrl (Eric Jensen).
wxGTK:
diff --git a/include/wx/generic/dvrenderers.h b/include/wx/generic/dvrenderers.h
index a56beaf034..3e7f6825af 100644
--- a/include/wx/generic/dvrenderers.h
+++ b/include/wx/generic/dvrenderers.h
@@ -53,6 +53,11 @@ public:
wxDataViewTextRenderer( const wxString &varianttype = GetDefaultType(),
wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT,
int align = wxDVR_DEFAULT_ALIGNMENT );
+ virtual ~wxDataViewTextRenderer();
+
+#if wxUSE_MARKUP
+ void EnableMarkup(bool enable = true);
+#endif // wxUSE_MARKUP
virtual bool SetValue( const wxVariant &value );
virtual bool GetValue( wxVariant &value ) const;
@@ -69,7 +74,11 @@ public:
protected:
wxString m_text;
-protected:
+private:
+#if wxUSE_MARKUP
+ class wxMarkupText *m_markupText;
+#endif // wxUSE_MARKUP
+
wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewTextRenderer);
};
diff --git a/include/wx/generic/private/markuptext.h b/include/wx/generic/private/markuptext.h
index 1d9569229e..eba3f2252d 100644
--- a/include/wx/generic/private/markuptext.h
+++ b/include/wx/generic/private/markuptext.h
@@ -15,6 +15,8 @@
class WXDLLIMPEXP_FWD_CORE wxDC;
class WXDLLIMPEXP_FWD_CORE wxRect;
+class wxMarkupParserOutput;
+
// ----------------------------------------------------------------------------
// wxMarkupText: allows to measure and draw the text containing markup.
// ----------------------------------------------------------------------------
@@ -53,6 +55,11 @@ public:
// The same rules for mnemonics as in the ctor apply to this string.
void SetMarkup(const wxString& markup) { m_markup = markup; }
+ // This is a convenience method which can be used with the string in which
+ // mnemonics should be completely ignored, i.e. not interpreted in any way
+ // but just handled as ordinary characters.
+ void SetMarkupText(const wxString& markup);
+
// Return the width and height required by the given string and optionally
// the height of the visible part above the baseline (i.e. ascent minus
@@ -70,6 +77,18 @@ public:
// and set the clipping region before rendering if necessary.
void Render(wxDC& dc, const wxRect& rect, int flags);
+ // Similar to Render(), but uses wxRendererNative::DrawItemText() instead
+ // of generic wxDC::DrawLabel(), so is more suitable for use in controls
+ // that already use DrawItemText() for its items.
+ //
+ // The meaning of the flags here is different than in the overload above:
+ // they're passed to DrawItemText() and Render_ShowAccels is not supported
+ // here.
+ void RenderItemText(wxWindow *win,
+ wxDC& dc,
+ const wxRect& rect,
+ int rendererFlags);
+
private:
wxString m_markup;
};
diff --git a/include/wx/gtk/dvrenderers.h b/include/wx/gtk/dvrenderers.h
index 68e4d4a980..3305203057 100644
--- a/include/wx/gtk/dvrenderers.h
+++ b/include/wx/gtk/dvrenderers.h
@@ -31,6 +31,10 @@ public:
wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT,
int align = wxDVR_DEFAULT_ALIGNMENT );
+#if wxUSE_MARKUP
+ void EnableMarkup(bool enable = true);
+#endif // wxUSE_MARKUP
+
virtual bool SetValue( const wxVariant &value ) wxOVERRIDE
{
return SetTextValue(value);
@@ -58,6 +62,14 @@ protected:
bool SetTextValue(const wxString& str);
bool GetTextValue(wxString& str) const;
+ // Return the name of the GtkCellRendererText property to use: "text" or
+ // "markup".
+ const char* GetTextPropertyName() const;
+
+#if wxUSE_MARKUP
+ // True if we should interpret markup in our text.
+ bool m_useMarkup;
+#endif // wxUSE_MARKUP
wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewTextRenderer);
};
diff --git a/include/wx/osx/dvrenderers.h b/include/wx/osx/dvrenderers.h
index 4da26441a6..c62a19ffb5 100644
--- a/include/wx/osx/dvrenderers.h
+++ b/include/wx/osx/dvrenderers.h
@@ -55,6 +55,10 @@ public:
wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT,
int align = wxDVR_DEFAULT_ALIGNMENT);
+#if wxUSE_MARKUP && wxOSX_USE_COCOA
+ void EnableMarkup(bool enable = true);
+#endif // wxUSE_MARKUP && Cocoa
+
virtual bool MacRender();
virtual void OSXOnCellChanged(NSObject *value,
@@ -62,6 +66,11 @@ public:
unsigned col);
private:
+#if wxUSE_MARKUP && wxOSX_USE_COCOA
+ // True if we should interpret markup in our text.
+ bool m_useMarkup;
+#endif // wxUSE_MARKUP && Cocoa
+
wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewTextRenderer);
};
diff --git a/interface/wx/dataview.h b/interface/wx/dataview.h
index 2c29c76049..e68a589097 100644
--- a/interface/wx/dataview.h
+++ b/interface/wx/dataview.h
@@ -1966,6 +1966,49 @@ public:
wxDataViewTextRenderer(const wxString& varianttype = GetDefaultType(),
wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT,
int align = wxDVR_DEFAULT_ALIGNMENT );
+
+ /**
+ Enable interpretation of markup in the item data.
+
+ If this method is called with @true argument, markup (@ref
+ wxControl::SetLabelMarkup()) in the data of the items in this column
+ will be interpreted, which can be used for a more fine-grained
+ appearance control than just setting an attribute, which affects all of
+ the item text.
+
+ For example, as shown in the @ref page_samples_dataview, after creating
+ a column using a markup-enabled renderer:
+ @code
+ wxDataViewTextRenderer* renderer = new wxDataViewTextRenderer();
+ renderer->EnableMarkup();
+ dataViewCtrl->AppendColumn(new wxDataViewColumn("title", renderer, 0));
+ @endcode
+
+ The overridden model wxDataViewModel::GetValue() method may return
+ values containing markup for this column:
+ @code
+ void MyModel::GetValue(wxVariant& variant,
+ const wxDataViewItem& item,
+ unsigned int col) const
+ {
+ if ( col == 0 && item == ... )
+ {
+ variant = "light and "
+ "dark blue";
+ }
+
+ ...
+ }
+ @endcode
+
+ @note Currently wxDataViewIconTextRenderer only provides EnableMarkup()
+ EnableMarkup() in wxGTK, but not under the other platforms, so you
+ should only use it for plain wxDataViewTextRenderer columns,
+ without icons, in portable code.
+
+ @since 3.1.1
+ */
+ void EnableMarkup(bool enable = true);
};
diff --git a/samples/dataview/dataview.cpp b/samples/dataview/dataview.cpp
index fca7630647..6cd58d97b6 100644
--- a/samples/dataview/dataview.cpp
+++ b/samples/dataview/dataview.cpp
@@ -702,9 +702,14 @@ void MyFrame::BuildDataViewCtrl(wxPanel* parent, unsigned int nPanel, unsigned l
m_ctrl[1]->AppendDateColumn("date",
MyListModel::Col_Date);
+
+ wxDataViewTextRenderer* const markupRenderer = new wxDataViewTextRenderer();
+#if wxUSE_MARKUP
+ markupRenderer->EnableMarkup();
+#endif // wxUSE_MARKUP
m_attributes =
new wxDataViewColumn("attributes",
- new wxDataViewTextRenderer,
+ markupRenderer,
MyListModel::Col_TextWithAttr,
wxCOL_WIDTH_AUTOSIZE,
wxALIGN_RIGHT,
diff --git a/samples/dataview/mymodels.cpp b/samples/dataview/mymodels.cpp
index bf6b219206..1ee62f8083 100644
--- a/samples/dataview/mymodels.cpp
+++ b/samples/dataview/mymodels.cpp
@@ -436,7 +436,14 @@ void MyListModel::GetValueByRow( wxVariant &variant,
{
static const char *labels[5] =
{
- "blue", "green", "red", "bold cyan", "default",
+ // These strings will look wrong without wxUSE_MARKUP, but
+ // it's just a sample, so we don't care.
+ "light and "
+ "dark blue",
+ "growing green",
+ "emphatic red",
+ "bold cyan",
+ "dull default",
};
variant = labels[row % 5];
diff --git a/src/common/datavcmn.cpp b/src/common/datavcmn.cpp
index e4e5521bd8..f8dcfee354 100644
--- a/src/common/datavcmn.cpp
+++ b/src/common/datavcmn.cpp
@@ -1005,7 +1005,7 @@ wxDataViewCustomRendererBase::RenderText(const wxString& text,
int flags = 0;
if ( state & wxDATAVIEW_CELL_SELECTED )
- flags |= wxCONTROL_SELECTED | wxCONTROL_FOCUSED;
+ flags |= wxCONTROL_SELECTED;
if ( !GetOwner()->GetOwner()->IsEnabled() )
flags |= wxCONTROL_DISABLED;
diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp
index a18f8a5cd2..24d8a36010 100644
--- a/src/generic/datavgen.cpp
+++ b/src/generic/datavgen.cpp
@@ -50,6 +50,7 @@
#include "wx/selstore.h"
#include "wx/stopwatch.h"
#include "wx/weakref.h"
+#include "wx/generic/private/markuptext.h"
#include "wx/generic/private/widthcalc.h"
//-----------------------------------------------------------------------------
@@ -1004,12 +1005,48 @@ wxDataViewTextRenderer::wxDataViewTextRenderer( const wxString &varianttype,
wxDataViewCellMode mode, int align ) :
wxDataViewRenderer( varianttype, mode, align )
{
+#if wxUSE_MARKUP
+ m_markupText = NULL;
+#endif // wxUSE_MARKUP
}
+wxDataViewTextRenderer::~wxDataViewTextRenderer()
+{
+#if wxUSE_MARKUP
+ delete m_markupText;
+#endif // wxUSE_MARKUP
+}
+
+#if wxUSE_MARKUP
+void wxDataViewTextRenderer::EnableMarkup(bool enable)
+{
+ if ( enable )
+ {
+ if ( !m_markupText )
+ {
+ m_markupText = new wxMarkupText(wxString());
+ }
+ }
+ else
+ {
+ if ( m_markupText )
+ {
+ delete m_markupText;
+ m_markupText = NULL;
+ }
+ }
+}
+#endif // wxUSE_MARKUP
+
bool wxDataViewTextRenderer::SetValue( const wxVariant &value )
{
m_text = value.GetString();
+#if wxUSE_MARKUP
+ if ( m_markupText )
+ m_markupText->SetMarkupText(m_text);
+#endif // wxUSE_MARKUP
+
return true;
}
@@ -1038,14 +1075,39 @@ bool wxDataViewTextRenderer::GetValueFromEditorCtrl( wxWindow *editor, wxVariant
bool wxDataViewTextRenderer::Render(wxRect rect, wxDC *dc, int state)
{
- RenderText(m_text, 0, rect, dc, state);
+#if wxUSE_MARKUP
+ if ( m_markupText )
+ {
+ int flags = 0;
+ if ( state & wxDATAVIEW_CELL_SELECTED )
+ flags |= wxCONTROL_SELECTED;
+ m_markupText->RenderItemText(GetView(), *dc, rect, flags);
+ }
+ else
+#endif // wxUSE_MARKUP
+ RenderText(m_text, 0, rect, dc, state);
+
return true;
}
wxSize wxDataViewTextRenderer::GetSize() const
{
if (!m_text.empty())
+ {
+#if wxUSE_MARKUP
+ if ( m_markupText )
+ {
+ wxDataViewCtrl* const view = GetView();
+ wxClientDC dc(view);
+ if ( GetAttr().HasFont() )
+ dc.SetFont(GetAttr().GetEffectiveFont(view->GetFont()));
+
+ return m_markupText->Measure(dc);
+ }
+#endif // wxUSE_MARKUP
+
return GetTextExtent(m_text);
+ }
else
return wxSize(wxDVC_DEFAULT_RENDERER_SIZE,wxDVC_DEFAULT_RENDERER_SIZE);
}
diff --git a/src/generic/markuptext.cpp b/src/generic/markuptext.cpp
index 6516e791c0..d226246814 100644
--- a/src/generic/markuptext.cpp
+++ b/src/generic/markuptext.cpp
@@ -30,6 +30,8 @@
#include "wx/dc.h"
#endif // WX_PRECOMP
+#include "wx/renderer.h"
+
#include "wx/generic/private/markuptext.h"
#include "wx/private/markupparserattr.h"
@@ -132,35 +134,6 @@ public:
m_origTextBackground = dc.GetTextBackground();
}
- virtual void OnText(const wxString& text_) wxOVERRIDE
- {
- wxString text;
- int indexAccel = wxControl::FindAccelIndex(text_, &text);
- if ( !(m_flags & wxMarkupText::Render_ShowAccels) )
- indexAccel = wxNOT_FOUND;
-
- // Adjust the position (unfortunately we need to do this manually as
- // there is no notion of current text position in wx API) rectangle to
- // ensure that all text segments use the same baseline (as there is
- // nothing equivalent to Windows SetTextAlign(TA_BASELINE) neither).
- wxRect rect(m_rect);
- rect.x = m_pos;
-
- int descent;
- m_dc.GetTextExtent(text, &rect.width, &rect.height, &descent);
- rect.height -= descent;
- rect.y += m_rect.height - rect.height;
-
- wxRect bounds;
- m_dc.DrawLabel(text, wxBitmap(),
- rect, wxALIGN_LEFT | wxALIGN_TOP,
- indexAccel,
- &bounds);
-
- // TODO-MULTILINE-MARKUP: Must update vertical position too.
- m_pos += bounds.width;
- }
-
virtual void OnAttrStart(const Attr& attr) wxOVERRIDE
{
m_dc.SetFont(attr.font);
@@ -202,7 +175,7 @@ public:
}
}
-private:
+protected:
wxDC& m_dc;
const wxRect m_rect;
const int m_flags;
@@ -217,12 +190,96 @@ private:
wxDECLARE_NO_COPY_CLASS(wxMarkupParserRenderOutput);
};
+// An output renderer suitable for control labels.
+class wxMarkupParserRenderLabelOutput : public wxMarkupParserRenderOutput
+{
+public:
+ wxMarkupParserRenderLabelOutput(wxDC& dc,
+ const wxRect& rect,
+ int flags)
+ : wxMarkupParserRenderOutput(dc, rect, flags)
+ {
+ }
+
+ virtual void OnText(const wxString& text_) wxOVERRIDE
+ {
+ wxString text;
+ int indexAccel = wxControl::FindAccelIndex(text_, &text);
+ if ( !(m_flags & wxMarkupText::Render_ShowAccels) )
+ indexAccel = wxNOT_FOUND;
+
+ // Adjust the position (unfortunately we need to do this manually as
+ // there is no notion of current text position in wx API) rectangle to
+ // ensure that all text segments use the same baseline (as there is
+ // nothing equivalent to Windows SetTextAlign(TA_BASELINE) neither).
+ wxRect rect(m_rect);
+ rect.x = m_pos;
+
+ int descent;
+ m_dc.GetTextExtent(text, &rect.width, &rect.height, &descent);
+ rect.height -= descent;
+ rect.y += m_rect.height - rect.height;
+
+ wxRect bounds;
+ m_dc.DrawLabel(text, wxBitmap(),
+ rect, wxALIGN_LEFT | wxALIGN_TOP,
+ indexAccel,
+ &bounds);
+
+ m_pos += bounds.width;
+ }
+};
+
+// An output renderer suitable for multi-item controls items.
+class wxMarkupParserRenderItemOutput : public wxMarkupParserRenderOutput
+{
+public:
+ wxMarkupParserRenderItemOutput(wxWindow *win,
+ wxDC& dc,
+ const wxRect& rect,
+ int rendererFlags)
+ : wxMarkupParserRenderOutput(dc, rect, wxMarkupText::Render_Default),
+ m_win(win),
+ m_rendererFlags(rendererFlags),
+ m_renderer(&wxRendererNative::Get())
+ {
+ }
+
+ virtual void OnText(const wxString& text) wxOVERRIDE
+ {
+ wxRect rect(m_rect);
+ rect.x = m_pos;
+
+ m_renderer->DrawItemText(m_win,
+ m_dc,
+ wxControl::RemoveMnemonics(text),
+ rect,
+ wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL,
+ m_rendererFlags,
+ wxELLIPSIZE_NONE);
+
+ m_pos += m_dc.GetTextExtent(text).x;
+ }
+
+private:
+ wxWindow* const m_win;
+ int const m_rendererFlags;
+ wxRendererNative* const m_renderer;
+
+ wxDECLARE_NO_COPY_CLASS(wxMarkupParserRenderItemOutput);
+};
+
} // anonymous namespace
// ============================================================================
// wxMarkupText implementation
// ============================================================================
+void wxMarkupText::SetMarkupText(const wxString& markup)
+{
+ m_markup = wxControl::EscapeMnemonics(markup);
+}
+
wxSize wxMarkupText::Measure(wxDC& dc, int *visibleHeight) const
{
wxMarkupParserMeasureOutput out(dc, visibleHeight);
@@ -245,7 +302,17 @@ void wxMarkupText::Render(wxDC& dc, const wxRect& rect, int flags)
wxRect rectText(rect.GetPosition(), Measure(dc, &visibleHeight));
rectText.height = visibleHeight;
- wxMarkupParserRenderOutput out(dc, rectText.CentreIn(rect), flags);
+ wxMarkupParserRenderLabelOutput out(dc, rectText.CentreIn(rect), flags);
+ wxMarkupParser parser(out);
+ parser.Parse(m_markup);
+}
+
+void wxMarkupText::RenderItemText(wxWindow *win,
+ wxDC& dc,
+ const wxRect& rect,
+ int rendererFlags)
+{
+ wxMarkupParserRenderItemOutput out(win, dc, rect, rendererFlags);
wxMarkupParser parser(out);
parser.Parse(m_markup);
}
diff --git a/src/generic/renderg.cpp b/src/generic/renderg.cpp
index b76c96b9bf..1961141fc4 100644
--- a/src/generic/renderg.cpp
+++ b/src/generic/renderg.cpp
@@ -938,14 +938,7 @@ wxRendererGeneric::DrawItemText(wxWindow* WXUNUSED(win),
wxColour textColour;
if ( flags & wxCONTROL_SELECTED )
{
- if ( flags & wxCONTROL_FOCUSED )
- {
- textColour = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
- }
- else // !focused
- {
- textColour = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOXTEXT);
- }
+ textColour = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
}
else if ( flags & wxCONTROL_DISABLED )
{
diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp
index 8be64c4633..9a3c82e39c 100644
--- a/src/gtk/dataview.cpp
+++ b/src/gtk/dataview.cpp
@@ -2277,6 +2277,10 @@ wxDataViewTextRenderer::wxDataViewTextRenderer( const wxString &varianttype, wxD
int align ) :
wxDataViewRenderer( varianttype, mode, align )
{
+#if wxUSE_MARKUP
+ m_useMarkup = false;
+#endif // wxUSE_MARKUP
+
GtkWxCellRendererText *text_renderer = gtk_wx_cell_renderer_text_new();
text_renderer->wx_renderer = this;
m_renderer = (GtkCellRenderer*) text_renderer;
@@ -2298,12 +2302,29 @@ wxDataViewTextRenderer::wxDataViewTextRenderer( const wxString &varianttype, wxD
SetAlignment(align);
}
+#if wxUSE_MARKUP
+void wxDataViewTextRenderer::EnableMarkup(bool enable)
+{
+ m_useMarkup = enable;
+}
+#endif // wxUSE_MARKUP
+
+const char* wxDataViewTextRenderer::GetTextPropertyName() const
+{
+#if wxUSE_MARKUP
+ if ( m_useMarkup )
+ return "markup";
+#endif // wxUSE_MARKUP
+
+ return "text";
+}
+
bool wxDataViewTextRenderer::SetTextValue(const wxString& str)
{
GValue gvalue = G_VALUE_INIT;
g_value_init( &gvalue, G_TYPE_STRING );
g_value_set_string( &gvalue, wxGTK_CONV_FONT( str, GetOwner()->GetOwner()->GetFont() ) );
- g_object_set_property( G_OBJECT(m_renderer), "text", &gvalue );
+ g_object_set_property( G_OBJECT(m_renderer), GetTextPropertyName(), &gvalue );
g_value_unset( &gvalue );
return true;
@@ -2313,7 +2334,7 @@ bool wxDataViewTextRenderer::GetTextValue(wxString& str) const
{
GValue gvalue = G_VALUE_INIT;
g_value_init( &gvalue, G_TYPE_STRING );
- g_object_get_property( G_OBJECT(m_renderer), "text", &gvalue );
+ g_object_get_property( G_OBJECT(m_renderer), GetTextPropertyName(), &gvalue );
str = wxGTK_CONV_BACK_FONT( g_value_get_string( &gvalue ), const_cast(this)->GetOwner()->GetOwner()->GetFont() );
g_value_unset( &gvalue );
diff --git a/src/osx/cocoa/dataview.mm b/src/osx/cocoa/dataview.mm
index db4f96d6d1..427945316c 100644
--- a/src/osx/cocoa/dataview.mm
+++ b/src/osx/cocoa/dataview.mm
@@ -30,6 +30,10 @@
#include "wx/stopwatch.h"
#include "wx/dcgraph.h"
+#if wxUSE_MARKUP
+ #include "wx/osx/cocoa/private/markuptoattr.h"
+#endif // wxUSE_MARKUP
+
// ============================================================================
// Constants used locally
// ============================================================================
@@ -2730,6 +2734,10 @@ wxDataViewTextRenderer::wxDataViewTextRenderer(const wxString& varianttype,
int align)
: wxDataViewRenderer(varianttype,mode,align)
{
+#if wxUSE_MARKUP
+ m_useMarkup = false;
+#endif // wxUSE_MARKUP
+
NSTextFieldCell* cell;
@@ -2739,8 +2747,27 @@ wxDataViewTextRenderer::wxDataViewTextRenderer(const wxString& varianttype,
[cell release];
}
+#if wxUSE_MARKUP
+
+void wxDataViewTextRenderer::EnableMarkup(bool enable)
+{
+ m_useMarkup = enable;
+}
+
+#endif // wxUSE_MARKUP
+
bool wxDataViewTextRenderer::MacRender()
{
+#if wxUSE_MARKUP
+ if ( m_useMarkup )
+ {
+ wxMarkupToAttrString toAttr(GetView(), GetValue().GetString());
+
+ [GetNativeData()->GetItemCell() setAttributedStringValue:toAttr.GetNSAttributedString()];
+ return true;
+ }
+#endif // wxUSE_MARKUP
+
[GetNativeData()->GetItemCell() setObjectValue:wxCFStringRef(GetValue().GetString()).AsNSString()];
return true;
}