diff --git a/PROMS/VEPROMS.CSLA.Library/Extension/ItemExt.cs b/PROMS/VEPROMS.CSLA.Library/Extension/ItemExt.cs index 7fee2f86..34146cea 100644 --- a/PROMS/VEPROMS.CSLA.Library/Extension/ItemExt.cs +++ b/PROMS/VEPROMS.CSLA.Library/Extension/ItemExt.cs @@ -297,6 +297,25 @@ namespace VEPROMS.CSLA.Library // return ii._ItemID == _ItemID; // return false; //} + private int _PrintBias = 0; + public int PrintBias + { + get { return _PrintBias; } + set { _PrintBias = value; } + } + private int _PrintLevel = 0; + public int PrintLevel + { + get + { + if (_PrintLevel != 0) return _PrintLevel; + int _PrintBias = 0; + _PrintLevel = GetStepLevel(ref _PrintBias); + + return _PrintLevel; + } + set { _PrintLevel = value; } + } private float _MSWordPageCount = 0; public float MSWordPageCount { @@ -2030,31 +2049,40 @@ namespace VEPROMS.CSLA.Library _MyTab.CleanText = ""; return; } + + // account for metasection indenting/tabbing in the 'PrintLevel', i.e. if we have metasection, we may be in + // a subsection. Index into the seqtabs array has to account for metasection level. + int localPrintLevel = PrintLevel; + StepSectionData sd = ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData; + if (sd.StepSectionLayoutData.TieTabToLevel && ActiveFormat.PlantFormat.FormatData.SectData.UseMetaSections) + { + if (sd.StepSectionLayoutData.ShowSectionTitles + && !MyDocStyle.CancelSectTitle + && !(MyDocStyle.SpecialStepsFoldout && MyDocStyle.UseColSByLevel)) + localPrintLevel = PrintLevel + CurrentSectionLevel(); + } // Start with basic cases of alpha/numeric/seq: if (tbformat.IndexOf("{seq}") > -1) { - int bias = 0; - int level = GetStepLevel(ref bias); SeqTabFmtList seqtabs = ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.SeqTabFmtList; - int itmp = (level + bias) % seqtabs.Count; + int itmp = (localPrintLevel + PrintBias) % seqtabs.Count; tbformat = seqtabs[itmp].PrintTabFormat; // seqtab in 16bit, i.e. '. or )' etc. - string tbtoken = seqtabs[level % seqtabs.Count].TabToken; // seqstart in 16bit, number/letter - + string tbtoken = seqtabs[localPrintLevel % seqtabs.Count].TabToken; // seqstart in 16bit, number/letter tbformat = tbformat.Replace("{seq}", tbtoken); - - // If token includes 'Wpar', the parent tab prefix's the tab. - if (level > 0 && (tbformat.IndexOf("{numericWpar}") > -1 || tbformat.IndexOf("{alphaWpar}") > -1 || tbformat.IndexOf("{ALPHAWpar}") > -1)) - { - string parentTab = ((ItemInfo)(ActiveParent)).MyTab.CleanText.Trim(); - tbformat = parentTab + (parentTab.EndsWith(".") ? "" : ".") + tbformat.TrimStart(); - } - if (tbformat.IndexOf("#2#") > -1 || tbformat.IndexOf("#1#") > -1) - { - string ofst = tbformat.Substring(0, 3); - _MyTab.Offset = Convert.ToInt32(ofst.Substring(1, 1)); - cltext = tbformat.Replace("#2#", ""); - cltext = cltext.Replace("#1#", ""); - } + } + + // If token includes 'Wpar', the parent tab prefix's the tab. + if (localPrintLevel > 0 && (tbformat.IndexOf("{numericWpar}") > -1 || tbformat.IndexOf("{alphaWpar}") > -1 || tbformat.IndexOf("{ALPHAWpar}") > -1)) + { + string parentTab = ((ItemInfo)(ActiveParent)).MyTab.CleanText.Trim(); + tbformat = parentTab + (parentTab.EndsWith(".") ? "" : ".") + tbformat.TrimStart(); + } + if (tbformat.IndexOf("#2#") > -1 || tbformat.IndexOf("#1#") > -1) + { + string ofst = tbformat.Substring(0, 3); + _MyTab.Offset = Convert.ToInt32(ofst.Substring(1, 1)); + cltext = tbformat.Replace("#2#", ""); + cltext = cltext.Replace("#1#", ""); } // if this is a caution/note type determine where 'NOTE/CAUTION' tab goes, as tab or as 'header' // and also determine whether the tab itself gets converted to a bullet. @@ -2144,12 +2172,12 @@ namespace VEPROMS.CSLA.Library return (tbformat.Substring(stindx, tbformat.IndexOf("}")-stindx+1)); } - private int GetStepLevel(ref int bias) + public int GetStepLevel(ref int bias) { int level = 0; ItemInfo par = this; ItemInfo LastRNO = null; - while (!par.IsHigh) + while (par != null && !par.IsSection && !par.IsProcedure && !par.IsHigh) { if (par.IsRNOPart) LastRNO = par.MyParent; if (!par.IsRNOPart && (par.IsSequential || (!(par.IsCaution || par.IsNote) @@ -2192,15 +2220,52 @@ namespace VEPROMS.CSLA.Library } return level; } - + public int CurrentSectionLevel() + { + int countlev = 0; + if ((MyActiveSection.MyDocStyle.StructureStyle.Style ?? 0 & E_DocStructStyle.DSS_TreatAsTrueSectNum) != 0) + { + ItemInfo ii = ActiveSection.MyParent; + while (!ii.IsProcedure) + { + // the following line must also include a check for the section config autoindent flag + if (ii.DisplayNumber != null && ii.DisplayNumber != "") countlev++; + ii = ii.MyParent; + } + } + return countlev; + } private string SectionPrefix(string tbformat) { - // 16 bit has code that handles various levels of sections with a flag called TieTabToLevel. This - // code will need to be added at some point. For now, handle the basic case of just getting the - // section tab up to and including the '.'. - int indxs = ActiveSection.MyTab.CleanText.IndexOf("."); - // if the '.' is found, include it in the tab: - return indxs > 0 ? ActiveSection.MyTab.CleanText.Substring(0, indxs + 1) : ActiveSection.MyTab.CleanText.Trim(); + // If the Section's 'tab' is a character or has a character preceding the '.' is an alpha character, + // just return the alpha (no '.') + // If the character preceding the '. 'is a number, return the section tab up to and including the '.' + // Otherwise, just return the section tab. + + // Before checking for anything, if the DisplayNumber starts with 'ATTACHMENT ', don't use that in the Section + // prefix for the tabstring. + string attNum = ActiveSection.DisplayNumber.ToUpper().StartsWith("ATTACHMENT ") ? ActiveSection.DisplayNumber.Substring(11) : ActiveSection.DisplayNumber; + Match m = Regex.Match(attNum, @"[a-zA-Z]"); // for alpha, use non-touched displaynumber + int indx = -1; + if (m.Success) + { + indx = attNum.IndexOf("."); + if (indx < 0) return attNum; + return attNum.Substring(0, indx); + } + if (IsHigh && ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.TieTabToLevel) + { + int subsection = CurrentSectionLevel(); + if (subsection >= 1) + { + string tmptab = ActiveSection.MyTab.CleanText.TrimEnd(); + if (tmptab.LastIndexOf(".") != tmptab.Length - 1) tmptab = tmptab + "."; + return tmptab; + } + } + indx = ActiveSection.MyTab.CleanText.IndexOf("."); + if (indx > 0) return ActiveSection.MyTab.CleanText.Substring(0,indx+1); // include the '.' + return ActiveSection.MyTab.CleanText.TrimEnd(); } private string CheckNoteCautionTab(string tbformat) @@ -2395,6 +2460,95 @@ namespace VEPROMS.CSLA.Library if (tmp.Count > 0) _MyMacros = tmp; } #endregion + #region CheckOffs + private string _SectionCheckOffHeader; + public string SectionCheckOffHeader + { + get + { + if (_SectionCheckOffHeader == null) + { + // first check if format has checkoff data, including checkoffheaders. + ProcData pd = ActiveFormat.PlantFormat.FormatData.ProcData; + if (pd.CheckOffData == null || pd.CheckOffData.CheckOffHeaderList == null || pd.CheckOffData.CheckOffHeaderList.Count <= 1) _SectionCheckOffHeader = string.Empty; + else + { + SectionConfig sc = ActiveSection.MyConfig as SectionConfig; + if (sc == null) _SectionCheckOffHeader = string.Empty; + else if (sc.Section_CheckoffHeaderSelection <= 0) _SectionCheckOffHeader = string.Empty; + else + { + _SectionCheckOffHeader = pd.CheckOffData.CheckOffHeaderList[sc.Section_CheckoffHeaderSelection].CheckOffHeading; + if (_SectionCheckOffHeader.Contains("{NO HEADING}")) _SectionCheckOffHeader = string.Empty; + } + } + } + return _SectionCheckOffHeader; + } + } + public bool SectionHasCheckOffs() + { + // To determine if the section has a checkoff... + // Section won't have checkoffs if there is no checkofflist, or + ProcData pd = ActiveFormat.PlantFormat.FormatData.ProcData; + if (pd.CheckOffData == null || pd.CheckOffData.CheckOffList == null || pd.CheckOffData.CheckOffList.Count <= 0) return false; + if (pd.CheckOffData.CheckOffHeaderList == null || pd.CheckOffData.CheckOffHeaderList.Count <= 1) return true; + //if (pd.CheckOffData == null || pd.CheckOffData.CheckOffHeaderList == null || pd.CheckOffData.CheckOffHeaderList.Count <= 1) return false; + + // To find whether the step has a checkoff, first check that the section + // has a check off header. If it doesn't, just return -1. + // if config item is set for checkoffindex, use it. If it == 0, then use + // the section default. + SectionConfig sc = ActiveSection.MyConfig as SectionConfig; + if (sc == null) return false; + if (sc.Section_CheckoffHeaderSelection <= 0) return false; + return true; + } + private int CheckOffIndex() + { + StepConfig stc = MyConfig as StepConfig; + if (stc == null) return 0; //section default. + if (stc != null && stc.Step_CheckOffIndex == 1) return -1; // index of 1, always means 'No Checkoff' + return stc.Step_CheckOffIndex; + } + private int SectionDefaultCheckOffIndex() + { + ProcData pd = ActiveFormat.PlantFormat.FormatData.ProcData; + SectionConfig sc = ActiveSection.MyConfig as SectionConfig; + if (pd.CheckOffData != null && pd.CheckOffData.CheckOffList != null && pd.CheckOffData.CheckOffList.Count == 2) return 0; // if only two items, first is macro - use it. + return sc.Section_CheckoffListSelection; + } + public CheckOff GetCheckOffStep() + { + if (!IsStep || !SectionHasCheckOffs()) return null; + int stpCoIndx = CheckOffIndex(); // this step has a checkoff defined + if (stpCoIndx == -1) return null; + if (stpCoIndx > 1) return ActiveFormat.PlantFormat.FormatData.ProcData.CheckOffData.CheckOffList[stpCoIndx]; + int sectCoIndx = SectionDefaultCheckOffIndex(); // no checkoff on step, see if there is a section default. + if (sectCoIndx == -1) return null; + if ((ActiveFormat.PlantFormat.FormatData.ProcData.CheckOffData.CheckOffOnHLSOnly && IsHigh) + || (!ActiveFormat.PlantFormat.FormatData.ProcData.CheckOffData.CheckOffOnHLSOnly && IsLowestLevelStep() && !RNOsHighHasCheckOff())) + return ActiveFormat.PlantFormat.FormatData.ProcData.CheckOffData.CheckOffList[sectCoIndx]; + return null; + } + private bool IsLowestLevelStep() + { + // This test only checks if using the section default, otherwise the code above, uses what the checkoff + // that is set in the config. + StepConfig stc = MyConfig as StepConfig; + if (stc != null && stc.Step_CheckOffIndex == 0) + { + if (!(IsCaution || IsNote || IsTable || Steps != null || MyParent.IsCaution || MyParent.IsNote)) return true; + } + return false; + } + private bool RNOsHighHasCheckOff() + { + // If this is a High Level Step's RNO, the checkoff would be placed on the HLS, not the RNO. + if (IsRNOPart && MyParent.IsHigh && MyParent.CheckOffIndex() != -1) return true; + return false; + } + #endregion #region JCB Item Status private bool _IsItemNew = false; public bool IsItemNew @@ -3174,6 +3328,23 @@ namespace VEPROMS.CSLA.Library } return (-1); } + public bool TrueSectionNum() + { + int indx = DisplayNumber.IndexOf("."); + if (indx < 0 || indx + 1 == DisplayNumber.Length) return false; + // for it to be a 'TrueSectionNum', there can be no letters after the '.' + for (int lindx = indx; lindx < DisplayNumber.Length - 1; lindx++) if (DisplayNumber[lindx] < '0' || DisplayNumber[lindx] > '9') return false; + return true; + } + // the following returns the 'index' into the format's CheckOffHeaderList. + // It returns a -1 if not set or none exist. + public int CheckOffHeadingIndex() + { + if (ActiveFormat.PlantFormat.FormatData.ProcData.CheckOffData.CheckOffHeaderList == null || ActiveFormat.PlantFormat.FormatData.ProcData.CheckOffData.CheckOffHeaderList.Count == 0) return -1; + SectionConfig sc = MyConfig as SectionConfig; + if (sc == null) return -1; + return sc.Section_CheckoffHeaderSelection; + } protected override void RefreshFields(Item tmp) { base.RefreshFields(tmp); @@ -3216,6 +3387,7 @@ namespace VEPROMS.CSLA.Library { return (Section)(_Editable = Section.Get(ItemID)); } + #region SectionConfig [NonSerialized] private SectionConfig _SectionConfig;