ea 0.6.53 → 0.6.55
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 +4 -4
- data/lib/ea/model/diagram_connector.rb +9 -0
- data/lib/ea/sources/qea/diagram_builder.rb +38 -13
- data/lib/ea/svg/ea_emitter/connector_redock.rb +49 -5
- data/lib/ea/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7d4c834fa91906a0866bf29561214b7c9d140cb4b2a7106eb332f4ec029e56f1
|
|
4
|
+
data.tar.gz: e99cb2ff135675ec69d47397c102bd67f07925d8e59565bbabf6b96fb70cb60d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 302544eb3d7bc17747114aac54f1aacb3b91c6f87340c699d4c35bb8eace2f76c9a4766fd675eb1d58d0c5faa039624124ee5d7dca75d36b7a2e6e109d9aef2c
|
|
7
|
+
data.tar.gz: e5a86d18db02e980a690a2653529f17cd87b431ba7d7aee03683abe6f1fc3de9d4881347817735365a53575e234a91e0cca36364552a39d24e9b725a06932017
|
|
@@ -44,6 +44,13 @@ module Ea
|
|
|
44
44
|
# when the geometry string carries no offsets (auto-routed).
|
|
45
45
|
attribute :source_port, Ea::Model::Point
|
|
46
46
|
attribute :target_port, Ea::Model::Point
|
|
47
|
+
# Ray origins for the drawn line: element center translated by
|
|
48
|
+
# the stored Geometry SX/SY / EX/EY offsets. EA clips the
|
|
49
|
+
# segment between the two anchors at the DRAWN outlines
|
|
50
|
+
# (F851A657: anchors center+(-29,0)/center+(-29,0) clip to EA's
|
|
51
|
+
# (297,788)/(433,514) within 1.5px).
|
|
52
|
+
attribute :source_anchor, Ea::Model::Point
|
|
53
|
+
attribute :target_anchor, Ea::Model::Point
|
|
47
54
|
|
|
48
55
|
json do
|
|
49
56
|
map "id", to: :id
|
|
@@ -57,6 +64,8 @@ module Ea
|
|
|
57
64
|
map "targetEdge", to: :target_edge
|
|
58
65
|
map "sourcePort", to: :source_port
|
|
59
66
|
map "targetPort", to: :target_port
|
|
67
|
+
map "sourceAnchor", to: :source_anchor
|
|
68
|
+
map "targetAnchor", to: :target_anchor
|
|
60
69
|
map "connectorType", to: :connector_type
|
|
61
70
|
map "direction", to: :direction
|
|
62
71
|
map "sourceStereotype", to: :source_stereotype
|
|
@@ -111,26 +111,27 @@ module Ea
|
|
|
111
111
|
value.nil? || value.to_s.empty? ? nil : value
|
|
112
112
|
end
|
|
113
113
|
|
|
114
|
-
# EA stores the element font size in tenths of a point
|
|
115
|
-
#
|
|
116
|
-
#
|
|
117
|
-
#
|
|
118
|
-
#
|
|
119
|
-
#
|
|
120
|
-
#
|
|
121
|
-
#
|
|
122
|
-
#
|
|
123
|
-
|
|
114
|
+
# EA stores the element font size in tenths of a point and
|
|
115
|
+
# renders it through GDI's double rounding: pixel height =
|
|
116
|
+
# floor(tenths * 96 / 720), then point size =
|
|
117
|
+
# floor(pixels * 72 / 96). 70 -> 9px -> 6pt (F3660305 Text),
|
|
118
|
+
# 80 -> 10px -> 7pt, 90 -> 12px -> 9pt (4EBDE645's PI_*
|
|
119
|
+
# classes), 100 -> 13px -> 9pt (0D31AED1's all-100 elements
|
|
120
|
+
# publish 321 texts at 9pt), 120 -> 16px -> 12pt
|
|
121
|
+
# (412BC89E's Boundary title), 140 -> 18px -> 13pt.
|
|
122
|
+
# fontsz=0 ("use default", written back by the font dialog)
|
|
123
|
+
# renders at the 7pt theme size.
|
|
124
|
+
USE_DEFAULT_FONTSZ = [0].freeze
|
|
125
|
+
GDI_DPI = 96
|
|
124
126
|
|
|
125
127
|
def font_size_from(style_hash)
|
|
126
128
|
raw = style_hash[:fontsz]
|
|
127
129
|
return nil if raw.nil? || raw.to_s.empty?
|
|
128
130
|
|
|
129
|
-
return nil if raw.to_i.zero?
|
|
130
|
-
|
|
131
131
|
return nil if USE_DEFAULT_FONTSZ.include?(raw.to_i)
|
|
132
132
|
|
|
133
|
-
(raw.to_f /
|
|
133
|
+
pixels = (raw.to_f * GDI_DPI / 720).floor
|
|
134
|
+
(pixels * 72.0 / GDI_DPI).floor
|
|
134
135
|
end
|
|
135
136
|
|
|
136
137
|
def build_connectors(diagram_row)
|
|
@@ -372,6 +373,10 @@ module Ea
|
|
|
372
373
|
target_stereotype: connector&.deststereotype,
|
|
373
374
|
waypoints: context ? context_waypoints_for(connector, diagram_row) :
|
|
374
375
|
waypoints_for_link(link_row, diagram_row),
|
|
376
|
+
source_anchor: port_anchor_for(connector, diagram_row,
|
|
377
|
+
geom, :source),
|
|
378
|
+
target_anchor: port_anchor_for(connector, diagram_row,
|
|
379
|
+
geom, :target),
|
|
375
380
|
source_port: connection_port(diagram_row, connector, :source, geom),
|
|
376
381
|
target_port: connection_port(diagram_row, connector, :target, geom),
|
|
377
382
|
label_boxes: context ? {} : (geom[:label_boxes] || {}),
|
|
@@ -383,6 +388,26 @@ module Ea
|
|
|
383
388
|
)
|
|
384
389
|
end
|
|
385
390
|
|
|
391
|
+
# Ray origin for one connector end: the element's center
|
|
392
|
+
# translated by the stored SX/SY (source) or EX/EY (target)
|
|
393
|
+
# offset. EA clips the anchor-to-anchor segment at the drawn
|
|
394
|
+
# outlines.
|
|
395
|
+
def port_anchor_for(connector, diagram_row, geom, end_kind)
|
|
396
|
+
return nil unless connector
|
|
397
|
+
|
|
398
|
+
object_id = end_kind == :source ? connector.start_object_id :
|
|
399
|
+
connector.end_object_id
|
|
400
|
+
placement = diagram_object_placement(diagram_row.diagram_id,
|
|
401
|
+
object_id)
|
|
402
|
+
return nil unless placement
|
|
403
|
+
|
|
404
|
+
bounds = bounds_from_rect(placement)
|
|
405
|
+
dx = (end_kind == :source ? geom[:sx] : geom[:ex]).to_i
|
|
406
|
+
dy = (end_kind == :source ? geom[:sy] : geom[:ey]).to_i
|
|
407
|
+
Ea::Model::Point.new(x: bounds.x + bounds.width / 2 + dx,
|
|
408
|
+
y: bounds.y + bounds.height / 2 + dy)
|
|
409
|
+
end
|
|
410
|
+
|
|
386
411
|
# Context diagrams re-route every drawn connector as a
|
|
387
412
|
# direct line at draw time: the center-to-center ray clipped
|
|
388
413
|
# at both box outlines. The stored SX/SY/EDGE geometry is
|
|
@@ -19,11 +19,12 @@ module Ea
|
|
|
19
19
|
# self-loop, or no drawn bounds for either end).
|
|
20
20
|
def pairs_for(connector, diagram, model_index, bounds_map)
|
|
21
21
|
return nil unless bounds_map
|
|
22
|
-
return nil unless direct?(connector)
|
|
22
|
+
return nil unless direct?(connector) || two_point?(connector)
|
|
23
23
|
|
|
24
24
|
points = waypoint_pairs(connector)
|
|
25
25
|
return nil unless points.size == 2
|
|
26
26
|
|
|
27
|
+
|
|
27
28
|
rel = relationship_for(connector, model_index)
|
|
28
29
|
return nil unless rel
|
|
29
30
|
|
|
@@ -35,8 +36,45 @@ module Ea
|
|
|
35
36
|
return nil unless source_bounds && target_bounds
|
|
36
37
|
return nil if source_ref == target_ref
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
sa = connector.source_anchor
|
|
40
|
+
ta = connector.target_anchor
|
|
41
|
+
if sa && ta
|
|
42
|
+
[anchor_exit(sa, source_bounds, ta),
|
|
43
|
+
anchor_exit(ta, target_bounds, sa)]
|
|
44
|
+
else
|
|
45
|
+
[edge_point(source_bounds, target_bounds),
|
|
46
|
+
edge_point(target_bounds, source_bounds)]
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Exit point of the anchor-to-anchor segment through a box's
|
|
51
|
+
# outline: smallest positive t whose crossing lies on the
|
|
52
|
+
# rectangle perimeter.
|
|
53
|
+
def anchor_exit(anchor, bounds, other)
|
|
54
|
+
ax, ay = anchor.x.to_f, anchor.y.to_f
|
|
55
|
+
ox, oy = other.x.to_f, other.y.to_f
|
|
56
|
+
dx, dy = ox - ax, oy - ay
|
|
57
|
+
candidates = []
|
|
58
|
+
if dx != 0
|
|
59
|
+
[bounds.x, bounds.x + bounds.width].each do |x|
|
|
60
|
+
t = (x - ax) / dx
|
|
61
|
+
candidates << [t, x, ay + t * dy] if t.positive?
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
if dy != 0
|
|
65
|
+
[bounds.y, bounds.y + bounds.height].each do |y|
|
|
66
|
+
t = (y - ay) / dy
|
|
67
|
+
candidates << [t, ax + t * dx, y] if t.positive?
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
on_perimeter = candidates.select do |_t, x, y|
|
|
71
|
+
x >= bounds.x - 0.01 && x <= bounds.x + bounds.width + 0.01 &&
|
|
72
|
+
y >= bounds.y - 0.01 && y <= bounds.y + bounds.height + 0.01
|
|
73
|
+
end
|
|
74
|
+
best = on_perimeter.min_by(&:first)
|
|
75
|
+
# EA floors the dock coordinates (F851A657: 297.75 -> 297,
|
|
76
|
+
# 433.7 -> 433) - a rounded-up dock is a visible miss.
|
|
77
|
+
best ? [best[1].floor, best[2].floor] : [ax.floor, ay.floor]
|
|
40
78
|
end
|
|
41
79
|
|
|
42
80
|
# EA never docks a horizontal connector line at the header
|
|
@@ -85,6 +123,12 @@ module Ea
|
|
|
85
123
|
%w[direct regenerated].any? { |k| style.key?(k) }
|
|
86
124
|
end
|
|
87
125
|
|
|
126
|
+
# EXPERIMENT: every auto-laid 2-waypoint connector re-docks
|
|
127
|
+
# as the center-to-center ray clipped at the drawn outlines.
|
|
128
|
+
def two_point?(connector)
|
|
129
|
+
(connector.waypoints || []).size == 2
|
|
130
|
+
end
|
|
131
|
+
|
|
88
132
|
def waypoint_pairs(connector)
|
|
89
133
|
(connector.waypoints || []).filter_map do |wp|
|
|
90
134
|
next unless wp.position
|
|
@@ -126,11 +170,11 @@ module Ea
|
|
|
126
170
|
if dx.abs * bounds.height > dy.abs * bounds.width
|
|
127
171
|
x = dx.positive? ? bounds.x + bounds.width : bounds.x
|
|
128
172
|
y = safe_y(cx, cy, dx, dy, x)
|
|
129
|
-
[x, y]
|
|
173
|
+
[x, y.floor]
|
|
130
174
|
else
|
|
131
175
|
y = dy.positive? ? bounds.y + bounds.height : bounds.y
|
|
132
176
|
x = safe_x(cx, cy, dx, dy, y)
|
|
133
|
-
[x, y]
|
|
177
|
+
[x.floor, y]
|
|
134
178
|
end
|
|
135
179
|
end
|
|
136
180
|
|
data/lib/ea/version.rb
CHANGED