Commit ec35a4d5 authored by Russ Fish's avatar Russ Fish

Minor additions: a hypview wrapper script to set up local shared lib loading;...

Minor additions: a hypview wrapper script to set up local shared lib loading; control- or shift-left-mouse for rotate as an alternative to middle-mouse; glob expression to fan-out top-level nodes in getExperiment.
parent 2861a1a6
......@@ -28,7 +28,8 @@ PYFILES = hypview.py exptToHv.py sshxmlrpc.py emulabclient.py hvFrameUI.py hv.py
SRCFILES = README ROADMAP GNUMakefile hvgui.wxg hvmain.cpp hv.i hv.mod _hv.cpp
BINFILES = _hv.so
DATAFILES = BigLan.hyp ts600.hyp
DISTFILES = ${PYFILES} ${SRCFILES} ${BINFILES} ${DATAFILES} ${HVROOT}
SCRIPTFILES = hypview pangorc.local pango.modules.local
DISTFILES = ${SCRIPTFILES} ${PYFILES} ${SRCFILES} ${BINFILES} ${DATAFILES} ${HVROOT}
# Finally, make something.
default: _hv.so
......
......@@ -7,6 +7,7 @@
# exptToHv - Get an experiment topology via xmlrpc, and write a HyperViewer .hyp file.
import sets
import string
import fnmatch
from sshxmlrpc import *
from emulabclient import *
......@@ -51,7 +52,7 @@ def addConnection(graph, h1, h2):
else:
graph[h2] = sets.Set([h1])
## exptToHv - Make the request from the server. Reconstitute a topology graph
## getExperiment - Make the request from the server. Reconstitute a topology graph
## from the host interface list, and traverse it to write HyperViewer .hyp file.
#
# Args are the project and experiment names, and optionally the root of the topology.
......@@ -75,7 +76,7 @@ def getExperiment(project, experiment, root=""):
if response["code"] != RESPONSE_SUCCESS:
print "XMLRPC failure, code", response["code"]
pass
return response["code"]
links = response["value"]
# Figure out the nodes from the experiment links (interfaces) from the virt_lans table.
......@@ -87,6 +88,7 @@ def getExperiment(project, experiment, root=""):
if not linksByName.has_key(linkName):
linksByName[linkName] = sets.Set()
linksByName[linkName].add(member) # Each link/lan connects a set of interfaces.
pass
# Build the connection graph as a dictionary of nodes with sets of connected nodes.
hosts = sets.Set() # Collect unique node names (hosts and lans.)
......@@ -99,18 +101,45 @@ def getExperiment(project, experiment, root=""):
hosts.add(h1)
hosts.add(h2)
addConnection(graph, h1, h2)
pass
else:
# Lan nodes are are links with more than two interfaces as members.
lans.add(link)
for intfc in intfcs:
addConnection(graph, link, intfcHost(intfc))
pass
pass
pass
# Use the first lan or the first host as the default root node.
if root == "":
if len(lans) > 0:
root = lans.copy().pop()
pass
else:
root = hosts.copy().pop()
pass
pass
# The root may be a glob expression, in which case we make up a root node and put
# the matching nodes under it. We could add a regexp option as well...
rootNodes = []
if '*' in root or '?' in root or '[' in root:
glob = root
rootNodes = fnmatch.filter(hosts, glob) + fnmatch.filter(lans, glob)
if len(rootNodes) > 1:
# Find a new root name that isn't already in the hosts or lans lists.
for newroot in ['root','Root','ROOT','RoOt']:
if not newroot in hosts and not newroot in lans:
root = newroot
##print "Connecting", root, "to", rootNodes
for node in rootNodes:
addConnection(graph, root, node)
pass
pass
break
pass
pass
# Walk the graph structure in depth-first order to generate the .hyp file.
# Make a second copy of the graph as we go to avoid repeating nodes due to back-links.
......@@ -120,12 +149,15 @@ def getExperiment(project, experiment, root=""):
# Recursively traverse the nodes connected to this one.
for conn in graph[node]:
if not (node in graph2 and conn in graph2[node]):
if (not (node in graph2 and conn in graph2[node])
# rootNodes are fanned-out from the root only.
and (level == 0 or not conn in rootNodes)):
addConnection(graph2, node, conn)
walkNodes(graph, graph2, conn, level+1, outfile)
pass
pass
pass
hypfile = "/tmp/"+experiment+'.hyp'
outfile = file(hypfile,'w')
graph2 = {}
......
......@@ -6,14 +6,14 @@
# All rights reserved.
#
from wxPython.wx import *
from wxPython import glcanvas
from wxPython.glcanvas import wxGLCanvas
class UsageDialogUI(wxDialog):
def __init__(self, *args, **kwds):
# begin wxGlade: UsageDialogUI.__init__
kwds["style"] = wxDEFAULT_DIALOG_STYLE
wxDialog.__init__(self, *args, **kwds)
self.Usage = wxStaticText(self, -1, "\n HyperViewer usage:\n -------------------------\n\n Objects close to the center of the sphere are largest. \n\n Left mouse drag: X,Y movement in hyperbolic space. \n\n Middle mouse drag: Rotate the hyperbolic space. \n\n Pickable nodes under the cursor turn green. \n Left-click to bring them to the center. \n\n")
self.Usage = wxStaticText(self, -1, "\n HyperViewer mouse usage:\n -----------------------------------\n\n Objects close to the center of the sphere are largest. \n\n Left mouse drag: X,Y movement in hyperbolic space. \n\n Control- or Shift- Left mouse, or Middle mouse, drag:\n Rotate the hyperbolic space. \n\n Pickable nodes under the cursor turn bright green. \n Left-click to bring them to the center. \n\n")
self.__set_properties()
self.__do_layout()
......@@ -46,6 +46,7 @@ class OpenDialogUI(wxDialog):
wxDialog.__init__(self, *args, **kwds)
self.FileToOpen = wxTextCtrl(self, -1, "")
self.OpenFile = wxButton(self, -1, "Open Data File")
self.FileMsg = wxStaticText(self, -1, "")
self.label_2 = wxStaticText(self, -1, "Project name:", style=wxALIGN_RIGHT)
self.ProjectName = wxTextCtrl(self, -1, "")
self.label_7 = wxStaticText(self, -1, "Experiment name:")
......@@ -53,6 +54,7 @@ class OpenDialogUI(wxDialog):
self.label_8 = wxStaticText(self, -1, "Root (optional):")
self.ExperimentRoot = wxTextCtrl(self, -1, "")
self.OpenExperiment = wxButton(self, -1, "Retrieve experiment")
self.ExperimentMsg = wxStaticText(self, -1, "")
self.__set_properties()
self.__do_layout()
......@@ -77,7 +79,7 @@ class OpenDialogUI(wxDialog):
FileOpening.Add(self.FileToOpen, 0, 0, 0)
FileOpening.Add(20, 10, 0, 0, 0)
FileOpening.Add(self.OpenFile, 0, wxALIGN_CENTER_HORIZONTAL, 0)
FileOpening.Add(20, 20, 0, 0, 0)
FileOpening.Add(self.FileMsg, 0, 0, 0)
sizer_4.Add(FileOpening, 0, wxALL, 0)
sizer_4.Add(20, 10, 0, 0, 0)
grid_sizer_1.Add(self.label_2, 0, 0, 0)
......@@ -90,6 +92,7 @@ class OpenDialogUI(wxDialog):
grid_sizer_1.Add(20, 1, 0, 0, 0)
ExperimentOpening.Add(grid_sizer_1, 0, wxEXPAND, 0)
ExperimentOpening.Add(self.OpenExperiment, 0, wxALIGN_CENTER_HORIZONTAL, 0)
ExperimentOpening.Add(self.ExperimentMsg, 0, 0, 0)
ExperimentOpening.Add(20, 10, 0, 0, 0)
sizer_4.Add(ExperimentOpening, 1, wxALL, 0)
self.SetAutoLayout(1)
......@@ -120,7 +123,7 @@ class hvFrameUI(wxFrame):
wxglade_tmp_menu.Append(3, "&Usage\tCtrl+H", "", wxITEM_NORMAL)
self.Menu.Append(wxglade_tmp_menu, "&Help")
# Menu Bar end
self.hypView = glcanvas.wxGLCanvas(self.panel_1, -1)
self.hypView = wxGLCanvas(self.panel_1, -1)
self.GoToTop = wxButton(self.Controls, -1, "go to top")
self.LabelNodeName = wxStaticText(self.Controls, -1, " Node name ")
self.NodeName = wxTextCtrl(self.Controls, -1, "")
......
This diff is collapsed.
#! /bin/sh
#
# hypview - Wrapper script for the hyperviewer application.
#
# EMULAB-COPYRIGHT
# Copyright (c) 2004 University of Utah and the Flux Group.
# All rights reserved.
#
# Optionally use shared libs under the local directory.
if [ -d libs ]; then
LD_LIBRARY_PATH=./libs; export LD_LIBRARY_PATH
fi
# Optionally use Pango loadable modules under the local directory.
if [ -d libs/pango ]; then
PANGO_RC_FILE=./pangorc.local; export PANGO_RC_FILE
fi
# If the wxPython or OpenGL directories are local, they will be used.
python hypview.py $*
......@@ -18,7 +18,7 @@ from hvFrameUI import *
from OpenGL.GL import *
from wxPython.wx import *
from wxPython import glcanvas
from wxPython.glcanvas import wxGLCanvas
# A wxPython application.
class hvApp(wxApp):
......@@ -37,42 +37,58 @@ class hvApp(wxApp):
self.SetTopWindow(self.frame)
# Given command-line argument(s), attempt to read in a topology.
if len(sys.argv) == 2 and sys.argv[1][0] == '-': # Any dash arg gives usage message.
filename = project = None
# Any dash argument prints a usage message and exits.
if len(sys.argv) == 2 and sys.argv[1][0] == '-':
print '''Hyperviewer usage:
No args - Starts up the GUI. Use the File/Open menu item to read a topology.
One arg - A .hyp file name. Read it in and start the GUI, e.g.:
./hypview.py BigLan.hyp
./hypview BigLan.hyp
Two args - Project and experiment names in the database.
Get the topology from XMLRPC, make a .hyp file, start as above.
./hypview.py testbed BigLan
./hypview testbed BigLan
Three args - Project and experiment names, plus an optional root node name.
./hypview.py testbed BigLan clan'''
./hypview testbed BigLan clan'''
sys.exit()
elif len(sys.argv) == 2: # Read from a file.
print "Reading file:", sys.argv[1]
self.frame.ReadTopFile("wxHyperViewer", sys.argv[1])
pass
elif len(sys.argv) == 3: # Read from the database via XML-RPC, make a file.
print "Getting project:", sys.argv[1] + ", experiment:", sys.argv[2]
filename = exptToHv.getExperiment(sys.argv[1], sys.argv[2])
if filename:
self.frame.ReadTopFile("wxHyperViewer", filename)
# One command-line argument: read from a .hyp file.
elif len(sys.argv) == 2:
filename = sys.argv[1]
print "Reading file:", filename
pass
else:
print "Failed to get experiment from database."
# Two args: read an experiment from the DB via XML-RPC, and make a .hyp file.
elif len(sys.argv) == 3:
project = sys.argv[1]
experiment = sys.argv[2]
print "Getting project:", project + ", experiment:", experiment
filename = exptToHv.getExperiment(project, experiment)
pass
# Three args: experiment from database, with optional graph root node.
elif len(sys.argv) == 4:
project = sys.argv[1]
experiment = sys.argv[2]
root = sys.argv[3]
print "Getting project:", project + ", experiment:", experiment \
+ ", root node:", root
filename = exptToHv.getExperiment(project, experiment, root)
pass
elif len(sys.argv) == 4: # From database, with optional graph root node.
print "Getting project:", sys.argv[1] + ", experiment:", sys.argv[2] \
+ ", root node:", sys.argv[3]
filename = exptToHv.getExperiment(sys.argv[1], sys.argv[2], sys.argv[3])
if filename:
self.frame.ReadTopFile("wxHyperViewer", filename)
if filename == 2:
exptError = "There is no experiment " + project + "/" + experiment
print exptError
pass
else:
print "Failed to get experiment from database."
self.frame.ReadTopFile("wxHyperViewer", filename)
pass
pass
elif project:
print "Failed to get experiment from database."
pass
return True
pass
......@@ -224,8 +240,11 @@ class hvFrame(hvFrameUI):
##
# Mouse click events.
def OnClick(self, mouseEvent):
# Encode mouse button events for HypView.
btnNum = -1
if mouseEvent.LeftDown(): # Encode mouse button events.
# Left mouse button for X-Y motion of the hyperbolic center.
if mouseEvent.LeftDown():
btnNum = 0
btnState = 0
pass
......@@ -233,6 +252,8 @@ class hvFrame(hvFrameUI):
btnNum = 0
btnState = 1
pass
# Middle button for rotation of the hyperbolic space.
elif mouseEvent.MiddleDown():
btnNum = 1
btnState = 0
......@@ -242,7 +263,12 @@ class hvFrame(hvFrameUI):
btnState = 1
pass
# Pass mouse clicks on to HypView.
# Left button with control or shift held down is also rotation.
if btnNum == 0 and ( mouseEvent.ControlDown() or mouseEvent.ShiftDown() ):
btnNum = 1
pass
# Handle mouse clicks in HypView.
if btnNum != -1:
self.vwr.mouse(btnNum, btnState, mouseEvent.GetX(), mouseEvent.GetY(), 0, 0)
self.vwr.redraw()
......@@ -315,7 +341,14 @@ class hvOpen(OpenDialogUI):
root = self.ExperimentRoot.GetLineText(0)
hypfile = exptToHv.getExperiment(project, experiment, root)
if hypfile:
if hypfile == 2:
exptError = "There is no experiment " + project + "/" + experiment
self.ExperimentMsg.SetLabel(exptError)
print exptError
return
self.app.frame.ReadTopFile("wxHyperViewer", hypfile)
self.ExperimentMsg.SetLabel(" ")
self.Hide();
pass
......
# Pango Modules file
# Automatically generated file, do not edit
#
# ModulesPath = /usr/X11R6/lib/pango/1.4.0/modules
#
libs/pango/1.4.0/modules/pango-arabic-fc.so ArabicScriptEngineFc PangoEngineShape PangoRenderFc arabic:*
libs/pango/1.4.0/modules/pango-basic-x.so BasicScriptEngineX PangoEngineShape PangoRenderX common:
libs/pango/1.4.0/modules/pango-basic-fc.so BasicScriptEngineFc PangoEngineShape PangoRenderFc armenian:* bopomofo:* cherokee:* coptic:* cyrillic:* deseret:* ethiopic:* georgian:* gothic:* greek:* han:* hiragana:* katakana:* latin:* ogham:* old-italic:* runic:* canadian-aboriginal:* yi:* braille:* cypriot:* limbu:* osmanya:* shavian:* linear-b:* ugaritic:* common:
libs/pango/1.4.0/modules/pango-hangul-fc.so HangulScriptEngineFc PangoEngineShape PangoRenderFc hangul:*
libs/pango/1.4.0/modules/pango-indic-fc.so devaScriptEngineFc PangoEngineShape PangoRenderFc devanagari:*
libs/pango/1.4.0/modules/pango-indic-fc.so bengScriptEngineFc PangoEngineShape PangoRenderFc bengali:*
libs/pango/1.4.0/modules/pango-indic-fc.so guruScriptEngineFc PangoEngineShape PangoRenderFc gurmukhi:*
libs/pango/1.4.0/modules/pango-indic-fc.so gujrScriptEngineFc PangoEngineShape PangoRenderFc gujarati:*
libs/pango/1.4.0/modules/pango-indic-fc.so oryaScriptEngineFc PangoEngineShape PangoRenderFc oriya:*
libs/pango/1.4.0/modules/pango-indic-fc.so tamlScriptEngineFc PangoEngineShape PangoRenderFc tamil:*
libs/pango/1.4.0/modules/pango-indic-fc.so teluScriptEngineFc PangoEngineShape PangoRenderFc telugu:*
libs/pango/1.4.0/modules/pango-indic-fc.so kndaScriptEngineFc PangoEngineShape PangoRenderFc kannada:*
libs/pango/1.4.0/modules/pango-indic-fc.so mlymScriptEngineFc PangoEngineShape PangoRenderFc malayalam:*
libs/pango/1.4.0/modules/pango-thai-fc.so ThaiScriptEngineFc PangoEngineShape PangoRenderFc thai:*
libs/pango/1.4.0/modules/pango-hebrew-fc.so HebrewScriptEngineFc PangoEngineShape PangoRenderFc hebrew:*
#
# pangorc file for uninstalled operation. If pango-viewer is run with
# this file in the current directory it will set it as PANGO_RC_FILE
#
[Pango]
# Use this when the pango modules are in a subdirectory.
ModuleFiles = ./pango.modules.local
[PangoX]
AliasFiles = ./pangox.aliases
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment