1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/markuptext.cpp
3 // Purpose: wxMarkupText implementation
4 // Author: Vadim Zeitlin
6 // RCS-ID: $Id: wxhead.cpp,v 1.11 2010-04-22 12:44:51 zeitlin Exp $
7 // Copyright: (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
29 #include "wx/gdicmn.h"
30 #include "wx/control.h"
34 #include "wx/generic/private/markuptext.h"
36 #include "wx/private/markupparserattr.h"
41 // ----------------------------------------------------------------------------
42 // wxMarkupParserMeasureOutput: measure the extends of a markup string.
43 // ----------------------------------------------------------------------------
45 class wxMarkupParserMeasureOutput
: public wxMarkupParserAttrOutput
48 // Initialize the base class with the font to use. As we don't care about
49 // colours (which don't affect the text measurements), don't bother to
50 // specify them at all.
51 wxMarkupParserMeasureOutput(wxDC
& dc
, int *visibleHeight
)
52 : wxMarkupParserAttrOutput(dc
.GetFont(), wxColour(), wxColour()),
54 m_visibleHeight(visibleHeight
)
60 const wxSize
& GetSize() const { return m_size
; }
63 virtual void OnText(const wxString
& text_
)
65 const wxString
text(wxControl::RemoveMnemonics(text_
));
67 // TODO-MULTILINE-MARKUP: Must use GetMultiLineTextExtent().
68 const wxSize size
= m_dc
.GetTextExtent(text
);
71 if ( size
.y
> m_size
.y
)
74 if ( m_visibleHeight
)
76 wxFontMetrics tm
= m_dc
.GetFontMetrics();
77 int visibleHeight
= tm
.ascent
- tm
.internalLeading
;
78 if ( *m_visibleHeight
< visibleHeight
)
79 *m_visibleHeight
= visibleHeight
;
83 virtual void OnAttrStart(const Attr
& attr
)
85 m_dc
.SetFont(attr
.font
);
88 virtual void OnAttrEnd(const Attr
& WXUNUSED(attr
))
90 m_dc
.SetFont(GetFont());
96 // The values that we compute.
98 int * const m_visibleHeight
; // may be NULL
100 wxDECLARE_NO_COPY_CLASS(wxMarkupParserMeasureOutput
);
103 // ----------------------------------------------------------------------------
104 // wxMarkupParserRenderOutput: render a markup string.
105 // ----------------------------------------------------------------------------
107 class wxMarkupParserRenderOutput
: public wxMarkupParserAttrOutput
110 // Notice that the bottom of rectangle passed to our ctor is used as the
111 // baseline for the text we draw, i.e. it needs to be adjusted to exclude
112 // descent by the caller.
113 wxMarkupParserRenderOutput(wxDC
& dc
,
116 : wxMarkupParserAttrOutput(dc
.GetFont(),
117 dc
.GetTextForeground(),
125 // We don't initialize the base class initial text background colour to
126 // the valid value because we want to be able to detect when we revert
127 // to the "absence of background colour" and set the background mode to
128 // be transparent in OnAttrStart() below. But do remember it to be able
129 // to restore it there later -- this doesn't affect us as the text
130 // background isn't used anyhow when the background mode is transparent
131 // but it might affect the caller if it sets the background mode to
132 // opaque and draws some text after using us.
133 m_origTextBackground
= dc
.GetTextBackground();
136 virtual void OnText(const wxString
& text_
)
139 int indexAccel
= wxControl::FindAccelIndex(text_
, &text
);
140 if ( !(m_flags
& wxMarkupText::Render_ShowAccels
) )
141 indexAccel
= wxNOT_FOUND
;
143 // Adjust the position (unfortunately we need to do this manually as
144 // there is no notion of current text position in wx API) rectangle to
145 // ensure that all text segments use the same baseline (as there is
146 // nothing equivalent to Windows SetTextAlign(TA_BASELINE) neither).
151 m_dc
.GetTextExtent(text
, &rect
.width
, &rect
.height
, &descent
);
152 rect
.height
-= descent
;
153 rect
.y
+= m_rect
.height
- rect
.height
;
156 m_dc
.DrawLabel(text
, wxBitmap(),
157 rect
, wxALIGN_LEFT
| wxALIGN_TOP
,
161 // TODO-MULTILINE-MARKUP: Must update vertical position too.
162 m_pos
+= bounds
.width
;
165 virtual void OnAttrStart(const Attr
& attr
)
167 m_dc
.SetFont(attr
.font
);
168 if ( attr
.foreground
.IsOk() )
169 m_dc
.SetTextForeground(attr
.foreground
);
171 if ( attr
.background
.IsOk() )
173 // Setting the background colour is not enough, we must also change
174 // the mode to ensure that it is actually used.
175 m_dc
.SetBackgroundMode(wxSOLID
);
176 m_dc
.SetTextBackground(attr
.background
);
180 virtual void OnAttrEnd(const Attr
& attr
)
182 // We always restore the font because we always change it...
183 m_dc
.SetFont(GetFont());
185 // ...but we only need to restore the colours if we had changed them.
186 if ( attr
.foreground
.IsOk() )
187 m_dc
.SetTextForeground(GetAttr().foreground
);
189 if ( attr
.background
.IsOk() )
191 wxColour background
= GetAttr().background
;
192 if ( !background
.IsOk() )
194 // Invalid background colour indicates that the background
195 // should actually be made transparent and in this case the
196 // actual value of background colour doesn't matter but we also
197 // restore it just in case, see comment in the ctor.
198 m_dc
.SetBackgroundMode(wxTRANSPARENT
);
199 background
= m_origTextBackground
;
202 m_dc
.SetTextBackground(background
);
211 wxColour m_origTextBackground
;
213 // Current horizontal text output position.
215 // TODO-MULTILINE-MARKUP: Must keep vertical position too.
218 wxDECLARE_NO_COPY_CLASS(wxMarkupParserRenderOutput
);
221 } // anonymous namespace
223 // ============================================================================
224 // wxMarkupText implementation
225 // ============================================================================
227 wxSize
wxMarkupText::Measure(wxDC
& dc
, int *visibleHeight
) const
229 wxMarkupParserMeasureOutput
out(dc
, visibleHeight
);
230 wxMarkupParser
parser(out
);
231 if ( !parser
.Parse(m_markup
) )
233 wxFAIL_MSG( "Invalid markup" );
234 return wxDefaultSize
;
237 return out
.GetSize();
240 void wxMarkupText::Render(wxDC
& dc
, const wxRect
& rect
, int flags
)
242 // We want to center the above-baseline parts of the letter vertically, so
243 // we use the visible height and not the total height (which includes
244 // descent and internal leading) here.
246 wxRect
rectText(rect
.GetPosition(), Measure(dc
, &visibleHeight
));
247 rectText
.height
= visibleHeight
;
249 wxMarkupParserRenderOutput
out(dc
, rectText
.CentreIn(rect
), flags
);
250 wxMarkupParser
parser(out
);
251 parser
.Parse(m_markup
);
254 #endif // wxUSE_MARKUP