ea 0.6.20 → 0.6.22

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: 4414e6921d37d619d953382395e7ecf9c8ddb19da4cca389e57177eb7a4ab398
4
- data.tar.gz: 3365590f62c21b9855d18d70656515b361c4c93def5fe1d8341af944ed01822c
3
+ metadata.gz: 995544bb338cd3ca1a632cd580c978aeb4e85e59e74cce7d35df5736714e397c
4
+ data.tar.gz: c1039f763b50e27f87bfc94f72fdac4de3f542b4a21e7eeb19caf688563ffe9c
5
5
  SHA512:
6
- metadata.gz: 87930fec1aeee29cae1c4352527bcb896147f971427c78a1f58c053b3496d891b82d78afd5aadd7e43a6356534ac9393c21c405cdb991d2703d228706077c01b
7
- data.tar.gz: 2d0bce26c6aad8b83004004b86e156306847331b2e357c1599793dfce22ce8f953ee179fae02dde2a327f2c408faf347bbfeab5f3551f520954bccd801b9e56a
6
+ metadata.gz: cbc871ca5c043bc1555fb8940beebe50258bfe901df6b2b2e61a7f572ef103dff9aa757dd9896e555dea8da9bf8f17b5a72e8035caeab044dd9f58d5cd730e33
7
+ data.tar.gz: 28a342b4ed8e0129e52f706982d3aa4d0504496fcb15f439158a5c6b8f39128fb1e3ac1dccc12033b55753876904fd9f7f659c66a8181abf3dd249d517ff0741
@@ -25,14 +25,48 @@ module Ea
25
25
  def render_literals_block(context)
26
26
  line_h = context.size + LITERAL_LINE_OFFSET
27
27
  text_blocks = []
28
+ row_y = context.geometry.enum_literal_first_y
29
+ # EA renders a centered italic "literals" caption above
30
+ # the rows when the literals carry stored code values
31
+ # (t_attribute.Default); bare literal lists render the
32
+ # rows directly. Corpus-verified (PT_TypeOfSA:
33
+ # "literals" caption + "ServingParcel = SP" rows;
34
+ # CV_SequenceType: bare rows, no caption).
35
+ if caption?(context)
36
+ text_blocks << caption_text(context, row_y)
37
+ row_y += line_h
38
+ end
28
39
  context.enum_literals.each_with_index do |literal, idx|
29
- y = context.geometry.enum_literal_first_y + (idx * line_h)
40
+ y = row_y + (idx * line_h)
30
41
  text_blocks << visibility_placeholder(context, y)
31
42
  text_blocks << literal_name_text(context, literal, y)
32
43
  end
33
44
  wrap_group(text_blocks, context.theme.text_color)
34
45
  end
35
46
 
47
+ def caption?(context)
48
+ context.enum_literals.any? do |l|
49
+ value = l.value.to_s
50
+ !value.empty? && value != l.name.to_s
51
+ end
52
+ end
53
+
54
+ def caption_text(context, y)
55
+ content = "literals"
56
+ len = TextRenderer.estimate_width(content, context.size, nil,
57
+ family: context.family).round
58
+ x = (context.bounds.x + (context.bounds.width - len) / 2.0).floor
59
+ TextRenderer.new(
60
+ content: content,
61
+ x: x, y: y,
62
+ family: context.family, size: context.size, size_unit: context.size_unit,
63
+ fill: context.theme.text_color,
64
+ stroke_in_text: context.theme.stroke_in_text_color,
65
+ width_factor: context.theme.text_width_factor,
66
+ style: "italic"
67
+ ).to_svg
68
+ end
69
+
36
70
  def visibility_placeholder(context, y)
37
71
  TextRenderer.new(
38
72
  content: " ",
@@ -46,8 +80,9 @@ module Ea
46
80
  end
47
81
 
48
82
  def literal_name_text(context, literal, y)
83
+ content = literal_display(literal)
49
84
  TextRenderer.new(
50
- content: literal.name.to_s,
85
+ content: content,
51
86
  x: context.bounds.x + (context.theme.attribute_spec.content_x_offset || 26),
52
87
  y: y,
53
88
  family: context.family, size: context.size, size_unit: context.size_unit,
@@ -57,6 +92,15 @@ module Ea
57
92
  ).to_svg
58
93
  end
59
94
 
95
+ # EA shows "Name = Code" for literals with a stored
96
+ # default value; bare names otherwise.
97
+ def literal_display(literal)
98
+ value = literal.value.to_s
99
+ return literal.name.to_s if value.empty? || value == literal.name.to_s
100
+
101
+ "#{literal.name} = #{value}"
102
+ end
103
+
60
104
  def wrap_group(text_blocks, text_color)
61
105
  style = "stroke-width:1;stroke-linecap:round;stroke-linejoin:bevel; " \
62
106
  "fill:#{text_color};fill-opacity:1.00; " \
@@ -84,10 +84,10 @@ module Ea
84
84
  op_lines = (is_classifier && show_operations?) ? Element::OperationRenderer.lines_for(classifier) : []
85
85
  geometry = compartment_geometry(bounds, size, attr_lines, op_lines,
86
86
  tagged_values_for(classifier).size,
87
- header_lines,
87
+ header_lines, classifier: classifier,
88
88
  constraints_count: constraints_for(classifier).size,
89
89
  marker_count: marker_lines_for(classifier).size,
90
- enum_literals_count: enum_literals_for(classifier).size)
90
+ enum_literals_count: enum_row_count_for(classifier))
91
91
  # EA suppresses the whole attribute compartment when its
