DataStructs.HierarchyVis

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