----------
Created an abstract class called DocXElement and made every document element such as {Table, Row, Cell, Paragraph, Run, Text, etc} extend it.
Created an abstract class InsertBeforeOrAfter which is derived from DocXElement. This provides functions for inserting, page breaks, Paragraphs and Tables before and after self.
Moved Text and Run inside Paragraph, keep consistancy with Table which contains Row and Cell.
To Do: Investigated why the Picture class had two internal constructors. I removed one.
Added a _ to each .cs file that does not contain instanceable types, {Enumerations.cs, Extensions.cs, etc}
Bugs fixed
----------
Cell had a parameter Paragraph, this was incorrect as paragraphs can contain multiple Paragraphs. Now it returns a List<Paragraph>
InsertDocProperty now returns a DocProperty instead of void.
New features
------------
InsertDocProperty now contains overloads for the parameter track changes.
Cell now contains a Shading property, this can be used to set the background color of a cell.
master
| @@ -7,16 +7,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution | |||
| EndProject | |||
| Global | |||
| GlobalSection(TeamFoundationVersionControl) = preSolution | |||
| SccNumberOfProjects = 3 | |||
| SccNumberOfProjects = 2 | |||
| SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C} | |||
| SccTeamFoundationServer = https://tfs08.codeplex.com/ | |||
| SccLocalPath0 = . | |||
| SccProjectUniqueName1 = DocX\\DocX.csproj | |||
| SccProjectName1 = DocX | |||
| SccLocalPath1 = DocX | |||
| SccProjectUniqueName2 = ConsoleApplication1\\ConsoleApplication1.csproj | |||
| SccProjectName2 = ConsoleApplication1 | |||
| SccLocalPath2 = ConsoleApplication1 | |||
| EndGlobalSection | |||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
| Debug|Any CPU = Debug|Any CPU | |||
| @@ -10,10 +10,9 @@ namespace Novacode | |||
| /// <summary> | |||
| /// Represents a field of type document property. This field displays the value stored in a custom property. | |||
| /// </summary> | |||
| public class DocProperty | |||
| public class DocProperty: DocXElement | |||
| { | |||
| internal Regex extractName = new Regex(@"DOCPROPERTY (?<name>.*) "); | |||
| internal XElement xml; | |||
| private string name; | |||
| /// <summary> | |||
| @@ -21,11 +20,9 @@ namespace Novacode | |||
| /// </summary> | |||
| public string Name { get { return name; } } | |||
| internal DocProperty(XElement xml) | |||
| { | |||
| this.xml = xml; | |||
| string instr = xml.Attribute(XName.Get("instr", "http://schemas.openxmlformats.org/wordprocessingml/2006/main")).Value; | |||
| internal DocProperty(DocX document, XElement xml):base(document, xml) | |||
| { | |||
| string instr = Xml.Attribute(XName.Get("instr", "http://schemas.openxmlformats.org/wordprocessingml/2006/main")).Value; | |||
| this.name = extractName.Match(instr.Trim()).Groups["name"].Value; | |||
| } | |||
| } | |||
| @@ -196,7 +196,7 @@ namespace Novacode | |||
| // Loop through each run in this paragraph | |||
| foreach (XElement par in paras) | |||
| { | |||
| Paragraph xp = new Paragraph(document, startIndex, par); | |||
| Paragraph xp = new Paragraph(document, par, startIndex); | |||
| // Add to paragraph list | |||
| document.paragraphs.Add(xp); | |||
| @@ -235,6 +235,31 @@ namespace Novacode | |||
| return InsertParagraph(text, trackChanges, new Formatting()); | |||
| } | |||
| /// <summary> | |||
| /// Insert a new Paragraph at the end of this document. | |||
| /// </summary> | |||
| /// <param name="text">The text of this Paragraph.</param> | |||
| /// <param name="trackChanges">Should this insertion be tracked as a change?</param> | |||
| /// <returns>A new Paragraph.</returns> | |||
| /// <example> | |||
| /// Inserting a new Paragraph at the end of a document with text formatting. | |||
| /// <code> | |||
| /// // Load a document. | |||
| /// using (DocX document = DocX.Load(@"C:\Example\Test.docx")) | |||
| /// { | |||
| /// // Insert a new Paragraph at the end of this document. | |||
| /// document.InsertParagraph("New text"); | |||
| /// | |||
| /// // Save all changes made to this document. | |||
| /// document.Save(); | |||
| /// }// Release this document from memory | |||
| /// </code> | |||
| /// </example> | |||
| public Paragraph InsertParagraph(string text) | |||
| { | |||
| return InsertParagraph(text, false, new Formatting()); | |||
| } | |||
| internal static List<XElement> FormatInput(string text, XElement rPr) | |||
| { | |||
| List<XElement> newRuns = new List<XElement>(); | |||
| @@ -815,18 +840,18 @@ namespace Novacode | |||
| /// </example> | |||
| public Paragraph InsertParagraph(int index, Paragraph p) | |||
| { | |||
| XElement newXElement = new XElement(p.xml); | |||
| p.xml = newXElement; | |||
| XElement newXElement = new XElement(p.Xml); | |||
| p.Xml = newXElement; | |||
| Paragraph paragraph = GetFirstParagraphEffectedByInsert(this, index); | |||
| if (paragraph == null) | |||
| mainDoc.Descendants(XName.Get("body", DocX.w.NamespaceName)).First().Add(p.xml); | |||
| mainDoc.Descendants(XName.Get("body", DocX.w.NamespaceName)).First().Add(p.Xml); | |||
| else | |||
| { | |||
| XElement[] split = SplitParagraph(paragraph, index - paragraph.startIndex); | |||
| paragraph.xml.ReplaceWith | |||
| paragraph.Xml.ReplaceWith | |||
| ( | |||
| split[0], | |||
| newXElement, | |||
| @@ -918,7 +943,7 @@ namespace Novacode | |||
| } | |||
| #endregion | |||
| XElement newXElement = new XElement(p.xml); | |||
| XElement newXElement = new XElement(p.Xml); | |||
| mainDoc.Descendants(XName.Get("body", DocX.w.NamespaceName)).First().Add(newXElement); | |||
| int index = 0; | |||
| @@ -932,7 +957,7 @@ namespace Novacode | |||
| index += paragraphLookup.Last().Value.Text.Length; | |||
| } | |||
| Paragraph newParagraph = new Paragraph(this, index, newXElement); | |||
| Paragraph newParagraph = new Paragraph(this, newXElement, index); | |||
| paragraphLookup.Add(index, newParagraph); | |||
| return newParagraph; | |||
| } | |||
| @@ -1064,8 +1089,8 @@ namespace Novacode | |||
| Paragraph p = GetFirstParagraphEffectedByInsert(this, index); | |||
| XElement[] split = SplitParagraph(p, index - p.startIndex); | |||
| XElement newXElement = new XElement(t.xml); | |||
| p.xml.ReplaceWith | |||
| XElement newXElement = new XElement(t.Xml); | |||
| p.Xml.ReplaceWith | |||
| ( | |||
| split[0], | |||
| newXElement, | |||
| @@ -1114,7 +1139,7 @@ namespace Novacode | |||
| /// </example> | |||
| public Table InsertTable(Table t) | |||
| { | |||
| XElement newXElement = new XElement(t.xml); | |||
| XElement newXElement = new XElement(t.Xml); | |||
| mainDoc.Descendants(XName.Get("body", DocX.w.NamespaceName)).First().Add(newXElement); | |||
| Table newTable = new Table(this, newXElement); | |||
| @@ -1173,7 +1198,7 @@ namespace Novacode | |||
| { | |||
| XElement[] split = SplitParagraph(p, index - p.startIndex); | |||
| p.xml.ReplaceWith | |||
| p.Xml.ReplaceWith | |||
| ( | |||
| split[0], | |||
| newTable, | |||
| @@ -1229,7 +1254,7 @@ namespace Novacode | |||
| /// </example> | |||
| public Paragraph InsertParagraph(int index, string text, bool trackChanges, Formatting formatting) | |||
| { | |||
| Paragraph newParagraph = new Paragraph(this, index, new XElement(w + "p")); | |||
| Paragraph newParagraph = new Paragraph(this, new XElement(w + "p"), index); | |||
| newParagraph.InsertText(0, text, trackChanges, formatting); | |||
| Paragraph firstPar = GetFirstParagraphEffectedByInsert(this, index); | |||
| @@ -1238,16 +1263,16 @@ namespace Novacode | |||
| { | |||
| XElement[] splitParagraph = SplitParagraph(firstPar, index - firstPar.startIndex); | |||
| firstPar.xml.ReplaceWith | |||
| firstPar.Xml.ReplaceWith | |||
| ( | |||
| splitParagraph[0], | |||
| newParagraph.xml, | |||
| newParagraph.Xml, | |||
| splitParagraph[1] | |||
| ); | |||
| } | |||
| else | |||
| mainDoc.Descendants(XName.Get("body", DocX.w.NamespaceName)).First().Add(newParagraph.xml); | |||
| mainDoc.Descendants(XName.Get("body", DocX.w.NamespaceName)).First().Add(newParagraph.Xml); | |||
| DocX.RebuildParagraphs(this); | |||
| return newParagraph; | |||
| @@ -1275,27 +1300,27 @@ namespace Novacode | |||
| XElement[] split; | |||
| XElement before, after; | |||
| if (r.xml.Parent.Name.LocalName == "ins") | |||
| if (r.Xml.Parent.Name.LocalName == "ins") | |||
| { | |||
| split = p.SplitEdit(r.xml.Parent, index, EditType.ins); | |||
| before = new XElement(p.xml.Name, p.xml.Attributes(), r.xml.Parent.ElementsBeforeSelf(), split[0]); | |||
| after = new XElement(p.xml.Name, p.xml.Attributes(), r.xml.Parent.ElementsAfterSelf(), split[1]); | |||
| split = p.SplitEdit(r.Xml.Parent, index, EditType.ins); | |||
| before = new XElement(p.Xml.Name, p.Xml.Attributes(), r.Xml.Parent.ElementsBeforeSelf(), split[0]); | |||
| after = new XElement(p.Xml.Name, p.Xml.Attributes(), r.Xml.Parent.ElementsAfterSelf(), split[1]); | |||
| } | |||
| else if (r.xml.Parent.Name.LocalName == "del") | |||
| else if (r.Xml.Parent.Name.LocalName == "del") | |||
| { | |||
| split = p.SplitEdit(r.xml.Parent, index, EditType.del); | |||
| split = p.SplitEdit(r.Xml.Parent, index, EditType.del); | |||
| before = new XElement(p.xml.Name, p.xml.Attributes(), r.xml.Parent.ElementsBeforeSelf(), split[0]); | |||
| after = new XElement(p.xml.Name, p.xml.Attributes(), r.xml.Parent.ElementsAfterSelf(), split[1]); | |||
| before = new XElement(p.Xml.Name, p.Xml.Attributes(), r.Xml.Parent.ElementsBeforeSelf(), split[0]); | |||
| after = new XElement(p.Xml.Name, p.Xml.Attributes(), r.Xml.Parent.ElementsAfterSelf(), split[1]); | |||
| } | |||
| else | |||
| { | |||
| split = Run.SplitRun(r, index); | |||
| before = new XElement(p.xml.Name, p.xml.Attributes(), r.xml.ElementsBeforeSelf(), split[0]); | |||
| after = new XElement(p.xml.Name, p.xml.Attributes(), split[1], r.xml.ElementsAfterSelf()); | |||
| before = new XElement(p.Xml.Name, p.Xml.Attributes(), r.Xml.ElementsBeforeSelf(), split[0]); | |||
| after = new XElement(p.Xml.Name, p.Xml.Attributes(), split[1], r.Xml.ElementsAfterSelf()); | |||
| } | |||
| if (before.Elements().Count() == 0) | |||
| @@ -2385,7 +2410,7 @@ namespace Novacode | |||
| d = XDocument.Load(tr); | |||
| // Get the runs in this paragraph | |||
| IEnumerable<Paragraph> paras = d.Descendants(XName.Get("p", "http://schemas.openxmlformats.org/wordprocessingml/2006/main")).Select(p => new Paragraph(this, -1, p)); | |||
| IEnumerable<Paragraph> paras = d.Descendants(XName.Get("p", "http://schemas.openxmlformats.org/wordprocessingml/2006/main")).Select(p => new Paragraph(this, p, -1)); | |||
| foreach (Paragraph p in paras) | |||
| { | |||
| @@ -62,17 +62,18 @@ | |||
| <ItemGroup> | |||
| <Compile Include="CustomProperty.cs" /> | |||
| <Compile Include="DocProperty.cs" /> | |||
| <Compile Include="_BaseClasses.cs" /> | |||
| <Compile Include="Table.cs" /> | |||
| <Compile Include="Enumerations.cs" /> | |||
| <Compile Include="Extensions.cs" /> | |||
| <Compile Include="_Enumerations.cs" /> | |||
| <Compile Include="Formatting.cs" /> | |||
| <Compile Include="Image.cs" /> | |||
| <Compile Include="Picture.cs" /> | |||
| <Compile Include="Paragraph.cs" /> | |||
| <Compile Include="DocX.cs" /> | |||
| <Compile Include="Properties\AssemblyInfo.cs" /> | |||
| <Compile Include="Run.cs" /> | |||
| <Compile Include="Text.cs" /> | |||
| <Compile Include="_Extensions.cs"> | |||
| <SubType>Code</SubType> | |||
| </Compile> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <None Include="Help\DocX v1.0.0.8 - Documentation.chm" /> | |||
| @@ -11,7 +11,7 @@ namespace Novacode | |||
| /// <summary> | |||
| /// Represents a Picture in this document, a Picture is a customized view of an Image. | |||
| /// </summary> | |||
| public class Picture | |||
| public class Picture: DocXElement | |||
| { | |||
| private string id; | |||
| private string name; | |||
| @@ -20,118 +20,33 @@ namespace Novacode | |||
| private uint rotation; | |||
| private bool hFlip, vFlip; | |||
| private object pictureShape; | |||
| // The underlying XElement which this Image wraps | |||
| internal XElement xml; | |||
| private XElement xfrm; | |||
| private XElement prstGeom; | |||
| /// <summary> | |||
| /// Create a new Picture. | |||
| /// </summary> | |||
| /// <param name="id">A unique id that identifies an Image embedded in this document.</param> | |||
| /// <param name="name">The name of this Picture.</param> | |||
| /// <param name="descr">The description of this Picture.</param> | |||
| internal Picture(DocX document, string id, string name, string descr) | |||
| { | |||
| PackagePart word_document = document.package.GetPart(new Uri("/word/document.xml", UriKind.Relative)); | |||
| PackagePart part = document.package.GetPart(word_document.GetRelationship(id).TargetUri); | |||
| this.id = id; | |||
| this.name = name; | |||
| this.descr = descr; | |||
| using (System.Drawing.Image img = System.Drawing.Image.FromStream(part.GetStream())) | |||
| { | |||
| this.cx = img.Width * 9526; | |||
| this.cy = img.Height * 9526; | |||
| } | |||
| XElement e = new XElement(DocX.w + "drawing"); | |||
| xml = XElement.Parse | |||
| (string.Format(@" | |||
| <drawing xmlns = ""http://schemas.openxmlformats.org/wordprocessingml/2006/main""> | |||
| <wp:inline distT=""0"" distB=""0"" distL=""0"" distR=""0"" xmlns:wp=""http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing""> | |||
| <wp:extent cx=""{0}"" cy=""{1}"" /> | |||
| <wp:effectExtent l=""0"" t=""0"" r=""0"" b=""0"" /> | |||
| <wp:docPr id=""1"" name=""{3}"" descr=""{4}"" /> | |||
| <wp:cNvGraphicFramePr> | |||
| <a:graphicFrameLocks xmlns:a=""http://schemas.openxmlformats.org/drawingml/2006/main"" noChangeAspect=""1"" /> | |||
| </wp:cNvGraphicFramePr> | |||
| <a:graphic xmlns:a=""http://schemas.openxmlformats.org/drawingml/2006/main""> | |||
| <a:graphicData uri=""http://schemas.openxmlformats.org/drawingml/2006/picture""> | |||
| <pic:pic xmlns:pic=""http://schemas.openxmlformats.org/drawingml/2006/picture""> | |||
| <pic:nvPicPr> | |||
| <pic:cNvPr id=""0"" name=""{3}"" /> | |||
| <pic:cNvPicPr /> | |||
| </pic:nvPicPr> | |||
| <pic:blipFill> | |||
| <a:blip r:embed=""{2}"" xmlns:r=""http://schemas.openxmlformats.org/officeDocument/2006/relationships""/> | |||
| <a:stretch> | |||
| <a:fillRect /> | |||
| </a:stretch> | |||
| </pic:blipFill> | |||
| <pic:spPr> | |||
| <a:xfrm> | |||
| <a:off x=""0"" y=""0"" /> | |||
| <a:ext cx=""{0}"" cy=""{1}"" /> | |||
| </a:xfrm> | |||
| <a:prstGeom prst=""rect""> | |||
| <a:avLst /> | |||
| </a:prstGeom> | |||
| </pic:spPr> | |||
| </pic:pic> | |||
| </a:graphicData> | |||
| </a:graphic> | |||
| </wp:inline> | |||
| </drawing> | |||
| ", cx, cy, id, name, descr)); | |||
| this.xfrm = | |||
| ( | |||
| from d in xml.Descendants() | |||
| where d.Name.LocalName.Equals("xfrm") | |||
| select d | |||
| ).Single(); | |||
| this.prstGeom = | |||
| ( | |||
| from d in xml.Descendants() | |||
| where d.Name.LocalName.Equals("prstGeom") | |||
| select d | |||
| ).Single(); | |||
| this.rotation = xfrm.Attribute(XName.Get("rot")) == null ? 0 : uint.Parse(xfrm.Attribute(XName.Get("rot")).Value); | |||
| } | |||
| /// <summary> | |||
| /// Remove this Picture from this document. | |||
| /// </summary> | |||
| public void Remove() | |||
| { | |||
| xml.Remove(); | |||
| Xml.Remove(); | |||
| } | |||
| /// <summary> | |||
| /// Wraps an XElement as an Image | |||
| /// </summary> | |||
| /// <param name="i">The XElement i to wrap</param> | |||
| internal Picture(XElement i) | |||
| internal Picture(DocX document, XElement i):base(document, i) | |||
| { | |||
| this.xml = i; | |||
| this.id = | |||
| ( | |||
| from e in i.Descendants() | |||
| from e in Xml.Descendants() | |||
| where e.Name.LocalName.Equals("blip") | |||
| select e.Attribute(XName.Get("embed", "http://schemas.openxmlformats.org/officeDocument/2006/relationships")).Value | |||
| ).Single(); | |||
| this.name = | |||
| ( | |||
| from e in i.Descendants() | |||
| from e in Xml.Descendants() | |||
| let a = e.Attribute(XName.Get("name")) | |||
| where (a != null) | |||
| select a.Value | |||
| @@ -140,7 +55,7 @@ namespace Novacode | |||
| this.descr = | |||
| ( | |||
| from e in i.Descendants() | |||
| from e in Xml.Descendants() | |||
| let a = e.Attribute(XName.Get("descr")) | |||
| where (a != null) | |||
| select a.Value | |||
| @@ -148,7 +63,7 @@ namespace Novacode | |||
| this.cx = | |||
| ( | |||
| from e in i.Descendants() | |||
| from e in Xml.Descendants() | |||
| let a = e.Attribute(XName.Get("cx")) | |||
| where (a != null) | |||
| select int.Parse(a.Value) | |||
| @@ -156,7 +71,7 @@ namespace Novacode | |||
| this.cy = | |||
| ( | |||
| from e in i.Descendants() | |||
| from e in Xml.Descendants() | |||
| let a = e.Attribute(XName.Get("cy")) | |||
| where (a != null) | |||
| select int.Parse(a.Value) | |||
| @@ -164,14 +79,14 @@ namespace Novacode | |||
| this.xfrm = | |||
| ( | |||
| from d in i.Descendants() | |||
| from d in Xml.Descendants() | |||
| where d.Name.LocalName.Equals("xfrm") | |||
| select d | |||
| ).Single(); | |||
| this.prstGeom = | |||
| ( | |||
| from d in i.Descendants() | |||
| from d in Xml.Descendants() | |||
| where d.Name.LocalName.Equals("prstGeom") | |||
| select d | |||
| ).Single(); | |||
| @@ -309,8 +224,8 @@ namespace Novacode | |||
| set | |||
| { | |||
| rotation = (value % 360) * 60000; | |||
| XElement xfrm = | |||
| (from d in xml.Descendants() | |||
| XElement xfrm = | |||
| (from d in Xml.Descendants() | |||
| where d.Name.LocalName.Equals("xfrm") | |||
| select d).Single(); | |||
| @@ -333,7 +248,7 @@ namespace Novacode | |||
| { | |||
| name = value; | |||
| foreach (XAttribute a in xml.Descendants().Attributes(XName.Get("name"))) | |||
| foreach (XAttribute a in Xml.Descendants().Attributes(XName.Get("name"))) | |||
| a.Value = name; | |||
| } | |||
| } | |||
| @@ -349,7 +264,7 @@ namespace Novacode | |||
| { | |||
| descr = value; | |||
| foreach (XAttribute a in xml.Descendants().Attributes(XName.Get("descr"))) | |||
| foreach (XAttribute a in Xml.Descendants().Attributes(XName.Get("descr"))) | |||
| a.Value = descr; | |||
| } | |||
| } | |||
| @@ -365,7 +280,7 @@ namespace Novacode | |||
| { | |||
| cx = value; | |||
| foreach (XAttribute a in xml.Descendants().Attributes(XName.Get("cx"))) | |||
| foreach (XAttribute a in Xml.Descendants().Attributes(XName.Get("cx"))) | |||
| a.Value = (cx * 4156).ToString(); | |||
| } | |||
| } | |||
| @@ -381,7 +296,7 @@ namespace Novacode | |||
| { | |||
| cy = value; | |||
| foreach (XAttribute a in xml.Descendants().Attributes(XName.Get("cy"))) | |||
| foreach (XAttribute a in Xml.Descendants().Attributes(XName.Get("cy"))) | |||
| a.Value = (cy * 4156).ToString(); | |||
| } | |||
| } | |||
| @@ -1,119 +0,0 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Xml.Linq; | |||
| namespace Novacode | |||
| { | |||
| internal class Run | |||
| { | |||
| // A lookup for the text elements in this paragraph | |||
| Dictionary<int, Text> textLookup = new Dictionary<int, Text>(); | |||
| private int startIndex; | |||
| private int endIndex; | |||
| private string text; | |||
| internal XElement xml; | |||
| /// <summary> | |||
| /// Gets the start index of this Text (text length before this text) | |||
| /// </summary> | |||
| public int StartIndex { get { return startIndex; } } | |||
| /// <summary> | |||
| /// Gets the end index of this Text (text length before this text + this texts length) | |||
| /// </summary> | |||
| public int EndIndex { get { return endIndex; } } | |||
| /// <summary> | |||
| /// The text value of this text element | |||
| /// </summary> | |||
| internal string Value { set { value = text; } get { return text; } } | |||
| internal Run(int startIndex, XElement xml) | |||
| { | |||
| this.startIndex = startIndex; | |||
| this.xml = xml; | |||
| // Get the text elements in this run | |||
| IEnumerable<XElement> texts = xml.Descendants(); | |||
| int start = startIndex; | |||
| // Loop through each text in this run | |||
| foreach (XElement te in texts) | |||
| { | |||
| switch (te.Name.LocalName) | |||
| { | |||
| case "tab": | |||
| { | |||
| textLookup.Add(start + 1, new Text(start, te)); | |||
| text += "\t"; | |||
| start++; | |||
| break; | |||
| } | |||
| case "br": | |||
| { | |||
| textLookup.Add(start + 1, new Text(start, te)); | |||
| text += "\n"; | |||
| start++; | |||
| break; | |||
| } | |||
| case "t": goto case "delText"; | |||
| case "delText": | |||
| { | |||
| // Only add strings which are not empty | |||
| if (te.Value.Length > 0) | |||
| { | |||
| textLookup.Add(start + te.Value.Length, new Text(start, te)); | |||
| text += te.Value; | |||
| start += te.Value.Length; | |||
| } | |||
| break; | |||
| } | |||
| default: break; | |||
| } | |||
| } | |||
| endIndex = start; | |||
| } | |||
| static internal XElement[] SplitRun(Run r, int index) | |||
| { | |||
| Text t = r.GetFirstTextEffectedByEdit(index); | |||
| XElement[] splitText = Text.SplitText(t, index); | |||
| XElement splitLeft = new XElement(r.xml.Name, r.xml.Attributes(), r.xml.Element(XName.Get("rPr", DocX.w.NamespaceName)), t.xml.ElementsBeforeSelf().Where(n => n.Name.LocalName != "rPr"), splitText[0]); | |||
| if(Paragraph.GetElementTextLength(splitLeft) == 0) | |||
| splitLeft = null; | |||
| XElement splitRight = new XElement(r.xml.Name, r.xml.Attributes(), r.xml.Element(XName.Get("rPr", DocX.w.NamespaceName)), splitText[1], t.xml.ElementsAfterSelf().Where(n => n.Name.LocalName != "rPr")); | |||
| if(Paragraph.GetElementTextLength(splitRight) == 0) | |||
| splitRight = null; | |||
| return | |||
| ( | |||
| new XElement[] | |||
| { | |||
| splitLeft, | |||
| splitRight | |||
| } | |||
| ); | |||
| } | |||
| internal Text GetFirstTextEffectedByEdit(int index) | |||
| { | |||
| foreach (int textEndIndex in textLookup.Keys) | |||
| { | |||
| if (textEndIndex > index) | |||
| return textLookup[textEndIndex]; | |||
| } | |||
| if (textLookup.Last().Value.EndIndex == index) | |||
| return textLookup.Last().Value; | |||
| throw new ArgumentOutOfRangeException(); | |||
| } | |||
| } | |||
| } | |||
| @@ -7,25 +7,19 @@ using Novacode; | |||
| using System.IO.Packaging; | |||
| using System.IO; | |||
| using System.Reflection; | |||
| using System.Drawing; | |||
| namespace Novacode | |||
| { | |||
| /// <summary> | |||
| /// Designs\Styles that can be applied to a table. | |||
| /// </summary> | |||
| public enum TableDesign { Custom, TableNormal, TableGrid, LightShading, LightShadingAccent1, LightShadingAccent2, LightShadingAccent3, LightShadingAccent4, LightShadingAccent5, LightShadingAccent6, LightList, LightListAccent1, LightListAccent2, LightListAccent3, LightListAccent4, LightListAccent5, LightListAccent6, LightGrid, LightGridAccent1, LightGridAccent2, LightGridAccent3, LightGridAccent4, LightGridAccent5, LightGridAccent6, MediumShading1, MediumShading1Accent1, MediumShading1Accent2, MediumShading1Accent3, MediumShading1Accent4, MediumShading1Accent5, MediumShading1Accent6, MediumShading2, MediumShading2Accent1, MediumShading2Accent2, MediumShading2Accent3, MediumShading2Accent4, MediumShading2Accent5, MediumShading2Accent6, MediumList1, MediumList1Accent1, MediumList1Accent2, MediumList1Accent3, MediumList1Accent4, MediumList1Accent5, MediumList1Accent6, MediumList2, MediumList2Accent1, MediumList2Accent2, MediumList2Accent3, MediumList2Accent4, MediumList2Accent5, MediumList2Accent6, MediumGrid1, MediumGrid1Accent1, MediumGrid1Accent2, MediumGrid1Accent3, MediumGrid1Accent4, MediumGrid1Accent5, MediumGrid1Accent6, MediumGrid2, MediumGrid2Accent1, MediumGrid2Accent2, MediumGrid2Accent3, MediumGrid2Accent4, MediumGrid2Accent5, MediumGrid2Accent6, MediumGrid3, MediumGrid3Accent1, MediumGrid3Accent2, MediumGrid3Accent3, MediumGrid3Accent4, MediumGrid3Accent5, MediumGrid3Accent6, DarkList, DarkListAccent1, DarkListAccent2, DarkListAccent3, DarkListAccent4, DarkListAccent5, DarkListAccent6, ColorfulShading, ColorfulShadingAccent1, ColorfulShadingAccent2, ColorfulShadingAccent3, ColorfulShadingAccent4, ColorfulShadingAccent5, ColorfulShadingAccent6, ColorfulList, ColorfulListAccent1, ColorfulListAccent2, ColorfulListAccent3, ColorfulListAccent4, ColorfulListAccent5, ColorfulListAccent6, ColorfulGrid, ColorfulGridAccent1, ColorfulGridAccent2, ColorfulGridAccent3, ColorfulGridAccent4, ColorfulGridAccent5, ColorfulGridAccent6, None}; | |||
| public enum AutoFit{Contents, Window, ColoumnWidth}; | |||
| { | |||
| /// <summary> | |||
| /// Represents a Table in a document. | |||
| /// </summary> | |||
| public class Table | |||
| public class Table : InsertBeforeOrAfter | |||
| { | |||
| private Alignment alignment; | |||
| private AutoFit autofit; | |||
| private List<Row> rows; | |||
| private int rowCount, columnCount; | |||
| internal XElement xml; | |||
| /// <summary> | |||
| /// Returns the number of rows in this table. | |||
| @@ -41,14 +35,12 @@ namespace Novacode | |||
| /// Returns a list of rows in this table. | |||
| /// </summary> | |||
| public List<Row> Rows { get { return rows; } } | |||
| DocX document; | |||
| private TableDesign design; | |||
| internal Table(DocX document, XElement xml) | |||
| internal Table(DocX document, XElement xml):base(document, xml) | |||
| { | |||
| autofit = AutoFit.ColoumnWidth; | |||
| this.xml = xml; | |||
| this.document = document; | |||
| this.Xml = xml; | |||
| XElement properties = xml.Element(XName.Get("tblPr", DocX.w.NamespaceName)); | |||
| @@ -120,7 +112,7 @@ namespace Novacode | |||
| } | |||
| } | |||
| XElement tblPr = xml.Descendants(XName.Get("tblPr", DocX.w.NamespaceName)).First(); | |||
| XElement tblPr = Xml.Descendants(XName.Get("tblPr", DocX.w.NamespaceName)).First(); | |||
| XElement jc = tblPr.Descendants(XName.Get("jc", DocX.w.NamespaceName)).FirstOrDefault(); | |||
| if(jc != null) | |||
| @@ -163,7 +155,7 @@ namespace Novacode | |||
| } | |||
| } | |||
| var query = from d in xml.Descendants() | |||
| var query = from d in Xml.Descendants() | |||
| let type = d.Attribute(XName.Get("type", DocX.w.NamespaceName)) | |||
| where (d.Name.LocalName == "tcW" || d.Name.LocalName == "tblW") && type != null | |||
| select type; | |||
| @@ -182,7 +174,7 @@ namespace Novacode | |||
| get { return design; } | |||
| set | |||
| { | |||
| XElement tblPr = xml.Element(XName.Get("tblPr", DocX.w.NamespaceName)); | |||
| XElement tblPr = Xml.Element(XName.Get("tblPr", DocX.w.NamespaceName)); | |||
| XElement style = tblPr.Element(XName.Get("tblStyle", DocX.w.NamespaceName)); | |||
| if (style == null) | |||
| { | |||
| @@ -316,7 +308,7 @@ namespace Novacode | |||
| } | |||
| XDocument style_doc; | |||
| PackagePart word_styles = document.package.GetPart(new Uri("/word/styles.xml", UriKind.Relative)); | |||
| PackagePart word_styles = Document.package.GetPart(new Uri("/word/styles.xml", UriKind.Relative)); | |||
| using (TextReader tr = new StreamReader(word_styles.GetStream())) | |||
| style_doc = XDocument.Load(tr); | |||
| @@ -414,7 +406,7 @@ namespace Novacode | |||
| get | |||
| { | |||
| int index = 0; | |||
| IEnumerable<XElement> previous = xml.ElementsBeforeSelf(); | |||
| IEnumerable<XElement> previous = Xml.ElementsBeforeSelf(); | |||
| foreach (XElement e in previous) | |||
| index += Paragraph.GetElementTextLength(e); | |||
| @@ -445,7 +437,7 @@ namespace Novacode | |||
| /// </example> | |||
| public void Remove() | |||
| { | |||
| xml.Remove(); | |||
| Xml.Remove(); | |||
| } | |||
| /// <summary> | |||
| @@ -541,7 +533,7 @@ namespace Novacode | |||
| if (index < 0 || index > rows.Count) | |||
| throw new IndexOutOfRangeException(); | |||
| rows[index].xml.Remove(); | |||
| rows[index].Xml.Remove(); | |||
| } | |||
| /// <summary> | |||
| @@ -596,7 +588,7 @@ namespace Novacode | |||
| throw new IndexOutOfRangeException(); | |||
| foreach (Row r in rows) | |||
| r.Cells[index].xml.Remove(); | |||
| r.Cells[index].Xml.Remove(); | |||
| } | |||
| /// <summary> | |||
| @@ -638,19 +630,19 @@ namespace Novacode | |||
| content.Add(new XElement(XName.Get("tc", DocX.w.NamespaceName), new XElement(XName.Get("p", DocX.w.NamespaceName)))); | |||
| XElement e = new XElement(XName.Get("tr", DocX.w.NamespaceName), content); | |||
| Row newRow = new Row(document, e); | |||
| Row newRow = new Row(Document, e); | |||
| XElement rowXml; | |||
| if (index == rows.Count) | |||
| { | |||
| rowXml = rows.Last().xml; | |||
| rowXml.AddAfterSelf(newRow.xml); | |||
| rowXml = rows.Last().Xml; | |||
| rowXml.AddAfterSelf(newRow.Xml); | |||
| } | |||
| else | |||
| { | |||
| rowXml = rows[index].xml; | |||
| rowXml.AddBeforeSelf(newRow.xml); | |||
| rowXml = rows[index].Xml; | |||
| rowXml.AddBeforeSelf(newRow.Xml); | |||
| } | |||
| rows.Insert(index, newRow); | |||
| @@ -704,13 +696,13 @@ namespace Novacode | |||
| foreach (Row r in rows) | |||
| { | |||
| if(columnCount == index) | |||
| r.Cells[index - 1].xml.AddAfterSelf(new XElement(XName.Get("tc", DocX.w.NamespaceName), new XElement(XName.Get("p", DocX.w.NamespaceName)))); | |||
| r.Cells[index - 1].Xml.AddAfterSelf(new XElement(XName.Get("tc", DocX.w.NamespaceName), new XElement(XName.Get("p", DocX.w.NamespaceName)))); | |||
| else | |||
| r.Cells[index].xml.AddBeforeSelf(new XElement(XName.Get("tc", DocX.w.NamespaceName), new XElement(XName.Get("p", DocX.w.NamespaceName)))); | |||
| r.Cells[index].Xml.AddBeforeSelf(new XElement(XName.Get("tc", DocX.w.NamespaceName), new XElement(XName.Get("p", DocX.w.NamespaceName)))); | |||
| } | |||
| rows = (from r in xml.Elements(XName.Get("tr", DocX.w.NamespaceName)) | |||
| select new Row(document, r)).ToList(); | |||
| rows = (from r in Xml.Elements(XName.Get("tr", DocX.w.NamespaceName)) | |||
| select new Row(Document, r)).ToList(); | |||
| rowCount = rows.Count; | |||
| @@ -721,89 +713,62 @@ namespace Novacode | |||
| } | |||
| /// <summary> | |||
| /// Insert a page break after a Table. | |||
| /// Insert a page break before a Table. | |||
| /// </summary> | |||
| /// <example> | |||
| /// Insert a Table and a Paragraph into a document with a page break between them. | |||
| /// <code> | |||
| /// // Create a new document. | |||
| /// using (DocX document = DocX.Create(@"Test.docx")) | |||
| /// { | |||
| /// // Insert a new Table. | |||
| /// Table t1 = document.InsertTable(2, 2); | |||
| /// t1.Design = TableDesign.LightShadingAccent1; | |||
| /// | |||
| /// // Insert a page break after this Table. | |||
| /// t1.InsertPageBreakAfterSelf(); | |||
| /// | |||
| /// { | |||
| /// // Insert a new Paragraph. | |||
| /// Paragraph p1 = document.InsertParagraph("Paragraph", false); | |||
| /// | |||
| /// // Insert a new Table. | |||
| /// Table t1 = document.InsertTable(2, 2); | |||
| /// t1.Design = TableDesign.LightShadingAccent1; | |||
| /// | |||
| /// // Insert a page break before this Table. | |||
| /// t1.InsertPageBreakBeforeSelf(); | |||
| /// | |||
| /// // Save this document. | |||
| /// document.Save(); | |||
| /// }// Release this document from memory. | |||
| /// </code> | |||
| /// </example> | |||
| public void InsertPageBreakAfterSelf() | |||
| public override void InsertPageBreakBeforeSelf() | |||
| { | |||
| XElement p = new XElement | |||
| ( | |||
| XName.Get("p", DocX.w.NamespaceName), | |||
| new XElement | |||
| ( | |||
| XName.Get("r", DocX.w.NamespaceName), | |||
| new XElement | |||
| ( | |||
| XName.Get("br", DocX.w.NamespaceName), | |||
| new XAttribute(XName.Get("type", DocX.w.NamespaceName), "page") | |||
| ) | |||
| ) | |||
| ); | |||
| xml.AddAfterSelf(p); | |||
| base.InsertPageBreakBeforeSelf(); | |||
| } | |||
| /// <summary> | |||
| /// Insert a page break before a Table. | |||
| /// Insert a page break after a Table. | |||
| /// </summary> | |||
| /// <example> | |||
| /// Insert a Table and a Paragraph into a document with a page break between them. | |||
| /// <code> | |||
| /// // Create a new document. | |||
| /// using (DocX document = DocX.Create(@"Test.docx")) | |||
| /// { | |||
| /// // Insert a new Paragraph. | |||
| /// Paragraph p1 = document.InsertParagraph("Paragraph", false); | |||
| /// | |||
| /// { | |||
| /// // Insert a new Table. | |||
| /// Table t1 = document.InsertTable(2, 2); | |||
| /// t1.Design = TableDesign.LightShadingAccent1; | |||
| /// | |||
| /// // Insert a page break before this Table. | |||
| /// t1.InsertPageBreakBeforeSelf(); | |||
| /// | |||
| /// | |||
| /// // Insert a page break after this Table. | |||
| /// t1.InsertPageBreakAfterSelf(); | |||
| /// | |||
| /// // Insert a new Paragraph. | |||
| /// Paragraph p1 = document.InsertParagraph("Paragraph", false); | |||
| /// | |||
| /// // Save this document. | |||
| /// document.Save(); | |||
| /// }// Release this document from memory. | |||
| /// </code> | |||
| /// </example> | |||
| public void InsertPageBreakBeforeSelf() | |||
| public override void InsertPageBreakAfterSelf() | |||
| { | |||
| XElement p = new XElement | |||
| ( | |||
| XName.Get("p", DocX.w.NamespaceName), | |||
| new XElement | |||
| ( | |||
| XName.Get("r", DocX.w.NamespaceName), | |||
| new XElement | |||
| ( | |||
| XName.Get("br", DocX.w.NamespaceName), | |||
| new XAttribute(XName.Get("type", DocX.w.NamespaceName), "page") | |||
| ) | |||
| ) | |||
| ); | |||
| xml.AddBeforeSelf(p); | |||
| base.InsertPageBreakAfterSelf(); | |||
| } | |||
| /// <summary> | |||
| @@ -838,16 +803,9 @@ namespace Novacode | |||
| /// }// Release this document from memory. | |||
| /// </code> | |||
| /// </example> | |||
| public Table InsertTableBeforeSelf(Table t) | |||
| public override Table InsertTableBeforeSelf(Table t) | |||
| { | |||
| xml.AddBeforeSelf(t.xml); | |||
| XElement newlyInserted = xml.ElementsBeforeSelf().First(); | |||
| t.xml = newlyInserted; | |||
| DocX.RebuildTables(document); | |||
| DocX.RebuildParagraphs(document); | |||
| return t; | |||
| return base.InsertTableBeforeSelf(t); | |||
| } | |||
| /// <summary> | |||
| @@ -876,15 +834,9 @@ namespace Novacode | |||
| /// }// Release this document from memory. | |||
| /// </code> | |||
| /// </example> | |||
| public Table InsertTableBeforeSelf(int rowCount, int coloumnCount) | |||
| public override Table InsertTableBeforeSelf(int rowCount, int coloumnCount) | |||
| { | |||
| XElement newTable = DocX.CreateTable(rowCount, coloumnCount); | |||
| xml.AddBeforeSelf(newTable); | |||
| XElement newlyInserted = xml.ElementsBeforeSelf().First(); | |||
| DocX.RebuildTables(document); | |||
| DocX.RebuildParagraphs(document); | |||
| return new Table(document, newlyInserted); | |||
| return base.InsertTableBeforeSelf(rowCount, coloumnCount); | |||
| } | |||
| /// <summary> | |||
| @@ -919,16 +871,9 @@ namespace Novacode | |||
| /// }// Release this document from memory. | |||
| /// </code> | |||
| /// </example> | |||
| public Table InsertTableAfterSelf(Table t) | |||
| public override Table InsertTableAfterSelf(Table t) | |||
| { | |||
| xml.AddAfterSelf(t.xml); | |||
| XElement newlyInserted = xml.ElementsAfterSelf().First(); | |||
| t.xml = newlyInserted; | |||
| DocX.RebuildTables(document); | |||
| DocX.RebuildParagraphs(document); | |||
| return t; | |||
| return base.InsertTableAfterSelf(t); | |||
| } | |||
| /// <summary> | |||
| @@ -957,15 +902,9 @@ namespace Novacode | |||
| /// }// Release this document from memory. | |||
| /// </code> | |||
| /// </example> | |||
| public Table InsertTableAfterSelf(int rowCount, int coloumnCount) | |||
| public override Table InsertTableAfterSelf(int rowCount, int coloumnCount) | |||
| { | |||
| XElement newTable = DocX.CreateTable(rowCount, coloumnCount); | |||
| xml.AddAfterSelf(newTable); | |||
| XElement newlyInserted = xml.ElementsAfterSelf().First(); | |||
| DocX.RebuildTables(document); | |||
| DocX.RebuildParagraphs(document); | |||
| return new Table(document, newlyInserted); | |||
| return base.InsertTableAfterSelf(rowCount, coloumnCount); | |||
| } | |||
| /// <summary> | |||
| @@ -1000,15 +939,9 @@ namespace Novacode | |||
| /// }// Release this document from memory. | |||
| /// </code> | |||
| /// </example> | |||
| public Paragraph InsertParagraphBeforeSelf(Paragraph p) | |||
| public override Paragraph InsertParagraphBeforeSelf(Paragraph p) | |||
| { | |||
| xml.AddBeforeSelf(p.xml); | |||
| XElement newlyInserted = xml.ElementsBeforeSelf().First(); | |||
| p.xml = newlyInserted; | |||
| DocX.RebuildParagraphs(document); | |||
| return p; | |||
| return base.InsertParagraphBeforeSelf(p); | |||
| } | |||
| /// <summary> | |||
| @@ -1032,9 +965,9 @@ namespace Novacode | |||
| /// }// Release this new document form memory. | |||
| /// </code> | |||
| /// </example> | |||
| public Paragraph InsertParagraphBeforeSelf(string text) | |||
| public override Paragraph InsertParagraphBeforeSelf(string text) | |||
| { | |||
| return InsertParagraphBeforeSelf(text, false, new Formatting()); | |||
| return base.InsertParagraphBeforeSelf(text); | |||
| } | |||
| /// <summary> | |||
| @@ -1059,9 +992,9 @@ namespace Novacode | |||
| /// }// Release this new document form memory. | |||
| /// </code> | |||
| /// </example> | |||
| public Paragraph InsertParagraphBeforeSelf(string text, bool trackChanges) | |||
| public override Paragraph InsertParagraphBeforeSelf(string text, bool trackChanges) | |||
| { | |||
| return InsertParagraphBeforeSelf(text, trackChanges, new Formatting()); | |||
| return base.InsertParagraphBeforeSelf(text, trackChanges); | |||
| } | |||
| /// <summary> | |||
| @@ -1090,23 +1023,9 @@ namespace Novacode | |||
| /// }// Release this new document form memory. | |||
| /// </code> | |||
| /// </example> | |||
| public Paragraph InsertParagraphBeforeSelf(string text, bool trackChanges, Formatting formatting) | |||
| public override Paragraph InsertParagraphBeforeSelf(string text, bool trackChanges, Formatting formatting) | |||
| { | |||
| XElement newParagraph = new XElement | |||
| ( | |||
| XName.Get("p", DocX.w.NamespaceName), new XElement(XName.Get("pPr", DocX.w.NamespaceName)), DocX.FormatInput(text, formatting.Xml) | |||
| ); | |||
| if (trackChanges) | |||
| newParagraph = Paragraph.CreateEdit(EditType.ins, DateTime.Now, newParagraph); | |||
| xml.AddBeforeSelf(newParagraph); | |||
| XElement newlyInserted = xml.ElementsBeforeSelf().First(); | |||
| Paragraph p = new Paragraph(document, -1, newlyInserted); | |||
| DocX.RebuildParagraphs(document); | |||
| return p; | |||
| return base.InsertParagraphBeforeSelf(text, trackChanges, formatting); | |||
| } | |||
| /// <summary> | |||
| @@ -1141,15 +1060,9 @@ namespace Novacode | |||
| /// }// Release this document from memory. | |||
| /// </code> | |||
| /// </example> | |||
| public Paragraph InsertParagraphAfterSelf(Paragraph p) | |||
| public override Paragraph InsertParagraphAfterSelf(Paragraph p) | |||
| { | |||
| xml.AddAfterSelf(p.xml); | |||
| XElement newlyInserted = xml.ElementsAfterSelf().First(); | |||
| p.xml = newlyInserted; | |||
| DocX.RebuildParagraphs(document); | |||
| return p; | |||
| return base.InsertParagraphAfterSelf(p); | |||
| } | |||
| /// <summary> | |||
| @@ -1178,23 +1091,9 @@ namespace Novacode | |||
| /// }// Release this new document form memory. | |||
| /// </code> | |||
| /// </example> | |||
| public Paragraph InsertParagraphAfterSelf(string text, bool trackChanges, Formatting formatting) | |||
| public override Paragraph InsertParagraphAfterSelf(string text, bool trackChanges, Formatting formatting) | |||
| { | |||
| XElement newParagraph = new XElement | |||
| ( | |||
| XName.Get("p", DocX.w.NamespaceName), new XElement(XName.Get("pPr", DocX.w.NamespaceName)), DocX.FormatInput(text, formatting.Xml) | |||
| ); | |||
| if (trackChanges) | |||
| newParagraph = Paragraph.CreateEdit(EditType.ins, DateTime.Now, newParagraph); | |||
| xml.AddAfterSelf(newParagraph); | |||
| XElement newlyInserted = xml.ElementsAfterSelf().First(); | |||
| Paragraph p = new Paragraph(document, -1, newlyInserted); | |||
| DocX.RebuildParagraphs(document); | |||
| return p; | |||
| return base.InsertParagraphAfterSelf(text, trackChanges, formatting); | |||
| } | |||
| /// <summary> | |||
| @@ -1219,9 +1118,9 @@ namespace Novacode | |||
| /// }// Release this new document form memory. | |||
| /// </code> | |||
| /// </example> | |||
| public Paragraph InsertParagraphAfterSelf(string text, bool trackChanges) | |||
| public override Paragraph InsertParagraphAfterSelf(string text, bool trackChanges) | |||
| { | |||
| return InsertParagraphAfterSelf(text, trackChanges, new Formatting()); | |||
| return base.InsertParagraphAfterSelf(text, trackChanges); | |||
| } | |||
| /// <summary> | |||
| @@ -1245,19 +1144,17 @@ namespace Novacode | |||
| /// }// Release this new document form memory. | |||
| /// </code> | |||
| /// </example> | |||
| public Paragraph InsertParagraphAfterSelf(string text) | |||
| public override Paragraph InsertParagraphAfterSelf(string text) | |||
| { | |||
| return InsertParagraphAfterSelf(text, false, new Formatting()); | |||
| return base.InsertParagraphAfterSelf(text); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Represents a single row in a Table. | |||
| /// </summary> | |||
| public class Row | |||
| public class Row:DocXElement | |||
| { | |||
| DocX document; | |||
| internal XElement xml; | |||
| private List<Cell> cells; | |||
| /// <summary> | |||
| @@ -1265,10 +1162,8 @@ namespace Novacode | |||
| /// </summary> | |||
| public List<Cell> Cells { get { return cells; } } | |||
| internal Row(DocX document, XElement xml) | |||
| internal Row(DocX document, XElement xml):base(document, xml) | |||
| { | |||
| this.document = document; | |||
| this.xml = xml; | |||
| cells = (from c in xml.Elements(XName.Get("tc", DocX.w.NamespaceName)) | |||
| select new Cell(document, c)).ToList(); | |||
| } | |||
| @@ -1284,7 +1179,7 @@ namespace Novacode | |||
| * Get the trPr (table row properties) element for this Row, | |||
| * null will be return if no such element exists. | |||
| */ | |||
| XElement trPr = xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||
| XElement trPr = Xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||
| // If trPr is null, this row contains no height information. | |||
| if(trPr == null) | |||
| @@ -1325,11 +1220,11 @@ namespace Novacode | |||
| * Get the trPr (table row properties) element for this Row, | |||
| * null will be return if no such element exists. | |||
| */ | |||
| XElement trPr = xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||
| XElement trPr = Xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||
| if (trPr == null) | |||
| { | |||
| xml.SetElementValue(XName.Get("trPr", DocX.w.NamespaceName), string.Empty); | |||
| trPr = xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||
| Xml.SetElementValue(XName.Get("trPr", DocX.w.NamespaceName), string.Empty); | |||
| trPr = Xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||
| } | |||
| /* | |||
| @@ -1366,7 +1261,7 @@ namespace Novacode | |||
| // Foreach each Cell between startIndex and endIndex inclusive. | |||
| foreach (Cell c in cells.Where((z, i) => i > startIndex && i <= endIndex)) | |||
| { | |||
| XElement tcPr = c.xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||
| XElement tcPr = c.Xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||
| if (tcPr != null) | |||
| { | |||
| XElement gridSpan = tcPr.Element(XName.Get("gridSpan", DocX.w.NamespaceName)); | |||
| @@ -1382,21 +1277,21 @@ namespace Novacode | |||
| } | |||
| // Add this cells Pragraph to the merge start Cell. | |||
| cells[startIndex].xml.Add(c.xml.Elements(XName.Get("p", DocX.w.NamespaceName))); | |||
| cells[startIndex].Xml.Add(c.Xml.Elements(XName.Get("p", DocX.w.NamespaceName))); | |||
| // Remove this Cell. | |||
| c.xml.Remove(); | |||
| c.Xml.Remove(); | |||
| } | |||
| /* | |||
| * Get the tcPr (table cell properties) element for the first cell in this merge, | |||
| * null will be returned if no such element exists. | |||
| */ | |||
| XElement start_tcPr = cells[startIndex].xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||
| XElement start_tcPr = cells[startIndex].Xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||
| if (start_tcPr == null) | |||
| { | |||
| cells[startIndex].xml.SetElementValue(XName.Get("tcPr", DocX.w.NamespaceName), string.Empty); | |||
| start_tcPr = cells[startIndex].xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||
| cells[startIndex].Xml.SetElementValue(XName.Get("tcPr", DocX.w.NamespaceName), string.Empty); | |||
| start_tcPr = cells[startIndex].Xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||
| } | |||
| /* | |||
| @@ -1427,32 +1322,94 @@ namespace Novacode | |||
| // Rebuild the cells collection. | |||
| cells = | |||
| ( | |||
| from c in xml.Elements(XName.Get("tc", DocX.w.NamespaceName)) | |||
| select new Cell(document, c) | |||
| from c in Xml.Elements(XName.Get("tc", DocX.w.NamespaceName)) | |||
| select new Cell(Document, c) | |||
| ).ToList(); | |||
| } | |||
| } | |||
| public class Cell | |||
| public class Cell:DocXElement | |||
| { | |||
| private Paragraph p; | |||
| private DocX document; | |||
| internal XElement xml; | |||
| private List<Paragraph> paragraphs; | |||
| public List<Paragraph> Paragraphs | |||
| { | |||
| get { return paragraphs; } | |||
| set { paragraphs = value; } | |||
| } | |||
| public Paragraph Paragraph | |||
| internal Cell(DocX document, XElement xml):base(document, xml) | |||
| { | |||
| get { return p; } | |||
| set { p = value; } | |||
| paragraphs = xml.Elements(XName.Get("p", DocX.w.NamespaceName)).Select(p => new Paragraph(document, p, 0)).ToList(); | |||
| } | |||
| internal Cell(DocX document, XElement xml) | |||
| public Color Shading | |||
| { | |||
| this.document = document; | |||
| this.xml = xml; | |||
| get | |||
| { | |||
| /* | |||
| * Get the tcPr (table cell properties) element for this Cell, | |||
| * null will be return if no such element exists. | |||
| */ | |||
| XElement tcPr = Xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||
| // If tcPr is null, this cell contains no Color information. | |||
| if (tcPr == null) | |||
| return Color.White; | |||
| XElement properties = xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||
| /* | |||
| * Get the shd (table shade) element for this Cell, | |||
| * null will be return if no such element exists. | |||
| */ | |||
| XElement shd = tcPr.Element(XName.Get("shd", DocX.w.NamespaceName)); | |||
| p = new Paragraph(document, 0, xml.Element(XName.Get("p", DocX.w.NamespaceName))); | |||
| // If shd is null, this cell contains no Color information. | |||
| if (shd == null) | |||
| return Color.White; | |||
| // Get the w attribute of the tcW element. | |||
| XAttribute fill = shd.Attribute(XName.Get("fill", DocX.w.NamespaceName)); | |||
| // If fill is null, this cell contains no Color information. | |||
| if (fill == null) | |||
| return Color.White; | |||
| return ColorTranslator.FromHtml(string.Format("#{0}", fill.Value)); | |||
| } | |||
| set | |||
| { | |||
| /* | |||
| * Get the tcPr (table cell properties) element for this Cell, | |||
| * null will be return if no such element exists. | |||
| */ | |||
| XElement tcPr = Xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||
| if (tcPr == null) | |||
| { | |||
| Xml.SetElementValue(XName.Get("tcPr", DocX.w.NamespaceName), string.Empty); | |||
| tcPr = Xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||
| } | |||
| /* | |||
| * Get the shd (table shade) element for this Cell, | |||
| * null will be return if no such element exists. | |||
| */ | |||
| XElement shd = tcPr.Element(XName.Get("shd", DocX.w.NamespaceName)); | |||
| if (shd == null) | |||
| { | |||
| tcPr.SetElementValue(XName.Get("shd", DocX.w.NamespaceName), string.Empty); | |||
| shd = tcPr.Element(XName.Get("shd", DocX.w.NamespaceName)); | |||
| } | |||
| // The val attribute needs to be set to clear | |||
| shd.SetAttributeValue(XName.Get("val", DocX.w.NamespaceName), "clear"); | |||
| // The color attribute needs to be set to auto | |||
| shd.SetAttributeValue(XName.Get("color", DocX.w.NamespaceName), "auto"); | |||
| // The fill attribute needs to be set to the hex for this Color. | |||
| shd.SetAttributeValue(XName.Get("fill", DocX.w.NamespaceName), value.ToHex()); | |||
| } | |||
| } | |||
| /// <summary> | |||
| @@ -1466,7 +1423,7 @@ namespace Novacode | |||
| * Get the tcPr (table cell properties) element for this Cell, | |||
| * null will be return if no such element exists. | |||
| */ | |||
| XElement tcPr = xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||
| XElement tcPr = Xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||
| // If tcPr is null, this cell contains no width information. | |||
| if (tcPr == null) | |||
| @@ -1507,11 +1464,11 @@ namespace Novacode | |||
| * Get the tcPr (table cell properties) element for this Cell, | |||
| * null will be return if no such element exists. | |||
| */ | |||
| XElement tcPr = xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||
| XElement tcPr = Xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||
| if (tcPr == null) | |||
| { | |||
| xml.SetElementValue(XName.Get("tcPr", DocX.w.NamespaceName), string.Empty); | |||
| tcPr = xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||
| Xml.SetElementValue(XName.Get("tcPr", DocX.w.NamespaceName), string.Empty); | |||
| tcPr = Xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||
| } | |||
| /* | |||
| @@ -1,143 +0,0 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Xml.Linq; | |||
| namespace Novacode | |||
| { | |||
| internal class Text | |||
| { | |||
| private int startIndex; | |||
| private int endIndex; | |||
| private string text; | |||
| internal XElement xml; | |||
| /// <summary> | |||
| /// Gets the start index of this Text (text length before this text) | |||
| /// </summary> | |||
| public int StartIndex { get { return startIndex; } } | |||
| /// <summary> | |||
| /// Gets the end index of this Text (text length before this text + this texts length) | |||
| /// </summary> | |||
| public int EndIndex { get { return endIndex; } } | |||
| /// <summary> | |||
| /// The text value of this text element | |||
| /// </summary> | |||
| public string Value { get { return text; } } | |||
| internal Text(int startIndex, XElement e) | |||
| { | |||
| this.startIndex = startIndex; | |||
| this.xml = e; | |||
| switch (e.Name.LocalName) | |||
| { | |||
| case "t": | |||
| { | |||
| goto case "delText"; | |||
| } | |||
| case "delText": | |||
| { | |||
| endIndex = startIndex + e.Value.Length; | |||
| text = e.Value; | |||
| break; | |||
| } | |||
| case "br": | |||
| { | |||
| text = "\n"; | |||
| endIndex = startIndex + 1; | |||
| break; | |||
| } | |||
| case "tab": | |||
| { | |||
| text = "\t"; | |||
| endIndex = startIndex + 1; | |||
| break; | |||
| } | |||
| default: | |||
| { | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| internal static XElement[] SplitText(Text t, int index) | |||
| { | |||
| if (index < t.startIndex || index > t.EndIndex) | |||
| throw new ArgumentOutOfRangeException("index"); | |||
| XElement splitLeft = null, splitRight = null; | |||
| if (t.xml.Name.LocalName == "t" || t.xml.Name.LocalName == "delText") | |||
| { | |||
| // The origional text element, now containing only the text before the index point. | |||
| splitLeft = new XElement(t.xml.Name, t.xml.Attributes(), t.xml.Value.Substring(0, index - t.startIndex)); | |||
| if (splitLeft.Value.Length == 0) | |||
| splitLeft = null; | |||
| else | |||
| PreserveSpace(splitLeft); | |||
| // The origional text element, now containing only the text after the index point. | |||
| splitRight = new XElement(t.xml.Name, t.xml.Attributes(), t.xml.Value.Substring(index - t.startIndex, t.xml.Value.Length - (index - t.startIndex))); | |||
| if (splitRight.Value.Length == 0) | |||
| splitRight = null; | |||
| else | |||
| PreserveSpace(splitRight); | |||
| } | |||
| else | |||
| { | |||
| if (index == t.StartIndex) | |||
| splitLeft = t.xml; | |||
| else | |||
| splitRight = t.xml; | |||
| } | |||
| return | |||
| ( | |||
| new XElement[] | |||
| { | |||
| splitLeft, | |||
| splitRight | |||
| } | |||
| ); | |||
| } | |||
| /// <summary> | |||
| /// If a text element or delText element, starts or ends with a space, | |||
| /// it must have the attribute space, otherwise it must not have it. | |||
| /// </summary> | |||
| /// <param name="e">The (t or delText) element check</param> | |||
| public static void PreserveSpace(XElement e) | |||
| { | |||
| // PreserveSpace should only be used on (t or delText) elements | |||
| if (!e.Name.Equals(DocX.w + "t") && !e.Name.Equals(DocX.w + "delText")) | |||
| throw new ArgumentException("SplitText can only split elements of type t or delText", "e"); | |||
| // Check if this w:t contains a space atribute | |||
| XAttribute space = e.Attributes().Where(a => a.Name.Equals(XNamespace.Xml + "space")).SingleOrDefault(); | |||
| // This w:t's text begins or ends with whitespace | |||
| if (e.Value.StartsWith(" ") || e.Value.EndsWith(" ")) | |||
| { | |||
| // If this w:t contains no space attribute, add one. | |||
| if (space == null) | |||
| e.Add(new XAttribute(XNamespace.Xml + "space", "preserve")); | |||
| } | |||
| // This w:t's text does not begin or end with a space | |||
| else | |||
| { | |||
| // If this w:r contains a space attribute, remove it. | |||
| if (space != null) | |||
| space.Remove(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,218 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Xml.Linq; | |||
| namespace Novacode | |||
| { | |||
| /// <summary> | |||
| /// All DocX types are derived from DocXElement. | |||
| /// This class contains properties which every element of a DocX must contain. | |||
| /// </summary> | |||
| public abstract class DocXElement | |||
| { | |||
| /// <summary> | |||
| /// This is the actual Xml that gives this element substance. | |||
| /// For example, a Paragraphs Xml might look something like the following | |||
| /// <p> | |||
| /// <r> | |||
| /// <t>Hello World!</t> | |||
| /// </r> | |||
| /// </p> | |||
| /// </summary> | |||
| private XElement xml; | |||
| internal XElement Xml { get { return xml; } set { xml = value; } } | |||
| /// <summary> | |||
| /// This is a reference to the DocX object that this element belongs to. | |||
| /// Every DocX element is connected to a document. | |||
| /// </summary> | |||
| private DocX document; | |||
| internal DocX Document { get { return document; } set { document = value; } } | |||
| /// <summary> | |||
| /// Store both the document and xml so that they can be accessed by derived types. | |||
| /// </summary> | |||
| /// <param name="document">The document that this element belongs to.</param> | |||
| /// <param name="xml">The Xml that gives this element substance</param> | |||
| public DocXElement(DocX document, XElement xml) | |||
| { | |||
| this.document = document; | |||
| this.xml = xml; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// This class provides functions for inserting new DocXElements before or after the current DocXElement. | |||
| /// Only certain DocXElements can support these functions without creating invalid documents, at the moment these are Paragraphs and Table. | |||
| /// </summary> | |||
| public abstract class InsertBeforeOrAfter:DocXElement | |||
| { | |||
| public InsertBeforeOrAfter(DocX document, XElement xml):base(document, xml) { } | |||
| public virtual void InsertPageBreakBeforeSelf() | |||
| { | |||
| XElement p = new XElement | |||
| ( | |||
| XName.Get("p", DocX.w.NamespaceName), | |||
| new XElement | |||
| ( | |||
| XName.Get("r", DocX.w.NamespaceName), | |||
| new XElement | |||
| ( | |||
| XName.Get("br", DocX.w.NamespaceName), | |||
| new XAttribute(XName.Get("type", DocX.w.NamespaceName), "page") | |||
| ) | |||
| ) | |||
| ); | |||
| Xml.AddBeforeSelf(p); | |||
| } | |||
| public virtual void InsertPageBreakAfterSelf() | |||
| { | |||
| XElement p = new XElement | |||
| ( | |||
| XName.Get("p", DocX.w.NamespaceName), | |||
| new XElement | |||
| ( | |||
| XName.Get("r", DocX.w.NamespaceName), | |||
| new XElement | |||
| ( | |||
| XName.Get("br", DocX.w.NamespaceName), | |||
| new XAttribute(XName.Get("type", DocX.w.NamespaceName), "page") | |||
| ) | |||
| ) | |||
| ); | |||
| Xml.AddAfterSelf(p); | |||
| } | |||
| public virtual Paragraph InsertParagraphBeforeSelf(Paragraph p) | |||
| { | |||
| Xml.AddBeforeSelf(p.Xml); | |||
| XElement newlyInserted = Xml.ElementsBeforeSelf().First(); | |||
| p.Xml = newlyInserted; | |||
| DocX.RebuildParagraphs(Document); | |||
| return p; | |||
| } | |||
| public virtual Paragraph InsertParagraphAfterSelf(Paragraph p) | |||
| { | |||
| Xml.AddAfterSelf(p.Xml); | |||
| XElement newlyInserted = Xml.ElementsAfterSelf().First(); | |||
| p.Xml = newlyInserted; | |||
| DocX.RebuildParagraphs(Document); | |||
| return p; | |||
| } | |||
| public virtual Paragraph InsertParagraphBeforeSelf(string text) | |||
| { | |||
| return InsertParagraphBeforeSelf(text, false, new Formatting()); | |||
| } | |||
| public virtual Paragraph InsertParagraphAfterSelf(string text) | |||
| { | |||
| return InsertParagraphAfterSelf(text, false, new Formatting()); | |||
| } | |||
| public virtual Paragraph InsertParagraphBeforeSelf(string text, bool trackChanges) | |||
| { | |||
| return InsertParagraphBeforeSelf(text, trackChanges, new Formatting()); | |||
| } | |||
| public virtual Paragraph InsertParagraphAfterSelf(string text, bool trackChanges) | |||
| { | |||
| return InsertParagraphAfterSelf(text, trackChanges, new Formatting()); | |||
| } | |||
| public virtual Paragraph InsertParagraphBeforeSelf(string text, bool trackChanges, Formatting formatting) | |||
| { | |||
| XElement newParagraph = new XElement | |||
| ( | |||
| XName.Get("p", DocX.w.NamespaceName), new XElement(XName.Get("pPr", DocX.w.NamespaceName)), DocX.FormatInput(text, formatting.Xml) | |||
| ); | |||
| if (trackChanges) | |||
| newParagraph = Paragraph.CreateEdit(EditType.ins, DateTime.Now, newParagraph); | |||
| Xml.AddBeforeSelf(newParagraph); | |||
| XElement newlyInserted = Xml.ElementsBeforeSelf().First(); | |||
| Paragraph p = new Paragraph(Document, newlyInserted, -1); | |||
| DocX.RebuildParagraphs(Document); | |||
| return p; | |||
| } | |||
| public virtual Paragraph InsertParagraphAfterSelf(string text, bool trackChanges, Formatting formatting) | |||
| { | |||
| XElement newParagraph = new XElement | |||
| ( | |||
| XName.Get("p", DocX.w.NamespaceName), new XElement(XName.Get("pPr", DocX.w.NamespaceName)), DocX.FormatInput(text, formatting.Xml) | |||
| ); | |||
| if (trackChanges) | |||
| newParagraph = Paragraph.CreateEdit(EditType.ins, DateTime.Now, newParagraph); | |||
| Xml.AddAfterSelf(newParagraph); | |||
| XElement newlyInserted = Xml.ElementsAfterSelf().First(); | |||
| Paragraph p = new Paragraph(Document, newlyInserted, -1); | |||
| DocX.RebuildParagraphs(Document); | |||
| return p; | |||
| } | |||
| public virtual Table InsertTableAfterSelf(int rowCount, int coloumnCount) | |||
| { | |||
| XElement newTable = DocX.CreateTable(rowCount, coloumnCount); | |||
| Xml.AddAfterSelf(newTable); | |||
| XElement newlyInserted = Xml.ElementsAfterSelf().First(); | |||
| DocX.RebuildTables(Document); | |||
| DocX.RebuildParagraphs(Document); | |||
| return new Table(Document, newlyInserted); | |||
| } | |||
| public virtual Table InsertTableAfterSelf(Table t) | |||
| { | |||
| Xml.AddAfterSelf(t.Xml); | |||
| XElement newlyInserted = Xml.ElementsAfterSelf().First(); | |||
| t.Xml = newlyInserted; | |||
| DocX.RebuildTables(Document); | |||
| DocX.RebuildParagraphs(Document); | |||
| return t; | |||
| } | |||
| public virtual Table InsertTableBeforeSelf(int rowCount, int coloumnCount) | |||
| { | |||
| XElement newTable = DocX.CreateTable(rowCount, coloumnCount); | |||
| Xml.AddBeforeSelf(newTable); | |||
| XElement newlyInserted = Xml.ElementsBeforeSelf().First(); | |||
| DocX.RebuildTables(Document); | |||
| DocX.RebuildParagraphs(Document); | |||
| return new Table(Document, newlyInserted); | |||
| } | |||
| public virtual Table InsertTableBeforeSelf(Table t) | |||
| { | |||
| Xml.AddBeforeSelf(t.Xml); | |||
| XElement newlyInserted = Xml.ElementsBeforeSelf().First(); | |||
| t.Xml = newlyInserted; | |||
| DocX.RebuildTables(Document); | |||
| DocX.RebuildParagraphs(Document); | |||
| return t; | |||
| } | |||
| } | |||
| } | |||
| @@ -13,6 +13,12 @@ namespace Novacode | |||
| public enum Misc { none, shadow, outline, outlineShadow, emboss, engrave }; | |||
| public enum CapsStyle { none, caps, smallCaps }; | |||
| /// <summary> | |||
| /// Designs\Styles that can be applied to a table. | |||
| /// </summary> | |||
| public enum TableDesign { Custom, TableNormal, TableGrid, LightShading, LightShadingAccent1, LightShadingAccent2, LightShadingAccent3, LightShadingAccent4, LightShadingAccent5, LightShadingAccent6, LightList, LightListAccent1, LightListAccent2, LightListAccent3, LightListAccent4, LightListAccent5, LightListAccent6, LightGrid, LightGridAccent1, LightGridAccent2, LightGridAccent3, LightGridAccent4, LightGridAccent5, LightGridAccent6, MediumShading1, MediumShading1Accent1, MediumShading1Accent2, MediumShading1Accent3, MediumShading1Accent4, MediumShading1Accent5, MediumShading1Accent6, MediumShading2, MediumShading2Accent1, MediumShading2Accent2, MediumShading2Accent3, MediumShading2Accent4, MediumShading2Accent5, MediumShading2Accent6, MediumList1, MediumList1Accent1, MediumList1Accent2, MediumList1Accent3, MediumList1Accent4, MediumList1Accent5, MediumList1Accent6, MediumList2, MediumList2Accent1, MediumList2Accent2, MediumList2Accent3, MediumList2Accent4, MediumList2Accent5, MediumList2Accent6, MediumGrid1, MediumGrid1Accent1, MediumGrid1Accent2, MediumGrid1Accent3, MediumGrid1Accent4, MediumGrid1Accent5, MediumGrid1Accent6, MediumGrid2, MediumGrid2Accent1, MediumGrid2Accent2, MediumGrid2Accent3, MediumGrid2Accent4, MediumGrid2Accent5, MediumGrid2Accent6, MediumGrid3, MediumGrid3Accent1, MediumGrid3Accent2, MediumGrid3Accent3, MediumGrid3Accent4, MediumGrid3Accent5, MediumGrid3Accent6, DarkList, DarkListAccent1, DarkListAccent2, DarkListAccent3, DarkListAccent4, DarkListAccent5, DarkListAccent6, ColorfulShading, ColorfulShadingAccent1, ColorfulShadingAccent2, ColorfulShadingAccent3, ColorfulShadingAccent4, ColorfulShadingAccent5, ColorfulShadingAccent6, ColorfulList, ColorfulListAccent1, ColorfulListAccent2, ColorfulListAccent3, ColorfulListAccent4, ColorfulListAccent5, ColorfulListAccent6, ColorfulGrid, ColorfulGridAccent1, ColorfulGridAccent2, ColorfulGridAccent3, ColorfulGridAccent4, ColorfulGridAccent5, ColorfulGridAccent6, None }; | |||
| public enum AutoFit { Contents, Window, ColoumnWidth }; | |||
| public enum RectangleShapes | |||
| { | |||
| rect, | |||