Graph Display Tweaking

I have a few things i cant fully sort out;

  1. if i have a large sub tree then when its minimized the focus stays at the bottom opposed to refocusing back up to the top of the page / or to the focal point of the graph

  2. is it possible, seeing as i am using layout.Angle = 0; to get the top level part of the tree to always dock right up against the left hand side of the go view? its very annoying having to do horizontal scrolling. And on the topic of horizontal scrolling, is there anyway to keep that to a minimum?

Thanks very much

You can “scroll” the view under program control, which I think that gets to both your issues here.



Read through the API reference for GoView.DocExtent, DocPosition, DocExtentCenter. And search the forum here for those methods too, as you’ll see various sample code.

Hi Jake, i’ve spent a day or two now looking through the stuff you posted and I still cant seem to find how to scale a picture appropriately to fit in to its container so that horizontal scrolling is disabled.



Add to that i still can’t see how to dock the left most part of the tree to the left most part of the container either :/



Some help would be greatly appreciated.

This code is for a “fit horizontal” Button. (CurrentView is a function that returns the current GoView)



private void buttonFitHorizontal_Click(object sender, EventArgs e) {

GoView view = CurrentView;

GoDocument doc = view.Document;

RectangleF docbounds = doc.ComputeBounds();

doc.Bounds = docbounds;



Size dispSize = view.DisplayRectangle.Size;

if (!view.HorizontalScrollBar.Visible) dispSize.Height -= view.HorizontalScrollBar.Height;

if (!view.VerticalScrollBar.Visible) dispSize.Width -= view.VerticalScrollBar.Width;



SizeF shadSize = view.ShadowOffset;

docbounds.Width += Math.Abs(shadSize.Width);

docbounds.Height += Math.Abs(shadSize.Height);

if (shadSize.Width < 0)

docbounds.X += shadSize.Width; // moves topleft to the left!

if (shadSize.Height < 0)

docbounds.Y += shadSize.Height;



view.DocPosition = new PointF(docbounds.X, docbounds.Y);



float newscale = 1;

if (docbounds.Width > 0 && docbounds.Height > 0)

newscale = dispSize.Width / docbounds.Width;

if (newscale > 1)

newscale = 1;

view.DocScale = newscale;

}

i am disappointed in myself to be asking this question :$



when exactly should i be calling that method if i want it done on the drawing of a graph?



i have a display class which gets a goview object from a graph



i set the container and then add the goview object to my forms controls collection.



If i call the fithorizontal method just before adding to the controls collection i get a really small graph in the upper left hand corner, its very small tbh, so small you cant see anything.



if i put the method call in the click event of a graph



protected void goView1_ObjectSingleClicked(Object sender, GoObjectEventArgs evt)



then it resizes but only when i contract a node opposed to expand it.

I’m not entirely sure what you’re going for here, but there may be a couple of points where you call this… it seems like whenever you call PerformLayout is one. This would handle all the times where you are expanding/collapsing the tree, right?



Another time might be after you load the Document, but…you’re probably doing a Layout there, so the earlier suggestion would handle that.



ok, can i put together a really small example project and email it over and show you what i mean?

sure.

[QUOTE=Jake] sure.[/quote] can i have your email please?

i will post in here to help others

//-------------------------------------------------------

namespace testapp

