From cd3656c95546645cd83cd4ac3e5c7f809bdf4b32 Mon Sep 17 00:00:00 2001 From: Kathy Date: Thu, 25 Apr 2019 13:07:19 +0000 Subject: [PATCH] B2019-052: Pdf Links for each Referenced Object and Transition within a Step --- PROMS/Volian.Print.Library/Rtf2iTextSharp.cs | 145 ++++++++++++++++++- PROMS/Volian.Print.Library/vlnParagraph.cs | 77 +--------- PROMS/Volian.Print.Library/vlnPrintObject.cs | 7 +- 3 files changed, 154 insertions(+), 75 deletions(-) diff --git a/PROMS/Volian.Print.Library/Rtf2iTextSharp.cs b/PROMS/Volian.Print.Library/Rtf2iTextSharp.cs index a2771f76..73b6ac1c 100644 --- a/PROMS/Volian.Print.Library/Rtf2iTextSharp.cs +++ b/PROMS/Volian.Print.Library/Rtf2iTextSharp.cs @@ -12,6 +12,7 @@ using Itenso.Rtf.Support; using Microsoft.Win32; using Volian.Base.Library; using System.Text.RegularExpressions; +using VEPROMS.CSLA.Library; namespace Volian.Print.Library { @@ -91,6 +92,7 @@ namespace Volian.Print.Library } public class Rtf2iTextSharp : RtfVisualVisitorBase { + private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private bool _HasIndent = false; public bool HasIndent { @@ -125,7 +127,7 @@ namespace Volian.Print.Library get { return _MyDebugID; } set { _MyDebugID = value; } } - + public bool DoPdfLinks = false; // public Rtf2iTextSharp(IRtfDocument rtfDoc, Document doc, PdfWriter writer) public Rtf2iTextSharp(IRtfDocument rtfDoc) { @@ -270,6 +272,86 @@ namespace Volian.Print.Library // sb.Append(c); // return sb.ToString(); //} + // ParseLink & GetDefaultItemInfo (which used to be in vlnParagraph) support coding that was added to DoVisitText for + // doing pdflink for each transition/ro in a step, see bug B2019-052 + private RoUsageInfo _Roui = null; + private TransitionInfo _Ti = null; + private int _linkType = 0; + // for the particular link, parse its text to see the type of link and its associated data, either transitioninfo or rousageinfo: + public void ParseLink(string _LinkInfoText) + { + if (_LinkInfoText == null) return; + // First parse the string + if (_LinkInfoText.Contains(@"\v")) + throw new Exception("LinkText.ParseLink found RTF token"); + Match m = Regex.Match(_LinkInfoText, @"[#]Link:([A-Za-z]*):(.*)"); + string _MyValue = m.Groups[1].Value; + string _MyLink = "#Link:" + m.Groups[2].Value + ":" + m.Groups[3].Value; + switch (m.Groups[1].Value) + { + case "ReferencedObject": + _linkType = 1; + string[] subs = m.Groups[2].Value.Split(" ".ToCharArray()); + if (subs[0].IndexOf("CROUSGID") > -1) + _Roui = null; + else if (subs[0].IndexOf("NewID") > -1) + _Roui = null; + else + { + int roUsageid = int.Parse(subs[0]); + _Roui = RoUsageInfo.Get(roUsageid); + } + break; + case "Transition": + case "TransitionRange": + _linkType = 2; + string[] subst = m.Groups[2].Value.Split(" ".ToCharArray()); + if (subst[1].IndexOf("CTID") > -1) + _Ti = null; + else if (subst[1].IndexOf("NewID") > -1) + _Ti = null; + else + { + int transitionID = int.Parse(m.Groups[2].Value.Split(" ".ToCharArray())[1]); + _Ti = TransitionInfo.Get(transitionID); + } + break; + } + } + // GetDefaultItemInfo finds the item that a transition goes to. If it goes to procedure, go to default section's (or procedure + // steps section if no default) first step (or go to default section if there are not steps). Also, go to step if there are + // steps, else go to section. And last, if none of these can be found, just go to the item passed in. + private ItemInfo GetDefaultItemInfo(ItemInfo myItemInfo) + { + if (myItemInfo.IsProcedure && myItemInfo.Sections != null) + { + SectionInfo siProcedureSteps = null; + foreach (SectionInfo si in myItemInfo.Sections) + { + if (si.IsDefaultSection) + { + if (si.Steps != null) return si.Steps[0]; + if (si.Sections != null) return si.Sections[0]; + return si; + } + if (si.DisplayText.Contains("Procedure Step")) + siProcedureSteps = si; + } + if (siProcedureSteps != null) + { + if (siProcedureSteps.Steps != null) return siProcedureSteps.Steps[0]; + if (siProcedureSteps.Sections != null) return siProcedureSteps.Sections[0]; + return siProcedureSteps; + } + } + if (myItemInfo.IsSection) + { + if (myItemInfo.Steps != null) return myItemInfo.Steps[0]; + if (myItemInfo.Sections != null) return myItemInfo.Sections[0]; + } + return myItemInfo; + } + private static int chkStart = -1; protected override void DoVisitText(IRtfVisualText visualText) { //Code to find text (non-symbol) being output with a symbol font @@ -283,6 +365,67 @@ namespace Volian.Print.Library int profileDepth = ProfileTimer.Push(">>>> DoVisitText"); if (visualText.Format.IsHidden) { + // B2019-052: Hidden text contains the link text - so if doing the pdf links when printing, this can be used to determine how + // to create the link. A given link may have multiple chunks though, if there are attribute changes, symbols, etc. This + // code goes through all of the chunks of a link and sets attributes on each chunk so that the link goes to the correct + // place (RO or Transition 'to'). Note that the pdf links were originally done in vlnparagraph.cs but only went to a single + // link within a step. The code was moved here so that each ro and transition link within a step could have its on pdf link. + if (DoPdfLinks) + { + // use the start and end tokens in the link text, these may span more than one chunk. + if (visualText.Text.Contains("")) + { + string txt = visualText.Text; + ParseLink(txt); // get the link data, ro or transition + for (int i = chkStart; i < _MyParagraph.Chunks.Count; i++) + { + try + { + Chunk chk = _MyParagraph.Chunks[i] as Chunk; + if (chk != null) + { + if (_linkType == 2 && _Ti != null) // transition + { + ItemInfo tiDefault = GetDefaultItemInfo(_Ti.MyItemToID); + ItemInfo from = _Ti.MyContent.ContentItems[0]; + if (_Ti.MyItemToID.MyProcedure.ItemID == from.MyProcedure.ItemID && + !from.ActiveSection.DisplayNumber.ToUpper().StartsWith("FOLDOUT")) + { // Local Go To + if (_Ti.MyItemToID.MyContent.Type > 9999) // internal to this file + { + chk.SetLocalGoto(string.Format("ItemID={0}", tiDefault.ItemID)); + chk.SetBackground(Color.CYAN); + chk.SetBackground(new Color(System.Drawing.Color.LightCyan)); + } + } + else if (_Ti != null) // Remote Go To + { + chk.SetRemoteGoto(_Ti.MyItemToID.MyProcedure.DisplayNumber.Replace("/", "_") + ".pdf", string.Format("ItemID={0}", tiDefault.ItemID)); + chk.SetBackground(new Color(System.Drawing.Color.PeachPuff)); + } + } + else if (_linkType == 1 && _Roui != null) // referenced object + { + if (_Roui.ROID.Substring(0, 4) != "FFFF") + { + chk.SetRemoteGoto("completeroreport.pdf", string.Format("ROID={0}", _Roui.ROID.Substring(0, 12).ToUpper())); + chk.SetBackground(new Color(System.Drawing.Color.LightGreen)); + } + } + } + } + catch (Exception ex) + { + _MyLog.ErrorFormat("Error creating pdf links {0}", ex.Message); + } + } + _Ti = null; + _Roui = null; + _linkType = 0; + chkStart = -1; + } + } ProfileTimer.Pop(profileDepth); _lastWasLineBreak = 0; // B2017-191 reset hard return count return; diff --git a/PROMS/Volian.Print.Library/vlnParagraph.cs b/PROMS/Volian.Print.Library/vlnParagraph.cs index 02d0ba7c..6cd2bdb4 100644 --- a/PROMS/Volian.Print.Library/vlnParagraph.cs +++ b/PROMS/Volian.Print.Library/vlnParagraph.cs @@ -1061,47 +1061,12 @@ namespace Volian.Print.Library if (MyItemInfo.MyContent.Text.ToUpper().Contains("LINK:TR") && MyItemInfo.MyContent.ContentTransitionCount==0) Console.WriteLine("Missing Transition {0}", MyItemInfo.ItemID); chk1.SetLocalDestination(string.Format("ItemID={0}", MyItemInfo.ItemID)); // Destination - if (MyItemInfo.MyContent.ContentTransitionCount > 0) - { - TransitionInfo ti = MyItemInfo.MyContent.ContentTransitions[0]; - ItemInfo tiDefault = GetDefaultItemInfo(ti.MyItemToID); - if (ti.MyItemToID.MyProcedure.ItemID == MyItemInfo.MyProcedure.ItemID && - !MyItemInfo.ActiveSection.DisplayNumber.ToUpper().StartsWith("FOLDOUT")) - { // Local Go To - if (ti.MyItemToID.MyContent.Type > 9999) // B2019-053: internal if going to a section, not just a step (changed from 19999 to 9999 - // B2018-034 The following code previously used IParagraph rather than _IParagraph. See first Comment - foreach (Chunk chk in _IParagraph.Chunks) - { - //Console.WriteLine("\"LocalGoTo\"\t{0}", tiDefault.ItemID); - chk.SetLocalGoto(string.Format("ItemID={0}", tiDefault.ItemID)); - chk.SetBackground(Color.CYAN); - chk.SetBackground(new Color(System.Drawing.Color.LightCyan)); - } - } - else // Remote Go To - { - foreach (Chunk chk in IParagraph.Chunks) - { - //Console.WriteLine("\"RemoteGoTo\"\t{0}", tiDefault.ItemID); - chk.SetRemoteGoto(ti.MyItemToID.MyProcedure.DisplayNumber.Replace("/", "_") + ".pdf", string.Format("ItemID={0}", tiDefault.ItemID)); - chk.SetBackground(new Color(System.Drawing.Color.PeachPuff)); - } - } - } - if (MyItemInfo.MyContent.ContentRoUsageCount > 0) - { - RoUsageInfo ru = MyItemInfo.MyContent.ContentRoUsages[0]; - // B2018-034 The following code previously used IParagraph rather than _IParagraph. See first Comment - foreach (Chunk chk in _IParagraph.Chunks) - { - if (ru.ROID.Substring(0, 4) != "FFFF") - { - chk.SetRemoteGoto("completeroreport.pdf", string.Format("ROID={0}", ru.ROID.Substring(0, 12).ToUpper())); - //Console.WriteLine("ROID={0},{1}", ru.ROID.Substring(0, 12).ToUpper(), chk.Content); - chk.SetBackground(new Color(System.Drawing.Color.LightGreen)); - } - } - } + // B2019-052: If multiple ROs/Transitions within a step, each should have a their own link rather than all linking to same thing. + // Note the pdf link code that was here was moved to Rtf2iTextSharp.cs in DoVisitText so that each 'chunk' could have a link. + // The code that remained here was the code that marks the destination for each step & the code that does the pdf links for + // enhanced steps. + // Also, the method GetDefaultItemInfo was moved to Rtf2iTextSharp.cs also - it was only called from code that was moved. + StepConfig sc = new StepConfig(MyItemInfo.MyContent.Config); DVEnhancedDocuments dveds = MyItemInfo.MyDocVersion.DocVersionConfig.MyEnhancedDocuments; foreach (EnhancedDocument ed in sc.MyEnhancedDocuments) @@ -1163,36 +1128,6 @@ namespace Volian.Print.Library // chk.SetBackground(new Color(System.Drawing.Color.LemonChiffon)); //} } - private ItemInfo GetDefaultItemInfo(ItemInfo myItemInfo) - { - if (myItemInfo.IsProcedure && myItemInfo.Sections != null) - { - SectionInfo siProcedureSteps = null; - foreach (SectionInfo si in myItemInfo.Sections) - { - if (si.IsDefaultSection) - { - if (si.Steps != null) return si.Steps[0]; - if (si.Sections != null) return si.Sections[0]; - return si; - } - if (si.DisplayText.Contains("Procedure Step")) - siProcedureSteps = si; - } - if (siProcedureSteps != null) - { - if (siProcedureSteps.Steps != null) return siProcedureSteps.Steps[0]; - if (siProcedureSteps.Sections != null) return siProcedureSteps.Sections[0]; - return siProcedureSteps; - } - } - if (myItemInfo.IsSection) - { - if (myItemInfo.Steps != null) return myItemInfo.Steps[0]; - if (myItemInfo.Sections != null) return myItemInfo.Sections[0]; - } - return myItemInfo; - } private static bool _MissingInitials = false; public static bool MissingInitials diff --git a/PROMS/Volian.Print.Library/vlnPrintObject.cs b/PROMS/Volian.Print.Library/vlnPrintObject.cs index 4e2c275b..703e13a3 100644 --- a/PROMS/Volian.Print.Library/vlnPrintObject.cs +++ b/PROMS/Volian.Print.Library/vlnPrintObject.cs @@ -130,7 +130,7 @@ namespace Volian.Print.Library // B2018-034 Attributes were being lost when the IsCompressed flag was true. // CopyAttributesToNewIParagraph retains any attribute which have been set Paragraph oldParagraph = _IParagraph; - _IParagraph = RtfToParagraph(myRtf, HasIndent); + _IParagraph = RtfToParagraph(myRtf, HasIndent, MyPageHelper.MyPromsPrinter.SaveLinks); // B2018-034 Attributes were being lost when the IsCompressed flag was true. // CopyAttributesToNewIParagraph retains any attribute which have been set CopyAttributesToNewIParagraph(oldParagraph, _IParagraph); @@ -433,9 +433,9 @@ namespace Volian.Print.Library } public static iTextSharp.text.Paragraph RtfToParagraph(string rtf) { - return RtfToParagraph(rtf, false); + return RtfToParagraph(rtf, false, false); } - public static iTextSharp.text.Paragraph RtfToParagraph(string rtf, bool hasIndent) + public static iTextSharp.text.Paragraph RtfToParagraph(string rtf, bool hasIndent, bool doPdfLinks) { if (hasIndent) { @@ -446,6 +446,7 @@ namespace Volian.Print.Library IRtfDocument rtfDoc = RtfInterpreterTool.BuildDoc(rtf); Rtf2iTextSharp rtf2IText = new Rtf2iTextSharp(rtfDoc); + rtf2IText.DoPdfLinks = doPdfLinks; rtf2IText.HasIndent = hasIndent; iTextSharp.text.Paragraph para = rtf2IText.Convert(); para.SetLeading(_SixLinesPerInch, 0);