Package DataStructs :: Module HierarchyVis
[hide private]
[frames] | no frames]

Source Code for Module DataStructs.HierarchyVis

  1  # $Id: HierarchyVis.py 2 2006-05-06 22:54:39Z glandrum $ 
  2  #  
  3  #  Copyright (C)2003-2006  Rational Discovery LLC 
  4  # 
  5  #   @@ All Rights Reserved  @@ 
  6  # 
  7  """ functionality for drawing hierarchical catalogs on sping 
  8      canvases 
  9   
 10  """     
 11  from sping import pid as piddle 
 12   
13 -class VisOpts(object):
14 circRad = 10 15 minCircRad = 4 16 maxCircRad = 16 17 circColor = piddle.Color(0.6,0.6,0.9) 18 terminalEmptyColor = piddle.Color(.8,.8,.2) 19 terminalOnColor = piddle.Color(0.8,0.8,0.8) 20 terminalOffColor = piddle.Color(0.2,0.2,0.2) 21 outlineColor = piddle.transparent 22 lineColor = piddle.Color(0,0,0) 23 lineWidth = 1 24 horizOffset = 5 25 vertOffset = 75 26 topMargin = 20 27 labelFont = piddle.Font(face='helvetica',size=10) 28 highlightColor = piddle.Color(1.,1.,.4) 29 highlightWidth = 2
30 31 visOpts = VisOpts() 32
33 -def GetMinCanvasSize(adjList,levelList):
34 maxAcross = -1 35 for k in levelList.keys(): 36 nHere = len(levelList[k]) 37 maxAcross = max(maxAcross,nHere) 38 nLevs = len(levelList.keys()) 39 minSize = ( maxAcross*(visOpts.minCircRad*2+visOpts.horizOffset), 40 visOpts.topMargin + nLevs * visOpts.vertOffset ) 41 return minSize
42
43 -def DrawHierarchy(adjList,levelList,canvas,entryColors=None, 44 bitIds=None,minLevel=-1,maxLevel=1e8):
45 """ 46 47 Arguments: 48 49 - adjList: adjacency list representation of the hierarchy to be drawn 50 51 - levelList: dictionary mapping level -> list of ids 52 53 """ 54 if bitIds is None: 55 bitIds = [] 56 if entryColors is None: 57 entryColors = {} 58 59 levelLengths = levelList.keys() 60 levelLengths.sort() 61 minLevel = max(minLevel,levelLengths[0]) 62 maxLevel = min(maxLevel,levelLengths[-1]) 63 64 dims = canvas.size 65 drawLocs = {} 66 # start at the bottom of the hierarchy and work up: 67 for levelLen in range(maxLevel,minLevel-1,-1): 68 nLevelsDown = levelLen-minLevel 69 pos = [0,visOpts.vertOffset*nLevelsDown+visOpts.topMargin] 70 71 ids = levelList.get(levelLen,[]) 72 73 # FIX: we'll eventually want to figure out some kind of sorting here: 74 nHere = len(ids) 75 canvas.defaultFont=visOpts.labelFont 76 if nHere: 77 # figure the size of each node at this level: 78 spacePerNode = float(dims[0]) / nHere 79 spacePerNode -= visOpts.horizOffset 80 nodeRad = max(spacePerNode/2,visOpts.minCircRad) 81 nodeRad = min(nodeRad,visOpts.maxCircRad) 82 spacePerNode = nodeRad*2+visOpts.horizOffset 83 # start in the midde of the canvas: 84 pos[0] = dims[0]/2. 85 # maybe we need to offset a little: 86 if nHere%2: 87 pos[0] -= spacePerNode/2 88 89 # move to the left by half the number of nodes: 90 pos[0] -= (nHere // 2 - .5) * spacePerNode 91 92 # Find the locations and draw connectors: 93 for id in ids: 94 if not bitIds or id in bitIds: 95 # first do lines down to the next level: 96 if levelLen != maxLevel: 97 for neighbor in adjList[id]: 98 if drawLocs.has_key(neighbor): 99 p2 = drawLocs[neighbor][0] 100 canvas.drawLine(pos[0],pos[1],p2[0],p2[1], 101 visOpts.lineColor,visOpts.lineWidth) 102 drawLocs[id] = tuple(pos),nodeRad 103 pos[0] += spacePerNode 104 105 for id in drawLocs.keys(): 106 pos,nodeRad = drawLocs[id] 107 x1,y1 = pos[0]-nodeRad,pos[1]-nodeRad 108 x2,y2 = pos[0]+nodeRad,pos[1]+nodeRad 109 drawColor = entryColors.get(id,visOpts.circColor) 110 canvas.drawEllipse(x1,y1,x2,y2,visOpts.outlineColor, 111 0,drawColor) 112 label = str(id) 113 #txtLoc = ( pos[0]-canvas.stringWidth(label)/2, 114 # pos[1]+canvas.fontHeight()/4 ) 115 txtLoc = ( pos[0]+canvas.fontHeight()/4, 116 pos[1]+canvas.stringWidth(label)/2) 117 canvas.drawString(label,txtLoc[0],txtLoc[1],angle=90) 118 119 return drawLocs
120