1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/markuptext.cpp
3 // Purpose: wxMarkupText implementation
4 // Author: Vadim Zeitlin
6 // Copyright: (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
10 // ============================================================================
12 // ============================================================================
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
18 // for compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
28 #include "wx/gdicmn.h"
29 #include "wx/control.h"
33 #include "wx/generic/private/markuptext.h"
35 #include "wx/private/markupparserattr.h"
40 // ----------------------------------------------------------------------------
41 // wxMarkupParserMeasureOutput: measure the extends of a markup string.
42 // ----------------------------------------------------------------------------
44 class wxMarkupParserMeasureOutput
: public wxMarkupParserAttrOutput
47 // Initialize the base class with the font to use. As we don't care about
48 // colours (which don't affect the text measurements), don't bother to
49 // specify them at all.
50 wxMarkupParserMeasureOutput(wxDC
& dc
, int *visibleHeight
)
51 : wxMarkupParserAttrOutput(dc
.GetFont(), wxColour(), wxColour()),
53 m_visibleHeight(visibleHeight
)
59 const wxSize
& GetSize() const { return m_size
; }
62 virtual void OnText(const wxString
& text_
)
64 const wxString
text(wxControl::RemoveMnemonics(text_
));
66 // TODO-MULTILINE-MARKUP: Must use GetMultiLineTextExtent().
67 const wxSize size
= m_dc
.GetTextExtent(text
);
70 if ( size
.y
> m_size
.y
)
73 if ( m_visibleHeight
)
75 wxFontMetrics tm
= m_dc
.GetFontMetrics();
76 int visibleHeight
= tm
.ascent
- tm
.internalLeading
;
77 if ( *m_visibleHeight
< visibleHeight
)
78 *m_visibleHeight
= visibleHeight
;
82 virtual void OnAttrStart(const Attr
& attr
)
84 m_dc
.SetFont(attr
.font
);
87 virtual void OnAttrEnd(const Attr
& WXUNUSED(attr
))
89 m_dc
.SetFont(GetFont());
95 // The values that we compute.
97 int * const m_visibleHeight
; // may be NULL
99 wxDECLARE_NO_COPY_CLASS(wxMarkupParserMeasureOutput
);
102 // ----------------------------------------------------------------------------
103 // wxMarkupParserRenderOutput: render a markup string.
104 // ----------------------------------------------------------------------------
106 class wxMarkupParserRenderOutput
: public wxMarkupParserAttrOutput
109 // Notice that the bottom of rectangle passed to our ctor is used as the
110 // baseline for the text we draw, i.e. it needs to be adjusted to exclude
111 // descent by the caller.
112 wxMarkupParserRenderOutput(wxDC
& dc
,
115 : wxMarkupParserAttrOutput(dc
.GetFont(),
116 dc
.GetTextForeground(),
124 // We don't initialize the base class initial text background colour to
125 // the valid value because we want to be able to detect when we revert
126 // to the "absence of background colour" and set the background mode to
127 // be transparent in OnAttrStart() below. But do remember it to be able
128 // to restore it there later -- this doesn't affect us as the text
129 // background isn't used anyhow when the background mode is transparent
130 // but it might affect the caller if it sets the background mode to
131 // opaque and draws some text after using us.
132 m_origTextBackground
= dc
.GetTextBackground();
135 virtual void OnText(const wxString
& text_
)
138 int indexAccel
= wxControl::FindAccelIndex(text_
, &text
);
139 if ( !(m_flags
& wxMarkupText::Render_ShowAccels
) )
140 indexAccel
= wxNOT_FOUND
;
142 // Adjust the position (unfortunately we need to do this manually as
143 // there is no notion of current text position in wx API) rectangle to
144 // ensure that all text segments use the same baseline (as there is
145 // nothing equivalent to Windows SetTextAlign(TA_BASELINE) neither).
150 m_dc
.GetTextExtent(text
, &rect
.width
, &rect
.height
, &descent
);
151 rect
.height
-= descent
;
152 rect
.y
+= m_rect
.height
- rect
.height
;
155 m_dc
.DrawLabel(text
, wxBitmap(),
156 rect
, wxALIGN_LEFT
| wxALIGN_TOP
,
160 // TODO-MULTILINE-MARKUP: Must update vertical position too.
161 m_pos
+= bounds
.width
;
164 virtual void OnAttrStart(const Attr
& attr
)
166 m_dc
.SetFont(attr
.font
);
167 if ( attr
.foreground
.IsOk() )
168 m_dc
.SetTextForeground(attr
.foreground
);
170 if ( attr
.background
.IsOk() )
172 // Setting the background colour is not enough, we must also change
173 // the mode to ensure that it is actually used.
174 m_dc
.SetBackgroundMode(wxSOLID
);
175 m_dc
.SetTextBackground(attr
.background
);
179 virtual void OnAttrEnd(const Attr
& attr
)
181 // We always restore the font because we always change it...
182 m_dc
.SetFont(GetFont());
184 // ...but we only need to restore the colours if we had changed them.
185 if ( attr
.foreground
.IsOk() )
186 m_dc
.SetTextForeground(GetAttr().foreground
);
188 if ( attr
.background
.IsOk() )
190 wxColour background
= GetAttr().background
;
191 if ( !background
.IsOk() )
193 // Invalid background colour indicates that the background
194 // should actually be made transparent and in this case the
195 // actual value of background colour doesn't matter but we also
196 // restore it just in case, see comment in the ctor.
197 m_dc
.SetBackgroundMode(wxTRANSPARENT
);
198 background
= m_origTextBackground
;
201 m_dc
.SetTextBackground(background
);
210 wxColour m_origTextBackground
;
212 // Current horizontal text output position.
214 // TODO-MULTILINE-MARKUP: Must keep vertical position too.
217 wxDECLARE_NO_COPY_CLASS(wxMarkupParserRenderOutput
);
220 } // anonymous namespace
222 // ============================================================================
223 // wxMarkupText implementation
224 // ============================================================================
226 wxSize
wxMarkupText::Measure(wxDC
& dc
, int *visibleHeight
) const
228 wxMarkupParserMeasureOutput
out(dc
, visibleHeight
);
229 wxMarkupParser
parser(out
);
230 if ( !parser
.Parse(m_markup
) )
232 wxFAIL_MSG( "Invalid markup" );
233 return wxDefaultSize
;
236 return out
.GetSize();
239 void wxMarkupText::Render(wxDC
& dc
, const wxRect
& rect
, int flags
)
241 // We want to center the above-baseline parts of the letter vertically, so
242 // we use the visible height and not the total height (which includes
243 // descent and internal leading) here.
245 wxRect
rectText(rect
.GetPosition(), Measure(dc
, &visibleHeight
));
246 rectText
.height
= visibleHeight
;
248 wxMarkupParserRenderOutput
out(dc
, rectText
.CentreIn(rect
), flags
);
249 wxMarkupParser
parser(out
);
250 parser
.Parse(m_markup
);
253 #endif // wxUSE_MARKUP