Class: RailroadDiagrams::OneOrMore
- Inherits:
-
DiagramItem
show all
- Defined in:
- lib/railroad_diagrams/one_or_more.rb,
sig/generated/railroad_diagrams/one_or_more.rbs
Overview
Draws one or more occurrences of an item.
Instance Attribute Summary
Attributes inherited from DiagramItem
#attrs, #children, #down, #height, #needs_space, #up, #width
Instance Method Summary
collapse
-
#add_edge_paths(x, y, left_gap, right_gap) ⇒ void
-
#child_nodes ⇒ Object
-
#draw_main_item(x, y) ⇒ void
-
#draw_repeat_arc(x, y) ⇒ void
-
#format(x, y, width) ⇒ OneOrMore
-
#initialize(item, repeat = nil, id: nil, cls: nil, attrs: {}) ⇒ OneOrMore
constructor
A new instance of OneOrMore.
-
#measure(context) ⇒ Object
-
#render_svg(context, x, y, width) ⇒ Object
-
#render_text(context) ⇒ Object
-
#svg_path(data) ⇒ Object
-
#text_diagram ⇒ TextDiagram
-
#to_s ⇒ String
-
#walk(callback) ⇒ void
Methods inherited from DiagramItem
#==, #add, #apply_user_attributes, #container_element?, #determine_gaps, #each_node, #hash, inherited, #inspect, #structural_state, #to_str, #wrap_string, #write_children, #write_opening_tag, #write_standalone, #write_svg
Constructor Details
#initialize(item, repeat = nil, id: nil, cls: nil, attrs: {}) ⇒ OneOrMore
Returns a new instance of OneOrMore.
12
13
14
15
16
17
18
19
20
21
22
|
# File 'lib/railroad_diagrams/one_or_more.rb', line 12
def initialize(item, repeat = nil, id: nil, cls: nil, attrs: {})
super('g', id: id, cls: cls, data_attrs: attrs)
@item = wrap_string(item)
repeat ||= Skip.new
@rep = wrap_string(repeat)
@width = [@item.width, @rep.width].max + (AR * 2)
@height = @item.height
@up = @item.up
@down = [AR * 2, @item.down + VS + @rep.up + @rep.height + @rep.down].max
@needs_space = true
end
|
Instance Method Details
#add_edge_paths(x, y, left_gap, right_gap) ⇒ void
This method returns an undefined value.
156
157
158
159
|
# File 'lib/railroad_diagrams/one_or_more.rb', line 156
def add_edge_paths(x, y, left_gap, right_gap)
Path.new(x, y).h(left_gap).add(self)
Path.new(x + left_gap + @width, y + @height).h(right_gap).add(self)
end
|
#child_nodes ⇒ Object
133
134
135
|
# File 'lib/railroad_diagrams/one_or_more.rb', line 133
def child_nodes
[@item, @rep]
end
|
#draw_main_item(x, y) ⇒ void
This method returns an undefined value.
164
165
166
167
168
|
# File 'lib/railroad_diagrams/one_or_more.rb', line 164
def draw_main_item(x, y)
Path.new(x, y).right(AR).add(self)
@item.format(x + AR, y, @width - (AR * 2)).add(self)
Path.new(x + @width - AR, y + @height).right(AR).add(self)
end
|
#draw_repeat_arc(x, y) ⇒ void
This method returns an undefined value.
173
174
175
176
177
178
179
180
181
182
183
|
# File 'lib/railroad_diagrams/one_or_more.rb', line 173
def draw_repeat_arc(x, y)
distance_from_y = [AR * 2, @item.height + @item.down + VS + @rep.up].max
Path.new(x + AR, y).arc('nw').down(distance_from_y - (AR * 2)).arc('ws').add(self)
@rep.format(x + AR, y + distance_from_y, @width - (AR * 2)).add(self)
Path.new(x + @width - AR, y + distance_from_y + @rep.height)
.arc('se')
.up(distance_from_y - (AR * 2) + @rep.height - @item.height)
.arc('en')
.add(self)
end
|
33
34
35
36
37
38
39
40
41
42
|
# File 'lib/railroad_diagrams/one_or_more.rb', line 33
def format(x, y, width)
left_gap, right_gap = determine_gaps(width, @width)
add_edge_paths(x, y, left_gap, right_gap)
x += left_gap
draw_main_item(x, y)
draw_repeat_arc(x, y)
self
end
|
#measure(context) ⇒ Object
75
76
77
78
79
80
81
82
83
84
|
# File 'lib/railroad_diagrams/one_or_more.rb', line 75
def measure(context)
item = context.metrics(@item)
repeat = context.metrics(@rep)
arc = context.options.arc_radius
separation = context.options.vertical_separation
Metrics.new(width: [item.width, repeat.width].max + (arc * 2),
up: item.up, height: item.height,
down: [arc * 2, item.down + separation + repeat.up + repeat.height + repeat.down].max,
needs_space: true)
end
|
#render_svg(context, x, y, width) ⇒ Object
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
# File 'lib/railroad_diagrams/one_or_more.rb', line 86
def render_svg(context, x, y, width)
metrics = context.metrics(self)
item = context.metrics(@item)
repeat = context.metrics(@rep)
arc = context.options.arc_radius
separation = context.options.vertical_separation
left_gap, right_gap = context.gaps(width, metrics.width)
group = Svg::Element.new('g', @attrs.dup)
group << svg_path(Svg::PathData.new(x, y).h(left_gap))
group << svg_path(Svg::PathData.new(x + left_gap + metrics.width, y + metrics.height).h(right_gap))
x += left_gap
group << svg_path(Svg::PathData.new(x, y).h(arc))
group << context.render_svg(@item, x + arc, y, metrics.width - (arc * 2))
group << svg_path(Svg::PathData.new(x + metrics.width - arc, y + metrics.height).h(arc))
distance = [arc * 2, item.height + item.down + separation + repeat.up].max
group << svg_path(Svg::PathData.new(x + arc, y, arc_radius: arc).arc('nw').v([0, distance - (arc * 2)].max).arc('ws'))
group << context.render_svg(@rep, x + arc, y + distance, metrics.width - (arc * 2))
climb = distance - (arc * 2) + repeat.height - item.height
group << svg_path(Svg::PathData.new(x + metrics.width - arc, y + distance + repeat.height, arc_radius: arc)
.arc('se').v(-[0, climb].max).arc('en'))
group
end
|
#render_text(context) ⇒ Object
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
# File 'lib/railroad_diagrams/one_or_more.rb', line 110
def render_text(context)
line, top_left, left, bottom_left, top_right, right, bottom_right = context.parts.values_at(
'line', 'repeat_top_left', 'repeat_left', 'repeat_bot_left',
'repeat_top_right', 'repeat_right', 'repeat_bot_right'
)
item = @item.render_text(context)
repeat = @rep.render_text(context)
width = TextDiagram.max_width(item, repeat)
repeat = repeat.expand(0, width - repeat.width, 0, 0)
item = item.expand(0, width - item.width, 0, 0)
both = item.append_below(repeat, [])
left_lines = [top_left + line]
left_lines += ["#{left} "] * ((item.height - item.entry) + repeat.entry - 1)
left_lines << (bottom_left + line)
diagram = TextDiagram.new(0, 0, left_lines).append_right(both, '')
right_lines = [line + top_right]
right_lines += [" #{right}"] * ((item.height - item.exit) + repeat.exit - 1)
right_lines << (line + bottom_right)
diagram.append_right(TextDiagram.new(0, 0, right_lines), '')
end
|
#svg_path(data) ⇒ Object
147
148
149
|
# File 'lib/railroad_diagrams/one_or_more.rb', line 147
def svg_path(data)
Svg::Element.new('path', { 'd' => data }, self_closing: true)
end
|
#text_diagram ⇒ TextDiagram
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
|
# File 'lib/railroad_diagrams/one_or_more.rb', line 45
def text_diagram
parts = TextDiagram.get_parts(
%w[
line repeat_top_left repeat_left repeat_bot_left repeat_top_right repeat_right repeat_bot_right
]
)
line, repeat_top_left, repeat_left, repeat_bot_left, repeat_top_right, repeat_right, repeat_bot_right = parts
item_td = @item.text_diagram
repeat_td = @rep.text_diagram
fir_width = TextDiagram.max_width(item_td, repeat_td)
repeat_td = repeat_td.expand(0, fir_width - repeat_td.width, 0, 0)
item_td = item_td.expand(0, fir_width - item_td.width, 0, 0)
item_and_repeat_td = item_td.append_below(repeat_td, [])
left_lines = []
left_lines << (repeat_top_left + line)
left_lines += ["#{repeat_left} "] * ((item_td.height - item_td.entry) + repeat_td.entry - 1)
left_lines << (repeat_bot_left + line)
left_td = TextDiagram.new(0, 0, left_lines)
left_td = left_td.append_right(item_and_repeat_td, '')
right_lines = []
right_lines << (line + repeat_top_right)
right_lines += [" #{repeat_right}"] * ((item_td.height - item_td.exit) + repeat_td.exit - 1)
right_lines << (line + repeat_bot_right)
right_td = TextDiagram.new(0, 0, right_lines)
left_td.append_right(right_td, '')
end
|
#to_s ⇒ String
25
26
27
|
# File 'lib/railroad_diagrams/one_or_more.rb', line 25
def to_s
"OneOrMore(#{@item}, repeat=#{@rep})"
end
|
#walk(callback) ⇒ void
This method returns an undefined value.
139
140
141
142
143
|
# File 'lib/railroad_diagrams/one_or_more.rb', line 139
def walk(callback)
callback.call(self)
@item.walk(callback)
@rep.walk(callback)
end
|