Class: Archimate::Svg::Legend

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(svg_diagram) ⇒ Legend

Returns a new instance of Legend.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/archimate/svg/legend.rb', line 25

def initialize(svg_diagram)
  @svg_diagram = svg_diagram
  @legend_group = svg_diagram.legend_group
  @top_margin = 25
  @columns = 2
  @element_width = 110
  @element_height = 50
  @line_height = 15
  @text_indent = 10
  @description_width = 500
  @col_width = element_width + text_indent + description_width + text_indent
  @row_height = element_height + text_indent
  @section_width = columns * col_width
  @legend_width = text_indent * 2 + columns * col_width
  diagram = svg_diagram.diagram
  @element_classes = diagram.elements.map(&:class).uniq
  @layers = diagram.elements.map(&:layer).uniq.sort
  @relationship_classes = diagram.relationships.map(&:class).uniq
end

Instance Attribute Details

#col_widthObject (readonly)

Returns the value of attribute col_width.



16
17
18
# File 'lib/archimate/svg/legend.rb', line 16

def col_width
  @col_width
end

#columnsObject (readonly)

Returns the value of attribute columns.



10
11
12
# File 'lib/archimate/svg/legend.rb', line 10

def columns
  @columns
end

#description_widthObject (readonly)

Returns the value of attribute description_width.



15
16
17
# File 'lib/archimate/svg/legend.rb', line 15

def description_width
  @description_width
end

#element_classesObject (readonly)

Returns the value of attribute element_classes.



22
23
24
# File 'lib/archimate/svg/legend.rb', line 22

def element_classes
  @element_classes
end

#element_heightObject (readonly)

Returns the value of attribute element_height.



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

def element_height
  @element_height
end

#element_widthObject (readonly)

Returns the value of attribute element_width.



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

def element_width
  @element_width
end

#layersObject (readonly)

Returns the value of attribute layers.



21
22
23
# File 'lib/archimate/svg/legend.rb', line 21

def layers
  @layers
end

#legend_groupObject (readonly)

Returns the value of attribute legend_group.



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

def legend_group
  @legend_group
end

#legend_widthObject (readonly)

Returns the value of attribute legend_width.



20
21
22
# File 'lib/archimate/svg/legend.rb', line 20

def legend_width
  @legend_width
end

#line_heightObject (readonly)

Returns the value of attribute line_height.



13
14
15
# File 'lib/archimate/svg/legend.rb', line 13

def line_height
  @line_height
end

#relationship_classesObject (readonly)

Returns the value of attribute relationship_classes.



23
24
25
# File 'lib/archimate/svg/legend.rb', line 23

def relationship_classes
  @relationship_classes
end

#row_heightObject (readonly)

Returns the value of attribute row_height.



17
18
19
# File 'lib/archimate/svg/legend.rb', line 17

def row_height
  @row_height
end

#section_widthObject (readonly)

Returns the value of attribute section_width.



19
20
21
# File 'lib/archimate/svg/legend.rb', line 19

def section_width
  @section_width
end

#svg_diagramObject (readonly)

Returns the value of attribute svg_diagram.



8
9
10
# File 'lib/archimate/svg/legend.rb', line 8

def svg_diagram
  @svg_diagram
end

#text_indentObject (readonly)

Returns the value of attribute text_indent.



14
15
16
# File 'lib/archimate/svg/legend.rb', line 14

def text_indent
  @text_indent
end

#top_marginObject (readonly)

Returns the value of attribute top_margin.



18
19
20
# File 'lib/archimate/svg/legend.rb', line 18

def top_margin
  @top_margin
end

Instance Method Details

#diagram_widthObject



162
163
164
# File 'lib/archimate/svg/legend.rb', line 162

def diagram_width
  @diagram_width ||= extents.width
end

#element_example(x, y, klass, klass_name, xml) ⇒ Object



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
# File 'lib/archimate/svg/legend.rb', line 93

