Skip to content

Commit

Permalink
revised autolayout code, added layout abstractions, added new naive b…
Browse files Browse the repository at this point in the history
…ox layout, other misc fixes, stubbed out future layouts to allow future research
  • Loading branch information
ESIC-DA committed Sep 16, 2019
1 parent e88b934 commit efb95ff
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 28 deletions.
2 changes: 1 addition & 1 deletion build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<property name="build.numThreads" value="1" />
<property name="src.dir" value="./src"/>
<property name="lib.dir" value="./deps/org.graphstream/lib"/>
<property name="build.version" value="AHA-GUI v0.6.8b113"/>
<property name="build.version" value="AHA-GUI v0.6.8b150"/>
<property name="CP" value="."/>
<tstamp>
<format property="TODAY" pattern="yyyy-MM-dd HH:mm" />
Expand Down
138 changes: 122 additions & 16 deletions src/esic/AHAController.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public class AHAController implements org.graphstream.ui.view.ViewerListener, ja
private java.util.concurrent.atomic.AtomicReference<AHAModel> m_model=new java.util.concurrent.atomic.AtomicReference<>();
private AHAGUI m_gui;
private final java.util.concurrent.atomic.AtomicReference<AHANode> m_currentlyDisplayedNode=new java.util.concurrent.atomic.AtomicReference<>(null);
protected java.util.concurrent.atomic.AtomicReference<String> m_layoutMode=new java.util.concurrent.atomic.AtomicReference<>(); //set the default in AHAGUI:resetUI

