NumberedList2.cs
  1. //
  2. // This code is part of Document Solutions for PDF demos.
  3. // Copyright (c) MESCIUS inc. All rights reserved.
  4. //
  5. using System;
  6. using System.IO;
  7. using System.Drawing;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Text;
  11. using GrapeCity.Documents.Pdf;
  12. using GrapeCity.Documents.Text;
  13. using GrapeCity.Documents.Drawing;
  14.  
  15. namespace DsPdfWeb.Demos.Basics
  16. {
  17. // This sample demonstrates how different styles of numbered lists
  18. // can be rendered in DsPdf.
  19. // See also NumberedList.
  20. public class NumberedList2
  21. {
  22. // Encapsulate page layout constants used in the sample:
  23. private struct Layout
  24. {
  25. // All around page margins:
  26. public static float Margin => 72;
  27. // List offset relative to item number:
  28. public static float ListOffset => 24;
  29. // List level indent:
  30. public static float ListIndent => 30;
  31. };
  32.  
  33. // Define simple tree type:
  34. private class Node
  35. {
  36. public Node(string text)
  37. {
  38. Text = text;
  39. }
  40. public string Text { get; }
  41. public List<Node> Children = new List<Node>();
  42. }
  43.  
  44. // Renders a list of nodes as a numbered list.
  45. private PointF RenderNodes(ref Page page, PointF pt, List<Node> nodes, int level)
  46. {
  47. var tlBullet = new TextLayout(72);
  48. tlBullet.DefaultFormat.Font = StandardFonts.Times;
  49. tlBullet.MarginLeft = Layout.ListIndent * level;
  50.  
  51. var tlText = new TextLayout(72);
  52. tlText.DefaultFormat.Font = StandardFonts.Times;
  53. tlText.MarginLeft = Layout.ListOffset + Layout.ListIndent * level;
  54.  
  55. for (int i = 0; i < nodes.Count; ++i)
  56. {
  57. var g = page.Graphics;
  58. // Prep item text:
  59. tlText.Clear();
  60. tlText.Append(nodes[i].Text);
  61. tlText.PerformLayout(true);
  62. if (pt.Y + tlText.ContentHeight > page.Size.Height - Layout.Margin)
  63. {
  64. page = page.Doc.NewPage();
  65. g = page.Graphics;
  66. pt.Y = Layout.Margin;
  67. }
  68. // Prep item number:
  69. tlBullet.Clear();
  70. tlBullet.Append(ItemIdxToString(i, level, tlBullet));
  71. tlBullet.PerformLayout(true);
  72. // Render item:
  73. g.DrawTextLayout(tlBullet, pt);
  74. g.DrawTextLayout(tlText, pt);
  75. // Advance insertion point:
  76. pt.Y += tlText.ContentHeight;
  77. // Render children:
  78. if (nodes[i].Children.Count > 0)
  79. pt = RenderNodes(ref page, pt, nodes[i].Children, level + 1);
  80. }
  81. return pt;
  82. }
  83.  
  84. // Convert item index to item number representation, in a
  85. // Arabic -> Latin letters -> Roman numbers loop.
  86. // Roman numbers are right-aligned, others are left-aligned.
  87. private string ItemIdxToString(int itemIdx, int level, TextLayout tl)
  88. {
  89. switch (level % 3)
  90. {
  91. case 0:
  92. tl.MarginLeft = Layout.ListIndent * level;
  93. tl.MaxWidth = null;
  94. tl.TextAlignment = TextAlignment.Leading;
  95. return $"{itemIdx + 1}.";
  96. case 1:
  97. tl.MarginLeft = Layout.ListIndent * level;
  98. tl.MaxWidth = null;
  99. tl.TextAlignment = TextAlignment.Leading;
  100. return $"{(char)('a' + itemIdx)}.";
  101. case 2:
  102. tl.MarginLeft = 0;
  103. var font = tl.DefaultFormat.Font;
  104. tl.MaxWidth = Layout.ListIndent * level + tl.DefaultFormat.FontSize;
  105. tl.TextAlignment = TextAlignment.Trailing;
  106. return $"{IntToRoman(itemIdx + 1)}.";
  107. default:
  108. throw new Exception("Unexpected.");
  109. }
  110. }
  111.  
  112. // From http://dotnet-snippets.com/snippet/roman-numerals/667
  113. private string IntToRoman(int number)
  114. {
  115. var result = new StringBuilder();
  116. int[] digitsValues = { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000 };
  117. string[] romanDigits = { "I", "IV", "V", "IX", "X", "XL", "L", "XC", "C", "CD", "D", "CM", "M" };
  118. while (number > 0)
  119. {
  120. for (int i = digitsValues.Count() - 1; i >= 0; i--)
  121. if (number / digitsValues[i] >= 1)
  122. {
  123. number -= digitsValues[i];
  124. result.Append(romanDigits[i].ToLower());
  125. break;
  126. }
  127. }
  128. return result.ToString();
  129. }
  130.  
  131. // Main entry point:
  132. public int CreatePDF(Stream stream)
  133. {
  134. var doc = new GcPdfDocument();
  135. var page = doc.NewPage();
  136. RenderNodes(ref page, new PointF(Layout.Margin, Layout.Margin), _arthrapods.Children, 0);
  137. // Done:
  138. doc.Save(stream);
  139. return doc.Pages.Count;
  140. }
  141.  
  142. // Sample tree data:
  143. private Node _arthrapods = new Node("Animalia Arthrapoda")
  144. {
  145. Children = new List<Node>()
  146. {
  147. new Node("Insecta")
  148. {
  149. Children = new List<Node>()
  150. {
  151. new Node("Archaeognatha")
  152. {
  153. Children = new List<Node>()
  154. {
  155. new Node("Protozoa")
  156. },
  157. },
  158. new Node("Thysanura")
  159. {
  160. Children = new List<Node>()
  161. {
  162. new Node("Silverfish")
  163. },
  164. },
  165. new Node("Ephemeoptera")
  166. {
  167. Children = new List<Node>()
  168. {
  169. new Node("Mafly")
  170. },
  171. },
  172. new Node("Odonata")
  173. {
  174. Children = new List<Node>()
  175. {
  176. new Node("Dragonfly"),
  177. new Node("Azure Damzelfly"),
  178. new Node("Emerald Damzelfly"),
  179. },
  180. },
  181. new Node("Orthoptera")
  182. {
  183. Children = new List<Node>()
  184. {
  185. new Node("Grasshopper"),
  186. new Node("Cricket"),
  187. new Node("Cave Cricket"),
  188. },
  189. },
  190. new Node("Phasmatodea")
  191. {
  192. Children = new List<Node>()
  193. {
  194. new Node("Walking Stick"),
  195. new Node("Leaf Bug"),
  196. },
  197. },
  198. new Node("Mantodea")
  199. {
  200. Children = new List<Node>()
  201. {
  202. new Node("Praying Mantis"),
  203. },
  204. },
  205. new Node("Blattoeda")
  206. {
  207. Children = new List<Node>()
  208. {
  209. new Node("Cockroach"),
  210. },
  211. },
  212. new Node("Isoptera")
  213. {
  214. Children = new List<Node>()
  215. {
  216. new Node("Termite"),
  217. },
  218. },
  219. new Node("Phithiraptera")
  220. {
  221. Children = new List<Node>()
  222. {
  223. new Node("Bird Lice"),
  224. new Node("Human Lice"),
  225. new Node("Pubic Lice"),
  226. },
  227. },
  228. new Node("Hemiptera")
  229. {
  230. Children = new List<Node>()
  231. {
  232. new Node("Cicada"),
  233. new Node("Pond Skater"),
  234. new Node("Tree Hopper"),
  235. new Node("Stink Bug"),
  236. new Node("Thrip"),
  237. new Node("Alderfly"),
  238. },
  239. },
  240. new Node("Siphonatera")
  241. {
  242. Children = new List<Node>()
  243. {
  244. new Node("Flea"),
  245. },
  246. },
  247. // Coleoptera etc skipped
  248. },
  249. },
  250. new Node("Myriapoda")
  251. {
  252. Children = new List<Node>()
  253. {
  254. new Node("Chilopoda")
  255. {
  256. Children = new List<Node>()
  257. {
  258. new Node("Centipede"),
  259. },
  260. },
  261. new Node("Diplopoda")
  262. {
  263. Children = new List<Node>()
  264. {
  265. new Node("Millipede"),
  266. new Node("Pitbug"),
  267. },
  268. },
  269. },
  270. },
  271. new Node("Crustacea")
  272. {
  273. Children = new List<Node>()
  274. {
  275. new Node("Branchiopod")
  276. {
  277. Children = new List<Node>()
  278. {
  279. new Node("Brine Shrimp"),
  280. new Node("Water Flea"),
  281. },
  282. },
  283. new Node("Maxillopod")
  284. {
  285. Children = new List<Node>()
  286. {
  287. new Node("Cyclopoid"),
  288. new Node("Calgid"),
  289. new Node("Barnacles"),
  290. },
  291. },
  292. new Node("Malacostracan")
  293. {
  294. Children = new List<Node>()
  295. {
  296. new Node("Krill"),
  297. new Node("Prawn"),
  298. new Node("Shrimp"),
  299. new Node("Cancrid Crab"),
  300. new Node("Fidder Crab"),
  301. new Node("Spider Crab"),
  302. new Node("Lobster"),
  303. new Node("Hermit Crab"),
  304. new Node("Cray Fish"),
  305. },
  306. },
  307. },
  308. },
  309. new Node("Pycnogonida")
  310. {
  311. Children = new List<Node>()
  312. {
  313. new Node("Pycnogonida")
  314. {
  315. Children = new List<Node>()
  316. {
  317. new Node("Sea Spider"),
  318. },
  319. },
  320. },
  321. },
  322. new Node("Merostomata")
  323. {
  324. Children = new List<Node>()
  325. {
  326. new Node("Merostomata")
  327. {
  328. Children = new List<Node>()
  329. {
  330. new Node("Horseshoe Spider"),
  331. },
  332. },
  333. },
  334. },
  335. new Node("Arachnida")
  336. {
  337. Children = new List<Node>()
  338. {
  339. new Node("Scorpiones")
  340. {
  341. Children = new List<Node>()
  342. {
  343. new Node("Buthid"),
  344. new Node("Imperial Scorpion"),
  345. },
  346. },
  347. new Node("Pseudoscorpions")
  348. {
  349. Children = new List<Node>()
  350. {
  351. new Node("Neobisiid"),
  352. new Node("Cheliferid"),
  353. },
  354. },
  355. new Node("Solfigugae")
  356. {
  357. Children = new List<Node>()
  358. {
  359. new Node("Wind Scorpion"),
  360. },
  361. },
  362. new Node("Acari")
  363. {
  364. Children = new List<Node>()
  365. {
  366. new Node("Tick"),
  367. new Node("Mite"),
  368. },
  369. },
  370. new Node("Araneae")
  371. {
  372. Children = new List<Node>()
  373. {
  374. new Node("Crib Weaver"),
  375. new Node("Funnel-web Spider"),
  376. new Node("Funnel Weaver"),
  377. new Node("Water Spider"),
  378. new Node("Jumping Spider"),
  379. new Node("Wolf Spider"),
  380. new Node("Nursery-web Spider"),
  381. new Node("Crab Spider"),
  382. new Node("Black Widow"),
  383. new Node("Tiger Oriental Tarantula"),
  384. new Node("Mexican Red-legged Tarantula"),
  385. },
  386. },
  387. },
  388. },
  389. },
  390. };
  391. }
  392. }
  393.