using System;
using System.Collections.Generic;
namespace ClosedXML.Excel
{
using System.Linq;
internal class XLHeaderFooter: IXLHeaderFooter
{
public XLHeaderFooter(XLWorksheet worksheet)
{
this.Worksheet = worksheet;
Left = new XLHFItem(this);
Right = new XLHFItem(this);
Center = new XLHFItem(this);
SetAsInitial();
}
public XLHeaderFooter(XLHeaderFooter defaultHF, XLWorksheet worksheet)
{
this.Worksheet = worksheet;
defaultHF.innerTexts.ForEach(kp => innerTexts.Add(kp.Key, kp.Value));
Left = new XLHFItem(defaultHF.Left as XLHFItem, this);
Center = new XLHFItem(defaultHF.Center as XLHFItem, this);
Right = new XLHFItem(defaultHF.Right as XLHFItem, this);
SetAsInitial();
}
internal readonly IXLWorksheet Worksheet;
public IXLHFItem Left { get; private set; }
public IXLHFItem Center { get; private set; }
public IXLHFItem Right { get; private set; }
public String GetText(XLHFOccurrence occurrence)
{
//if (innerTexts.ContainsKey(occurrence)) return innerTexts[occurrence];
var retVal = String.Empty;
var leftText = Left.GetText(occurrence);
var centerText = Center.GetText(occurrence);
var rightText = Right.GetText(occurrence);
retVal += leftText.Length > 0 ? "&L" + leftText : String.Empty;
retVal += centerText.Length > 0 ? "&C" + centerText : String.Empty;
retVal += rightText.Length > 0 ? "&R" + rightText : String.Empty;
if (retVal.Length > 255)
throw new ArgumentOutOfRangeException("Headers and Footers cannot be longer than 255 characters (including style markups)");
return retVal;
}
private Dictionary<XLHFOccurrence, String> innerTexts = new Dictionary<XLHFOccurrence, String>();
internal String SetInnerText(XLHFOccurrence occurrence, String text)
{
var parsedElements = ParseFormattedHeaderFooterText(text);
if (parsedElements.Any(e => e.Position == 'L'))
this.Left.AddText(string.Join("\r\n", parsedElements.Where(e => e.Position == 'L').Select(e => e.Text).ToArray()), occurrence);
if (parsedElements.Any(e => e.Position == 'C'))
this.Center.AddText(string.Join("\r\n", parsedElements.Where(e => e.Position == 'C').Select(e => e.Text).ToArray()), occurrence);
if (parsedElements.Any(e => e.Position == 'R'))
this.Right.AddText(string.Join("\r\n", parsedElements.Where(e => e.Position == 'R').Select(e => e.Text).ToArray()), occurrence);
if (innerTexts.ContainsKey(occurrence))
innerTexts[occurrence] = text;
else
innerTexts.Add(occurrence, text);
return innerTexts[occurrence];
}
private struct ParsedHeaderFooterElement
{
public char Position;
public string Text;
}
private static IEnumerable<ParsedHeaderFooterElement> ParseFormattedHeaderFooterText(string text)
{
var parsedElements = new List<ParsedHeaderFooterElement>();
var currentPosition = 'L'; // default is LEFT
var hfElement = "";
for (int i = 0; i < text.Length; i++)
{
if (i < text.Length - 1 && text[i] == '&' && (new char[] { 'L', 'C', 'R' }.Contains(text[i + 1])))
{
if ("" != hfElement) parsedElements.Add(new ParsedHeaderFooterElement()
{
Position = currentPosition,
Text = hfElement
});
currentPosition = text[i + 1];
i += 2;
hfElement = "";
}
hfElement += text[i];
}
if ("" != hfElement)
parsedElements.Add(new ParsedHeaderFooterElement()
{
Position = currentPosition,
Text = hfElement
});
return parsedElements;
}
private Dictionary<XLHFOccurrence, String> _initialTexts;
private Boolean _changed;
internal Boolean Changed
{
get
{
return _changed || _initialTexts.Any(it => GetText(it.Key) != it.Value);
}
set { _changed = value; }
}
internal void SetAsInitial()
{
_initialTexts = new Dictionary<XLHFOccurrence, string>();
foreach (var o in Enum.GetValues(typeof(XLHFOccurrence)).Cast<XLHFOccurrence>())
{
_initialTexts.Add(o, GetText(o));
}
}
public IXLHeaderFooter Clear(XLHFOccurrence occurrence = XLHFOccurrence.AllPages)
{
Left.Clear(occurrence);
Right.Clear(occurrence);
Center.Clear(occurrence);
return this;
}
}
}