PreparedPage.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. using FastReport.Engine;
  2. using FastReport.Utils;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Drawing;
  6. using System.IO;
  7. using System.Windows.Forms;
  8. namespace FastReport.Preview
  9. {
  10. internal class PreparedPage : IDisposable
  11. {
  12. #region Fields
  13. private XmlItem xmlItem;
  14. private PreparedPages preparedPages;
  15. private SizeF pageSize;
  16. private long tempFilePosition;
  17. private bool uploaded;
  18. private PreparedPagePosprocessor posprocessor;
  19. #endregion Fields
  20. #region Properties
  21. private Report Report
  22. {
  23. get { return preparedPages.Report; }
  24. }
  25. private bool UseFileCache
  26. {
  27. get { return Report.UseFileCache; }
  28. }
  29. public XmlItem Xml
  30. {
  31. get { return xmlItem; }
  32. set
  33. {
  34. xmlItem = value;
  35. value.Parent = null;
  36. }
  37. }
  38. public SizeF PageSize
  39. {
  40. get
  41. {
  42. if (pageSize.IsEmpty)
  43. {
  44. ReCalcSizes();
  45. }
  46. return pageSize;
  47. }
  48. set
  49. {
  50. pageSize = value;
  51. }
  52. }
  53. public int CurPosition
  54. {
  55. get { return xmlItem.Count; }
  56. }
  57. #endregion Properties
  58. #region Private Methods
  59. private bool DoAdd(Base c, XmlItem item)
  60. {
  61. if (c == null)
  62. return false;
  63. ReportEngine engine = Report.Engine;
  64. bool isRunning = Report.IsRunning && engine != null;
  65. if (c is ReportComponentBase)
  66. {
  67. if (isRunning && !engine.CanPrint(c as ReportComponentBase))
  68. return false;
  69. }
  70. item = item.Add();
  71. using (FRWriter writer = new FRWriter(item))
  72. {
  73. writer.SerializeTo = SerializeTo.Preview;
  74. writer.SaveChildren = false;
  75. writer.BlobStore = preparedPages.BlobStore;
  76. writer.Write(c);
  77. }
  78. if (isRunning)
  79. engine.AddObjectToProcess(c, item);
  80. if ((c.Flags & Flags.CanWriteChildren) == 0)
  81. {
  82. ObjectCollection childObjects = c.ChildObjects;
  83. foreach (Base obj in childObjects)
  84. {
  85. DoAdd(obj, item);
  86. }
  87. }
  88. return true;
  89. }
  90. private Base ReadObject(Base parent, XmlItem item, bool readChildren, FRReader reader)
  91. {
  92. string objName = item.Name;
  93. // try to find the object in the dictionary
  94. Base obj = preparedPages.Dictionary.GetObject(objName);
  95. // object not found, objName is type name
  96. if (obj == null)
  97. {
  98. Type type = RegisteredObjects.FindType(objName);
  99. if (type == null)
  100. return null;
  101. obj = Activator.CreateInstance(type) as Base;
  102. }
  103. obj.SetRunning(true);
  104. // read object's properties
  105. if (!item.IsNullOrEmptyProps())
  106. {
  107. // since the BlobStore is shared resource, lock it to avoid problems with multi-thread access.
  108. // this may happen in the html export that uses several threads to export one report.
  109. lock (reader.BlobStore)
  110. {
  111. reader.Read(obj, item);
  112. }
  113. }
  114. if (readChildren)
  115. {
  116. for (int i = 0; i < item.Count; i++)
  117. {
  118. ReadObject(obj, item[i], true, reader);
  119. }
  120. }
  121. obj.Parent = parent;
  122. return obj;
  123. }
  124. private void UpdateUnlimitedPage(Base obj, XmlItem item)
  125. {
  126. item.Clear();
  127. using (FRWriter writer = new FRWriter(item))
  128. {
  129. writer.SerializeTo = SerializeTo.Preview;
  130. writer.SaveChildren = false;
  131. writer.BlobStore = preparedPages.BlobStore;
  132. writer.Write(obj);
  133. }
  134. foreach (Base child in obj.ChildObjects)
  135. {
  136. UpdateUnlimitedPage(child, item.Add());
  137. }
  138. }
  139. #endregion Private Methods
  140. #region Internal Methods
  141. internal ReportPage ReadPage(Base parent, XmlItem item, bool readchild, FRReader reader)
  142. {
  143. ReportPage page = ReadObject(parent, item, false, reader) as ReportPage;
  144. if (readchild)
  145. for (int i = 0; i < item.Count; i++)
  146. {
  147. ReadObject(page, item[i], true, reader);
  148. }
  149. return page;
  150. }
  151. internal ReportPage StartGetPage(int index)
  152. {
  153. Load();
  154. ReportPage page;
  155. using (FRReader reader = new FRReader(null))
  156. {
  157. reader.DeserializeFrom = SerializeTo.Preview;
  158. reader.ReadChildren = false;
  159. reader.BlobStore = preparedPages.BlobStore;
  160. page = ReadPage(null, xmlItem, false, reader);
  161. if (!(page.UnlimitedHeight || page.UnlimitedWidth))
  162. {
  163. page.Dispose();
  164. page = ReadPage(null, xmlItem, true, reader);
  165. page.SetReport(preparedPages.Report);
  166. posprocessor = new PreparedPagePosprocessor();
  167. posprocessor.Postprocess(page);
  168. posprocessor = null;
  169. }
  170. else
  171. {
  172. page.SetReport(preparedPages.Report);
  173. posprocessor = new PreparedPagePosprocessor();
  174. posprocessor.PostprocessUnlimited(this, page);
  175. }
  176. }
  177. if (page.MirrorMargins && (index + 1) % 2 == 0)
  178. {
  179. float f = page.LeftMargin;
  180. page.LeftMargin = page.RightMargin;
  181. page.RightMargin = f;
  182. }
  183. return page;
  184. }
  185. internal void EndGetPage(ReportPage page)
  186. {
  187. if (posprocessor != null) posprocessor = null;
  188. if (page != null)
  189. page.Dispose();
  190. ClearUploadedXml();
  191. }
  192. internal IEnumerable<Base> GetPageItems(ReportPage page, bool postprocess)
  193. {
  194. if (!(page.UnlimitedHeight || page.UnlimitedWidth))
  195. {
  196. foreach (Base child in page.ChildObjects)
  197. {
  198. if (postprocess) yield return child;
  199. else
  200. using (child)
  201. yield return child;
  202. }
  203. }
  204. else
  205. {
  206. if (Export.ExportBase.HAVE_TO_WORK_WITH_OVERLAY)
  207. #pragma warning disable CS0162 // Unreachable code detected
  208. foreach (Base child in page.ChildObjects)
  209. #pragma warning restore CS0162 // Unreachable code detected
  210. {
  211. if (child is OverlayBand)
  212. yield return child;
  213. }
  214. using (FRReader reader = new FRReader(null))
  215. {
  216. reader.DeserializeFrom = SerializeTo.Preview;
  217. reader.ReadChildren = false;
  218. reader.BlobStore = preparedPages.BlobStore;
  219. for (int i = 0; i < xmlItem.Count; i++)
  220. {
  221. if (postprocess) yield return ReadObject(page, xmlItem[i], true, reader);
  222. else
  223. using (Base obj = ReadObject(page, xmlItem[i], true, reader))
  224. {
  225. using (Base obj2 = posprocessor.PostProcessBandUnlimitedPage(obj))
  226. yield return obj2;
  227. }
  228. }
  229. }
  230. }
  231. }
  232. internal string GetName()
  233. {
  234. using (FRReader reader = new FRReader(null))
  235. {
  236. reader.DeserializeFrom = SerializeTo.Preview;
  237. reader.ReadChildren = false;
  238. reader.BlobStore = preparedPages.BlobStore;
  239. ReportPage page = ReadObject(null, xmlItem, false, reader) as ReportPage;
  240. return page.Name;
  241. }
  242. }
  243. internal void ReCalcSizes()
  244. {
  245. XmlItem item = xmlItem;
  246. using (FRReader reader = new FRReader(null, item))
  247. {
  248. reader.DeserializeFrom = SerializeTo.Preview;
  249. reader.BlobStore = preparedPages.BlobStore;
  250. reader.ReadChildren = false;
  251. using (ReportPage page = ReadPage(Report, item, false, reader))
  252. {
  253. if (page.UnlimitedHeight | page.UnlimitedWidth)
  254. {
  255. float maxWidth = 0.0f;
  256. float maxHeight = 0.0f;
  257. for (int i = 0; i < item.Count; i++)
  258. {
  259. using (Base obj = ReadObject(page, item[i], true, reader))
  260. {
  261. if (obj is BandBase)
  262. {
  263. BandBase band = obj as BandBase;
  264. float bandsHeight = band.Top + band.Height;
  265. if (maxHeight < bandsHeight)
  266. maxHeight = bandsHeight;
  267. float bandWidth = 0.0f;
  268. foreach (ComponentBase comp in band.Objects)
  269. {
  270. if ((comp.Anchor & AnchorStyles.Right) == 0 && comp.Dock == DockStyle.None)
  271. {
  272. bandWidth = Math.Max(bandWidth, comp.Left + comp.Width);
  273. }
  274. }
  275. if (maxWidth < bandWidth)
  276. maxWidth = bandWidth;
  277. }
  278. }
  279. }
  280. if (page.UnlimitedHeight)
  281. page.UnlimitedHeightValue = maxHeight + (page.TopMargin + page.BottomMargin) * Units.Millimeters;
  282. if (page.UnlimitedWidth)
  283. page.UnlimitedWidthValue = maxWidth + (page.LeftMargin + page.RightMargin) * Units.Millimeters;
  284. }
  285. pageSize = new SizeF(page.WidthInPixels, page.HeightInPixels);
  286. using (FRWriter writer = new FRWriter(item))
  287. {
  288. writer.SerializeTo = SerializeTo.Preview;
  289. writer.SaveChildren = false;
  290. writer.BlobStore = preparedPages.BlobStore;
  291. writer.Write(page);
  292. }
  293. }
  294. }
  295. }
  296. #endregion Internal Methods
  297. #region Public Methods
  298. public PreparedPage(ReportPage page, PreparedPages preparedPages)
  299. {
  300. this.preparedPages = preparedPages;
  301. xmlItem = new XmlItem();
  302. // page == null when we load prepared report from a file
  303. if (page != null)
  304. {
  305. using (FRWriter writer = new FRWriter(xmlItem))
  306. {
  307. writer.SerializeTo = SerializeTo.Preview;
  308. writer.SaveChildren = false;
  309. writer.Write(page);
  310. }
  311. pageSize = new SizeF(page.WidthInPixels, page.HeightInPixels);
  312. }
  313. }
  314. public bool AddBand(BandBase band)
  315. {
  316. return DoAdd(band, xmlItem);
  317. }
  318. public ReportPage GetPage()
  319. {
  320. Load();
  321. ReportPage page;
  322. using (FRReader reader = new FRReader(null))
  323. {
  324. reader.DeserializeFrom = SerializeTo.Preview;
  325. reader.ReadChildren = false;
  326. reader.BlobStore = preparedPages.BlobStore;
  327. page = ReadPage(null, xmlItem, true, reader);
  328. }
  329. page.SetReport(preparedPages.Report);
  330. new PreparedPagePosprocessor().Postprocess(page);
  331. ClearUploadedXml();
  332. return page;
  333. }
  334. public void Load()
  335. {
  336. if (UseFileCache && uploaded)
  337. {
  338. preparedPages.TempFile.Position = tempFilePosition;
  339. XmlReader reader = new XmlReader(preparedPages.TempFile);
  340. reader.Read(xmlItem);
  341. }
  342. }
  343. public void ClearUploadedXml()
  344. {
  345. if (UseFileCache && uploaded)
  346. xmlItem.Clear();
  347. }
  348. public void Upload()
  349. {
  350. if (UseFileCache && !uploaded)
  351. {
  352. preparedPages.TempFile.Seek(0, SeekOrigin.End);
  353. tempFilePosition = preparedPages.TempFile.Position;
  354. XmlWriter writer = new XmlWriter(preparedPages.TempFile);
  355. writer.Write(xmlItem);
  356. xmlItem.Clear();
  357. uploaded = true;
  358. }
  359. }
  360. public XmlItem CutObjects(int index)
  361. {
  362. XmlItem result = new XmlItem();
  363. while (xmlItem.Count > index)
  364. {
  365. result.AddItem(xmlItem[index]);
  366. }
  367. return result;
  368. }
  369. public void PasteObjects(XmlItem objects, float deltaX, float deltaY)
  370. {
  371. if (objects.Count > 0)
  372. {
  373. while (objects.Count > 0)
  374. {
  375. XmlItem obj = objects[0];
  376. // shift the object's location
  377. float objX = (obj.GetProp("l") != "") ?
  378. Converter.StringToFloat(obj.GetProp("l")) : 0;
  379. float objY = (obj.GetProp("t") != "") ?
  380. Converter.StringToFloat(obj.GetProp("t")) : 0;
  381. obj.SetProp("l", Converter.ToString(objX + deltaX));
  382. obj.SetProp("t", Converter.ToString(objY + deltaY));
  383. // add object to a page
  384. xmlItem.AddItem(obj);
  385. }
  386. }
  387. }
  388. public float GetLastY()
  389. {
  390. float result = 0;
  391. for (int i = 0; i < xmlItem.Count; i++)
  392. {
  393. XmlItem xi = xmlItem[i];
  394. BandBase obj = preparedPages.Dictionary.GetOriginalObject(xi.Name) as BandBase;
  395. if (obj != null && !(obj is PageFooterBand) && !(obj is OverlayBand))
  396. {
  397. string s = xi.GetProp("t");
  398. float top = (s != "") ? Converter.StringToFloat(s) : obj.Top;
  399. s = xi.GetProp("h");
  400. float height = (s != "") ? Converter.StringToFloat(s) : obj.Height;
  401. if (top + height > result)
  402. result = top + height;
  403. }
  404. }
  405. return result;
  406. }
  407. public bool ContainsBand(Type bandType)
  408. {
  409. for (int i = 0; i < xmlItem.Count; i++)
  410. {
  411. XmlItem xi = xmlItem[i];
  412. BandBase obj = preparedPages.Dictionary.GetOriginalObject(xi.Name) as BandBase;
  413. if (obj != null && obj.GetType() == bandType)
  414. return true;
  415. }
  416. return false;
  417. }
  418. public bool ContainsBand(string bandName)
  419. {
  420. for (int i = 0; i < xmlItem.Count; i++)
  421. {
  422. XmlItem xi = xmlItem[i];
  423. BandBase obj = preparedPages.Dictionary.GetOriginalObject(xi.Name) as BandBase;
  424. if (obj != null && obj.Name == bandName)
  425. return true;
  426. }
  427. return false;
  428. }
  429. public void Dispose()
  430. {
  431. xmlItem.Dispose();
  432. }
  433. #endregion Public Methods
  434. }
  435. }