def element_example(x, y, klass, klass_name, xml)
  case klass_name
  when "OrJunction"
    r = (element_height - 10) / 4
    xml.circle(cx: x + r, cy: y + row_height / 2 - r, r: r, style: "fill:#fff;stroke:#000")
    xml.text_(x: x + r * 2 + text_indent, y: y + row_height / 2 - line_height / 2, class: "archimate-legend-title") do
      xml.text("Or Junction")
    end
  when "AndJunction"
    r = (element_height - 10) / 4
    xml.circle(cx: x + r, cy: y + row_height / 2 - r, r: r, style: "fill:#000;stroke:#000")
    xml.text_(x: x + r * 2 + text_indent, y: y + row_height / 2 - line_height / 2, class: "archimate-legend-title") do
      xml.text("And Junction")
    end
  else
    element = DataModel::Elements.const_get(klass_name).new(id: "legend-element-#{klass_name}", name: klass::NAME)
    view_node = DataModel::ViewNode.new(
      id: "legend-element-type-#{klass_name}",
      name: klass::NAME,
      type: klass_name,
      element: element,
      diagram: svg_diagram.diagram,
      bounds: DataModel::Bounds.new(x: x, y: y, width: element_width, height: element_height)
    )
    EntityFactory.make_entity(view_node, nil).to_svg(xml)
  end
end

#element_type_description(text, text_bounds, xml) ⇒ Object

Paragraph that describes a element or relationship



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/archimate/svg/legend.rb', line 130

def element_type_description(text, text_bounds, xml)
  css_style = "height:#{text_bounds.height}px;width:#{text_bounds.width}px;"
  xml.foreignObject(text_bounds.to_h) do
    xml.table(xmlns: "http://www.w3.org/1999/xhtml", style: css_style) do
      xml.tr(style: "height:#{text_bounds.height}px;") do
        xml.td(class: "entity-description") do
          xml.p(class: "entity-description") do
            text.tr("\r\n", "\n").split(/[\r\n]/).each do |line|
              xml.text(line)
              xml.br
            end
          end
        end
      end
    end
  end
end

#extentsObject



158
159
160
# File 'lib/archimate/svg/legend.rb', line 158

def extents
  @extents ||= svg_diagram.calculate_max_extents
end

#insertObject



49
50
51
52
53
54
55
# File 'lib/archimate/svg/legend.rb', line 49

def insert
  Nokogiri::XML::Builder.with(legend_group) do |xml|
    legend_for_relationship_classes(xml,
                                    legend_for_element_types_by_layer(xml,
                                                                      top_level_legend(xml)))
  end
end

#item_example(x, y, klass, xml) ⇒ Object

Legend entry for a particular element type



83
84
85
86
87
88
89
90
91
# File 'lib/archimate/svg/legend.rb', line 83

def item_example(x, y, klass, xml)
  klass_name = klass.name.split("::").last
  if klass.superclass == DataModel::Element
    element_example(x, y, klass, klass_name, xml)
  elsif klass.superclass == DataModel::Relationship
    relationship_example(x, y, klass, klass_name, xml)
  end
  element_type_description(klass::DESCRIPTION, text_bounds(x, y), xml)
end

#item_x(idx) ⇒ Object



194
195
196
# File 'lib/archimate/svg/legend.rb', line 194

def item_x(idx)
  legend_left + (text_indent * 2) + (col_width * (idx % columns))
end

#item_y(top, idx) ⇒ Object



198
199
200
# File 'lib/archimate/svg/legend.rb', line 198

def item_y(top, idx)
  top + (row_height * (idx / columns))
end

#layer_elements(layer) ⇒ Object



174
175
176
# File 'lib/archimate/svg/legend.rb', line 174

def layer_elements(layer)
  element_classes.select { |k| k::LAYER == layer }
end

#legend_for_element_types_by_layer(xml, top) ⇒ Object



