ea 0.6.123 → 0.6.124
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/legend.rb +2 -0
- data/lib/ea/sources/qea/legend_builder.rb +2 -0
- data/lib/ea/svg/ea_emitter/connector_redock.rb +5 -3
- data/lib/ea/svg/ea_emitter/element/compartment_geometry.rb +18 -11
- data/lib/ea/svg/ea_emitter/element/legend_renderer.rb +15 -5
- data/lib/ea/svg/ea_emitter/elements.rb +25 -2
- 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: dd02b1a50cdc130c8d08643767666068e9272158df4592e4bea690c1b1e7e778
|
|
4
|
+
data.tar.gz: dc499639ec487f46cc5ee952b1fa16ce58a7eb5fc57747ca4b9ff7584488fed4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 537cd073276c4eb487d6848c28e5522df1c87cdf55170d2e94e4142f4ed3e6b2dd2544fc8220cbc75373fd33ac47349e25f0f979b126791d567946be3a3a2007
|
|
7
|
+
data.tar.gz: e07055d655ee0667d604a9089bf243ea3dc7d4e602035ec1a2a58e2db27f744e410dc4b095b3d85f0fdffd02a8068675c24c172bd44062a82d1259191242359d
|
data/lib/ea/model/legend.rb
CHANGED
|
@@ -21,6 +21,7 @@ module Ea
|
|
|
21
21
|
|
|
22
22
|
attribute :title, :string, default: -> { DEFAULT_TITLE }
|
|
23
23
|
attribute :heading_size, :integer
|
|
24
|
+
attribute :heading_family, :string
|
|
24
25
|
attribute :font_color, :integer, default: -> { DEFAULT_FONT_COLOR }
|
|
25
26
|
attribute :background_color, :integer, default: -> { DEFAULT_BACKGROUND_COLOR }
|
|
26
27
|
attribute :border_color, :integer, default: -> { DEFAULT_BORDER_COLOR }
|
|
@@ -32,6 +33,7 @@ module Ea
|
|
|
32
33
|
map "name", to: :name
|
|
33
34
|
map "title", to: :title
|
|
34
35
|
map "headingSize", to: :heading_size
|
|
36
|
+
map "headingFamily", to: :heading_family
|
|
35
37
|
map "fontColor", to: :font_color
|
|
36
38
|
map "backgroundColor", to: :background_color
|
|
37
39
|
map "borderColor", to: :border_color
|
|
@@ -12,6 +12,7 @@ module Ea
|
|
|
12
12
|
# Returns nil when no matching xref exists (the Text element
|
|
13
13
|
# is not a legend — caller should render it as a plain note).
|
|
14
14
|
class LegendBuilder
|
|
15
|
+
DEFAULT_HEADING_FAMILY = "Cambria"
|
|
15
16
|
LEGEND_XREF_NAME = "CustomProperties"
|
|
16
17
|
LEGEND_TYPE_OBJECT_STYLE = "LEGEND_OBJECTSTYLE"
|
|
17
18
|
LEGEND_TYPE_STYLE_SETTINGS = "LEGEND_STYLE_SETTINGS"
|
|
@@ -77,6 +78,7 @@ module Ea
|
|
|
77
78
|
Ea::Model::Legend.new(
|
|
78
79
|
title: style["TITLE"] || Ea::Model::Legend::DEFAULT_TITLE,
|
|
79
80
|
heading_size: int_or_nil(style["HEADINGSIZE"]),
|
|
81
|
+
heading_family: DEFAULT_HEADING_FAMILY,
|
|
80
82
|
font_color: int_or(style["FONTCOLOR"],
|
|
81
83
|
Ea::Model::Legend::DEFAULT_FONT_COLOR),
|
|
82
84
|
background_color: int_or(style["BACKGROUNDCOLOR"],
|
|
@@ -256,12 +256,14 @@ module Ea
|
|
|
256
256
|
end
|
|
257
257
|
private_class_method :default_model_connector?
|
|
258
258
|
|
|
259
|
-
#
|
|
260
|
-
#
|
|
259
|
+
# Thin connectors between explicitly bordered elements stop on the outer
|
|
260
|
+
# edge of their 2px borders, including package imports.
|
|
261
261
|
def bordered_outline?(connector, diagram, refs, bounds)
|
|
262
262
|
style = connector.style.to_h
|
|
263
263
|
return false unless style[:lwidth] == "0" && !style[:tree]
|
|
264
|
-
return false unless %w[Generalization Aggregation Association Dependency].include?(
|
|
264
|
+
return false unless %w[Generalization Aggregation Association Dependency Package].include?(
|
|
265
|
+
connector.connector_type
|
|
266
|
+
)
|
|
265
267
|
return false unless bounds.all? { |box| box.width.positive? && box.height.positive? }
|
|
266
268
|
|
|
267
269
|
ends = [[refs.first, style[:soid]], [refs.last, style[:eoid]]]
|
|
@@ -40,6 +40,7 @@ module Ea
|
|
|
40
40
|
attr_line_offset: 6,
|
|
41
41
|
attr_first_offset: 7,
|
|
42
42
|
attr_group_lead: 0,
|
|
43
|
+
compact_standard_operations: false,
|
|
43
44
|
family: nil, size_unit: "pt", logical_height: nil,
|
|
44
45
|
header_ghost: false,
|
|
45
46
|
header_ghost_tight: false)
|
|
@@ -61,6 +62,7 @@ module Ea
|
|
|
61
62
|
@attr_line_offset = attr_line_offset
|
|
62
63
|
@attr_first_offset = attr_first_offset
|
|
63
64
|
@attr_group_lead = attr_group_lead
|
|
65
|
+
@compact_standard_operations = compact_standard_operations
|
|
64
66
|
@header_ghost = header_ghost
|
|
65
67
|
@header_ghost_tight = header_ghost_tight
|
|
66
68
|
end
|
|
@@ -137,24 +139,29 @@ module Ea
|
|
|
137
139
|
end
|
|
138
140
|
|
|
139
141
|
def op_divider_y
|
|
142
|
+
return attr_bottom_y + line_height(attr_line_offset || 6) / 2.0 if compact_operation_spacing?
|
|
143
|
+
|
|
140
144
|
attr_bottom_y + size + 5
|
|
141
145
|
end
|
|
142
146
|
|
|
143
|
-
#
|
|
144
|
-
#
|
|
145
|
-
# attrs AND ops (6D4C665D: attrs ..520, ops 541..658 step 13).
|
|
146
|
-
# Attribute-empty boxes anchor on the divider instead:
|
|
147
|
-
# first op at divider + 14 (001A64C1: EA ops 104 vs our
|
|
148
|
-
# 125 when attrs were absent).
|
|
147
|
+
# Compact standard classes end attributes with a half row cell;
|
|
148
|
+
# operations then use the same inset as an attribute-empty box.
|
|
149
149
|
def op_first_y
|
|
150
150
|
return nil unless op_lines_count&.positive?
|
|
151
151
|
|
|
152
|
-
if attr_lines_count.to_i.positive?
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
152
|
+
anchor = if attr_lines_count.to_i.positive?
|
|
153
|
+
compact_operation_spacing? ? op_divider_y : attr_bottom_y + 7
|
|
154
|
+
else
|
|
155
|
+
divider_y
|
|
156
|
+
end
|
|
157
|
+
anchor + size + 7
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def compact_operation_spacing?
|
|
161
|
+
@compact_standard_operations && attr_lines_count.to_i.positive? &&
|
|
162
|
+
Ea::Fonts::Metrics.compact_compartment_font?(size, family: @family, unit: @size_unit)
|
|
157
163
|
end
|
|
164
|
+
private :compact_operation_spacing?
|
|
158
165
|
|
|
159
166
|
def op_bottom_y
|
|
160
167
|
return op_divider_y unless op_lines_count&.positive?
|
|
@@ -126,10 +126,16 @@ module Ea
|
|
|
126
126
|
|
|
127
127
|
def item_label(item, index)
|
|
128
128
|
x = bounds.x + ICON_X_OFFSET + ICON_LABEL_GAP
|
|
129
|
-
y = item_top_y(index) +
|
|
129
|
+
y = item_top_y(index) + item_label_baseline
|
|
130
130
|
build_text(item.name, x: x, y: y, size: item_font_size, weight: 0)
|
|
131
131
|
end
|
|
132
132
|
|
|
133
|
+
def item_label_baseline
|
|
134
|
+
return LABEL_BASELINE_FROM_ICON_TOP unless (item_font[:unit] || "pt") == "pt"
|
|
135
|
+
|
|
136
|
+
item_font[:logical_height] || LABEL_BASELINE_FROM_ICON_TOP
|
|
137
|
+
end
|
|
138
|
+
|
|
133
139
|
def title_text
|
|
134
140
|
x = title_x
|
|
135
141
|
y = bounds.y + TITLE_Y_OFFSET
|
|
@@ -152,8 +158,8 @@ module Ea
|
|
|
152
158
|
|
|
153
159
|
# Real font metrics when available; legacy per-char
|
|
154
160
|
# estimate otherwise (families without metric tables).
|
|
155
|
-
def estimated_width(text, size, weight: nil, logical_height: nil)
|
|
156
|
-
measured = Ea::Fonts::Metrics.text_length(text, size, family:
|
|
161
|
+
def estimated_width(text, size, weight: nil, logical_height: nil, text_family: family)
|
|
162
|
+
measured = Ea::Fonts::Metrics.text_length(text, size, family: text_family, weight: weight,
|
|
157
163
|
logical_height: logical_height)
|
|
158
164
|
return measured if measured
|
|
159
165
|
|
|
@@ -186,7 +192,11 @@ module Ea
|
|
|
186
192
|
end
|
|
187
193
|
|
|
188
194
|
def title_text_width
|
|
189
|
-
estimated_width(legend.title, title_font_size, weight: 700)
|
|
195
|
+
estimated_width(legend.title, title_font_size, weight: 700, text_family: heading_family)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def heading_family
|
|
199
|
+
legend.heading_family || family
|
|
190
200
|
end
|
|
191
201
|
|
|
192
202
|
def build_text(content, x:, y:, size:, weight:)
|
|
@@ -194,7 +204,7 @@ module Ea
|
|
|
194
204
|
size_unit = weight.zero? ? (item_font[:unit] || "pt") : "pt"
|
|
195
205
|
TextRenderer.new(
|
|
196
206
|
content: content.to_s, x: tx, y: ty,
|
|
197
|
-
family: family, size: size, size_unit: size_unit,
|
|
207
|
+
family: weight.zero? ? family : heading_family, size: size, size_unit: size_unit,
|
|
198
208
|
weight: weight, fill: label_fill, logical_height: weight.zero? ? item_font[:logical_height] : nil
|
|
199
209
|
).to_svg
|
|
200
210
|
end
|
|
@@ -332,8 +332,22 @@ module Ea
|
|
|
332
332
|
constraints_count: 0, marker_count: 0,
|
|
333
333
|
enum_literals_count: 0,
|
|
334
334
|
attr_group_lead: 0, family: nil, size_unit: "pt", logical_height: nil)
|
|
335
|
+
divider_offset = divider_offset_for(header_lines, classifier)
|
|
336
|
+
attr_first_offset = attr_first_offset_for(attr_lines)
|
|
337
|
+
compact_standard = compact_header_offsets?(
|
|
338
|
+
classifier, header_lines, size,
|
|
339
|
+
family: family, size_unit: size_unit, logical_height: logical_height,
|
|
340
|
+
marker_count: marker_count, enum_literals_count: enum_literals_count,
|
|
341
|
+
divider_offset: divider_offset, attr_first_offset: attr_first_offset
|
|
342
|
+
)
|
|
343
|
+
if compact_standard
|
|
344
|
+
divider_offset = 7
|
|
345
|
+
# Attribute baselines retain their anchor when the divider moves up.
|
|
346
|
+
attr_first_offset = 8
|
|
347
|
+
end
|
|
335
348
|
CompartmentGeometry.new(bounds: bounds, size: size, family: family,
|
|
336
349
|
size_unit: size_unit, logical_height: logical_height,
|
|
350
|
+
compact_standard_operations: compact_standard,
|
|
337
351
|
header_ghost: header_lines.any? &&
|
|
338
352
|
%i[italic italic_tight].include?(header_lines.first.last),
|
|
339
353
|
header_ghost_tight: Element::HeaderLines.parent_ghost_gap(header_lines) == 3,
|
|
@@ -346,12 +360,21 @@ module Ea
|
|
|
346
360
|
enum_literals_count: enum_literals_count,
|
|
347
361
|
header_top_padding: header_padding_for(header_lines, classifier),
|
|
348
362
|
header_line_offset: theme.compartments.header_line_offset,
|
|
349
|
-
divider_offset:
|
|
363
|
+
divider_offset: divider_offset,
|
|
350
364
|
attr_line_offset: theme.compartments.attr_line_offset,
|
|
351
|
-
attr_first_offset:
|
|
365
|
+
attr_first_offset: attr_first_offset,
|
|
352
366
|
attr_group_lead: attr_group_lead)
|
|
353
367
|
end
|
|
354
368
|
|
|
369
|
+
def compact_header_offsets?(classifier, header_lines, size, **options)
|
|
370
|
+
classifier.is_a?(Ea::Model::Klass) &&
|
|
371
|
+
Ea::Fonts::Metrics.compact_compartment_font?(size, family: options[:family], unit: options[:size_unit]) &&
|
|
372
|
+
!%i[italic italic_tight].include?(header_lines.dig(0, 1)) &&
|
|
373
|
+
options.values_at(:logical_height, :marker_count, :enum_literals_count,
|
|
374
|
+
:divider_offset, :attr_first_offset) == [nil, 0, 0, 8, 7] &&
|
|
375
|
+
theme.compartments.header_line_offset == 6 && theme.compartments.attr_line_offset == 6
|
|
376
|
+
end
|
|
377
|
+
|
|
355
378
|
# EA seats a stereotype line 3px higher than a bare class name
|
|
356
379
|
# (first baseline +16 vs +19 at 7pt) - and Enumeration /
|
|
357
380
|
# Interface elements seat their stereotype 3px higher still
|
data/lib/ea/version.rb
CHANGED