| /******************************************************************************* | 
 |  * You may amend and distribute as you like, but don't remove this header! | 
 |  * | 
 |  * EPPlus provides server-side generation of Excel 2007/2010 spreadsheets. | 
 |  * See http://www.codeplex.com/EPPlus for details. | 
 |  * | 
 |  * Copyright (C) 2011  Jan Källman | 
 |  * | 
 |  * This library is free software; you can redistribute it and/or | 
 |  * modify it under the terms of the GNU Lesser General Public | 
 |  * License as published by the Free Software Foundation; either | 
 |  * version 2.1 of the License, or (at your option) any later version. | 
 |  | 
 |  * This library is distributed in the hope that it will be useful, | 
 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 
 |  * See the GNU Lesser General Public License for more details. | 
 |  * | 
 |  * The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php | 
 |  * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html | 
 |  * | 
 |  * All code and executables are provided "as is" with no warranty either express or implied. | 
 |  * The author accepts no liability for any damage or loss of business that this product may cause. | 
 |  * | 
 |  * Code change notes: | 
 |  * | 
 |  * Author							Change						Date | 
 |  * ****************************************************************************** | 
 |  * Jan Källman		                Initial Release		        2009-10-01 | 
 |  * Jan Källman		License changed GPL-->LGPL 2011-12-16 | 
 |  * Richard Tallent					Fix inadvertent removal of XML node					2012-10-31 | 
 |  * Richard Tallent					Remove VertAlign node if no alignment specified		2012-10-31 | 
 |  *******************************************************************************/ | 
 |  | 
 | using System; | 
 | using System.Drawing; | 
 | using System.Globalization; | 
 | using System.Xml; | 
 |  | 
 | namespace OfficeOpenXml.Style; | 
 |  | 
 | /// <summary> | 
 | /// A richtext part | 
 | /// </summary> | 
 | public class ExcelRichText : XmlHelper { | 
 |   internal ExcelRichText( | 
 |       XmlNamespaceManager ns, | 
 |       XmlNode topNode, | 
 |       ExcelRichTextCollection collection) | 
 |       : base(ns, topNode) { | 
 |     SchemaNodeOrder = new[] { | 
 |       "rPr", | 
 |       "t", | 
 |       "b", | 
 |       "i", | 
 |       "strike", | 
 |       "u", | 
 |       "vertAlign", | 
 |       "sz", | 
 |       "color", | 
 |       "rFont", | 
 |       "family", | 
 |       "scheme", | 
 |       "charset", | 
 |     }; | 
 |     _collection = collection; | 
 |   } | 
 |  | 
 |   internal delegate void CallbackDelegate(); | 
 |  | 
 |   private CallbackDelegate _callback; | 
 |  | 
 |   internal void SetCallback(CallbackDelegate callback) { | 
 |     _callback = callback; | 
 |   } | 
 |  | 
 |   private const string _textPath = "d:t"; | 
 |  | 
 |   /// <summary> | 
 |   /// The text | 
 |   /// </summary> | 
 |   public string Text { | 
 |     get { | 
 |       // Bug 15151 | 
 |       if (TopNode.Name == "t") { | 
 |         return TopNode.InnerText; | 
 |       } | 
 |       return GetXmlNodeString(_textPath); | 
 |     } | 
 |     set { | 
 |       _collection.ConvertRichtext(); | 
 |       // Don't remove if blank -- setting a blank rich text value on a node is common, | 
 |       // for example when applying both bold and italic to text. | 
 |       SetXmlNodeString(_textPath, value, false); | 
 |       if (PreserveSpace) { | 
 |         XmlElement elem = TopNode.SelectSingleNode(_textPath, NameSpaceManager) as XmlElement; | 
 |         elem.SetAttribute("xml:space", "preserve"); | 
 |       } | 
 |       if (_callback != null) { | 
 |         _callback(); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   /// <summary> | 
 |   /// Preserves whitespace. Default true | 
 |   /// </summary> | 
 |   public bool PreserveSpace { | 
 |     get { | 
 |       XmlElement elem = TopNode.SelectSingleNode(_textPath, NameSpaceManager) as XmlElement; | 
 |       if (elem != null) { | 
 |         return elem.GetAttribute("xml:space") == "preserve"; | 
 |       } | 
 |       return false; | 
 |     } | 
 |     set { | 
 |       _collection.ConvertRichtext(); | 
 |       XmlElement elem = TopNode.SelectSingleNode(_textPath, NameSpaceManager) as XmlElement; | 
 |       if (elem != null) { | 
 |         if (value) { | 
 |           elem.SetAttribute("xml:space", "preserve"); | 
 |         } else { | 
 |           elem.RemoveAttribute("xml:space"); | 
 |         } | 
 |       } | 
 |       if (_callback != null) { | 
 |         _callback(); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   private const string _boldPath = "d:rPr/d:b"; | 
 |  | 
 |   /// <summary> | 
 |   /// Bold text | 
 |   /// </summary> | 
 |   public bool Bold { | 
 |     get => ExistNode(_boldPath); | 
 |     set { | 
 |       _collection.ConvertRichtext(); | 
 |       if (value) { | 
 |         CreateNode(_boldPath); | 
 |       } else { | 
 |         DeleteNode(_boldPath); | 
 |       } | 
 |       if (_callback != null) { | 
 |         _callback(); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   private const string _italicPath = "d:rPr/d:i"; | 
 |  | 
 |   /// <summary> | 
 |   /// Italic text | 
 |   /// </summary> | 
 |   public bool Italic { | 
 |     get => | 
 |       //return GetXmlNodeBool(ITALIC_PATH, false); | 
 |       ExistNode(_italicPath); | 
 |     set { | 
 |       _collection.ConvertRichtext(); | 
 |       if (value) { | 
 |         CreateNode(_italicPath); | 
 |       } else { | 
 |         DeleteNode(_italicPath); | 
 |       } | 
 |       if (_callback != null) { | 
 |         _callback(); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   private const string _strikePath = "d:rPr/d:strike"; | 
 |  | 
 |   /// <summary> | 
 |   /// Strike-out text | 
 |   /// </summary> | 
 |   public bool Strike { | 
 |     get => ExistNode(_strikePath); | 
 |     set { | 
 |       _collection.ConvertRichtext(); | 
 |       if (value) { | 
 |         CreateNode(_strikePath); | 
 |       } else { | 
 |         DeleteNode(_strikePath); | 
 |       } | 
 |       if (_callback != null) { | 
 |         _callback(); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   private const string _underlinePath = "d:rPr/d:u"; | 
 |  | 
 |   /// <summary> | 
 |   /// Underlined text | 
 |   /// </summary> | 
 |   public bool UnderLine { | 
 |     get => ExistNode(_underlinePath); | 
 |     set { | 
 |       _collection.ConvertRichtext(); | 
 |       if (value) { | 
 |         CreateNode(_underlinePath); | 
 |       } else { | 
 |         DeleteNode(_underlinePath); | 
 |       } | 
 |       if (_callback != null) { | 
 |         _callback(); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   private const string _vertAlignPath = "d:rPr/d:vertAlign/@val"; | 
 |  | 
 |   /// <summary> | 
 |   /// Vertical Alignment | 
 |   /// </summary> | 
 |   public ExcelVerticalAlignmentFont VerticalAlign { | 
 |     get { | 
 |       string v = GetXmlNodeString(_vertAlignPath); | 
 |       if (v == "") { | 
 |         return ExcelVerticalAlignmentFont.None; | 
 |       } | 
 |       try { | 
 |         return (ExcelVerticalAlignmentFont)Enum.Parse(typeof(ExcelVerticalAlignmentFont), v, true); | 
 |       } catch { | 
 |         return ExcelVerticalAlignmentFont.None; | 
 |       } | 
 |     } | 
 |     set { | 
 |       _collection.ConvertRichtext(); | 
 |       if (value == ExcelVerticalAlignmentFont.None) { | 
 |         // If Excel 2010 encounters a vertical align value of blank, it will not load | 
 |         // the spreadsheet. So if None is specified, delete the node, it will be | 
 |         // recreated if a new value is applied later. | 
 |         DeleteNode(_vertAlignPath); | 
 |       } else { | 
 |         SetXmlNodeString(_vertAlignPath, value.ToString().ToLowerInvariant()); | 
 |       } | 
 |       if (_callback != null) { | 
 |         _callback(); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   private const string _sizePath = "d:rPr/d:sz/@val"; | 
 |  | 
 |   /// <summary> | 
 |   /// Font size | 
 |   /// </summary> | 
 |   public float Size { | 
 |     get => Convert.ToSingle(GetXmlNodeDecimal(_sizePath)); | 
 |     set { | 
 |       _collection.ConvertRichtext(); | 
 |       SetXmlNodeString(_sizePath, value.ToString(CultureInfo.InvariantCulture)); | 
 |       if (_callback != null) { | 
 |         _callback(); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   private const string _fontPath = "d:rPr/d:rFont/@val"; | 
 |  | 
 |   /// <summary> | 
 |   /// Name of the font | 
 |   /// </summary> | 
 |   public string FontName { | 
 |     get => GetXmlNodeString(_fontPath); | 
 |     set { | 
 |       _collection.ConvertRichtext(); | 
 |       SetXmlNodeString(_fontPath, value); | 
 |       if (_callback != null) { | 
 |         _callback(); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   private const string _colorPath = "d:rPr/d:color/@rgb"; | 
 |  | 
 |   /// <summary> | 
 |   /// Text color | 
 |   /// </summary> | 
 |   public Color Color { | 
 |     get { | 
 |       string col = GetXmlNodeString(_colorPath); | 
 |       if (col == "") { | 
 |         return Color.Empty; | 
 |       } | 
 |       return Color.FromArgb(int.Parse(col, NumberStyles.AllowHexSpecifier)); | 
 |     } | 
 |     set { | 
 |       _collection.ConvertRichtext(); | 
 |       SetXmlNodeString( | 
 |           _colorPath, | 
 |           value | 
 |               .ToArgb() | 
 |               .ToString( | 
 |                   "X") /*.Substring(2, 6)*/); | 
 |       if (_callback != null) { | 
 |         _callback(); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   public ExcelRichTextCollection _collection { get; set; } | 
 | } |