92
92
  # rows do not fit the stored box height (never truncates
93
93
  # rows) - the AOS box on CityFurniture hides its
@@ -100,10 +100,10 @@ module Ea
100
100
  attr_lines = []
101
101
  geometry = compartment_geometry(bounds, size, attr_lines, op_lines,
102
102
  tagged_values_for(classifier).size,
103
- header_lines,
103
+ header_lines, classifier: classifier,
104
104
  constraints_count: constraints_for(classifier).size,
105
105
  marker_count: marker_lines_for(classifier).size,
106
- enum_literals_count: enum_literals_for(classifier).size)
106
+ enum_literals_count: enum_row_count_for(classifier))
107
107
  end
108
108
  # EA suppresses the operations compartment when its rows
109
109
  # overflow the stored box height (same rule as attributes).
@@ -112,10 +112,10 @@ module Ea
112
112
  op_lines = []
113
113
  geometry = compartment_geometry(bounds, size, attr_lines, op_lines,
114
114
  tagged_values_for(classifier).size,
115
- header_lines,
115
+ header_lines, classifier: classifier,
116
116
  constraints_count: constraints_for(classifier).size,
117
117
  marker_count: marker_lines_for(classifier).size,
118
- enum_literals_count: enum_literals_for(classifier).size)
118
+ enum_literals_count: enum_row_count_for(classifier))
119
119
  end
120
120
  RenderContext.new(
121
121
  element: element,
@@ -145,7 +145,7 @@ module Ea
145
145
  end
146
146
 
147
147
  def compartment_geometry(bounds, size, attr_lines, op_lines,
148
- tagged_count, header_lines,
148
+ tagged_count, header_lines, classifier: nil,
149
149
  constraints_count: 0, marker_count: 0,
150
150
  enum_literals_count: 0)
151
151
  CompartmentGeometry.new(bounds: bounds, size: size,
@@ -156,7 +156,7 @@ module Ea
156
156
  constraints_count: constraints_count,
157
157
  marker_count: marker_count,
158
158
  enum_literals_count: enum_literals_count,
159
- header_top_padding: header_padding_for(header_lines),
159
+ header_top_padding: header_padding_for(header_lines, classifier),
160
160
  header_line_offset: theme.compartments.header_line_offset,
161
161
  divider_offset: theme.compartments.divider_offset,
162
162
  attr_line_offset: theme.compartments.attr_line_offset,
@@ -164,21 +164,29 @@ module Ea
164
164
  end
165
165
 
166
166
  # EA seats a stereotype line 3px higher than a bare class name
167
- # (first baseline +16 vs +19 at 7pt) - verified against the
168
- # EA-published reference SVGs.
169
- def header_padding_for(header_lines)
167
+ # (first baseline +16 vs +19 at 7pt) - and Enumeration /
168
+ # Interface elements seat their stereotype 3px higher still
169
+ # (+13). Corpus-verified by identity-matched elements:
170
+ # Interface +13 x44 vs +16 x17, Enumeration +13 x13 vs +16
171
+ # x3, Class/Object/DataType +16 x515.
172
+ def header_padding_for(header_lines, classifier)
170
173
  first = header_lines.first
171
174
  return theme.compartments.header_top_padding unless first
172
175
 
173
176
  if first.last == :italic
174
177
  6 # ghost-led: EA seats the right-aligned ghost at +13
175
178
  elsif first.first.to_s.start_with?("«")
176
- 9
179
+ enumeration_or_interface?(classifier) ? 6 : 9
177
180
  else
178
181
  theme.compartments.header_top_padding
179
182
  end
180
183
  end
181
184
 
185
+ def enumeration_or_interface?(classifier)
186
+ classifier.is_a?(Ea::Model::Enumeration) ||
187
+ classifier.is_a?(Ea::Model::Interface)
188
+ end
189
+
182
190
  # A stereotype group header («Property») sits 4px below where
183
191
  # plain rows start (divider+18 vs divider+14 at 7pt).
184
192
  def attr_first_offset_for(attr_lines)
@@ -196,6 +204,14 @@ module Ea
196
204
  classifier.literals || []
197
205
  end
198
206
 
207
+ # The "literals" caption occupies a row slot when any
208
+ # literal carries a stored code value.
209
+ def enum_row_count_for(classifier)
210
+ literals = enum_literals_for(classifier)
211
+ caption = literals.any? { |l| !l.value.to_s.empty? && l.value.to_s != l.name.to_s }
212
+ literals.size + (caption ? 1 : 0)
213
+ end
214
+
199
215
  def tagged_values_for(classifier)
200
216
  return [] unless classifier.is_a?(Ea::Model::Classifier)
201
217
 
data/lib/ea/version.rb CHANGED
@@ -4,5 +4,5 @@ module Ea
4
4
  # Gem release version. Extracted to its own file so the
5
5
  # `gem-release` tool's `gem bump` can find and update it via the
6
6
  # standard `lib/<gem>/version.rb` convention.
7
- VERSION = "0.6.20"
7
+ VERSION = "0.6.22"
8
8
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ea
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.20
4
+ version: 0.6.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.