61
62
63
64
65
# File 'lib/archimate/svg/legend.rb', line 61

def legend_for_element_types_by_layer(xml, top)
  layers.inject(top) do |section_top, layer|
    section_legend(section_top, layer.name, layer.background_class, layer_elements(layer), xml)
  end
end

#legend_for_relationship_classes(xml, top) ⇒ Object



67
68
69
70
71
# File 'lib/archimate/svg/legend.rb', line 67

def legend_for_relationship_classes(xml, top)
  return top if relationship_classes.empty?

  section_legend(top, "Relationships", "archimate-other-background", relationship_classes, xml)
end

#legend_heightObject



178
179
180
181
182
183
184
# File 'lib/archimate/svg/legend.rb', line 178

def legend_height
  height = layers.inject(line_height) do |h, layer|
    h + rows(layer_elements(layer)) * row_height + line_height * 3
  end + line_height
  height += rows(relationship_classes) * row_height + line_height * 3 unless relationship_classes.empty?
  height
end

#legend_leftObject



170
171
172
# File 'lib/archimate/svg/legend.rb', line 170

def legend_left
  extents.min_x
end

#legend_topObject



166
167
168
# File 'lib/archimate/svg/legend.rb', line 166

def legend_top
  extents.max_y + top_margin
end

#relationship_example(x, y, klass, klass_name, xml) ⇒ Object



121
122
123
124
125
126
127
# File 'lib/archimate/svg/legend.rb', line 121

def relationship_example(x, y, klass, klass_name, xml)
  xml.text_(x: x + text_indent, y: y + line_height, class: "archimate-legend-title") do
    xml.text(klass::NAME)
  end
  css_class = "archimate-#{klass_name.downcase} archimate-relationship"
  xml.path(d: "M#{x} #{y + row_height / 2} h #{element_width}", class: css_class)
end

#removeObject



45
46
47
# File 'lib/archimate/svg/legend.rb', line 45

def remove
  legend_group.remove
end

#rows(items) ⇒ Object



186
187
188
# File 'lib/archimate/svg/legend.rb', line 186

def rows(items)
  (items.size / columns.to_f).round
end

#section_height(items) ⇒ Object



190
191
192
# File 'lib/archimate/svg/legend.rb', line 190

def section_height(items)
  rows(items) * row_height + line_height * 2
end

#section_legend(top, heading, css_class, items, xml) ⇒ Object



73
74
75
76
77
78
79
80
# File 'lib/archimate/svg/legend.rb', line 73

def section_legend(top, heading, css_class, items, xml)
  sec_height = section_height(items)
  top = text(legend_left + text_indent, top, section_width, sec_height, heading, css_class, xml)
  items.each_with_index do |item, idx|
    item_example(item_x(idx), item_y(top, idx), item, xml)
  end
  top + sec_height
end

#text(x, y, width, height, str, css_class, xml) ⇒ Object



148
149
150
151
152
153
154
155
156
# File 'lib/archimate/svg/legend.rb', line 148

def text(x, y, width, height, str, css_class, xml)
  css_style = "fill-opacity: 0.4"
  xml.rect(x: x, y: y - line_height, width: width, height: height,
           rx: 5, ry: 5, class: css_class, style: css_style)
  xml.text_(x: x + text_indent, y: y, class: "archimate-legend-title") do
    xml.text(str)
  end
  y + line_height
end

#text_bounds(x, y) ⇒ Object



202
203
204
205
206
207
208
209
# File 'lib/archimate/svg/legend.rb', line 202

def text_bounds(x, y)
  DataModel::Bounds.new(
    x: x + element_width + text_indent,
    y: y,
    width: description_width,
    height: element_height
  )
end

#top_level_legend(xml) ⇒ Object



57
58
59
# File 'lib/archimate/svg/legend.rb', line 57

def top_level_legend(xml)
  text(legend_left, legend_top, legend_width, legend_height, "Legend", "archimate-legend", xml) + line_height
end