1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
#
# node.rb - RubyTreemap
#
# Copyright (c) 2006 by Andrew Bruno <aeb@qnot.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
#
require "md5"
module Treemap
#
# A generic tree node class which is used to represent the data to be
# treemap'ed. The Layout and Output classes expect an object of this
# type to perform the treemap calculations on.
#
# Create a simple tree:
# root = Treemap::Node.new
# root.new_child(:size => 6)
# root.new_child(:size => 6)
# root.new_child(:size => 4)
# root.new_child(:size => 3)
# root.new_child(:size => 2)
# root.new_child(:size => 2)
# root.new_child(:size => 1)
#
# Initialize values:
# root = Treemap::Node.new(:label => "All", :size => 100, :color => "#FFCCFF")
# child1 = Treemap::Node.new(:label => "Child 1", :size => 50)
# child2 = Treemap::Node.new(:label => "Child 2", :size => 50)
# root.add_child(child1)
# root.add_child(child2)
#
#
class Treemap::Node
attr_accessor :id, :label, :color, :size, :bounds, :parent, :tooltip, :url, :title, :rid, :browsable
attr_reader :children
#
# Create a new Node. You can initialize the node by passing in
# a hash with any of the following keys:
#
# * :size - The size that this node represents. For non-leaf nodes the
# size must be equal to the sum of the sizes of it's children. If size
# is nil then the value will be calculated by recursing the children.
# * :label - The label for this node. Used when displaying. Defaults to "node"
# * :color - The background fill color in hex to render when drawing the
# square. If the value is a number a color will be calculated. An example
# string color would be: ##FFFFFF (white)
# * :id - a unique id to assign to this node. Default id will be generated if
# one is not provided.
#
#
def initialize(opts = {})
@size = opts[:size]
@label = opts[:label]
@title = opts[:title]
@color = opts[:color]
@id = opts[:id]
@url = opts[:url]
@tooltip = opts[:tooltip]
@children = []
@rid = opts[:rid]
@browsable = opts[:browsable]
if(@id.nil?)
make_id
end
end
#
# Returns the depth of the node. 0 for root.
#
def depth
return 0 if parent.nil?
1 + self.parent.depth
end
def add_child(node)
# XXX check to see that a node with the same label doesn't already exist.
# having 2 nodes with the same label at the same depth
# doesn't seem to make sense
node.parent = self
@children.push(node)
end
#
# Creates a new node and adds it as a child. See new method.
#
def new_child(*args)
node = Treemap::Node.new(*args)
self.add_child(node)
end
def find
@children.find { |c| yield(c) }
end
def to_s
str = "[:id => " + id + " :label => " + label
str += " :size => " + size.to_s + " :color => " + color.to_s
if(not(bounds.nil?))
str += " :bounds => " + bounds.to_s
end
str += "]"
str
end
def size
return @size if !@size.nil?
sum = 0
@children.each do |c|
sum += c.size
end
sum
end
def label
return @label if !@label.nil?
"node - " + size.to_s
end
def leaf?
return true if @children.nil?
!(@children.size > 0)
end
private
def make_id
#XXX prob should change this. Create a better way to generate unique id's
@id = MD5.new([self.label, rand(100000000)].join("-")).hexdigest
end
end
end
|