ea 0.6.91 → 0.6.93
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ffc412a948388b91fc07382b857fdcdbb4fda6a6d12bdc4cba7931c29720bf2e
|
|
4
|
+
data.tar.gz: 06cf5da1fb2062d414866f36e03798cfc9052fb2fcae45dfb78552e754d07662
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3d498df6109da7ad7c4368b589f34c9dbe3a48171571e9993fef75d80874e3f1eb6a31e6f890db39c5f413a61e895da8e3bf7f81a6d01b94fdc0a225267fb809
|
|
7
|
+
data.tar.gz: ec4537e30476a83f7ecc39c29aacb1d54f6a788f9a87c97bfcf86f665ece6010ca640a31062d30c0ad2f1fa8362bc1e834f207355989b27f9197ede225eff54a
|
|
@@ -8,6 +8,21 @@ module Ea
|
|
|
8
8
|
module Routing
|
|
9
9
|
private
|
|
10
10
|
|
|
11
|
+
# A lateral tree leaves the side edge before turning upward.
|
|
12
|
+
# Keep that dock only when its first leg actually points outward.
|
|
13
|
+
def lateral_source_exit?(points, link_row, bounds)
|
|
14
|
+
return false unless points.size == 3 && DiagramStyleParser.parse(link_row.style)[:tree] == "LV"
|
|
15
|
+
|
|
16
|
+
anchor, bend = points.take(2)
|
|
17
|
+
anchor[1] == bend[1] && outward_side_exit?(anchor[0], bend[0], bounds)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def outward_side_exit?(anchor_x, bend_x, bounds)
|
|
21
|
+
left = bounds.x
|
|
22
|
+
right = left + bounds.width
|
|
23
|
+
(anchor_x == left && bend_x < left) || (anchor_x == right && bend_x > right)
|
|
24
|
+
end
|
|
25
|
+
|
|
11
26
|
# Keep a vertical tree trunk whose bends still fit both boxes
|
|
12
27
|
# and the open gap; the closest facing edges need not share its x.
|
|
13
28
|
def preserve_stored_tree?(points, link_row, connector, src, tgt)
|
|
@@ -577,9 +577,8 @@ module Ea
|
|
|
577
577
|
# describe the source-side and target-side bend offsets
|
|
578
578
|
# relative to the edge attachment points.
|
|
579
579
|
#
|
|
580
|
-
# Path takes precedence when present
|
|
581
|
-
#
|
|
582
|
-
# connectors with at most one bend on each end.
|
|
580
|
+
# Custom-line Path takes precedence when present. Direct mode
|
|
581
|
+
# ignores old custom bends; SX/SY/EX/EY supply its endpoint ports.
|
|
583
582
|
#
|
|
584
583
|
# If we can't resolve the source or target element placement
|
|
585
584
|
# for this diagram, we emit no waypoints (the connector will
|
|
@@ -607,8 +606,10 @@ module Ea
|
|
|
607
606
|
element_edge_point(target_placement, :target, edge_out)
|
|
608
607
|
|
|
609
608
|
intermediate = intermediate_waypoints(link_row)
|
|
610
|
-
if
|
|
611
|
-
|
|
609
|
+
if DiagramStyleParser.parse(link_row.style)[:mode] == "1"
|
|
610
|
+
points = [source_point, target_point]
|
|
611
|
+
elsif edge_out == 2 && source_port && target_port &&
|
|
612
|
+
!valid_tree_path?(intermediate, source_placement)
|
|
612
613
|
# A stale tree Path (not on the source's facing edge) is
|
|
613
614
|
# recomputed: source port -> corner at (target dock x,
|
|
614
615
|
# source exit y) -> target port.
|
|
@@ -923,7 +924,7 @@ module Ea
|
|
|
923
924
|
target_y = tgt_b.y + tgt_b.height
|
|
924
925
|
source_y -= inset if points[1][1] < source_y - inset
|
|
925
926
|
target_y += inset if points[-2][1] > target_y + inset
|
|
926
|
-
unless strict && points[1][1] >= source_y
|
|
927
|
+
unless lateral_source_exit?(points, link_row, src_b) || (strict && points[1][1] >= source_y)
|
|
927
928
|
points[0] = [points[1][0].clamp(src_b.x, src_b.x + src_b.width), source_y]
|
|
928
929
|
end
|
|
929
930
|
unless strict && points[-2][1] <= target_y
|
|
@@ -19,6 +19,8 @@ module Ea
|
|
|
19
19
|
# for those — only simple role names render.
|
|
20
20
|
class EndLabel
|
|
21
21
|
PROPERTY_STEREOTYPE = "«Property»"
|
|
22
|
+
SEAT_FONT_SIZE = 7
|
|
23
|
+
SEAT_X_INSET = 3
|
|
22
24
|
|
|
23
25
|
attr_reader :canvas, :model_index, :document, :theme,
|
|
24
26
|
:font_family, :font_size, :font_unit
|
|
@@ -41,12 +43,23 @@ module Ea
|
|
|
41
43
|
# anchor - [x, y] of the connector endpoint
|
|
42
44
|
# connector - the DiagramConnector (for relationship lookup)
|
|
43
45
|
# end_kind - :source or :target
|
|
46
|
+
# heading - [dx, dy] of the first leg leaving the anchor
|
|
47
|
+
# stored_labels - the connector has stored label boxes at
|
|
48
|
+
# either end; false keeps the opposite-end
|
|
49
|
+
# fallback
|
|
44
50
|
def texts(text_box:, mult_box:, anchor:, connector:, end_kind:,
|
|
45
|
-
tree: false)
|
|
51
|
+
tree: false, heading: nil, stored_labels: false)
|
|
46
52
|
from_property, role, mult = role_and_multiplicity(connector, end_kind)
|
|
47
53
|
if role_empty?(role) && mult_empty?(mult)
|
|
48
54
|
other_from_prop, other_role, other_mult = role_and_multiplicity(connector,
|
|
49
55
|
opposite(end_kind))
|
|
56
|
+
if stored_labels
|
|
57
|
+
return [] if role_empty?(other_role) && mult_empty?(other_mult)
|
|
58
|
+
|
|
59
|
+
return own_stereotype_only(text_box, anchor, connector,
|
|
60
|
+
end_kind)
|
|
61
|
+
end
|
|
62
|
+
|
|
50
63
|
role = other_role if role_empty?(role)
|
|
51
64
|
mult ||= other_mult
|
|
52
65
|
from_property ||= other_from_prop
|
|
@@ -73,6 +86,11 @@ module Ea
|
|
|
73
86
|
# the end has none.
|
|
74
87
|
stereo = connector_source_dest_stereotype(connector, end_kind)
|
|
75
88
|
stereo = stereo.nil? || stereo.empty? ? nil : "«#{stereo}»"
|
|
89
|
+
direction = leg_direction(end_kind, heading)
|
|
90
|
+
if direction && !(tree && zero_offset?(text_box, mult_box))
|
|
91
|
+
text_pos = role_seat(direction, anchor, text_box, role) || text_pos
|
|
92
|
+
mult_pos = mult_seat(direction, anchor, mult_box) || mult_pos
|
|
93
|
+
end
|
|
76
94
|
|
|
77
95
|
build_texts(role:, mult:, standalone:,
|
|
78
96
|
text_pos:, mult_pos:, stereo:, text_box:)
|
|
@@ -80,6 +98,19 @@ module Ea
|
|
|
80
98
|
|
|
81
99
|
private
|
|
82
100
|
|
|
101
|
+
# With stored boxes on the connector, an end that carries no
|
|
102
|
+
# data of its own draws only its own stereotype; the data end
|
|
103
|
+
# draws the role and multiplicity; with no data anywhere nothing
|
|
104
|
+
# is drawn. Connectors with no stored box keep the opposite-end
|
|
105
|
+
# fallback.
|
|
106
|
+
def own_stereotype_only(text_box, anchor, connector, end_kind)
|
|
107
|
+
stereo = connector_source_dest_stereotype(connector, end_kind)
|
|
108
|
+
pos = position_at(text_box, anchor)
|
|
109
|
+
return [] if stereo.nil? || stereo.empty? || pos.nil?
|
|
110
|
+
|
|
111
|
+
[text_at(pos[0], pos[1], "«#{stereo}»")]
|
|
112
|
+
end
|
|
113
|
+
|
|
83
114
|
# EA's tree-route label clusters (hand-verified against the
|
|
84
115
|
# EA-published reference, SY 8542 with canvas=(0,0)):
|
|
85
116
|
# source-end pairs stack at the exit point (role +3/-23,
|
|
@@ -109,6 +140,63 @@ module Ea
|
|
|
109
140
|
end
|
|
110
141
|
end
|
|
111
142
|
|
|
143
|
+
# Stored source-end boxes on a 7pt label whose first leg
|
|
144
|
+
# leaves straight up or straight right are seated at the box
|
|
145
|
+
# corner, anchor + (OX, OY) with no sign flip, 3px to its
|
|
146
|
+
# right: the multiplicity 6px above it on an upward leg and
|
|
147
|
+
# 15px below it on a rightward one, the role 7px above it on
|
|
148
|
+
# a rightward one. Other sizes, headings, the target end,
|
|
149
|
+
# custom presentation keep their offsets; zero multiplicity boxes keep their default seat.
|
|
150
|
+
def leg_direction(end_kind, heading)
|
|
151
|
+
return nil unless source_seat?(end_kind, heading)
|
|
152
|
+
|
|
153
|
+
dx, dy = heading
|
|
154
|
+
return :up if dx.zero? && dy.negative?
|
|
155
|
+
return :right if dy.zero? && dx.positive?
|
|
156
|
+
|
|
157
|
+
nil
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Role text on a rightward leg is left-aligned at the corner,
|
|
161
|
+
# 7px above it. Upward legs keep the plain role offset.
|
|
162
|
+
def role_seat(direction, anchor, box, role)
|
|
163
|
+
return nil unless direction == :right
|
|
164
|
+
return nil if box.nil? || role_empty?(role)
|
|
165
|
+
return nil unless default_presentation?(box)
|
|
166
|
+
|
|
167
|
+
x, y = seat_corner(anchor, box)
|
|
168
|
+
[x + SEAT_X_INSET, y - 7]
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def mult_seat(direction, anchor, box)
|
|
172
|
+
return nil if box.nil? || stored_offsets_zero?(box)
|
|
173
|
+
return nil unless default_presentation?(box)
|
|
174
|
+
|
|
175
|
+
x, y = seat_corner(anchor, box)
|
|
176
|
+
[x + SEAT_X_INSET, direction == :right ? y + 15 : y - 6]
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def source_seat?(end_kind, heading)
|
|
180
|
+
end_kind == :source && heading &&
|
|
181
|
+
font_size == SEAT_FONT_SIZE && font_unit == "pt"
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Boxes with explicit string-keyed OX/OY (the QEA shape) that
|
|
185
|
+
# are unrotated, unhidden, unstyled and left/center aligned.
|
|
186
|
+
def default_presentation?(box)
|
|
187
|
+
return false unless box["ox"] && box["oy"]
|
|
188
|
+
return false unless [nil, 0, 1].include?(box["alignment"])
|
|
189
|
+
return false unless [nil, -1].include?(box["color"])
|
|
190
|
+
|
|
191
|
+
box["rotation"].to_i.zero? && box["direction"].to_i.zero? &&
|
|
192
|
+
box.values_at("hidden", "bold", "italic", "underline")
|
|
193
|
+
.none?
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def seat_corner(anchor, box)
|
|
197
|
+
[anchor[0] + box["ox"].to_i, anchor[1] + box["oy"].to_i]
|
|
198
|
+
end
|
|
199
|
+
|
|
112
200
|
def build_texts(role:, mult:, standalone:, text_pos:, mult_pos:,
|
|
113
201
|
stereo:, text_box:)
|
|
114
202
|
if role && !role.empty? && text_pos
|
|
@@ -78,19 +78,23 @@ module Ea
|
|
|
78
78
|
boxes = connector.label_boxes || {}
|
|
79
79
|
tree = tree_shaped?(points)
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
stored_src = end_boxes(boxes, :llt, :llb)
|
|
82
|
+
stored_tgt = end_boxes(boxes, :lrt, :lrb)
|
|
83
|
+
stored_labels = !(stored_src.nil? && stored_tgt.nil?)
|
|
84
|
+
src_tb, src_mb = stored_src || default_label_boxes(points, :source)
|
|
85
|
+
tgt_tb, tgt_mb = stored_tgt || default_label_boxes(points, :target)
|
|
85
86
|
|
|
86
87
|
texts = []
|
|
87
88
|
end_renderer.texts(text_box: src_tb, mult_box: src_mb,
|
|
88
89
|
anchor: source_pt, connector: connector,
|
|
89
|
-
end_kind: :source, tree: tree && tree[:source]
|
|
90
|
+
end_kind: :source, tree: tree && tree[:source],
|
|
91
|
+
heading: stored_src && leg_heading(points),
|
|
92
|
+
stored_labels: stored_labels).each { |t| texts << t }
|
|
90
93
|
end_renderer.texts(text_box: tgt_tb,
|
|
91
94
|
mult_box: tgt_mb,
|
|
92
95
|
anchor: target_pt, connector: connector,
|
|
93
|
-
end_kind: :target, tree: tree && tree[:target]
|
|
96
|
+
end_kind: :target, tree: tree && tree[:target],
|
|
97
|
+
stored_labels: stored_labels).each { |t| texts << t }
|
|
94
98
|
texts
|
|
95
99
|
end
|
|
96
100
|
|
|
@@ -105,6 +109,10 @@ module Ea
|
|
|
105
109
|
{ source: true, target: true }
|
|
106
110
|
end
|
|
107
111
|
|
|
112
|
+
def leg_heading(points)
|
|
113
|
+
[points[1][0] - points[0][0], points[1][1] - points[0][1]]
|
|
114
|
+
end
|
|
115
|
+
|
|
108
116
|
def end_boxes(boxes, text_key, mult_key)
|
|
109
117
|
return nil if boxes[text_key].nil? && boxes[mult_key].nil?
|
|
110
118
|
|
data/lib/ea/version.rb
CHANGED