PageRenderTime 33ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/AODL/Document/Content/Tables/Row.cs

https://bitbucket.org/chrisc/aodl
C# | 434 lines | 205 code | 48 blank | 181 comment | 26 complexity | e8b62cc85d28270cb107eb75b6d9930c MD5 | raw file
  1. /*************************************************************************
  2. *
  3. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
  4. *
  5. * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
  6. *
  7. * Use is subject to license terms.
  8. *
  9. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  10. * use this file except in compliance with the License. You may obtain a copy
  11. * of the License at http://www.apache.org/licenses/LICENSE-2.0. You can also
  12. * obtain a copy of the License at http://odftoolkit.org/docs/license.txt
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  16. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. *
  18. * See the License for the specific language governing permissions and
  19. * limitations under the License.
  20. *
  21. ************************************************************************/
  22. using System.Collections.Generic;
  23. using System.Linq;
  24. using System.Xml.Linq;
  25. using AODL.Document.SpreadsheetDocuments;
  26. using AODL.Document.Styles;
  27. using AODL.Document.TextDocuments;
  28. namespace AODL.Document.Content.Tables
  29. {
  30. /// <summary>
  31. /// Row represent a row within a table. If the row is part of a table which is
  32. /// used in a text document, then Cell merging is possible.
  33. /// </summary>
  34. public class Row : IContent, IHtml
  35. {
  36. #region Delegates
  37. /// <summary>
  38. /// RowChanged delegate
  39. /// </summary>
  40. public delegate void RowChanged(int rowNumber, int cellCount);
  41. #endregion
  42. private CellCollection _cells;
  43. /// <summary>
  44. /// Initializes a new instance of the <see cref="Row"/> class.
  45. /// </summary>
  46. /// <param name="document">The document.</param>
  47. /// <param name="node">The node.</param>
  48. public Row(IDocument document, XElement node)
  49. {
  50. Document = document;
  51. Node = node;
  52. InitStandards();
  53. }
  54. /// <summary>
  55. /// Initializes a new instance of the <see cref="Row"/> class.
  56. /// </summary>
  57. /// <param name="table">The table.</param>
  58. public Row(Table table)
  59. {
  60. Table = table;
  61. Document = table.Document;
  62. Node = new XElement(Ns.Table + "table-row");
  63. InitStandards();
  64. }
  65. /// <summary>
  66. /// Initializes a new instance of the <see cref="Row"/> class.
  67. /// </summary>
  68. /// <param name="table">The table.</param>
  69. /// <param name="styleName">Name of the style.</param>
  70. public Row(Table table, string styleName)
  71. {
  72. Table = table;
  73. Document = table.Document;
  74. Node = new XElement(Ns.Table + "table-row");
  75. Node.SetAttributeValue(Ns.Table + "style-name", styleName);
  76. RowStyle = Document.StyleFactory.Request<RowStyle>(styleName);
  77. InitStandards();
  78. }
  79. /// <summary>
  80. /// Gets or sets the node.
  81. /// </summary>
  82. /// <value>The node.</value>
  83. public Table Table { get; set; }
  84. /// <summary>
  85. /// Gets or sets the row style.
  86. /// </summary>
  87. /// <value>The row style.</value>
  88. public RowStyle RowStyle
  89. {
  90. get { return (RowStyle) Style; }
  91. set
  92. {
  93. StyleName = value.StyleName;
  94. Style = value;
  95. }
  96. }
  97. /// <summary>
  98. /// Gets or sets the cell collection.
  99. /// </summary>
  100. /// <value>The cell collection.</value>
  101. public CellCollection Cells
  102. {
  103. get { return _cells; }
  104. set { _cells = value; }
  105. }
  106. /// <summary>
  107. /// Gets or sets the cell collection.
  108. /// </summary>
  109. /// <value>The cell collection.</value>
  110. public CellSpanCollection CellSpanCollection { get; set; }
  111. /// <summary>
  112. /// Inits the standards.
  113. /// </summary>
  114. private void InitStandards()
  115. {
  116. Cells = new CellCollection();
  117. Cells.Removed += CellCollection_Removed;
  118. Cells.Inserted += CellCollection_Inserted;
  119. CellSpanCollection = new CellSpanCollection();
  120. CellSpanCollection.Inserted += CellSpanCollection_Inserted;
  121. CellSpanCollection.Removed += CellSpanCollection_Removed;
  122. }
  123. /// <summary>
  124. /// Inserts the cell at the given zero based position.
  125. /// </summary>
  126. /// <param name="position">The position.</param>
  127. /// <param name="cell">The cell.</param>
  128. public void InsertCellAt(int position, Cell cell)
  129. {
  130. // Phil Jollans 16-Feb-2008: Largely rewritten
  131. if (_cells.Count > position)
  132. {
  133. // We need to ask Lars how he intended this list to work.
  134. // Note that Table.Row_OnRowChanged() adds cells to all rows when
  135. // we add a cell to a single row.
  136. _cells.RemoveAt(position);
  137. _cells.Insert(position, cell);
  138. }
  139. else
  140. {
  141. while (_cells.Count < position)
  142. {
  143. _cells.Add(new Cell(Table.Document));
  144. }
  145. _cells.Add(cell);
  146. }
  147. }
  148. /// <summary>
  149. /// Merge cells. This is only possible if the rows table is part
  150. /// of a text document.
  151. /// </summary>
  152. /// <param name="document">The TextDocument this row belongs to.</param>
  153. /// <param name="cellStartIndex">Start index of the cell.</param>
  154. /// <param name="mergeCells">The count of cells to merge incl. the starting cell.</param>
  155. /// <param name="mergeContent">if set to <c>true</c> [merge content].</param>
  156. public void MergeCells(TextDocument document, int cellStartIndex, int mergeCells, bool mergeContent)
  157. {
  158. Cells[cellStartIndex].ColumnRepeating = mergeCells.ToString();
  159. if (mergeContent)
  160. {
  161. for (int i = cellStartIndex + 1; i < cellStartIndex + mergeCells; i++)
  162. {
  163. foreach (IContent content in Cells[i].Content)
  164. Cells[cellStartIndex].Content.Add(content);
  165. }
  166. }
  167. for (int i = cellStartIndex + mergeCells - 1; i > cellStartIndex; i--)
  168. {
  169. Cells.RemoveAt(i);
  170. CellSpanCollection.Add(new CellSpan(this, Document));
  171. }
  172. }
  173. /// <summary>
  174. /// Gets the index of the cell.
  175. /// </summary>
  176. /// <param name="cell">The cell.</param>
  177. /// <returns>The index of the cell wthin the cell collection. If the
  178. /// cell isn't part of the collection -1 will be returned.</returns>
  179. public int GetCellIndex(Cell cell)
  180. {
  181. if (cell != null && Cells != null)
  182. {
  183. for (int i = 0; i < Cells.Count; i++)
  184. if (Cells[i].Equals(cell))
  185. return i;
  186. }
  187. return -1;
  188. }
  189. /// <summary>
  190. /// Cells the collection_ removed.
  191. /// </summary>
  192. /// <param name="index">The index.</param>
  193. /// <param name="value">The value.</param>
  194. private static void CellCollection_Removed(int index, object value)
  195. {
  196. ((Cell) value).Node.Remove();
  197. }
  198. /// <summary>
  199. /// Cells the collection_ inserted.
  200. /// </summary>
  201. /// <param name="index">The index.</param>
  202. /// <param name="value">The value.</param>
  203. private void CellCollection_Inserted(int index, object value)
  204. {
  205. //Only Spreadsheet documents are automaticaly resized
  206. //not needed if the file is loaded (right order!);
  207. if (Document is SpreadsheetDocument
  208. && !Document.IsLoadedFile)
  209. {
  210. if (Node.Elements().Count() == index)
  211. Node.Add(((Cell) value).Node);
  212. else
  213. {
  214. List<XElement> elements = new List<XElement>(Node.Elements());
  215. elements.Insert(index + 1, ((Cell) value).Node);
  216. Node.ReplaceNodes(elements);
  217. }
  218. Row_OnRowChanged(GetRowIndex(), Cells.Count);
  219. }
  220. else
  221. Node.Add(((Cell) value).Node);
  222. }
  223. /// <summary>
  224. /// Cells the span collection_ inserted.
  225. /// </summary>
  226. /// <param name="index">The index.</param>
  227. /// <param name="value">The value.</param>
  228. private void CellSpanCollection_Inserted(int index, object value)
  229. {
  230. Node.Add(((CellSpan) value).Node);
  231. }
  232. /// <summary>
  233. /// Cells the span collection_ removed.
  234. /// </summary>
  235. /// <param name="index">The index.</param>
  236. /// <param name="value">The value.</param>
  237. private static void CellSpanCollection_Removed(int index, object value)
  238. {
  239. ((CellSpan) value).Node.Remove();
  240. }
  241. /// <summary>
  242. /// Gets the index of the row.
  243. /// </summary>
  244. /// <returns>The index within the table rowcollection of this row.</returns>
  245. private int GetRowIndex()
  246. {
  247. for (int i = 0; i < Table.Rows.Count; i++)
  248. {
  249. if (Table.Rows[i] == this)
  250. return i;
  251. }
  252. //Maybe this row isn't already added.
  253. //e.g. this is a new row which will be added
  254. //to the end of the collection
  255. // TODO - there is no "Maybe" :) Throw exception if not found
  256. return Table.Rows.Count;
  257. }
  258. #region IContent Member
  259. private IStyle _style;
  260. /// <summary>
  261. /// Gets or sets the node.
  262. /// </summary>
  263. /// <value>The node.</value>
  264. public XElement Node { get; set; }
  265. /// <summary>
  266. /// Gets or sets the name of the style.
  267. /// </summary>
  268. /// <value>The name of the style.</value>
  269. public string StyleName
  270. {
  271. get { return (string) Node.Attribute(Ns.Table + "style-name"); }
  272. set { Node.SetAttributeValue(Ns.Table + "style-name", value); }
  273. }
  274. /// <summary>
  275. /// Every object (typeof(IContent)) have to know his document.
  276. /// </summary>
  277. /// <value></value>
  278. public IDocument Document { get; set; }
  279. /// <summary>
  280. /// A Style class wich is referenced with the content object.
  281. /// If no style is available this is null.
  282. /// </summary>
  283. /// <value></value>
  284. public IStyle Style
  285. {
  286. get { return _style; }
  287. set
  288. {
  289. StyleName = value.StyleName;
  290. _style = value;
  291. }
  292. }
  293. /// <summary>
  294. /// Gets or sets the node.
  295. /// </summary>
  296. /// <value>The node.</value>
  297. XNode IContent.Node
  298. {
  299. get { return Node; }
  300. set { Node = (XElement) value; }
  301. }
  302. #endregion
  303. #region IHtml Member
  304. /// <summary>
  305. /// Return the content as Html string
  306. /// </summary>
  307. /// <returns>The html string</returns>
  308. public string GetHtml()
  309. {
  310. string html = "<tr ";
  311. if (((RowStyle) Style).RowProperties != null)
  312. html += ((RowStyle) Style).RowProperties.GetHtmlStyle();
  313. html += ">\n";
  314. foreach (Cell cell in Cells)
  315. if (cell is IHtml)
  316. html += cell.GetHtml() + "\n";
  317. html += "</tr>";
  318. return html;
  319. }
  320. #endregion
  321. #region Eventhandling
  322. /// <summary>
  323. /// After a row size changed all rows before the changed row
  324. /// maybe need to be resized. This also belongs to the columns.
  325. /// </summary>
  326. /// <param name="rowNumber">The row number.</param>
  327. /// <param name="cellCount">The cell count.</param>
  328. private void Row_OnRowChanged(int rowNumber, int cellCount)
  329. {
  330. if (Table.ColumnCollection.Count <= cellCount)
  331. {
  332. for (int i = 0; i <= cellCount - Table.ColumnCollection.Count; i++)
  333. {
  334. Table.ColumnCollection.Add(new Column(Table, string.Format("col{0}", Table.ColumnCollection.Count)));
  335. }
  336. }
  337. for (int i = 0; i < rowNumber; i++)
  338. {
  339. Row row = Table.Rows[i];
  340. if (row.Cells.Count >= cellCount)
  341. continue;
  342. for (int ii = 0; ii < cellCount - row.Cells.Count; ii++)
  343. //for(int ii = cellCount - row.Cells.Count; ii < cellCount; ii++)
  344. {
  345. row.Cells.Add(new Cell(Table.Document));
  346. }
  347. }
  348. }
  349. #endregion
  350. }
  351. }
  352. /*
  353. * $Log: Row.cs,v $
  354. * Revision 1.4 2008/04/29 15:39:46 mt
  355. * new copyright header
  356. *
  357. * Revision 1.3 2008/04/10 17:33:15 larsbehr
  358. * - Added several bug fixes mainly for the table handling which are submitted by Phil Jollans
  359. *
  360. * Revision 1.2 2007/04/08 16:51:23 larsbehr
  361. * - finished master pages and styles for text documents
  362. * - several bug fixes
  363. *
  364. * Revision 1.1 2007/02/25 08:58:36 larsbehr
  365. * initial checkin, import from Sourceforge.net to OpenOffice.org
  366. *
  367. * Revision 1.3 2006/02/16 18:35:41 larsbm
  368. * - Add FrameBuilder class
  369. * - TextSequence implementation (Todo loading!)
  370. * - Free draing postioning via x and y coordinates
  371. * - Graphic will give access to it's full qualified path
  372. * via the GraphicRealPath property
  373. * - Fixed Bug with CellSpan in Spreadsheetdocuments
  374. * - Fixed bug graphic of loaded files won't be deleted if they
  375. * are removed from the content.
  376. * - Break-Before property for Paragraph properties for Page Break
  377. *
  378. * Revision 1.2 2006/01/29 18:52:14 larsbm
  379. * - Added support for common styles (style templates in OpenOffice)
  380. * - Draw TextBox import and export
  381. * - DrawTextBox html export
  382. *
  383. * Revision 1.1 2006/01/29 11:28:22 larsbm
  384. * - Changes for the new version. 1.2. see next changelog for details
  385. *
  386. */