using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Text.RegularExpressions; using System.Windows.Forms; using System.Runtime.InteropServices; // For DragHelper using System.Reflection; using Csla; using Csla.Validation; using VEPROMS.CSLA.Library; using System.IO; using Volian.Base.Library; using DevComponents.DotNetBar; using JR.Utils.GUI.Forms; //C2018-026 show notes entered during approval or workflow stage namespace Volian.Controls.Library { #region DelegatesAndEventArgs public delegate void vlnTreeViewEvent(object sender, vlnTreeEventArgs args); public delegate void vlnTreeViewTimeEvent(object sender, vlnTreeTimeEventArgs args); public delegate void vlnTreeViewStatusEvent(object sender, vlnTreeStatusEventArgs args); public delegate ItemInfo vlnTreeViewClipboardStatusEvent(object sender, vlnTreeEventArgs args); public delegate void vlnTreeViewItemInfoEvent(object sender, vlnTreeItemInfoEventArgs args); public delegate bool vlnTreeViewBoolEvent(object sender, vlnTreeEventArgs args); public delegate bool vlnTreeViewItemInfoDeleteEvent(object sender, vlnTreeItemInfoEventArgs args); public delegate bool vlnTreeViewItemInfoInsertEvent(object sender, vlnTreeItemInfoInsertEventArgs args); public delegate bool vlnTreeViewItemInfoDeleteFolderEvent(object sender, vlnTreeFolderDeleteEventArgs args); public delegate bool vlnTreeViewItemInfoPasteEvent(object sender, vlnTreeItemInfoPasteEventArgs args); public delegate TreeNode vlnTreeViewTreeNodeEvent(object sender, vlnTreeEventArgs args); public delegate DialogResult vlnTreeViewPropertyEvent(object sender, vlnTreePropertyEventArgs args); public delegate DialogResult vlnTreeViewPSIEvent(object sender, vlnTreeEventArgs args); public delegate DialogResult vlnTreeViewSIEvent(object sender, vlnTreeEventArgs args); public delegate void vlnTreeViewSectionInfoEvent(object sender, vlnTreeSectionInfoEventArgs args); public delegate void WordSectionDeletedEvent(object sender, WordSectionEventArgs args); public delegate void vlnTreeViewPdfEvent(object sender, vlnTreeViewPdfArgs args); public delegate string vlnTreeViewGetChangeIdEvent(object sender, vlnTreeItemInfoEventArgs args); public delegate ItemInfo vlnTreeViewSearchIncTransEvent(object sender, vlnTreeItemInfoEventArgs args); public partial class vlnTreeSectionInfoEventArgs { private bool _IsDeleting = false; public bool IsDeleting { get { return _IsDeleting; } set { _IsDeleting = value; } } private SectionInfo _MySectionInfo; public SectionInfo MySectionInfo { get { return _MySectionInfo; } set { _MySectionInfo = value; } } public vlnTreeSectionInfoEventArgs(SectionInfo mySectionInfo) { _MySectionInfo = mySectionInfo; } public vlnTreeSectionInfoEventArgs(SectionInfo mySectionInfo,bool isDeleting) { _MySectionInfo = mySectionInfo; _IsDeleting = isDeleting; } } public partial class vlnTreeViewPdfArgs { private string _MyFilename; public string MyFilename { get { return _MyFilename; } set { _MyFilename = value; } } private byte[] _MyBuffer; public byte[] MyBuffer { get { return _MyBuffer; } set { _MyBuffer = value; } } private string _MyWatermark; public string MyWatermark { get { return _MyWatermark; } set { _MyWatermark = value; } } public vlnTreeViewPdfArgs(string filename, byte[] buffer, string watermark) { _MyFilename = filename; _MyBuffer = buffer; _MyWatermark = watermark; } } public partial class vlnTreeTimeEventArgs { private TimeSpan _myTimeSpan; public TimeSpan MyTimeSpan { get { return _myTimeSpan; } set { _myTimeSpan = value; } } private string _MyMessage; public string MyMessage { get { return _MyMessage; } set { _MyMessage = value; } } public vlnTreeTimeEventArgs(DateTime dtStart, string message) { MyTimeSpan = TimeSpan.FromTicks(DateTime.Now.Ticks - dtStart.Ticks); MyMessage = message; } } public partial class vlnTreeStatusEventArgs { private bool _MyStatus; public bool MyStatus { get { return _MyStatus; } set { _MyStatus = value; } } private string _MyMessage; public string MyMessage { get { return _MyMessage; } set { _MyMessage = value; } } public vlnTreeStatusEventArgs(bool status, string message) { MyStatus = status; MyMessage = message; } } public partial class vlnTreeEventArgs { #region Business Methods private TreeNode _Node; public TreeNode Node { get { return _Node; } set { _Node = value; } } private TreeNode _Destination=null; public TreeNode Destination { get { return _Destination; } set { _Destination = value; } } private int _Index; public int Index { get { return _Index; } set { _Index = value; } } //jcb multiunit private string _Unit; public string Unit { get { return _Unit; } set { _Unit = value; } } private int _UnitIndex = -1; public int UnitIndex { get { return _UnitIndex; } set { _UnitIndex = value; } } //end jcb multiunit #endregion #region Factory Methods private vlnTreeEventArgs() { ;} public vlnTreeEventArgs(TreeNode node) { _Node = node; } public vlnTreeEventArgs(TreeNode node, TreeNode destination, int index) { _Node = node; _Destination = destination; _Index = index; } //jcb multiunit public vlnTreeEventArgs(TreeNode node, TreeNode destination, int index, string unit, int unitIndex) { _Node = node; _Destination = destination; _Index = index; _Unit = unit; _UnitIndex = unitIndex; } //end jcb multiunit #endregion public override string ToString() { return string.Format("Node={0},Destination={1},Index={2},Unit={3},UnitIndex={4}",NodePath(this.Node),this.Destination, this.Index,this.Unit, this.UnitIndex); } private string NodePath(TreeNode node) { string retval = ""; if (node.Parent != null) retval = NodePath(node.Parent) + ":"; retval += node.Text; return retval; } } public partial class vlnTreeItemInfoEventArgs { #region Business Methods private ItemInfo _MyItemInfo; public ItemInfo MyItemInfo { get { return _MyItemInfo; } set { _MyItemInfo = value; } } #endregion #region Factory Methods private vlnTreeItemInfoEventArgs() { ;} public vlnTreeItemInfoEventArgs(ItemInfo myItemInfo) { _MyItemInfo = myItemInfo; } #endregion } public class vlnTreeFolderDeleteEventArgs : EventArgs { public int FolderId { get; } public vlnTreeFolderDeleteEventArgs(int folderId) { FolderId = folderId; } } public enum E_InsertType {Before, After, Child}; public partial class vlnTreeItemInfoInsertEventArgs { #region Business Methods private ItemInfo _MyItemInfo; public ItemInfo MyItemInfo { get { return _MyItemInfo; } set { _MyItemInfo = value; } } private E_InsertType _InsertType; public E_InsertType InsertType { get { return _InsertType; } set { _InsertType = value; } } private int _Type; public int Type { get { return _Type; } set { _Type = value; } } private E_FromType _FromType; public E_FromType FromType { get { return _FromType; } set { _FromType = value; } } private string _StepText; public string StepText { get { return _StepText; } set { _StepText = value; } } #endregion #region Factory Methods private vlnTreeItemInfoInsertEventArgs() { ;} public vlnTreeItemInfoInsertEventArgs(ItemInfo myItemInfo, E_InsertType insertType, string stepText) { _MyItemInfo = myItemInfo; _InsertType = insertType; _StepText = stepText; } public vlnTreeItemInfoInsertEventArgs(ItemInfo myItemInfo, E_InsertType insertType, string stepText, int type, E_FromType fromType) { _MyItemInfo = myItemInfo; _InsertType = insertType; _StepText = stepText; _Type = type; _FromType = fromType; } #endregion } #region PasteEventArgs public partial class vlnTreeItemInfoPasteEventArgs { #region Business Methods private ItemInfo _MyItemInfo; public ItemInfo MyItemInfo { get { return _MyItemInfo; } set { _MyItemInfo = value; } } private int _CopyStartID; public int CopyStartID { get { return _CopyStartID; } set { _CopyStartID = value; } } private ItemInfo.EAddpingPart _PasteType; public ItemInfo.EAddpingPart PasteType { get { return _PasteType; } set { _PasteType = value; } } private int? _Type; public int? Type { get { return _Type; } set { _Type = value; } } #endregion #region Factory Methods private vlnTreeItemInfoPasteEventArgs() { ;} public vlnTreeItemInfoPasteEventArgs(ItemInfo myItemInfo, int copyStartId, ItemInfo.EAddpingPart pasteType, int? type) { _MyItemInfo = myItemInfo; _CopyStartID = copyStartId; _PasteType = pasteType; _Type = type; } #endregion } #endregion public partial class vlnTreePropertyEventArgs : EventArgs { private string _Title; public string Title { get { return _Title; } set { _Title = value; } } private object _ConfigObject; public object ConfigObject { get { return _ConfigObject; } set { _ConfigObject = value; } } private FolderConfig _FolderConfig; public FolderConfig FolderConfig { get { return _FolderConfig; } set { _ConfigObject = _FolderConfig = value; } } private DocVersionConfig _DocVersionConfig; public DocVersionConfig DocVersionConfig { get { return _DocVersionConfig; } set { _ConfigObject = _DocVersionConfig = value; } } private ProcedureConfig _ProcedureConfig; public ProcedureConfig ProcedureConfig { get { return _ProcedureConfig; } set { _ConfigObject = _ProcedureConfig = value; } } private SectionConfig _SectionConfig; public SectionConfig SectionConfig { get { return _SectionConfig; } set { _ConfigObject = _SectionConfig = value; } } private vlnTreePropertyEventArgs() { ;} public vlnTreePropertyEventArgs(string title, FolderConfig folderConfig) { _Title = title; FolderConfig = folderConfig; } public vlnTreePropertyEventArgs(string title, DocVersionConfig docVersionConfig) { _Title = title; DocVersionConfig = docVersionConfig; } public vlnTreePropertyEventArgs(string title, ProcedureConfig procedureConfig) { _Title = title; ProcedureConfig = procedureConfig; } public vlnTreePropertyEventArgs(string title, SectionConfig sectionConfig) { _Title = title; DocStyleListConverter.MySection = sectionConfig.MySection; SectionConfig = sectionConfig; } } #endregion public partial class vlnTreeView : TreeView { private ProcedureInfo _currentPri = null; // used to get child name to append to approved export filename -AddApprovedRevisionsMultiUnit() & ImportProcedure_Click() private SessionInfo _MySessionInfo; public SessionInfo MySessionInfo { get { return _MySessionInfo; } set { _MySessionInfo = value; } } private UserInfo _MyUserInfo; public UserInfo MyUserInfo { get { return _MyUserInfo; } set { _MyUserInfo = value; } } private string _DelProcReason; // C2020-038: request reason for delete procedure so this can be saved in database public string DelProcReason { get { return _DelProcReason; } set { _DelProcReason = value; } } #region Local Vars private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); FolderInfo _LastFolderInfo = null; ProcedureInfo _LastProcedureInfo = null; DocVersionInfo _LastDocVersionInfo = null; SectionInfo _LastSectionInfo = null; VETreeNode _LastTreeNode = null; StepInfo _LastStepInfo = null; ItemInfo _LastItemInfo = null; #endregion #region Events public event vlnTreeViewGetChangeIdEvent GetChangeId; private string OnGetChangeId(object sender, vlnTreeItemInfoEventArgs args) { if (GetChangeId != null) return GetChangeId(sender, args); return null; } public event vlnTreeViewPdfEvent ViewPDF; private void OnViewPDF(object sender, vlnTreeViewPdfArgs args) { if (ViewPDF != null) ViewPDF(sender, args); } public event vlnTreeViewItemInfoDeleteEvent DeleteItemInfo; private bool OnDeleteItemInfo(object sender, vlnTreeItemInfoEventArgs args) { if (DeleteItemInfo != null) return DeleteItemInfo(sender, args); return false; } public event vlnTreeViewItemInfoDeleteFolderEvent DeleteFolder; private bool OnDeleteFolder(object sender, vlnTreeFolderDeleteEventArgs args) { if (DeleteItemInfo != null) return DeleteFolder(sender, args); return false; } public event vlnTreeViewItemInfoInsertEvent InsertItemInfo; private bool OnInsertItemInfo(object sender, vlnTreeItemInfoInsertEventArgs args) { if (InsertItemInfo != null) return InsertItemInfo(sender, args); return false; } public event vlnTreeViewItemInfoPasteEvent PasteItemInfo; private bool OnPasteItemInfo(object sender, vlnTreeItemInfoPasteEventArgs args) { if (PasteItemInfo != null) return PasteItemInfo(sender, args); return false; } public event vlnTreeViewEvent NodeMove; private void OnNodeMove(object sender, vlnTreeEventArgs args) { if (NodeMove != null) NodeMove(sender, args); } public event vlnTreeViewClipboardStatusEvent ClipboardStatus; private ItemInfo OnClipboardStatus(object sender, vlnTreeEventArgs args) { ItemInfo rv = null; if (ClipboardStatus != null) rv = ClipboardStatus(sender, args); return rv; } public event vlnTreeViewEvent NodeCopy; private void OnNodeCopy(object sender, vlnTreeEventArgs args) { if (NodeCopy != null) NodeCopy(sender, args); } public event vlnTreeViewPropertyEvent NodeOpenProperty; private DialogResult OnNodeOpenProperty(object sender, vlnTreePropertyEventArgs args) { if (NodeOpenProperty != null) return NodeOpenProperty(sender, args); return DialogResult.Cancel; } public event vlnTreeViewPSIEvent NodePSI; private DialogResult OnNodePSI(object sender, vlnTreeEventArgs args) { if (NodePSI != null) return NodePSI(sender, args); return DialogResult.Cancel; } // C2020-033: Support the menu item to bring up Search/Incoming Transitions panel public event vlnTreeViewSearchIncTransEvent SearchIncTrans; private ItemInfo OnSearchIncTransIn(object sender, vlnTreeItemInfoEventArgs args) { if (SearchIncTrans != null) return SearchIncTrans(sender, args); return args.MyItemInfo; } public event vlnTreeViewSIEvent NodeSI; private DialogResult OnNodeSI(object sender, vlnTreeEventArgs args) { if (NodeSI != null) return NodeSI(sender, args); return DialogResult.Cancel; } public event vlnTreeViewEvent NodeSelect; private void OnNodeSelect(object sender, vlnTreeEventArgs args) { if (NodeSelect != null) NodeSelect(sender, args); } public event vlnTreeViewEvent CreateContinuousActionSummary; private void OnCreateContinuousActionSummary(object sender, vlnTreeEventArgs args) { if (CreateContinuousActionSummary != null) CreateContinuousActionSummary(sender, args); } public event vlnTreeViewEvent CreateTimeCriticalActionSummary; private void OnCreateTimeCriticalActionSummary(object sender, vlnTreeEventArgs args) { if (CreateTimeCriticalActionSummary != null) CreateTimeCriticalActionSummary(sender, args); } public event vlnTreeViewEvent PrintProcedure; private void OnPrintProcedure(object sender, vlnTreeEventArgs args) { if (PrintProcedure != null) PrintProcedure(sender, args); } public event vlnTreeViewEvent QPrintProcedure; private void OnQPrintProcedure(object sender, vlnTreeEventArgs args) { if (QPrintProcedure != null) QPrintProcedure(sender, args); } public event vlnTreeViewEvent PrintSection; private void OnPrintSection(object sender, vlnTreeEventArgs args) { if (PrintSection != null) PrintSection(sender, args); } public event vlnTreeViewEvent PrintAllProcedures; private void OnPrintAllProcedures(object sender, vlnTreeEventArgs args) { if (PrintAllProcedures != null) PrintAllProcedures(sender, args); } public event vlnTreeViewEvent SelectDateToStartChangeBars; private void OnSelectDateToStartChangeBars(object sender, vlnTreeEventArgs args) { if (SelectDateToStartChangeBars != null) SelectDateToStartChangeBars(sender, args); } public event vlnTreeViewEvent ApproveProcedure; private void OnApproveProcedure(object sender, vlnTreeEventArgs args) { if (ApproveProcedure != null) ApproveProcedure(sender, args); } public event vlnTreeViewEvent ApproveAllProcedures; private void OnApproveAllProcedures(object sender, vlnTreeEventArgs args) { if (ApproveAllProcedures != null) ApproveAllProcedures(sender, args); } public event vlnTreeViewEvent ApproveSomeProcedures; private void OnApproveSomeProcedures(object sender, vlnTreeEventArgs args) { if (ApproveSomeProcedures != null) ApproveSomeProcedures(sender, args); } public event vlnTreeViewEvent ReportAllProceduresInconsistencies; private void OnReportAllProceduresInconsistencies(object sender, vlnTreeEventArgs args) { if (ReportAllProceduresInconsistencies != null) ReportAllProceduresInconsistencies(sender, args); } public event vlnTreeViewEvent RefreshCheckedOutProcedures; private void OnRefreshCheckedOutProcedures(object sender, vlnTreeEventArgs args) { if (RefreshCheckedOutProcedures != null) RefreshCheckedOutProcedures(sender, args); } public event vlnTreeViewEvent ProcedureCheckedOutTo; private void OnProcedureCheckedOutTo(object sender, vlnTreeEventArgs args) { if (ProcedureCheckedOutTo != null) ProcedureCheckedOutTo(sender, args); } public event vlnTreeViewEvent ExportImportProcedureSets; private void OnExportImportProcedureSets(object sender, vlnTreeEventArgs args) { if (ExportImportProcedureSets != null) ExportImportProcedureSets(sender, args); } public event vlnTreeViewEvent PrintTransitionReport; private void OnPrintTransitionReport(object sender, vlnTreeEventArgs args) { if (PrintTransitionReport != null) PrintTransitionReport(sender, args); } public event vlnTreeViewEvent NodeNew; private void OnNodeNew(object sender, vlnTreeEventArgs args) { if (NodeNew != null) NodeNew(sender, args); } /// /// Raised after a new step is added. /// public event vlnTreeViewEvent NodeInsert; private void OnNodeInsert(object sender, vlnTreeEventArgs args) { if (NodeInsert != null) NodeInsert(sender, args); } public event vlnTreeViewEvent NodeSelectionChange; private void OnNodeSelectionChange(object sender, vlnTreeEventArgs args) { if (NodeSelectionChange != null) NodeSelectionChange(sender, args); } public event vlnTreeViewSectionInfoEvent SectionShouldClose; private void OnSectionShouldClose(object sender, vlnTreeSectionInfoEventArgs args) { if (SectionShouldClose != null) SectionShouldClose(sender, args); } public event vlnTreeViewSectionInfoEvent PauseRefresh; private void OnPauseRefresh(object sender, vlnTreeSectionInfoEventArgs args) { if (PauseRefresh != null) PauseRefresh(sender, args); } public event vlnTreeViewSectionInfoEvent UnPauseRefresh; private void OnUnPauseRefresh(object sender, vlnTreeSectionInfoEventArgs args) { if (UnPauseRefresh != null) UnPauseRefresh(sender, args); } public event WordSectionDeletedEvent WordSectionDeleted; internal void OnWordSectionDeleted(object sender, WordSectionEventArgs args) { WordSectionDeleted(sender, args); } public event vlnTreeViewItemInfoEvent OpenItem; private void OnOpenItem(object sender, vlnTreeItemInfoEventArgs args) { if (OpenItem != null) OpenItem(sender, args); } // This event was added to update the Step Properties/RO & Tools/Search RO & Reports // when an update of ro.fst is done & the ro trees on those panels needs refreshed. // (bug fix B2015-226) public event StepPanelTabDisplayEvent TabDisplay; private void OnTabDisplay(object sender, StepPanelTabDisplayEventArgs args) { if (TabDisplay != null) TabDisplay(sender, args); } #endregion #region Constructors public vlnTreeView() { InitializeComponent(); this.AllowDrop = true; DragHelper.InitCommonControls(); this.ItemDrag += new ItemDragEventHandler(tv_ItemDrag); this.DragDrop += new DragEventHandler(tv_DragDrop); this.DragEnter += new DragEventHandler(tv_DragEnter); this.DragLeave += new EventHandler(tv_DragLeave); this.DragOver += new DragEventHandler(tv_DragOver); this.MouseDown += new MouseEventHandler(tv_MouseDown); this.KeyPress += new KeyPressEventHandler(tv_KeyPress); base.AfterSelect += new TreeViewEventHandler(tv_AfterSelect); } #endregion #region MenuSupport private void tv_AfterSelect(object sender, TreeViewEventArgs e) { if (!_AdjustingTree) OnNodeSelectionChange(sender, new vlnTreeEventArgs(e.Node)); } // use to determine which menu items have been selected for those tree nodes // that allow more than one type of operation associated with their selection. public enum MenuSelections : int { Folder = 1, FolderBefore = 2, FolderAfter = 3, DocVersion = 4, Procedure = 5, ProcedureBefore = 6, ProcedureAfter = 7, Section = 8, SectionBefore = 9, SectionAfter = 10, Step = 11, StepBefore = 12, StepAfter = 13, StepReplace = 14 } void tv_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { OwnerInfoList oil = null; OwnerInfo oi = null; FolderInfo fi = null; // B2016-058 so we can customize the "collapse" menu item text bool isProcNode = false; bool isSectNode = false; bool isFolderNode = false; bool isWrkDftNode = false; VETreeNode tn = this.GetNodeAt(new Point(e.X, e.Y)) as VETreeNode; if (tn != null) { this.SelectedNode = tn as TreeNode; Application.DoEvents(); // Display Menu ToolStripMenuItem mi = new ToolStripMenuItem(); ContextMenu cm = new ContextMenu(); //_MyLog.WarnFormat("Context Menu 1 - {0}",GC.GetTotalMemory(true)); UserInfo ui = UserInfo.GetByUserID(VlnSettings.UserID); //_MyLog.WarnFormat("Context Menu 1a - {0}", GC.GetTotalMemory(true)); if (ui == null) { FlexibleMessageBox.Show("Security has not been defined for PROMS. All functionality has been defaulted to the lowest level for all users until security is defined.", "no security defined", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } this.Cursor = Cursors.WaitCursor; #region Menu_New if (tn.VEObject as FolderInfo != null) { isFolderNode = true; // For Folders, if no children, can add either docversion or folder. If children are // folders then can only add another folder, and if children are docversions can only // add docversion. fi = tn.VEObject as FolderInfo; bool DoSpecificInfo = fi.ActiveFormat.PlantFormat.FormatData.SpecificInfo; if (ui.IsAdministrator() || ui.IsSetAdministrator(fi))// && fi.MyParent == null) //VEPROMS level { if (fi.HasWorkingDraft) cm.MenuItems.Add("Export Procedure Set", new EventHandler(mi_Click)); else cm.MenuItems.Add("Import Procedure Set", new EventHandler(mi_Click)); if (DoSpecificInfo) cm.MenuItems.Add("Folder Specific Information", new EventHandler(mi_Click)); // C2020-008: change to 'Folder' } //_MyLog.WarnFormat("Context Menu 1b - {0}", GC.GetTotalMemory(true)); if (ui.IsAdministrator() || ui.IsSetAdministrator(fi)) { if (fi.MyParent != null) // don't allow insert before/after if at top node { if (!ui.IsAdministrator() && DoSpecificInfo) cm.MenuItems.Add("Procedure Set Specific Information", new EventHandler(mi_Click)); // B2020-111 only allow Set Administrator to add new folders inside folders they admininstrate if (ui.IsAdministrator()||ui.IsSetAdministrator(fi.MyParent)) { cm.MenuItems.Add("Insert Folder Before", new EventHandler(mi_Click)); cm.MenuItems.Add("Insert Folder After", new EventHandler(mi_Click)); } } // B2020-111 only allow Set Administrator to add new folders inside folders they admininstrate if ((ui.IsAdministrator() || ui.IsSetAdministrator(fi.MyParent)) && fi.FolderDocVersionCount == 0) cm.MenuItems.Add("New Folder", new EventHandler(mi_Click)); if (fi.ChildFolderCount == 0 && !fi.HasWorkingDraft) cm.MenuItems.Add("Create Working Draft", new EventHandler(mi_Click)); } if (fi.HasWorkingDraft) cm.MenuItems.Add("Print Transition Report", new EventHandler(mi_Click)); } else if (tn.VEObject as DocVersionInfo != null) // DocVersions can only contain procs { isWrkDftNode = true; //_MyLog.WarnFormat("Context Menu 1c - {0}", GC.GetTotalMemory(true)); DocVersionInfo dvi = tn.VEObject as DocVersionInfo; if (ui.IsAdministrator() || ui.IsSetAdministrator(dvi)) { cm.MenuItems.Add("Import Procedure", mi_Click); } if (ui.IsAdministrator() || ui.IsSetAdministrator(dvi) || ui.IsWriter(dvi)) { OwnerInfoList.Reset(); oil = OwnerInfoList.GetByVersionID(dvi.VersionID); if (dvi.ActiveFormat.PlantFormat.FormatData.SpecificInfo) cm.MenuItems.Add("Procedure Set Specific Information", new EventHandler(mi_Click)); cm.MenuItems.Add("Refresh Checked Out Procedures", new EventHandler(mi_Click)); cm.MenuItems.Add("New Procedure", new EventHandler(mi_Click)); if (dvi.MultiUnitCount > 1) { MenuItem mip = new MenuItem("Print All Procedures for"); MenuItem mia = new MenuItem("Approve All Procedures for"); MenuItem mis = new MenuItem("Approve Some Procedures for"); int k = 0; foreach (string s in dvi.UnitNames) { k++; MenuItem mp = mip.MenuItems.Add(s, new EventHandler(miMultiUnit_Click)); mp.Tag = k; MenuItem ma = mia.MenuItems.Add(s, new EventHandler(miMultiUnit_Click)); ma.Tag = k; MenuItem ms = mis.MenuItems.Add(s, new EventHandler(miMultiUnit_Click)); ms.Tag = k; } //MenuItem mmp = mip.MenuItems.Add("All Units", new EventHandler(miMultiUnit_Click)); //mmp.Tag = 0; //MenuItem mma = mia.MenuItems.Add("All Units", new EventHandler(miMultiUnit_Click)); //mma.Tag = 0; //MenuItem mms = mis.MenuItems.Add("All Units", new EventHandler(miMultiUnit_Click)); //mms.Tag = 0; cm.MenuItems.Add(mip); cm.MenuItems.Add(mia); cm.MenuItems.Add(mis); } else { //_MyLog.WarnFormat("Context Menu 1d - {0}", GC.GetTotalMemory(true)); cm.MenuItems.Add("Print All Procedures", new EventHandler(mi_Click)); cm.MenuItems.Add("Approve All Procedures", new EventHandler(mi_Click)); cm.MenuItems.Add("Approve Some Procedures", new EventHandler(mi_Click)); } cm.MenuItems.Add("Report All Procedures Inconsistencies", new EventHandler(mi_Click)); } else { //_MyLog.WarnFormat("Context Menu 1e - {0}", GC.GetTotalMemory(true)); OwnerInfoList.Reset(); oil = OwnerInfoList.GetByVersionID(dvi.VersionID); cm.MenuItems.Add("Refresh Checked Out Procedures", new EventHandler(mi_Click)); if (dvi.MultiUnitCount > 1) { MenuItem mip = new MenuItem("Print All Procedures for"); int k = 0; foreach (string s in dvi.UnitNames) { k++; MenuItem mp = mip.MenuItems.Add(s, new EventHandler(miMultiUnit_Click)); mp.Tag = k; } //MenuItem mmp = mip.MenuItems.Add("All Units", new EventHandler(miMultiUnit_Click)); //mmp.Tag = 0; //MenuItem mma = mia.MenuItems.Add("All Units", new EventHandler(miMultiUnit_Click)); //mma.Tag = 0; //MenuItem mms = mis.MenuItems.Add("All Units", new EventHandler(miMultiUnit_Click)); //mms.Tag = 0; cm.MenuItems.Add(mip); } else { //_MyLog.WarnFormat("Context Menu 1f - {0}", GC.GetTotalMemory(true)); cm.MenuItems.Add("Print All Procedures", new EventHandler(mi_Click)); } } //if (ui.IsAdministrator() || ui.IsSetAdministrator(dvi)) //{ // cm.MenuItems.Add("Check Out Procedure Set", new EventHandler(mi_Click)); // cm.MenuItems.Add("Check In Procedure Set", new EventHandler(mi_Click)); //} if (ui.IsAdministrator() || ui.IsSetAdministrator(dvi) || ui.IsROEditor(dvi)) { //_MyLog.WarnFormat("Context Menu 1g - {0}", GC.GetTotalMemory(true)); cm.MenuItems.Add("Run RO Editor", new EventHandler(mi_Click)); } if (ui.IsAdministrator() || ui.IsSetAdministrator(dvi)) { //_MyLog.WarnFormat("Context Menu 1h - {0}", GC.GetTotalMemory(true)); MenuItem urv = cm.MenuItems.Add("Update RO Values", new EventHandler(mi_Click)); // only allow update if association, and the RO update was not done and/or not completed urv.Enabled = !dvi.ROfstLastCompleted || dvi.NewerRoFst; } } else if (tn.VEObject as ProcedureInfo != null) // Procs can only contain sections { isProcNode = true; ProcedureInfo pri = tn.VEObject as ProcedureInfo; oi = OwnerInfo.GetByItemID(pri.ItemID, CheckOutType.Procedure); if (ui.IsAdministrator() || ui.IsSetAdministrator(pri.MyDocVersion)) { cm.MenuItems.Add("Export Procedure", mi_Click); } if (ui.IsAdministrator() || ui.IsSetAdministrator(pri.MyDocVersion) || ui.IsWriter(pri.MyDocVersion)) { if (oi != null && oi.SessionID != MySessionInfo.SessionID) cm.MenuItems.Add(string.Format("Procedure Checked Out to {0}", oi.SessionUserID), new EventHandler(mi_Click)); if (pri.ActiveFormat.PlantFormat.FormatData.ProcData.PSI.Caption != null) cm.MenuItems.Add("Procedure Specific Information", new EventHandler(mi_Click)); cm.MenuItems.Add("Insert Procedure Before", new EventHandler(mi_Click)); cm.MenuItems.Add("Insert Procedure After", new EventHandler(mi_Click)); // if this format has change ids that were added from edit, allow removal of // change ids for this procedure: //FolderInfo fi = FolderInfo.Get(1); //FormatInfo frmI = FormatInfo.Get(fi.FormatID ?? 1); //if (frmI.PlantFormat.FormatData.ProcData.ChangeBarData.ChgBarMessageFromEdit) // cm.MenuItems.Add("Remove Change Ids", new EventHandler(mi_Click)); cm.MenuItems.Add("New Section", new EventHandler(mi_Click)); if (pri.MyDocVersion.MultiUnitCount > 1) { MenuItem micas = new MenuItem("Create Continuous Action Summary"); MenuItem mitcas = new MenuItem("Create Time Critical Action Summary"); //F2022-024 added menu option MenuItem mip = new MenuItem("Print"); MenuItem miqp = new MenuItem("Quick Print"); //MenuItem mips = new MenuItem("Print Section"); MenuItem mia = new MenuItem("Approve"); int k = 0; foreach (string s in pri.MyDocVersion.UnitNames) { // C2021-027: Procedure level PC/PC - see if menu items for unit should be enabled bool procAppl = pri.ApplIncludeFromStr(s); k++; MenuItem mp = mip.MenuItems.Add(s, new EventHandler(miMultiUnit_Click)); mp.Enabled = procAppl; mp.Tag = k; MenuItem mqp = miqp.MenuItems.Add(s, new EventHandler(miMultiUnit_Click)); mqp.Enabled = procAppl; mqp.Tag = k; //MenuItem mps = mips.MenuItems.Add(s, new EventHandler(miMultiUnit_Click)); //mps.Enabled = procAppl; //mps.Tag = k; MenuItem ma = mia.MenuItems.Add(s, new EventHandler(miMultiUnit_Click)); ma.Enabled = procAppl; ma.Tag = k; MenuItem mc = micas.MenuItems.Add(s, new EventHandler(miMultiUnit_Click)); mc.Enabled = procAppl; mc.Tag = k; MenuItem mtc = mitcas.MenuItems.Add(s, new EventHandler(miMultiUnit_Click)); mtc.Enabled = procAppl; mtc.Tag = k; } cm.MenuItems.Add(micas); cm.MenuItems.Add(mitcas); cm.MenuItems.Add(mip); cm.MenuItems.Add(miqp); //cm.MenuItems.Add(mips); AddShowChangeBarsAfterMenuItem(cm.MenuItems, pri); cm.MenuItems.Add(mia); AddApprovedRevisionsMultiUnit(cm.MenuItems, pri); } else { cm.MenuItems.Add("Create Continuous Action Summary", new EventHandler(mi_Click)); cm.MenuItems.Add("Create Time Critical Action Summary", new EventHandler(mi_Click)); cm.MenuItems.Add("Print", new EventHandler(mi_Click)); cm.MenuItems.Add("Quick Print", new EventHandler(mi_Click)); //cm.MenuItems.Add("Print Section", new EventHandler(mi_Click)); //MenuItem miqp = new MenuItem("Print"); AddShowChangeBarsAfterMenuItem(cm.MenuItems, pri); cm.MenuItems.Add("Approve", new EventHandler(mi_Click)); //_MyLog.WarnFormat("Context Menu 1 before - {0}", GC.GetTotalMemory(true)); AddApprovedRevisions(cm.MenuItems, pri); //_MyLog.WarnFormat("Context Menu 1 after - {0}", GC.GetTotalMemory(true)); } } else { if (oi != null && oi.SessionID != MySessionInfo.SessionID) cm.MenuItems.Add(string.Format("Procedure Checked Out to {0}", oi.SessionUserID), new EventHandler(mi_Click)); if (pri.MyDocVersion.MultiUnitCount > 1) { MenuItem mip = new MenuItem("Print"); MenuItem miqp = new MenuItem("Quick Print"); int k = 0; foreach (string s in pri.MyDocVersion.UnitNames) { k++; MenuItem mp = mip.MenuItems.Add(s, new EventHandler(miMultiUnit_Click)); mp.Tag = k; MenuItem mqp = miqp.MenuItems.Add(s, new EventHandler(miMultiUnit_Click)); mqp.Tag = k; } cm.MenuItems.Add(mip); cm.MenuItems.Add(miqp); AddApprovedRevisionsMultiUnit(cm.MenuItems, pri); } else { cm.MenuItems.Add("Print", new EventHandler(mi_Click)); cm.MenuItems.Add("Quick Print", new EventHandler(mi_Click)); AddApprovedRevisions(cm.MenuItems, pri); } } cm.MenuItems.Add("Print Transition Report", new EventHandler(mi_Click)); } else if (tn.VEObject as SectionInfo != null) { isSectNode = true; // A step Section can contain other steps or can contain subsections (either step section // or word doc section). Also note that there can be a mix. // A word doc section can contain another subsection (either step section or word doc section), // but cannot contain steps. SectionInfo si = tn.VEObject as SectionInfo; // if this is an enhanced section, don't do 'New Step' if (ui.IsAdministrator() || ui.IsSetAdministrator(si.MyProcedure.MyDocVersion) || ui.IsWriter(si.MyProcedure.MyDocVersion)) { if (si.HasWordContent) { oi = OwnerInfo.GetByItemID(si.MyContent.MyEntry.DocID, CheckOutType.Document); } si.MyConfig = null; // Do not need step versus Word doc options, user enters this in property page during // insert process. if (oi != null && oi.SessionID != MySessionInfo.SessionID) cm.MenuItems.Add(string.Format("Document Checked Out to {0}", oi.SessionUserID), new EventHandler(mi_Click)); cm.MenuItems.Add("Insert Section Before", new EventHandler(mi_Click)); cm.MenuItems.Add("Insert Section After", new EventHandler(mi_Click)); if (!si.IsAutoTOCSection && si.IsStepSection) // B2016-282: Don't allow insert of subsections off Word Section. { bool meta = si.ActiveFormat.PlantFormat.FormatData.SectData.UseMetaSections; if (meta) cm.MenuItems.Add("New Subsection", new EventHandler(mi_Click)); // if this section has subsections, then be sure that the 'editable' data config // is set to allow new step creation. if (si.IsStepSection) { SectionConfig sc = si.MyConfig as SectionConfig; if (!si.IsEnhancedSection && (si.Sections == null || si.Sections.Count == 0 || (meta && sc != null && si.Sections != null && si.Sections.Count > 0 && sc.SubSection_Edit == "Y"))) cm.MenuItems.Add("New Step", new EventHandler(mi_Click)); //ProcedureInfo pri = tn as SectionInfo; SectionInfo si2 = (tn as VETreeNode).VEObject as SectionInfo; if (si2.MyDocVersion.MultiUnitCount > 1) { MenuItem mps = new MenuItem("Print Section"); int k = 0; foreach (string s in si2.MyDocVersion.UnitNames) { k++; MenuItem mp = mps.MenuItems.Add(s, new EventHandler(miMultiUnit_Click)); mp.Tag = k; } cm.MenuItems.Add(mps); } else { cm.MenuItems.Add("Print Section", new EventHandler(mi_Click)); } } } } } else if (tn.VEObject as StepInfo != null) { // check the format for allowable inserts, and also, ItemInfo i = tn.VEObject as ItemInfo; if (ui.IsAdministrator() || ui.IsSetAdministrator(i.MyProcedure.MyDocVersion) || ui.IsWriter(i.MyProcedure.MyDocVersion)) { //oi = OwnerInfo.GetByItemID(i.MyProcedure.ItemID); if (AddToInsertMenu(i, 0)) cm.MenuItems.Add("Insert Step Before", new EventHandler(mi_Click)); if (AddToInsertMenu(i, 1)) cm.MenuItems.Add("Insert Step After", new EventHandler(mi_Click)); } } #endregion //_MyLog.WarnFormat("Context Menu 2 - {0}", GC.GetTotalMemory(true)); //#region Print_Section //if (!tn.IsExpanded && tn.VEObject as SectionInfo != null) //{ // SectionInfo si = tn.VEObject as SectionInfo; // if (si.IsStepSection) cm.MenuItems.Add("Print Section", new EventHandler(mi_Click)); //} //#endregion #region Menu_Open if (!tn.IsExpanded && tn.VEObject as SectionInfo != null) { SectionInfo si = tn.VEObject as SectionInfo; if (si.IsStepSection) cm.MenuItems.Add("Open", new EventHandler(mi_Click)); } else if (!tn.IsExpanded && tn.VEObject as StepInfo != null) { StepInfo stpi = tn.VEObject as StepInfo; if (stpi.HasChildren) cm.MenuItems.Add("Open", new EventHandler(mi_Click)); } else if (!tn.IsExpanded) cm.MenuItems.Add("Open", new EventHandler(mi_Click)); else { // B2016-058 customize the "Collapse" menu text based on tree node type string mtext = "Collapse"; // only the step or substep (RNOs, Cautions, Notes as well) will be collapsed if (isFolderNode || isWrkDftNode) mtext += " All Procedures"; // all expanded procedure nodes in all procedure sets are collapsed (folder and working draft nodes remain expanded) else if (isProcNode) mtext += " Procedure"; // only the current procedure node is collapsed else if (isSectNode) mtext += " Section"; // only the current section node is collapsed cm.MenuItems.Add(mtext, new EventHandler(mi_Click)); } #endregion //_MyLog.WarnFormat("Context Menu 3 - {0}", GC.GetTotalMemory(true)); #region Menu_CutCopy // For initial release, copy is not available for folders or docversions if (tn.VEObject as ItemInfo != null) { ItemInfo i = tn.VEObject as ItemInfo; // in the following, 'Copy' is not allowed for any procedure/section/step that is enhanced. Note that this may be // changed later, but for the initial enhanced development it was decided to not allow copy of enhanced since paste would // require clearing of all enhanced config data or mapping it to existing data (quite complicated) if ((ui.IsAdministrator() || ui.IsSetAdministrator(i.MyProcedure.MyDocVersion) || ui.IsWriter(i.MyProcedure.MyDocVersion)) && (!i.IsEnhancedStep && !i.IsEnhancedProcedure && !i.IsEnhancedSection && !i.IsRtfRaw && !i.IsFigure)) cm.MenuItems.Add("Copy", new EventHandler(mi_Click)); if (i.HasWordContent) { cm.MenuItems.Add("Print Section", new EventHandler(mi_Click)); } } #endregion //_MyLog.WarnFormat("Context Menu 4 - {0}", GC.GetTotalMemory(true)); #region Menu_Paste bool ok = false; if (tn.VEObject is FolderInfo && (ui.IsAdministrator() || ui.IsSetAdministrator(tn.VEObject as FolderInfo))) ok = true; else if (tn.VEObject is DocVersionInfo && (ui.IsAdministrator() || ui.IsSetAdministrator(tn.VEObject as DocVersionInfo))) ok = true; else if (tn.VEObject is ItemInfo && (ui.IsAdministrator() || ui.IsSetAdministrator((tn.VEObject as ItemInfo).MyProcedure.MyDocVersion) || ui.IsWriter((tn.VEObject as ItemInfo).MyProcedure.MyDocVersion))) ok = true; if(ok) Menu_Paste(tn, cm); #endregion //_MyLog.WarnFormat("Context Menu 5 - {0}", GC.GetTotalMemory(true)); #region Menu_Delete if (ok) { // Add delete to the menu unless at the very 'top' node, on a grouping (partinfo) // node (RNOs, Steps, Cautions, Notes) or Folder/DocVersion that contains any items. PartInfo pi = tn.VEObject as PartInfo; if (pi == null && tn.Parent != null) // it's not a part and it's not the top.... { fi = tn.VEObject as FolderInfo; if (fi == null || tn.Nodes.Count == 0) // it's not a folder or it has no children { DocVersionInfo di = tn.VEObject as DocVersionInfo; if (di == null || tn.Nodes.Count == 0) // it's not a docversion or it has no children { // if it's an enhanced step that was linked from a source, don't allow delete bool canDoDel = true; ItemInfo iienh = tn.VEObject as ItemInfo; if (iienh != null && iienh.IsProcedure && iienh.IsEnhancedProcedure) canDoDel = false; if (iienh != null && iienh.IsSection && iienh.IsEnhancedSection && !iienh.IsEnhancedSectionTitleOnly) canDoDel = false; if (iienh != null && iienh.IsEnhancedStep) canDoDel = false; if (canDoDel) cm.MenuItems.Add("Delete", new EventHandler(mi_Click)); } } } } #endregion //_MyLog.WarnFormat("Context Menu 6 - {0}", GC.GetTotalMemory(true)); #region Menu_ExternalTransitions // C2020-033: Support the menu item to bring up Search/Incoming Transitions panel ItemInfo iix = tn.VEObject as ItemInfo; if (iix != null) { cm.MenuItems.Add("Incoming Transitions", new EventHandler(mi_Click)); } #endregion #region Menu_UnLinkEnhanced // B2022-049: provide for way to unlink a procedure from the tree view. Also unlinks procedure if no // connected (linked) procedure. if (tn.VEObject is ProcedureInfo) { ItemInfo prc = (ItemInfo)tn.VEObject; if (ui.IsAdministrator() || ui.IsSetAdministrator(prc.MyDocVersion) || ui.IsWriter(prc.MyDocVersion)) { DVEnhancedDocuments dveds = prc.MyDocVersion.DocVersionConfig.MyEnhancedDocuments; EnhancedDocuments eds = prc.GetMyEnhancedDocuments(); // if just one link, add single menu item to unlink. If more than one, need a list with all. if (eds != null && eds.Count == 1) { // Get menu string, must start with 'Unlink Source ' string doclink = null; doclink = dveds.GetByType(eds[0].Type).Name; // need background/dev if on source if (eds[0].Type == 0) { ItemInfo prl = ItemInfo.Get(eds[0].ItemID); DVEnhancedDocuments dvedsl = prl.MyDocVersion.DocVersionConfig.MyEnhancedDocuments; foreach (DVEnhancedDocument dvel in dvedsl) if (dvel.VersionID == prc.MyDocVersion.VersionID) doclink = dvel.Name; } doclink = string.Format("Unlink Source and {0} Procedure", doclink); MenuItem mix = cm.MenuItems.Add(doclink, new EventHandler(miEnhanced_Click)); mix.Tag = -1; // NOTE this is what flags what gets processed on menu click, i.e. -1 } // if this is a source procedure that has enhanced, for example Background and/or deviation, ask which should be unlinked including all else if (eds != null && eds.Count > 1) { MenuItem miu = new MenuItem("Unlink Enhanced Procedure(s) from Source"); miu.Tag = -2; // this menu item doesn't get used. int k = 0; foreach (EnhancedDocument ed in eds) { // add submenu item for it k++; MenuItem mp = miu.MenuItems.Add(dveds.GetByType(ed.Type).Name, new EventHandler(miEnhanced_Click)); mp.Tag = k; } // add all submenu item MenuItem mp1 = miu.MenuItems.Add("All", new EventHandler(miEnhanced_Click)); mp1.Tag = 0; // Tag of 0 flags All cm.MenuItems.Add(miu); } } } #endregion #region Menu_Properties // Add Properties to the menu unless at the very 'top' node or on a grouping (partinfo) // node (RNOs, Steps, Cautions, Notes) or at the step level. // B2020-105 Allow Set Administrators to rename folder's (sets of procedures) to which they have been given access. if ( tn.VEObject is FolderInfo) ok = (ui.IsAdministrator() || ui.IsSetAdministrator(tn.VEObject as FolderInfo)); else ok = (tn.VEObject is DocVersionInfo) ? (ui.IsAdministrator() || ui.IsSetAdministrator(tn.VEObject as DocVersionInfo)) : (ui.IsAdministrator() || (tn.VEObject is ItemInfo) && (ui.IsSetAdministrator((tn.VEObject as ItemInfo).MyProcedure.MyDocVersion) || ui.IsWriter((tn.VEObject as ItemInfo).MyProcedure.MyDocVersion))); PartInfo pia = tn.VEObject as PartInfo; ItemInfo ii = tn.VEObject as ItemInfo; if (ok) if (pia == null && tn.VEObject as StepInfo == null) cm.MenuItems.Add("Properties...", new EventHandler(mi_Click)); #endregion //_MyLog.WarnFormat("Context Menu 7 - {0}", GC.GetTotalMemory(true)); if (fi != null && fi.HasWorkingDraft) { /* --Folder level see if we need to disable "Export Procedure Set" or "Folder Specific Information" */ if (tn.MovedToSeparateWindow) { foreach (MenuItem itm in cm.MenuItems) { if (!itm.Text.StartsWith("Insert")) // C2015-022 only enable insert folder before/after if in the main window and the procedures of this folder are in a child window itm.Enabled = false; } } else if (tn.InChildWindow) { foreach (MenuItem itm in cm.MenuItems) { if (itm.Text.StartsWith("Insert")) // C2015-022 disable insert folder before/after if doing a properties on a folder in a child window itm.Enabled = false; } } else { if (!tn.ChildrenLoaded) tn.LoadChildren(); VETreeNode wrkdrft = (VETreeNode)tn.LastNode; DocVersionInfo docver = wrkdrft.VEObject as DocVersionInfo; OwnerInfoList.Reset(); oil = OwnerInfoList.GetByVersionID(docver.VersionID); bool greyOut = false; foreach (OwnerInfo own in oil) { if (own.SessionID != MySessionInfo.SessionID) { greyOut = true; break; } } if (greyOut) { foreach (MenuItem itm in cm.MenuItems) { if (itm.Text == "Export Procedure Set" || itm.Text == "Folder Specific Information") // C2020-008: change to 'Folder' itm.Enabled = false; } } } } if (oil != null && oil.Count > 0 && tn.VEObject as DocVersionInfo != null) { /* --docversion level Approve All Procedures Report All Procedures Inconsistencies */ bool greyOut = false; foreach (OwnerInfo own in oil) { if (own.SessionID != MySessionInfo.SessionID) { greyOut = true; break; } } if (greyOut) { foreach (MenuItem itm in cm.MenuItems) { if (itm.Text == "Approve All Procedures" || itm.Text == "Report All Procedures Inconsistencies" || itm.Text == "Procedure Set Specific Information" || itm.Text == "Approve All Procedures for" || itm.Text == "Approve Some Procedures" || itm.Text == "Approve Some Procedures for") itm.Enabled = false; } } } if (oi != null && oi.SessionID != MySessionInfo.SessionID) { /* --procedure level Procedure Specific Information New Section Approve Open Copy Delete Properties... --section level all of them --step level all of them */ //_MyLog.WarnFormat("Context Menu 8 - {0}", GC.GetTotalMemory(true)); if (tn.VEObject as ProcedureInfo != null) { // F2022-024 added Time Critical Action Summary option foreach (MenuItem itm in cm.MenuItems) { if(itm.Text == "Procedure Specific Information" || itm.Text == "New Section" || itm.Text == "Approve" || itm.Text == "Open" || itm.Text == "Copy" || itm.Text == "Delete" || itm.Text == "Properties..." || itm.Text == "Replace Existing Procedure" || itm.Text.StartsWith("Showing Change Bars Starting") || itm.Text == "Create Continuous Action Summary" || itm.Text == "Create Time Critical Action Summary" || itm.Text == "Export Procedure") itm.Enabled = false; } } if (tn.VEObject as SectionInfo != null || tn.VEObject as StepInfo != null) { foreach (MenuItem itm in cm.MenuItems) { if(!itm.Text.StartsWith("Document Checked Out")) itm.Enabled = false; } } } this.Cursor = Cursors.Default; //_MyLog.WarnFormat("Context Menu 9 - {0}", GC.GetTotalMemory(true)); cm.Show(this, new Point(e.X, e.Y)); } } } private void AddApprovedRevisionsMultiUnit(Menu.MenuItemCollection menuItemCollection, ProcedureInfo pri) { _currentPri = pri; RevisionInfoList ril = RevisionInfoList.GetByItemID(pri.ItemID); if (ril.Count == 0) return; // no versions to list MenuItem mi = menuItemCollection.Add("Versions"); int k = 0; int lastApprovedRevisionID = 0; foreach (string s in pri.MyDocVersion.UnitNames) { k++; MenuItem mv = mi.MenuItems.Add(s); mv.Tag = k; ril = RevisionInfoList.GetByItemIDandUnitID(pri.ItemID, k); foreach (RevisionInfo ri in ril) { MenuItem mir = mv.MenuItems.Add(ri.ToString()); mir.Tag = ri; if (ri.LatestVersion.MyStage.IsApproved > 0 && (ri.RevisionID > lastApprovedRevisionID)) lastApprovedRevisionID = ri.RevisionID; if (ri.Notes.Length > 0) //C2018-026 add the ability to show notes entered during approval or workflow stage in the sub-menu { MenuItem mirp = mir.MenuItems.Add("View Revision Stage Notes"); mirp.Tag = ri; mirp.Click += new EventHandler(ViewRevisonStageNotes_Click); } if (ri.LatestVersion.PDF != null) { MenuItem mirp = mir.MenuItems.Add("View Procedure"); mirp.Tag = ri.RevisionID; mirp.Click += new EventHandler(MultiUnitApprovedRevision_Click); } if (ri.LatestVersion.SummaryPDF != null) { MenuItem mirs = mir.MenuItems.Add("View Summary of Changes"); mirs.Tag = ri.RevisionID; mirs.Click += new EventHandler(MultiUnitSummaryOfChanges_Click); } if (ri.LatestVersion.ApprovedXML != null && ri.LatestVersion.ApprovedXML != "") { MenuItem miri = mir.MenuItems.Add("Create Procedure to Import"); miri.Tag = ri.RevisionID; miri.Click += new EventHandler(MultiUnitImportProcedure_Click); //B2024-024 Parent Child Create Approved Import file } //end added jcb 20111031 mv.Tag = lastApprovedRevisionID; } ril = null; } } public void AddNewNode(IVEDrillDownReadOnly o) { VETreeNode tn = new VETreeNode(o); SelectedNode.Nodes.Add(tn); } private void AddApprovedRevisions(Menu.MenuItemCollection menuItemCollection, ProcedureInfo pri) { try { //_MyLog.WarnFormat("Context Menu 1 before GET - {0}", GC.GetTotalMemory(true)); _currentPri = pri; using (RevisionInfoList ril = RevisionInfoList.GetByItemID(pri.ItemID)) { //_MyLog.WarnFormat("Context Menu 1 After GET - {0}", GC.GetTotalMemory(true)); if (ril.Count == 0) return; // no versions to list MenuItem mi = menuItemCollection.Add("Versions"); int lastApprovedRevisionID = 0; foreach (RevisionInfo ri in ril) { MenuItem mir = mi.MenuItems.Add(ri.ToString()); mir.Tag = ri; bool addImportMI = false; if (ri.LatestVersion.MyStage.IsApproved > 0 && (ri.RevisionID > lastApprovedRevisionID)) { lastApprovedRevisionID = ri.RevisionID; addImportMI = true; } //mir.Click += new EventHandler(ApprovedRevision_Click); //added jcb 20111031 //_MyLog.WarnFormat("Context Menu 1 b4ViewProc- {0}", GC.GetTotalMemory(true)); if (ri.Notes.Length > 0) //C2018-026 add the ability to show notes entered during approval or workflow stage in the sub-menu { MenuItem mirp = mir.MenuItems.Add("View Revision Stage Notes"); mirp.Tag = ri; mirp.Click += new EventHandler(ViewRevisonStageNotes_Click); } if (ri.LatestVersion.PDF != null) { MenuItem mirp = mir.MenuItems.Add("View Procedure"); mirp.Tag = ri; mirp.Click += new EventHandler(ApprovedRevision_Click); } //_MyLog.WarnFormat("Context Menu 1 b4viewSum- {0}", GC.GetTotalMemory(true)); if (ri.LatestVersion.SummaryPDF != null) { MenuItem mirs = mir.MenuItems.Add("View Summary of Changes"); mirs.Tag = ri; mirs.Click += new EventHandler(SummaryOfChanges_Click); } //_MyLog.WarnFormat("Context Menu 1 b4 import - {0}", GC.GetTotalMemory(true)); if (addImportMI && ri.LatestVersion.ApprovedXML != null && ri.LatestVersion.ApprovedXML != "") { MenuItem miri = mir.MenuItems.Add("Create Procedure to Import"); miri.Tag = ri; miri.Click += new EventHandler(ImportProcedure_Click); } //_MyLog.WarnFormat("Context Menu 1 after import- {0}", GC.GetTotalMemory(true)); //end added jcb 20111031 mi.Tag = lastApprovedRevisionID; } } } catch { return; } } private void AddShowChangeBarsAfterMenuItem(Menu.MenuItemCollection menuItemCollection, ProcedureInfo pri) { using (RevisionInfoList ril = RevisionInfoList.GetByItemID(pri.ItemID)) { if (ril.Count == 0 || MyUserInfo.IsAdministrator() || MyUserInfo.IsSetAdministrator(pri.MyDocVersion)) { ProcedureConfig pc = pri.MyConfig as ProcedureConfig; string currentChgBarDateTime = ""; if (pc != null) currentChgBarDateTime = pc.Print_ChangeBarDate; // Current change bar date time before if (currentChgBarDateTime == "") currentChgBarDateTime = "(date not set)"; else currentChgBarDateTime = currentChgBarDateTime.Split(' ')[0]; // only show the date not the time menuItemCollection.Add(string.Format("Showing Change Bars Starting {0}", currentChgBarDateTime), new EventHandler(mi_Click)); } } } void ImportProcedure_Click(object sender, EventArgs e) { //B2024-024 restored the line below from prior change - didn't work for non parent/childs sets - created a new click event method (below) for parent/child sets. RevisionInfo ri = (sender as MenuItem).Tag as RevisionInfo; RevisionConfig rc = ri.MyConfig as RevisionConfig; // bug fix: B2016-183 - add the child's name (ex Unit 1) to the export file name for Parent/Child procedures. int applIdx = rc.Applicability_Index; string str = (applIdx > 0)?_currentPri.MyDocVersion.UnitNames[applIdx-1] +"_":""; // if parent/child get the defined child name to inlcude the export filename System.Xml.XmlDocument xd = new System.Xml.XmlDocument(); xd.LoadXml(ri.LatestVersion.ApprovedXML); string PEIPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\VEPROMS\PEI_" + Database.VEPROMS_SqlConnection.Database; DirectoryInfo di = new DirectoryInfo(PEIPath); if (!di.Exists) di.Create(); // B2022-048: Crash when creating Procedure to Import from versions. Couldn't handle '/' in proc number. string fNametmp = xd.SelectSingleNode("procedure/content/@number").InnerText.Replace(" ", "_").Replace(@"\u8209?", "-").Replace(@"\u9586?", "_").Replace("/", "-") + ".pxml"; // B2022-112: If applicability, need to resolve the '<' and '>' characters. Just use the UnitNames, i.e. str, from above. if (applIdx > 0) fNametmp = Regex.Replace(fNametmp, @"\", str, RegexOptions.IgnoreCase); string fileName = PEIPath + "\\" + str + "Approved_Rev_" + ri.RevisionNumber.Replace(" ", "_").Replace("\\", "-").Replace("/", "-") + "_" + fNametmp; xd.Save(fileName); FlexibleMessageBox.Show("Approved procedure saved to import file " + fileName, "Creating Export of Approved Procedure", MessageBoxButtons.OK, MessageBoxIcon.Information); } //B2024-024 create import file for parent/child procedure set void MultiUnitImportProcedure_Click(object sender, EventArgs e) { //RevisionInfo ri = (sender as MenuItem).Tag as RevisionInfo; RevisionInfo ri = RevisionInfo.Get(int.Parse((sender as MenuItem).Tag.ToString())); RevisionConfig rc = ri.MyConfig as RevisionConfig; // bug fix: B2016-183 - add the child's name (ex Unit 1) to the export file name for Parent/Child procedures. int applIdx = rc.Applicability_Index; string str = (applIdx > 0) ? _currentPri.MyDocVersion.UnitNames[applIdx - 1] + "_" : ""; // if parent/child get the defined child name to inlcude the export filename System.Xml.XmlDocument xd = new System.Xml.XmlDocument(); xd.LoadXml(ri.LatestVersion.ApprovedXML); string PEIPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\VEPROMS\PEI_" + Database.VEPROMS_SqlConnection.Database; DirectoryInfo di = new DirectoryInfo(PEIPath); if (!di.Exists) di.Create(); // B2022-048: Crash when creating Procedure to Import from versions. Couldn't handle '/' in proc number. string fNametmp = xd.SelectSingleNode("procedure/content/@number").InnerText.Replace(" ", "_").Replace(@"\u8209?", "-").Replace(@"\u9586?", "_").Replace("/", "-") + ".pxml"; // B2022-112: If applicability, need to resolve the '<' and '>' characters. Just use the UnitNames, i.e. str, from above. if (applIdx > 0) fNametmp = Regex.Replace(fNametmp, @"\", str, RegexOptions.IgnoreCase); string fileName = PEIPath + "\\" + str + "Approved_Rev_" + ri.RevisionNumber.Replace(" ", "_").Replace("\\", "-").Replace("/", "-") + "_" + fNametmp; xd.Save(fileName); FlexibleMessageBox.Show("Approved procedure saved to import file " + fileName, "Creating Export of Approved Procedure", MessageBoxButtons.OK, MessageBoxIcon.Information); } void ApprovedRevision_Click(object sender, EventArgs e) { bool superceded = false; MenuItem mi = sender as MenuItem; if (mi == null) return; RevisionInfo ri = mi.Tag as RevisionInfo; { MenuItem mip = mi.Parent as MenuItem; //B2021-086 Added the check for the last revision stage is an Approved stage if ((ri.RevisionID < int.Parse(mip.Parent.Tag.ToString())) && ri.LatestVersion.MyStage.IsApproved!=0) superceded = true; } vlnTreeViewPdfArgs args = new vlnTreeViewPdfArgs(Volian.Base.Library.TmpFile.CreateFileName(ProcedureInfo.Get(ri.ItemID).PDFNumber), ri.LatestVersion.PDF, superceded ? "Superceded" : ""); OnViewPDF(sender, args); // System.Diagnostics.Process pp = System.Diagnostics.Process.Start(GetDocPdf(ri, superceded)); } void MultiUnitApprovedRevision_Click(object sender, EventArgs e) { bool superceded = false; MenuItem mi = sender as MenuItem; if (mi == null) return; //RevisionInfo ri = mi.Tag as RevisionInfo; RevisionInfo ri = RevisionInfo.Get(int.Parse(mi.Tag.ToString())); { MenuItem mip = mi.Parent as MenuItem; //B2021-086 Added the check for the last revision stage is an Approved stage if ((ri.RevisionID < int.Parse(mip.Parent.Tag.ToString())) && ri.LatestVersion.MyStage.IsApproved != 0) superceded = true; } ItemInfo ii = ItemInfo.Get(ri.ItemID); ii.MyDocVersion.DocVersionConfig.SelectedSlave = ri.MyConfig.Applicability_Index; vlnTreeViewPdfArgs args = new vlnTreeViewPdfArgs(Volian.Base.Library.TmpFile.CreateFileName(ProcedureInfo.Get(ri.ItemID).PDFNumber), ri.LatestVersion.PDF, superceded ? "Superceded" : ""); OnViewPDF(sender, args); // System.Diagnostics.Process pp = System.Diagnostics.Process.Start(GetDocPdf(ri, superceded)); } void SummaryOfChanges_Click(object sender, EventArgs e) { MenuItem mi = sender as MenuItem; if (mi == null) return; RevisionInfo ri = mi.Tag as RevisionInfo; vlnTreeViewPdfArgs args = new vlnTreeViewPdfArgs(Volian.Base.Library.TmpFile.CreateFileName(ProcedureInfo.Get(ri.ItemID).PDFNumber + " Summary of Changes"), ri.LatestVersion.SummaryPDF, ""); OnViewPDF(sender, args); // System.Diagnostics.Process pps = System.Diagnostics.Process.Start(GetDocSummaryPdf(ri)); } void MultiUnitSummaryOfChanges_Click(object sender, EventArgs e) { MenuItem mi = sender as MenuItem; if (mi == null) return; //RevisionInfo ri = mi.Tag as RevisionInfo; RevisionInfo ri = RevisionInfo.Get(int.Parse(mi.Tag.ToString())); ItemInfo ii = ItemInfo.Get(ri.ItemID); ii.MyDocVersion.DocVersionConfig.SelectedSlave = ri.MyConfig.Applicability_Index; vlnTreeViewPdfArgs args = new vlnTreeViewPdfArgs(Volian.Base.Library.TmpFile.CreateFileName(ProcedureInfo.Get(ri.ItemID).PDFNumber + " Summary of Changes"), ri.LatestVersion.SummaryPDF, ""); OnViewPDF(sender, args); // System.Diagnostics.Process pps = System.Diagnostics.Process.Start(GetDocSummaryPdf(ri)); } //C2018-026 show notes entered during approval or workflow stage private void ViewRevisonStageNotes_Click(object sender, EventArgs e) { MenuItem mi = sender as MenuItem; if (mi == null) return; RevisionInfo ri = mi.Tag as RevisionInfo; FlexibleMessageBox.Show(ri.Notes, "Revison Stage Notes", MessageBoxButtons.OK); } //private string GetDocPdf(RevisionInfo ri, bool superceded) //{ // string fileName = Volian.Base.Library.TmpFile.CreateFileName(ItemInfo.Get(ri.ItemID).DisplayNumber); // FileInfo fi = new FileInfo(VlnSettings.TemporaryFolder + @"\" + fileName); // FileStream fs = fi.Create(); // byte[] myPdf = ri.LatestVersion.PDF; // if (myPdf != null) fs.Write(myPdf, 0, myPdf.Length); // fs.Close(); // if (superceded) // AddSupercededWatermark(VlnSettings.TemporaryFolder + @"\" + fileName); // return VlnSettings.TemporaryFolder + @"\" + fileName; //} //private void AddSupercededWatermark(string p) //{ // MessageBox.Show("superceded"); //} //private string GetDocSummaryPdf(RevisionInfo ri) //{ // string fileName = Volian.Base.Library.TmpFile.CreateFileName(ItemInfo.Get(ri.ItemID).DisplayNumber + " Summary of Changes"); // FileInfo fi = new FileInfo(VlnSettings.TemporaryFolder + @"\" + fileName); // FileStream fs = fi.Create(); // byte[] myPdf = ri.LatestVersion.SummaryPDF; // if (myPdf != null) fs.Write(myPdf, 0, myPdf.Length); // fs.Close(); // return VlnSettings.TemporaryFolder + @"\" + fileName; //} private bool AddToInsertMenu(ItemInfo ii, int ba) // 0 = before, 1 = after { // set up insert buttons based on format bool retB = true; E_AccStep? actable = 0; StepData sd = ii.FormatStepData; if (sd != null) actable = sd.StepEditData.AcTable; if (actable == null) actable = 0; return (ba == 0) ? !ii.IsRNOPart && (actable & E_AccStep.AddingPrev) > 0 : !ii.IsRNOPart && (actable & E_AccStep.AddingNext) > 0; } private void Menu_Paste(VETreeNode tn, ContextMenu cm) { #region Menu_Paste method // Find what's in paste buffer & determine whether the paste can occur for the selected node. ItemInfo iiClipboard = OnClipboardStatus(this, new vlnTreeEventArgs(tn)); if (iiClipboard != null) { // can it be pasted at current node. // for now (Jan 2016 - initial implementation of enhanced document support) do NOT paste // any items that have enhanced data associated with it unless pasting within an enhanced source item. // The reason is that code would need to handle clearing/setting the pasted enhanced config which // becomes very complicated. // For all enhanced comments in code use the following: // 'source' is Procedures, for example EOP procedures (that has config's myenhanceddocuments pointing to enhanced, i.e. not source) // 'enhanced' is enhanced procedures, for example Background/deviation (that has config's myenhanceddocuments pointing back to source) // 'non' or 'not enhanced', anything other than 'source' or 'enhanced' (has no myenhanceddocuments on config) // 'from' is object copied // 'to' is object where paste was selected from #region Menu_Paste_ToDocVersion if (tn.VEObject as DocVersionInfo != null) // paste item must be a proc { if (iiClipboard.IsProcedure) { // In order to paste a procedure into a docVersion: NOTE that an 'enhanced' procedure cannot be in paste buffer! // 1) 'to' & 'from' both 'non', i.e. Neither can have enhanced config data (be source or enhanced) // 2) 'to' docVersion is 'source' and 'from' procedure is 'non' (has no MyEnhancedDocuments) // 3) 'to' docversion is 'source' and 'from' procedure is within this docversion // 4) 'to' docVersion is 'enhanced' and 'from' procedure is not bool canPaste = false; DocVersionInfo dvi = tn.VEObject as DocVersionInfo; DocVersionConfig dvc = dvi.DocVersionConfig; bool docVersionIsEnhanced = dvc.MyEnhancedDocuments != null && dvc.MyEnhancedDocuments.Count > 0 && dvc.MyEnhancedDocuments[0].Type == 0; bool docVersionIsSource = dvc.MyEnhancedDocuments != null && dvc.MyEnhancedDocuments.Count > 0 && dvc.MyEnhancedDocuments[0].Type != 0; ProcedureInfo pi = iiClipboard as ProcedureInfo; ProcedureConfig pcfg = pi.MyConfig as ProcedureConfig; bool procIsSource = pcfg.MyEnhancedDocuments != null && pcfg.MyEnhancedDocuments.Count > 0 && pcfg.MyEnhancedDocuments[0].Type != 0; if (!docVersionIsEnhanced && !docVersionIsSource && !procIsSource) canPaste = true; else if (docVersionIsSource && !procIsSource) canPaste = true; else if (docVersionIsSource) canPaste = (!procIsSource || (iiClipboard.MyDocVersion.ItemID == dvi.ItemID)); else if (docVersionIsEnhanced) { // B2024-028 Do not allow paste of non-enhanced into enhanced set // (consistent with paste before/after, i.e. don't allow) canPaste = false; cm.MenuItems.Add("CANNOT PASTE HERE, Click for more information...", new EventHandler(mi_Click)); } if (iiClipboard.IsRtfRaw) canPaste = false; // never paste an equation. if (canPaste) cm.MenuItems.Add("Paste Procedure", new EventHandler(mi_Click)); } #endregion } else { ItemInfo iiPasteHere = tn.VEObject as ItemInfo; if (iiPasteHere == null) return; bool okToReplace = iiClipboard.ItemID != iiPasteHere.ItemID; if (iiPasteHere != null) { SectionInfo si = (tn.VEObject as SectionInfo != null) ? tn.VEObject as SectionInfo : null; #region Menu_Paste_ToFromProcedure if (iiPasteHere.IsProcedure && iiClipboard.IsProcedure) // procedure can be pasted before/replace/after { // Enhanced considerations, in order to paste a procedure around another procedure: NOTE that an 'enhanced' procedure cannot be in paste buffer! // 1) 'to' & 'from' both 'non', i.e. Neither can have enhanced config data (be source or enhanced) // can do Before/After/Replace // 2) 'to' is 'non', 'from' is 'source' // cannot do any // 3) 'to' procedure is 'source' and 'from' procedure is 'non' (has no MyEnhancedDocuments) // can do Before/After - no links exist in pasted procedure. // cannot do Replace // 4) 'to' procedure is 'source' and 'from' procedure is same docversion 'source' // can do Before/After/Replace // 5) 'to' procedure is 'source' and 'from' procedure is different docversion 'source' // cannot do any // 6) 'to' procedure is 'enhanced' and 'from' procedure is 'source' // cannot do any ProcedureConfig pcToCfg = iiPasteHere.MyConfig as ProcedureConfig; ProcedureConfig pcFromCfg = iiClipboard.MyConfig as ProcedureConfig; bool prToIsEnhanced = iiPasteHere.IsEnhancedProcedure; bool prToIsSource = pcToCfg.MyEnhancedDocuments != null && pcToCfg.MyEnhancedDocuments.Count > 0 && pcToCfg.MyEnhancedDocuments[0].Type != 0; bool prFromIsEnhanced = iiClipboard.IsEnhancedProcedure; bool prFromIsSource = pcFromCfg.MyEnhancedDocuments != null && pcFromCfg.MyEnhancedDocuments.Count > 0 && pcFromCfg.MyEnhancedDocuments[0].Type != 0; bool prCanPaste = false; if (!prToIsEnhanced && !prToIsSource && !prFromIsEnhanced && !prFromIsSource) prCanPaste = true; // 1) // else if ((!prToIsEnhanced && !prToIsSource) && prFromIsSource) prCanPaste = false; // 2) commented out because already set to false else if (prToIsSource && !prFromIsEnhanced && !prFromIsSource) // 3) { prCanPaste = true; okToReplace = false; } else if (prToIsSource && iiPasteHere.MyDocVersion.VersionID == iiClipboard.MyDocVersion.VersionID) prCanPaste = true; // 4) //else if (prToIsSource && iiPasteHere.MyDocVersion.VersionID != iiClipboard.MyDocVersion.VersionID) prCanPaste = false; // 5) commented out because already set to false //else if (prToIsEnhanced && prFromIsSource) prCanPaste = false; // 6)commented out because already set to false if (iiClipboard.IsRtfRaw) prCanPaste = okToReplace = prCanPaste = false; // never paste an equation. if (prCanPaste) cm.MenuItems.Add("Paste Procedure Before", new EventHandler(mi_Click)); if (okToReplace && prCanPaste) cm.MenuItems.Add("Replace Existing Procedure", new EventHandler(mi_Click)); if (prCanPaste) cm.MenuItems.Add("Paste Procedure After", new EventHandler(mi_Click)); // B2017-243 added the following two Cannot Paste menu items when dealing with enhanced documents // when then user selects these menu items a message box will appear giving more information as to why it cannot be pasted if (!prCanPaste) { if (prToIsEnhanced) cm.MenuItems.Add("CANNOT PASTE HERE, Click for more information...", new EventHandler(mi_Click)); else cm.MenuItems.Add("CANNOT PASTE HERE. Click for more information...", new EventHandler(mi_Click)); } } #endregion #region Menu_Paste_ToProcedureFromSection else if (iiPasteHere.IsProcedure && iiClipboard.IsSection) // procedure must have sections only { // In order to paste a section into a procedure: NOTE that an 'enhanced' section cannot be in paste buffer! // 1) 'to' & 'from' both 'non', i.e. Neither can have enhanced config data (be source or enhanced) // can do // 2) 'to' procedure is 'source' and 'from' section is 'non' (has no MyEnhancedDocuments) // can do // 3) 'to' procedure is 'source' and 'from' section is same source ProcedureConfig pccToCfg = iiPasteHere.MyConfig as ProcedureConfig; SectionConfig scFromCfg = iiClipboard.MyConfig as SectionConfig; bool prToIsEnhanced = iiPasteHere.IsEnhancedProcedure; bool prToIsSource = pccToCfg.MyEnhancedDocuments != null && pccToCfg.MyEnhancedDocuments.Count > 0 && pccToCfg.MyEnhancedDocuments[0].Type != 0; bool scFromIsEnhanced = iiClipboard.IsEnhancedSection; bool scFromIsSource = scFromCfg.MyEnhancedDocuments != null && scFromCfg.MyEnhancedDocuments.Count > 0 && scFromCfg.MyEnhancedDocuments[0].Type != 0; bool scCanPaste = false; if (!prToIsEnhanced && !prToIsSource && !scFromIsEnhanced && !scFromIsSource) scCanPaste = true; // 1) else if (prToIsSource && !scFromIsEnhanced && !scFromIsSource) scCanPaste = true; else if (prToIsSource && iiPasteHere.MyDocVersion.VersionID == iiClipboard.MyDocVersion.VersionID) scCanPaste = true; // 3) if (iiClipboard.IsRtfRaw) scCanPaste = false; // never paste an equation. if (scCanPaste) cm.MenuItems.Add("Paste Section", new EventHandler(mi_Click)); } #endregion #region Menu_Paste_ToSectionFromSection else if (iiPasteHere.IsSection && iiClipboard.IsSection) { // Enhanced considerations, in order to paste a section around another section: NOTE that an 'enhanced' section cannot be in paste buffer! // 1) 'to' & 'from' both 'non', i.e. Neither can have enhanced config data (be source or enhanced) // can do Before/After/Replace // 2) 'to' section is 'source' and 'from' section is 'non' (has no MyEnhancedDocuments) // can do Before/After - no links exist in pasted section. // cannot do Replace // 3) 'to' section is 'source' and 'from' section is same docversion 'source' // can do Before/After/Replace SectionConfig secToCfg = iiPasteHere.MyConfig as SectionConfig; SectionConfig secFromCfg = iiClipboard.MyConfig as SectionConfig; bool secToIsEnhanced = iiPasteHere.IsEnhancedSection; bool secToIsSource = secToCfg.MyEnhancedDocuments != null && secToCfg.MyEnhancedDocuments.Count > 0 && secToCfg.MyEnhancedDocuments[0].Type != 0; bool secFromIsEnhanced = iiClipboard.IsEnhancedSection; bool secFromIsSource = secFromCfg.MyEnhancedDocuments != null && secFromCfg.MyEnhancedDocuments.Count > 0 && secFromCfg.MyEnhancedDocuments[0].Type != 0; bool secCanPaste = false; if (!secToIsEnhanced && !secToIsSource && !secFromIsEnhanced && !secFromIsSource) secCanPaste = true; // 1) else if (secToIsSource && !secFromIsEnhanced && !secFromIsSource) // 2) { secCanPaste = true; okToReplace = false; } else if (secToIsSource && iiPasteHere.MyDocVersion.VersionID == iiClipboard.MyDocVersion.VersionID) secCanPaste = true; // 3) if (iiClipboard.IsRtfRaw) secCanPaste = okToReplace = false; // never paste an equation. if (secCanPaste) cm.MenuItems.Add("Paste Section Before", new EventHandler(mi_Click)); if (okToReplace && secCanPaste) cm.MenuItems.Add("Replace Existing Section", new EventHandler(mi_Click)); if (secCanPaste) cm.MenuItems.Add("Paste Section After", new EventHandler(mi_Click)); if (si.ActiveFormat.PlantFormat.FormatData.SectData.UseMetaSections && iiPasteHere.IsStepSection && iiClipboard.IsStepSection) { // only paste a subsection if the paste here is an empty section or has // subsections. if (!iiClipboard.IsRtfRaw && (iiPasteHere.Sections == null || iiPasteHere.Sections.Count > 0)) cm.MenuItems.Add("Paste Subsection", new EventHandler(mi_Click)); } } #endregion #region Menu_Paste_ToSectionFromStep else if (iiPasteHere.IsStepSection && iiClipboard.IsStep) { // In order to paste a step into a section: NOTE that an 'enhanced' step cannot be in paste buffer! // 1) 'to' & 'from' both 'non', i.e. Neither can have enhanced config data (be source or enhanced) // can do // 2) 'to' section is 'source' and 'from' step is 'non' (has no MyEnhancedDocuments) // can do // 3) 'to' section is 'source' and 'from' section is same source SectionConfig secToCfg = iiPasteHere.MyConfig as SectionConfig; StepConfig stpFromCfg = iiClipboard.MyConfig as StepConfig; bool secToIsEnhanced = iiPasteHere.IsEnhancedSection; bool secToIsSource = secToCfg.MyEnhancedDocuments != null && secToCfg.MyEnhancedDocuments.Count > 0 && secToCfg.MyEnhancedDocuments[0].Type != 0; bool stpFromIsEnhanced = iiClipboard.IsEnhancedStep; bool stpFromIsSource = stpFromCfg.MyEnhancedDocuments != null && stpFromCfg.MyEnhancedDocuments.Count > 0 && stpFromCfg.MyEnhancedDocuments[0].Type != 0; bool stpCanPaste = false; if (!secToIsEnhanced && !secToIsSource && !stpFromIsEnhanced && !stpFromIsSource) stpCanPaste = true; // 1) else if (secToIsSource && !stpFromIsEnhanced && !stpFromIsSource) stpCanPaste = true; // 2) else if (secToIsSource && iiPasteHere.MyDocVersion.VersionID == iiClipboard.MyDocVersion.VersionID) stpCanPaste = true; // 3) if (iiClipboard.IsRtfRaw) stpCanPaste = false; // never paste an equation. if (stpCanPaste) cm.MenuItems.Add("Paste Step", new EventHandler(mi_Click)); } #endregion #region Menu_Paste_ToStepFromStep else if (iiPasteHere.IsStep && iiClipboard.IsStep) { // Enhanced considerations, in order to paste a step around another step: NOTE that an 'enhanced' section cannot be in paste buffer! // 1) 'to' & 'from' both 'non', i.e. Neither can have enhanced config data (be source or enhanced) // can do Before/After/Replace // 2) 'to' step is 'source' and 'from' step is 'non' (has no MyEnhancedDocuments) // can do Before/After - no links exist in pasted step, treat like an insert.. // cannot do Replace // 3) 'to' step is 'source' and 'from' step is same docversion 'source' // can do Before/After/Replace (Note that replace is not allowed per B2017-183) StepConfig stpToCfg = iiPasteHere.MyConfig as StepConfig; StepConfig stpFromCfg = iiClipboard.MyConfig as StepConfig; bool stpToIsEnhanced = iiPasteHere.IsEnhancedStep; bool stpToIsSource = stpToCfg.MyEnhancedDocuments != null && stpToCfg.MyEnhancedDocuments.Count > 0 && stpToCfg.MyEnhancedDocuments[0].Type != 0; bool stpFromIsEnhanced = iiClipboard.IsEnhancedStep; bool stpFromIsSource = stpFromCfg.MyEnhancedDocuments != null && stpFromCfg.MyEnhancedDocuments.Count > 0 && stpFromCfg.MyEnhancedDocuments[0].Type != 0; bool stpCanPaste = false; if (!stpToIsEnhanced && !stpToIsSource && !stpFromIsEnhanced && !stpFromIsSource) stpCanPaste = true; // 1) else if (stpToIsSource && !stpFromIsEnhanced && !stpFromIsSource) // 2) { stpCanPaste = true; okToReplace = false; } else if (stpToIsSource && iiPasteHere.MyDocVersion.VersionID == iiClipboard.MyDocVersion.VersionID) // 3 { stpCanPaste = true; if (stpFromIsSource) okToReplace = false; // B2017-183: don't allow a replace to source steps } if (iiClipboard.IsRtfRaw) stpCanPaste = false; // never paste an equation. if (stpCanPaste && AddToInsertMenu(iiPasteHere, 0)) cm.MenuItems.Add("Paste Step Before", new EventHandler(mi_Click)); if (stpCanPaste && okToReplace) cm.MenuItems.Add("Replace Existing Step", new EventHandler(mi_Click)); if (stpCanPaste && AddToInsertMenu(iiPasteHere, 1)) cm.MenuItems.Add("Paste Step After", new EventHandler(mi_Click)); } #endregion } } } #endregion menupaste } //jcb multiunit void miMultiUnit_Click(object sender, EventArgs e) { MenuItem mi = sender as MenuItem; MenuItem mip = mi.Parent as MenuItem; switch (mip.Text) { case "Print": OnPrintProcedure(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0, mi.Text, (int)mi.Tag)); break; case "Quick Print": OnQPrintProcedure(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0, mi.Text, (int)mi.Tag)); break; case "Print Section": OnPrintSection(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0, mi.Text, (int)mi.Tag)); break; case "Print All Procedures for": OnPrintAllProcedures(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0,mi.Text,(int)mi.Tag)); break; case "Approve": OnApproveProcedure(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0, mi.Text, (int)mi.Tag)); break; case "Approve All Procedures for": OnApproveAllProcedures(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0, mi.Text, (int)mi.Tag)); break; case "Approve Some Procedures for": OnApproveSomeProcedures(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0, mi.Text, (int)mi.Tag)); break; case "Create Continuous Action Summary": OnCreateContinuousActionSummary(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null,0,mi.Text,(int)mi.Tag)); break; case "Create Time Critical Action Summary": OnCreateTimeCriticalActionSummary(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null,0,mi.Text,(int)mi.Tag)); break; default: if (mip.Text.StartsWith("Showing Change Bars Starting")) OnSelectDateToStartChangeBars(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0)); else FlexibleMessageBox.Show(string.Format("Unrecognized Menu Item '{0}'", mip.Text)); break; } } //end jcb multiunit private bool CheckForValidEnhLink(ItemInfo prc) // Check if this procedure has valid link { EnhancedDocuments eds = prc.GetMyEnhancedDocuments(); foreach (EnhancedDocument ed in eds) // only unlink those that are selected { ItemInfo lprc = ItemInfo.Get(ed.ItemID); EnhancedDocuments edsl = lprc.GetMyEnhancedDocuments(); foreach (EnhancedDocument edl in edsl) if (edl.ItemID == prc.ItemID) return true; } return false; } // B2022-049: Copy/paste of enhanced procedure and bad links between source and enhanced // Handle menu selection for unlinking the source/enhanced OR if not valid links, just the procedure selected void miEnhanced_Click(object sender, EventArgs e) { MenuItem mi = sender as MenuItem; VETreeNode tnprc = SelectedNode as VETreeNode; ItemInfo selprc = tnprc.VEObject as ItemInfo; EnhancedDocuments seleds = selprc.GetMyEnhancedDocuments(); // if tag on menu = -1, it is a single document, no need to loop. This can be from either the source or enhanced. if ((int)mi.Tag == -1) { bool hasValidConnectingProc = CheckForValidEnhLink(selprc); if (FlexibleMessageBox.Show(this, "Do you want to unlink the Enhanced procedure from its Source?", "Confirm Procedure Unlink", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { if (selprc.IsEnhancedProcedure) { selprc.DoUnlinkEnhanced(selprc, 0, !hasValidConnectingProc); // if no valid linked: enhtype = 0 since this an enhanced doc is getting unlinked } else // from source { // if valid connection, make call from the linked enhanced, otherwise just unlink the source only if (hasValidConnectingProc) { ItemInfo lprc = ItemInfo.Get(seleds[0].ItemID); lprc.DoUnlinkEnhanced(lprc, 0, !hasValidConnectingProc); } else selprc.DoUnlinkEnhanced(selprc, seleds[0].Type, !hasValidConnectingProc); } } } else { // The following code is run if selection made from source. There may be moore than one enhanced, for example background // and deviation if (FlexibleMessageBox.Show(this, "Do you want to unlink the selected Enhanced procedure(s) from the Source procedure?", "Confirm Procedure Unlink", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { int k = 1; foreach (EnhancedDocument ed in seleds) // only unlink those that are selected { if (k == (int)mi.Tag || (int)mi.Tag == 0) { ItemInfo lprc = ItemInfo.Get(ed.ItemID); bool hasValidConnectingProc = CheckForValidEnhLink(lprc); // if there is a valid connection, unlink both. Otherwise, just unlink this selected procedure. if (hasValidConnectingProc) lprc.DoUnlinkEnhanced(lprc, ed.Type, !hasValidConnectingProc); else selprc.DoUnlinkEnhanced(selprc, ed.Type, !hasValidConnectingProc); } k++; } } } } void mi_Click(object sender, EventArgs e) { MenuItem mi = sender as MenuItem; if (mi == null) return; // B2019-076: make folder/working draft level proc set specific info consistent (various places in this file were changed from Folder Specific & Working Draft Specific) if (mi.Text == "Procedure Set Specific Information" || mi.Text == "Folder Specific Information") // C2020-008: change to 'Folder' { VETreeNode tn = SelectedNode as VETreeNode; OnNodeSI(this, new vlnTreeEventArgs(tn, null, 0)); return; } if (mi.Text.StartsWith("Collapse")) { CollapseProcedures(); return; } if (mi.Text == "Print Transition Report") { OnPrintTransitionReport(this, new vlnTreeEventArgs(SelectedNode as VETreeNode)); return; } if (mi.Text == "Export Procedure Set" || mi.Text == "Export Procedure") { OnExportImportProcedureSets(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0)); return; } if (mi.Text == "Import Procedure Set" || mi.Text == "Import Procedure") { OnExportImportProcedureSets(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 1)); return; } if (mi.Text.StartsWith("Procedure Checked Out to") || mi.Text.StartsWith("Document Checked Out to")) { OnProcedureCheckedOutTo(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0)); return; } switch (mi.Text) { case "Print Section": VETreeNode tn2 = SelectedNode as VETreeNode; OnPrintSection(this, new vlnTreeEventArgs(tn2 as VETreeNode, null, 0)); break; case "Open": OpenNode(); break; case "Insert Folder Before": tv_NodeNew(MenuSelections.FolderBefore); break; case "Insert Folder After": tv_NodeNew(MenuSelections.FolderAfter); break; case "New Folder": SelectedNode.Expand(); tv_NodeNew(MenuSelections.Folder); break; case "Create Working Draft": SelectedNode.Expand(); tv_NodeNew(MenuSelections.DocVersion); break; case "New Procedure": SelectedNode.Expand(); tv_NodeNew(MenuSelections.Procedure); break; case "Insert Procedure Before": tv_NodeNew(MenuSelections.ProcedureBefore); break; case "Insert Procedure After": tv_NodeNew(MenuSelections.ProcedureAfter); break; case "Remove Change Ids": tv_RemoveChgIds(); break; case "New Section": case "New Subsection": SelectedNode.Expand(); tv_NodeNew(MenuSelections.Section); break; case "Insert Section Before": tv_NodeNew(MenuSelections.SectionBefore); break; case "Insert Section After": tv_NodeNew(MenuSelections.SectionAfter); break; case "Insert Step Before": tv_NodeNew(MenuSelections.StepBefore); break; case "Insert Step After": tv_NodeNew(MenuSelections.StepAfter); break; case "New Step": SelectedNode.Expand(); tv_NodeNew(MenuSelections.Step); break; case "Copy"://Copy the selected node tv_NodeCopy(); break; // lots of paste options: case "Paste Procedure": case "Paste Procedure Before": case "Paste Procedure After": case "Paste Section": case "Paste Section Before": case "Replace Existing Section": case "Paste Section After": case "Paste Step": case "Paste Step Before": case "Replace Existing Step": case "Paste Step After": case "Paste Subsection": tv_NodePaste(mi.Text); break; case "Replace Existing Procedure": DialogResult ovewriteEx = FlexibleMessageBox.Show("This will overwrite the selected procedure with then one you copied, would you like to overwrite it?\r\n\r\nSelecting 'Cancel' will cancel the paste action.", "Overwrite the procedure?", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);// == DialogResult.Yes; if (ovewriteEx == DialogResult.Cancel) break; else { TreeNode treenodeDirectory = SelectedNode.Parent; tv_NodePaste(mi.Text); break; } case "Delete": if (tv_NodeDelete()) { TreeNode myParent = SelectedNode.Parent; SelectedNode.Remove(); SelectedNode = myParent; OnNodeSelect(this, new vlnTreeEventArgs(SelectedNode)); } break; case "Incoming Transitions": // C2020-033: Support the menu item to bring up Search/Incoming Transitions panel VETreeNode tnx = SelectedNode as VETreeNode; ItemInfo iii = tnx.VEObject as ItemInfo; if (iii != null) { this.Cursor = Cursors.WaitCursor; // B2023-103 add spinner when searching for incoming transitions OnSearchIncTransIn(this, new vlnTreeItemInfoEventArgs(iii)); this.Cursor = Cursors.Default; } break; case "Properties..."://Show the properties for the selected node SetLastValues((VETreeNode)SelectedNode); SetupNodeProperties(); break; case "Procedure Specific Information": VETreeNode tn = SelectedNode as VETreeNode; ProcedureInfo pi = tn.VEObject as ProcedureInfo; if (pi != null) { using (Procedure proc = pi.Get()) { OnNodePSI(this, new vlnTreeEventArgs(tn, null, 0)); } } break; case "Print": OnPrintProcedure(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0)); break; case "Quick Print": OnQPrintProcedure(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0)); break; case "Print All Procedures": OnPrintAllProcedures(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0)); break; case "Approve": OnApproveProcedure(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0)); break; case "Approve All Procedures": OnApproveAllProcedures(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0)); break; case "Approve Some Procedures": OnApproveSomeProcedures(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0)); break; case "Report All Procedures Inconsistencies": OnReportAllProceduresInconsistencies(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0)); break; case "Refresh Checked Out Procedures": OnRefreshCheckedOutProcedures(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0)); break; case "Run RO Editor": RunROEditor(SelectedNode as VETreeNode); break; case "Update RO Values": UpdateROValues(SelectedNode as VETreeNode); break; case "Create Continuous Action Summary": OnCreateContinuousActionSummary(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null,0)); break; // F2022-024 Time Critical Action Summary case "Create Time Critical Action Summary": OnCreateTimeCriticalActionSummary(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null,0)); break; // B2017-243 added the following two Cannot Paste items when dealing with enhanced documents // when then user selects these menu items a message box will appear giving more information as to why it cannot be pasted case "CANNOT PASTE HERE. Click for more information...": FlexibleMessageBox.Show("You have copied a document that is linked to an Enhanced Document.\n\n" + "It can only be pasted before or after another document, within the set, that is linked to an Enhanced Document.", "Cannot Paste Here"); break; case "CANNOT PASTE HERE, Click for more information...": // B2024-028 clarify message FlexibleMessageBox.Show("You have copied a document that is NOT linked to an Enhanced Document.\n\n" + "You cannot paste a Non-Enhanced Procedure into an Enhanced Procedure Set.", "Cannot Paste Here"); break; //case "Check Out Procedure Set": // CheckOutDocVersion(SelectedNode as VETreeNode); // break; //case "Check In Procedure Set": // CheckInDocVersion(SelectedNode as VETreeNode); // break; default: if (mi.Text.StartsWith("Showing Change Bars Starting")) OnSelectDateToStartChangeBars(this, new vlnTreeEventArgs(SelectedNode as VETreeNode, null, 0)); else FlexibleMessageBox.Show(string.Format("Unrecognized Menu Item '{0}'", mi.Text)); break; } } private bool _doingCollapseNode = false; // B2016-058 when collapse is done, it always calls the drag node event which doesn't appear to be needed private void CollapseProcedures() { CollapseProcedures(SelectedNode as VETreeNode); } private void CollapseProcedures(VETreeNode tn) { if (tn == null) return; if (!tn.IsExpanded) return; if (tn.VEObject.GetType() == typeof(ProcedureInfo)) { tn.Collapse(); _doingCollapseNode = true; // B2016-058 this will prevent a Drag Node error when collapsing an RNOs, Cautions, or Notes tree node return; } foreach (VETreeNode tnc in tn.Nodes) CollapseProcedures(tnc); if (tn.VEObject as DocVersionInfo == null && tn.VEObject as FolderInfo == null) tn.Collapse(); _doingCollapseNode = true; // B2016-058 this will prevent a Drag Node error when collapsing an RNOs, Cautions, or Notes tree node } private void tv_RemoveChgIds() { //Console.WriteLine("HERE"); // add code/query to clear change ids in config. } private Dictionary MyCheckedOutDocVersions; private void CheckInDocVersion(VETreeNode tn) { DocVersionInfo MyDVI = tn.VEObject as DocVersionInfo; MySessionInfo.CheckInItem(MyCheckedOutDocVersions[MyDVI.VersionID]); MyCheckedOutDocVersions.Remove(MyDVI.VersionID); } private void UpdateROValues(VETreeNode tn) { InitialProgressBarMessage = "Updating ROs"; DocVersionInfo MyDVI = tn.VEObject as DocVersionInfo; // use rodb directory path of the first rofst for the this document version. Later, will need // to modify code to get which one (when there is more than one) if (MyDVI.DocVersionAssociations.Count < 1) { FlexibleMessageBox.Show("Error Updating ro.fst. No associated ro.fst", "No ROs associated"); //B2017-125 added title to messagebox FinalProgressBarMessage = "No ROs associated"; return; } ROFstInfo roFstInfo = MyDVI.DocVersionAssociations[0].MyROFst; string rofstPath = roFstInfo.MyRODb.FolderPath + @"\ro.fst"; if (!File.Exists(rofstPath)) { FlexibleMessageBox.Show("No existing ro.fst in path " + roFstInfo.MyRODb.FolderPath + ". Check for invalid path", "No existing RO.FST"); //B2017-125 added title to messagebox FinalProgressBarMessage = "No existing RO.FST"; return; } FileInfo fiRofst = new FileInfo(rofstPath); if (roFstInfo.DTS == fiRofst.LastWriteTimeUtc) { FlexibleMessageBox.Show("ro.fst files are same for path " + roFstInfo.MyRODb.FolderPath + ", import of that ro.fst will not be done", "RO.FST up to date"); //B2017-125 added title to messagebox FinalProgressBarMessage = "RO.FST up to date"; return; } if (roFstInfo.DTS > fiRofst.LastWriteTimeUtc) { FlexibleMessageBox.Show("Cannot copy older ro.fst from " + roFstInfo.MyRODb.FolderPath + ", import of that ro.fst will not be done", "Older RO.FST"); //B2017-125 added title to messagebox FinalProgressBarMessage = "Older RO.FST"; return; } string message = string.Empty; if (!MySessionInfo.CanCheckOutItem(MyDVI.VersionID, CheckOutType.DocVersion, ref message)) { FlexibleMessageBox.Show(this, message, "Working Draft Has Items Already Checked Out", MessageBoxButtons.OK, MessageBoxIcon.Warning); FinalProgressBarMessage = "Cannot check-out Working Draft"; return; } Cursor = Cursors.WaitCursor; // C2023-002: move wait cursor after check out error int ownerid = MySessionInfo.CheckOutItem(MyDVI.VersionID, CheckOutType.DocVersion); using (DocVersion dv = DocVersion.Get(MyDVI.VersionID)) { swROUpdate = new System.IO.StreamWriter(ROFstInfo.ROUpdateResultsPath(MyDVI)); // RO changes placed in file in the Documents\VEPROMS folder // B2022-026 RO Memory Reduction code - first load the new ro.fst so that we can assign the ROTableUpdate event to the correct roFstInfo if (dv.ROfstLoadingFigures || dv.NewerRoFst) // B2017-125 see if loading figures was completed { // only load the RO.fst ROFstInfo.UpdateRoFst(roFstInfo.MyRODb, dv, roFstInfo, DoProgressBarRefresh); roFstInfo = MyDVI.DocVersionAssociations[0].MyROFst; } roFstInfo.ROTableUpdate += new ROFstInfoROTableUpdateEvent(roFstInfo_ROTableUpdate); ContentInfo.StaticContentInfoChange += ContentInfo_StaticContentInfoChange; // write changes to a text file ROFst newrofst = ROFstInfo.RefreshROFst(dv, roFstInfo, DoProgressBarRefresh, null); swROUpdate.Close(); ContentInfo.StaticContentInfoChange -= ContentInfo_StaticContentInfoChange; roFstInfo.ROTableUpdate -= new ROFstInfoROTableUpdateEvent(roFstInfo_ROTableUpdate); OnTabDisplay(this, new StepPanelTabDisplayEventArgs("DisplayROUpdateROFST")); } MySessionInfo.CheckInItem(ownerid); Cursor = Cursors.Default; FinalProgressBarMessage = "ROs values updated"; } private System.IO.StreamWriter swROUpdate; // write the RO reference changes to a text file, include the old/new text, location, and the itemid of the step element void ContentInfo_StaticContentInfoChange(object sender, StaticContentInfoEventArgs args) { if (args.Type == "RO") swROUpdate.Write(string.Format("Fixed Referenced Object for {1}({4}){0}Old Text: {2}{0}New Text: {3}{0}{0}", Environment.NewLine, (sender as ItemInfo).ShortPath, args.OldValue, args.NewValue, (sender as ItemInfo).ItemID)); } private ProgressBarItem _ProgressBar=null; public ProgressBarItem ProgressBar { get { return _ProgressBar; } set { _ProgressBar = value; } } private void DoProgressBarRefresh(int value, int max, string text) { if (ProgressBar == null) return; ProgressBar.Maximum = max; ProgressBar.Value = value; ProgressBar.Text = text; Application.DoEvents(); } private string InitialProgressBarMessage { set { if (ProgressBar == null) return; ProgressBar.Value = 0; ProgressBar.Maximum = 100; ProgressBar.Text = value; Application.DoEvents(); } } private string FinalProgressBarMessage { set { if (ProgressBar == null) return; ProgressBar.Value = 100; ProgressBar.Maximum = 100; ProgressBar.Text = value; Application.DoEvents(); } } public List roFstInfo_ROTableUpdate(object sender, ROFstInfoROTableUpdateEventArgs args) { return VlnFlexGrid.ROTableUpdate(sender, args); //string xml = null; //string srchtxt = null; //using (VlnFlexGrid myGrid = new VlnFlexGrid()) //{ // using (StringReader sr = new StringReader(args.OldGridXml)) // { // myGrid.ReadXml(sr); // myGrid.KeyActionTab = C1.Win.C1FlexGrid.KeyActionEnum.MoveAcross; // sr.Close(); // } // string roid = myGrid.ROID; // int rodbid = myGrid.RODbId; // Font GridFont = myGrid.Font; // myGrid.Clear(); // myGrid.ParseTableFromText(args.ROText, GridLinePattern.Single); // myGrid.AutoSizeCols(); // myGrid.AutoSizeRows(); // myGrid.MakeRTFcells(); // myGrid.RODbId = rodbid; // myGrid.ROID = roid; // myGrid.IsRoTable = true; // using (StringWriter sw = new StringWriter()) // { // myGrid.WriteXml(sw); // xml = sw.GetStringBuilder().ToString(); // sw.Close(); // } // srchtxt = myGrid.GetSearchableText(); //} //List retlist = new List(); //retlist.Add(srchtxt); //retlist.Add(xml); //return retlist; } private void RunROEditor(VETreeNode tn) { DocVersionInfo MyDVI = tn.VEObject as DocVersionInfo; if (VlnSettings.ReleaseMode.Equals("DEMO")) { FlexibleMessageBox.Show("Referenced Object Editor not available in the Demo version.", "PROMS Demo Version"); return; } //string roapp = Environment.GetEnvironmentVariable("roapp"); string roapp = Volian.Base.Library.ExeInfo.GetROEditorPath(); // get the path to the RO Editor Executable if (roapp == null || roapp == string.Empty) { FlexibleMessageBox.Show("The 'roapp' environment variable needs to be set to the path of the RO Editor\n\n Ex: C:\\VE-PROMS.NET\\Bin\\roeditor.exe", "Environment Variable Error"); return; } if (!File.Exists(roapp)) { string errtxt = string.Format("Could not find path to Referenced Objects Editor:\n\n roapp = {0}\n\n Verify the path assigned to the 'roapp' environment variable", roapp); FlexibleMessageBox.Show(errtxt, "Environment Variable Error"); //MessageBox.Show("Could not find path to Ro Editor, check 'roapp' environment variable","Environment Variable Error"); return; } //if (roapp == null) //{ // MessageBox.Show("Could not find path to Ro Editor, check 'roapp' environment variable"); // return; //} if (MyDVI == null || MyDVI.DocVersionAssociationCount < 1) { FlexibleMessageBox.Show("Could not find associated path for ro data.", "No RO Data", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } string roloc = "\"" + MyDVI.DocVersionAssociations[0].MyROFst.MyRODb.FolderPath + "\""; if (!Directory.Exists(MyDVI.DocVersionAssociations[0].MyROFst.MyRODb.FolderPath)) { FlexibleMessageBox.Show(string.Format("RO Database directory does not exist: {0}", MyDVI.DocVersionAssociations[0].MyROFst.MyRODb.FolderPath)); return; } // C2017-003: ro data in sql server, check for sql connection string if (MyDVI.DocVersionAssociations[0].MyROFst.MyRODb.DBConnectionString != "cstring") roloc = roloc + " \"" + MyDVI.DocVersionAssociations[0].MyROFst.MyRODb.DBConnectionString + "\""; // C2021-026 pass in Parent/Child information (list of the children) // B2022-019 look at all DocVersions to find ParentChild information // to ensure we pass in Parent/Child even when not coming from a Parent/Child procedure set // B2022-073 Break out of the foreach when we find a set with parent/child information DocVersionInfoList dvil = DocVersionInfoList.Get(); foreach (DocVersionInfo dvi in dvil) { DocVersionConfig dvc = dvi.DocVersionConfig as DocVersionConfig; if (dvc != null && dvc.Unit_Name != "" && dvc.Unit_Count > 1) // B2021-089 only pass in applicability info if defined for more than one unit { roloc += " \"PC=" + dvc.Unit_Name + "\""; break; } } System.Diagnostics.Process.Start(roapp, roloc); } [Serializable] public struct PromsClipboard { public int cType; public int itemId; } public enum PromsClipboardType : int { Copy = 1, Cut = 2 } private void tv_NodePaste(string p) { ItemInfo iiClipboard = OnClipboardStatus(this, null); if (iiClipboard == null) return; string message = string.Empty; if (iiClipboard.MyContent.MyEntry == null) { if (!MySessionInfo.CanCheckOutItem(iiClipboard.MyProcedure.ItemID, CheckOutType.Procedure, ref message)) { FlexibleMessageBox.Show(this, message, "Copied Procedure Already Checked Out", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } } else { if (!MySessionInfo.CanCheckOutItem(iiClipboard.MyContent.MyEntry.DocID, CheckOutType.Document, ref message)) { FlexibleMessageBox.Show(this, message, "Copied Document Already Checked Out", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } } VETreeNode tn = SelectedNode as VETreeNode; DocVersionInfo dvi = tn.VEObject as DocVersionInfo; // Check for paste into a docversion - queries/code is different than paste related to an item (into a proc or section) if (dvi != null) { // If the docversion has procedures (children), change to a 'paste-after the last procedure'. if (tn.Nodes.Count > 0) { // if the node count is 1, children may not have been loaded yet - load if necessary: if (tn.Nodes.Count == 1 && tn.Nodes[0].Text.ToUpper().Contains("DUMMY VETREENODE")) tn.LoadChildren(); // assume that item to paste is a procedure, otherwise the menuing would not have // included the paste options tn = (VETreeNode) tn.Nodes[tn.Nodes.Count - 1]; p = "After"; } else // this is an empty docversion: { // First check if the doc version has RO's // Paste as a child to the doc version: this.Cursor = Cursors.WaitCursor; PasteAsDocVersionChild(tn, iiClipboard.ItemID); this.Cursor = Cursors.Default; return; } } ItemInfo iiPaste = tn.VEObject as ItemInfo; if (iiPaste == null) return; this.Cursor = Cursors.WaitCursor; if (p.IndexOf("Before") > -1) PasteBeforeOrAfter(MenuSelections.StepBefore, tn, iiClipboard.ItemID); else if (p.IndexOf("After") > -1) PasteBeforeOrAfter(MenuSelections.StepAfter, tn, iiClipboard.ItemID); else if (p.IndexOf("Replace") > -1) { bool OnlyProc = iiPaste.IsProcedure && iiPaste.MyPrevious == null && (iiPaste.NextItems == null || iiPaste.NextItems.Count == 0); VETreeNode tmp = null; if (OnlyProc) { VETreeNode tnp = SelectedNode as VETreeNode; tmp = tnp == null ? null : tnp.Parent as VETreeNode; } ItemInfo repitem = PasteReplace(tn, iiClipboard.ItemID); // B2024-045, 049 and 050: The treenode was passed into the business object's replace but sometimes it was null. And this // wasn't working if it was a single procedure in a working Draft. Adjust the tree here if single procedure in working draft. if (OnlyProc && repitem != null && tmp != null) { VETreeNode tn1 = new VETreeNode(repitem); tmp.Nodes.Add(tn1); SelectedNode = tn1; } } else // paste as child PasteAsChild(tn, iiClipboard.ItemID); //if (p.IndexOf("Replace") <= -1) this.Cursor = Cursors.Default; } public void PasteAsDocVersionChild(VETreeNode tn, int copyStartID) { // Only need to handle paste in tree since this will create a new procedure. DocVersionInfo dvi = tn.VEObject as DocVersionInfo; if (dvi.DocVersionAssociationCount == 0) { // Set docversionassociation to the copied docversion association // so that the rofst for ro's can be found. (if there is no association set) ROFstInfo rfi = GetAssociationRofstId(copyStartID); Association myAs = Association.MakeAssociation(dvi.Get(), rfi.GetJustROFst(), ""); dvi.RefreshDocVersionAssociations(); } ItemInfo newProc = dvi.PasteChild(copyStartID); VETreeNode tn1 = new VETreeNode(newProc); SelectedNode.Nodes.Add(tn1); // add tree node to end of list. SelectedNode = tn1; } private ROFstInfo GetAssociationRofstId(int copyStartID) { ItemInfo ii = ItemInfo.Get(copyStartID); return ii.MyDocVersion.DocVersionAssociations[0].MyROFst; } private void PasteAsChild(VETreeNode tn, int copyStartID) { bool pasteSectIntoEmptySect = false; ItemInfo ii = tn.VEObject as ItemInfo; if (ii.IsStepSection) // is pasting a subsection, need to force a reload of the treeview { ItemInfo tmpcopy = ItemInfo.Get(copyStartID); if (tmpcopy.IsStepSection) pasteSectIntoEmptySect = true; } ItemInfo.EAddpingPart pasteOpt = ItemInfo.EAddpingPart.Child; // If parent step is open in step editor, the 'OnPasteItemInfo' event will cause // the item to be pasted in the step editor and the tree. if (!OnPasteItemInfo(this, new vlnTreeItemInfoPasteEventArgs(ii, copyStartID, pasteOpt, ii.MyContent.Type))) { // The parent step was not open in the step editor, just paste step (in data) and add treenode. // first, check if a changeid is required. string chgId = OnGetChangeId(this, new vlnTreeItemInfoEventArgs(ii)); ItemInfo newItemInfo = null; newItemInfo = ii.PasteChild(copyStartID, chgId); if (newItemInfo != null) { // paste enhanced steps if applicable (this code is only run if a step is pasted, not for a section). ItemInfo.EAddpingPart addpart = ItemInfo.EAddpingPart.Child; ItemInfo newEnhStep = newItemInfo.PasteEnhancedItems(copyStartID, ii, addpart, chgId); } } if (pasteSectIntoEmptySect) { tn.ChildrenLoaded = false; // force a reload of treenode tn.LoadChildren(true); } SelectedNode = tn; } private void PasteBeforeOrAfter(MenuSelections newtype, VETreeNode tn, int copyStartID) { // If paste-from step is open in the editor, use the OnPasteItemInfo to paste the step and add RTBItems // to the step editor panel. ItemInfo ii = tn.VEObject as ItemInfo; ItemInfo.EAddpingPart pasteOpt = newtype == MenuSelections.StepBefore ? ItemInfo.EAddpingPart.Before : ItemInfo.EAddpingPart.After; // If parent step is open in step editor, the 'OnPasteItemInfo' event will cause // the item to be pasted in the step editor and the tree. ItemInfo newItemInfo = null; // F2021-009 display a message if pasting step will results in more sub-step levels than are defined in the format if (!ii.IsProcedure) ItemInfo.PasteStepIsWithinDefinedSubStepLevels(copyStartID, ii, false); if (ii.IsProcedure || !OnPasteItemInfo(this, new vlnTreeItemInfoPasteEventArgs(ii, copyStartID, pasteOpt, ii.MyContent.Type))) { // The parent step was not open in the step editor, just paste step (in data) and add treenode. // first, check if a changeid is required. string chgId = OnGetChangeId(this, new vlnTreeItemInfoEventArgs(ii)); if (newtype == MenuSelections.StepBefore) newItemInfo = ii.PasteSiblingBefore(copyStartID, chgId); else newItemInfo = ii.PasteSiblingAfter(copyStartID, chgId); if (newItemInfo != null) { // paste enhanced steps if applicable (this code is only run if a step is pasted, not for a section). ItemInfo.EAddpingPart addpart = ItemInfo.EAddpingPart.After; if (newtype == MenuSelections.StepBefore) addpart = ItemInfo.EAddpingPart.Before; ItemInfo newEnhStep = newItemInfo.PasteEnhancedItems(copyStartID, ii, addpart, chgId); } } SelectedNode = (VETreeNode)((newtype == MenuSelections.StepAfter) ? tn.NextNode : tn.PrevNode); } private ItemInfo PasteReplace(VETreeNode tn, int copyStartID) { VETreeNode prevtn = (VETreeNode) tn.PrevNode; VETreeNode partn = (VETreeNode) tn.Parent; ItemInfo ii = tn.VEObject as ItemInfo; // F2021-009 display a message if pasting step will results in more sub-step levels than are defined in the format ItemInfo.PasteStepIsWithinDefinedSubStepLevels(copyStartID, ii, true); ItemInfo replItemInfo = null; if (!OnPasteItemInfo(this, new vlnTreeItemInfoPasteEventArgs(ii, copyStartID, ItemInfo.EAddpingPart.Replace, ii.MyContent.Type))) { // first, check if a changeid is required. string chgId = OnGetChangeId(this, new vlnTreeItemInfoEventArgs(ii)); replItemInfo = Item.PasteReplace(ii, copyStartID, chgId); StepConfig replItemConfig = ii.MyConfig as StepConfig; if (replItemInfo != null) { ItemInfo newEnhStep = replItemInfo.PasteEnhancedItems(copyStartID, ii, ItemInfo.EAddpingPart.Replace, chgId); } } // B2018-047: was crashing on the following line (before change it was casting the result to a VETreeNote when the partn.FirstNode was just a TreeNode) SelectedNode = prevtn != null ? prevtn.NextNode : partn.FirstNode; return replItemInfo; } public void PasteRepalceEmpty(VETreeNode tn, int copyStartID) { // Only need to handle paste in tree since this will create a new procedure. DocVersionInfo dvi = tn.VEObject as DocVersionInfo; if (dvi.DocVersionAssociationCount == 0) { // Set docversionassociation to the copied docversion association // so that the rofst for ro's can be found. (if there is no association set) ROFstInfo rfi = GetAssociationRofstId(copyStartID); Association myAs = Association.MakeAssociation(dvi.Get(), rfi.GetJustROFst(), ""); dvi.RefreshDocVersionAssociations(); } ItemInfo newProc = dvi.PasteChild(copyStartID); VETreeNode tn1 = new VETreeNode(newProc); SelectedNode.Nodes.Add(tn1); // add tree node to end of list. SelectedNode = tn1; } private void tv_NodeCopy() { if (SelectedNode == null) return; VETreeNode tn = SelectedNode as VETreeNode; OnNodeCopy(this, new vlnTreeEventArgs(tn)); } #endregion #region PropertyPagesInterface private void SetupNodeProperties() { VETreeNode tn = SelectedNode as VETreeNode; if (tn==null)return; if ((tn.VEObject as FolderInfo) != null) OpenProperties(tn.VEObject as FolderInfo); else if ((tn.VEObject as DocVersionInfo) != null) { // see if rofst is changed, if so, need to refresh any step panel values. int rofstid = 0; DocVersionInfo dvi = tn.VEObject as DocVersionInfo; if (dvi != null && dvi.DocVersionAssociations != null && dvi.DocVersionAssociations.Count > 0) rofstid = dvi.DocVersionAssociations[0].MyROFst.ROFstID; OpenProperties(tn.VEObject as DocVersionInfo); if (dvi != null && dvi.DocVersionAssociations != null && dvi.DocVersionAssociations.Count > 0 && rofstid != dvi.DocVersionAssociations[0].MyROFst.ROFstID) OnTabDisplay(this,new StepPanelTabDisplayEventArgs("DisplayROUpdateROFST")); } else if ((tn.VEObject as ProcedureInfo) != null) OpenProperties(tn.VEObject as ProcedureInfo); else if ((tn.VEObject as SectionInfo) != null) OpenProperties(tn.VEObject as SectionInfo); else if ((tn.VEObject as StepInfo) != null) FlexibleMessageBox.Show("Open up info tab or whatever is associated with step"); if (!tn.MovedToSeparateWindow) tn.RefreshNode(); // C2015-022 don't want to rebuild tree node in the main window if it is currently in a child window } private void OpenProperties(FolderInfo folderInfo) { using (Folder folder = folderInfo.Get()) { OnNodeOpenProperty(this, new vlnTreePropertyEventArgs(string.Format("{0} Properties", folder.FolderConfig.Name), folder.FolderConfig)); } } private void OpenProperties(DocVersionInfo dvInfo) { using (DocVersion dv = dvInfo.Get()) { OnNodeOpenProperty(this, new vlnTreePropertyEventArgs(string.Format("{0} Properties", dv.DocVersionConfig.Name), dv.DocVersionConfig)); } } private void OpenProperties(ProcedureInfo procInfo) { using (Procedure proc = procInfo.Get()) { OnNodeOpenProperty(this, new vlnTreePropertyEventArgs(string.Format("{0} {1} Properties", proc.ProcedureConfig.Number, proc.ProcedureConfig.Title), proc.ProcedureConfig)); } } private void OpenProperties(SectionInfo sectInfo) { OnSectionShouldClose(this, new vlnTreeSectionInfoEventArgs(sectInfo)); using (Section sect = sectInfo.Get()) { string title = null; if (sectInfo.SectionConfig.Number.Length > 0) title = string.Format("{0} {1} Properties", sectInfo.SectionConfig.Number, sectInfo.SectionConfig.Title); else title = string.Format("{0} Properties", sectInfo.SectionConfig.Title); OnNodeOpenProperty(this, new vlnTreePropertyEventArgs(title, sect.SectionConfig)); } } private void OpenProperties(StepInfo stpinfo) { using (Step stp = stpinfo.Get()) { } } #endregion #region OpenNode private void tv_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == '\r') { OpenNode(); e.Handled = true; } } public void OpenNode() { VETreeNode tn = SelectedNode as VETreeNode; if (tn != null) { if (tn.VEObject.GetType() == typeof(FolderInfo) || tn.VEObject.GetType() == typeof(DocVersionInfo) || tn.VEObject.GetType() == typeof(PartInfo)) { if (tn.Nodes.Count > 0) { tn.Expand(); SelectedNode = tn.Nodes[0]; Focus(); } } else OnNodeSelect(this, new vlnTreeEventArgs(SelectedNode)); } } #endregion #region InsertAllLevels public void tv_NodeNew(MenuSelections newtype) { VETreeNode tn = null; if (SelectedNode == null) return; OnPauseRefresh(this, null); SetLastValues((VETreeNode)SelectedNode); #region InsertFolderOrDocVersion if (_LastFolderInfo != null) { using (Folder parentfolder = _LastFolderInfo.Get()) { if (newtype == MenuSelections.DocVersion) { int dvid = -1; // flag to allow user to cancel from dialog & then we remove it. using (DocVersion docversion = DocVersion.MakeDocVersion(parentfolder, "Working Draft", "Title", null, null, null)) { ShowBrokenRules(docversion.BrokenRulesCollection); SetLastValues(DocVersionInfo.Get(docversion.VersionID)); if (OnNodeOpenProperty(this, new vlnTreePropertyEventArgs("Working Draft", docversion.DocVersionConfig)) == DialogResult.OK) { docversion.Save(); tn = new VETreeNode(_LastDocVersionInfo); SelectedNode.Nodes.Add(tn); // add tree node to end of list. parentfolder.Reset_ChildFolders(); parentfolder.Reset_FolderDocVersions(); } else dvid = docversion.VersionID; } if (dvid != -1) DocVersion.Delete(dvid); } else if (newtype == MenuSelections.Folder) { int f1 = -1; // flag to allow user to cancel from dialog & then we remove it. string uniquename = _LastFolderInfo.UniqueChildName("New Folder"); using (Folder folder = Folder.MakeFolder(parentfolder, parentfolder.MyConnection, uniquename, string.Empty, "Short Name", null, string.Empty, DateTime.Now, VlnSettings.UserID)) { ShowBrokenRules(folder.BrokenRulesCollection); FolderInfo fi = FolderInfo.Get(folder.FolderID); folder.ManualOrder = fi.ManualOrder; SetLastValues(fi); if (OnNodeOpenProperty(this, new vlnTreePropertyEventArgs(uniquename, folder.FolderConfig)) == DialogResult.OK) { folder.Save(); tn = new VETreeNode((IVEDrillDownReadOnly)_LastFolderInfo); SelectedNode.Nodes.Add(tn); // add new tree node to end of childlist. } else f1 = folder.FolderID; } if (f1 != -1) Folder.Delete(f1); } else if (newtype == MenuSelections.FolderAfter||newtype == MenuSelections.FolderBefore) { int f2 = -1; string uniquename = _LastFolderInfo.MyParent.UniqueChildName("New Folder"); int myindex = SelectedNode.Index + ((newtype == MenuSelections.FolderAfter) ? 1 : 0); FolderInfo parfolderinfo = FolderInfo.Get(parentfolder.FolderID); double? myorder = parfolderinfo.NewManualOrder(myindex); using (Folder folder = Folder.MakeFolder(parentfolder.MyParent, parentfolder.MyConnection, uniquename, string.Empty, "Short Name", null, myorder, string.Empty, DateTime.Now, VlnSettings.UserID)) { ShowBrokenRules(folder.BrokenRulesCollection); SetLastValues(FolderInfo.Get(folder.FolderID)); if (OnNodeOpenProperty(this, new vlnTreePropertyEventArgs(uniquename, folder.FolderConfig)) == DialogResult.OK) { folder.Save(); tn = new VETreeNode((IVEDrillDownReadOnly)_LastFolderInfo); if (newtype == MenuSelections.FolderBefore) SelectedNode.Parent.Nodes.Insert(SelectedNode.Index, tn); if (newtype == MenuSelections.FolderAfter) SelectedNode.Parent.Nodes.Insert(SelectedNode.Index + 1, tn); } else f2 = folder.FolderID; } if (f2 != -1) Folder.Delete(f2); } } } #endregion #region InsertProcedure else if (newtype == MenuSelections.Procedure) { int p1 = -1; using (Procedure procedure = Procedure.MakeProcedure(_LastDocVersionInfo, _LastDocVersionInfo.Procedures.Count!=0?_LastDocVersionInfo.Procedures[_LastDocVersionInfo.Procedures.Count-1]:null, null, "New Procedure", 0)) { ShowBrokenRules(procedure.BrokenRulesCollection); SetLastValues(ProcedureInfo.Get(procedure.ItemID)); procedure.ProcedureConfig.CreatingNew = true; if (OnNodeOpenProperty(this, new vlnTreePropertyEventArgs("New Procedure", procedure.ProcedureConfig)) == DialogResult.OK) { procedure.Save(); tn = new VETreeNode(_LastProcedureInfo); SelectedNode.Nodes.Add(tn); // add tree node to end of list. // The following line will allow for a refresh of the procedure list on the Working Draft's treenodes docversion (B2016-034) if (((SelectedNode as VETreeNode).VEObject as DocVersionInfo) != null) ((SelectedNode as VETreeNode).VEObject as DocVersionInfo).ResetProcedures(); if (procedure.MyProcedureInfo.CreateEnhanced) { procedure.MyProcedureInfo.CreateEnhanced = false; CreateEnhancedForProcedure(newtype, procedure, null); } } else p1 = procedure.ItemID; } if (p1 != -1) DeleteItemInfoAndChildren(_LastProcedureInfo);// Delete Item and reset Previous and Next } else if (newtype == MenuSelections.ProcedureAfter || newtype == MenuSelections.ProcedureBefore) { int p2 = -1; int tvindex = SelectedNode.Index; // if inserting before, the parent is set in case previous is null, i.e. beginning of the list. ProcedureInfo savLastProcedureInfo = _LastProcedureInfo; using (Procedure procedure = Procedure.MakeProcedure((newtype == MenuSelections.ProcedureAfter) ? null : _LastProcedureInfo.ActiveParent, (newtype == MenuSelections.ProcedureAfter) ? _LastProcedureInfo : _LastProcedureInfo.MyPrevious, null, "New Procedure", 0)) { ShowBrokenRules(procedure.BrokenRulesCollection); SetLastValues(ProcedureInfo.Get(procedure.ItemID)); procedure.ProcedureConfig.CreatingNew = true; if (OnNodeOpenProperty(this, new vlnTreePropertyEventArgs("New Procedure", procedure.ProcedureConfig)) == DialogResult.OK) { procedure.Save(); tn = new VETreeNode(_LastProcedureInfo); TreeNode par = SelectedNode.Parent; par.Nodes.Insert(tvindex + ((newtype == MenuSelections.ProcedureBefore) ? 0 : 1), tn); // The following line will allow for a refresh of the procedure list on the Working Draft's treenodes docversion (B2016-034) if (((par as VETreeNode).VEObject as DocVersionInfo) != null) ((par as VETreeNode).VEObject as DocVersionInfo).ResetProcedures(); if (procedure.MyProcedureInfo.CreateEnhanced) { procedure.MyProcedureInfo.CreateEnhanced = false; CreateEnhancedForProcedure(newtype, procedure, savLastProcedureInfo); } } else p2 = procedure.ItemID; } if (p2 != -1) DeleteItemInfoAndChildren(_LastProcedureInfo); // Delete Item and reset Previous and Next } #endregion #region InsertSection else if (newtype == MenuSelections.Section) // Insert subsection at end of parents section list { string message = string.Empty; if (_LastProcedureInfo != null) if (!MySessionInfo.CanCheckOutItem(_LastProcedureInfo.ItemID, CheckOutType.Procedure, ref message)) { FlexibleMessageBox.Show(this, message, "Item Already Checked Out", MessageBoxButtons.OK, MessageBoxIcon.Warning); OnUnPauseRefresh(this, null); return; } int s1 = -1; if (!(_LastProcedureInfo == null) || !(_LastSectionInfo == null)) { // May need to create 'pseudo' nodes, for the 'Steps' and 'Sections' grouping tree nodes. // If no grouping nodes exist off a section (we are adding a subsection), then // add a 'pseudo' node. // If step(s) exists, but not a section, then need 'pseudo' nodes, i.e. 'Steps' and 'Sections' // tree nodes. // Otherwise, the 'Sections' pseudo node will exist. // Note that this check has to be done before the section is made, otherwise the item will // have sections, i.e. the one getting added. bool doPseudo = false; if (_LastItemInfo.IsSection) // if adding off of a procedure, don't add pseudo. { // B2017-014: removed code that was adding a 2nd section part node. if (SelectedNode.Nodes.Count > 0) { // if inserting from a section that has steps, but no subsections, prompt user to let them // know that the steps will not be visible after the subsection insert (C2016-042): if (_LastItemInfo.Sections == null && _LastItemInfo.Steps != null && _LastItemInfo.Steps.Count > 0) { // C2020-016 reformatted and reworded the message. // C2020-047 reformatted and reworded the message. string msgstr = "If there are already steps in the high level section, then PROMS will hide\n" + "the steps in this section when the subsection is created.\n\n" + "If you would like to view or copy these hidden steps you will need to go\n" + "into the properties of this section and check the Editable Data checkbox.\n" + "You will then be able to view and copy those steps. When finished, open\n" + "the properties page again and uncheck the Editable Data checkbox.\n\n"+ "Do you want to continue creating the subsection?"; if (FlexibleMessageBox.Show(this, msgstr, "Subsection Insert", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) { return; } } // Check to see if sections already exist, if so, the pseudo node will too. bool hasMetaSubs = _LastItemInfo.Sections != null && _LastItemInfo.Sections.Count > 0; if (!hasMetaSubs) doPseudo = true; } } using(Section section = CreateNewSection()) { ShowBrokenRules(section.BrokenRulesCollection); SectionInfo savLastSectionInfo = _LastSectionInfo; SetLastValues(SectionInfo.Get(section.ItemID)); if (OnNodeOpenProperty(this, new vlnTreePropertyEventArgs("New Section", section.SectionConfig)) == DialogResult.OK) { if (!doPseudo) { tn = new VETreeNode(_LastSectionInfo); SelectedNode.Nodes.Add(tn); // add tree node to end of list. // if the new section was flagged as either having an enhanced link for Title or Contents, create the // Enhanced section: Section sectiontmp = Section.Get(section.ItemID); // need to do this because of 'caching' problem. if (sectiontmp.SectionConfig.LinkEnhanced == "T" || sectiontmp.SectionConfig.LinkEnhanced == "Y") CreateEnhancedForSection(newtype, sectiontmp, savLastSectionInfo, sectiontmp.DisplayNumber, sectiontmp.MyContent.Text); sectiontmp.Dispose(); OnNodeSelect(this, new vlnTreeEventArgs(tn)); } else { // may have to add a 'steps' node if a step(s) already exist... ItemInfo ii = (SelectedNode as VETreeNode).VEObject as ItemInfo; int cpindx = 0; if (SelectedNode.Nodes.Count>0) { VETreeNode vtn = SelectedNode.Nodes[0] as VETreeNode; // B2017-014: removed code that was adding a 2nd section part node. and also select node to // refresh display if (vtn.FirstNode != null) OnNodeSelect(this, new vlnTreeEventArgs(vtn.FirstNode)); } // B2017-014: removed code that was adding a 2nd section part node. } } else // Properties was canceled out of: s1 = section.ItemID; } if (s1 != -1) { DeleteItemInfoAndChildren(_LastSectionInfo);// Delete Item and reset Previous and Next // B2020-087 refresh the tree node after canceling the creation of the subsection _LastTreeNode.ChildrenLoaded = false; _LastTreeNode.RefreshNode(); _LastTreeNode.Collapse(); } } } else if (newtype == MenuSelections.SectionAfter || newtype == MenuSelections.SectionBefore) { string message = string.Empty; if (!MySessionInfo.CanCheckOutItem(_LastSectionInfo.MyProcedure.ItemID, CheckOutType.Procedure, ref message)) { FlexibleMessageBox.Show(this, message, "Item Already Checked Out", MessageBoxButtons.OK, MessageBoxIcon.Warning); OnUnPauseRefresh(this, null); return; } int tvindex = SelectedNode.Index; // if inserting before, the parent is set in case previous is null, i.e. beginning of the list. int s2 = -1; using (Section section = Section.MakeSection((newtype == MenuSelections.SectionAfter) ? null : _LastSectionInfo.MyParent, (newtype == MenuSelections.SectionAfter) ? _LastSectionInfo : _LastSectionInfo.MyPrevious, null, "New Section", 10000)) { ShowBrokenRules(section.BrokenRulesCollection); SectionInfo savLastSectionInfo = _LastSectionInfo; SetLastValues(SectionInfo.Get(section.ItemID)); TreeNode par = SelectedNode.Parent; if (OnNodeOpenProperty(this, new vlnTreePropertyEventArgs("New Section", section.SectionConfig)) == DialogResult.OK) { int indx = tvindex + ((newtype == MenuSelections.SectionBefore) ? 0 : 1); int itemido = (indx >= par.Nodes.Count)?-1:(((par.Nodes[indx] as VETreeNode).VEObject) as ItemInfo).ItemID; if (indx >= par.Nodes.Count || (par.Nodes[indx] as VETreeNode).VEObject.ToString() != _LastSectionInfo.ToString() || itemido !=section.ItemID) { tn = new VETreeNode(_LastSectionInfo); par.Nodes.Insert(indx, tn); // if the new section was flagged as either having an enhanced link for Title or Contents, create the // Enhanced section: Section sectiontmp = Section.Get(section.ItemID); // need to do this because of 'caching' problem. if (sectiontmp.SectionConfig.LinkEnhanced == "T" || sectiontmp.SectionConfig.LinkEnhanced == "Y") CreateEnhancedForSection(newtype, sectiontmp, savLastSectionInfo, sectiontmp.DisplayNumber, sectiontmp.MyContent.Text); sectiontmp.Dispose(); } } else s2 = section.ItemID; } if (s2 != -1) { DeleteItemInfoAndChildren(_LastSectionInfo);// Delete Item and reset Previous and Next // B2020-087 refresh the tree node after canceling the creation of the subsection _LastTreeNode.ChildrenLoaded = false; _LastTreeNode.RefreshNode(); _LastTreeNode.Collapse(); } } #endregion #region InsertStep else if (newtype == MenuSelections.Step) // insert step from section - no substeps from tree. { string message = string.Empty; if (!MySessionInfo.CanCheckOutItem(_LastSectionInfo.MyProcedure.ItemID, CheckOutType.Procedure, ref message)) { FlexibleMessageBox.Show(this, message, "Item Already Checked Out", MessageBoxButtons.OK, MessageBoxIcon.Warning); OnUnPauseRefresh(this, null); return; } tn = InsertChildStep((VETreeNode)SelectedNode); } else if (newtype == MenuSelections.StepAfter || newtype == MenuSelections.StepBefore && _LastStepInfo != null) { string message = string.Empty; if (!MySessionInfo.CanCheckOutItem(_LastStepInfo.MyProcedure.ItemID, CheckOutType.Procedure, ref message)) { FlexibleMessageBox.Show(this, message, "Item Already Checked Out", MessageBoxButtons.OK, MessageBoxIcon.Warning); OnUnPauseRefresh(this, null); return; } tn = InsertBeforeOrAfter(newtype, (VETreeNode)SelectedNode); } #endregion if (tn != null) { SelectedNode = tn; OnNodeNew(this, new vlnTreeEventArgs(SelectedNode)); Refresh(); OnNodeInsert(this, new vlnTreeEventArgs(SelectedNode)); } OnUnPauseRefresh(this, null); } private void CreateEnhancedForProcedure(MenuSelections typ, Procedure sourceProc, ProcedureInfo lastProcedureInfo) { if (typ == MenuSelections.ProcedureAfter || typ == MenuSelections.ProcedureBefore) // new from procedure (before or after) { // The procedure that this is inserted from may not have associated enhanced procedures. Going up list, look for a procedure // that has enhanced. ItemInfo tmpPI = lastProcedureInfo; EnhancedDocuments eds = null; while (eds == null && tmpPI != null) { ProcedureConfig pc = tmpPI.MyConfig as ProcedureConfig; if (pc.MyEnhancedDocuments != null && pc.MyEnhancedDocuments.Count > 0) { eds = pc.MyEnhancedDocuments; break; } tmpPI = tmpPI.MyPrevious; } if (eds != null) { foreach (EnhancedDocument ped in eds) { ProcedureInfo epi = ProcedureInfo.Get(ped.ItemID); using (Procedure newenhProcedure = Procedure.MakeProcedure((typ == MenuSelections.ProcedureAfter) ? null : epi.ActiveParent, (typ == MenuSelections.ProcedureAfter) ? epi : epi.MyPrevious, null, "New Procedure", 0)) { SaveEnhancedForProcedure(sourceProc, newenhProcedure, ped.Type); RefreshRelatedNode(ProcedureInfo.Get(newenhProcedure.ItemID)); } } return; } } // do the following code if insert the procedure from docverion, or if no linked procedure was found above while doing an insert section from before/after DocVersionConfig dvc = sourceProc.MyProcedureInfo.MyDocVersion.MyConfig as DocVersionConfig; ProcedureConfig sourcecfg = sourceProc.ProcedureConfig; if (dvc != null) { foreach (DVEnhancedDocument ded in dvc.MyEnhancedDocuments) { // get the enhaced docversioninfo: DocVersionInfo enhDVInfo = DocVersionInfo.Get(ded.VersionID); using (Procedure newenhProcedure = Procedure.MakeProcedure(enhDVInfo, enhDVInfo.Procedures.Count != 0 ? enhDVInfo.Procedures[enhDVInfo.Procedures.Count - 1] : null, null, "New Procedure", 0)) { SaveEnhancedForProcedure(sourceProc, newenhProcedure, ded.Type); RefreshRelatedNode(ProcedureInfo.Get(newenhProcedure.ItemID)); // this updates the treeview to include the new enhanced procedure } } } } private void SaveEnhancedForProcedure(Procedure sourceProc, Procedure newenhProcedure, int enhtype) { ProcedureConfig newenhcfg = new ProcedureConfig(newenhProcedure); newenhcfg.AddEnhancedDocument(0, sourceProc.ItemID); newenhcfg.SaveEnhancedDocuments(); using (Content c1 = Content.Get(newenhProcedure.ContentID)) { c1.Config = newenhcfg.ToString(); c1.Save(); } sourceProc.ProcedureConfig.AddEnhancedDocument(enhtype, newenhProcedure.ItemID); sourceProc.ProcedureConfig.SaveEnhancedDocuments(); using (Content cs = Content.Get(sourceProc.ContentID)) { cs.Config = sourceProc.ProcedureConfig.ToString(); cs.Save(); } } private void CreateEnhancedForSection(MenuSelections typ, Section sourceSect, SectionInfo lastSectionInfo, string num, string title) { MenuSelections tmptyp = typ; if (typ == MenuSelections.SectionAfter || typ == MenuSelections.SectionBefore) { ItemInfo tmpSI = lastSectionInfo; EnhancedDocuments eds = null; // need to find a good list, i.e. there may be non-linked sections before/after: while (eds == null && tmpSI != null) { SectionConfig sc = tmpSI.MyConfig as SectionConfig; if (sc.MyEnhancedDocuments != null && sc.MyEnhancedDocuments.Count > 0) { eds = sc.MyEnhancedDocuments; break; } // if had to skip unlinked sections, it becomes an 'after' a linked one: tmptyp = MenuSelections.SectionAfter; tmpSI = tmpSI.MyPrevious; } if (eds != null) // found valid enhanced ids to insert from: { foreach (EnhancedDocument sed in eds) { SectionInfo esi = SectionInfo.Get(sed.ItemID); using (Section newenhSection = Section.MakeSection((tmptyp == MenuSelections.SectionAfter) ? null : esi.ActiveParent, (tmptyp == MenuSelections.SectionAfter) ? esi : esi.MyPrevious, num, title, 10000)) { SaveEnhancedForSection(sourceSect, newenhSection, sed.Type); RefreshRelatedNode(SectionInfo.Get(newenhSection.ItemID)); // B2024-023: when inserting a source section, the associated // enhanced section did not appear in tree view or in edit window (if it // was displayed in editor). Add to tree view and close the enhanced // procedure edit window. Note that closing of edit window was done to // be consistent on what happens upon delete of source w/ and enhanced // section. SectionInfo tmpsi = SectionInfo.Get(newenhSection.ItemID); RefreshRelatedNode(ProcedureInfo.Get(tmpsi.MyParent.ItemID)); OnSectionShouldClose(this, new vlnTreeSectionInfoEventArgs(tmpsi, true)); } } return; } } // do the following code if insert the section from the procedure, or if no linked section was found above while doing an insert section from before/after ProcedureConfig pc = sourceSect.MyItemInfo.MyProcedure.MyConfig as ProcedureConfig; SectionConfig sourcecfg = sourceSect.SectionConfig; if (pc != null) { foreach (EnhancedDocument ed in pc.MyEnhancedDocuments) { // get the enhanced procedureinfo: ProcedureInfo enhInfo = ProcedureInfo.Get(ed.ItemID); if (enhInfo.LastChild(E_FromType.Section) != null) { using (Section newenhSection = Section.MakeSection(enhInfo, (enhInfo.Sections != null && enhInfo.Sections.Count != 0) ? enhInfo.Sections[enhInfo.Sections.Count - 1] : null, num, title, 10000)) { SaveEnhancedForSection(sourceSect, newenhSection, ed.Type); RefreshRelatedNode(SectionInfo.Get(newenhSection.ItemID)); } } else { ItemInfo newenhSectionII = enhInfo.InsertChild(E_FromType.Section, 10000, title, num); using (Section newenhSect = Section.Get(newenhSectionII.ItemID)) { SaveEnhancedForSection(sourceSect, newenhSect, ed.Type); RefreshRelatedNode(SectionInfo.Get(newenhSect.ItemID)); } } } } } private void SaveEnhancedForSection(Section sourceSect, Section newenhSection, int enhtype) { SectionConfig newenhcfg = new SectionConfig(newenhSection); newenhcfg.AddEnhancedDocument(0, sourceSect.ItemID); newenhcfg.SaveEnhancedDocuments(); // does this save data? using (Content c1 = Content.Get(newenhSection.ContentID)) { c1.Config = newenhcfg.ToString(); c1.Save(); } sourceSect.SectionConfig.AddEnhancedDocument(enhtype, newenhSection.ItemID); sourceSect.SectionConfig.SaveEnhancedDocuments(); using (Content cs = Content.Get(sourceSect.ContentID)) { cs.Config = sourceSect.SectionConfig.ToString(); cs.Save(); } } private Section CreateNewSection() { // B2020-087 the config for SubSection_Edit was sometimes set even when there wasn't any subsections, // so make sure it's cleared if there are no existing subsections SectionConfig sc = _LastItemInfo.MyConfig as SectionConfig; if (sc != null && sc.SubSection_Edit == "Y" && _LastItemInfo.Sections == null) { sc.SubSection_Edit = null; using (Section mysect = Section.Get(_LastItemInfo.ItemID)) { mysect.MyContent.Config = sc.ToString(); mysect.Save(); } } if (_LastItemInfo.LastChild(E_FromType.Section) != null) return Section.MakeSection(_LastItemInfo, _LastItemInfo.LastChild(E_FromType.Section), null, "New Section", 10000); ItemInfo iii = _LastItemInfo.InsertChild(E_FromType.Section, 10000, "New Section", null); return Section.Get(iii.ItemID); } private VETreeNode InsertChildStep(VETreeNode tn) { // 11/17/15: if inserted with step editor open, step gets inserted as child first child. If step editor is not // open, step gets inserted at end (as last item in list) // If parent step is open in editor, use the OnInsertItemInfo to insert step & add RTBItems to step editor panel ItemInfo ii = tn.VEObject as ItemInfo; if (OnInsertItemInfo(this, new vlnTreeItemInfoInsertEventArgs(ii, E_InsertType.Child, "New Step", 20002, E_FromType.Step))) { if (ii.IsStep) return null; // if this was a section, it may have enhanced, so the enhanced steps will need to be created also. SectionConfig scfg = ii.MyConfig as SectionConfig; if (scfg.Section_LnkEnh != "Y") return null; SetLastValues(StepInfo.Get(ii.Steps[0].ItemID)); } else { // The parent step was not open in the step editor, just create new step(s) and add treenode. int newId = -1; // B2020-076: if this step has a template, insert template steps. int topType = ii.GetSmartTemplateTopLevelIndxOfThisType(20002); if (topType != -1) { ItemInfo tmp = null; tmp = ii.InsertSmartTemplateSubStep("New Step", null, null, ItemInfo.EAddpingPart.Child, 20002, E_FromType.Step); newId = tmp.ItemID; } else { // this line (below) adds the new step to the bottom of the section, the other line (not commented) adds it to the top. Bug fix B2016-002 //using (Step step = Step.MakeStep(_LastItemInfo, _LastItemInfo.LastChild(E_FromType.Step), null, "New Step", 20002, E_FromType.Step)) using (Step step = Step.MakeStep(_LastItemInfo, null, null, "New Step", 20002, E_FromType.Step)) { ShowBrokenRules(step.BrokenRulesCollection); newId = step.ItemID; } } SetLastValues(StepInfo.Get(newId)); tn = new VETreeNode(_LastStepInfo); _LastStepInfo.UpdateTransitionText(); _LastStepInfo.UpdateROText(); TreeNode par = SelectedNode; par.Nodes.Insert(0, tn); } // see if enhanced related steps need created: SectionConfig scfgE = _LastItemInfo.ActiveSection.MyConfig as SectionConfig; // C2018-003 fixed use of getting the active section if (scfgE != null && scfgE.Section_LnkEnh=="Y") { // set up which item to insert from based on whether editor was open (see comment from 11/17 above). EnhancedDocuments enhdocs = null; ItemInfo.EAddpingPart addpart = ItemInfo.EAddpingPart.Child; if (_LastItemInfo.MyPrevious != null) // the code above will do the MakeStep regardless of whether editor is up if this is the only step. { addpart = ItemInfo.EAddpingPart.After; ItemInfo lstSrc = _LastItemInfo.MyPrevious; StepConfig stcfg = lstSrc.MyConfig as StepConfig; if (stcfg == null) enhdocs = scfgE.MyEnhancedDocuments; else enhdocs = stcfg.MyEnhancedDocuments; } else { enhdocs = scfgE.MyEnhancedDocuments; } foreach (EnhancedDocument ed in enhdocs) { // the new source step's item is passed in to know what type & what to link to. // The ed.Type & itemid show what type of enhanced document (used to create new // config Type) _LastItemInfo.DoAddEnhancedSteps(ed.Type, ed.ItemID, addpart); } } return tn; } private VETreeNode InsertBeforeOrAfter(MenuSelections newtype, VETreeNode tn) { // If parent step is open in editor, use the OnInsertItemInfo to insert step & add RTBItems to step editor panel ItemInfo ii = tn.VEObject as ItemInfo; if (OnInsertItemInfo(this, new vlnTreeItemInfoInsertEventArgs(ii, (newtype == MenuSelections.StepAfter) ? E_InsertType.After : E_InsertType.Before, ""))) { tn = (VETreeNode)((newtype == MenuSelections.StepAfter) ? tn.NextNode : tn.PrevNode); } else { // The parent step was not open in the step editor, just create new step and add treenode. int tvindex = SelectedNode.Index; // B2020-076: if this step has a template, insert template steps. int newid = -1; if (ii.FormatStepData.UseSmartTemplate || ii.FormatStepData.UseOldTemplate) { ItemInfo tmp = ii.InsertSmartTemplateSteps("New Step", null, null, newtype == MenuSelections.StepAfter ? ItemInfo.EAddpingPart.After : ItemInfo.EAddpingPart.Before, (int)ii.MyContent.Type); newid = tmp.ItemID; } else { // if inserting before, the parent is set in case previous is null, i.e. beginning of the list. ItemInfo parent = (newtype == MenuSelections.StepAfter) ? null : _LastStepInfo.MyParent; using (Step step = Step.MakeStep(parent, (newtype == MenuSelections.StepAfter) ? _LastStepInfo : _LastStepInfo.MyPrevious, null, "New Step", (int)_LastStepInfo.MyContent.Type, (E_FromType)_LastStepInfo.FirstSibling.ItemParts[0].FromType)) { ShowBrokenRules(step.BrokenRulesCollection); newid = step.ItemID; } } SetLastValues(StepInfo.Get(newid)); tn = new VETreeNode(_LastStepInfo); _LastStepInfo.UpdateTransitionText(); _LastStepInfo.UpdateROText(); TreeNode par = SelectedNode.Parent; par.Nodes.Insert(tvindex + ((newtype == MenuSelections.StepBefore) ? 0 : 1), tn); } if (tn != null) { // add enhanced steps if applicable (this code is only run if a step is inserted, not for a section). // Also, NOTE that this is not needed for InsertChildStep from tree because there is no menu item // to support inserting a type that would have enhanced from tree. StepConfig sib = ii.MyConfig as StepConfig; foreach (EnhancedDocument ed in sib.MyEnhancedDocuments) { // create a new enhanced step and link it to this new source step. // the new source step's item is passed in to know what type & what to link to. // The ed.Type & itemid show what type of enhanced document (use to create new // config Type) and itemid is the one to insert after. ItemInfo.EAddpingPart addpart = ItemInfo.EAddpingPart.After; if (newtype == MenuSelections.StepBefore) addpart = ItemInfo.EAddpingPart.Before; ItemInfo newSourceStep = tn.VEObject as ItemInfo; newSourceStep.DoAddEnhancedSteps(ed.Type, ed.ItemID, addpart); } } return tn; } private void ShowBrokenRules(BrokenRulesCollection brs) { if (brs != null) { foreach (BrokenRule br in brs) { Console.WriteLine("broken rule {0}", br.Description); } } } #endregion #region DeleteAllLevels private bool tv_NodeDelete() { SetLastValues((VETreeNode)SelectedNode); string message = string.Empty; string typeDescription = "item"; if (_LastStepInfo != null) { if (!MySessionInfo.CanCheckOutItem(_LastStepInfo.MyProcedure.ItemID, CheckOutType.Procedure, ref message)) { FlexibleMessageBox.Show(this, message, "Item Already Checked Out", MessageBoxButtons.OK, MessageBoxIcon.Warning); return false; } //C2020-026 specific description of what user is trying to delete typeDescription = "\"" + _LastStepInfo.FormatStepData.StepEditData.TypeMenu.MenuItem + "\""; if (_LastStepInfo.HasChildren) typeDescription += " and its substeps"; } if (_LastSectionInfo != null) { if (!MySessionInfo.CanCheckOutItem(_LastSectionInfo.MyProcedure.ItemID, CheckOutType.Procedure, ref message)) { FlexibleMessageBox.Show(this, message, "Item Already Checked Out", MessageBoxButtons.OK, MessageBoxIcon.Warning); return false; } //C2020-026 specific description of what user is trying to delete typeDescription = "Section"; if (_LastSectionInfo.HasChildren) typeDescription += " and its steps"; } if (_LastProcedureInfo != null) { if (!MySessionInfo.CanCheckOutItem(_LastProcedureInfo.ItemID, CheckOutType.Procedure, ref message)) { FlexibleMessageBox.Show(this, message, "Item Already Checked Out", MessageBoxButtons.OK, MessageBoxIcon.Warning); return false; } typeDescription = "Procedure"; //C2020-026 specific description of what user is trying to delete } if (_LastDocVersionInfo != null) { StringBuilder sb = new StringBuilder(); foreach (ProcedureInfo pi in _LastDocVersionInfo.Procedures) { if (!MySessionInfo.CanCheckOutItem(pi.ItemID, CheckOutType.Procedure, ref message)) sb.AppendLine(message); message = string.Empty; } if (sb.Length > 0) { FlexibleMessageBox.Show(this, sb.ToString(), "Items Already Checked Out", MessageBoxButtons.OK, MessageBoxIcon.Warning); return false; } typeDescription = "Procedure Set"; //C2020-026 specific description of what user is trying to delete } if (_LastFolderInfo != null) { StringBuilder sb = new StringBuilder(); if (_LastFolderInfo.FolderDocVersionCount > 0) { foreach (DocVersionInfo dvi in _LastFolderInfo.FolderDocVersions) { foreach (ProcedureInfo pi in dvi.Procedures) { if (!MySessionInfo.CanCheckOutItem(pi.ItemID, CheckOutType.Procedure, ref message)) sb.AppendLine(message); message = string.Empty; } } } if (sb.Length > 0) { FlexibleMessageBox.Show(this, sb.ToString(), "Items Already Checked Out", MessageBoxButtons.OK, MessageBoxIcon.Warning); return false; } typeDescription = "Folder"; //C2020-026 specific description of what user is trying to delete } //C2020-026 added standardized wording when attempting to delete DialogResult result = DialogResult.No; if (_LastProcedureInfo == null) { result = FlexibleMessageBox.Show("Are you sure you want to delete this " + typeDescription + "?", "Verify Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question); } if (_LastProcedureInfo != null || result == DialogResult.Yes) { if (_LastFolderInfo != null) { Folder.Delete(_LastFolderInfo.FolderID); _LastFolderInfo = null; return true; } else if (_LastDocVersionInfo != null) { // if this has enhanced linked DocVersions, delete them first. DocVersionConfig dvc = _LastDocVersionInfo.MyConfig as DocVersionConfig; if (dvc != null && dvc.MyEnhancedDocuments != null && dvc.MyEnhancedDocuments.Count > 0) { foreach (DVEnhancedDocument dve in dvc.MyEnhancedDocuments) { if (dve.Type != 0) DocVersion.Delete(dve.VersionID); else { // B2018-025: for the input source docversion (id), clear out its enhanced document link information // dvi is the source, remove this (_LastDocVersionInfo) background link from the source's config DocVersionInfo dvi = DocVersionInfo.Get(dve.VersionID); DocVersionConfig dvci = dvi.MyConfig as DocVersionConfig; dvci.RemoveEnhancedLink(_LastDocVersionInfo.VersionID); string dvccfg = dvci.ToString(); using (DocVersion dv = dvi.Get()) { dv.Config = dvccfg; dv.Save(); DocVersionInfo.Refresh(dv); } } } } DocVersion.Delete(_LastDocVersionInfo.VersionID); _LastDocVersionInfo = null; (((VETreeNode)SelectedNode.Parent).VEObject as FolderInfo).RefreshFolderDocVersions(); // B2018-082 tell tree node that it no longer has a working draft return true; } else if (_LastProcedureInfo != null) { dlgDelProcReason dlgDPA = new dlgDelProcReason(this); // C2020-038: prompt user for reason DialogResult res = dlgDPA.ShowDialog(this); if (res == DialogResult.OK) { //If there are enhanced, they will also need deleted, save the ids so that they // can be deleted after this item gets deleted. List enhIds = new List(); // C2020-038: request reason for delete procedure so this can be saved in database ProcedureConfig prc = _LastProcedureInfo.MyConfig as ProcedureConfig; prc.General_DelProcReason = DelProcReason; using (Item itm = Item.Get(_LastProcedureInfo.ItemID)) { itm.MyContent.Config = prc.ToString(); itm.UserID = Volian.Base.Library.VlnSettings.UserID; itm.Save(); } foreach (EnhancedDocument ed in prc.MyEnhancedDocuments) if (ed.Type != 0) enhIds.Add(ed.ItemID); // always return false because an event gets fired to delete tree nodes. if (!DeleteItemInfoAndChildren(_LastProcedureInfo)) return false; _LastProcedureInfo = null; foreach (int enhId in enhIds) { ProcedureInfo pi = ProcedureInfo.Get(enhId); // if the item was displayed in the editor, the 'DeleteItemInfoAndChildren' call // above will go through user interface code that deletes the enhanced, so 'Get' // will return a null (i.e. the data no longer exists). if (pi != null) { if (!DeleteItemInfoAndChildren(pi)) Console.WriteLine("do an error log item"); } } return false; } } else if (_LastSectionInfo != null) { // For sections, there are a number of things to check for if enhanced is active: // 1) in a source and the enhanced link can be none, title or contents. // 2) if none, just delete // 3) If just title and in source, clear links in enhanced back to this source // before delete. // 4) If in enhanced, by source has link type set to title, can delete this // section, but first clear source's links //If there are enhanced, they will also need deleted, save the ids so that they // can be deleted after this item gets deleted. List enhIds = new List(); SectionConfig sec = _LastSectionInfo.MyConfig as SectionConfig; if (_LastSectionInfo.IsEnhancedSectionTitleOnly) { _LastSectionInfo.ClearEnhancedSectionFromSource(sec.MyEnhancedDocuments[0].ItemID); } else if (sec.Section_LnkEnh == "Y") { foreach (EnhancedDocument ed in sec.MyEnhancedDocuments) if (ed.Type != 0) enhIds.Add(ed.ItemID); } else if (sec.Section_LnkEnh == "T") { // just clear enhanced links back _LastSectionInfo.ClearEnhancedSectionLink(); } OnSectionShouldClose(this, new vlnTreeSectionInfoEventArgs(_LastSectionInfo,true)); // always return false because an event gets fired to delete tree nodes. if (!DeleteItemInfoAndChildren(_LastSectionInfo)) { return false; } // B2020-087 refresh the tree node after the delete - needed when deleting the last subsection or canceling the creation of the first subsection (this.SelectedNode as VETreeNode).ChildrenLoaded = false; (this.SelectedNode as VETreeNode).RefreshNode(); (this.SelectedNode as VETreeNode).Collapse(); WordSectionEventArgs args = new WordSectionEventArgs(_LastSectionInfo); OnWordSectionDeleted(this, args); _LastSectionInfo = null; foreach (int enhId in enhIds) { SectionInfo si = SectionInfo.Get(enhId); // if the item was displayed in the editor, the 'DeleteItemInfoAndChildren' call // above will go through user interface code that deletes the enhanced, so 'Get' // will return a null (i.e. the data no longer exists). if (si != null) { if (!DeleteItemInfoAndChildren(si)) Console.WriteLine("do an error log item"); } } return false; } else if (_LastStepInfo != null) { //If there are enhanced, they will also need deleted, save the ids so that they // can be deleted after this item gets deleted. Note that if the step(s) were // displayed in step editor, that code deletes the enhanced steps. List enhIds = new List(); StepConfig sc = _LastStepInfo.MyConfig as StepConfig; foreach (EnhancedDocument ed in sc.MyEnhancedDocuments) if (ed.Type != 0) enhIds.Add(ed.ItemID); // always return false because an event gets fired to delete tree nodes. if (!DeleteItemInfoAndChildren(_LastStepInfo)) return false; _LastStepInfo = null; foreach (int enhId in enhIds) { StepInfo si = StepInfo.Get(enhId); // if the item was displayed in the editor, the 'DeleteItemInfoAndChildren' call // above will go through user interface code that deletes the enhanced, so 'Get' // will return a null (i.e. the data no longer exists). if (si != null) { if (!DeleteItemInfoAndChildren(si)) Console.WriteLine("do an error log item"); } } return false; } } return false; } public void RemoveFolder(int folderId) { TreeNode nodeToRemove = FindNodeById(folderId, this.Nodes); if (nodeToRemove != null) { // Perform the removal logic nodeToRemove.Remove(); // This removes the node from its parent } } private TreeNode FindNodeById(int folderId, TreeNodeCollection nodes) { foreach (TreeNode node in nodes) { VETreeNode vetNode = node as VETreeNode; if (vetNode != null) { FolderInfo folderInfo = vetNode.VEObject as FolderInfo; if (folderInfo != null && folderInfo.FolderID == folderId) { return node; } else { TreeNode foundNode = FindNodeById(folderId, node.Nodes); if (foundNode != null) { return foundNode; } } } } return null; } private bool DeleteItemInfoAndChildren(ItemInfo ii) { DateTime dtStart = DateTime.Now; try { ItemInfo pii = ii.MyParent; bool deletedSection = ii.IsSection; // send an event to frmVeproms that sends an event to the stepeditor to // do delete using RTBItem - this manages windowing from the step editor. // If the procedure is open & you're deleting procedure, you want to close open // window - this is done in DisplayTabControl-DeleteStepTabItem. OnProcessing(true,"Deleting"); if (!OnDeleteItemInfo(this, new vlnTreeItemInfoEventArgs(ii))) Item.DeleteItemAndChildren(ii); OnProcessing(false,"Deleted"); OnProcessingComplete(dtStart,"Deleted"); if (deletedSection) { // B2020-087 if we deleted the last sub section, then clear the SubSection_Edit in the parent's config SectionConfig sc = pii.MyConfig as SectionConfig; if (sc != null && sc.SubSection_Edit == "Y" && pii.Sections == null) // B2020-103: Added null check { sc.SubSection_Edit = null; using (Section mysect = Section.Get(pii.ItemID)) { mysect.MyContent.Config = sc.ToString(); mysect.Save(); } } } return true; } catch (System.Data.SqlClient.SqlException ex) { OnProcessing(false,"Delete Failed"); OnProcessingComplete(dtStart,"Delete Failed"); // C2020-033: Support delete to bring up Search/Incoming Transitions panel if (ex.Message.Contains("has External Transitions")) { ItemInfo iis = ItemInfo.Get(ii.ItemID); OnSearchIncTransIn(this, new vlnTreeItemInfoEventArgs(iis)); iis = ii.HandleSqlExceptionOnDelete(ex); } else { ItemInfo iii = ii.HandleSqlExceptionOnDelete(ex); if (iii != null) OnOpenItem(this, new vlnTreeItemInfoEventArgs(iii)); } return false; } } public event vlnTreeViewTimeEvent ProcessingComplete; private void OnProcessingComplete(DateTime dtStart, string message) { if (ProcessingComplete != null) ProcessingComplete(this, new vlnTreeTimeEventArgs(dtStart,message)); } public event vlnTreeViewStatusEvent Processing; private void OnProcessing(bool status, string message) { if (Processing != null) Processing(this, new vlnTreeStatusEventArgs(status,message)); } #endregion #region SetLastValuesAndSaveIfChangedStuff private void SetLastValues(VETreeNode node) { _LastTreeNode = node; SetLastValues(node.VEObject); } private void SetLastValues(IVEDrillDownReadOnly veobject) { _LastFolderInfo = veobject as FolderInfo; _LastDocVersionInfo = veobject as DocVersionInfo; _LastProcedureInfo = veobject as ProcedureInfo; _LastSectionInfo = veobject as SectionInfo; _LastStepInfo = veobject as StepInfo; _LastItemInfo = veobject as ItemInfo; } #endregion #region Cursor private bool SetupDragCursor(ImageList il, TreeNode tn) { // Reset image list used for drag image il.Images.Clear(); int howBig = tn.Bounds.Size.Width + this.Indent; if (howBig > 256) howBig = 256; il.ImageSize = new Size(howBig, tn.Bounds.Height); // Create new bitmap // This bitmap will contain the tree node image to be dragged Bitmap bmp = new Bitmap(tn.Bounds.Width + this.Indent, tn.Bounds.Height); // Get graphics from bitmap Graphics gfx = Graphics.FromImage(bmp); // Draw node icon into the bitmap if (this.ImageList != null) gfx.DrawImage(this.ImageList.Images[0], 0, 0); // Draw node label into bitmap gfx.DrawString(tn.Text, this.Font, new SolidBrush(this.ForeColor), // new SolidBrush(Color.Blue), (float)this.Indent, 1.0f); // Add bitmap to imagelist _dragImageList.Images.Add(bmp); // Get mouse position in client coordinates Point p = this.PointToClient(Control.MousePosition); // Compute delta between mouse position and node bounds int dx = p.X + this.Indent - tn.Bounds.Left; int dy = p.Y - tn.Bounds.Top; // Begin dragging image return DragHelper.ImageList_BeginDrag(_dragImageList.Handle, 0, dx, dy); } private void tv_ItemDrag(object sender, System.Windows.Forms.ItemDragEventArgs e) { if (_doingCollapseNode) { _doingCollapseNode = false; return; } // Get drag node and select it try { TreeNode dragNode = (TreeNode)e.Item; Type t = dragNode.GetType(); //if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("Item Drag {0} - {1}", t.FullName, t.BaseType.FullName); Type t2 = Type.GetType(t.FullName); //if(t2 != null) // if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("Item Drag {0} - {1}", t2.FullName, t2.BaseType.FullName); this.SelectedNode = dragNode; ItemInfo iidrag = ((VETreeNode)dragNode).VEObject as ItemInfo; FolderInfo fdrag = ((VETreeNode)dragNode).VEObject as FolderInfo; DocVersionInfo ddrag = ((VETreeNode)dragNode).VEObject as DocVersionInfo; if ((iidrag == null && fdrag == null && ddrag == null)) { FlexibleMessageBox.Show("Cannot drag/drop a grouping node."); return; } // don't put up message, message kept coming up on any selection of node (to copy, properties, etc) //if (iidrag != null && iidrag.IsStep) return; if (SetupDragCursor(_dragImageList, dragNode)) { this.DoDragDrop(dragNode, DragDropEffects.Move | DragDropEffects.Copy);// Begin dragging DragHelper.ImageList_EndDrag();// End dragging image } } catch (Exception ex) { if(_MyLog.IsErrorEnabled)_MyLog.Error("tv_ItemDrag", ex); } } #endregion #region DragDrop ImageList _dragImageList = new ImageList(); public enum DropPosition : int { Child = 0, Before = 1, After = 2 } private class DropLocation { #region Business Methods private TreeNode _dropNode; public TreeNode DropNode { get { return _dropNode; } set { _dropNode = value; } } private int _index; public int Index { get { return _index; } set { _index = value; } } private DropPosition _position; public DropPosition Position { get { return _position; } set { _position = value; } } DateTime _lastScroll; public DateTime LastScroll { get { return _lastScroll; } } private string _location = string.Empty; #endregion #region Constructors public DropLocation(TreeView tv, System.Windows.Forms.DragEventArgs e, DateTime lastScroll) { _lastScroll = lastScroll; _dropNode = tv.GetNodeAt(tv.PointToClient(new Point(e.X, e.Y))); if (_dropNode == null) return; int OffsetY = tv.PointToClient(Cursor.Position).Y - _dropNode.Bounds.Top; if (OffsetY < _dropNode.Bounds.Height / 3) // First Third - Before { _index = _dropNode.Index; _dropNode = _dropNode.Parent; _position = DropPosition.Before; _location = string.Format("Before1 {0}[{1}] y={2}", _dropNode.Text, _index, OffsetY); } else if ((OffsetY / 2) < _dropNode.Bounds.Height / 3) // Second Third - Child { _location = string.Format("Child {0} y={1}", _dropNode.Text, OffsetY); _position = DropPosition.Child; _index = 0; //if (_dropNode.Parent == null) //{ // if(_MyLog.IsInfoEnabled)_MyLog.Info("Root Node"); //} } else // Last Third - After Now I need to check the X value { if (_dropNode.NextVisibleNode != null && _dropNode.Nodes.Count > 0 && _dropNode.IsExpanded)// Has Children & Expanded - Insert first child { // _dropNode = _dropNode.Nodes[0]; _index = 0; _position = DropPosition.Before; _location = string.Format("Before2 {0}[{1}] y={2}", _dropNode.Text, _index, OffsetY); } else // No Children or Children Collapsed - Insert Next at various levels depending upon horizontal location. { Point pt = tv.PointToClient(new Point(e.X, e.Y)); TreeNode nextParent = _dropNode.NextNode; if (nextParent != null) nextParent = nextParent.Parent; do { _index = _dropNode.Index; _dropNode = _dropNode.Parent; } while (pt.X < _dropNode.Bounds.X && _dropNode != nextParent); _location = string.Format("After {0}[{1}] y={2}", _dropNode.Text, _index, OffsetY); _position = DropPosition.After; } } LimitMoves(e); } public void LimitMoves(DragEventArgs e) { if ((e.KeyState & 8) == 0) { //TreeNode dragNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode"); //TreeNode dragNode = (TreeNode)e.Data.GetData("TreeTest.FolderTreeNode"); TreeNode dragNode = vlnTreeView.GetTreeNodeFromData(e.Data); switch (_position) { case DropPosition.Before: if (dragNode == _dropNode.Nodes[_index] || dragNode == _dropNode.Nodes[_index].PrevNode) { // if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("Before {0} {1} {2} {3} {4}", dragNode.Text ,_position.ToString() , _dropNode.Nodes[_index].Text // ,_dropNode.Nodes[_index].PrevNode,_dropNode.Nodes[_index].NextNode); _dropNode = null; } break; case DropPosition.Child: if (dragNode.Parent == _dropNode) { // if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("Child {0} {1} {2} {3} {4} {5}", dragNode.Text ,_position.ToString() , _dropNode.Nodes[_index].Text // ,_dropNode.Nodes[_index].PrevNode,_dropNode.Nodes[_index].NextNode,DateTime.Now); _dropNode = null; } break; case DropPosition.After: if (dragNode == _dropNode.Nodes[_index] || dragNode == _dropNode.Nodes[_index].NextNode) { // if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("After {0} {1} {2} {3} {4}", dragNode.Text ,_position.ToString() , _dropNode.Nodes[_index].Text // ,_dropNode.Nodes[_index].PrevNode,_dropNode.Nodes[_index].NextNode); _dropNode = null; } break; } } } #endregion public override string ToString() { return string.Format("{0}[{1}].{2}", _dropNode.Text, _index, _position.ToString()); } #region Drawing private void TreeNodeTriangle(Graphics g) { Rectangle r = _dropNode.Bounds; int RightPos = r.Right + 6; Point[] RightTriangle = new Point[]{ new Point(RightPos, r.Y ), new Point(RightPos - (r.Height / 2), r.Y + (r.Height / 2)), new Point(RightPos, r.Y + r.Height), new Point(RightPos - (r.Height / 3), r.Y + (r.Height / 2)) }; g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle); } private void InsertPointer(TreeNode tn, Graphics g) { TreeView tv = _dropNode.TreeView; Rectangle r2 = _dropNode.Nodes[_index].Bounds; Rectangle r3 = tn.Bounds; int y = (_position == DropPosition.Before ? r2.Y : r3.Bottom); int x = r2.Left; if (y == 0) { return; } //if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("Line at {0} Node {1}[{2}] {3}", _location, _dropNode.Text, _index, _position.ToString()); // Changed the color of the drag indicator to always be red Color lc = (_position == DropPosition.After ? Color.Red : Color.Red); Brush lb = (_position == DropPosition.After ? Brushes.Red : Brushes.Red); Point[] RightTriangle; if (_position == DropPosition.After) { RightTriangle = new Point[]{ new Point(x, y ), new Point(x+4, y+4), new Point(x+8, y)}; } else { RightTriangle = new Point[]{ new Point(x, y), new Point(x+4, y-4), new Point(x+8, y)}; } g.DrawLine(new System.Drawing.Pen(lc, 2), new Point(r2.Left, y), new Point(tv.Width - 8, y)); g.FillPolygon(lb, RightTriangle); } public void ShowLocation(System.Windows.Forms.DragEventArgs e, bool ScrollOnly) { //if (e.Effect == DragDropEffects.None) return; if (_dropNode != null) { // if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("ShowLocation1 {0} {1}", e.Effect.ToString(), DateTime.Now.Millisecond); DragHelper.ImageList_DragShowNolock(false); TreeView tv = _dropNode.TreeView; TreeNode tmp = tv.GetNodeAt(tv.PointToClient(new Point(e.X, e.Y))); // if (!ScrollOnly) // { if (ScrollTreeView(tmp) || !ScrollOnly) { //if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("ShowLocation2 {0} {1}", e.Effect.ToString(), DateTime.Now.Millisecond); tv.Refresh(); if (e.Effect != DragDropEffects.None) { //tv.SelectedNode = dropNode; Graphics g = tv.CreateGraphics(); TreeNodeTriangle(g); if (_position != DropPosition.Child)InsertPointer(tmp, g); } } // } // else ScrollTreeView(tmp); DragHelper.ImageList_DragShowNolock(true); } } #endregion public void ShowLocation() { //if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("{0}[{1}] {2}", _dropNode.Text, _index, _position.ToString()); } #region AutoScroll private bool ScrollTreeView(TreeNode tn) { bool retval = false; TimeSpan ts = new TimeSpan(DateTime.Now.Ticks - _lastScroll.Ticks); if (ts.Milliseconds > 100)// This controls the scroll speed { int top = tn.Bounds.Top; _lastScroll = DateTime.Now; if (tn.TreeView.ClientSize.Height < tn.Bounds.Bottom) tn.EnsureVisible();// Make sure that the current node is visible if (tn.NextVisibleNode != null && tn.TreeView.ClientSize.Height < tn.NextVisibleNode.Bounds.Bottom) tn.NextVisibleNode.EnsureVisible();// Make sure that the next node is visible else if (tn.PrevVisibleNode != null && tn.PrevVisibleNode.PrevVisibleNode != null && tn.PrevVisibleNode.PrevVisibleNode.IsVisible == false) tn.PrevVisibleNode.PrevVisibleNode.EnsureVisible();// Make sure that the previous node is visible } else if (tn.PrevVisibleNode != null && tn.PrevVisibleNode.IsVisible == false) tn.PrevVisibleNode.EnsureVisible();// Make sure that the previous node is visible retval = (top != tn.Bounds.Top); // if (retval) if(_MyLog.IsInfoEnabled)_MyLog.Info("Scroll"); } return retval; } #endregion public bool Equals(DropLocation dl) { return (dl != null && _lastScroll.Equals(dl.LastScroll) && _dropNode.Equals(dl.DropNode) && _position.Equals(dl.Position)); } } private DropLocation _LastDropLocation = null; private void tv_DragOver(object sender, System.Windows.Forms.DragEventArgs e) { try { TreeNode dragNode = GetTreeNodeFromData(e.Data); if (dragNode == null) return; // Compute drag position and move image Point formP = this.FindForm().PointToClient(new Point(e.X, e.Y)); DragHelper.ImageList_DragMove(formP.X - this.Left, formP.Y - this.Top); DropLocation dl = new DropLocation(this, e, _LastDropLocation == null ? DateTime.Now : _LastDropLocation.LastScroll); string s = string.Empty; if (dl.DropNode == null || !AllowedToMove((VETreeNode)dragNode)) { e.Effect = DragDropEffects.None; } else { DragDropEffects ee = e.Effect; if (e.KeyState == 13) // Shift and Control Keys to do a move. ee = DragDropEffects.Move; else ee = DragDropEffects.None; // Default - Do nothing if (IsChild(dragNode, dl.DropNode)) // Don't copy or move to a child node ee = DragDropEffects.None; else if (IsDocVersion((VETreeNode)dragNode)) // Don't move docversions ee = DragDropEffects.None; else if (IsFolder((VETreeNode)dragNode)) // Folder move is only valid if moving to folder with NO docversions { FolderInfo fdropi = ((VETreeNode)dl.DropNode).VEObject as FolderInfo; if (fdropi == null || fdropi.FolderDocVersionCount > 0) ee = DragDropEffects.None; } else if (IsSection((VETreeNode)dragNode)) { // A section can be moved within a procedure or to a section within the same procedure... // For HLP, just move within the same procedure // TODO: allow for section move within subsections. ProcedureInfo pdropi = ((VETreeNode)dl.DropNode).VEObject as ProcedureInfo; if (pdropi == null || (dragNode.Parent != dl.DropNode)) ee = DragDropEffects.None; } else if (!IsFolder((VETreeNode)dragNode) && (dragNode.Parent != dl.DropNode)) ee = DragDropEffects.None; if (e.Effect != ee) e.Effect = ee; dl.ShowLocation(e, dl.Equals(_LastDropLocation)); _LastDropLocation = dl; } } catch (Exception ex) { if(_MyLog.IsErrorEnabled)_MyLog.Error("tv_DragOver", ex); } } private bool IsSection(VETreeNode vETreeNode) { SectionInfo sectInfo = vETreeNode.VEObject as SectionInfo; if (sectInfo != null) return true; return false; } private bool IsProcedure(VETreeNode vETreeNode) { ProcedureInfo procInfo = vETreeNode.VEObject as ProcedureInfo; if (procInfo != null) return true; return false; } private bool IsDocVersion(VETreeNode dragNode) { DocVersionInfo dvInfo = dragNode.VEObject as DocVersionInfo; if (dvInfo != null) return true; return false; } private bool AllowedToMove(VETreeNode dragNode) { DocVersionInfo dvInfo = null; if (IsFolder(dragNode)) { FolderInfo fi = dragNode.VEObject as FolderInfo; return (MyUserInfo.IsAdministrator() || MyUserInfo.IsSetAdministrator(fi)); } else if (IsDocVersion(dragNode)) dvInfo = dragNode.VEObject as DocVersionInfo; else if (IsProcedure(dragNode)) dvInfo = (dragNode.VEObject as ProcedureInfo).MyDocVersion; else if (IsSection(dragNode)) dvInfo = (dragNode.VEObject as SectionInfo).MyDocVersion; // Bug fix B2016-274 if an Admin user also had Reviewer or ROEditor settings, admin could not move the tree node if (dvInfo != null) return (MyUserInfo.IsAdministrator() || MyUserInfo.IsSetAdministrator(dvInfo)) || MyUserInfo.IsWriter(dvInfo); return false; } private static TreeNode GetTreeNodeFromData(IDataObject datobj) { foreach (string s in datobj.GetFormats()) { try { // B2021-006: dragging text from Microsoft Word onto the tree view was crashing PROMS // This included dragging text from the Word doc editor within PROMS. Check object type: Object tmp = datobj.GetData(s); if (!(tmp is TreeNode)) return null; return (TreeNode)datobj.GetData(s); } catch (Exception ex) { if(_MyLog.IsErrorEnabled)_MyLog.Error("GetTreeNodeFromData", ex); } } return null; } private bool IsFolder(VETreeNode veTreeNode) { return (veTreeNode.VEObject.GetType() == typeof(FolderInfo)); } private void tv_DragDrop(object sender, System.Windows.Forms.DragEventArgs e) { try { TreeNode dragNode = GetTreeNodeFromData(e.Data); DragHelper.ImageList_DragLeave(this.Handle); int index = _LastDropLocation.Index + (_LastDropLocation.Position == DropPosition.After ? 1 : 0); int myIndex = index; if (dragNode.Parent == _LastDropLocation.DropNode && dragNode.Index <= _LastDropLocation.Index) index--; if (e.Effect == DragDropEffects.Move)// If Move Remove drag node from parent dragNode.Remove(); else dragNode = Clone(dragNode); _LastDropLocation.DropNode.Nodes.Insert(index, dragNode); this.SelectedNode = dragNode; FolderInfo fdragi = ((VETreeNode)dragNode).VEObject as FolderInfo; FolderInfo fdropi = ((VETreeNode)_LastDropLocation.DropNode).VEObject as FolderInfo; if (fdragi != null && fdropi != null && fdropi.FolderDocVersionCount==0) { using (Folder fdrag = fdragi.Get()) { using (Folder fdrop = fdropi.Get()) { fdrag.ManualOrder = fdropi.NewManualOrder(myIndex); fdrag.MyParent = fdrop; fdrag.Save(); } } return; } // No drag/drop supported for document versions. // Allow drag/drop of procedures within a Document Version (must have same parent). Note that drop location // may either be a document version or a procedure depending on where the user wants to position the procedure. ProcedureInfo pdragi = ((VETreeNode)dragNode).VEObject as ProcedureInfo; ProcedureInfo pdropi = null; if (pdragi != null) // moving a procedure { pdropi = ((VETreeNode)_LastDropLocation.DropNode).VEObject as ProcedureInfo; if (pdropi != null && pdragi.ActiveParent == pdropi.ActiveParent) { pdragi.MoveProcedure(pdragi.ActiveParent, myIndex); return; } DocVersionInfo dvdropi = ((VETreeNode)_LastDropLocation.DropNode).VEObject as DocVersionInfo; DocVersionInfo dvdragpar = pdragi.ActiveParent as DocVersionInfo; if (dvdropi != null && dvdragpar.VersionID == dvdropi.VersionID) { pdragi.MoveProcedure(dvdropi, myIndex); return; } } // Allow drag/drop of sections within the same procedure or same section (if subsection) (must have same parent) SectionInfo sdragi = ((VETreeNode)dragNode).VEObject as SectionInfo; SectionInfo sdropi = null; if (sdragi != null) // moving a section { sdropi = ((VETreeNode)_LastDropLocation.DropNode).VEObject as SectionInfo; if (sdropi != null && sdragi.ActiveParent == sdropi.ActiveParent) { sdragi.MoveSection(sdragi, myIndex); return; } pdropi = ((VETreeNode)_LastDropLocation.DropNode).VEObject as ProcedureInfo; if (pdropi != null && ((ItemInfo)(sdragi.ActiveParent)).ItemID == pdropi.ItemID) { sdragi.MoveSection(pdropi, myIndex); sdragi.Moving = true; OnNodeSelect(dragNode, new vlnTreeEventArgs(dragNode)); return; } } // Allow drag/drop of steps within the same parent only StepInfo stdragi = ((VETreeNode)dragNode).VEObject as StepInfo; StepInfo stdropi = null; if (stdragi != null) // moving a step { stdropi = ((VETreeNode)_LastDropLocation.DropNode).VEObject as StepInfo; if (stdropi != null && stdragi.ActiveParent == stdropi.ActiveParent) { stdragi.MoveStep(stdragi.ActiveParent, myIndex); return; } sdropi = ((VETreeNode)_LastDropLocation.DropNode).VEObject as SectionInfo; if (sdropi != null && stdragi.MyParent.ItemID == sdropi.ItemID) { stdragi.MoveStep(stdragi.ActiveParent, myIndex); return; } // the following handles items under the app nodes of 'steps', 'notes', 'cautions', etc. if (sdropi == null && dragNode.Parent == _LastDropLocation.DropNode) { stdragi.MoveStep(stdragi.ActiveParent, myIndex); return; } } } catch (Exception ex) { if(_MyLog.IsErrorEnabled)_MyLog.Error("tv_DragDrop", ex); } } // private void DumpMembers(object o) // { // Type t = o.GetType(); // //if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("\r\n\r\nMembers for type {0}", t.ToString()); // MemberInfo[] mis = t.GetMembers(); // int i = 0; // foreach (MemberInfo mi in mis) // { // i++; // try // { // //if(mi.MemberType != MemberTypes.Method) // //if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("{0} {1} {2}", i, mi.Name, mi.MemberType); //// if (fi.Name == "TreeView") //// fi.SetValue(o, null); // } // catch (Exception ex) // { // if(_MyLog.IsErrorEnabled)_MyLog.Error("DumpMembers", ex); // } // } // } private TreeNode Clone(TreeNode tn) { TreeNode tmp = (TreeNode)tn.Clone(); ExpandMatch(tmp,tn); return tmp; } private void tv_DragDropOld(object sender, System.Windows.Forms.DragEventArgs e) { TreeNode dragNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");// Get the drag node DragHelper.ImageList_DragLeave(this.Handle); TreeNode cloneNode = (TreeNode)dragNode.Clone();// copy the source node ExpandMatch(cloneNode, dragNode); _LastDropLocation.DropNode.Nodes.Insert(_LastDropLocation.Index + (_LastDropLocation.Position == DropPosition.After ? 1 : 0), cloneNode); if (e.Effect == DragDropEffects.Move)// If Move Remove drag node from parent dragNode.Remove(); this.SelectedNode = cloneNode; } private void tv_DragEnter(object sender, System.Windows.Forms.DragEventArgs e) { DragHelper.ImageList_DragEnter(this.Handle, e.X - this.Left, e.Y - this.Top); } private void tv_DragLeave(object sender, System.EventArgs e) { DragHelper.ImageList_DragLeave(this.Handle); this.Refresh(); } private void ExpandMatch(TreeNode tn1, TreeNode tn2) { if (tn2.IsExpanded) tn1.Expand(); foreach (TreeNode tc in tn2.Nodes) ExpandMatch(tn1.Nodes[tc.Index], tc); } private bool IsChild(TreeNode parent, TreeNode child) { if (parent.Equals(child)) return true;// Check against self foreach (TreeNode tc in parent.Nodes) if (IsChild(tc, child)) return true;//Check all children return false;// Must not be a child at this level } #endregion private bool _AdjustingTree = false; public void AdjustTree(ItemInfo selectedItem) { // start at the top parent and walk down the nodes to find child if (selectedItem == null) return; VETreeNode node = FindNodeAndExpand(selectedItem); if (node != null) { _AdjustingTree = true; this.SelectedNode = node; _AdjustingTree = false; } } public VETreeNode FindNodeAndExpand(IVEDrillDownReadOnly selectedItem) { if (selectedItem.ActiveParent == null) { return (VETreeNode)this.Nodes[0]; // Return the top node } if (selectedItem == ((VETreeNode)this.Nodes[0]).VEObject) return (VETreeNode)this.Nodes[0]; // C2015-022 check needed for tree in child windows VETreeNode parent = FindNodeAndExpand(selectedItem.ActiveParent); if (parent == null) return null; if (!parent.IsExpanded) parent.Expand(); VETreeNode child = GetChildNode(selectedItem, parent); if (child != null) return child; parent.ChildrenLoaded = false; parent.RefreshNode(); child = GetChildNode(selectedItem, parent); return child; } public VETreeNode FindNode(IVEDrillDownReadOnly selectedItem, TreeNodeCollection tnc) { foreach (TreeNode tn in tnc) if (tn is VETreeNode) { if ((tn as VETreeNode).VEObject is ItemInfo && (selectedItem is ItemInfo) && ((tn as VETreeNode).VEObject as ItemInfo).ItemID == (selectedItem as ItemInfo).ItemID) return tn as VETreeNode; else { VETreeNode cn = FindNode(selectedItem, tn.Nodes); if (cn != null) return cn; } } return null; } public VETreeNode RefreshRelatedNode(IVEDrillDownReadOnly selectedItem) { Console.WriteLine("vlntreeview:refreshrelatednote:start"); VETreeNode child = FindNode(selectedItem, this.Nodes); if (child == null) return null; if (!child.IsExpanded) child.Expand(); child.ChildrenLoaded = false; child.RefreshNode(); Console.WriteLine("vlntreeview:refreshrelatednote:end"); return child; } // B2021-066: refresh the procedure numbers within Working Draft (docversion) for applicability changed public void RefreshDocVersion() { VETreeNode vetn = SelectedNode as VETreeNode; if (vetn != null) { DocVersionInfo dvi = vetn.VEObject as DocVersionInfo; if (dvi != null) { if (SelectedNode.Nodes != null && SelectedNode.Nodes.Count > 0 && SelectedNode.Nodes[0] is VETreeNode) { foreach (VETreeNode tn in SelectedNode.Nodes) { tn.RefreshNode(); } } } } } private VETreeNode GetChildNode(IVEDrillDownReadOnly selectedItem, VETreeNode parent) { foreach (TreeNode childNode in parent.Nodes) { VETreeNode child = childNode as VETreeNode; if (child != null && CompareVEObject(child.VEObject, selectedItem)) return child; } foreach (TreeNode childNode in parent.Nodes) { VETreeNode child = childNode as VETreeNode; if (child.VEObject is PartInfo) foreach (VETreeNode grandchild in child.Nodes) if (CompareVEObject(grandchild.VEObject, selectedItem)) return grandchild; } return null; } public bool CompareVEObject(IVEDrillDownReadOnly obj1, IVEDrillDownReadOnly obj2) { if (obj1.GetType().Name != obj2.GetType().Name) { // see if both can be cast as ItemInfo, because 1st check may be comparing ItemInfo & ProcedureInfo and returns // false even though they are same base object type (fixes bug B2016-094) ItemInfo ii1 = obj1 as ItemInfo; ItemInfo ii2 = obj2 as ItemInfo; if (ii1 == null || ii2 == null) return false; } ItemInfo myItem = obj1 as ItemInfo; if (myItem != null) if (myItem.ItemID == ((ItemInfo)obj2).ItemID) return true; DocVersionInfo myDV = obj1 as DocVersionInfo; if (myDV != null) if (myDV.VersionID == ((DocVersionInfo)obj2).VersionID) return true; FolderInfo myFolder = obj1 as FolderInfo; if (myFolder != null) if (myFolder.FolderID == ((FolderInfo)obj2).FolderID) return true; return false; } } #region DragHelper public class DragHelper { [DllImport("comctl32.dll")] public static extern bool InitCommonControls(); [DllImport("comctl32.dll", CharSet = CharSet.Auto)] public static extern bool ImageList_BeginDrag(IntPtr himlTrack, int iTrack, int dxHotspot, int dyHotspot); [DllImport("comctl32.dll", CharSet = CharSet.Auto)] public static extern bool ImageList_DragMove(int x, int y); [DllImport("comctl32.dll", CharSet = CharSet.Auto)] public static extern void ImageList_EndDrag(); [DllImport("comctl32.dll", CharSet = CharSet.Auto)] public static extern bool ImageList_DragEnter(IntPtr hwndLock, int x, int y); [DllImport("comctl32.dll", CharSet = CharSet.Auto)] public static extern bool ImageList_DragLeave(IntPtr hwndLock); [DllImport("comctl32.dll", CharSet = CharSet.Auto)] public static extern bool ImageList_DragShowNolock(bool fShow); static DragHelper() { InitCommonControls(); } } #endregion }