1
2
3
4
5
6
7
8
9
10
11 """ functionality for drawing hierarchical catalogs on sping
12 canvases
13
14 """
15 from sping import pid as piddle
16
17
19 circRad = 10
20 minCircRad = 4
21 maxCircRad = 16
22 circColor = piddle.Color(0.6, 0.6, 0.9)
23 terminalEmptyColor = piddle.Color(.8, .8, .2)
24 terminalOnColor = piddle.Color(0.8, 0.8, 0.8)
25 terminalOffColor = piddle.Color(0.2, 0.2, 0.2)
26 outlineColor = piddle.transparent
27 lineColor = piddle.Color(0, 0, 0)
28 lineWidth = 1
29 horizOffset = 5
30 vertOffset = 75
31 topMargin = 20
32 labelFont = piddle.Font(face='helvetica', size=10)
33 highlightColor = piddle.Color(1., 1., .4)
34 highlightWidth = 2
35
36
37 visOpts = VisOpts()
38
39
49
50
51 -def DrawHierarchy(adjList, levelList, canvas, entryColors=None, bitIds=None, minLevel=-1,
52 maxLevel=1e8):
53 """
54
55 Arguments:
56
57 - adjList: adjacency list representation of the hierarchy to be drawn
58
59 - levelList: dictionary mapping level -> list of ids
60
61 """
62 if bitIds is None:
63 bitIds = []
64 if entryColors is None:
65 entryColors = {}
66
67 levelLengths = levelList.keys()
68 levelLengths.sort()
69 minLevel = max(minLevel, levelLengths[0])
70 maxLevel = min(maxLevel, levelLengths[-1])
71
72 dims = canvas.size
73 drawLocs = {}
74
75 for levelLen in range(maxLevel, minLevel - 1, -1):
76 nLevelsDown = levelLen - minLevel
77 pos = [0, visOpts.vertOffset * nLevelsDown + visOpts.topMargin]
78
79 ids = levelList.get(levelLen, [])
80
81
82 nHere = len(ids)
83 canvas.defaultFont = visOpts.labelFont
84 if nHere:
85
86 spacePerNode = float(dims[0]) / nHere
87 spacePerNode -= visOpts.horizOffset
88 nodeRad = max(spacePerNode / 2, visOpts.minCircRad)
89 nodeRad = min(nodeRad, visOpts.maxCircRad)
90 spacePerNode = nodeRad * 2 + visOpts.horizOffset
91
92 pos[0] = dims[0] / 2.
93
94 if nHere % 2:
95 pos[0] -= spacePerNode / 2
96
97
98 pos[0] -= (nHere // 2 - .5) * spacePerNode
99
100
101 for ID in ids:
102 if not bitIds or ID in bitIds:
103
104 if levelLen != maxLevel:
105 for neighbor in adjList[ID]:
106 if neighbor in drawLocs:
107 p2 = drawLocs[neighbor][0]
108 canvas.drawLine(pos[0], pos[1], p2[0], p2[1], visOpts.lineColor, visOpts.lineWidth)
109 drawLocs[ID] = tuple(pos), nodeRad
110 pos[0] += spacePerNode
111
112 for ID in drawLocs.keys():
113 pos, nodeRad = drawLocs[ID]
114 x1, y1 = pos[0] - nodeRad, pos[1] - nodeRad
115 x2, y2 = pos[0] + nodeRad, pos[1] + nodeRad
116 drawColor = entryColors.get(ID, visOpts.circColor)
117 canvas.drawEllipse(x1, y1, x2, y2, visOpts.outlineColor, 0, drawColor)
118 label = str(ID)
119
120
121 txtLoc = (pos[0] + canvas.fontHeight() / 4, pos[1] + canvas.stringWidth(label) / 2)
122 canvas.drawString(label, txtLoc[0], txtLoc[1], angle=90)
123
124 return drawLocs
125