Expandable nodes

Hiiii All
I need to make expandable nodes, I saw many sample about this
but What I need exactly to make the
MultiPortNode which is in sample class in Demo1 as expendable node in TreeApp Sample Wacko
plz replay me ASAP

Thank you

you can probably steal all of the IGoCollapsible code out of TreeNode and drop it into MultiPortNode. I don’t see any reason why that won’t work.

it will not work coz the treeapp node use one port and addobserv on it

when it change it change the expandble status
but in my project the node at least have 4 port
i don't know how to achive the treeapp code to be suite for my code
plz help my as you can.
thnx

It can be done… I’ll see what I can throw together.

Thank you Jake

Well, it’s late, and I should probably wait until tomorrow to look at this code again before I post it. But, since it’s probably already Monday for you, I’ll toss this over the wall tonight and hope it is of some help to you…

Note I pulled a couple of methods out of TreeDraggingTool and a bunch of code from TreeAppNode. The port now calls the parent node any time a link is added or removed to set the collapsible handle state.
[code]
/*
* Copyright © Northwoods Software Corporation, 1998-2007. All Rights
* Reserved.
*
* Restricted Rights: Use, duplication, or disclosure by the U.S.
* Government is subject to restrictions as set forth in subparagraph
* (c) (1) (ii) of DFARS 252.227-7013, or in FAR 52.227-19, or in FAR
* 52.227-14 Alt. III, as applicable.
*/
using System;
using System.Collections;
using System.Drawing;
using Northwoods.Go;
namespace Demo1 {
///
/// A MultiPortNode has an icon, a label, and some number of ports.
///

[Serializable]
public class CollapsibleMultiPortNode : GoIconicNode, IGoCollapsible {
///
/// Create an empty MultiPortNode--call to
/// create an icon and a label.
///

public CollapsibleMultiPortNode() {
this.DraggableLabel = true;
GoCollapsibleHandle h = new GoCollapsibleHandle();
h.Position = this.Position;
Add(h);
AddChildName("handle", h);
UpdateHandle();
}
///
/// Don't create any ports initially--these need to be added and positioned explicitly.
///

/// a by default
protected override GoPort CreatePort() {
if (this.Initializing) return null;
CollapsibleMultiPortNodePort p = new CollapsibleMultiPortNodePort();
return p;
}

public override void LayoutChildren(GoObject childchanged) {
base.LayoutChildren(childchanged);
GoObject h = FindChild("handle");
if (h == null || this.Icon == null) return;
h.SetSpotLocation(BottomRight, this.Icon, TopLeft);
}
///
/// Create and Add a port to this node at a particular position
/// relative to the icon.
///

///
/// the property is set to this value
/// in order to help distinguish between different ports
///
/// relative to the top-left corner of the icon
///
/// initial values for the port's
/// and properties
///
/// the result of the call to
public GoPort AddPort(int id, SizeF iconoffset, int linkspot) {
GoPort p = CreatePort();
if (p != null) {
p.UserFlags = id;
PointF pnt = this.SelectionObject.Position;
p.Center = new PointF(pnt.X + iconoffset.Width, pnt.Y + iconoffset.Height);
p.FromSpot = linkspot;
p.ToSpot = linkspot;
Add(p);
}
return p;
}
///
/// Update the positions of all the other ports before performing the
/// standard call to
///

///
///
protected override void OnChildBoundsChanged(GoObject child, RectangleF old) {
if (child != null && child == this.Icon && old.Width > 0 && old.Height > 0) {
RectangleF thisRect = this.Icon.Bounds;
float scaleFactorX = thisRect.Width / old.Width;
float scaleFactorY = thisRect.Height / old.Height;
foreach (GoObject obj in this) {
if (obj == this.Icon) continue;
RectangleF childRect = obj.Bounds;
float newRectx = thisRect.X + ((childRect.X - old.X) * scaleFactorX);
float newRecty = thisRect.Y + ((childRect.Y - old.Y) * scaleFactorY);
float newRectwidth = childRect.Width;
float newRectheight = childRect.Height;
if (obj.AutoRescales) {
newRectwidth *= scaleFactorX;
newRectheight *= scaleFactorY;
}
obj.Bounds = new RectangleF(newRectx, newRecty, newRectwidth, newRectheight);
}
}
base.OnChildBoundsChanged(child, old); // this will call LayoutChildren
}
public void PortHasChanged() {
// called by the port when a link is added or removed
// takes the place of the port observer in TreeAppNode.
SetExpanded(!HasAnyChildrenUnseen());
UpdateHandle();
}
protected void UpdateHandle() {
foreach (GoObject obj in this) {
GoCollapsibleHandle h = obj as GoCollapsibleHandle;
if (h != null) {
h.Visible = HasChildren();
h.Printable = h.Visible;
break;
}
}
}
public virtual bool HasChildren() {
//return true;
return this.Collapsible &&
(ChildrenAreDestinations ?
this.DestinationLinks.Count > 0 :
this.SourceLinks.Count > 0);
}
public virtual bool HasAnyChildrenUnseen() {
if (!this.Collapsible)
return false;
bool unseen = false;
foreach (IGoNode n in (ChildrenAreDestinations ? this.Destinations : this.Sources)) {
if (!n.GoObject.CanView()) {
unseen = true;
break;
}
}
return unseen;
}

// next 2 methods taken from TreeDraggingTool
// extend the collection by recursively adding all of the destination links and nodes
// of all of the collection's nodes and links
public static void AddSubtrees(IGoCollection sel) {
Hashtable coll = new Hashtable();
foreach (GoObject obj in sel) {
AddReachable(coll, obj as IGoNode);
}
foreach (GoObject obj in coll.Keys) {
sel.Add(obj);
}
}
// recurse through graph
private static void AddReachable(Hashtable coll, IGoNode inode) {
if (inode == null) return;
GoObject obj = inode.GoObject;
if (!coll.ContainsKey(obj)) {
coll.Add(obj, obj);
foreach (IGoLink ilink in inode.DestinationLinks) {
GoObject link = ilink.GoObject;
if (!coll.ContainsKey(link))
coll.Add(link, link);
AddReachable(coll, ilink.ToNode);
}
}
}

///
/// Make all child links and nodes not Visible.
///

///
/// This calls
/// to determine what should be made not visible.
///
public virtual void Collapse() {
if (!this.Collapsible) return;
SetExpanded(false);
GoCollection coll = new GoCollection();
coll.Add(this);
//TreeDraggingTool.AddSubtrees(coll);
AddSubtrees(coll);
foreach (GoObject obj in coll) {
if (obj == this) continue;
CollapsibleMultiPortNode tn = obj as CollapsibleMultiPortNode;
if (tn != null) {
// make this child not visible
tn.Visible = false;
tn.Printable = false;
// also update the visibility of any links coming into TN
foreach (IGoLink inlink in tn.SourceLinks) {
inlink.GoObject.Visible = false;
inlink.GoObject.Printable = false;
}
}
}
}
///
/// Make child links and nodes visible.
///

///
/// Edit the code to govern how many/which children should become visible.
///
public virtual void Expand() {
if (!this.Collapsible) return;
SetExpanded(true);
/*
// Choice one--only display immediate children:
foreach (GoObject obj in (ChildrenAreDestinations ? this.Destinations : this.Sources)) {
if (obj == this) continue;
CollapsibleMultiPortNode tn = obj as CollapsibleMultiPortNode;
if (tn != null) {
// make this child visible
tn.Visible = true;
tn.Printable = true;
// also update the visibility of any links coming into TN
foreach (IGoLink inlink in tn.SourceLinks) {
inlink.GoObject.Visible = true;
inlink.GoObject.Printable = true;
}
}
}
*/
// Choice two--display all children that had been Expanded
// when this node was Collapsed:
foreach (GoObject obj in (ChildrenAreDestinations ? this.Destinations : this.Sources)) {
if (obj == this) continue;
CollapsibleMultiPortNode tn = obj as CollapsibleMultiPortNode;
if (tn != null) {
// make this child visible
tn.Visible = true;
tn.Printable = true;
// also update the visibility of any links coming into TN
foreach (IGoLink inlink in tn.SourceLinks) {
inlink.GoObject.Visible = true;
inlink.GoObject.Printable = true;
}
// expand children, if they were expanded when collapsed
if (tn.IsExpanded)
tn.Expand();
}
}
/*
// Choice three--display all children
GoCollection coll = new GoCollection();
coll.Add(this);
TreeDraggingTool.AddSubtrees(coll);
foreach (GoObject obj in coll) {
if (obj == this) continue;
CollapsibleMultiPortNode tn = obj as CollapsibleMultiPortNode;
if (tn != null) {
// make this child visible
tn.Visible = true;
tn.Printable = true;
// also update the visibility of any links coming into TN
foreach (IGoLink inlink in tn.SourceLinks) {
inlink.GoObject.Visible = true;
inlink.GoObject.Printable = true;
}
}
}
*/
}
///
/// If , then , else .
///

public virtual void Toggle() {
if (HasAnyChildrenUnseen())
Expand();
else
Collapse();
}
///
/// Gets whether has been called.
///

public bool IsExpanded {
get { return myExpanded; }
}
protected void SetExpanded(bool e) {
bool old = myExpanded;
if (old != e) {
myExpanded = e;
Changed(ChangedExpanded, 0, old, NullRect, 0, e, NullRect);
UpdateHandle();
}
}
///
/// Gets or sets disabling of the collapse/expand behavior.
///

public virtual bool Collapsible {
get { return myCollapsible; }
set {
bool old = myCollapsible;
if (old != value) {
myCollapsible = value;
Changed(ChangedCollapsible, 0, old, NullRect, 0, value, NullRect);
UpdateHandle();
}
}
}
public override void ChangeValue(GoChangedEventArgs e, bool undo) {
switch (e.SubHint) {
case ChangedCollapsible:
this.Collapsible = (bool)e.GetValue(undo);
return;
case ChangedExpanded:
SetExpanded((bool)e.GetValue(undo));
return;
default:
base.ChangeValue(e, undo);
return;
}
}

public const int ChangedCollapsible = 1235;
public const int ChangedExpanded = 1236;
// change this from true to false if the tree goes in the opposite direction
private static bool ChildrenAreDestinations = true;
private bool myExpanded = true;
private bool myCollapsible = true;
}
///
///
///

[Serializable]
public class CollapsibleMultiPortNodePort : GoPort {
public CollapsibleMultiPortNodePort() {
this.Style = GoPortStyle.Ellipse;
this.Brush = null;
this.Size = new SizeF(8, 8);
this.FromSpot = NoSpot;
this.ToSpot = NoSpot;
this.AutoRescales = false;
}
///
/// This is a convenience property for treating the parent node as a .
///

public MultiPortNode MultiPortNode {
get { return this.Parent as MultiPortNode; }
}
///
/// This is a convenience property when the port's appearance is actually a .
///

///
/// Setting this to a non-null value will change the appropriately.
///
public GoImage PortImage {
get { return this.PortObject as GoImage; }
set {
this.PortObject = value;
if (value == null)
this.Style = GoPortStyle.Ellipse;
else
this.Style = GoPortStyle.Object;
}
}
///
/// Gets or sets the maximum number of links the user may draw to this port.
///

public int MaxLinks {
get { return myMaxLinks; }
set {
int old = myMaxLinks;
if (old != value && value >= 0) {
myMaxLinks = value;
Changed(ChangedMaxLinks, old, null, NullRect, value, null, NullRect);
}
}
}

///
/// This override also checks to see if is less
/// than the permissible value.
///

///
public override bool CanLinkFrom() {
return base.CanLinkFrom() &&
this.LinksCount < this.MaxLinks;
}
///
/// This override also checks to see if is less
/// than the permissible value.
///

///
public override bool CanLinkTo() {
return base.CanLinkTo() &&
this.LinksCount < this.MaxLinks;
}
public override void ChangeValue(GoChangedEventArgs e, bool undo) {
switch (e.SubHint) {
case ChangedMaxLinks:
this.MaxLinks = e.GetInt(undo);
return;
default:
base.ChangeValue(e, undo);
return;
}
}
public override void OnLinkChanged(IGoLink l, int subhint, int oldI, object oldVal, RectangleF oldRect, int newI, object newVal, RectangleF newRect) {
base.OnLinkChanged(l, subhint, oldI, oldVal, oldRect, newI, newVal, newRect);
CollapsibleMultiPortNode node = this.Parent as CollapsibleMultiPortNode;
if (node != null) node.PortHasChanged();
}
public const int ChangedMaxLinks = 2121;
// State
private int myMaxLinks = 999999;
}
}
[/code]

Thank you Jake for your help

I will check the code ASAP and update you

Thank you Jake for your help

I was Busy with urgent Task that prevent me from check your code
I check it Today I found it Helpfull and the task done :)
thnx

Glad we could help.