449 lines
18 KiB
C#
449 lines
18 KiB
C#
using System;
|
|
using System.Windows.Forms;
|
|
using System.Collections;
|
|
using System.Reflection;
|
|
|
|
namespace VEPROMS.CSLA.Library
|
|
{
|
|
public delegate void VETreeNodeEvent(object sender, VETreeNodeEventArgs args);
|
|
public class VETreeNodeEventArgs : EventArgs
|
|
{
|
|
public VETreeNodeEventArgs() { ; }
|
|
public VETreeNodeEventArgs(string info) => Info = info;
|
|
public VETreeNodeEventArgs(int value) => Value = value;
|
|
public VETreeNodeEventArgs(string info, int value)
|
|
{
|
|
Info = info;
|
|
Value = value;
|
|
}
|
|
|
|
public int Value { get; set; }
|
|
|
|
public string Info { get; set; }
|
|
|
|
}
|
|
public class VETreeNode : TreeNode
|
|
{
|
|
#region Events
|
|
private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
|
public event VETreeNodeEvent LoadingChildrenSQL;
|
|
public event VETreeNodeEvent LoadingChildrenMax;
|
|
public event VETreeNodeEvent LoadingChildrenValue;
|
|
public event VETreeNodeEvent LoadingChildrenDone;
|
|
private void OnLoadingChildrenSQL(object sender, VETreeNodeEventArgs args) => LoadingChildrenSQL?.Invoke(sender, args);
|
|
private void OnLoadingChildrenMax(object sender, VETreeNodeEventArgs args) => LoadingChildrenMax?.Invoke(sender, args);
|
|
private void OnLoadingChildrenValue(object sender, VETreeNodeEventArgs args) => LoadingChildrenValue?.Invoke(sender, args);
|
|
private void OnLoadingChildrenDone(object sender, VETreeNodeEventArgs args) => LoadingChildrenDone?.Invoke(sender, args);
|
|
#endregion
|
|
#region Business Methods
|
|
protected IVEDrillDownReadOnly _VEObject;
|
|
public IVEDrillDownReadOnly VEObject
|
|
{
|
|
get { return _VEObject; }
|
|
set
|
|
{
|
|
_VEObject = value;
|
|
base.Text = _VEObject.ToString();
|
|
ResetNode("Dummy Set_VEObject");
|
|
}
|
|
}
|
|
// Only load the Children Once
|
|
protected bool _ChildrenLoaded = false;
|
|
public bool ChildrenLoaded
|
|
{
|
|
get { return _ChildrenLoaded; }
|
|
set { _ChildrenLoaded = value; }
|
|
}
|
|
protected bool _MovedToSeparateWindow = false; // C2015-022 tells us this tree node and childern are now in a child window (separate Window) - used on Parent window side for a folder context menu
|
|
public bool MovedToSeparateWindow
|
|
{
|
|
get { return _MovedToSeparateWindow; }
|
|
set { _MovedToSeparateWindow = value; }
|
|
}
|
|
protected bool _InChildWindow = false; // C2015-022 tells us this tree node is in the child window - used on child window side for folder context menu
|
|
public bool InChildWindow
|
|
{
|
|
get { return _InChildWindow; }
|
|
set { _InChildWindow = value; }
|
|
}
|
|
private void SetProperty(string name)
|
|
{
|
|
PropertyInfo propertyInfoObj = _VEObject.GetType().GetProperty(name);
|
|
if (propertyInfoObj == null) return;
|
|
PropertyInfo propertyInfoThis = GetType().GetProperty(name);
|
|
if (propertyInfoThis == null) return;
|
|
try
|
|
{
|
|
propertyInfoThis.SetValue(this, propertyInfoObj.GetValue(_VEObject, null), null);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine("Error: {0}", ex.Message);
|
|
}
|
|
}
|
|
public void ResetNode(string dummy)
|
|
{
|
|
if (_VEObject!=null && _VEObject.HasChildren && _ChildrenLoaded == false && CheckForParts())
|
|
{
|
|
_ChildrenLoaded = false;// Reset the children loaded flag
|
|
Nodes.Add(dummy);// Add a Dummy Node so that the item will appear to be expanable.
|
|
}
|
|
else
|
|
{
|
|
_ChildrenLoaded = true;// Reset the children loaded flag
|
|
}
|
|
if (base.Text != _VEObject.ToString()) base.Text = _VEObject.ToString();
|
|
SetProperty("ForeColor");
|
|
SetProperty("BackColor");
|
|
SetProperty("ImageIndex");
|
|
SetProperty("IsVisible");
|
|
SetProperty("SelectedImageIndex");
|
|
// ToDo: Need to reset object as well
|
|
}
|
|
|
|
private bool CheckForParts()
|
|
{
|
|
if (_allParts) return true;
|
|
// only has 'children' if parts are steps or sections
|
|
if (_VEObject.GetType() == typeof(StepInfo) || _VEObject.GetType() == typeof(SectionInfo) || _VEObject.GetType() == typeof(ItemInfo))
|
|
{
|
|
IList ol = ((ItemInfo)_VEObject).GetChildren(_allParts);
|
|
if (ol == null || ol.Count == 0) return false;
|
|
}
|
|
return true;
|
|
}
|
|
public void RefreshNode()
|
|
{
|
|
ResetNode("Dummy RefreshNode");// Drop Children
|
|
LoadChildren();// Load Children
|
|
}
|
|
public static VETreeNode GetFolder(int folderID)
|
|
{
|
|
VETreeNode tn = new VETreeNode(FolderInfo.Get(folderID));
|
|
//tn.Nodes.Add("Dummy");
|
|
tn.ResetNode("Dummy GetFolder");
|
|
return tn;
|
|
}
|
|
public virtual void LoadChildren() => LoadChildren(true);
|
|
private bool _allParts = true;
|
|
private bool _excludeTablesFigsEqu = false; // used for inserting Step Text transitions (BNPP)
|
|
public virtual void LoadChildren(bool allParts, bool excldTablesFigEq = false)
|
|
{
|
|
_allParts = allParts;
|
|
// B2024-019 don't show Tables, Figures, or Equations in step tree when inserting Text Transitions
|
|
_excludeTablesFigsEqu = excldTablesFigEq;
|
|
if (!_ChildrenLoaded)
|
|
{
|
|
Nodes.Clear();
|
|
DateTime tStart = DateTime.Now;
|
|
OnLoadingChildrenSQL(this, new VETreeNodeEventArgs());
|
|
IList ol;
|
|
if (_VEObject is ItemInfo item) item.RefreshItemParts();
|
|
if (_VEObject.GetType() == typeof(StepInfo) || _VEObject.GetType() == typeof(SectionInfo) || _VEObject.GetType() == typeof(ItemInfo))
|
|
ol = ((ItemInfo)_VEObject).GetChildren(allParts);
|
|
else
|
|
ol = _VEObject.GetChildren();
|
|
if (ol != null)
|
|
{
|
|
OnLoadingChildrenMax(this, new VETreeNodeEventArgs(ol.Count));
|
|
if (TreeView != null) TreeView.BeginUpdate();
|
|
else _MyLog.WarnFormat("TreeView.BeginUpdate - Null");
|
|
ExpandChildren(ol);
|
|
if (TreeView != null) TreeView.EndUpdate();
|
|
else _MyLog.WarnFormat("TreeView.EndUpdate - Null");
|
|
}
|
|
_ChildrenLoaded = true;
|
|
OnLoadingChildrenDone(this, new VETreeNodeEventArgs(TimeSpan.FromTicks(DateTime.Now.Ticks - tStart.Ticks).TotalSeconds.ToString()));
|
|
}
|
|
}
|
|
|
|
private void ExpandChildren(IList ol)
|
|
{
|
|
int icnt = 0;
|
|
bool lastWasSection = false;
|
|
foreach (IVEDrillDownReadOnly o in ol)
|
|
{
|
|
OnLoadingChildrenValue(this, new VETreeNodeEventArgs(++icnt));
|
|
try
|
|
{
|
|
bool skipIt = false;
|
|
bool isStepPart = (o is PartInfo && (o as PartInfo).PartType == E_FromType.Step);
|
|
if (isStepPart)
|
|
{
|
|
|
|
// get parent section and see if it has the Editable flag set. Only skip
|
|
// if this flag is set to "N".
|
|
ItemInfo sectInfo = (ItemInfo)(o as PartInfo).ActiveParent;
|
|
bool hasMetaSubs = sectInfo != null && sectInfo.Sections != null && sectInfo.Sections.Count > 0;
|
|
bool editSteps = !hasMetaSubs || (sectInfo.MyConfig is SectionConfig && (sectInfo.MyConfig as SectionConfig).SubSection_Edit == "Y");
|
|
if (!editSteps) skipIt = true;
|
|
}
|
|
if (!skipIt)
|
|
{
|
|
VETreeNode tmp = new VETreeNode(o, _allParts);
|
|
// B2024-019 don't show Tables, Figures, or Equations in step tree when inserting Text Transitions
|
|
bool isTableFigEqu = tmp.Text.Equals("Table") ||
|
|
tmp.Text.Equals("Figure") ||
|
|
tmp.Text.Equals("Equation");
|
|
if (o.HasChildren)
|
|
{
|
|
if (o is PartInfo)
|
|
{
|
|
tmp.Nodes.Clear();
|
|
tmp.ExpandChildren(o.GetChildren());
|
|
tmp._ChildrenLoaded = true;
|
|
}
|
|
}
|
|
else
|
|
tmp._ChildrenLoaded = true;// Reset the children loaded flag
|
|
if (lastWasSection)
|
|
Nodes.Insert(0, tmp);
|
|
// B2024-019 don't show Tables, Figures, or Equations in step tree when inserting Text Transitions
|
|
else if (!_excludeTablesFigsEqu || !isTableFigEqu)
|
|
Nodes.Add(tmp);
|
|
// if last thing was section & this is step, do insert - i.e. so that steps go before sections.
|
|
lastWasSection = (o is PartInfo && (o as PartInfo).PartType == E_FromType.Section);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine("{0}\r\n{1}", ex.Message, ex.InnerException);
|
|
}
|
|
}
|
|
}
|
|
private void TVAddChildren(IVEDrillDownReadOnly veobj, VETreeNode tn)
|
|
{
|
|
OnLoadingChildrenSQL(tn, new VETreeNodeEventArgs());
|
|
IList ol;
|
|
if (veobj.GetType() == typeof(StepInfo) || veobj.GetType() == typeof(SectionInfo) || veobj.GetType() == typeof(ItemInfo))
|
|
ol = ((ItemInfo)veobj).GetChildren(true);
|
|
else
|
|
ol = veobj.GetChildren();
|
|
if (ol != null)
|
|
{
|
|
OnLoadingChildrenMax(this, new VETreeNodeEventArgs(ol.Count));
|
|
TreeView.BeginUpdate();
|
|
int icnt = 0;
|
|
foreach (IVEDrillDownReadOnly o in ol)
|
|
{
|
|
OnLoadingChildrenValue(this, new VETreeNodeEventArgs(++icnt));
|
|
try
|
|
{
|
|
VETreeNode tmp = new VETreeNode(o);
|
|
PartInfo pi = o as PartInfo;
|
|
if (pi == null && o.HasChildren)
|
|
tmp.Nodes.Add("Dummy");// Add a Dummy Node so that the item will appear to be expanable.
|
|
else
|
|
tmp._ChildrenLoaded = true;// Reset the children loaded flag
|
|
tn.Nodes.Add(tmp);
|
|
if (pi != null && o.HasChildren)
|
|
TVAddChildren(o, tmp);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine("{0}\r\n{1}", ex.Message, ex.InnerException);
|
|
}
|
|
}
|
|
TreeView.EndUpdate();
|
|
}
|
|
}
|
|
void myItemInfo_Deleted(object sender)
|
|
{
|
|
if (!(Parent is VETreeNode parnode)) return;
|
|
Remove();
|
|
// get rid of 'Steps', 'RNOs', i.e. grouping nodes, if there are no children.
|
|
if (parnode.VEObject is PartInfo && parnode.Nodes.Count == 0)
|
|
{
|
|
parnode.Remove();
|
|
// if only 'Steps' node is left, move steps 'up' a level.
|
|
if (parnode.Parent is VETreeNode grndparnode && grndparnode.Nodes.Count == 1)
|
|
{
|
|
VETreeNode sibnode = grndparnode.Nodes[0] as VETreeNode;
|
|
if (sibnode.VEObject is PartInfo pisib && (pisib.ToString() == "Steps"))
|
|
{
|
|
if (!sibnode.ChildrenLoaded) sibnode.LoadChildren();
|
|
while (sibnode.Nodes.Count > 0)
|
|
{
|
|
VETreeNode tmp = sibnode.Nodes[0] as VETreeNode;
|
|
tmp.Remove();
|
|
grndparnode.Nodes.Add(tmp);
|
|
}
|
|
sibnode.Remove();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
#region Factory Methods
|
|
// Constructors
|
|
public VETreeNode() : base("NoText") { ; }
|
|
public VETreeNode(IVEDrillDownReadOnly o, bool allParts)
|
|
: base(o.ToString())
|
|
{
|
|
_allParts = allParts;
|
|
_VEObject = o;// Save the BusinessObject
|
|
ResetNode("Dummy VETreeNode(IVEDrillDownReadOnly o)");
|
|
if (o is ItemInfo myItemInfo)
|
|
{
|
|
myItemInfo.Deleted -= new ItemInfoEvent(myItemInfo_Deleted);
|
|
myItemInfo.Deleted += new ItemInfoEvent(myItemInfo_Deleted);
|
|
myItemInfo.ChildrenDeleted -= new ItemInfoEvent(myItemInfo_ChildrenDeleted);
|
|
myItemInfo.ChildrenDeleted += new ItemInfoEvent(myItemInfo_ChildrenDeleted);
|
|
myItemInfo.MyContent.Changed -= new ContentInfoEvent(NodeText_Changed);
|
|
myItemInfo.MyContent.Changed += new ContentInfoEvent(NodeText_Changed);
|
|
myItemInfo.OrdinalChanged -= new ItemInfoEvent(NodeText_Changed);
|
|
myItemInfo.OrdinalChanged += new ItemInfoEvent(NodeText_Changed);
|
|
myItemInfo.NewSiblingAfter -= new ItemInfoInsertEvent(myItemInfo_NewSiblingAfter);
|
|
myItemInfo.NewSiblingAfter += new ItemInfoInsertEvent(myItemInfo_NewSiblingAfter);
|
|
myItemInfo.NewSiblingBefore -= new ItemInfoInsertEvent(myItemInfo_NewSiblingBefore);
|
|
myItemInfo.NewSiblingBefore += new ItemInfoInsertEvent(myItemInfo_NewSiblingBefore);
|
|
myItemInfo.NewChild -= new ItemInfoInsertEvent(myItemInfo_NewChild);
|
|
myItemInfo.NewChild += new ItemInfoInsertEvent(myItemInfo_NewChild);
|
|
}
|
|
}
|
|
void NodeText_Changed(object sender)
|
|
{
|
|
Text = _VEObject.ToString();
|
|
ItemInfo myItemInfo = _VEObject as ItemInfo;
|
|
if (myItemInfo != null && myItemInfo.MyDocVersion.DocVersionConfig.SelectedSlave > 0)
|
|
{
|
|
int k = myItemInfo.MyDocVersion.DocVersionConfig.SelectedSlave;
|
|
myItemInfo.MyDocVersion.DocVersionConfig.SelectedSlave = 0;
|
|
Text = myItemInfo.ToString();
|
|
myItemInfo.MyDocVersion.DocVersionConfig.SelectedSlave = k;
|
|
}
|
|
if (myItemInfo != null && myItemInfo.IsSection)
|
|
{
|
|
myItemInfo.RefreshConfig();
|
|
// check if metasection & has subsections. This could be a change in config
|
|
// item, i.e. Editable Data, that would add or remove any step nodes, i.e. requires a
|
|
// tree refresh.
|
|
if (myItemInfo.Sections != null && myItemInfo.Sections.Count > 0 && myItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.UseMetaSections)
|
|
{
|
|
// see if change in children tree nodes.
|
|
Nodes.Clear();
|
|
_ChildrenLoaded = false;
|
|
LoadChildren(true);
|
|
}
|
|
}
|
|
}
|
|
public VETreeNode(IVEDrillDownReadOnly o)
|
|
: base(o.ToString())
|
|
{
|
|
_VEObject = o;// Save the BusinessObject
|
|
ResetNode("Dummy VETreeNode(IVEDrillDownReadOnly o)");
|
|
if (o is ItemInfo myItemInfo)
|
|
{
|
|
myItemInfo.Deleted -= new ItemInfoEvent(myItemInfo_Deleted);
|
|
myItemInfo.Deleted += new ItemInfoEvent(myItemInfo_Deleted);
|
|
myItemInfo.ChildrenDeleted -= new ItemInfoEvent(myItemInfo_ChildrenDeleted);
|
|
myItemInfo.ChildrenDeleted += new ItemInfoEvent(myItemInfo_ChildrenDeleted);
|
|
myItemInfo.MyContent.Changed -= new ContentInfoEvent(NodeText_Changed);
|
|
myItemInfo.MyContent.Changed += new ContentInfoEvent(NodeText_Changed);
|
|
myItemInfo.OrdinalChanged -= new ItemInfoEvent(NodeText_Changed);
|
|
myItemInfo.OrdinalChanged += new ItemInfoEvent(NodeText_Changed);
|
|
myItemInfo.NewSiblingAfter -= new ItemInfoInsertEvent(myItemInfo_NewSiblingAfter);
|
|
myItemInfo.NewSiblingAfter += new ItemInfoInsertEvent(myItemInfo_NewSiblingAfter);
|
|
myItemInfo.NewSiblingBefore -= new ItemInfoInsertEvent(myItemInfo_NewSiblingBefore);
|
|
myItemInfo.NewSiblingBefore += new ItemInfoInsertEvent(myItemInfo_NewSiblingBefore);
|
|
myItemInfo.NewChild -= new ItemInfoInsertEvent(myItemInfo_NewChild);
|
|
myItemInfo.NewChild += new ItemInfoInsertEvent(myItemInfo_NewChild);
|
|
}
|
|
}
|
|
|
|
void myItemInfo_ChildrenDeleted(object sender)
|
|
{
|
|
//Console.WriteLine("Fix Children");
|
|
ItemInfo myItemInfo = VEObject as ItemInfo;
|
|
//if (Nodes.Count > 1)
|
|
// Console.WriteLine("{0}, {1}",Nodes[0], Nodes[1]);
|
|
|
|
if (!myItemInfo.HasChildren && Nodes.Count>0 && !(Nodes[0] is VETreeNode))
|
|
Nodes.Clear();
|
|
}
|
|
void myItemInfo_NewChild(object sender, ItemInfoInsertEventArgs args)
|
|
{
|
|
if (args.ItemInserted.NextItem != null) // insert before
|
|
{
|
|
int nextItemID = args.ItemInserted.NextItem.ItemID;
|
|
VETreeNode nextNode = FindChildOrGrandChild(nextItemID);
|
|
nextNode?.myItemInfo_NewSiblingBefore(sender, args);
|
|
return;
|
|
}
|
|
if (args.ItemInserted.MyPrevious != null) // insert after
|
|
{
|
|
int prevItemID = args.ItemInserted.MyPrevious.ItemID;
|
|
VETreeNode prevNode = FindChildOrGrandChild(prevItemID);
|
|
prevNode.myItemInfo_NewSiblingAfter(sender, args);
|
|
return;
|
|
}
|
|
bool isExpanded = IsExpanded;
|
|
// Restore the tree as it currently is expanded.
|
|
Collapse();
|
|
Nodes.Clear();
|
|
_ChildrenLoaded = false;
|
|
ResetNode("Dummy myItemInfo_NewChild");
|
|
if (isExpanded && VEObject is ItemInfo item && item.MyContent.ContentPartCount > 1) // || args.ItemInserted.NextItem != null || args.ItemInserted.MyPrevious != null))
|
|
Expand();
|
|
else
|
|
Collapse();
|
|
}
|
|
private VETreeNode FindChildOrGrandChild(int itemID)
|
|
{
|
|
foreach (TreeNode childNode in Nodes)
|
|
{
|
|
if (childNode is VETreeNode child)
|
|
{
|
|
if (child.VEObject is ItemInfo item && item.ItemID == itemID)
|
|
return child;
|
|
}
|
|
}
|
|
foreach (TreeNode childNode in Nodes)
|
|
{
|
|
if (childNode is VETreeNode child && child.VEObject is PartInfo)
|
|
foreach (VETreeNode grandchild in child.Nodes)
|
|
{
|
|
if (grandchild.VEObject is ItemInfo item && item.ItemID == itemID)
|
|
return grandchild;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
void myItemInfo_NewSiblingBefore(object sender, ItemInfoInsertEventArgs args)
|
|
{
|
|
if (Parent != null) // Only do this if the node has a parent - RHM 20100106
|
|
{
|
|
if (!(args.ItemInserted is ItemInfo ii))
|
|
Parent.Nodes.Insert(Index, (new VETreeNode(args.ItemInserted)));
|
|
else // B2020-142: Can't get properties of restored item (no treeview context menu would be correct after restore)
|
|
{
|
|
if (ii.IsProcedure) Parent.Nodes.Insert(Index, (new VETreeNode(ProcedureInfo.Get(ii.ItemID))));
|
|
if (ii.IsSection) Parent.Nodes.Insert(Index, (new VETreeNode(SectionInfo.Get(ii.ItemID))));
|
|
if (ii.IsStep) Parent.Nodes.Insert(Index, (new VETreeNode(StepInfo.Get(ii.ItemID))));
|
|
}
|
|
}
|
|
}
|
|
void myItemInfo_NewSiblingAfter(object sender, ItemInfoInsertEventArgs args)
|
|
{
|
|
if (Parent != null) // Only do this if the node has a parent - RHM 20100106
|
|
{
|
|
if (!(args.ItemInserted is ItemInfo ii))
|
|
Parent.Nodes.Insert(Index + 1, (new VETreeNode(args.ItemInserted)));
|
|
else // B2020-142: Can't get properties of restored item (no treeview context menu would be correct after restore)
|
|
{
|
|
if (ii.IsProcedure) Parent.Nodes.Insert(Index + 1, (new VETreeNode(ProcedureInfo.Get(ii.ItemID))));
|
|
if (ii.IsSection) Parent.Nodes.Insert(Index + 1, (new VETreeNode(SectionInfo.Get(ii.ItemID))));
|
|
if (ii.IsStep) Parent.Nodes.Insert(Index + 1, (new VETreeNode(StepInfo.Get(ii.ItemID))));
|
|
}
|
|
}
|
|
}
|
|
public VETreeNode(string s)
|
|
: base(s)
|
|
{
|
|
_VEObject = null;// Save the BusinessObject
|
|
}
|
|
#endregion
|
|
}
|
|
}
|