Class: Archimate::Svg::Diagram

Inherits:
Object
  • Object
show all
Defined in:
lib/archimate/svg/diagram.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(diagram) ⇒ Diagram

Returns a new instance of Diagram.



11
12
13
14
# File 'lib/archimate/svg/diagram.rb', line 11

def initialize(diagram)
  @diagram = diagram
  @svg_template = Nokogiri::XML(SvgTemplate.new.to_s).freeze
end

Instance Attribute Details

#diagramObject (readonly)

Returns the value of attribute diagram.



9
10
11
# File 'lib/archimate/svg/diagram.rb', line 9

def diagram
  @diagram
end

Instance Method Details

#attr_to_i(node, attr) ⇒ Object



69
70
71
72
# File 'lib/archimate/svg/diagram.rb', line 69

def attr_to_i(node, attr)
  ival = node.attr(attr)
  ival.to_i unless ival.nil? || ival.strip.empty?
end

#calculate_max_extents(doc) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/archimate/svg/diagram.rb', line 50

def calculate_max_extents(doc)
  node_vals =
    doc
    .xpath("//*[@x or @y]")
    .map { |node| %w[x y width height].map { |attr| node.attr(attr).to_i } }
  doc.css(".archimate-relationship")
    .each { |path|
      path.attr("d").split(" ").each_slice(3) do |point|
        node_vals << [point[1].to_i, point[2].to_i, 0, 0]
      end
    }
  Extents.new(
    node_vals.map(&:first).min,
    node_vals.map { |v| v[0] + v[2] }.max,
    node_vals.map { |v| v[1] }.min,
    node_vals.map { |v| v[1] + v[3] }.max
  )
end

#format_node(node, depth = 4) ⇒ Object



42
43
44
45
46
47
48
# File 'lib/archimate/svg/diagram.rb', line 42

def format_node(node, depth = 4)
  node.children.each do |child|
    child.add_previous_sibling("\n#{ ' ' * depth }")
    format_node(child, depth + 2)
    child.add_next_sibling("\n#{ ' ' * (depth - 2) }") if node.children.last == child
  end
end

#render_connections(svg_node) ⇒ Object



80
81
82
83
84
# File 'lib/archimate/svg/diagram.rb', line 80

def render_connections(svg_node)
  diagram
    .connections
    .reduce(svg_node) { |svg, connection| Connection.new(connection).render(svg) }
end

#render_elements(svg_node) ⇒ Object



74
75
76
77
78
# File 'lib/archimate/svg/diagram.rb', line 74

def render_elements(svg_node)
  diagram
    .nodes
    .reduce(svg_node) { |svg, child| Child.new(child).render_elements(svg) }
end

#set_title(svg) ⇒ Object



28
29
30
31
# File 'lib/archimate/svg/diagram.rb', line 28

def set_title(svg)
  svg.at_css("title").content = diagram.name || "untitled"
  svg.at_css("desc").content = diagram.documentation.to_s || ""
end

#to_svgObject



16
17
18
19
20
21
22
23
24
25
26
# File 'lib/archimate/svg/diagram.rb', line 16

def to_svg
  svg_doc = @svg_template.clone
  set_title(svg_doc)
  top_group = svg_doc.at_css("#archimate-diagram")
  render_connections(
    render_elements(top_group)
  )
  update_viewbox(svg_doc.at_css("svg"))
  format_node(top_group)
  svg_doc.to_xml(encoding: 'UTF-8', indent: 2)
end

#update_viewbox(svg) ⇒ Object

Scan the SVG and figure out min & max



34
35
36
37
38
39
40
# File 'lib/archimate/svg/diagram.rb', line 34

def update_viewbox(svg)
  extents = calculate_max_extents(svg).expand(10)
  svg.set_attribute(:width, extents.width)
  svg.set_attribute(:height, extents.height)
  svg.set_attribute("viewBox", "#{extents.min_x} #{extents.min_y} #{extents.width} #{extents.height}")
  svg
end