Fix handling of ampersands in wxDataViewCtrl markup
Handle "&" in exactly the same way as "&" in wxMarkupParser, i.e. do not map the former to "&&" to prevent it from being interpreted as a mnemonic as this is incompatible with using markup for anything but the control labels, e.g. for wxDataViewCtrl items text, in which mnemonics are not recognized. And even when using markup for control labels, it was a questionable decision as it's really not clear at all why should the XML entity and the raw character itself be handled differently. Also split wxMarkupText into two classes, wxMarkupText that handles mnemonics in the markup (which is typically a label) and a very similar, but not derived, wxItemMarkupText that handles mnemonics-less markup for list etc. items, uses DrawItemText() and supports ellipsizing. Illustrate the use of ampersands in the dataview sample.
This commit is contained in:
committed by
Václav Slavík
parent
0e2f6f6ec0
commit
60bd6842e4
@@ -83,7 +83,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
#if wxUSE_MARKUP
|
#if wxUSE_MARKUP
|
||||||
class wxMarkupText *m_markupText;
|
class wxItemMarkupText *m_markupText;
|
||||||
#endif // wxUSE_MARKUP
|
#endif // wxUSE_MARKUP
|
||||||
|
|
||||||
wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewTextRenderer);
|
wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewTextRenderer);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Name: wx/generic/private/markuptext.h
|
// Name: wx/generic/private/markuptext.h
|
||||||
// Purpose: Generic wxMarkupText class for managing text with markup.
|
// Purpose: Generic wx*MarkupText classes for managing text with markup.
|
||||||
// Author: Vadim Zeitlin
|
// Author: Vadim Zeitlin
|
||||||
// Created: 2011-02-21
|
// Created: 2011-02-21
|
||||||
// Copyright: (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
|
// Copyright: (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
|
||||||
@@ -21,7 +21,36 @@ class wxMarkupParserOutput;
|
|||||||
// wxMarkupText: allows to measure and draw the text containing markup.
|
// wxMarkupText: allows to measure and draw the text containing markup.
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
class WXDLLIMPEXP_CORE wxMarkupText
|
class WXDLLIMPEXP_CORE wxMarkupTextBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Update the markup string.
|
||||||
|
void SetMarkup(const wxString& markup) { m_markup = 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
|
||||||
|
// internal leading).
|
||||||
|
//
|
||||||
|
// The font currently selected into the DC is used for measuring (notice
|
||||||
|
// that it is changed by this function but normally -- i.e. if markup is
|
||||||
|
// valid -- restored to its original value when it returns).
|
||||||
|
wxSize Measure(wxDC& dc, int *visibleHeight = NULL) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
wxMarkupTextBase(const wxString& markup)
|
||||||
|
: m_markup(markup)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return m_markup suitable for measuring by Measure, i.e. stripped of
|
||||||
|
// any mnenomics.
|
||||||
|
virtual wxString GetMarkupForMeasuring() const = 0;
|
||||||
|
|
||||||
|
wxString m_markup;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class WXDLLIMPEXP_CORE wxMarkupText : public wxMarkupTextBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Constants for Render() flags.
|
// Constants for Render() flags.
|
||||||
@@ -43,8 +72,7 @@ public:
|
|||||||
// TODO-MULTILINE-MARKUP: Currently only single line labels are supported,
|
// TODO-MULTILINE-MARKUP: Currently only single line labels are supported,
|
||||||
// search for other occurrences of this comment to find the places which
|
// search for other occurrences of this comment to find the places which
|
||||||
// need to be updated to support multiline labels with markup.
|
// need to be updated to support multiline labels with markup.
|
||||||
wxMarkupText(const wxString& markup)
|
wxMarkupText(const wxString& markup) : wxMarkupTextBase(markup)
|
||||||
: m_markup(markup)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,21 +83,6 @@ public:
|
|||||||
// The same rules for mnemonics as in the ctor apply to this string.
|
// The same rules for mnemonics as in the ctor apply to this string.
|
||||||
void SetMarkup(const wxString& markup) { m_markup = markup; }
|
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
|
|
||||||
// internal leading).
|
|
||||||
//
|
|
||||||
// The font currently selected into the DC is used for measuring (notice
|
|
||||||
// that it is changed by this function but normally -- i.e. if markup is
|
|
||||||
// valid -- restored to its original value when it returns).
|
|
||||||
wxSize Measure(wxDC& dc, int *visibleHeight = NULL) const;
|
|
||||||
|
|
||||||
// Render the markup string into the given DC in the specified rectangle.
|
// Render the markup string into the given DC in the specified rectangle.
|
||||||
//
|
//
|
||||||
// Notice that while the function uses the provided rectangle for alignment
|
// Notice that while the function uses the provided rectangle for alignment
|
||||||
@@ -77,24 +90,47 @@ public:
|
|||||||
// and set the clipping region before rendering if necessary.
|
// and set the clipping region before rendering if necessary.
|
||||||
void Render(wxDC& dc, const wxRect& rect, int flags);
|
void Render(wxDC& dc, const wxRect& rect, int flags);
|
||||||
|
|
||||||
// Similar to Render(), but uses wxRendererNative::DrawItemText() instead
|
protected:
|
||||||
// of generic wxDC::DrawLabel(), so is more suitable for use in controls
|
virtual wxString GetMarkupForMeasuring() const wxOVERRIDE;
|
||||||
// that already use DrawItemText() for its items.
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxItemMarkupText: variant of wxMarkupText for items without mnemonics
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// This class has similar interface to wxItemMarkup, but no strings contain
|
||||||
|
// mnemonics and no escaping is done.
|
||||||
|
class WXDLLIMPEXP_CORE wxItemMarkupText : public wxMarkupTextBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Initialize with the given string containing markup (which is supposed to
|
||||||
|
// be valid, the caller must check for it before constructing this object).
|
||||||
|
// Notice that mnemonics are not interpreted at all by this class, so
|
||||||
|
// literal ampersands shouldn't be escaped/doubled.
|
||||||
|
wxItemMarkupText(const wxString& markup) : wxMarkupTextBase(markup)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default copy ctor, assignment operator and dtor are ok.
|
||||||
|
|
||||||
|
// Similar to wxMarkupText::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:
|
// The meaning of the flags here is different than in wxMarkupText too:
|
||||||
// they're passed to DrawItemText() and Render_ShowAccels is not supported
|
// they're passed to DrawItemText().
|
||||||
// here.
|
|
||||||
//
|
//
|
||||||
// Currently the only supported ellipsize modes are wxELLIPSIZE_NONE and
|
// Currently the only supported ellipsize modes are wxELLIPSIZE_NONE and
|
||||||
// wxELLIPSIZE_END, the others are treated as wxELLIPSIZE_END.
|
// wxELLIPSIZE_END, the others are treated as wxELLIPSIZE_END.
|
||||||
void RenderItemText(wxWindow *win,
|
void Render(wxWindow *win,
|
||||||
wxDC& dc,
|
wxDC& dc,
|
||||||
const wxRect& rect,
|
const wxRect& rect,
|
||||||
int rendererFlags,
|
int rendererFlags,
|
||||||
wxEllipsizeMode ellipsizeMode);
|
wxEllipsizeMode ellipsizeMode);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
wxString m_markup;
|
virtual wxString GetMarkupForMeasuring() const wxOVERRIDE { return m_markup; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _WX_GENERIC_PRIVATE_MARKUPTEXT_H_
|
#endif // _WX_GENERIC_PRIVATE_MARKUPTEXT_H_
|
||||||
|
@@ -441,8 +441,8 @@ void MyListModel::GetValueByRow( wxVariant &variant,
|
|||||||
"<span color=\"#87ceeb\">light</span> and "
|
"<span color=\"#87ceeb\">light</span> and "
|
||||||
"<span color=\"#000080\">dark</span> blue",
|
"<span color=\"#000080\">dark</span> blue",
|
||||||
"<big>growing green</big>",
|
"<big>growing green</big>",
|
||||||
"<i>emphatic red</i>",
|
"<i>emphatic & red</i>",
|
||||||
"<b>bold cyan</b>",
|
"<b>bold && cyan</b>",
|
||||||
"<small><tt>dull default</tt></small>",
|
"<small><tt>dull default</tt></small>",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -371,11 +371,6 @@ bool wxMarkupParser::Parse(const wxString& text)
|
|||||||
if ( text.compare(pos, xmlEnt.len, xmlEnt.name) == 0
|
if ( text.compare(pos, xmlEnt.len, xmlEnt.name) == 0
|
||||||
&& text[pos + xmlEnt.len] == ';' )
|
&& text[pos + xmlEnt.len] == ';' )
|
||||||
{
|
{
|
||||||
// Escape the ampersands if needed to protect them
|
|
||||||
// from being interpreted as mnemonics indicators.
|
|
||||||
if ( xmlEnt.value == '&' )
|
|
||||||
current += "&&";
|
|
||||||
else
|
|
||||||
current += xmlEnt.value;
|
current += xmlEnt.value;
|
||||||
|
|
||||||
it += xmlEnt.len + 1; // +1 for '&' itself
|
it += xmlEnt.len + 1; // +1 for '&' itself
|
||||||
|
@@ -1067,7 +1067,7 @@ void wxDataViewTextRenderer::EnableMarkup(bool enable)
|
|||||||
{
|
{
|
||||||
if ( !m_markupText )
|
if ( !m_markupText )
|
||||||
{
|
{
|
||||||
m_markupText = new wxMarkupText(wxString());
|
m_markupText = new wxItemMarkupText(wxString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1087,7 +1087,7 @@ bool wxDataViewTextRenderer::SetValue( const wxVariant &value )
|
|||||||
|
|
||||||
#if wxUSE_MARKUP
|
#if wxUSE_MARKUP
|
||||||
if ( m_markupText )
|
if ( m_markupText )
|
||||||
m_markupText->SetMarkupText(m_text);
|
m_markupText->SetMarkup(m_text);
|
||||||
#endif // wxUSE_MARKUP
|
#endif // wxUSE_MARKUP
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -1135,7 +1135,7 @@ bool wxDataViewTextRenderer::Render(wxRect rect, wxDC *dc, int state)
|
|||||||
int flags = 0;
|
int flags = 0;
|
||||||
if ( state & wxDATAVIEW_CELL_SELECTED )
|
if ( state & wxDATAVIEW_CELL_SELECTED )
|
||||||
flags |= wxCONTROL_SELECTED;
|
flags |= wxCONTROL_SELECTED;
|
||||||
m_markupText->RenderItemText(GetView(), *dc, rect, flags, GetEllipsizeMode());
|
m_markupText->Render(GetView(), *dc, rect, flags, GetEllipsizeMode());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif // wxUSE_MARKUP
|
#endif // wxUSE_MARKUP
|
||||||
|
@@ -66,10 +66,8 @@ public:
|
|||||||
const wxSize& GetSize() const { return m_size; }
|
const wxSize& GetSize() const { return m_size; }
|
||||||
|
|
||||||
|
|
||||||
virtual void OnText(const wxString& text_) wxOVERRIDE
|
virtual void OnText(const wxString& text) wxOVERRIDE
|
||||||
{
|
{
|
||||||
const wxString text(wxControl::RemoveMnemonics(text_));
|
|
||||||
|
|
||||||
// TODO-MULTILINE-MARKUP: Must use GetMultiLineTextExtent().
|
// TODO-MULTILINE-MARKUP: Must use GetMultiLineTextExtent().
|
||||||
const wxSize size = m_dc.GetTextExtent(text);
|
const wxSize size = m_dc.GetTextExtent(text);
|
||||||
|
|
||||||
@@ -253,10 +251,8 @@ public:
|
|||||||
m_ellipsizeMode = ellipsizeMode == wxELLIPSIZE_NONE ? wxELLIPSIZE_NONE : wxELLIPSIZE_END;
|
m_ellipsizeMode = ellipsizeMode == wxELLIPSIZE_NONE ? wxELLIPSIZE_NONE : wxELLIPSIZE_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void OnText(const wxString& text_) wxOVERRIDE
|
virtual void OnText(const wxString& text) wxOVERRIDE
|
||||||
{
|
{
|
||||||
const wxString text(wxControl::RemoveMnemonics(text_));
|
|
||||||
|
|
||||||
wxRect rect(m_rect);
|
wxRect rect(m_rect);
|
||||||
rect.x = m_pos;
|
rect.x = m_pos;
|
||||||
rect.SetRight(m_rect.GetRight());
|
rect.SetRight(m_rect.GetRight());
|
||||||
@@ -315,16 +311,11 @@ private:
|
|||||||
// wxMarkupText implementation
|
// wxMarkupText implementation
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
void wxMarkupText::SetMarkupText(const wxString& markup)
|
wxSize wxMarkupTextBase::Measure(wxDC& dc, int *visibleHeight) const
|
||||||
{
|
|
||||||
m_markup = wxControl::EscapeMnemonics(markup);
|
|
||||||
}
|
|
||||||
|
|
||||||
wxSize wxMarkupText::Measure(wxDC& dc, int *visibleHeight) const
|
|
||||||
{
|
{
|
||||||
wxMarkupParserMeasureOutput out(dc, visibleHeight);
|
wxMarkupParserMeasureOutput out(dc, visibleHeight);
|
||||||
wxMarkupParser parser(out);
|
wxMarkupParser parser(out);
|
||||||
if ( !parser.Parse(m_markup) )
|
if ( !parser.Parse(GetMarkupForMeasuring()) )
|
||||||
{
|
{
|
||||||
wxFAIL_MSG( "Invalid markup" );
|
wxFAIL_MSG( "Invalid markup" );
|
||||||
return wxDefaultSize;
|
return wxDefaultSize;
|
||||||
@@ -333,6 +324,11 @@ wxSize wxMarkupText::Measure(wxDC& dc, int *visibleHeight) const
|
|||||||
return out.GetSize();
|
return out.GetSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxString wxMarkupText::GetMarkupForMeasuring() const
|
||||||
|
{
|
||||||
|
return wxControl::RemoveMnemonics(m_markup);
|
||||||
|
}
|
||||||
|
|
||||||
void wxMarkupText::Render(wxDC& dc, const wxRect& rect, int flags)
|
void wxMarkupText::Render(wxDC& dc, const wxRect& rect, int flags)
|
||||||
{
|
{
|
||||||
// We want to center the above-baseline parts of the letter vertically, so
|
// We want to center the above-baseline parts of the letter vertically, so
|
||||||
@@ -347,7 +343,12 @@ void wxMarkupText::Render(wxDC& dc, const wxRect& rect, int flags)
|
|||||||
parser.Parse(m_markup);
|
parser.Parse(m_markup);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxMarkupText::RenderItemText(wxWindow *win,
|
|
||||||
|
// ============================================================================
|
||||||
|
// wxItemMarkupText implementation
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
void wxItemMarkupText::Render(wxWindow *win,
|
||||||
wxDC& dc,
|
wxDC& dc,
|
||||||
const wxRect& rect,
|
const wxRect& rect,
|
||||||
int rendererFlags,
|
int rendererFlags,
|
||||||
|
Reference in New Issue
Block a user