using System; using System.Windows.Forms; using System.Drawing; using System.Collections.Generic; using System.Diagnostics; using System.ComponentModel; using System.ComponentModel.Design; using System.ComponentModel.Design.Serialization; using System.Drawing.Design; using System.Text; namespace BismNormalizer.TabularCompare.UI { [ ToolboxItem(false), DesignTimeVisible(false) ] public class TreeGridNode : DataGridViewRow//, IComponent { internal TreeGridView _grid; internal TreeGridNode _parent; internal TreeGridNodeCollection _owner; internal bool IsExpanded; internal bool IsRoot; internal bool _isSited; internal bool _isFirstSibling; internal bool _isLastSibling; internal Image _image; internal int _imageIndex; private Random rndSeed = new Random(); public int UniqueValue = -1; TreeGridCell _treeCell; TreeGridNodeCollection childrenNodes; private int _index; private int _level; private bool childCellsCreated = false; // needed for IComponent private ISite site = null; private EventHandler disposed = null; internal TreeGridNode(TreeGridView owner) : this() { this._grid = owner; this.IsExpanded = true; } public TreeGridNode() { _index = -1; _level = -1; IsExpanded = false; UniqueValue = this.rndSeed.Next(); _isSited = false; _isFirstSibling = false; _isLastSibling = false; _imageIndex = -1; } public override object Clone() { TreeGridNode r = (TreeGridNode)base.Clone(); r.UniqueValue = -1; r._level = this._level; r._grid = this._grid; r._parent = this.Parent; r._imageIndex = this._imageIndex; if (r._imageIndex == -1) r.Image = this.Image; r.IsExpanded = this.IsExpanded; //r.treeCell = new TreeGridCell(); return r; } internal protected virtual void UnSited() { // This row is being removed from being displayed on the grid. TreeGridCell cell; foreach (DataGridViewCell DGVcell in this.Cells) { cell = DGVcell as TreeGridCell; if (cell != null) { cell.UnSited(); } } this._isSited = false; } internal protected virtual void Sited() { // This row is being added to the grid. this._isSited = true; this.childCellsCreated = true; Debug.Assert(this._grid != null); TreeGridCell cell; foreach (DataGridViewCell DGVcell in this.Cells) { cell = DGVcell as TreeGridCell; if (cell != null) { cell.Sited();// Level = this.Level; } } } // Represents the index of this row in the Grid [System.ComponentModel.Description("Represents the index of this row in the Grid. Advanced usage."), System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public int RowIndex => base.Index; // Represents the index of this row based upon its position in the collection. [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public new int Index { get { if (_index == -1) { // get the index from the collection if unknown _index = this._owner.IndexOf(this); } return _index; } internal set { _index = value; } } [Browsable(false), EditorBrowsable( EditorBrowsableState.Never), DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden)] public ImageList ImageList { get { if (this._grid != null) return this._grid.ImageList; else return null; } } private bool ShouldSerializeImageIndex() => (this._imageIndex != -1 && this._image == null); [Category("Appearance"), Description("..."), DefaultValue(-1), TypeConverter(typeof(ImageIndexConverter)), Editor("System.Windows.Forms.Design.ImageIndexEditor", typeof(UITypeEditor))] public int ImageIndex { get { return _imageIndex; } set { _imageIndex = value; if (_imageIndex != -1) { // when a imageIndex is provided we do not store the image. this._image = null; } if (this._isSited) { // when the image changes the cell's style must be updated this._treeCell.UpdateStyle(); if (this.Displayed) this._grid.InvalidateRow(this.RowIndex); } } } private bool ShouldSerializeImage() => (this._imageIndex == -1 && this._image != null); public Image Image { get { if (_image == null && _imageIndex != -1) { if (this.ImageList != null && this._imageIndex < this.ImageList.Images.Count) { // get image from image index return this.ImageList.Images[this._imageIndex]; } else return null; } else { // image from image property return this._image; }; } set { _image = value; if (_image != null) { // when a image is provided we do not store the imageIndex. this._imageIndex = -1; } if (this._isSited) { // when the image changes the cell's style must be updated this._treeCell.UpdateStyle(); if (this.Displayed) this._grid.InvalidateRow(this.RowIndex); } } } protected override DataGridViewCellCollection CreateCellsInstance() { DataGridViewCellCollection cells = base.CreateCellsInstance(); cells.CollectionChanged += cells_CollectionChanged; return cells; } void cells_CollectionChanged(object sender, System.ComponentModel.CollectionChangeEventArgs e) { // Exit if there already is a tree cell for this row if (_treeCell != null) return; if (e.Action == System.ComponentModel.CollectionChangeAction.Add || e.Action == System.ComponentModel.CollectionChangeAction.Refresh) { TreeGridCell treeCell = null; if (e.Element == null) { foreach (DataGridViewCell cell in base.Cells) { if (cell.GetType().IsAssignableFrom(typeof(TreeGridCell))) { treeCell = (TreeGridCell)cell; break; } } } else { treeCell = e.Element as TreeGridCell; } if (treeCell != null) _treeCell = treeCell; } } [Category("Data"), Description("The collection of root nodes in the treelist."), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] //, //Editor(typeof(CollectionEditor), typeof(UITypeEditor))] public TreeGridNodeCollection Nodes { get { if (childrenNodes == null) { childrenNodes = new TreeGridNodeCollection(this); } return childrenNodes; } set { ;} } // Create a new Cell property because by default a row is not in the grid and won't // have any cells. We have to fabricate the cell collection ourself. [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public new DataGridViewCellCollection Cells { get { if (!childCellsCreated && this.DataGridView == null) { if (this._grid == null) return null; this.CreateCells(this._grid); childCellsCreated = true; } return base.Cells; } } [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public int Level { get { if (this._level == -1) { // calculate level int walk = 0; TreeGridNode walkRow = this.Parent; while (walkRow != null) { walk++; walkRow = walkRow.Parent; } this._level = walk; } return this._level; } } [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public TreeGridNode Parent => this._parent; [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public virtual bool HasChildren => (this.childrenNodes != null && this.Nodes.Count != 0); [Browsable(false)] public bool IsSited => this._isSited; [Browsable(false)] public bool IsFirstSibling => (this.Index == 0); [Browsable(false)] public bool IsLastSibling { get { TreeGridNode parent = this.Parent; if (parent != null && parent.HasChildren) { return (this.Index == parent.Nodes.Count - 1); } else return true; } } public virtual bool Collapse() => this._grid.CollapseNode(this); public virtual bool Expand() { if (this._grid != null) return this._grid.ExpandNode(this); else { this.IsExpanded = true; return true; } } internal protected virtual bool InsertChildNode(int index, TreeGridNode node) { node._parent = this; node._grid = this._grid; // ensure that all children of this node has their grid set if (this._grid != null) UpdateChildNodes(node); //TO_DO: do we need to use index parameter? if ((this._isSited || this.IsRoot) && this.IsExpanded) this._grid.SiteNode(node); return true; } internal protected virtual bool InsertChildNodes(int index, params TreeGridNode[] nodes) { foreach (TreeGridNode node in nodes) { this.InsertChildNode(index, node); } return true; } internal protected virtual bool AddChildNode(TreeGridNode node) { node._parent = this; node._grid = this._grid; // ensure that all children of this node has their grid set if (this._grid != null) UpdateChildNodes(node); if ((this._isSited || this.IsRoot) && this.IsExpanded && !node._isSited) this._grid.SiteNode(node); return true; } internal protected virtual bool AddChildNodes(params TreeGridNode[] nodes) { //TO_DO: Convert the final call into an SiteNodes?? foreach (TreeGridNode node in nodes) { this.AddChildNode(node); } return true; } internal protected virtual bool RemoveChildNode(TreeGridNode node) { if ((this.IsRoot || this._isSited) && this.IsExpanded ) { //We only unsite out child node if we are sited and expanded. this._grid.UnSiteNode(node); } node._grid = null; node._parent = null; return true; } internal protected virtual bool ClearNodes() { if (this.HasChildren) { for (int i = this.Nodes.Count - 1; i >= 0; i--) { this.Nodes.RemoveAt(i); } } return true; } [ Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced) ] public event EventHandler Disposed { add { this.disposed += value; } remove { this.disposed -= value; } } [ Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) ] public ISite Site { get { return this.site; } set { this.site = value; } } private void UpdateChildNodes(TreeGridNode node) { if (node.HasChildren) { foreach (TreeGridNode childNode in node.Nodes) { childNode._grid = node._grid; this.UpdateChildNodes(childNode); } } } public override string ToString() { StringBuilder sb = new StringBuilder(36); sb.Append("TreeGridNode { Index="); sb.Append(this.RowIndex.ToString(System.Globalization.CultureInfo.CurrentCulture)); sb.Append(" }"); return sb.ToString(); } //protected override void Dispose(bool disposing) { // if (disposing) // { // lock(this) // { // if (this.site != null && this.site.Container != null) // { // this.site.Container.Remove(this); // } // if (this.disposed != null) // { // this.disposed(this, EventArgs.Empty); // } // } // } // base.Dispose(disposing); //} } }