1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        wx/private/markupparserattr.h
3 // Purpose:     Classes mapping markup attributes to wxFont/wxColour.
4 // Author:      Vadim Zeitlin
5 // Created:     2011-02-18
6 // Copyright:   (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
7 // Licence:     wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
9 
10 #ifndef _WX_PRIVATE_MARKUPPARSERATTR_H_
11 #define _WX_PRIVATE_MARKUPPARSERATTR_H_
12 
13 #include "wx/private/markupparser.h"
14 
15 #include "wx/stack.h"
16 
17 #include "wx/colour.h"
18 #include "wx/font.h"
19 
20 // ----------------------------------------------------------------------------
21 // wxMarkupParserAttrOutput: simplified wxFont-using version of the above.
22 // ----------------------------------------------------------------------------
23 
24 // This class assumes that wxFont and wxColour are used to perform all the
25 // markup tags and implements the base class virtual functions in terms of
26 // OnAttr{Start,End}() only.
27 //
28 // Notice that you still must implement OnText() inherited from the base class
29 // when deriving from this one.
30 class wxMarkupParserAttrOutput : public wxMarkupParserOutput
31 {
32 public:
33     // A container of font and colours with inheritance support. It holds two
34     // sets of attributes:
35     // 1. The currently specified ones from parsed tags that contain
36     //    information on on what should change in the output; some of them
37     //    may be invalid if only the others are affected by a change.
38     // 2. The _effective_ attributes that are always valid and accumulate
39     //    all past changes as the markup is being parser; these are used
40     //    to restore state when unwinding nested attributes.
41     struct Attr
42     {
43         Attr(const Attr *attrInEffect,
44              const wxFont& font_,
45              const wxColour& foreground_ = wxColour(),
46              const wxColour& background_ = wxColour())
fontAttr47             : font(font_), foreground(foreground_), background(background_)
48         {
49             if (attrInEffect)
50             {
51                 effectiveFont = font.IsOk() ? font : attrInEffect->effectiveFont;
52                 effectiveForeground = foreground_.IsOk() ? foreground_ : attrInEffect->effectiveForeground;
53                 effectiveBackground = background.IsOk() ? background : attrInEffect->effectiveBackground;
54             }
55             else
56             {
57                 effectiveFont = font;
58                 effectiveForeground = foreground;
59                 effectiveBackground = background;
60             }
61         }
62 
63         wxFont font;
64         wxColour foreground,
65                  background;
66         wxFont   effectiveFont;
67         wxColour effectiveForeground,
68                  effectiveBackground;
69     };
70 
71 
72     // This object must be initialized with the font and colours to use
73     // initially, i.e. the ones used before any tags in the string.
wxMarkupParserAttrOutput(const wxFont & font,const wxColour & foreground,const wxColour & background)74     wxMarkupParserAttrOutput(const wxFont& font,
75                              const wxColour& foreground,
76                              const wxColour& background)
77     {
78         m_attrs.push(Attr(NULL, font, foreground, background));
79     }
80 
81     // Indicates the change of the font and/or colours used. Any of the
82     // fields of the argument may be invalid indicating that the corresponding
83     // attribute didn't actually change.
84     virtual void OnAttrStart(const Attr& attr) = 0;
85 
86     // Indicates the end of the region affected by the given attributes
87     // (the same ones that were passed to the matching OnAttrStart(), use
88     // GetAttr() to get the ones that will be used from now on).
89     virtual void OnAttrEnd(const Attr& attr) = 0;
90 
91 
92     // Implement all pure virtual methods inherited from the base class in
93     // terms of our own ones.
OnBoldStart()94     virtual void OnBoldStart() wxOVERRIDE { DoChangeFont(&wxFont::Bold); }
OnBoldEnd()95     virtual void OnBoldEnd() wxOVERRIDE { DoEndAttr(); }
96 
OnItalicStart()97     virtual void OnItalicStart() wxOVERRIDE { DoChangeFont(&wxFont::Italic); }
OnItalicEnd()98     virtual void OnItalicEnd() wxOVERRIDE { DoEndAttr(); }
99 
OnUnderlinedStart()100     virtual void OnUnderlinedStart() wxOVERRIDE { DoChangeFont(&wxFont::Underlined); }
OnUnderlinedEnd()101     virtual void OnUnderlinedEnd() wxOVERRIDE { DoEndAttr(); }
102 
OnStrikethroughStart()103     virtual void OnStrikethroughStart() wxOVERRIDE { DoChangeFont(&wxFont::Strikethrough); }
OnStrikethroughEnd()104     virtual void OnStrikethroughEnd() wxOVERRIDE { DoEndAttr(); }
105 
OnBigStart()106     virtual void OnBigStart() wxOVERRIDE { DoChangeFont(&wxFont::Larger); }
OnBigEnd()107     virtual void OnBigEnd() wxOVERRIDE { DoEndAttr(); }
108 
OnSmallStart()109     virtual void OnSmallStart() wxOVERRIDE { DoChangeFont(&wxFont::Smaller); }
OnSmallEnd()110     virtual void OnSmallEnd() wxOVERRIDE { DoEndAttr(); }
111 
OnTeletypeStart()112     virtual void OnTeletypeStart() wxOVERRIDE
113     {
114         wxFont font(GetFont());
115         font.SetFamily(wxFONTFAMILY_TELETYPE);
116         DoSetFont(font);
117     }
OnTeletypeEnd()118     virtual void OnTeletypeEnd() wxOVERRIDE { DoEndAttr(); }
119 
OnSpanStart(const wxMarkupSpanAttributes & spanAttr)120     virtual void OnSpanStart(const wxMarkupSpanAttributes& spanAttr) wxOVERRIDE
121     {
122         wxFont font(GetFont());
123         if ( !spanAttr.m_fontFace.empty() )
124             font.SetFaceName(spanAttr.m_fontFace);
125 
126         FontModifier<wxFontWeight>()(spanAttr.m_isBold,
127                                      font, &wxFont::SetWeight,
128                                      wxFONTWEIGHT_NORMAL, wxFONTWEIGHT_BOLD);
129 
130         FontModifier<wxFontStyle>()(spanAttr.m_isItalic,
131                                     font, &wxFont::SetStyle,
132                                     wxFONTSTYLE_NORMAL, wxFONTSTYLE_ITALIC);
133 
134         FontModifier<bool>()(spanAttr.m_isUnderlined,
135                              font, &wxFont::SetUnderlined,
136                              false, true);
137 
138         FontModifier<bool>()(spanAttr.m_isStrikethrough,
139                              font, &wxFont::SetStrikethrough,
140                              false, true);
141 
142         switch ( spanAttr.m_sizeKind )
143         {
144             case wxMarkupSpanAttributes::Size_Unspecified:
145                 break;
146 
147             case wxMarkupSpanAttributes::Size_Relative:
148                 if ( spanAttr.m_fontSize > 0 )
149                     font.MakeLarger();
150                 else
151                     font.MakeSmaller();
152                 break;
153 
154             case wxMarkupSpanAttributes::Size_Symbolic:
155                 // The values of font size intentionally coincide with the
156                 // values of wxFontSymbolicSize enum elements so simply cast
157                 // one to the other.
158                 font.SetSymbolicSize(
159                     static_cast<wxFontSymbolicSize>(spanAttr.m_fontSize)
160                 );
161                 break;
162 
163             case wxMarkupSpanAttributes::Size_PointParts:
164                 font.SetFractionalPointSize(spanAttr.m_fontSize/1024.);
165                 break;
166         }
167 
168 
169         const Attr attr(&m_attrs.top(), font, spanAttr.m_fgCol, spanAttr.m_bgCol);
170         OnAttrStart(attr);
171 
172         m_attrs.push(attr);
173     }
174 
OnSpanEnd(const wxMarkupSpanAttributes & WXUNUSED (spanAttr))175     virtual void OnSpanEnd(const wxMarkupSpanAttributes& WXUNUSED(spanAttr)) wxOVERRIDE
176     {
177         DoEndAttr();
178     }
179 
180 protected:
181     // Get the current attributes, i.e. the ones that should be used for
182     // rendering (or measuring or whatever) the text at the current position in
183     // the string.
184     //
185     // It may be called from OnAttrStart() to get the old attributes used
186     // before and from OnAttrEnd() to get the new attributes that will be used
187     // from now on but is mostly meant to be used from overridden OnText()
188     // implementations.
GetAttr()189     const Attr& GetAttr() const { return m_attrs.top(); }
190 
191     // A shortcut for accessing the font of the current attribute.
GetFont()192     const wxFont& GetFont() const { return GetAttr().font; }
193 
194 private:
195     // Change only the font to the given one. Call OnAttrStart() to notify
196     // about the change and update the attributes stack.
DoSetFont(const wxFont & font)197     void DoSetFont(const wxFont& font)
198     {
199         const Attr attr(&m_attrs.top(), font);
200 
201         OnAttrStart(attr);
202 
203         m_attrs.push(attr);
204     }
205 
206     // Apply the given function to the font currently on top of the font stack,
207     // push the new font on the stack and call OnAttrStart() with it.
DoChangeFont(wxFont (wxFont::* func)()const)208     void DoChangeFont(wxFont (wxFont::*func)() const)
209     {
210         DoSetFont((GetFont().*func)());
211     }
212 
DoEndAttr()213     void DoEndAttr()
214     {
215         const Attr attr(m_attrs.top());
216         m_attrs.pop();
217 
218         OnAttrEnd(attr);
219     }
220 
221     // A helper class used to apply the given function to a wxFont object
222     // depending on the value of an OptionalBool.
223     template <typename T>
224     struct FontModifier
225     {
FontModifierFontModifier226         FontModifier() { }
227 
operatorFontModifier228         void operator()(wxMarkupSpanAttributes::OptionalBool isIt,
229                         wxFont& font,
230                         void (wxFont::*func)(T),
231                         T noValue,
232                         T yesValue)
233         {
234             switch ( isIt )
235             {
236                 case wxMarkupSpanAttributes::Unspecified:
237                     break;
238 
239                 case wxMarkupSpanAttributes::No:
240                     (font.*func)(noValue);
241                     break;
242 
243                 case wxMarkupSpanAttributes::Yes:
244                     (font.*func)(yesValue);
245                     break;
246             }
247         }
248     };
249 
250 
251     wxStack<Attr> m_attrs;
252 
253     wxDECLARE_NO_COPY_CLASS(wxMarkupParserAttrOutput);
254 };
255 
256 #endif // _WX_PRIVATE_MARKUPPARSERATTR_H_
257