public AHAController(String inputFileName, String scoreFileName, int verbosity, boolean useMultiLineGraph)
{
Expand Down Expand Up @@ -66,6 +67,15 @@ else if (actionCommand.contains("scoreMethod") || actionCommand.equals("useCusto
model().swapNodeStyles(scoremethod, System.currentTimeMillis());
updateSidebar(m_currentlyDisplayedNode.get(), false); //refresh the info panel now that we're probably on a new score mode
}
else if (actionCommand.contains("layoutMethod-"))
{
String layoutMethod=actionCommand.replaceFirst("layoutMethod-", "");
m_layoutMode.set(layoutMethod);
new Thread()
{
public void run() { moveExternalNodes(model()); }
}.start();
}
else if (actionCommand.equals("updateFileFromRemoteDB"))
{
final AHAController controller=this;
Expand Down Expand Up @@ -194,40 +204,136 @@ public void run()
}

protected void moveExternalNodes(AHAModel m)
{
//System.out.printf("Size at time of layout: height=%d width=%d\n", m_gui.m_graphViewPanel.getHeight(), m_gui.m_graphViewPanel.getWidth());
long time=System.currentTimeMillis();
String layoutMode=m_layoutMode.get();
if (layoutMode.equalsIgnoreCase("naiveBox")) { naiveBoxLayout(m); }
else if (layoutMode.equalsIgnoreCase("test1")) { layoutTest1(m); }
else if (layoutMode.equalsIgnoreCase("test2")) { layoutTest2(m); }
else { autoLayoutAlg(m); } //default case
System.out.printf("Layout alg=%s took %sms\n", layoutMode, (System.currentTimeMillis()-time));
}

private void layoutTest1(AHAModel m)
{
System.out.println("Layout Test 1 not implemented yet.");
}

private void layoutTest2(AHAModel m)
{
System.out.println("Layout Test 2 not implemented yet.");
}

private void autoLayoutAlg(AHAModel m)
{
try
{
Thread.sleep(1500);
AHAGraph g=m.m_graph;
m_gui.m_graphViewPanel.getCamera().setAutoFitView(true);
for (AHANode n : g)
{
n.graphNode.removeAttribute("xyz"); //setAttribute("xyz", 0,0,0);
}
Thread.sleep(100);
m_gui.m_graphViewer.enableAutoLayout();
Thread.sleep(500);
m_gui.m_graphViewer.disableAutoLayout();
Thread.sleep(100); //add delay to see if issues with moving ext nodes goes away
Thread.sleep(100);
org.graphstream.ui.geom.Point3 hi=m_gui.m_graphViewPanel.getCamera().getMetrics().hi, lo=m_gui.m_graphViewPanel.getCamera().getMetrics().lo;
m_gui.m_graphViewPanel.getCamera().setGraphViewport(lo.x, lo.y, hi.x, hi.y);

java.util.Vector<AHANode> leftSideNodes=new java.util.Vector<>(); //moved this below the 1.5s graph stabilization threshold to see if it makes odd occasional issues with moving ext nodes better
for (AHANode n : m.m_graph)
java.util.ArrayList<AHANode> leftSideNodes=new java.util.ArrayList<>(1024);
for (AHANode n : g)
{
if (n.getAttribute("aha.realextnode")!=null) { leftSideNodes.add(n); } //extNode.setAttribute("aha.externalNode","aha.externalNode");
n.graphNode.setAttribute("layout.weight", 6); //switched to add attribute rather than set attribute since it seems to prevent a possible race condition.
if (n.getAttribute("aha.realextnode")!=null) { leftSideNodes.add(n); }
}
int numLeftNodes=leftSideNodes.size()+2; //1 is for main External node, 2 is so we dont put one at the very top or bottom
leftSideNodes.insertElementAt(m.m_graph.getNode("external"),leftSideNodes.size()/2);
Thread.sleep(100); //add delay to see if issues with moving ext nodes goes away

double numLeftNodes=leftSideNodes.size()+2; //1 is for main External node, 2 is so we dont put one at the very top or bottom
leftSideNodes.add(leftSideNodes.size()/2, g.getNode("external"));

int i=1;

org.graphstream.ui.view.camera.Camera cam=m_gui.m_graphViewPanel.getCamera();
for (AHANode n : leftSideNodes)
{
org.graphstream.ui.geom.Point3 loc=cam.transformPxToGu(60, (m_gui.m_graphViewPanel.getHeight()/numLeftNodes)*i);
n.graphNode.setAttribute("xyz", loc.x,loc.y,loc.z);
i++;
}
m_gui.m_graphViewPanel.getCamera().setViewPercent(1.01d);
org.graphstream.ui.geom.Point3 center=m_gui.m_graphViewPanel.getCamera().getViewCenter();
org.graphstream.ui.geom.Point3 pixels=m_gui.m_graphViewPanel.getCamera().transformGuToPx(center.x, center.y, center.z);
pixels.x-=60;
center=m_gui.m_graphViewPanel.getCamera().transformPxToGu(pixels.x, pixels.y);
m_gui.m_graphViewPanel.getCamera().setViewCenter(center.x, center.y, center.z);

//System.out.printf("xlo=%f xhi=%f ylo=%f yhi=%f\n", lo.x, hi.x, lo.y, hi.y);
m_gui.m_graphViewPanel.getCamera().setGraphViewport(lo.x, lo.y, hi.x, hi.y);
} catch (Exception e) { e.printStackTrace(); }
}

private void naiveBoxLayout(AHAModel m)
{
try
{
m_gui.m_graphViewer.disableAutoLayout();
Thread.sleep(200);
double height=70, width=100;
m_gui.m_graphViewPanel.getCamera().setBounds(0, 0, 0, width, height, 0);
m_gui.m_graphViewPanel.getCamera().setGraphViewport(0, 0, width, height);
m_gui.m_graphViewPanel.getCamera().setAutoFitView(false);

java.util.ArrayList<AHANode> nodes=new java.util.ArrayList<>(1024), leftSideNodes=new java.util.ArrayList<>(1024);
AHAGraph g=m.m_graph;
for (AHANode n : g)
{
//int degree=n.graphNode.getDegree();
//System.out.printf("Node %s has degree %d\n", n.getId() , degree);
if (n.getAttribute("aha.realextnode")!=null) { leftSideNodes.add(n); }
else if (n.getAttribute("aha.externalNode")==null) { nodes.add(n); } //we have to ignore the 'virtual external node' here too
}

java.util.Collections.sort(nodes, new java.util.Comparator<AHANode>()
{
public int compare(AHANode lhs, AHANode rhs) { return Integer.compare(rhs.graphNode.getDegree(), lhs.graphNode.getDegree()); }
});

double restOfNodes=nodes.size(), side=Math.ceil(Math.sqrt(restOfNodes)), colwidth=(width/side);
double numLeftNodes=leftSideNodes.size()+2; //1 is for main External node, 2 is so we dont put one at the very top or bottom
leftSideNodes.add(leftSideNodes.size()/2, g.getNode("external"));
{
int i=1;
for (AHANode n : leftSideNodes)
{
n.graphNode.setAttribute("xyz", colwidth/2,((double)height/(numLeftNodes)*i),0);
//System.out.printf("Setting node=%s x=%f y=%f\n", n.getId(),colwidth/2,((double)100d/(numLeftNodes)*i));
i++;
}
}

java.util.Iterator<AHANode> it=nodes.iterator();
//System.out.printf("side=%f colwidth=%f --------------------------------\n", side, colwidth);
for (int col=1; col < side; col++)
{
for (int row=0; row < side; row++)
{
if (!it.hasNext()) { break; }
AHANode n=it.next();
if (n!=null)
{
double colPos=colwidth*col+colwidth/2, rowPos=((double)height/(side)*row)+(height/2d/side);
if (col%2==1) { rowPos+=(height/4d/side); } // move every other row up slightly to keep labels from overlapping
else { rowPos-=(height/4d/side); }
n.graphNode.setAttribute("xyz", colPos,rowPos,0);
//System.out.printf("Setting node=%s x=%f y=%f\n", n.getId(),colPos,rowPos);
}
}
}

m_gui.m_graphViewPanel.getCamera().setBounds(0, 0, 0, width, height, 0);
m_gui.m_graphViewPanel.getCamera().setGraphViewport(0, 0, width, height);
m_gui.m_graphViewPanel.getCamera().setViewCenter(width/2, height/2, 0);

//org.graphstream.ui.geom.Point3 hi=m_gui.m_graphViewPanel.getCamera().getMetrics().hi, lo=m_gui.m_graphViewPanel.getCamera().getMetrics().lo;
//System.out.printf("xlo=%f xhi=%f ylo=%f yhi=%f\n", lo.x, hi.x, lo.y, hi.y);
} catch (Exception e) { e.printStackTrace(); }
}


protected void updateOverlayLegendScale(int maxScore) { m_gui.updateOverlayLegendScale(maxScore); }

//Begin graph interaction handlers
Expand Down
23 changes: 16 additions & 7 deletions src/esic/AHAGUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,19 @@ public AHAGUI(AHAModel model, AHAController controller, boolean useMultiLineGrap
AHAGUIHelpers.createMenuItem(new JCheckBoxMenuItem("Show UDP", true), m_controller, "aha.graphlayer==proto.udp", "Show / Hide UDP protocol nodes in the graph.", viewMenu, null, defaultTrue);

viewMenu.addSeparator();
ButtonGroup buttonGroup=new ButtonGroup();
buttonGroup.add(AHAGUIHelpers.createMenuItem(new JRadioButtonMenuItem("Normal Score Method", true), m_controller, "scoreMethod-0", "Use the default scoring method", viewMenu, null, defaultTrue));
buttonGroup.add(AHAGUIHelpers.createMenuItem(new JRadioButtonMenuItem("WorstCommonProc Score Method (beta)"), m_controller, "scoreMethod-1", "Use the WorstCommonProc scoring method (beta)", viewMenu, null, null));
buttonGroup.add(AHAGUIHelpers.createMenuItem(new JRadioButtonMenuItem("Relative Score Method (beta)"), m_controller, "scoreMethod-2", "Use the RelativeScore scoring method (beta)", viewMenu, null, null));
ButtonGroup scoreButtonGroup=new ButtonGroup();
scoreButtonGroup.add(AHAGUIHelpers.createMenuItem(new JRadioButtonMenuItem("Normal Score Method", true), m_controller, "scoreMethod-0", "Use the default scoring method", viewMenu, null, defaultTrue));
scoreButtonGroup.add(AHAGUIHelpers.createMenuItem(new JRadioButtonMenuItem("WorstCommonProc Score Method (beta)"), m_controller, "scoreMethod-1", "Use the WorstCommonProc scoring method (beta)", viewMenu, null, null));
scoreButtonGroup.add(AHAGUIHelpers.createMenuItem(new JRadioButtonMenuItem("Relative Score Method (beta)"), m_controller, "scoreMethod-2", "Use the RelativeScore scoring method (beta)", viewMenu, null, null));

viewMenu.addSeparator();
ButtonGroup layoutButtonGroup=new ButtonGroup();
layoutButtonGroup.add(AHAGUIHelpers.createMenuItem(new JRadioButtonMenuItem("Default Autolayout"), m_controller, "layoutMethod-autolayout", "Use the default graph layout method", viewMenu, null, defaultTrue));
layoutButtonGroup.add(AHAGUIHelpers.createMenuItem(new JRadioButtonMenuItem("NaiveBox Autolayout"), m_controller, "layoutMethod-naiveBox", "Naive box layout, attempt to spread all nodes out on an XY grid evenly", viewMenu, null, null));
layoutButtonGroup.add(AHAGUIHelpers.createMenuItem(new JRadioButtonMenuItem("TestLayout1"), m_controller, "layoutMethod-test1", "Reserved menu spot to test future beta layouts", viewMenu, null, null));
layoutButtonGroup.add(AHAGUIHelpers.createMenuItem(new JRadioButtonMenuItem("TestLayout2"), m_controller, "layoutMethod-test2", "Reserved menu spot to test future beta layouts", viewMenu, null, null));


// -- begin window menu --
AHAGUIHelpers.createMenuItem(new JMenuItem("Reset Zoom"), m_controller, "resetZoom", "Resets the zoom of the graph view to default.", windowMenu,KeyStroke.getKeyStroke(KeyEvent.VK_R, m_menuShortcutKey), null);
}
Expand Down Expand Up @@ -183,11 +191,11 @@ protected void initGraphView(AHAModel model)
stopGraphRefreshThread();
org.graphstream.ui.view.Viewer oldGraphViewer=m_graphViewer;

if (m_multilineGraph) { model.m_graph.graph = new org.graphstream.graph.implementations.MultiGraph("MultiGraph", false, true, 256, 2048); }
else { model.m_graph.graph = new org.graphstream.graph.implementations.SingleGraph("SingleGraph", false, true, 256, 2048); }
if (m_multilineGraph) { model.m_graph.graph = new org.graphstream.graph.implementations.MultiGraph("MultiGraph", false, false, 512, 2048); }
else { model.m_graph.graph = new org.graphstream.graph.implementations.SingleGraph("SingleGraph", false, false, 512, 2048); }

model.m_graph.graph.setAttribute("ui.stylesheet", model.styleSheet);
model.m_graph.graph.setAttribute("layout.gravity", 0.000001);
model.m_graph.graph.setAttribute("layout.gravity", 0.025);//0.000001);
model.m_graph.graph.setAttribute("layout.quality", 4);
model.m_graph.graph.setAttribute("layout.stabilization-limit", 0.95);
model.m_graph.graph.setAttribute("ui.antialias", true); //enable anti aliasing (looks way better this way)
Expand Down Expand Up @@ -263,6 +271,7 @@ private void resetUIToDefault()
for (JMenuItem i : defaultTrue) { setMenuElementTo(i,true); }
m_btmPnlSearch.setText("Search...");
m_btmPnlSearchStatus.setText("");
m_controller.m_layoutMode.set("autolayout");
}

protected boolean openFile (AHAModel model, String baseTitle)
Expand Down
1 change: 1 addition & 0 deletions src/esic/AHAGraph.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public AHANode(String nodeID, org.graphstream.graph.Node node)
m_nodeID=nodeID;
graphNode=node;
setAttribute("ui.label", AHAModel.capitalizeFirstLetter(m_nodeID));
node.setAttribute("layout.weight", 10);
setAttribute("processname", AHAModel.capitalizeFirstLetter(m_nodeID)); //for testing
putConnectionEntryTable("allConnections", new java.util.Vector<esic.AHAModel.ConnectionEntry>()); //TODO might want to not have to do this in the future / make generic
putStringMap("aha.graphlayer", new java.util.TreeMap<String,String>());
Expand Down
9 changes: 5 additions & 4 deletions src/esic/AHAModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -688,8 +688,8 @@ private void readInputFile()
if (m_allListeningProcessMap.get(protoLocalPort)!=null) { bumpIntRefCount(m_listeningPortConnectionCount,protoLocalPort,1); }
if (e!=null && isLocalOnly)
{
e.setAttribute("layout.weight", 10); //try to make internal edges longer
if (duplicateEdge) { e.setAttribute("layout.weight", 5); }
//e.setAttribute("layout.weight", 10); //try to make internal edges longer
//if (duplicateEdge) { e.setAttribute("layout.weight", 10); }
if (timewait && !duplicateEdge) { e.setAttribute("ui.class", "tw"); }
if (!timewait && duplicateEdge) { e.setAttribute("ui.class", "duplicate"); }
if (timewait && duplicateEdge) { e.setAttribute("ui.class", "duplicate, tw"); }
Expand All @@ -701,13 +701,14 @@ else if(e!=null)
m_graph.getNode(toNode).setAttribute("ui.class", "external");
m_graph.getNode(toNode).setAttribute("hostname", remoteHostname);
m_graph.getNode(toNode).setAttribute("IP", remoteAddr);
e.setAttribute("layout.weight", 9); //try to make internal edges longer
if (duplicateEdge) { e.setAttribute("layout.weight", 4); }
//e.setAttribute("layout.weight", 10); //try to make internal edges longer
//if (duplicateEdge) { e.setAttribute("layout.weight", 10); }
if (!timewait && !duplicateEdge) { e.setAttribute("ui.class", "external"); }
if (!timewait && duplicateEdge) { e.setAttribute("ui.class", "duplicate, xternal"); }
if (timewait && !duplicateEdge) { e.setAttribute("ui.class", "external, tw"); }
if (timewait && duplicateEdge) { e.setAttribute("ui.class", "duplicate, external, tw"); }
} // BEGIN RelativeScore CODE //
if (e!=null) { e.setAttribute("layout.weight", 10); }
AHANode toNode_node = m_graph.getNode(toNode);
if ( toNode.startsWith("Ext_") || node.getId().startsWith("Ext_") ) //TODO, this should probably use ui.class rather than string matching?
{
Expand Down

0 comments on commit efb95ff

Please sign in to comment.