{

public abstract class Graph

{

public Graph(String xmlFileName)

{

fileToLoad = xmlFileName;

}



public void FitHorizontal(GoView goView)

{

GoView view = goView;

GoDocument doc = view.Document;

RectangleF docbounds = doc.ComputeBounds();

doc.Bounds = docbounds;



Size dispSize = view.DisplayRectangle.Size;

if (!view.HorizontalScrollBar.Visible)

{

dispSize.Height -= view.HorizontalScrollBar.Height;

}

if (!view.VerticalScrollBar.Visible)

{

dispSize.Width -= view.VerticalScrollBar.Width;

}



SizeF shadSize = view.ShadowOffset;

docbounds.Width += Math.Abs(shadSize.Width);

docbounds.Height += Math.Abs(shadSize.Height);

if (shadSize.Width < 0)

docbounds.X += shadSize.Width; // moves topleft to the left!

if (shadSize.Height < 0)

docbounds.Y += shadSize.Height;



view.DocPosition = new PointF(docbounds.X, docbounds.Y);



float newscale = 1;

if (docbounds.Width > 0 && docbounds.Height > 0)

newscale = dispSize.Width / docbounds.Width;

if (newscale > 1)

newscale = 1;

view.DocScale = newscale;

view.Refresh();

}



public static void AutoLayout(GoDocument doc)

{

if (doc == null) return;

GoLayoutTree layout = new GoLayoutTree();

layout.Document = doc;

GoLayoutTreeNetwork network = new GoLayoutTreeNetwork(doc);

foreach (GoObject obj in doc)

{

TreeAppNode node = obj as TreeAppNode;

if (node == null) continue;

if (!node.CanView())

{

network.DeleteNode(node);

}

else

{

node.UpdateHandle();

}

}

layout.Network = network;

layout.Angle = 0;//determines if the graph is drawn with main search on the lft and everything else going accross, or top to bottom.

layout.LayerSpacing = 60;//the distance between the nodes horizontally

layout.AlternateDefaults.NodeIndent = 1000;

layout.AlternateDefaults.NodeIndentPastParent = 1.0f;

layout.AlternateDefaults.LayerSpacing = 60;

layout.AlternateDefaults.ChildPortSpot = GoObject.MiddleLeft;

layout.PerformLayout();

}



protected void GenerateTree()

{

n = new TreeAppNode();

n.Editable = false;

n.Selectable = true;

GoView1.ObjectSingleClicked += new GoObjectEventHandler(this.goView1_ObjectSingleClicked);



n.LabelSpot = GoObject.Middle;

n.Text = “”;

n.Shape = new GoRoundedRectangle();

tr = new GoXmlBindingTransformer(“node”, n);

tr.TreeStructured = true;

tr.TreeLinkPrototype = new GoLink();

tr.TreeLinksToChildren = true;



tr.AddBinding(“label”, “Text”);

Doc = GoView1.Document;



rdr = new GoXmlReader();

rdr.AddTransformer(tr);

rdr.RootObject = GoView1.Document;

using (StreamReader file = new StreamReader(fileToLoad))

{

rdr.Consume(file);

}

Layout = new GoLayoutTree();

Layout.Document = Doc;



GoView1.Dock = DockStyle.Fill;

GoView1.DocPosition = GoView1.LimitDocPosition(GoView1.DocPosition);

}



protected void goView1_ObjectSingleClicked(Object sender, GoObjectEventArgs evt)

{

FitHorizontal(goView1);

GoObject obj = evt.GoObject;

TreeAppNode n = obj.TopLevelObject as TreeAppNode;

if (n != null)

{

String parentNodeName = null;

foreach (IGoNode tan in n.Sources)

{

if (tan.GoObject is TreeAppNode)

{

TreeAppNode parentNode = (TreeAppNode)tan;

parentNodeName = parentNode.Text;

}

}

doSomeActionToTree(parentNodeName, n.Text);

}

}

}

}

//-------------------------------------------------------





that is my main graph class(jsut the core details)



then as a sublcass i have

//-------------------------------------------------------



public MyGraph(String searchVal) : base(“batch.xml”)

{

try

{

//here i instantiate my xml builder class but i have hardcoded one for now.

}

catch (Exception e)

{

throw;

}

base.GenerateTree();

setNodeToCollapse(getView().Document, “12345”);//collapse this node on startup

FitHorizontal(getView());

AutoLayout(getView().Document);



}

//-------------------------------------------------------



and in my main gui i have a constructor like this



//-------------------------------------------------------



public MainContaine(MyGraph g)

{

InitializeComponent();

g.Container = this;

panel1.Controls.Add(g.getView());

g.FitHorizontal(g.getView());

this.WindowState = FormWindowState.Maximized;

this.Show();

}

//-------------------------------------------------------





i cant find an appropriate place in any of those to call the method you suggested? If i place it in the MainContainer(gui constructor) after i placed it in the panel1.controls then nothing happens, if i place it in the click event for the graph then it resizes only when minimising a subgraph opposed to maximising

Do the “Fit” after the “Layout”.

[QUOTE=Jake]edit: fixed to the point where i know that the method has to be called in my main gui when its set as the goview gets passed to the display class for display, and until then the goview has no size as its not on the screen. The issue is, when i expand and contract a node i still get the same problem, which means i guess i need to call the fithorizontal method from the expand and collapse method in the treeappnode class.



The issue here is that treeappnode class has no reference to a graphing object.



Can i get a GoView object from a node? something like



private void collapse()

{

Graph v = this.parent()//which gets my Graph object

GoView gv = v.getView() which gets the the goview for this graph?





//do collapsing stuff

v.FitHorizontal(gv);

}



or am i miles off ?



edit2: i found i can get the view but its null :/. I was going to make the fithorizontal static and pass the goview in which i cant do now as i only have the document available.



edit 7645: fixed :D

GoObject.View is only non-null when the object has been added to a View Layer, which typically doesn’t happen (except for things like selection handles).



Yes, sometimes getting the GoView can be a pain.



What GoDocument does is calls RaiseChanged(hint, …) and relies on the GoView to catch the event and handle it appropriately.



In fact, the PerformLayout does a RaiseChanged(GoDocument.AllArranged, …) just before it returns, so I think your view could look for that… and do your “Fit” thing there. (I’ve never tried this.)