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